コード例 #1
0
        private void CompressAndWriteClusters(long focusVcn, int count, byte[] buffer, int offset)
        {
            BlockCompressor compressor = _context.Options.Compressor;

            compressor.BlockSize = _bytesPerCluster;

            int compressedLength = _ioBuffer.Length;
            var result           = compressor.Compress(buffer, offset, _attr.CompressionUnitSize * _bytesPerCluster, _ioBuffer, 0, ref compressedLength);

            if (result == CompressionResult.AllZeros)
            {
                _rawStream.ReleaseClusters(focusVcn, count);
            }
            else if (result == CompressionResult.Compressed && (_attr.CompressionUnitSize * _bytesPerCluster) - compressedLength > _bytesPerCluster)
            {
                int compClusters = Utilities.Ceil(compressedLength, _bytesPerCluster);
                _rawStream.AllocateClusters(focusVcn, compClusters);
                _rawStream.WriteClusters(focusVcn, compClusters, _ioBuffer, 0);
                _rawStream.ReleaseClusters(focusVcn + compClusters, _attr.CompressionUnitSize - compClusters);
            }
            else
            {
                _rawStream.AllocateClusters(focusVcn, _attr.CompressionUnitSize);
                _rawStream.WriteClusters(focusVcn, _attr.CompressionUnitSize, buffer, offset);
            }
        }
コード例 #2
0
        private int CompressAndWriteClusters(long focusVcn, int count, byte[] buffer, int offset)
        {
            BlockCompressor compressor = _context.Options.Compressor;

            compressor.BlockSize = _bytesPerCluster;

            int totalAllocated = 0;

            int compressedLength     = _ioBuffer.Length;
            CompressionResult result = compressor.Compress(buffer, offset, _attr.CompressionUnitSize * _bytesPerCluster, _ioBuffer, 0,
                                                           ref compressedLength);

            if (result == CompressionResult.AllZeros)
            {
                totalAllocated -= _rawStream.ReleaseClusters(focusVcn, count);
            }
            else if (result == CompressionResult.Compressed &&
                     _attr.CompressionUnitSize * _bytesPerCluster - compressedLength > _bytesPerCluster)
            {
                int compClusters = MathUtilities.Ceil(compressedLength, _bytesPerCluster);
                totalAllocated += _rawStream.AllocateClusters(focusVcn, compClusters);
                totalAllocated += _rawStream.WriteClusters(focusVcn, compClusters, _ioBuffer, 0);
                totalAllocated -= _rawStream.ReleaseClusters(focusVcn + compClusters,
                                                             _attr.CompressionUnitSize - compClusters);
            }
            else
            {
                totalAllocated += _rawStream.AllocateClusters(focusVcn, _attr.CompressionUnitSize);
                totalAllocated += _rawStream.WriteClusters(focusVcn, _attr.CompressionUnitSize, buffer, offset);
            }

            return(totalAllocated);
        }
コード例 #3
0
        public void Compress1KBlockSize()
        {
            object          instance   = typeof(NtfsFileSystem).Assembly.CreateInstance("DiscUtils.Ntfs.LZNT1");
            BlockCompressor compressor = (BlockCompressor)instance;

            int compressedLength = 16 * 4096;

            byte[] compressedData = new byte[compressedLength];

            // Double-check, make sure native code round-trips
            byte[] nativeCompressed = NativeCompress(_uncompressedData, 0, _uncompressedData.Length, 1024);
            Assert.AreEqual(_uncompressedData, NativeDecompress(nativeCompressed, 0, nativeCompressed.Length));

            compressor.BlockSize = 1024;
            CompressionResult r = compressor.Compress(_uncompressedData, 0, _uncompressedData.Length, compressedData, 0, ref compressedLength);

            Assert.AreEqual(CompressionResult.Compressed, r);

            byte[] duDecompressed    = new byte[_uncompressedData.Length];
            int    numDuDecompressed = compressor.Decompress(compressedData, 0, compressedLength, duDecompressed, 0);

            byte[] rightSizedDuDecompressed = new byte[numDuDecompressed];
            Array.Copy(duDecompressed, rightSizedDuDecompressed, numDuDecompressed);

            // Note: Due to bug in Windows LZNT1, we compare against native decompression, not the original data, since
            // Windows LZNT1 corrupts data on decompression when block size != 4096.
            Assert.AreEqual(rightSizedDuDecompressed, NativeDecompress(compressedData, 0, compressedLength));
        }
コード例 #4
0
        public void CompressAllZeros()
        {
            object          instance   = typeof(NtfsFileSystem).Assembly.CreateInstance("DiscUtils.Ntfs.LZNT1");
            BlockCompressor compressor = (BlockCompressor)instance;

            byte[] compressed    = new byte[64 * 1024];
            int    numCompressed = 64 * 1024;

            Assert.AreEqual(CompressionResult.AllZeros, compressor.Compress(new byte[64 * 1024], 0, 64 * 1024, compressed, 0, ref numCompressed));
        }
コード例 #5
0
        public void CompressionThrowsExceptionWhenImageHasInvalidDimensions()
        {
            var compressor = new BlockCompressor();
            var format     = new Mock <IBlockCompressionFormat>();

            var bitmap = new Mock <IUncompressedImage>();

            bitmap.Setup(b => b.Width).Returns(10);
            bitmap.Setup(b => b.Height).Returns(16);

            Assert.Throws <InvalidOperationException>(() => compressor.Compress(bitmap.Object, format.Object));
        }
コード例 #6
0
        public void CompressIncompressible()
        {
            object          instance   = typeof(NtfsFileSystem).Assembly.CreateInstance("DiscUtils.Ntfs.LZNT1");
            BlockCompressor compressor = (BlockCompressor)instance;

            Random rng = new Random(6324);

            byte[] uncompressed = new byte[64 * 1024];
            rng.NextBytes(uncompressed);

            byte[] compressed    = new byte[64 * 1024];
            int    numCompressed = 64 * 1024;

            Assert.AreEqual(CompressionResult.Incompressible, compressor.Compress(uncompressed, 0, uncompressed.Length, compressed, 0, ref numCompressed));
        }
コード例 #7
0
        public void BlockCompressorShouldWorkAsExpected()
        {
            // Arrange
            const int threadsCount = 8;
            var strater = MockRepository.GenerateMock<IBlockCompressorStarter>();
            strater.Expect(t => t.StartCompress(JobType.Compress)).Repeat.Times(threadsCount);

            var compressor = new BlockCompressor(threadsCount, strater);

            // Act
            compressor.Compress(JobType.Compress);

            // Assert
            strater.VerifyAllExpectations();
        }
コード例 #8
0
        public void Compress()
        {
            object          instance   = typeof(NtfsFileSystem).Assembly.CreateInstance("DiscUtils.Ntfs.LZNT1");
            BlockCompressor compressor = (BlockCompressor)instance;

            int compressedLength = 16 * 4096;

            byte[] compressedData = new byte[compressedLength];

            // Double-check, make sure native code round-trips
            byte[] nativeCompressed = NativeCompress(_uncompressedData, 0, _uncompressedData.Length, 4096);
            Assert.AreEqual(_uncompressedData, NativeDecompress(nativeCompressed, 0, nativeCompressed.Length));

            compressor.BlockSize = 4096;
            CompressionResult r = compressor.Compress(_uncompressedData, 0, _uncompressedData.Length, compressedData, 0, ref compressedLength);

            Assert.AreEqual(CompressionResult.Compressed, r);
            Assert.AreEqual(_uncompressedData, NativeDecompress(compressedData, 0, compressedLength));

            Assert.Less(compressedLength, _uncompressedData.Length * 0.66);
        }
コード例 #9
0
        public void CompressMidDestBuffer()
        {
            object          instance   = CreateInstance <NtfsFileSystem>("DiscUtils.Ntfs.LZNT1");
            BlockCompressor compressor = (BlockCompressor)instance;

            // Double-check, make sure native code round-trips
            byte[] nativeCompressed = NativeCompress(_uncompressedData, 0, _uncompressedData.Length, 4096);
            Assert.Equal(_uncompressedData, NativeDecompress(nativeCompressed, 0, nativeCompressed.Length));

            int compressedLength = 128 * 1024;

            byte[] compressedData = new byte[compressedLength];

            compressor.BlockSize = 4096;
            CompressionResult r = compressor.Compress(_uncompressedData, 0, _uncompressedData.Length, compressedData, 32 * 1024, ref compressedLength);

            Assert.Equal(CompressionResult.Compressed, r);
            Assert.True(compressedLength < _uncompressedData.Length);

            Assert.Equal(_uncompressedData, NativeDecompress(compressedData, 32 * 1024, compressedLength));
        }
コード例 #10
0
        public void RunsCompressionForEachBlock()
        {
            const int byteCount = 8;

            var format = new Mock <IBlockCompressionFormat>();

            format.Setup(f => f.BlockSize).Returns(byteCount);
            format.Setup(f => f.Compress(It.IsAny <Color[]>())).Returns(new byte[byteCount]);

            var compressor = new BlockCompressor();

            compressor.Compress(CreateBitmapMock(), format.Object);

            format.Verify(f => f.Compress(It.IsAny <Color[]>()), Times.Exactly(6));
            format.Verify(f => f.Compress(It.Is <Color[]>(colors => colors.All(c => c == Red))));
            format.Verify(f => f.Compress(It.Is <Color[]>(colors => colors.All(c => c == Green))));
            format.Verify(f => f.Compress(It.Is <Color[]>(colors => colors.All(c => c == Blue))));
            format.Verify(f => f.Compress(It.Is <Color[]>(colors => colors.All(c => c == White))));
            format.Verify(f => f.Compress(It.Is <Color[]>(colors => colors.All(c => c == Black))));
            format.Verify(f => f.Compress(It.Is <Color[]>(colors => colors.All(c => c == Gray))));
        }
コード例 #11
0
        public void Compress1KBlock()
        {
            object          instance   = typeof(NtfsFileSystem).Assembly.CreateInstance("DiscUtils.Ntfs.LZNT1");
            BlockCompressor compressor = (BlockCompressor)instance;

            byte[] uncompressed1K = new byte[1024];
            Array.Copy(_uncompressedData, uncompressed1K, 1024);

            int compressedLength = 1024;

            byte[] compressedData = new byte[compressedLength];

            // Double-check, make sure native code round-trips
            byte[] nativeCompressed = NativeCompress(uncompressed1K, 0, 1024, 1024);
            Assert.AreEqual(uncompressed1K, NativeDecompress(nativeCompressed, 0, nativeCompressed.Length));

            compressor.BlockSize = 1024;
            CompressionResult r = compressor.Compress(uncompressed1K, 0, 1024, compressedData, 0, ref compressedLength);

            Assert.AreEqual(CompressionResult.Compressed, r);
            Assert.AreEqual(uncompressed1K, NativeDecompress(compressedData, 0, compressedLength));
        }
コード例 #12
0
        private void Compress()
        {
            if (Interlocked.CompareExchange(ref _compressState, 3, 1) != 1)
            {
                return;
            }
            _lock.EnterReadLock();
            if (_mode == Empty)
            {
                return;
            }
            if (_array == null)
            {
                return;
            }
            IntervalTree <T> intervalTree = null;

            try
            {
                if (Width == Height)
                {
                    var compressor = new BlockCompressor(Width);
                    intervalTree = compressor.Compress(_array);
                }
                else
                {
                    var compressor = new ColumnCompressor(Width, Height);
                    intervalTree = compressor.Compress(_array);
                }
            }
            catch (Exception e)
            {
                Debug.LogError(e);
            }
            finally
            {
                _lock.ExitReadLock();
            }

            try
            {
                if (intervalTree != null && _lock.TryEnterWriteLock(150))
                {
                    _intervalTree = intervalTree;
                    _mode         = Interval;
                    var temp = _array;
                    _array = null;
                    for (var i = 0; i < temp.Length; i++)
                    {
                        temp[i] = default(T);
                    }

                    PoolManager.GetArrayPool <T[]>(_size).Push(temp);
                }
            }
            catch (Exception e)
            {
                Debug.LogError(e);
            }
            finally
            {
                _lock.ExitWriteLock();
                Interlocked.Exchange(ref _lastTouched, DateTime.Now.Ticks);
                Interlocked.Exchange(ref _compressState, 0);
            }
        }