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)); }
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 }; } }