private void WriteBlock(CompressionBlock block) { lock (_blocksToWrite) { _blocksToWrite.Enqueue(block); _onWriteQueryAddedEvent.Set(); } }
private void Decompress(CompressionBlock currentBlock) { if (_parallelDecompression) { using (var memoryStream = new MemoryStream(_bufferSize)) { using (var gzipStream = new GZipStream( new MemoryStream(currentBlock.Data), _compressionMode)) { byte[] decompressedData = new byte[_bufferSize]; int nRead; while ((nRead = gzipStream.Read(decompressedData, 0, decompressedData.Length)) > 0) { memoryStream.Write(decompressedData, 0, nRead); } } _processedIndex = currentBlock.BlockIndex; WriteBlock(new CompressionBlock(_processedIndex, memoryStream.ToArray())); } } else { if (_decompressionStream == null) { _memoryToDecompress = new MemoryStream(new byte[currentBlock.Data.Length]); _decompressionStream = new GZipStream(_memoryToDecompress, _compressionMode); } _memoryToDecompress.Write(currentBlock.Data, 0, currentBlock.Data.Length); _memoryToDecompress.Seek(0, SeekOrigin.Begin); while (true) { if (_blocksToWrite.Count > _blockCacheSize) { _onWrittenEvent.WaitOne(SyncWaitMs); continue; } byte[] decompressedData = new byte[_bufferSize]; int nRead = _decompressionStream.Read(decompressedData, 0, decompressedData.Length); if (nRead == 0) { break; } WriteBlock(new CompressionBlock(_processedIndex, decompressedData, nRead)); _processedIndex++; } _memoryToDecompress.Position = 0; } }
private void WriteWorker(Object streamObject) { Stream stream = streamObject as Stream; while (_blocksToWrite.Count > 0 || _compressionThreads.Any(t => t.IsAlive)) { CompressionBlock block = null; lock (_blocksToWrite) { if (_blocksToWrite.Any()) { block = _blocksToWrite.Dequeue(); } } if (block != null) { if (block.BlockIndex - _currentProcessedBlock == 1) { stream.Write(block.Data, 0, block.EffectiveSize); _onWrittenEvent.Set(); _currentProcessedBlock++; } else { _blocks.Add(block.BlockIndex, block); } } while (_blocks.ContainsKey(_currentProcessedBlock + 1)) { CompressionBlock currentBlock = _blocks[_currentProcessedBlock + 1]; _blocks.Remove(_currentProcessedBlock + 1); stream.Write(currentBlock.Data, 0, currentBlock.EffectiveSize); _onWrittenEvent.Set(); _currentProcessedBlock++; } if (block == null) { _onWriteQueryAddedEvent.WaitOne(SyncWaitMs); } } }
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(); } }