internal override void Visit(ReadVersionRequest req) { VersionEntry versionEntry = req.RemoteVerEntry; if (versionEntry == null) { ConcurrentDictionary <long, VersionEntry> versionList = null; if (!this.dict.TryGetValue(req.RecordKey, out versionList)) { req.Result = null; req.Finished = true; return; } if (!versionList.TryGetValue(req.VersionKey, out versionEntry)) { req.Result = null; req.Finished = true; return; } } Debug.Assert(Interlocked.Read(ref versionEntry.VersionKey) == req.VersionKey); // Debug Assertion // if (!versionEntry.RecordKey.Equals(req.RecordKey)) // { // throw new Exception("Inconsistent record key"); // } //int ticket = versionEntry.EnterQueuedLatch(); versionEntry.ReadLock(); VersionEntry.CopyFromRemote(versionEntry, req.LocalVerEntry); //versionEntry.ExitQueuedLatch(ticket); versionEntry.UnReadLock(); req.Result = req.LocalVerEntry; 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; }