예제 #1
0
		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);
					});
				}
			}
		}
예제 #2
0
		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);
					});
				}
			}
		}
예제 #3
0
		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));	
				}
			}
		}
예제 #4
0
파일: BlockStorage.cs 프로젝트: K-Eo/FooDB
		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;
		}
예제 #5
0
파일: BlockStorage.cs 프로젝트: K-Eo/FooDB
		//
		// 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;
		}
예제 #6
0
파일: BlockStorage.cs 프로젝트: K-Eo/FooDB
		//
		// 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;
		}