Ejemplo n.º 1
0
 uint ITableInfoResolver.GetLastPesistedVersion(uint id)
 {
     using (var tr = _keyValueDB.StartTransaction())
     {
         tr.SetKeyPrefix(TableVersionsPrefix);
         var key = new byte[PackUnpack.LengthVUInt(id) + 1];
         var ofs = 0;
         PackUnpack.PackVUInt(key, ref ofs, id);
         key[ofs] = 0xff;
         if (tr.FindKey(key, 0, key.Length, FindKeyStrategy.PreferPrevious) == FindKeyResult.NotFound)
         {
             return(0);
         }
         var key2 = tr.ReadKey();
         if (key2.Length < ofs)
         {
             return(0);
         }
         if (BitArrayManipulation.CompareByteArray(key, 0, ofs, key2, 0, ofs) != 0)
         {
             return(0);
         }
         return(checked ((uint)PackUnpack.UnpackVUInt(key2, ref ofs)));
     }
 }
Ejemplo n.º 2
0
        void PackVUIntIsOrderableCore(ulong t)
        {
            var buf1 = new byte[9];
            var o1   = 0;

            PackUnpack.PackVUInt(buf1, ref o1, t - 1);
            var buf2 = new byte[9];
            var o2   = 0;

            PackUnpack.PackVUInt(buf2, ref o2, t);
            if (t <= uint.MaxValue)
            {
                Assert.Equal(o2, PackUnpack.LengthVUInt((uint)t));
            }
            Assert.Equal(o2, PackUnpack.LengthVUInt(t));
            Assert.Equal(o2, PackUnpack.LengthVUInt(buf2, 0));
            Assert.True(0 > BitArrayManipulation.CompareByteArray(buf1, o1, buf2, o2));
            var o1A = 0;

            Assert.Equal(t - 1, PackUnpack.UnpackVUInt(buf1, ref o1A));
            Assert.Equal(o1, o1A);
            var o2A = 0;

            Assert.Equal(t, PackUnpack.UnpackVUInt(buf2, ref o2A));
            Assert.Equal(o2, o2A);
        }
Ejemplo n.º 3
0
            public void Send(ByteBuffer data)
            {
                if (_disconnected)
                {
                    throw new SocketException((int)SocketError.NotConnected);
                }
                var vuLen = PackUnpack.LengthVUInt((uint)data.Length);
                var vuBuf = new byte[vuLen];
                int o     = 0;

                PackUnpack.PackVUInt(vuBuf, ref o, (uint)data.Length);
                SocketError socketError;

                lock (_sendlock)
                {
                    _socket.Send(new[] { new ArraySegment <byte>(vuBuf), data.ToArraySegment() }, SocketFlags.None,
                                 out socketError);
                }
                if (socketError == SocketError.Success)
                {
                    return;
                }
                if (!IsConnected())
                {
                    SignalDisconnected();
                }
                throw new SocketException((int)socketError);
            }
Ejemplo n.º 4
0
        public void InternalDelete(object obj)
        {
            var o     = (IDBObject)obj;
            var oid   = o.Oid;
            var taken = false;

            try
            {
                _keyValueTrProtector.Start(ref taken);
                _keyValueTr.SetKeyPrefix(ObjectDB.AllObjectsPrefix);
                var key = new byte[PackUnpack.LengthVUInt(oid)];
                int ofs = 0;
                PackUnpack.PackVUInt(key, ref ofs, oid);
                if (_keyValueTr.FindExactKey(key))
                {
                    _keyValueTr.EraseCurrent();
                }
            }
            finally
            {
                if (taken)
                {
                    _keyValueTrProtector.Stop();
                }
            }
            _objCache.TryRemove(oid);
            _dirtyObjSet.TryRemove(oid);
        }
Ejemplo n.º 5
0
        public ulong ReadVUInt64()
        {
            NeedOneByteInBuffer();
            var   l = PackUnpack.LengthVUInt(Buf, Pos);
            ulong res;

            if (Pos + l <= End)
            {
                res = PackUnpack.UnpackVUInt(Buf, ref Pos);
            }
            else
            {
                res = (ulong)(Buf[Pos] & (0xff >> l));
                do
                {
                    Pos++;
                    res <<= 8;
                    NeedOneByteInBuffer();
                    res += Buf[Pos];
                    l--;
                } while (l > 1);
                Pos++;
            }
            return(res);
        }
Ejemplo n.º 6
0
 public RelationPrimaryKeyEnumerator(IInternalObjectDBTransaction tr, RelationInfo relationInfo, ByteBuffer keyBytes,
                                     RelationDBManipulator <T> manipulator)
     : base(tr, relationInfo, keyBytes, manipulator)
 {
     _manipulator = manipulator;
     _skipBytes   = ObjectDB.AllRelationsPKPrefix.Length + +PackUnpack.LengthVUInt(relationInfo.Id);
 }
Ejemplo n.º 7
0
        void GeneratePrefix()
        {
            var o = ObjectDB.AllDictionariesPrefix.Length;

            _prefix = new byte[o + PackUnpack.LengthVUInt(_id)];
            Array.Copy(ObjectDB.AllDictionariesPrefix, _prefix, o);
            PackUnpack.PackVUInt(_prefix, ref o, _id);
        }
Ejemplo n.º 8
0
        internal static byte[] BuildKeyFromOid(ulong oid)
        {
            var key = new byte[PackUnpack.LengthVUInt(oid)];
            int ofs = 0;

            PackUnpack.PackVUInt(key, ref ofs, oid);
            return(key);
        }
Ejemplo n.º 9
0
        static void WriteIdIl(IILGen ilGenerator, Action <IILGen> pushWriter, int id)
        {
            var bytes = new byte[PackUnpack.LengthVUInt((uint)id)];
            int o     = 0;

            PackUnpack.PackVUInt(bytes, ref o, (uint)id);
            WriteShortPrefixIl(ilGenerator, pushWriter, bytes);
        }
Ejemplo n.º 10
0
        static byte[] BuildRelationPrefix(uint relationIndex)
        {
            var o      = ObjectDB.AllRelationsPKPrefix.Length;
            var prefix = new byte[o + PackUnpack.LengthVUInt(relationIndex)];

            Array.Copy(ObjectDB.AllRelationsPKPrefix, prefix, o);
            PackUnpack.PackVUInt(prefix, ref o, relationIndex);
            return(prefix);
        }
Ejemplo n.º 11
0
        internal static byte[] BuildKeyForTableVersions(uint tableId, uint tableVersion)
        {
            var key = new byte[PackUnpack.LengthVUInt(tableId) + PackUnpack.LengthVUInt(tableVersion)];
            var ofs = 0;

            PackUnpack.PackVUInt(key, ref ofs, tableId);
            PackUnpack.PackVUInt(key, ref ofs, tableVersion);
            return(key);
        }
Ejemplo n.º 12
0
        internal static void FreeObject(IInternalObjectDBTransaction tr, ulong oid)
        {
            var o      = ObjectDB.AllDictionariesPrefix.Length;
            var prefix = new byte[o + PackUnpack.LengthVUInt(oid)];

            Array.Copy(ObjectDB.AllObjectsPrefix, prefix, o);
            PackUnpack.PackVUInt(prefix, ref o, oid);
            tr.TransactionProtector.Start();
            tr.KeyValueDBTransaction.SetKeyPrefixUnsafe(prefix);
            tr.KeyValueDBTransaction.EraseAll();
        }
Ejemplo n.º 13
0
        public void WriteVUInt64(ulong value)
        {
            var len = PackUnpack.LengthVUInt(value);

            if ((uint)_buf.Length < (uint)len)
            {
                Resize(len);
            }

            PackUnpack.UnsafePackVUInt(ref PackUnpack.UnsafeGetAndAdvance(ref _buf, len), value, len);
        }
Ejemplo n.º 14
0
        static byte[] BuildRelationSecondaryKeyPrefix(uint relationIndex, uint secondaryKeyIndex)
        {
            var prefix = new byte[1 + PackUnpack.LengthVUInt(relationIndex) + PackUnpack.LengthVUInt(secondaryKeyIndex)];

            prefix[0] = ObjectDB.AllRelationsSKPrefixByte;
            int pos = 1;

            PackUnpack.PackVUInt(prefix, ref pos, relationIndex);
            PackUnpack.PackVUInt(prefix, ref pos, secondaryKeyIndex);
            return(prefix);
        }
Ejemplo n.º 15
0
        void IterateSet(ulong dictId, IFieldHandler keyHandler)
        {
            if (_visitor != null && !_visitor.StartSet())
            {
                return;
            }
            var o      = ObjectDB.AllDictionariesPrefix.Length;
            var prefix = new byte[o + PackUnpack.LengthVUInt(dictId)];

            Array.Copy(ObjectDB.AllDictionariesPrefix, prefix, o);
            PackUnpack.PackVUInt(prefix, ref o, dictId);
            long prevProtectionCounter = 0;
            long pos = 0;

            while (true)
            {
                if (pos == 0)
                {
                    if (!_trkv.FindFirstKey(prefix))
                    {
                        break;
                    }
                }
                else
                {
                    if (_trkv.CursorMovedCounter != prevProtectionCounter)
                    {
                        if (!_trkv.SetKeyIndex(prefix, pos))
                        {
                            break;
                        }
                    }
                    else
                    {
                        if (!_trkv.FindNextKey(prefix))
                        {
                            break;
                        }
                    }
                }
                _fastVisitor.MarkCurrentKeyAsUsed(_trkv);
                prevProtectionCounter = _trkv.CursorMovedCounter;
                if (_visitor == null || _visitor.StartSetKey())
                {
                    var keyReader = new SpanReader(_trkv.GetKey().Slice(prefix.Length));
                    IterateHandler(ref keyReader, keyHandler, false, null);
                    _visitor?.EndSetKey();
                }
                pos++;
            }
            _visitor?.EndSet();
        }
Ejemplo n.º 16
0
        internal void ResizeValue(byte[] newData, long newSize)
        {
            var currentEntrySize = CurrentEntrySize;
            var newEntrySize     = CalcEntrySize(KeyLen, newSize);
            int withValuePtr     = 0;

            if (HasValueSectorPtr && newSize > MaxValueLenInline)
            {
                withValuePtr = KeyValueDB.PtrDownSize;
            }
            // preserves all before current item including current sizes + key
            int ofs = EntryOffset + PackUnpack.LengthVUInt((uint)KeyLen);

            if (!ReferenceEquals(Data, newData))
            {
                Array.Copy(Data, 0, newData, 0, ofs);
            }
            if (newSize > ValueLen) // because resize could be inplace bytes have to be copied correct order
            {
                // preserves all after current item
                Array.Copy(Data,
                           EntryOffset + currentEntrySize - withValuePtr,
                           newData,
                           EntryOffset + newEntrySize - withValuePtr,
                           TotalLength - EntryOffset - currentEntrySize + withValuePtr);
                // preserves key of current item
                Array.Copy(Data, KeyOffset, newData, ofs + PackUnpack.LengthVUInt((ulong)newSize), ValueOffset - KeyOffset);
            }
            else
            {
                // preserves key of current item
                Array.Copy(Data, KeyOffset, newData, ofs + PackUnpack.LengthVUInt((ulong)newSize), ValueOffset - KeyOffset);
                // preserves all after current item
                Array.Copy(Data,
                           EntryOffset + currentEntrySize - withValuePtr,
                           newData,
                           EntryOffset + newEntrySize - withValuePtr,
                           TotalLength - EntryOffset - currentEntrySize + withValuePtr);
            }
            PackUnpack.PackVUInt(newData, ref ofs, (ulong)newSize);
            _data     = newData;
            _valueLen = newSize;
            _ofsAfterKeyAndValueLen = ofs;
            var delta = newEntrySize - currentEntrySize;

            for (int i = _pos; i < _count; i++)
            {
                var o = HeaderSize + HeaderForEntry * i;
                PackUnpack.PackUInt16LE(_data, o, (ushort)(PackUnpack.UnpackUInt16LE(_data, o) + delta));
            }
        }
Ejemplo n.º 17
0
 public long GetSingletonOid(uint id)
 {
     using (var tr = _keyValueDB.StartTransaction())
     {
         tr.SetKeyPrefix(TableSingletonsPrefix);
         var key = new byte[PackUnpack.LengthVUInt(id)];
         var ofs = 0;
         PackUnpack.PackVUInt(key, ref ofs, id);
         if (tr.FindExactKey(key))
         {
             return((long)new KeyValueDBValueReader(tr).ReadVUInt64());
         }
         return(0);
     }
 }
Ejemplo n.º 18
0
        public ODBSet(IInternalObjectDBTransaction tr, ODBDictionaryConfiguration config, ulong id)
        {
            _tr         = tr;
            _keyHandler = config.KeyHandler;
            _id         = id;
            var o = ObjectDB.AllDictionariesPrefix.Length;

            _prefix = new byte[o + PackUnpack.LengthVUInt(_id)];
            Array.Copy(ObjectDB.AllDictionariesPrefix, _prefix, o);
            PackUnpack.PackVUInt(_prefix, ref o, _id);
            _keyReader           = ((Func <AbstractBufferedReader, IReaderCtx, TKey>)config.KeyReader) !;
            _keyWriter           = ((Action <TKey, AbstractBufferedWriter, IWriterCtx>)config.KeyWriter) !;
            _keyValueTr          = _tr.KeyValueDBTransaction;
            _keyValueTrProtector = _tr.TransactionProtector;
            _count = -1;
        }
Ejemplo n.º 19
0
        // ReSharper disable once MemberCanBePrivate.Global used by FieldHandler.Load
        public ODBSet(IInternalObjectDBTransaction tr, ODBDictionaryConfiguration config, ulong id)
        {
            _tr         = tr;
            _keyHandler = config.KeyHandler;
            _id         = id;
            var len    = PackUnpack.LengthVUInt(id);
            var prefix = new byte[ObjectDB.AllDictionariesPrefixLen + len];

            MemoryMarshal.GetReference(prefix.AsSpan()) = ObjectDB.AllDictionariesPrefixByte;
            PackUnpack.UnsafePackVUInt(ref Unsafe.AddByteOffset(ref MemoryMarshal.GetReference(prefix.AsSpan()), (IntPtr)ObjectDB.AllDictionariesPrefixLen), id, len);
            _prefix     = prefix;
            _keyReader  = ((ReaderFun <TKey>)config.KeyReader) !;
            _keyWriter  = ((WriterFun <TKey>)config.KeyWriter) !;
            _keyValueTr = _tr.KeyValueDBTransaction;
            _count      = -1;
        }
Ejemplo n.º 20
0
 TableVersionInfo ITableInfoResolver.LoadTableVersionInfo(uint id, uint version, string tableName)
 {
     using (var tr = _keyValueDB.StartTransaction())
     {
         tr.SetKeyPrefix(TableVersionsPrefix);
         var key = new byte[PackUnpack.LengthVUInt(id) + PackUnpack.LengthVUInt(version)];
         var ofs = 0;
         PackUnpack.PackVUInt(key, ref ofs, id);
         PackUnpack.PackVUInt(key, ref ofs, version);
         if (!tr.FindExactKey(key))
         {
             throw new BTDBException(string.Format("Missing TableVersionInfo Id:{0} Version:{1}", id, version));
         }
         return(TableVersionInfo.Load(new KeyValueDBValueReader(tr), _objectDB.FieldHandlerFactory, tableName));
     }
 }
Ejemplo n.º 21
0
        bool PersistTableInfo(TableInfo tableInfo)
        {
            var taken = false;

            try
            {
                _keyValueTrProtector.Start(ref taken);
                byte[] key;
                int    ofs;
                if (tableInfo.LastPersistedVersion <= 0)
                {
                    _keyValueTr.SetKeyPrefix(ObjectDB.TableNamesPrefix);
                    key = new byte[PackUnpack.LengthVUInt(tableInfo.Id)];
                    ofs = 0;
                    PackUnpack.PackVUInt(key, ref ofs, tableInfo.Id);
                    if (_keyValueTr.CreateKey(key))
                    {
                        using (var writer = new KeyValueDBValueWriter(_keyValueTr))
                        {
                            writer.WriteString(tableInfo.Name);
                        }
                    }
                }
                _keyValueTr.SetKeyPrefix(ObjectDB.TableVersionsPrefix);
                key = new byte[PackUnpack.LengthVUInt(tableInfo.Id) + PackUnpack.LengthVUInt(tableInfo.ClientTypeVersion)];
                ofs = 0;
                PackUnpack.PackVUInt(key, ref ofs, tableInfo.Id);
                PackUnpack.PackVUInt(key, ref ofs, tableInfo.ClientTypeVersion);
                if (_keyValueTr.CreateKey(key))
                {
                    var tableVersionInfo = tableInfo.ClientTableVersionInfo;
                    using (var writer = new KeyValueDBValueWriter(_keyValueTr))
                    {
                        tableVersionInfo.Save(writer);
                    }
                }
                return(true);
            }
            finally
            {
                if (taken)
                {
                    _keyValueTrProtector.Stop();
                }
            }
        }
Ejemplo n.º 22
0
        public void WriteVUInt64(ulong value)
        {
            var l = PackUnpack.LengthVUInt(value);

            if (Pos + l > End)
            {
                FlushBuffer();
                if (Pos + l > End)
                {
                    var b = new byte[l];
                    int i = 0;
                    PackUnpack.PackVUInt(b, ref i, value);
                    WriteBlock(b);
                    return;
                }
            }
            PackUnpack.PackVUInt(Buf, ref Pos, value);
        }
Ejemplo n.º 23
0
        public void WriteVUInt64(ulong value)
        {
            var len = PackUnpack.LengthVUInt(value);

            if (Pos + len > End)
            {
                FlushBuffer();
                if (Pos + len > End)
                {
                    Span <byte> b = stackalloc byte[len];
                    PackUnpack.UnsafePackVUInt(ref MemoryMarshal.GetReference(b), value, len);
                    WriteBlock(b);
                    return;
                }
            }

            PackUnpack.UnsafePackVUInt(ref Unsafe.AddByteOffset(ref MemoryMarshal.GetReference(Buf.AsSpan()), (IntPtr)Pos), value, len);
            Pos += len;
        }
Ejemplo n.º 24
0
 void ReceiveBody()
 {
     try
     {
         _connector.OnNext(true);
         var buf = new byte[9];
         while (!_disconnected)
         {
             if (!Receive(buf, 0, 1))
             {
                 return;
             }
             var packLen = PackUnpack.LengthVUInt(buf, 0);
             if (packLen > 1)
             {
                 if (!Receive(buf, 1, packLen - 1))
                 {
                     return;
                 }
             }
             int o   = 0;
             var len = PackUnpack.UnpackVUInt(buf, ref o);
             if (len > int.MaxValue)
             {
                 throw new InvalidDataException();
             }
             var result = new byte[len];
             if (len != 0)
             {
                 if (!Receive(result, 0, (int)len))
                 {
                     return;
                 }
             }
             _receiver.OnNext(ByteBuffer.NewAsync(result));
         }
     }
     catch (Exception)
     {
         SignalDisconnected();
     }
     SignalDisconnected();
 }
Ejemplo n.º 25
0
        public void SkipVUInt64()
        {
            NeedOneByteInBuffer();
            var l = PackUnpack.LengthVUInt(Buf, Pos);

            if (Pos + l <= End)
            {
                Pos += l;
            }
            else
            {
                do
                {
                    Pos++;
                    NeedOneByteInBuffer();
                    l--;
                } while (l > 1);
                Pos++;
            }
        }
Ejemplo n.º 26
0
        public int RemoveByKeyPrefixWithoutIterate(ByteBuffer keyBytesPrefix)
        {
            if (_hasSecondaryIndexes)
            {
                //keyBytePrefix contains [Index Relation, Primary key prefix] we need
                //                       [Index Relation, Secondary Key Index, Primary key prefix]
                int idBytesLength = ObjectDB.AllRelationsPKPrefix.Length + PackUnpack.LengthVUInt(_relationInfo.Id);
                var writer        = new ByteBufferWriter();
                foreach (var secKey in _relationInfo.ClientRelationVersionInfo.SecondaryKeys)
                {
                    writer.WriteBlock(ObjectDB.AllRelationsSKPrefix);
                    writer.WriteVUInt32(_relationInfo.Id);
                    writer.WriteVUInt32(secKey.Key);
                    writer.WriteBlock(keyBytesPrefix.Buffer, idBytesLength, keyBytesPrefix.Length - idBytesLength);
                    _transaction.KeyValueDBTransaction.SetKeyPrefix(writer.Data);
                    _transaction.KeyValueDBTransaction.EraseAll();
                    writer.Reset();
                }
            }

            return(RemovePrimaryKeysByPrefix(keyBytesPrefix));
        }
Ejemplo n.º 27
0
 uint ITableInfoResolver.GetLastPersistedVersion(uint id)
 {
     using (var tr = _keyValueDB.StartTransaction())
     {
         tr.SetKeyPrefix(TableVersionsPrefix);
         var key = TableInfo.BuildKeyForTableVersions(id, uint.MaxValue);
         if (tr.Find(ByteBuffer.NewSync(key)) == FindResult.NotFound)
         {
             return(0);
         }
         var key2 = tr.GetKeyAsByteArray();
         var ofs  = PackUnpack.LengthVUInt(id);
         if (key2.Length < ofs)
         {
             return(0);
         }
         if (BitArrayManipulation.CompareByteArray(key, ofs, key2, ofs) != 0)
         {
             return(0);
         }
         return(checked ((uint)PackUnpack.UnpackVUInt(key2, ref ofs)));
     }
 }
Ejemplo n.º 28
0
        public AbstractBufferedWriter PrepareToWriteObject(ulong id)
        {
            var shouldStop = false;

            try
            {
                _keyValueTrProtector.Start(ref shouldStop);
                _keyValueTr.SetKeyPrefix(ObjectDB.AllObjectsPrefix);
                var key = new byte[PackUnpack.LengthVUInt(id)];
                var ofs = 0;
                PackUnpack.PackVUInt(key, ref ofs, id);
                _keyValueTr.CreateKey(key);
                var writer = new KeyValueDBValueProtectedWriter(_keyValueTr, _keyValueTrProtector);
                shouldStop = false;
                return(writer);
            }
            finally
            {
                if (shouldStop)
                {
                    _keyValueTrProtector.Stop();
                }
            }
        }
Ejemplo n.º 29
0
        void IterateDict(ulong dictId, IFieldHandler keyHandler, IFieldHandler valueHandler)
        {
            if (_visitor != null && !_visitor.StartDictionary())
            {
                return;
            }
            var o      = ObjectDB.AllDictionariesPrefix.Length;
            var prefix = new byte[o + PackUnpack.LengthVUInt(dictId)];

            Array.Copy(ObjectDB.AllDictionariesPrefix, prefix, o);
            PackUnpack.PackVUInt(prefix, ref o, dictId);
            _trkv.SetKeyPrefix(prefix);
            var  protector             = _tr.TransactionProtector;
            long prevProtectionCounter = 0;
            long pos = 0;

            while (true)
            {
                protector.Start();
                if (pos == 0)
                {
                    _trkv.SetKeyPrefix(prefix);
                    if (!_trkv.FindFirstKey())
                    {
                        break;
                    }
                }
                else
                {
                    if (protector.WasInterupted(prevProtectionCounter))
                    {
                        _trkv.SetKeyPrefix(prefix);
                        if (!_trkv.SetKeyIndex(pos))
                        {
                            break;
                        }
                    }
                    else
                    {
                        if (!_trkv.FindNextKey())
                        {
                            break;
                        }
                    }
                }
                _fastVisitor.MarkCurrentKeyAsUsed(_trkv);
                prevProtectionCounter = protector.ProtectionCounter;
                if (_visitor == null || _visitor.StartDictKey())
                {
                    var keyReader = new KeyValueDBKeyReader(_trkv);
                    IterateHandler(keyReader, keyHandler, false, null);
                    _visitor?.EndDictKey();
                }
                if (protector.WasInterupted(prevProtectionCounter))
                {
                    _trkv.SetKeyPrefix(prefix);
                    if (!_trkv.SetKeyIndex(pos))
                    {
                        break;
                    }
                }
                if (_visitor == null || _visitor.StartDictValue())
                {
                    var valueReader = new KeyValueDBValueReader(_trkv);
                    IterateHandler(valueReader, valueHandler, false, null);
                    _visitor?.EndDictValue();
                }
                pos++;
            }
            _visitor?.EndDictionary();
        }
Ejemplo n.º 30
0
        void IterateRelation(uint relationIndex, string name)
        {
            var relationVersions     = new Dictionary <uint, RelationVersionInfo>();
            var lastPersistedVersion = ReadRelationVersions(relationIndex, name, relationVersions);

            _tr.TransactionProtector.Start();

            var o      = ObjectDB.AllRelationsPKPrefix.Length;
            var prefix = new byte[o + PackUnpack.LengthVUInt(relationIndex)];

            Array.Copy(ObjectDB.AllRelationsPKPrefix, prefix, o);
            PackUnpack.PackVUInt(prefix, ref o, relationIndex);

            var  protector             = _tr.TransactionProtector;
            long prevProtectionCounter = 0;
            long pos = 0;

            while (true)
            {
                protector.Start();
                if (pos == 0)
                {
                    _trkv.SetKeyPrefix(prefix);
                    if (!_trkv.FindFirstKey())
                    {
                        break;
                    }
                }
                else
                {
                    if (protector.WasInterupted(prevProtectionCounter))
                    {
                        _trkv.SetKeyPrefix(prefix);
                        if (!_trkv.SetKeyIndex(pos))
                        {
                            break;
                        }
                    }
                    else
                    {
                        if (!_trkv.FindNextKey())
                        {
                            break;
                        }
                    }
                }
                _fastVisitor.MarkCurrentKeyAsUsed(_trkv);
                prevProtectionCounter = protector.ProtectionCounter;
                if (_visitor == null || _visitor.StartRelationKey())
                {
                    var keyReader    = new KeyValueDBKeyReader(_trkv);
                    var relationInfo = relationVersions[lastPersistedVersion];
                    IterateFields(keyReader, relationInfo.GetPrimaryKeyFields(), null);
                    _visitor?.EndRelationKey();
                }
                if (protector.WasInterupted(prevProtectionCounter))
                {
                    _trkv.SetKeyPrefix(prefix);
                    if (!_trkv.SetKeyIndex(pos))
                    {
                        break;
                    }
                }
                if (_visitor == null || _visitor.StartRelationValue())
                {
                    var valueReader  = new KeyValueDBValueReader(_trkv);
                    var version      = valueReader.ReadVUInt32();
                    var relationInfo = relationVersions[version];
                    IterateFields(valueReader, relationInfo.GetValueFields(), new HashSet <int>());
                    _visitor?.EndRelationValue();
                }
                pos++;
            }
        }