bool Process(BlockType blockType, ReadOnlySpan <byte> block, IEventStoreObserver observer) { if ((blockType & BlockType.Compressed) != 0) { CompressionStrategy.Decompress(ref block); } var reader = new SpanReader(block); if ((blockType & BlockType.HasTypeDeclaration) != 0) { Mapping.LoadTypeDescriptors(ref reader); } var metadata = (blockType & BlockType.HasMetadata) != 0 ? Mapping.LoadObject(ref reader) : null; uint eventCount; if ((blockType & BlockType.HasOneEvent) != 0) { eventCount = 1; } else if ((blockType & BlockType.HasMoreEvents) != 0) { eventCount = reader.ReadVUInt32(); } else { eventCount = 0; } var readEvents = observer.ObservedMetadata(metadata, eventCount); if (!readEvents) { return(observer.ShouldStopReadingNextEvents()); } var events = new object[eventCount]; var successfulEventCount = 0; for (var i = 0; i < eventCount; i++) { var ev = Mapping.LoadObject(ref reader); if (ev == null) { continue; } events[successfulEventCount] = ev; successfulEventCount++; } if (eventCount != successfulEventCount) { Array.Resize(ref events, successfulEventCount); } observer.ObservedEvents(events); return(observer.ShouldStopReadingNextEvents()); }
bool Process(BlockType blockType, ByteBuffer block, IEventStoreObserver observer) { if ((blockType & BlockType.Compressed) != 0) { CompressionStrategy.Decompress(ref block); } var reader = new ByteBufferReader(block); if ((blockType & BlockType.HasTypeDeclaration) != 0) { Mapping.LoadTypeDescriptors(reader); } var metadata = (blockType & BlockType.HasMetadata) != 0 ? Mapping.LoadObject(reader) : null; uint eventCount; if ((blockType & BlockType.HasOneEvent) != 0) { eventCount = 1; } else if ((blockType & BlockType.HasMoreEvents) != 0) { eventCount = reader.ReadVUInt32(); } else { eventCount = 0; } var readEvents = observer.ObservedMetadata(metadata, eventCount); if (!readEvents) { return(observer.ShouldStopReadingNextEvents()); } var events = new object[eventCount]; for (var i = 0; i < eventCount; i++) { events[i] = Mapping.LoadObject(reader); } observer.ObservedEvents(events); return(observer.ShouldStopReadingNextEvents()); }
public void ReadToEnd(IEventStoreObserver observer) { var overflowWriter = default(ByteBufferWriter); var bufferBlock = new byte[FirstReadAhead + MaxBlockSize]; var bufferStartPosition = NextReadPosition & SectorMask; var bufferFullLength = 0; var bufferReadOffset = (int)(NextReadPosition - bufferStartPosition); var currentReadAhead = FirstReadAhead; var buf = ByteBuffer.NewSync(bufferBlock, bufferFullLength, currentReadAhead); var bufReadLength = (int)File.Read(buf, bufferStartPosition); bufferFullLength += bufReadLength; while (true) { if (bufferStartPosition + (ulong)bufferReadOffset + HeaderSize > File.MaxFileSize) { KnownAsFinished = true; return; } if (bufferReadOffset == bufferFullLength) { break; } if (bufferReadOffset + HeaderSize > bufferFullLength) { for (var i = bufferReadOffset; i < bufferFullLength; i++) { if (bufferBlock[i] != 0) { SetCorrupted(); return; } } break; } var blockCheckSum = PackUnpack.UnpackUInt32LE(bufferBlock, bufferReadOffset); bufferReadOffset += 4; var blockLen = PackUnpack.UnpackUInt32LE(bufferBlock, bufferReadOffset); if (blockCheckSum == 0 && blockLen == 0) { bufferReadOffset -= 4; break; } var blockType = (BlockType)(blockLen & 0xff); blockLen >>= 8; if (blockType == BlockType.LastBlock && blockLen == 0) { if (Checksum.CalcFletcher32(bufferBlock, (uint)bufferReadOffset, 4) != blockCheckSum) { SetCorrupted(); return; } KnownAsFinished = true; return; } if (blockLen == 0 && blockType != (BlockType.FirstBlock | BlockType.LastBlock)) { SetCorrupted(); return; } if (blockLen + HeaderSize > MaxBlockSize) { SetCorrupted(); return; } bufferReadOffset += 4; var bufferLenToFill = (uint)(bufferReadOffset + (int)blockLen + FirstReadAhead) & SectorMaskUInt; if (bufferLenToFill > bufferBlock.Length) { bufferLenToFill = (uint)bufferBlock.Length; } buf = ByteBuffer.NewSync(bufferBlock, bufferFullLength, (int)(bufferLenToFill - bufferFullLength)); if (buf.Length > 0) { bufferLenToFill = (uint)(bufferReadOffset + (int)blockLen + currentReadAhead) & SectorMaskUInt; if (bufferLenToFill > bufferBlock.Length) { bufferLenToFill = (uint)bufferBlock.Length; } if (bufferStartPosition + bufferLenToFill > File.MaxFileSize) { bufferLenToFill = (uint)(File.MaxFileSize - bufferStartPosition); } buf = ByteBuffer.NewSync(bufferBlock, bufferFullLength, (int)(bufferLenToFill - bufferFullLength)); if (buf.Length > 0) { if (currentReadAhead * 4 < MaxBlockSize) { currentReadAhead = currentReadAhead * 2; } bufReadLength = (int)File.Read(buf, bufferStartPosition + (ulong)bufferFullLength); bufferFullLength += bufReadLength; } } if (bufferReadOffset + (int)blockLen > bufferFullLength) { SetCorrupted(); return; } if (Checksum.CalcFletcher32(bufferBlock, (uint)bufferReadOffset - 4, blockLen + 4) != blockCheckSum) { SetCorrupted(); return; } var blockTypeBlock = blockType & (BlockType.FirstBlock | BlockType.MiddleBlock | BlockType.LastBlock); var stopReadingRequested = false; if (blockTypeBlock == (BlockType.FirstBlock | BlockType.LastBlock)) { stopReadingRequested = Process(blockType, ByteBuffer.NewSync(bufferBlock, bufferReadOffset, (int)blockLen), observer); } else { if (blockTypeBlock == BlockType.FirstBlock) { overflowWriter = new ByteBufferWriter(); } else if (blockTypeBlock == BlockType.MiddleBlock || blockTypeBlock == BlockType.LastBlock) { if (overflowWriter == null) { SetCorrupted(); return; } } else { SetCorrupted(); return; } overflowWriter.WriteBlock(ByteBuffer.NewSync(bufferBlock, bufferReadOffset, (int)blockLen)); if (blockTypeBlock == BlockType.LastBlock) { stopReadingRequested = Process(blockType, overflowWriter.Data, observer); overflowWriter = null; } } bufferReadOffset += (int)blockLen; if (overflowWriter == null) { NextReadPosition = bufferStartPosition + (ulong)bufferReadOffset; } if (stopReadingRequested) { return; } var nextBufferStartPosition = (bufferStartPosition + (ulong)bufferReadOffset) & SectorMask; var bufferMoveDistance = (int)(nextBufferStartPosition - bufferStartPosition); if (bufferMoveDistance <= 0) { continue; } Array.Copy(bufferBlock, bufferMoveDistance, bufferBlock, 0, bufferFullLength - bufferMoveDistance); bufferStartPosition = nextBufferStartPosition; bufferFullLength -= bufferMoveDistance; bufferReadOffset -= bufferMoveDistance; } if (overflowWriter != null) { // It is not corrupted here just unfinished, but definitely not appendable EndBufferPosition = ulong.MaxValue; return; } EndBufferLen = (uint)(bufferReadOffset - (bufferReadOffset & SectorMaskUInt)); EndBufferPosition = bufferStartPosition + (ulong)bufferReadOffset - EndBufferLen; Array.Copy(bufferBlock, bufferReadOffset - EndBufferLen, EndBuffer, 0, EndBufferLen); }
public void ReadFromStartToEnd(IEventStoreObserver observer) { NextReadPosition = 0; ReadToEnd(observer); }
public void ReadToEnd(IEventStoreObserver observer) { var overflowWriter = default(ByteBufferWriter); var bufferBlock = new byte[FirstReadAhead + MaxBlockSize]; var bufferStartPosition = NextReadPosition & SectorMask; var bufferFullLength = 0; var bufferReadOffset = (int)(NextReadPosition - bufferStartPosition); var currentReadAhead = FirstReadAhead; var buf = ByteBuffer.NewSync(bufferBlock, bufferFullLength, currentReadAhead); var bufReadLength = (int)File.Read(buf, bufferStartPosition); bufferFullLength += bufReadLength; while (true) { if (bufferStartPosition + (ulong)bufferReadOffset + HeaderSize > File.MaxFileSize) { KnownAsFinished = true; return; } if (bufferReadOffset == bufferFullLength) { break; } if (bufferReadOffset + HeaderSize > bufferFullLength) { for (var i = bufferReadOffset; i < bufferFullLength; i++) { if (bufferBlock[i] != 0) { SetCorrupted(); return; } } break; } var blockCheckSum = PackUnpack.UnpackUInt32LE(bufferBlock, bufferReadOffset); bufferReadOffset += 4; var blockLen = PackUnpack.UnpackUInt32LE(bufferBlock, bufferReadOffset); if (blockCheckSum == 0 && blockLen == 0) { bufferReadOffset -= 4; break; } var blockType = (BlockType)(blockLen & 0xff); blockLen >>= 8; if (blockType == BlockType.LastBlock && blockLen == 0) { if (Checksum.CalcFletcher32(bufferBlock, (uint)bufferReadOffset, 4) != blockCheckSum) { SetCorrupted(); return; } KnownAsFinished = true; return; } if (blockLen == 0 && blockType != (BlockType.FirstBlock | BlockType.LastBlock)) { SetCorrupted(); return; } if (blockLen + HeaderSize > MaxBlockSize) { SetCorrupted(); return; } bufferReadOffset += 4; var bufferLenToFill = (uint)(bufferReadOffset + (int)blockLen + FirstReadAhead) & SectorMaskUInt; if (bufferLenToFill > bufferBlock.Length) bufferLenToFill = (uint)bufferBlock.Length; buf = ByteBuffer.NewSync(bufferBlock, bufferFullLength, (int)(bufferLenToFill - bufferFullLength)); if (buf.Length > 0) { bufferLenToFill = (uint)(bufferReadOffset + (int)blockLen + currentReadAhead) & SectorMaskUInt; if (bufferLenToFill > bufferBlock.Length) bufferLenToFill = (uint)bufferBlock.Length; if (bufferStartPosition + bufferLenToFill > File.MaxFileSize) { bufferLenToFill = (uint)(File.MaxFileSize - bufferStartPosition); } buf = ByteBuffer.NewSync(bufferBlock, bufferFullLength, (int)(bufferLenToFill - bufferFullLength)); if (buf.Length > 0) { if (currentReadAhead * 4 < MaxBlockSize) { currentReadAhead = currentReadAhead * 2; } bufReadLength = (int)File.Read(buf, bufferStartPosition + (ulong)bufferFullLength); bufferFullLength += bufReadLength; } } if (bufferReadOffset + (int)blockLen > bufferFullLength) { SetCorrupted(); return; } if (Checksum.CalcFletcher32(bufferBlock, (uint)bufferReadOffset - 4, blockLen + 4) != blockCheckSum) { SetCorrupted(); return; } var blockTypeBlock = blockType & (BlockType.FirstBlock | BlockType.MiddleBlock | BlockType.LastBlock); var stopReadingRequested = false; if (blockTypeBlock == (BlockType.FirstBlock | BlockType.LastBlock)) { stopReadingRequested = Process(blockType, ByteBuffer.NewSync(bufferBlock, bufferReadOffset, (int)blockLen), observer); } else { if (blockTypeBlock == BlockType.FirstBlock) { overflowWriter = new ByteBufferWriter(); } else if (blockTypeBlock == BlockType.MiddleBlock || blockTypeBlock == BlockType.LastBlock) { if (overflowWriter == null) { SetCorrupted(); return; } } else { SetCorrupted(); return; } overflowWriter.WriteBlock(ByteBuffer.NewSync(bufferBlock, bufferReadOffset, (int)blockLen)); if (blockTypeBlock == BlockType.LastBlock) { stopReadingRequested = Process(blockType, overflowWriter.Data, observer); overflowWriter = null; } } bufferReadOffset += (int)blockLen; if (overflowWriter == null) NextReadPosition = bufferStartPosition + (ulong)bufferReadOffset; if (stopReadingRequested) { return; } var nextBufferStartPosition = (bufferStartPosition + (ulong)bufferReadOffset) & SectorMask; var bufferMoveDistance = (int)(nextBufferStartPosition - bufferStartPosition); if (bufferMoveDistance <= 0) continue; Array.Copy(bufferBlock, bufferMoveDistance, bufferBlock, 0, bufferFullLength - bufferMoveDistance); bufferStartPosition = nextBufferStartPosition; bufferFullLength -= bufferMoveDistance; bufferReadOffset -= bufferMoveDistance; } if (overflowWriter != null) { // It is not corrupted here just unfinished, but definitely not appendable EndBufferPosition = ulong.MaxValue; return; } EndBufferLen = (uint)(bufferReadOffset - (bufferReadOffset & SectorMaskUInt)); EndBufferPosition = bufferStartPosition + (ulong)bufferReadOffset - EndBufferLen; Array.Copy(bufferBlock, bufferReadOffset - EndBufferLen, EndBuffer, 0, EndBufferLen); }
public void ReadFromStartToEnd(IEventStoreObserver observer) { NextReadPosition = 0; ReadToEnd(observer); }
bool Process(BlockType blockType, ByteBuffer block, IEventStoreObserver observer) { if ((blockType & BlockType.Compressed) != 0) { CompressionStrategy.Decompress(ref block); } var reader = new ByteBufferReader(block); if ((blockType & BlockType.HasTypeDeclaration) != 0) { Mapping.LoadTypeDescriptors(reader); } var metadata = (blockType & BlockType.HasMetadata) != 0 ? Mapping.LoadObject(reader) : null; uint eventCount; if ((blockType & BlockType.HasOneEvent) != 0) { eventCount = 1; } else if ((blockType & BlockType.HasMoreEvents) != 0) { eventCount = reader.ReadVUInt32(); } else { eventCount = 0; } var readEvents = observer.ObservedMetadata(metadata, eventCount); if (!readEvents) return observer.ShouldStopReadingNextEvents(); var events = new object[eventCount]; for (var i = 0; i < eventCount; i++) { events[i] = Mapping.LoadObject(reader); } observer.ObservedEvents(events); return observer.ShouldStopReadingNextEvents(); }