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;
        }
Пример #2
0
        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;
        }
Пример #3
0
        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;
        }
Пример #5
0
        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;
        }