예제 #1
0
파일: CowDatabase.cs 프로젝트: K-Eo/FooDB
		/// <summary>
		/// </summary>
		/// <param name="pathToCowDb">Path to cow db.</param>
		public CowDatabase (string pathToCowDb)	
		{
			if (pathToCowDb == null)
				throw new ArgumentNullException ("pathToCowDb");

			// As soon as CowDatabase is constructed, open the steam to talk to the underlying files
			this.mainDatabaseFile = new FileStream (pathToCowDb, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None, 4096);
			this.primaryIndexFile = new FileStream (pathToCowDb + ".pidx", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None, 4096);
			this.secondaryIndexFile = new FileStream (pathToCowDb + ".sidx", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None, 4096);

			// Construct the RecordStorage that use to store main cow data
			this.cowRecords = new RecordStorage (new BlockStorage(this.mainDatabaseFile, 4096, 48));

			// Construct the primary and secondary indexes 
			this.primaryIndex = new Tree<Guid, uint> (
				new TreeDiskNodeManager<Guid, uint>(
					new GuidSerializer(),
					new TreeUIntSerializer(),
					new RecordStorage(new BlockStorage(this.primaryIndexFile, 4096))
				),
				false
			);

			this.secondaryIndex = new Tree<Tuple<string, int>, uint> (
				new TreeDiskNodeManager<Tuple<string, int>, uint>(
					new StringIntSerializer(), 
					new TreeUIntSerializer(), 
					new RecordStorage(new BlockStorage(this.secondaryIndexFile, 4096))
				),
				true
			);
		}
예제 #2
0
		public void TestUpdateBlockToMuchBiggerSize ()
		{
			var recordStorage = new RecordStorage (new BlockStorage(new MemoryStream(), 8192, 48));
			var x1 = UnitTestHelper.RandomData(2491);
			var x2 = UnitTestHelper.RandomData(9182);
			var x3 = UnitTestHelper.RandomData(5182);

			recordStorage.Create (x1); // Use 1 block
			recordStorage.Create (x2); // Use 2 blocks
			recordStorage.Create (x3); // Use 1 block

			var x2u = UnitTestHelper.RandomData (8192 * 11 + 19); // Use 12 blocks
			recordStorage.Update (2, x2u);

			Assert.IsTrue (recordStorage.Find (1).SequenceEqual (x1));
			Assert.IsTrue (recordStorage.Find (2).SequenceEqual (x2u));
			Assert.IsTrue (recordStorage.Find (4).SequenceEqual (x3));
		}
예제 #3
0
		public void TestUpdateBlockToSmallerSize ()
		{
			var recordStorage = new RecordStorage (new BlockStorage(new MemoryStream(), 8192, 48));
			var x1 = UnitTestHelper.RandomData(2491);
			var x2 = UnitTestHelper.RandomData(9182);
			var x3 = UnitTestHelper.RandomData(5182);

			recordStorage.Create (x1); // Use 1 block
			recordStorage.Create (x2); // Use 2 blocks
			recordStorage.Create (x3); // Use 1 block

			var x2u = UnitTestHelper.RandomData (1177); // Use 1 block, so this record should be truncated
			recordStorage.Update (2, x2u);

			Assert.IsTrue (recordStorage.Find (1).SequenceEqual (x1));
			Assert.IsTrue (recordStorage.Find (2).SequenceEqual (x2u));
			Assert.IsTrue (recordStorage.Find (4).SequenceEqual (x3));

			Assert.IsTrue (recordStorage.Create(UnitTestHelper.RandomData(10)) == 3); // Check if block #3 being reused
		}
예제 #4
0
		public void TestCreateNewPersist ()
		{
			var customData = new byte[4096*16 + 27];
			var rnd = new Random ();
			for (var i = 0; i < customData.Length; i++) {
				customData[i] = (byte)rnd.Next(0,256);
			}

			using (var ms = new MemoryStream())
			{
				var recordStorage = new RecordStorage(new BlockStorage(ms));
				var recordId = recordStorage.Create (customData);

				// First record, shoud has id of 1..
				Assert.AreEqual (1, recordId);

				// Test read back the data
				Assert.True (customData.SequenceEqual(recordStorage.Find(1)));

				// Now test persistant
				var recordStorage2 = new RecordStorage(new BlockStorage(ms));
				Assert.True (customData.SequenceEqual(recordStorage2.Find(1)));
			}
		}
예제 #5
0
		public void TestDeletion()
		{
			var d1 = GenerateRandomData (1029);	
			var d2 = GenerateRandomData (14 * 1024 * 4);	
			var d3 = GenerateRandomData (3591);	

			var d4 = GenerateRandomData (4444);	
			var d5 = GenerateRandomData (5555);	
			var d6 = GenerateRandomData (6666);	

			using (var ms = new MemoryStream())
			{
				var recordStorage = new RecordStorage(new BlockStorage(ms));
				var r1 = recordStorage.Create (d1);
				var r2 = recordStorage.Create (d2);
				var r3 = recordStorage.Create (d3);

				Assert.AreEqual (1, r1);
				Assert.AreEqual (2, r2);
				Assert.AreEqual (4, r3);

				Assert.True (recordStorage.Find(r1).SequenceEqual(d1));
				Assert.True (recordStorage.Find(r2).SequenceEqual(d2));
				Assert.True (recordStorage.Find(r3).SequenceEqual(d3));

				// Delete off 2, free 2 records
				recordStorage.Delete (r2);

				Assert.True (recordStorage.Find(r2)  == null);

				// INsert 2 new records, should take id of 2,3,4
				var r4 = recordStorage.Create (d4);
				var r5 = recordStorage.Create (d5);
				var r6 = recordStorage.Create (d6);
				Assert.AreEqual (3, r4);
				Assert.AreEqual (2, r5);
				Assert.AreEqual (5, r6);

				// Check that data is not being corrupted if we use the reusable block
				Assert.True (recordStorage.Find(r4).SequenceEqual(d4));
				Assert.True (recordStorage.Find(r5).SequenceEqual(d5));
				Assert.True (recordStorage.Find(r6).SequenceEqual(d6));

				// Test persistance
				var recordStorage2 = new RecordStorage(new BlockStorage(ms));
				Assert.True (recordStorage2.Find(r1).SequenceEqual(d1));
				Assert.True (recordStorage2.Find(r3).SequenceEqual(d3));
				Assert.True (recordStorage2.Find(r4).SequenceEqual(d4));
				Assert.True (recordStorage2.Find(r5).SequenceEqual(d5));
				Assert.True (recordStorage2.Find(r6).SequenceEqual(d6));
			}
		}
예제 #6
0
		public void TestTrackingOfLargeFreeBlockList ()
		{
			var tmp = Path.Combine (System.IO.Path.GetTempPath(), "data.bin");

			try {
				using (var ms = new FileStream(tmp, FileMode.Create))
				{
					var recordStorage = new RecordStorage(new BlockStorage(ms));

					// Create 10,000 records
					var ids = new Dictionary<uint, bool>();
					for (var i = 0; i < 15342; i++) {
						ids.Add (recordStorage.Create (new byte[]{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }), true);
					}

					// Now delete them all
					foreach (var kv in ids)
					{
						recordStorage.Delete (kv.Key);
					}

					// Create records and make sure they reuse these ids,
					// And make use it reuses the second block (15343) of free block tracking record as well
					var reusedSecondFreeBlockTracker = false;
					for (var i = 15342; i >= 0; i--)
					{
						var id = recordStorage.Create (new byte[]{ 0x00, 0x01, 0x02, 0x03});
						if (id == 15343) {
							reusedSecondFreeBlockTracker = true;
						} else {
							Assert.IsTrue (ids.ContainsKey(id));
						}
					}

					Assert.True (reusedSecondFreeBlockTracker);

					// Make sure it still continue increment the id..
					Assert.AreEqual (15344, recordStorage.Create (new byte[]{ 0x00, 0x01, 0x02, 0x03}));
				}
			} finally {
				if (File.Exists(tmp))
				{
					File.Delete (tmp);
					Console.WriteLine ("Deleted: " + tmp);
				}
			}
		}