public AggregateCopyOperationsDecorator(IDeltaWriter decorated) { this.decorated = decorated; }
public void BuildDelta(Stream newFileStream, ISignatureReader signatureReader, IDeltaWriter deltaWriter) { var signature = signatureReader.ReadSignature(); var chunks = signature.Chunks; var hash = signature.HashAlgorithm.ComputeHash(newFileStream); newFileStream.Seek(0, SeekOrigin.Begin); deltaWriter.WriteMetadata(signature.HashAlgorithm, hash); chunks = OrderChunksByChecksum(chunks); int minChunkSize; int maxChunkSize; var chunkMap = CreateChunkMap(chunks, out maxChunkSize, out minChunkSize); var buffer = new byte[ReadBufferSize]; long lastMatchPosition = 0; var fileSize = newFileStream.Length; ProgressReporter.ReportProgress("Building delta", 0, fileSize); while (true) { var startPosition = newFileStream.Position; var read = newFileStream.Read(buffer, 0, buffer.Length); if (read < 0) break; var checksumAlgorithm = signature.RollingChecksumAlgorithm; uint checksum = 0; var remainingPossibleChunkSize = maxChunkSize; for (var i = 0; i < read - minChunkSize + 1; i++) { var readSoFar = startPosition + i; var remainingBytes = read - i; if (remainingBytes < maxChunkSize) { remainingPossibleChunkSize = minChunkSize; } if (i == 0 || remainingBytes < maxChunkSize) { checksum = checksumAlgorithm.Calculate(buffer, i, remainingPossibleChunkSize); } else { var remove = buffer[i- 1]; var add = buffer[i + remainingPossibleChunkSize - 1]; checksum = checksumAlgorithm.Rotate(checksum, remove, add, remainingPossibleChunkSize); } ProgressReporter.ReportProgress("Building delta", readSoFar, fileSize); if (readSoFar - (lastMatchPosition - remainingPossibleChunkSize) < remainingPossibleChunkSize) continue; if (!chunkMap.ContainsKey(checksum)) continue; var startIndex = chunkMap[checksum]; for (var j = startIndex; j < chunks.Count && chunks[j].RollingChecksum == checksum; j++) { var chunk = chunks[j]; var sha = signature.HashAlgorithm.ComputeHash(buffer, i, remainingPossibleChunkSize); if (StructuralComparisons.StructuralEqualityComparer.Equals(sha, chunks[j].Hash)) { readSoFar = readSoFar + remainingPossibleChunkSize; var missing = readSoFar - lastMatchPosition; if (missing > remainingPossibleChunkSize) { deltaWriter.WriteDataCommand(newFileStream, lastMatchPosition, missing - remainingPossibleChunkSize); } deltaWriter.WriteCopyCommand(new DataRange(chunk.StartOffset, chunk.Length)); lastMatchPosition = readSoFar; break; } } } if (read < buffer.Length) { break; } newFileStream.Position = newFileStream.Position - maxChunkSize + 1; } if (newFileStream.Length != lastMatchPosition) { deltaWriter.WriteDataCommand(newFileStream, lastMatchPosition, newFileStream.Length - lastMatchPosition); } deltaWriter.Finish(); }
public void BuildDelta(Stream newFileStream, ISignatureReader signatureReader, IDeltaWriter deltaWriter) { var signature = signatureReader.ReadSignature(); var chunks = signature.Chunks; var hash = signature.HashAlgorithm.ComputeHash(newFileStream); newFileStream.Seek(0, SeekOrigin.Begin); deltaWriter.WriteMetadata(signature.HashAlgorithm, hash); chunks = OrderChunksByChecksum(chunks); int minChunkSize; int maxChunkSize; var chunkMap = CreateChunkMap(chunks, out maxChunkSize, out minChunkSize); var buffer = new byte[ReadBufferSize]; long lastMatchPosition = 0; var fileSize = newFileStream.Length; ProgressReporter.ReportProgress("Building delta", 0, fileSize); while (true) { var startPosition = newFileStream.Position; var read = newFileStream.Read(buffer, 0, buffer.Length); if (read < 0) { break; } var checksumAlgorithm = signature.RollingChecksumAlgorithm; uint checksum = 0; var remainingPossibleChunkSize = maxChunkSize; for (var i = 0; i < read - minChunkSize + 1; i++) { var readSoFar = startPosition + i; var remainingBytes = read - i; if (remainingBytes < maxChunkSize) { remainingPossibleChunkSize = minChunkSize; } if (i == 0 || remainingBytes < maxChunkSize) { checksum = checksumAlgorithm.Calculate(buffer, i, remainingPossibleChunkSize); } else { var remove = buffer[i - 1]; var add = buffer[i + remainingPossibleChunkSize - 1]; checksum = checksumAlgorithm.Rotate(checksum, remove, add, remainingPossibleChunkSize); } ProgressReporter.ReportProgress("Building delta", readSoFar, fileSize); if (readSoFar - (lastMatchPosition - remainingPossibleChunkSize) < remainingPossibleChunkSize) { continue; } if (!chunkMap.ContainsKey(checksum)) { continue; } var startIndex = chunkMap[checksum]; for (var j = startIndex; j < chunks.Count && chunks[j].RollingChecksum == checksum; j++) { var chunk = chunks[j]; var sha = signature.HashAlgorithm.ComputeHash(buffer, i, remainingPossibleChunkSize); if (StructuralComparisons.StructuralEqualityComparer.Equals(sha, chunks[j].Hash)) { readSoFar = readSoFar + remainingPossibleChunkSize; var missing = readSoFar - lastMatchPosition; if (missing > remainingPossibleChunkSize) { deltaWriter.WriteDataCommand(newFileStream, lastMatchPosition, missing - remainingPossibleChunkSize); } deltaWriter.WriteCopyCommand(new DataRange(chunk.StartOffset, chunk.Length)); lastMatchPosition = readSoFar; break; } } } if (read < buffer.Length) { break; } newFileStream.Position = newFileStream.Position - maxChunkSize + 1; } if (newFileStream.Length != lastMatchPosition) { deltaWriter.WriteDataCommand(newFileStream, lastMatchPosition, newFileStream.Length - lastMatchPosition); } deltaWriter.Finish(); }
public void BuildDelta(Stream newFileStream, ISignatureReader signatureReader, IDeltaWriter deltaWriter) { var newFileVerificationHashAlgorithm = SupportedAlgorithms.Hashing.Md5(); newFileStream.Seek(0, SeekOrigin.Begin); var newFileHash = newFileVerificationHashAlgorithm.ComputeHash(newFileStream); newFileStream.Seek(0, SeekOrigin.Begin); var signature = signatureReader.ReadSignature(); var chunks = OrderChunksByChecksum(signature.Chunks); var chunkMap = CreateChunkMap(chunks, out int maxChunkSize, out int minChunkSize); deltaWriter.WriteMetadata(new DeltaMetadata { HashAlgorithm = signature.HashAlgorithm.Name, ExpectedFileHashAlgorithm = newFileVerificationHashAlgorithm.Name, ExpectedFileHash = Convert.ToBase64String(newFileHash), BaseFileHash = signature.Metadata.BaseFileHash, BaseFileHashAlgorithm = signature.Metadata.BaseFileHashAlgorithm }); var checksumAlgorithm = signature.RollingChecksumAlgorithm; var buffer = new byte[readBufferSize]; long lastMatchPosition = 0; var fileSize = newFileStream.Length; ProgressReport?.Report(new ProgressReport { Operation = ProgressOperationType.BuildingDelta, CurrentPosition = 0, Total = fileSize }); while (true) { var startPosition = newFileStream.Position; var read = newFileStream.Read(buffer, 0, buffer.Length); if (read < 0) { break; } uint checksum = 0; long progressIterationCount = 0; var remainingPossibleChunkSize = maxChunkSize; for (var i = 0; i < read - minChunkSize + 1; i++) { var readSoFar = startPosition + i; var remainingBytes = read - i; if (remainingBytes < maxChunkSize) { remainingPossibleChunkSize = minChunkSize; } if (i == 0 || remainingBytes < maxChunkSize) { checksum = checksumAlgorithm.Calculate(buffer, i, remainingPossibleChunkSize); } else { var remove = buffer[i - 1]; var add = buffer[i + remainingPossibleChunkSize - 1]; checksum = checksumAlgorithm.Rotate(checksum, remove, add, remainingPossibleChunkSize); } progressIterationCount += 1; if (ProgressReportEvery == -1 || ProgressReportEvery <= progressIterationCount) { ProgressReport?.Report(new ProgressReport { Operation = ProgressOperationType.BuildingDelta, CurrentPosition = readSoFar, Total = fileSize }); progressIterationCount = 0; } if (readSoFar - (lastMatchPosition - remainingPossibleChunkSize) < remainingPossibleChunkSize) { continue; } if (!chunkMap.ContainsKey(checksum)) { continue; } var startIndex = chunkMap[checksum]; for (var j = startIndex; j < chunks.Count && chunks[j].RollingChecksum == checksum; j++) { var chunk = chunks[j]; var hash = signature.HashAlgorithm.ComputeHash(buffer, i, remainingPossibleChunkSize); if (StructuralComparisons.StructuralEqualityComparer.Equals(hash, chunks[j].Hash)) { readSoFar = readSoFar + remainingPossibleChunkSize; var missing = readSoFar - lastMatchPosition; if (missing > remainingPossibleChunkSize) { deltaWriter.WriteDataCommand(newFileStream, lastMatchPosition, missing - remainingPossibleChunkSize); } deltaWriter.WriteCopyCommand(new DataRange(chunk.StartOffset, chunk.Length)); lastMatchPosition = readSoFar; break; } } } if (read < buffer.Length) { break; } newFileStream.Position = newFileStream.Position - maxChunkSize + 1; } if (newFileStream.Length != lastMatchPosition) { deltaWriter.WriteDataCommand(newFileStream, lastMatchPosition, newFileStream.Length - lastMatchPosition); } deltaWriter.Finish(); }