private void Compress(CompressionBlock block) { using (var memoryStream = new MemoryStream(_bufferSize)) { using (var gzipStream = new GZipStream(memoryStream, _compressionMode)) { gzipStream.Write(block.Data, 0, block.EffectiveSize); } byte[] data = memoryStream.ToArray(); GZipHeader gZipHeader = new GZipHeader(data); int initialHeaderSize = gZipHeader.Header.Length; int size = 0; // Добавляем поле с размером. gZipHeader.SetExtra( CompressedBlocksProvider.VeeamArchiverSI1, CompressedBlocksProvider.VeeamArchiverSI2, BitConverter.GetBytes(size)); // Устанавливаем конечный размер блока. size = (int)(gZipHeader.Header.Length + data.Length - initialHeaderSize); gZipHeader.SetExtra( CompressedBlocksProvider.VeeamArchiverSI1, CompressedBlocksProvider.VeeamArchiverSI2, BitConverter.GetBytes(size)); byte[] resultBlock = new byte[size]; Array.Copy(gZipHeader.Header, resultBlock, gZipHeader.Header.Length); Array.Copy(data, initialHeaderSize, resultBlock, gZipHeader.Header.Length, data.Length - initialHeaderSize); _processedIndex = block.BlockIndex; WriteBlock(new CompressionBlock(_processedIndex, resultBlock)); } }
private void CompressionWorker(Object stream) { while (_readerThread.IsAlive || _readBlocks.Count > 0) { if (_blocksToWrite.Count > _blockCacheSize) { _onWrittenEvent.WaitOne(SyncWaitMs); continue; } CompressionBlock currentBlock = ReadBlock(); if (currentBlock == null) { if (_readerThread.IsAlive) { _onReadEvent.WaitOne(SyncWaitMs); } continue; } if (currentBlock.BlockIndex == 0) { int desiredThreadsCount = 1; _parallelDecompression = false; if (_compressionMode == CompressionMode.Compress) { desiredThreadsCount = Environment.ProcessorCount; _parallelDecompression = true; } else { try { GZipHeader header = new GZipHeader(currentBlock.Data); byte[] sizeData = header.GetExtra( CompressedBlocksProvider.VeeamArchiverSI1, CompressedBlocksProvider.VeeamArchiverSI2); if (sizeData != null && BitConverter.ToInt32(sizeData, 0) > 0) { desiredThreadsCount = Environment.ProcessorCount; _parallelDecompression = true; } } catch (Exception ex) { RaiseErrorOccured(ex); } } for (int i = 0; i < desiredThreadsCount - 1; i++) { var thread = new Thread(new ParameterizedThreadStart(CompressionWorker)); _compressionThreads.Add(thread); thread.Start(); } } try { if (_compressionMode == CompressionMode.Compress) { Compress(currentBlock); } else { Decompress(currentBlock); } } catch (Exception ex) { RaiseErrorOccured(ex); } } if (_decompressionStream != null) { _decompressionStream.Dispose(); } if (_memoryToDecompress != null) { _memoryToDecompress.Dispose(); } }
/// <inheritdoc /> public CompressionBlock GetNextBlock() { lock (_streamLock) { int readSize = _internalBufferSize; GZipHeader header = null; _currentBlockIndex++; byte[] resultBuffer; int bytesRead = 0; if (_gzippedStream.Position == _gzippedStream.Length) { return(null); } // Для первого буфера нужно вычитать заголовок, который гарантировано должен присутствовать. // Дальше принимается решение о том, записан файл данной утилитой и можно вычитывать поблочно или // блоки могут быть произвольными, поскольку границы блоков не выделить. if (_currentBlockIndex == 0) { header = new GZipHeader(_gzippedStream); byte[] sizeData = header.GetExtra(1, 4); if (sizeData != null && BitConverter.ToInt32(sizeData, 0) > 0) { _isBlocksDelimited = true; readSize = BitConverter.ToInt32(sizeData, 0); resultBuffer = new byte[readSize]; Array.Copy(header.Header, resultBuffer, header.Header.Length); _gzippedStream.Read( resultBuffer, header.Header.Length, readSize - header.Header.Length); _bytesProvided += resultBuffer.Length; return(new CompressionBlock(_currentBlockIndex, resultBuffer)); } else { resultBuffer = new byte[_internalBufferSize]; Array.Copy(header.Header, resultBuffer, header.Header.Length); bytesRead = _gzippedStream.Read( resultBuffer, header.Header.Length, _internalBufferSize - header.Header.Length); _bytesProvided += bytesRead + header.Header.Length; return(new CompressionBlock( _currentBlockIndex, resultBuffer, bytesRead + header.Header.Length)); } } if (_isBlocksDelimited) { header = new GZipHeader(_gzippedStream); byte[] sizeData = header.GetExtra(1, 4); if (sizeData != null && BitConverter.ToInt32(sizeData, 0) > 0) { readSize = BitConverter.ToInt32(sizeData, 0); } resultBuffer = new byte[readSize]; Array.Copy(header.Header, resultBuffer, header.Header.Length); _gzippedStream.Read( resultBuffer, header.Header.Length, readSize - header.Header.Length); bytesRead = readSize; } else { resultBuffer = new byte[_internalBufferSize]; bytesRead = _gzippedStream.Read( resultBuffer, 0, _internalBufferSize); } if (bytesRead == 0) { return(null); } _bytesProvided += bytesRead; return(new CompressionBlock(_currentBlockIndex, resultBuffer, bytesRead)); } }