public void TestBlockReadBody () { using (var ms = new MemoryStream()) { // Generate a stream var storage = new BlockStorage (new MemoryStream()); var blockStart = storage.BlockSize * 3; ms.Write (new byte[blockStart], 0, blockStart); ms.Write (LittleEndianByteOrder.GetBytes(11L), 0, 8); ms.Write (LittleEndianByteOrder.GetBytes(22L), 0, 8); ms.Write (LittleEndianByteOrder.GetBytes(33L), 0, 8); ms.Write (LittleEndianByteOrder.GetBytes(44L), 0, 8); // Move to start of body ms.Position = storage.BlockSize * 3 + storage.BlockHeaderSize; // Write ~6KB bytes of random shits into body var bodyLength = (6*1024)+71; var body = new byte[bodyLength]; var rnd = new Random (); for (var i = 0; i < body.Length; i++) { body[i] = (byte)rnd.Next (0, 256); } ms.Write (body); // Block to test // Read first sector first to construct block to test var firstSector = new byte[storage.DiskSectorSize]; ms.Position = storage.BlockSize * 3; ms.Read (firstSector); using (var block = new Block (storage, 3, firstSector, ms)) { // Test read the whole block var result = new byte[bodyLength]; block.Read (result, 0, 0, bodyLength); Assert.IsTrue (result.SequenceEqual(body)); // Test read part of block result =new byte[1024]; block.Read (result , 64 , storage.DiskSectorSize-storage.BlockHeaderSize , 1024-64); var result2 = new byte[1024-64]; Buffer.BlockCopy (result, 64, result2, 0, result2.Length); var expectedResult2 = new byte[1024-64]; Buffer.BlockCopy (body , storage.DiskSectorSize-storage.BlockHeaderSize , expectedResult2 , 0 , expectedResult2.Length); Assert.IsTrue (expectedResult2.SequenceEqual(result2)); // Test read just from first 4KB block result = new byte[128]; block.Read (result, 64, 16, 128-64); var result3 = new byte[128-64]; Buffer.BlockCopy (result, 64, result3, 0, result3.Length); var expectedResult3 = new byte[128-64]; Buffer.BlockCopy (body, 16, expectedResult3, 0, expectedResult3.Length); Assert.IsTrue (expectedResult3.SequenceEqual(result3)); // Test validation Assert.Throws<ArgumentOutOfRangeException>(delegate { block.Read (result, 0, 0, bodyLength + 1); }); Assert.Throws<ArgumentOutOfRangeException>(delegate { block.Read (new byte[12*1024], 0, 0, storage.BlockContentSize); }); } } }
public void TestBlockWriteBody () { using (var ms = new MemoryStream()) { // Construct block for testing var storage = new BlockStorage (new MemoryStream()); var firstSector = new byte[storage.DiskSectorSize]; ms.Position = storage.BlockSize * 3; ms.Read (firstSector); using (var block = new Block (storage, 3, firstSector, ms)) { // Test write some shit var data = new byte[]{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; block.Write (data, 2, 3, 4); var readBackResult = new byte[12]; block.Read (readBackResult, 0, 0, readBackResult.Length); Assert.IsTrue (readBackResult.SequenceEqual(new byte[] { 0x00, 0x00, 0x00, 0x03, 0x04, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, })); } var expectedReadBackResult = new byte[4095]; // Construct a new block and test a gain, to make sure data is persisted using (var block = new Block (storage, 3, firstSector, ms)) { var readBackResult = new byte[12]; block.Read (readBackResult, 0, 0, readBackResult.Length); Assert.IsTrue (readBackResult.SequenceEqual(new byte[] { 0x00, 0x00, 0x00, 0x03, 0x04, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, })); // Now write a chunk of data that outside of first 4KB block var data = new byte[4096*2]; var rnd = new Random (); for (var i = 0; i < data.Length; i++) { data[i] = (byte)rnd.Next (0, 256); } block.Write (data, 16, 4096+32, 4095); // Read back the data readBackResult = new byte[4095]; block.Read (readBackResult, 0, 4096+32, 4095); Buffer.BlockCopy (data, 16, expectedReadBackResult, 0, expectedReadBackResult.Length); Assert.IsTrue (expectedReadBackResult.SequenceEqual(readBackResult)); } // Test persist using (var block = new Block (storage, 3, firstSector, ms)) { var readBackResult = new byte[4095]; block.Read (readBackResult, 0, 4096+32, 4095); Assert.IsTrue (expectedReadBackResult.SequenceEqual(readBackResult)); // Test Write outide of the block Assert.Throws<ArgumentOutOfRangeException>(delegate { block.Write (new byte[32], 0, storage.BlockContentSize-31, 32); }); Assert.DoesNotThrow(delegate { block.Write (new byte[32], 0, storage.BlockContentSize-32, 32); }); } } }
public void TestBlockGetSetHeader () { using (var ms = new MemoryStream()) { var storage = new BlockStorage (new MemoryStream()); var blockStart = storage.BlockSize * 22; ms.Write (new byte[blockStart], 0, blockStart); ms.Write (LittleEndianByteOrder.GetBytes(11L), 0, 8); ms.Write (LittleEndianByteOrder.GetBytes(22L), 0, 8); ms.Write (LittleEndianByteOrder.GetBytes(33L), 0, 8); ms.Write (LittleEndianByteOrder.GetBytes(44L), 0, 8); var firstSector = new byte[storage.DiskSectorSize]; ms.Position = ms.Position - 4*8; ms.Read (firstSector); using (var block = new Block (storage, 22, firstSector, ms)) { block.GetHeader (0); Assert.AreEqual (11L, block.GetHeader (0)); Assert.AreEqual (22L, block.GetHeader (1)); Assert.AreEqual (33L, block.GetHeader (2)); Assert.AreEqual (44L, block.GetHeader (3)); // Change header block.SetHeader (1, 33L); // Changed in memory Assert.AreEqual (33L, block.GetHeader(1)); // Should not be changed in actual stream var buffer = new byte[8]; ms.Position = blockStart + 8; ms.Read (buffer, 0, 8); Assert.AreEqual (22L, LittleEndianByteOrder.GetInt64(buffer)); } // Until we flush { var buffer = new byte[8]; ms.Position = blockStart + 8; ms.Read (buffer, 0, 8); Assert.AreEqual (33L, LittleEndianByteOrder.GetInt64(buffer)); } } }
public IBlock CreateNew () { if ((this.stream.Length % blockSize) != 0) { throw new DataMisalignedException ("Unexpected length of the stream: " + this.stream.Length); } // Calculate new block id var blockId = (uint)Math.Ceiling ((double)this.stream.Length / (double)blockSize); // Extend length of underlying stream this.stream.SetLength ((long)((blockId * blockSize) + blockSize)); this.stream.Flush (); // Return desired block var block = new Block (this, blockId, new byte[DiskSectorSize], this.stream); OnBlockInitialized (block); return block; }
// // Public Methods // public IBlock Find (uint blockId) { // Check from initialized blocks if (true == blocks.ContainsKey(blockId)) { return blocks[blockId]; } // First, move to that block. // If there is no such block return NULL var blockPosition = blockId * blockSize; if ((blockPosition + blockSize) > this.stream.Length) { return null; } // Read the first 4KB of the block to construct a block from it var firstSector = new byte[DiskSectorSize]; stream.Position = blockId * blockSize; stream.Read (firstSector, 0, DiskSectorSize); var block = new Block (this, blockId, firstSector, this.stream); OnBlockInitialized (block); return block; }
// // Protected Methods // protected virtual void OnBlockInitialized (Block block) { // Keep reference to it blocks[block.Id] = block; // When block disposed, remove it from memory block.Disposed += HandleBlockDisposed; }