示例#1
0
 internal void WriteStartTransaction()
 {
     if (_fileIdWithTransactionLog == 0)
     {
         WriteStartOfNewTransactionLogFile();
     }
     else
     {
         if (_writerWithTransactionLog == null)
         {
             _fileWithTransactionLog   = FileCollection.GetFile(_fileIdWithTransactionLog);
             _writerWithTransactionLog = _fileWithTransactionLog.GetAppenderWriter();
         }
         if (_writerWithTransactionLog.GetCurrentPosition() > MaxTrLogFileSize)
         {
             WriteStartOfNewTransactionLogFile();
         }
     }
     _writerWithTransactionLog.WriteUInt8((byte)KVCommandType.TransactionStart);
     _writerWithTransactionLog.WriteByteArrayRaw(MagicStartOfTransaction);
 }
示例#2
0
        public ByteBuffer ReadValue(uint valueFileId, uint valueOfs, int valueSize)
        {
            if (valueSize == 0)
            {
                return(ByteBuffer.NewEmpty());
            }
            if (valueFileId == 0)
            {
                var len = valueSize >> 24;
                var buf = new byte[len];
                switch (len)
                {
                case 7:
                    buf[6] = (byte)(valueOfs >> 24);
                    goto case 6;

                case 6:
                    buf[5] = (byte)(valueOfs >> 16);
                    goto case 5;

                case 5:
                    buf[4] = (byte)(valueOfs >> 8);
                    goto case 4;

                case 4:
                    buf[3] = (byte)valueOfs;
                    goto case 3;

                case 3:
                    buf[2] = (byte)valueSize;
                    goto case 2;

                case 2:
                    buf[1] = (byte)(valueSize >> 8);
                    goto case 1;

                case 1:
                    buf[0] = (byte)(valueSize >> 16);
                    break;

                default:
                    throw new BTDBException("Corrupted DB");
                }
                return(ByteBuffer.NewAsync(buf));
            }
            var compressed = false;

            if (valueSize < 0)
            {
                compressed = true;
                valueSize  = -valueSize;
            }
            var result = ByteBuffer.NewAsync(new byte[valueSize]);
            var file   = FileCollection.GetFile(valueFileId);

            file.RandomRead(result.Buffer, 0, valueSize, valueOfs, false);
            if (compressed)
            {
                _compression.DecompressValue(ref result);
            }
            return(result);
        }
示例#3
0
        // Return true if it is suitable for continuing writing new transactions
        bool LoadTransactionLog(uint fileId, uint logOffset)
        {
            var inlineValueBuf = new byte[MaxValueSizeInlineInMemory];
            var stack          = new List <NodeIdxPair>();
            var collectionFile = FileCollection.GetFile(fileId);
            var reader         = collectionFile.GetExclusiveReader();

            try
            {
                if (logOffset == 0)
                {
                    FileTransactionLog.SkipHeader(reader);
                }
                else
                {
                    reader.SkipBlock(logOffset);
                }
                if (reader.Eof)
                {
                    return(true);
                }
                var afterTemporaryEnd = false;
                while (!reader.Eof)
                {
                    var command = (KVCommandType)reader.ReadUInt8();
                    if (command == 0 && afterTemporaryEnd)
                    {
                        collectionFile.SetSize(reader.GetCurrentPosition() - 1);
                        return(true);
                    }
                    afterTemporaryEnd = false;
                    switch (command & KVCommandType.CommandMask)
                    {
                    case KVCommandType.CreateOrUpdateDeprecated:
                    case KVCommandType.CreateOrUpdate:
                    {
                        if (_nextRoot == null)
                        {
                            return(false);
                        }
                        var keyLen   = reader.ReadVInt32();
                        var valueLen = reader.ReadVInt32();
                        var key      = new byte[keyLen];
                        reader.ReadBlock(key);
                        var keyBuf = ByteBuffer.NewAsync(key);
                        if ((command & KVCommandType.FirstParamCompressed) != 0)
                        {
                            _compression.DecompressKey(ref keyBuf);
                        }
                        var ctx = new CreateOrUpdateCtx
                        {
                            KeyPrefix   = BitArrayManipulation.EmptyByteArray,
                            Key         = keyBuf,
                            ValueFileId = fileId,
                            ValueOfs    = (uint)reader.GetCurrentPosition(),
                            ValueSize   = (command & KVCommandType.SecondParamCompressed) != 0 ? -valueLen : valueLen
                        };
                        if (valueLen <= MaxValueSizeInlineInMemory && (command & KVCommandType.SecondParamCompressed) == 0)
                        {
                            reader.ReadBlock(inlineValueBuf, 0, valueLen);
                            StoreValueInlineInMemory(ByteBuffer.NewSync(inlineValueBuf, 0, valueLen), out ctx.ValueOfs, out ctx.ValueSize);
                            ctx.ValueFileId = 0;
                        }
                        else
                        {
                            reader.SkipBlock(valueLen);
                        }
                        _nextRoot.CreateOrUpdate(ctx);
                    }
                    break;

                    case KVCommandType.EraseOne:
                    {
                        if (_nextRoot == null)
                        {
                            return(false);
                        }
                        var keyLen = reader.ReadVInt32();
                        var key    = new byte[keyLen];
                        reader.ReadBlock(key);
                        var keyBuf = ByteBuffer.NewAsync(key);
                        if ((command & KVCommandType.FirstParamCompressed) != 0)
                        {
                            _compression.DecompressKey(ref keyBuf);
                        }
                        long keyIndex;
                        var  findResult = _nextRoot.FindKey(stack, out keyIndex, BitArrayManipulation.EmptyByteArray, keyBuf);
                        if (findResult == FindResult.Exact)
                        {
                            _nextRoot.EraseRange(keyIndex, keyIndex);
                        }
                    }
                    break;

                    case KVCommandType.EraseRange:
                    {
                        if (_nextRoot == null)
                        {
                            return(false);
                        }
                        var keyLen1 = reader.ReadVInt32();
                        var keyLen2 = reader.ReadVInt32();
                        var key     = new byte[keyLen1];
                        reader.ReadBlock(key);
                        var keyBuf = ByteBuffer.NewAsync(key);
                        if ((command & KVCommandType.FirstParamCompressed) != 0)
                        {
                            _compression.DecompressKey(ref keyBuf);
                        }
                        long keyIndex1;
                        var  findResult = _nextRoot.FindKey(stack, out keyIndex1, BitArrayManipulation.EmptyByteArray, keyBuf);
                        if (findResult == FindResult.Previous)
                        {
                            keyIndex1++;
                        }
                        key = new byte[keyLen2];
                        reader.ReadBlock(key);
                        keyBuf = ByteBuffer.NewAsync(key);
                        if ((command & KVCommandType.SecondParamCompressed) != 0)
                        {
                            _compression.DecompressKey(ref keyBuf);
                        }
                        long keyIndex2;
                        findResult = _nextRoot.FindKey(stack, out keyIndex2, BitArrayManipulation.EmptyByteArray, keyBuf);
                        if (findResult == FindResult.Next)
                        {
                            keyIndex2--;
                        }
                        _nextRoot.EraseRange(keyIndex1, keyIndex2);
                    }
                    break;

                    case KVCommandType.TransactionStart:
                        if (!reader.CheckMagic(MagicStartOfTransaction))
                        {
                            return(false);
                        }
                        _nextRoot = LastCommited.NewTransactionRoot();
                        break;

                    case KVCommandType.CommitWithDeltaUlong:
                        unchecked     // overflow is expected in case commitUlong is decreasing but that should be rare
                        {
                            _nextRoot.CommitUlong += reader.ReadVUInt64();
                        }
                        goto case KVCommandType.Commit;

                    case KVCommandType.Commit:
                        _nextRoot.TrLogFileId = fileId;
                        _nextRoot.TrLogOffset = (uint)reader.GetCurrentPosition();
                        _lastCommited         = _nextRoot;
                        _nextRoot             = null;
                        break;

                    case KVCommandType.Rollback:
                        _nextRoot = null;
                        break;

                    case KVCommandType.EndOfFile:
                        return(false);

                    case KVCommandType.TemporaryEndOfFile:
                        _lastCommited.TrLogFileId = fileId;
                        _lastCommited.TrLogOffset = (uint)reader.GetCurrentPosition();
                        afterTemporaryEnd         = true;
                        break;

                    default:
                        _nextRoot = null;
                        return(false);
                    }
                }
                return(afterTemporaryEnd);
            }
            catch (EndOfStreamException)
            {
                _nextRoot = null;
                return(false);
            }
        }
示例#4
0
 bool LoadKeyIndex(uint fileId, IKeyIndex info)
 {
     try
     {
         var reader = FileCollection.GetFile(fileId).GetExclusiveReader();
         FileKeyIndex.SkipHeader(reader);
         var keyCount = info.KeyValueCount;
         _nextRoot.TrLogFileId = info.TrLogFileId;
         _nextRoot.TrLogOffset = info.TrLogOffset;
         _nextRoot.CommitUlong = info.CommitUlong;
         if (info.Compression == KeyIndexCompression.Old)
         {
             _nextRoot.BuildTree(keyCount, () =>
             {
                 var keyLength = reader.ReadVInt32();
                 var key       = ByteBuffer.NewAsync(new byte[Math.Abs(keyLength)]);
                 reader.ReadBlock(key);
                 if (keyLength < 0)
                 {
                     _compression.DecompressKey(ref key);
                 }
                 return(new BTreeLeafMember
                 {
                     Key = key.ToByteArray(),
                     ValueFileId = reader.ReadVUInt32(),
                     ValueOfs = reader.ReadVUInt32(),
                     ValueSize = reader.ReadVInt32()
                 });
             });
         }
         else
         {
             if (info.Compression != KeyIndexCompression.None)
             {
                 return(false);
             }
             var prevKey = ByteBuffer.NewEmpty();
             _nextRoot.BuildTree(keyCount, () =>
             {
                 var prefixLen = (int)reader.ReadVUInt32();
                 var keyLengthWithoutPrefix = (int)reader.ReadVUInt32();
                 var key = ByteBuffer.NewAsync(new byte[prefixLen + keyLengthWithoutPrefix]);
                 Array.Copy(prevKey.Buffer, prevKey.Offset, key.Buffer, key.Offset, prefixLen);
                 reader.ReadBlock(key.SubBuffer(prefixLen));
                 prevKey = key;
                 return(new BTreeLeafMember
                 {
                     Key = key.ToByteArray(),
                     ValueFileId = reader.ReadVUInt32(),
                     ValueOfs = reader.ReadVUInt32(),
                     ValueSize = reader.ReadVInt32()
                 });
             });
         }
         if (reader.Eof)
         {
             return(true);
         }
         if (reader.ReadInt32() == EndOfIndexFileMarker)
         {
             return(true);
         }
         return(false);
     }
     catch (Exception)
     {
         return(false);
     }
 }