private TcpPackage WrapDataChunkBulk(ReplicationMessage.DataChunkBulk msg) { var dto = new ReplicationMessageDto.DataChunkBulk(msg.LeaderId.ToByteArray(), msg.SubscriptionId.ToByteArray(), msg.ChunkStartNumber, msg.ChunkEndNumber, msg.SubscriptionPosition, msg.DataBytes, msg.CompleteChunk); return(new TcpPackage(TcpCommand.DataChunkBulk, Guid.NewGuid(), dto.Serialize())); }
public void Handle(ReplicationMessage.DataChunkBulk message) { Interlocked.Decrement(ref FlushMessagesInQueue); try { if (_subscriptionId != message.SubscriptionId) { return; } if (_activeChunk != null) { ReplicationFail("Data chunk bulk received, but we have active chunk for receiving raw chunk bulks."); } var chunk = Writer.CurrentChunk; if (chunk.ChunkHeader.ChunkStartNumber != message.ChunkStartNumber || chunk.ChunkHeader.ChunkEndNumber != message.ChunkEndNumber) { Log.Error("Received DataChunkBulk for TFChunk {0}-{1}, but active chunk is {2}-{3}.", message.ChunkStartNumber, message.ChunkEndNumber, chunk.ChunkHeader.ChunkStartNumber, chunk.ChunkHeader.ChunkEndNumber); return; } if (_subscriptionPos != message.SubscriptionPosition) { Log.Error("Received DataChunkBulk at SubscriptionPosition {0} (0x{0:X}) while current SubscriptionPosition is {1} (0x{1:X}).", message.SubscriptionPosition, _subscriptionPos); return; } _framer.UnFrameData(new ArraySegment <byte>(message.DataBytes)); _subscriptionPos += message.DataBytes.Length; if (message.CompleteChunk) { Log.Trace("Completing data chunk {0}-{1}...", message.ChunkStartNumber, message.ChunkEndNumber); Writer.CompleteChunk(); if (_framer.HasData) { ReplicationFail("There is some data left in framer when completing chunk."); } _subscriptionPos = chunk.ChunkHeader.ChunkEndPosition; _framer.Reset(); } } catch (Exception exc) { Log.ErrorException(exc, "Exception in writer."); throw; } finally { Flush(); } if (message.CompleteChunk || _subscriptionPos - _ackedSubscriptionPos >= MasterReplicationService.ReplicaAckWindow) { _ackedSubscriptionPos = _subscriptionPos; Bus.Publish(new ReplicationMessage.AckLogPosition(_subscriptionId, _ackedSubscriptionPos)); } }
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); }