internal override void Visit(ReplaceVersionRequest req) { VersionEntry verEntry = req.RemoteVerEntry; if (verEntry == null) { Dictionary <long, VersionEntry> versionList = null; if (!this.dict.TryGetValue(req.RecordKey, out versionList) || !versionList.TryGetValue(req.VersionKey, out verEntry)) { throw new TransactionException("The specified version does not exist."); } } if (verEntry.TxId == req.SenderId && verEntry.EndTimestamp == req.ExpectedEndTs) { verEntry.BeginTimestamp = req.BeginTs; verEntry.EndTimestamp = req.EndTs; verEntry.TxId = req.TxId; } VersionEntry.CopyValue(verEntry, req.LocalVerEntry); req.Result = req.LocalVerEntry; req.Finished = true; }
internal override void Visit(ReplaceVersionRequest req) { VersionEntry entry = req.RemoteVerEntry; if (entry == null) { throw new TransactionException("The version entry should be referenced for main-memory k-v."); } if (entry.TxId == req.SenderId && entry.EndTimestamp == req.ExpectedEndTs && entry.VersionKey == req.VersionKey) { while (Interlocked.CompareExchange(ref entry.latch, 1, 0) != 0) { ; } entry.BeginTimestamp = req.BeginTs; entry.EndTimestamp = req.EndTs; entry.TxId = req.TxId; VersionEntry.CopyValue(entry, req.LocalVerEntry); Interlocked.Exchange(ref entry.latch, 0); } req.Result = req.LocalVerEntry; req.Finished = true; }
internal override void Visit(UpdateVersionMaxCommitTsRequest req) { VersionEntry verEntry = req.RemoteVerEntry; if (verEntry == null) { throw new TransactionException("The version entry should be referenced for main-memory k-v."); } if (verEntry.VersionKey != req.VersionKey) { throw new TransactionException("The referenced version entry has been recycled for new data."); } while (Interlocked.CompareExchange(ref verEntry.latch, 1, 0) != 0) { ; } verEntry.MaxCommitTs = Math.Max(req.MaxCommitTs, verEntry.MaxCommitTs); VersionEntry.CopyValue(verEntry, req.LocalVerEntry); Interlocked.Exchange(ref verEntry.latch, 0); req.Result = req.LocalVerEntry; 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) { 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(ReadVersionRequest req) { VersionEntry verEntry = req.RemoteVerEntry; if (verEntry == null) { Dictionary <long, VersionEntry> versionList = null; if (!this.dict.TryGetValue(req.RecordKey, out versionList) || !versionList.TryGetValue(req.VersionKey, out verEntry)) { req.Result = null; req.Finished = true; } } VersionEntry.CopyValue(verEntry, req.LocalVerEntry); req.Result = req.LocalVerEntry; req.Finished = true; }
internal override void Visit(UpdateVersionMaxCommitTsRequest req) { VersionEntry verEntry = req.RemoteVerEntry; if (verEntry == null) { Dictionary <long, VersionEntry> versionList = null; if (!this.dict.TryGetValue(req.RecordKey, out versionList) || !versionList.TryGetValue(req.VersionKey, out verEntry)) { throw new TransactionException("The specified version does not exist."); } } // Only update the max commit time when uploaded commit time is larger than the version's verEntry.MaxCommitTs = Math.Max(verEntry.MaxCommitTs, req.MaxCommitTs); VersionEntry.CopyValue(verEntry, req.LocalVerEntry); req.Result = req.LocalVerEntry; req.Finished = true; }