예제 #1
0
        internal ReadOnlySpan <byte> EncodeBatch(KeyValuePair <byte[], ResultCacheEntry>[] operations)
        {
            if (operations.Length == 0)
            {
                throw new ArgumentException("Zero size batch", nameof(operations));
            }

            long maxSize = 0;

            maxSize += 8;                     // sequence
            maxSize += 4 * operations.Length; // count
            foreach (KeyValuePair <byte[], ResultCacheEntry> entry in operations)
            {
                maxSize += 1;                 // op code
                maxSize += 10;                // varint max
                maxSize += entry.Key.Length;
                if (entry.Value.ResultState == ResultState.Exist)
                {
                    maxSize += 10;                     // varint max
                    maxSize += entry.Value.Data?.Length ?? 0;
                }
            }

            Span <byte> data = new byte[maxSize];            // big enough to contain all data regardless of size

            var writer = new SpanWriter(data);

            // write sequence
            writer.Write((ulong)operations.First().Value.Sequence);
            // write operations count
            writer.Write((uint)operations.Length);

            foreach (KeyValuePair <byte[], ResultCacheEntry> operation in operations)
            {
                byte[]           key   = operation.Key;
                ResultCacheEntry entry = operation.Value;
                // write op type (byte)
                writer.Write(entry.ResultState == ResultState.Exist ? (byte)OperationType.Value : (byte)OperationType.Delete);
                // write key
                writer.WriteLengthPrefixed(key);

                if (entry.ResultState == ResultState.Exist)
                {
                    // write data
                    writer.WriteLengthPrefixed(entry.Data);
                }
            }

            return(data.Slice(0, writer.Position));
        }
예제 #2
0
        internal void Put(WriteBatch batch)
        {
            if (_resultCache == null)
            {
                throw new InvalidOperationException("Log not prepared for updates. Did you forget to call Open()?");
            }

            foreach (BatchOperation operation in batch.Operations)
            {
                byte[] key  = operation.Key;
                byte[] data = operation.Data;
                _estimatedSize += (ulong)(key.Length + 8 + data.Length + 10 /* varlong * 2 */);

                _resultCache[key] = new ResultCacheEntry
                {
                    Sequence    = (long)batch.Sequence,
                    Data        = data,
                    ResultState = ResultState.Exist
                };
            }
        }