internal override void Visit(GetVersionListRequest req) { if (!this.dict.TryGetValue(req.RecordKey, out VersionList versionList)) { req.RemoteVerList = null; req.Result = 0; req.Finished = true; return; } TxList <VersionEntry> localList = req.LocalContainer; TxList <VersionEntry> remoteList = req.RemoteContainer; int entryCount = 0; versionList.TryPeek( out VersionEntry lastVersion, out VersionEntry secondToLastEntry); while (Interlocked.CompareExchange(ref lastVersion.latch, 1, 0) != 0) { ; } VersionEntry.CopyValue(lastVersion, localList[entryCount]); Interlocked.Exchange(ref lastVersion.latch, 0); // Add a reference to a version entry. No need to take the latch. remoteList.Add(lastVersion); entryCount++; if (lastVersion.TxId != VersionEntry.EMPTY_TXID) { while (Interlocked.CompareExchange(ref secondToLastEntry.latch, 1, 0) != 0) { ; } VersionEntry.CopyValue(secondToLastEntry, localList[entryCount]); Interlocked.Exchange(ref secondToLastEntry.latch, 0); // Add a reference to a version entry. No need to take the latch. remoteList.Add(secondToLastEntry); entryCount++; } req.RemoteVerList = versionList; req.Result = entryCount; req.Finished = true; }
internal override void Visit(GetVersionListRequest req) { Dictionary <long, VersionEntry> versionList = null; if (!this.dict.TryGetValue(req.RecordKey, out versionList)) { req.RemoteVerList = null; req.Result = 0; req.Finished = true; return; } VersionEntry tailPointer = versionList[SingletonDictionaryVersionTable.TAIL_KEY]; long lastVersionKey = tailPointer.BeginTimestamp; TxList <VersionEntry> localList = req.LocalContainer; TxList <VersionEntry> remoteList = req.RemoteContainer; int entryCount = 0; // Only returns top 2 newest versions. This is enough for serializability. // For other isolation levels, more versions may need to be returned. // When old versions may be truncated, it is desirable to maintain a head pointer as well, // so as to increase the lower bound of version keys and reduce the number of iterations. while (lastVersionKey >= 0 && entryCount < 2) { // To make it run under .Net 4.5 VersionEntry verEntry = null; versionList.TryGetValue(lastVersionKey, out verEntry); if (verEntry != null) { VersionEntry.CopyValue(verEntry, localList[entryCount]); remoteList.Add(verEntry); entryCount++; if (verEntry.TxId == VersionEntry.EMPTY_TXID) { break; } } lastVersionKey--; } req.RemoteVerList = versionList; req.Result = entryCount; req.Finished = true; }
internal override void Visit(GetVersionListRequest req) { ConcurrentDictionary <long, VersionEntry> versionList = null; if (!this.dict.TryGetValue(req.RecordKey, out versionList)) { req.RemoteVerList = null; req.Result = 0; req.Finished = true; return; } int entryCount = 0; // The value at -1 in the version list is a special entry, // whose beginTimestamp points to the newest version. VersionEntry tailEntry = null; versionList.TryGetValue(SingletonDictionaryVersionTable.TAIL_KEY, out tailEntry); long lastVersionKey = Interlocked.Read(ref tailEntry.BeginTimestamp); TxList <VersionEntry> localList = req.LocalContainer; TxList <VersionEntry> remoteList = req.RemoteContainer; // Only returns top 2 newest versions. This is enough for serializability. // For other isolation levels, more versions may need to be returned. // When old versions may be truncated, it is desirable to maintain a head pointer as well, // so as to increase the lower bound of version keys and reduce the number of iterations. while (lastVersionKey >= 0 && entryCount < 2) { VersionEntry verEntry = null; if (versionList.TryGetValue(lastVersionKey, out verEntry)) { //int ticket = verEntry.EnterQueuedLatch(); verEntry.ReadLock(); // Debug Assertion // if (!verEntry.RecordKey.Equals(req.RecordKey)) // { // throw new Exception("Inconsistent record key"); // } VersionEntry.CopyFromRemote(verEntry, localList[entryCount]); //verEntry.ExitQueuedLatch(ticket); verEntry.UnReadLock(); // Here only add a reference to the list, no need to take the latch remoteList.Add(verEntry); entryCount++; if (Interlocked.Read(ref verEntry.TxId) == VersionEntry.EMPTY_TXID) { break; } } lastVersionKey--; } req.RemoteVerList = versionList; req.Result = entryCount; req.Finished = true; }