public void Handle(ReplicationMessage.RawChunkBulk message) { if (_subscriptionId != message.SubscriptionId) { return; } if (_activeChunk == null) { ReplicationFail( "Physical chunk bulk received, but we do not have active chunk.", "Physical chunk bulk received, but we do not have active chunk."); } if (_activeChunk.ChunkHeader.ChunkStartNumber != message.ChunkStartNumber || _activeChunk.ChunkHeader.ChunkEndNumber != message.ChunkEndNumber) { Log.Error( "Received RawChunkBulk for TFChunk {chunkStartNumber}-{chunkEndNumber}, but active chunk is {activeChunk}.", message.ChunkStartNumber, message.ChunkEndNumber, _activeChunk); return; } if (_activeChunk.RawWriterPosition != message.RawPosition) { Log.Error( "Received RawChunkBulk at raw pos {rawPosition} (0x{rawPosition:X}) while current writer raw pos is {rawWriterPosition} (0x{rawWriterPosition:X}).", message.RawPosition, message.RawPosition, _activeChunk.RawWriterPosition, _activeChunk.RawWriterPosition); return; } if (!_activeChunk.TryAppendRawData(message.RawBytes)) { ReplicationFail( "Could not append raw bytes to chunk {0}-{1}, raw pos: {2} (0x{3:X}), bytes length: {4} (0x{5:X}). Chunk file size: {6} (0x{7:X}).", "Could not append raw bytes to chunk {chunkStartNumber}-{chunkEndNumber}, raw pos: {rawPosition} (0x{rawPosition:X}), bytes length: {rawBytesLength} (0x{rawBytesLength:X}). Chunk file size: {chunkFileSize} (0x{chunkFileSize:X}).", message.ChunkStartNumber, message.ChunkEndNumber, message.RawPosition, message.RawPosition, message.RawBytes.Length, message.RawBytes.Length, _activeChunk.FileSize, _activeChunk.FileSize); } _subscriptionPos += message.RawBytes.Length; if (message.CompleteChunk) { Log.Trace("Completing raw chunk {chunkStartNumber}-{chunkEndNumber}...", message.ChunkStartNumber, message.ChunkEndNumber); Writer.CompleteReplicatedRawChunk(_activeChunk); _subscriptionPos = _activeChunk.ChunkHeader.ChunkEndPosition; _framer.Reset(); _activeChunk = null; } if (message.CompleteChunk || _subscriptionPos - _ackedSubscriptionPos >= MasterReplicationService.ReplicaAckWindow) { _ackedSubscriptionPos = _subscriptionPos; Bus.Publish(new ReplicationMessage.AckLogPosition(_subscriptionId, _ackedSubscriptionPos)); } }
private TcpPackage WrapRawChunkBulk(ReplicationMessage.RawChunkBulk msg) { var dto = new ReplicationMessageDto.RawChunkBulk(msg.LeaderId.ToByteArray(), msg.SubscriptionId.ToByteArray(), msg.ChunkStartNumber, msg.ChunkEndNumber, msg.RawPosition, msg.RawBytes, msg.CompleteChunk); return(new TcpPackage(TcpCommand.RawChunkBulk, Guid.NewGuid(), dto.Serialize())); }
private bool TrySendLogBulk(ReplicaSubscription subscription, long masterCheckpoint) { /* * if (subscription == null) throw new Exception("subscription == null"); * if (subscription.BulkReader == null) throw new Exception("subscription.BulkReader == null"); * if (subscription.BulkReader.Chunk == null) throw new Exception("subscription.BulkReader.Chunk == null"); * if (subscription.DataBuffer == null) throw new Exception("subscription.DataBuffer == null"); */ var bulkReader = subscription.BulkReader; var chunkHeader = bulkReader.Chunk.ChunkHeader; BulkReadResult bulkResult; if (subscription.RawSend) { bulkResult = bulkReader.ReadNextRawBytes(subscription.DataBuffer.Length, subscription.DataBuffer); } else { var bytesToRead = (int)Math.Min(subscription.DataBuffer.Length, masterCheckpoint - subscription.LogPosition); bulkResult = bulkReader.ReadNextDataBytes(bytesToRead, subscription.DataBuffer); } bool dataFound = false; // for logical send we can get 0 at the end multiple time, but we need to get EOF exactly once if (bulkResult.BytesRead > 0 || (bulkResult.IsEOF && !subscription.RawSend && !subscription.EOFSent)) { var data = new byte[bulkResult.BytesRead]; Buffer.BlockCopy(subscription.DataBuffer, 0, data, 0, bulkResult.BytesRead); dataFound = true; subscription.EOFSent = bulkResult.IsEOF; if (subscription.RawSend) { var msg = new ReplicationMessage.RawChunkBulk( _instanceId, subscription.SubscriptionId, chunkHeader.ChunkStartNumber, chunkHeader.ChunkEndNumber, bulkResult.OldPosition, data, bulkResult.IsEOF); subscription.SendMessage(msg); } else { if (chunkHeader.GetLocalLogPosition(subscription.LogPosition) != bulkResult.OldPosition) { throw new Exception(string.Format("Replication invariant failure. SubscriptionPosition {0}, bulkResult.OldPosition {1}", subscription.LogPosition, bulkResult.OldPosition)); } var msg = new ReplicationMessage.DataChunkBulk( _instanceId, subscription.SubscriptionId, chunkHeader.ChunkStartNumber, chunkHeader.ChunkEndNumber, subscription.LogPosition, data, bulkResult.IsEOF); subscription.LogPosition += bulkResult.BytesRead; subscription.SendMessage(msg); } } if (bulkResult.IsEOF) { var newLogPosition = chunkHeader.ChunkEndPosition; if (newLogPosition < masterCheckpoint) { dataFound = true; SetSubscriptionPosition(subscription, newLogPosition, Guid.Empty, replicationStart: false, verbose: true, trial: 0); } } return(dataFound); }