示例#1
0
        private void SendByteDelta(ByteDelta delta, Stream inputStream, Stream outputStream)
        {
            outputStream.WriteByte(DeltaStreamConstants.NEW_BLOCK_START_MARKER);
            outputStream.WriteInt(delta.Length);
            var buffer = new byte[delta.Length];

            inputStream.Seek(delta.Offset, SeekOrigin.Begin);
            long totalRead = 0;

            while (totalRead < delta.Length)
            {
                var toRead     = (int)MathEx.Bounded(0, StreamChunkSize, delta.Length - totalRead);
                int readLength = inputStream.Read(buffer, 0, toRead);
                if (readLength == 0 && totalRead < delta.Length)
                {
                    throw new IOException("Input stream offset out of bounds, or not enough data available");
                }
                outputStream.Write(buffer, 0, readLength);
                totalRead += readLength;
            }
        }
示例#2
0
        public IEnumerable<IDelta> GetDeltas(Stream inputStream)
        {
            if (inputStream == null) throw new ArgumentNullException("inputStream");
            if (_initialized == false) throw new InvalidOperationException("Initialize must be called");

            ChecksumProvider.Reset();
            var slidingBuffer = new SlidingStreamBuffer(inputStream, _blockSize);
            slidingBuffer.Warmup();
            bool startingNewBlock = true;
            long offset = 0;
            var deltas = new List<IDelta>();
            var currentByteDelta = new ByteDelta();

            #if DEBUG
            Statistics.Matching = 0;
            Statistics.PossibleMatches = 0;
            Statistics.NonMatching = 0;
            #endif
            int currentBlockSize;
            while ((currentBlockSize = (int) slidingBuffer.GetNumBytesAvailable()) > 0)
            {
                // Deal with signed integer limits
                if (IsSignedIntLength(offset - currentByteDelta.Offset))
                {
                    currentByteDelta.Length = (int) (offset - currentByteDelta.Offset);
                    deltas.Add(currentByteDelta);
                    startingNewBlock = true;
                }

                if (startingNewBlock)
                {
                    currentByteDelta = new ByteDelta {Offset = offset};
                    ChecksumProvider.ProcessBlock(slidingBuffer.GetBuffer(), 0, currentBlockSize);
                }
                else if (currentBlockSize < _blockSize)
                    ChecksumProvider.TrimFront(); // remaining bytes < block_size, so read nothing new - just trim
                else
                    ChecksumProvider.RollByte(slidingBuffer[(int) (currentBlockSize - 1)]);
                        // at this point, sigGen needs the last byte of the current block

                uint currentBlockChecksum = ChecksumProvider.Value;
                ushort currentBlockChecksumHash = RollingChecksum.HashChecksum(currentBlockChecksum);
                if (_remoteBlocksIndexTable.ContainsKey(currentBlockChecksumHash))
                {
                    List<HashBlock> possibleRemoteBlockMatches = _remoteBlocksIndexTable[currentBlockChecksumHash];
                    if (possibleRemoteBlockMatches.Any(entry => entry.Checksum == currentBlockChecksum))
                    {
            #if DEBUG
                        ++Statistics.PossibleMatches;
            #endif
                        byte[] currentBlockHash = HashProvider.ComputeHash(slidingBuffer.GetBuffer(), 0,
                                                                           (int) currentBlockSize);
                        HashBlock matchingTargetBlock;
                        if ((matchingTargetBlock =
                             possibleRemoteBlockMatches.FirstOrDefault(
                                 entry => entry.Hash.SequenceEqual(currentBlockHash))) != null)
                        {
            #if DEBUG
                            Statistics.Matching += 1;
            #endif
                            if ((currentByteDelta.Length = (int) (offset - currentByteDelta.Offset)) > 0)
                            {
                                deltas.Add(currentByteDelta);
                            }
                            deltas.Add(new CopyDelta
                                           {
                                               Offset = matchingTargetBlock.Offset,
                                               Length = matchingTargetBlock.Length
                                           });
                            slidingBuffer.MoveForward((int) currentBlockSize);
                            offset += currentBlockSize;
                            startingNewBlock = true;
                            continue;
                        }
                    }
                }
            #if DEBUG
                ++Statistics.NonMatching;
            #endif
                slidingBuffer.MoveForward(1);
                ++offset;
                startingNewBlock = false;
            }
            Statistics.FileLength = offset;
            if (!startingNewBlock && (currentByteDelta.Length = (int) (offset - currentByteDelta.Offset)) > 0)
            {
                deltas.Add(currentByteDelta);
            }
            #if DEBUG
            Statistics.FileLength = offset;
            #endif
            return deltas;
        }
示例#3
0
 private void SendByteDelta(ByteDelta delta, Stream inputStream, Stream outputStream)
 {
     outputStream.WriteByte(DeltaStreamConstants.NEW_BLOCK_START_MARKER);
     outputStream.WriteInt(delta.Length);
     var buffer = new byte[delta.Length];
     inputStream.Seek(delta.Offset, SeekOrigin.Begin);
     long totalRead = 0;
     while (totalRead < delta.Length)
     {
         var toRead = (int) MathEx.Bounded(0, StreamChunkSize, delta.Length - totalRead);
         int readLength = inputStream.Read(buffer, 0, toRead);
         if (readLength == 0 && totalRead < delta.Length)
             throw new IOException("Input stream offset out of bounds, or not enough data available");
         outputStream.Write(buffer, 0, readLength);
         totalRead += readLength;
     }
 }
示例#4
0
        public IEnumerable <IDelta> GetDeltas(Stream inputStream)
        {
            if (inputStream == null)
            {
                throw new ArgumentNullException("inputStream");
            }
            if (_initialized == false)
            {
                throw new InvalidOperationException("Initialize must be called");
            }

            ChecksumProvider.Reset();
            var slidingBuffer = new SlidingStreamBuffer(inputStream, _blockSize);

            slidingBuffer.Warmup();
            bool startingNewBlock = true;
            long offset           = 0;
            var  deltas           = new List <IDelta>();
            var  currentByteDelta = new ByteDelta();

#if DEBUG
            Statistics.Matching        = 0;
            Statistics.PossibleMatches = 0;
            Statistics.NonMatching     = 0;
#endif
            int currentBlockSize;
            while ((currentBlockSize = (int)slidingBuffer.GetNumBytesAvailable()) > 0)
            {
                // Deal with signed integer limits
                if (IsSignedIntLength(offset - currentByteDelta.Offset))
                {
                    currentByteDelta.Length = (int)(offset - currentByteDelta.Offset);
                    deltas.Add(currentByteDelta);
                    startingNewBlock = true;
                }

                if (startingNewBlock)
                {
                    currentByteDelta = new ByteDelta {
                        Offset = offset
                    };
                    ChecksumProvider.ProcessBlock(slidingBuffer.GetBuffer(), 0, currentBlockSize);
                }
                else if (currentBlockSize < _blockSize)
                {
                    ChecksumProvider.TrimFront(); // remaining bytes < block_size, so read nothing new - just trim
                }
                else
                {
                    ChecksumProvider.RollByte(slidingBuffer[(int)(currentBlockSize - 1)]);
                }
                // at this point, sigGen needs the last byte of the current block

                uint   currentBlockChecksum     = ChecksumProvider.Value;
                ushort currentBlockChecksumHash = RollingChecksum.HashChecksum(currentBlockChecksum);
                if (_remoteBlocksIndexTable.ContainsKey(currentBlockChecksumHash))
                {
                    List <HashBlock> possibleRemoteBlockMatches = _remoteBlocksIndexTable[currentBlockChecksumHash];
                    if (possibleRemoteBlockMatches.Any(entry => entry.Checksum == currentBlockChecksum))
                    {
#if DEBUG
                        ++Statistics.PossibleMatches;
#endif
                        byte[] currentBlockHash = HashProvider.ComputeHash(slidingBuffer.GetBuffer(), 0,
                                                                           (int)currentBlockSize);
                        HashBlock matchingTargetBlock;
                        if ((matchingTargetBlock =
                                 possibleRemoteBlockMatches.FirstOrDefault(
                                     entry => entry.Hash.SequenceEqual(currentBlockHash))) != null)
                        {
#if DEBUG
                            Statistics.Matching += 1;
#endif
                            if ((currentByteDelta.Length = (int)(offset - currentByteDelta.Offset)) > 0)
                            {
                                deltas.Add(currentByteDelta);
                            }
                            deltas.Add(new CopyDelta
                            {
                                Offset = matchingTargetBlock.Offset,
                                Length = matchingTargetBlock.Length
                            });
                            slidingBuffer.MoveForward((int)currentBlockSize);
                            offset          += currentBlockSize;
                            startingNewBlock = true;
                            continue;
                        }
                    }
                }
#if DEBUG
                ++Statistics.NonMatching;
#endif
                slidingBuffer.MoveForward(1);
                ++offset;
                startingNewBlock = false;
            }
            Statistics.FileLength = offset;
            if (!startingNewBlock && (currentByteDelta.Length = (int)(offset - currentByteDelta.Offset)) > 0)
            {
                deltas.Add(currentByteDelta);
            }
#if DEBUG
            Statistics.FileLength = offset;
#endif
            return(deltas);
        }