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);
        }
        private long SetSubscriptionPosition(ReplicaSubscription sub,
                                             long logPosition,
                                             Guid chunkId,
                                             bool replicationStart,
                                             bool verbose,
                                             int trial)
        {
            if (trial >= 10)
            {
                throw new Exception("Too many retrials to acquire reader for subscriber.");
            }

            try
            {
                var chunk = _db.Manager.GetChunkFor(logPosition);
                Debug.Assert(chunk != null, string.Format("Chunk for LogPosition {0} (0x{0:X}) is null in MasterReplicationService! Replica: [{1},C:{2},S:{3}]",
                                                          logPosition, sub.ReplicaEndPoint, sub.ConnectionId, sub.SubscriptionId));
                var bulkReader = chunk.AcquireReader();
                if (chunk.ChunkHeader.IsScavenged && (chunkId == Guid.Empty || chunkId != chunk.ChunkHeader.ChunkId))
                {
                    var chunkStartPos = chunk.ChunkHeader.ChunkStartPosition;
                    if (verbose)
                    {
                        Log.Info("Subscribed replica [{0}, S:{1}] for raw send at {2} (0x{2:X}) (requested {3} (0x{3:X})).",
                                 sub.ReplicaEndPoint, sub.SubscriptionId, chunkStartPos, logPosition);
                        if (chunkStartPos != logPosition)
                        {
                            Log.Info("Forcing replica [{0}, S:{1}] to recreate chunk from position {2} (0x{2:X})...",
                                     sub.ReplicaEndPoint, sub.SubscriptionId, chunkStartPos);
                        }
                    }

                    sub.LogPosition = chunkStartPos;
                    sub.RawSend     = true;
                    bulkReader.SetRawPosition(ChunkHeader.Size);
                    if (replicationStart)
                    {
                        sub.SendMessage(new ReplicationMessage.ReplicaSubscribed(_instanceId, sub.SubscriptionId, sub.LogPosition));
                    }
                    sub.SendMessage(new ReplicationMessage.CreateChunk(_instanceId,
                                                                       sub.SubscriptionId,
                                                                       chunk.ChunkHeader,
                                                                       chunk.FileSize,
                                                                       isCompletedChunk: true));
                }
                else
                {
                    if (verbose)
                    {
                        Log.Info("Subscribed replica [{0},S:{1}] for data send at {2} (0x{2:X}).", sub.ReplicaEndPoint, sub.SubscriptionId, logPosition);
                    }

                    sub.LogPosition = logPosition;
                    sub.RawSend     = false;
                    bulkReader.SetDataPosition(chunk.ChunkHeader.GetLocalLogPosition(logPosition));
                    if (replicationStart)
                    {
                        sub.SendMessage(new ReplicationMessage.ReplicaSubscribed(_instanceId, sub.SubscriptionId, sub.LogPosition));
                    }
                }

                sub.EOFSent = false;
                var oldBulkReader = Interlocked.Exchange(ref sub.BulkReader, bulkReader);
                if (oldBulkReader != null)
                {
                    oldBulkReader.Release();
                }
                return(sub.LogPosition);
            }
            catch (FileBeingDeletedException)
            {
                return(SetSubscriptionPosition(sub, logPosition, chunkId, replicationStart, verbose, trial + 1));
            }
        }