1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2009, 2013 Oracle and/or its affiliates.  All rights reserved.
5  *
6  */
7 using System;
8 using System.Collections;
9 using System.Collections.Generic;
10 using System.IO;
11 using System.Text;
12 using System.Xml;
13 using NUnit.Framework;
14 using BerkeleyDB;
15 
16 namespace CsharpAPITest
17 {
18 	[TestFixture]
19 	public class BTreeDatabaseTest : DatabaseTest
20 	{
21 
22 		[TestFixtureSetUp]
SetUpTestFixture()23 		public void SetUpTestFixture()
24 		{
25 			testFixtureName = "BTreeDatabaseTest";
26 			base.SetUpTestfixture();
27 		}
28 
29 		[Test]
TestCompactWithoutTxn()30 		public void TestCompactWithoutTxn()
31 		{
32 			int i, nRecs;
33 			nRecs = 1000;
34 			testName = "TestCompactWithoutTxn";
35 			SetUpTest(true);
36 			string btreeDBFileName = testHome + "/" +
37 			    testName + ".db";
38 
39 			BTreeDatabaseConfig btreeDBConfig =
40 			    new BTreeDatabaseConfig();
41 			btreeDBConfig.Creation = CreatePolicy.ALWAYS;
42 			// The minimum page size
43 			btreeDBConfig.PageSize = 512;
44 			btreeDBConfig.BTreeCompare =
45 			    new EntryComparisonDelegate(dbIntCompare);
46 			using (BTreeDatabase btreeDB = BTreeDatabase.Open(
47 			    btreeDBFileName, btreeDBConfig))
48 			{
49 				DatabaseEntry key;
50 				DatabaseEntry data;
51 
52 				// Fill the database with entries from 0 to 999
53 				for (i = 0; i < nRecs; i++)
54 				{
55 					key = new DatabaseEntry(
56 					    BitConverter.GetBytes(i));
57 					data = new DatabaseEntry(
58 ASCIIEncoding.ASCII.GetBytes(Configuration.RandomString(100)));
59 					btreeDB.Put(key, data);
60 				}
61 
62 				/*
63 				 * Delete entries below 50, between 300 and
64 				 * 500 and above 700
65 				 */
66 				for (i = 0; i < nRecs; i++)
67 					if (i < (int)(nRecs * 0.05) ||
68 					    i > (int)(nRecs * 0.7) ||
69 					    (i < (int)(nRecs * 0.5) &&
70 					    i > (int)(nRecs * 0.3)))
71 					{
72 						key = new DatabaseEntry(
73 						    BitConverter.GetBytes(i));
74 						btreeDB.Delete(key);
75 					}
76 
77 				btreeDB.Sync();
78 				long fileSize = new FileInfo(
79 				   btreeDBFileName).Length;
80 
81 				// Compact database
82 				CompactConfig cCfg = new CompactConfig();
83 				cCfg.FillPercentage = 80;
84 				cCfg.Pages = 4;
85 				cCfg.Timeout = 1000;
86 				cCfg.TruncatePages = true;
87 				cCfg.start = new DatabaseEntry(
88 				    BitConverter.GetBytes(1));
89 				cCfg.stop = new DatabaseEntry(
90 				    BitConverter.GetBytes(7000));
91 				CompactData compactData = btreeDB.Compact(cCfg);
92 				// Verify output statistics fields.
93 				Assert.AreEqual(0, compactData.Deadlocks);
94 				Assert.LessOrEqual(0, compactData.EmptyBuckets);
95 				Assert.LessOrEqual(0, compactData.Levels);
96 				Assert.Less(0, compactData.PagesExamined);
97 				Assert.Less(0, compactData.PagesFreed);
98 				Assert.Less(compactData.PagesFreed,
99 				    compactData.PagesTruncated);
100 
101 				btreeDB.Sync();
102 				long compactedFileSize =
103 				    new FileInfo(btreeDBFileName).Length;
104 				Assert.Less(compactedFileSize, fileSize);
105 			}
106 		}
107 
108                 [Test]
TestCompression()109                 public void TestCompression() {
110                         testName = "TestCompression";
111                         SetUpTest(true);
112                         string btreeDBName = testHome + "/" + testName + ".db";
113 
114                         BTreeDatabaseConfig cfg = new BTreeDatabaseConfig();
115                         cfg.Creation = CreatePolicy.ALWAYS;
116                         cfg.SetCompression(compress, decompress);
117                         BTreeDatabase db = BTreeDatabase.Open(btreeDBName, cfg);
118                         DatabaseEntry key, data;
119                         char[] keyData = { 'A', 'A', 'A', 'A' };
120                         data = new DatabaseEntry(
121                                 ASCIIEncoding.ASCII.GetBytes("abcdefghij"));
122                         int i;
123                         for (i = 0; i < 2000; i++) {
124                                 // Write random data
125                                 key = new DatabaseEntry(
126                                         ASCIIEncoding.ASCII.GetBytes(keyData));
127                                 db.Put(key, data);
128 
129                                 // Bump the key. Rollover from Z to A if necessary
130                                 int j = keyData.Length;
131                                 do {
132                                         j--;
133                                         if (keyData[j]++ == 'Z')
134                                                 keyData[j] = 'A';
135                                 } while (keyData[j] == 'A');
136                        }
137                         db.Close();
138                 }
139 
compress(DatabaseEntry prevKey, DatabaseEntry prevData, DatabaseEntry key, DatabaseEntry data, ref byte[] dest, out int size)140                 bool compress(DatabaseEntry prevKey, DatabaseEntry prevData,
141                     DatabaseEntry key, DatabaseEntry data, ref byte[] dest, out int size) {
142                         /*
143                          * Just a dummy function that doesn't do any compression.  It just
144                          * writes the 5 byte key and 10 byte data to the buffer.
145                          */
146                         size = key.Data.Length + data.Data.Length;
147                         if (size > dest.Length)
148                                 return false;
149                         key.Data.CopyTo(dest, 0);
150                         data.Data.CopyTo(dest, key.Data.Length);
151                         return true;
152                 }
153 
decompress( DatabaseEntry prevKey, DatabaseEntry prevData, byte[] compressed, out uint bytesRead)154                 KeyValuePair<DatabaseEntry, DatabaseEntry> decompress(
155                     DatabaseEntry prevKey, DatabaseEntry prevData, byte[] compressed, out uint bytesRead) {
156                         byte[] keyData = new byte[4];
157                         byte[] dataData = new byte[10];
158                         Array.ConstrainedCopy(compressed, 0, keyData, 0, 4);
159                         Array.ConstrainedCopy(compressed, 4, dataData, 0, 10);
160                         DatabaseEntry key = new DatabaseEntry(keyData);
161                         DatabaseEntry data = new DatabaseEntry(dataData);
162                         bytesRead = (uint)(key.Data.Length + data.Data.Length);
163                         return new KeyValuePair<DatabaseEntry, DatabaseEntry>(key, data);
164                 }
165 
166                 /*
167                  * Test the default compression - which is prefix compression
168                  * of keys. This should work well with ordered keys and short
169                  * data items.
170                  */
171                 [Test]
TestCompressionDefault()172                 public void TestCompressionDefault() {
173                         testName = "TestCompressionDefault";
174                         SetUpTest(true);
175                         string btreeDBName = testHome + "/" + testName + ".db";
176 
177                         BTreeDatabaseConfig cfg = new BTreeDatabaseConfig();
178                         cfg.Creation = CreatePolicy.ALWAYS;
179                         BTreeDatabase db = BTreeDatabase.Open(btreeDBName, cfg);
180                         DatabaseEntry key, data;
181                         char[] keyData = { 'A', 'A', 'A', 'A' };
182                         data = new DatabaseEntry(
183                                 ASCIIEncoding.ASCII.GetBytes("A"));
184                         int i;
185                         for (i = 0; i < 5000; i++) {
186                                 // Write random data
187                                 key = new DatabaseEntry(
188                                         ASCIIEncoding.ASCII.GetBytes(keyData));
189                                 db.Put(key, data);
190 
191                                 // Bump the key.
192                                 int j = keyData.Length;
193                                 do {
194                                         j--;
195                                         if (keyData[j]++ == 'Z')
196                                                 keyData[j] = 'A';
197                                 } while (keyData[j] == 'A');
198                         }
199                         db.Close();
200 
201                         FileInfo dbInfo = new FileInfo(btreeDBName);
202                         long uncompressedSize = dbInfo.Length;
203                         Configuration.ClearDir(testHome);
204 
205                         cfg = new BTreeDatabaseConfig();
206                         cfg.Creation = CreatePolicy.ALWAYS;
207                         cfg.SetCompression();
208                         db = BTreeDatabase.Open(btreeDBName, cfg);
209                         keyData = new char[]{ 'A', 'A', 'A', 'A' };
210                         data = new DatabaseEntry(
211                                 ASCIIEncoding.ASCII.GetBytes("A"));
212                         for (i = 0; i < 5000; i++) {
213                                 // Write random data
214                                 key = new DatabaseEntry(
215                                         ASCIIEncoding.ASCII.GetBytes(keyData));
216                                 db.Put(key, data);
217 
218                                 // Bump the key.
219                                 int j = keyData.Length;
220                                 do {
221                                         j--;
222                                         if (keyData[j]++ == 'Z')
223                                                 keyData[j] = 'A';
224                                 } while (keyData[j] == 'A');
225                         }
226                         Cursor dbc = db.Cursor();
227                         foreach (KeyValuePair<DatabaseEntry, DatabaseEntry> kvp
228                                 in dbc)
229                                 i--;
230                         dbc.Close();
231                         Assert.AreEqual(i, 0);
232                         db.Close();
233 
234                         dbInfo = new FileInfo(btreeDBName);
235                         Assert.Less(dbInfo.Length, uncompressedSize);
236                         Console.WriteLine(
237                                 "Uncompressed: {0}", uncompressedSize);
238                         Console.WriteLine("Compressed: {0}", dbInfo.Length);
239 
240                         Configuration.ClearDir(testHome);
241 
242                         cfg = new BTreeDatabaseConfig();
243                         cfg.Creation = CreatePolicy.ALWAYS;
244                         cfg.SetCompression();
245                         db = BTreeDatabase.Open(btreeDBName, cfg);
246                         for (i = 1023; i < 1124; i++){
247                                 key = new DatabaseEntry(BitConverter.GetBytes(i));
248                                 data = new DatabaseEntry(BitConverter.GetBytes(i + 3));
249                                 db.Put(key, data);
250                         }
251                         dbc = db.Cursor();
252                         foreach (KeyValuePair<DatabaseEntry, DatabaseEntry> kvp in dbc){
253                                 int keyInt = BitConverter.ToInt32(kvp.Key.Data, 0);
254                                 int dataInt = BitConverter.ToInt32(kvp.Value.Data, 0);
255                                 Assert.AreEqual(3, dataInt - keyInt);
256                         }
257                         dbc.Close();
258 
259                         db.Close();
260                 }
261 
262 		[Test, ExpectedException(typeof(AccessViolationException))]
TestClose()263 		public void TestClose()
264 		{
265 			testName = "TestClose";
266 			SetUpTest(true);
267 			string btreeDBFileName = testHome + "/" +
268 			    testName + ".db";
269 
270 			BTreeDatabaseConfig btreeDBConfig =
271 			    new BTreeDatabaseConfig();
272 			btreeDBConfig.Creation = CreatePolicy.ALWAYS;
273 			BTreeDatabase btreeDB = BTreeDatabase.Open(
274 			    btreeDBFileName, btreeDBConfig);
275 			btreeDB.Close();
276 			DatabaseEntry key = new DatabaseEntry(
277 			    ASCIIEncoding.ASCII.GetBytes("hi"));
278 			DatabaseEntry data = new DatabaseEntry(
279 			    ASCIIEncoding.ASCII.GetBytes("hi"));
280 			btreeDB.Put(key, data);
281 		}
282 
283 		[Test]
TestCloseWithoutSync()284 		public void TestCloseWithoutSync()
285 		{
286 			testName = "TestCloseWithoutSync";
287 			SetUpTest(true);
288 			string btreeDBName = testName + ".db";
289 
290 			DatabaseEnvironmentConfig envConfig =
291 			    new DatabaseEnvironmentConfig();
292 			envConfig.Create = true;
293 			envConfig.ForceFlush = true;
294 			envConfig.UseTxns = true;
295 			envConfig.UseMPool = true;
296 			envConfig.UseLogging = true;
297 			envConfig.LogSystemCfg = new LogConfig();
298 			envConfig.LogSystemCfg.ForceSync = false;
299 			envConfig.LogSystemCfg.AutoRemove = true;
300 			DatabaseEnvironment env = DatabaseEnvironment.Open(
301 			    testHome, envConfig);
302 
303 			TransactionConfig txnConfig = new TransactionConfig();
304 			txnConfig.SyncAction =
305 			    TransactionConfig.LogFlush.WRITE_NOSYNC;
306 			Transaction txn = env.BeginTransaction(txnConfig);
307 
308 			BTreeDatabaseConfig btreeConfig =
309 			    new BTreeDatabaseConfig();
310 			btreeConfig.Creation = CreatePolicy.ALWAYS;
311 			btreeConfig.Env = env;
312 
313 			BTreeDatabase btreeDB = BTreeDatabase.Open(
314 			    btreeDBName, btreeConfig, txn);
315 
316 			DatabaseEntry key = new DatabaseEntry(
317 			    ASCIIEncoding.ASCII.GetBytes("key"));
318 			DatabaseEntry data = new DatabaseEntry(
319 			    ASCIIEncoding.ASCII.GetBytes("data"));
320 			Assert.IsFalse(btreeDB.Exists(key, txn));
321 			btreeDB.Put(key, data, txn);
322 			btreeDB.Close(false);
323 			txn.Commit();
324 			env.Close();
325 
326 			BTreeDatabaseConfig dbConfig =
327 			    new BTreeDatabaseConfig();
328 			dbConfig.Creation = CreatePolicy.NEVER;
329 			using (BTreeDatabase db = BTreeDatabase.Open(
330 			    testHome + "/" + btreeDBName, dbConfig))
331 			{
332 				Assert.IsFalse(db.Exists(key));
333 			}
334 		}
335 
336 		[Test]
TestCursorWithoutEnv()337 		public void TestCursorWithoutEnv()
338 		{
339 			BTreeCursor cursor;
340 			BTreeDatabase db;
341 			string dbFileName;
342 
343 			testName = "TestCursorWithoutEnv";
344 			SetUpTest(true);
345 			dbFileName = testHome + "/" + testName + ".db";
346 
347 			// Open btree database.
348 			OpenBtreeDB(null, null, dbFileName, out db);
349 
350 			// Get a cursor.
351 			cursor = db.Cursor();
352 
353 			/*
354 			 * Add a record to the database with cursor and
355 			 * confirm that the record exists in the database.
356 			 */
357 			CursorTest.AddOneByCursor(db, cursor);
358 
359 			// Close cursor and database.
360 			cursor.Close();
361 			db.Close();
362 		}
363 
364 		[Test]
TestCursorWithConfigInTxn()365 		public void TestCursorWithConfigInTxn()
366 		{
367 			BTreeCursor cursor;
368 			BTreeDatabase db;
369 			DatabaseEnvironment env;
370 			Transaction txn;
371 			string dbFileName;
372 
373 			testName = "TestCursorWithConfigInTxn";
374 			SetUpTest(true);
375 			dbFileName = testName + ".db";
376 
377 			// Open environment and begin a transaction.
378 
379 			SetUpEnvAndTxn(testHome, out env, out txn);
380 			OpenBtreeDB(env, txn, dbFileName, out db);
381 
382 			// Config and get a cursor.
383 			cursor = db.Cursor(new CursorConfig(), txn);
384 
385 			/*
386 			 * Add a record to the database with cursor and
387 			 * confirm that the record exists in the database.
388 			 */
389 			CursorTest.AddOneByCursor(db, cursor);
390 
391 			/*
392 			 * Close cursor, database, commit the transaction
393 			 * and close the environment.
394 			 */
395 			cursor.Close();
396 			db.Close();
397 			txn.Commit();
398 			env.Close();
399 		}
400 
401 		[Test]
TestCursorWithoutConfigInTxn()402 		public void TestCursorWithoutConfigInTxn()
403 		{
404 			BTreeCursor cursor;
405 			BTreeDatabase db;
406 			DatabaseEnvironment env;
407 			Transaction txn;
408 			string dbFileName;
409 
410 			testName = "TestCursorWithoutConfigInTxn";
411 			SetUpTest(true);
412 			dbFileName = testName + ".db";
413 
414 			// Open environment and begin a transaction.
415 			SetUpEnvAndTxn(testHome, out env, out txn);
416 			OpenBtreeDB(env, txn, dbFileName, out db);
417 
418 			// Get a cursor in the transaction.
419 			cursor = db.Cursor(txn);
420 
421 			/*
422 			 * Add a record to the database with cursor and
423 			 * confirm that the record exists in the database.
424 			 */
425 			CursorTest.AddOneByCursor(db, cursor);
426 
427 			/*
428 			 * Close cursor, database, commit the transaction
429 			 * and close the environment.
430 			 */
431 			cursor.Close();
432 			db.Close();
433 			txn.Commit();
434 			env.Close();
435 		}
436 
437 		[Test, ExpectedException(typeof(ExpectedTestException))]
TestDelete()438 		public void TestDelete()
439 		{
440 			testName = "TestDelete";
441 			SetUpTest(true);
442 			string btreeDBFileName = testHome + "/" +
443 			    testName + ".db";
444 
445 			BTreeDatabaseConfig btreeDBConfig =
446 			    new BTreeDatabaseConfig();
447 			btreeDBConfig.Creation = CreatePolicy.ALWAYS;
448 			BTreeDatabase btreeDB = BTreeDatabase.Open(
449 			    btreeDBFileName, btreeDBConfig);
450 			DatabaseEntry key = new DatabaseEntry(
451 			    ASCIIEncoding.ASCII.GetBytes("key"));
452 			DatabaseEntry data = new DatabaseEntry(
453 			    ASCIIEncoding.ASCII.GetBytes("data"));
454 			btreeDB.Put(key, data);
455 			btreeDB.Delete(key);
456 			try
457 			{
458 				btreeDB.Get(key);
459 			}
460 			catch (NotFoundException)
461 			{
462 				throw new ExpectedTestException();
463 			}
464 			finally
465 			{
466 				btreeDB.Close();
467 			}
468 		}
469 
470 		[Test]
TestDupCompare()471 		public void TestDupCompare()
472 		{
473 			testName = "TestDupCompare";
474 			SetUpTest(true);
475 
476 			BTreeDatabaseConfig cfg = new BTreeDatabaseConfig();
477 			cfg.Creation = CreatePolicy.IF_NEEDED;
478 			cfg.Duplicates = DuplicatesPolicy.UNSORTED;
479 
480 			// Do not set the duplicate comparison delegate.
481 			using (BTreeDatabase db = BTreeDatabase.Open(
482 			    testHome + "/" + testName + ".db", cfg)) {
483 				try {
484 					int ret = db.DupCompare(
485 					    new DatabaseEntry(
486 					    BitConverter.GetBytes(255)),
487 					    new DatabaseEntry(
488 					    BitConverter.GetBytes(257)));
489 					throw new TestException();
490 				} catch(NullReferenceException) {
491 				}
492 			}
493 
494 			/*
495 			 * Set the duplicate comparison delegate, and verify
496 			 * the comparison delegate.
497 			 */
498 			cfg.DuplicateCompare =
499 			    new EntryComparisonDelegate(dbIntCompare);
500 			using (BTreeDatabase db = BTreeDatabase.Open(
501 			    testHome + "/" + testName + "1.db", cfg)) {
502 				int ret = db.DupCompare(
503 				    new DatabaseEntry(BitConverter.GetBytes(255)),
504 				    new DatabaseEntry(BitConverter.GetBytes(257)));
505 				Assert.Greater(0, ret);
506 			}
507 		}
508 
509 		[Test]
TestEncryption()510 		public void TestEncryption() {
511 			testName = "TestEncryption";
512 			SetUpTest(true);
513 
514 			BTreeDatabase db1;
515 
516 			BTreeDatabaseConfig dbCfg =
517 			    new BTreeDatabaseConfig();
518 			dbCfg.Creation = CreatePolicy.IF_NEEDED;
519 
520 			// Open an encrypted database.
521 			dbCfg.SetEncryption("bdb", EncryptionAlgorithm.AES);
522 			using (db1 = BTreeDatabase.Open(
523 			    testHome + "/" + testName + ".db", dbCfg)) {
524 				Assert.IsTrue(db1.Encrypted);
525 				for (int i = 0; i < 10; i++)
526 					db1.Put(new DatabaseEntry
527 					    (BitConverter.GetBytes(i)),
528 					    new DatabaseEntry(
529 					    BitConverter.GetBytes(i)));
530 			}
531 
532 			// Verify the database is encrypted.
533 			BTreeDatabaseConfig verifyDbCfg =
534 			    new BTreeDatabaseConfig();
535 			verifyDbCfg.Creation = CreatePolicy.IF_NEEDED;
536 			verifyDbCfg.SetEncryption(
537 			    dbCfg.EncryptionPassword,
538 			    dbCfg.EncryptAlgorithm);
539 			verifyDbCfg.Encrypted = true;
540 			using (db1 = BTreeDatabase.Open(
541 			    testHome + "/" + testName + ".db",
542 			    verifyDbCfg)) {
543 				for (int i = 0; i < 10; i++)
544 					db1.Get(new DatabaseEntry(
545 					    BitConverter.GetBytes(i)));
546 			};
547 		}
548 
549 		[Test]
TestExist()550 		public void TestExist()
551 		{
552 			testName = "TestExist";
553 			SetUpTest(true);
554 			string dbFileName = testHome + "/" + testName + ".db";
555 
556 			BTreeDatabaseConfig btreeDBConfig =
557 			    new BTreeDatabaseConfig();
558 			btreeDBConfig.Creation = CreatePolicy.IF_NEEDED;
559 			BTreeDatabase btreeDB;
560 			using (btreeDB = BTreeDatabase.Open(
561 			    dbFileName, btreeDBConfig))
562 			{
563 				DatabaseEntry key = new DatabaseEntry(
564 				     ASCIIEncoding.ASCII.GetBytes("key"));
565 				DatabaseEntry data = new DatabaseEntry(
566 				     ASCIIEncoding.ASCII.GetBytes("data"));
567 
568 				btreeDB.Put(key, data);
569 				Assert.IsTrue(btreeDB.Exists(
570 				     new DatabaseEntry(
571 				     ASCIIEncoding.ASCII.GetBytes("key"))));
572 				Assert.IsFalse(btreeDB.Exists(
573 				     new DatabaseEntry(
574 				     ASCIIEncoding.ASCII.GetBytes("data"))));
575 			}
576 		}
577 
578 		[Test]
TestExistWithTxn()579 		public void TestExistWithTxn()
580 		{
581 			BTreeDatabase btreeDB;
582 			Transaction txn;
583 			DatabaseEnvironmentConfig envConfig;
584 			DatabaseEnvironment env;
585 			DatabaseEntry key, data;
586 
587 			testName = "TestExistWithTxn";
588 			SetUpTest(true);
589 
590 			// Open an environment.
591 			envConfig = new DatabaseEnvironmentConfig();
592 			envConfig.Create = true;
593 			envConfig.UseMPool = true;
594 			envConfig.UseTxns = true;
595 			env = DatabaseEnvironment.Open(testHome, envConfig);
596 
597 			// Begin a transaction.
598 			txn = env.BeginTransaction();
599 
600 			// Open a database.
601 			BTreeDatabaseConfig btreeDBConfig =
602 			    new BTreeDatabaseConfig();
603 			btreeDBConfig.Creation = CreatePolicy.IF_NEEDED;
604 			btreeDBConfig.Env = env;
605 			btreeDB = BTreeDatabase.Open(testName + ".db",
606 			    btreeDBConfig, txn);
607 
608 			// Put key data pair into database.
609 			key = new DatabaseEntry(
610 				     ASCIIEncoding.ASCII.GetBytes("key"));
611 			data = new DatabaseEntry(
612 			     ASCIIEncoding.ASCII.GetBytes("data"));
613 			btreeDB.Put(key, data, txn);
614 
615 			// Confirm that the pair exists in the database.
616 			Assert.IsTrue(btreeDB.Exists(new DatabaseEntry(
617 			    ASCIIEncoding.ASCII.GetBytes("key")), txn));
618 			Assert.IsFalse(btreeDB.Exists(new DatabaseEntry(
619 			     ASCIIEncoding.ASCII.GetBytes("data")), txn));
620 
621 			// Dispose all.
622 			btreeDB.Close();
623 			txn.Commit();
624 			env.Close();
625 		}
626 
627 		[Test]
TestExistWithLockingInfo()628 		public void TestExistWithLockingInfo()
629 		{
630 			BTreeDatabase btreeDB;
631 			DatabaseEnvironment env;
632 			DatabaseEntry key, data;
633 
634 			testName = "TestExistWithLockingInfo";
635 			SetUpTest(true);
636 
637 			// Open the environment.
638 			DatabaseEnvironmentConfig envCfg =
639 			    new DatabaseEnvironmentConfig();
640 			envCfg.Create = true;
641 			envCfg.FreeThreaded = true;
642 			envCfg.UseLocking = true;
643 			envCfg.UseLogging = true;
644 			envCfg.UseMPool = true;
645 			envCfg.UseTxns = true;
646 			env = DatabaseEnvironment.Open(
647 			    testHome, envCfg);
648 
649 			// Open database in transaction.
650 			Transaction openTxn = env.BeginTransaction();
651 			BTreeDatabaseConfig cfg =
652 			    new BTreeDatabaseConfig();
653 			cfg.Creation = CreatePolicy.ALWAYS;
654 			cfg.Env = env;
655 			cfg.FreeThreaded = true;
656 			cfg.PageSize = 4096;
657 			cfg.Duplicates = DuplicatesPolicy.UNSORTED;
658 			btreeDB = BTreeDatabase.Open(testName + ".db",
659 			    cfg, openTxn);
660 			openTxn.Commit();
661 
662 			// Put key data pair into database.
663 			Transaction txn = env.BeginTransaction();
664 			key = new DatabaseEntry(
665 				     ASCIIEncoding.ASCII.GetBytes("key"));
666 			data = new DatabaseEntry(
667 			     ASCIIEncoding.ASCII.GetBytes("data"));
668 			btreeDB.Put(key, data, txn);
669 
670 			// Confirm that the pair exists in the database with LockingInfo.
671 			LockingInfo lockingInfo = new LockingInfo();
672 			lockingInfo.ReadModifyWrite = true;
673 
674 			// Confirm that the pair exists in the database.
675 			Assert.IsTrue(btreeDB.Exists(new DatabaseEntry(
676 			    ASCIIEncoding.ASCII.GetBytes("key")), txn, lockingInfo));
677 			Assert.IsFalse(btreeDB.Exists(new DatabaseEntry(
678 			     ASCIIEncoding.ASCII.GetBytes("data")), txn, lockingInfo));
679 			txn.Commit();
680 
681 			btreeDB.Close();
682 			env.Close();
683 		}
684 
685 		[Test]
TestGetByKey()686 		public void TestGetByKey()
687 		{
688 			testName = "TestGetByKey";
689 			SetUpTest(true);
690 			string btreeDBFileName = testHome + "/" +
691 				     testName + ".db";
692 			string btreeDBName =
693 			    Path.GetFileNameWithoutExtension(btreeDBFileName);
694 
695 			BTreeDatabaseConfig btreeDBConfig =
696 			    new BTreeDatabaseConfig();
697 			btreeDBConfig.Creation = CreatePolicy.ALWAYS;
698 			BTreeDatabase btreeDB = BTreeDatabase.Open(
699 			    btreeDBFileName, btreeDBName, btreeDBConfig);
700 
701 			DatabaseEntry key = new DatabaseEntry(
702 			    ASCIIEncoding.ASCII.GetBytes("key"));
703 			DatabaseEntry data = new DatabaseEntry(
704 			    ASCIIEncoding.ASCII.GetBytes("data"));
705 			btreeDB.Put(key, data);
706 
707 			KeyValuePair<DatabaseEntry, DatabaseEntry> pair =
708 			    new KeyValuePair<DatabaseEntry, DatabaseEntry>();
709 			pair = btreeDB.Get(key);
710 			Assert.AreEqual(pair.Key.Data, key.Data);
711 			Assert.AreEqual(pair.Value.Data, data.Data);
712 			btreeDB.Close();
713 		}
714 
715 		[Test]
TestGetByRecno()716 		public void TestGetByRecno()
717 		{
718 			testName = "TestGetByRecno";
719 			SetUpTest(true);
720 			string btreeDBFileName = testHome + "/" +
721 			    testName + ".db";
722 			string btreeDBName =
723 			    Path.GetFileNameWithoutExtension(btreeDBFileName);
724 
725 			BTreeDatabaseConfig btreeDBConfig =
726 			    new BTreeDatabaseConfig();
727 			btreeDBConfig.Creation = CreatePolicy.ALWAYS;
728 			btreeDBConfig.UseRecordNumbers = true;
729 			BTreeDatabase btreeDB = BTreeDatabase.Open(
730 			    btreeDBFileName, btreeDBName, btreeDBConfig);
731 			Assert.IsTrue(btreeDB.RecordNumbers);
732 
733 			DatabaseEntry key = new DatabaseEntry();
734 			DatabaseEntry data = new DatabaseEntry();
735 			uint recno, count, value;
736 			for (recno = 1; recno <= 100; recno++)
737 			{
738 				value = 200 - recno;
739 				Configuration.dbtFromString(key,
740 				    Convert.ToString(value));
741 				Configuration.dbtFromString(data,
742 				    Convert.ToString(value));
743 				btreeDB.Put(key, data);
744 			}
745 
746 			KeyValuePair<DatabaseEntry, DatabaseEntry> pair =
747 			    new KeyValuePair<DatabaseEntry, DatabaseEntry>();
748 
749 			for (count = 1; ; count++)
750 			{
751 				try
752 				{
753 					pair = btreeDB.Get(count);
754 				}
755 				catch (NotFoundException)
756 				{
757 					Assert.AreEqual(101, count);
758 					break;
759 				}
760 				value = 299 - 200 + count;
761 				Assert.AreEqual(value.ToString(),
762 				    Configuration.strFromDBT(pair.Key));
763 			}
764 
765 			btreeDB.Close();
766 		}
767 
768 		[Test, ExpectedException(typeof(NotFoundException))]
TestGetBoth()769 		public void TestGetBoth()
770 		{
771 			testName = "TestGetBoth";
772 			SetUpTest(true);
773 			string btreeDBFileName = testHome + "/" +
774 			    testName + ".db";
775 			string btreeDBName =
776 			    Path.GetFileNameWithoutExtension(btreeDBFileName);
777 
778 			BTreeDatabaseConfig btreeDBConfig =
779 			    new BTreeDatabaseConfig();
780 			btreeDBConfig.Creation = CreatePolicy.ALWAYS;
781 			using (BTreeDatabase btreeDB = BTreeDatabase.Open(
782 			    btreeDBFileName, btreeDBName, btreeDBConfig))
783 			{
784 				DatabaseEntry key = new DatabaseEntry();
785 				DatabaseEntry data = new DatabaseEntry();
786 
787 				Configuration.dbtFromString(key, "key");
788 				Configuration.dbtFromString(data, "data");
789 				btreeDB.Put(key, data);
790 				KeyValuePair<DatabaseEntry, DatabaseEntry> pair =
791 				    new KeyValuePair<DatabaseEntry, DatabaseEntry>();
792 				pair = btreeDB.GetBoth(key, data);
793 				Assert.AreEqual(key.Data, pair.Key.Data);
794 				Assert.AreEqual(data.Data, pair.Value.Data);
795 
796 				Configuration.dbtFromString(key, "key");
797 				Configuration.dbtFromString(data, "key");
798 				btreeDB.GetBoth(key, data);
799 			}
800 		}
801 
802 		[Test]
TestGetBothMultiple()803 		public void TestGetBothMultiple()
804 		{
805 			testName = "TestGetBothMultiple";
806 			SetUpTest(true);
807 			string btreeDBFileName = testHome + "/" +
808 			    testName + ".db";
809 			string btreeDBName = testName;
810 			DatabaseEntry key, data;
811 			KeyValuePair<DatabaseEntry, MultipleDatabaseEntry> kvp;
812 			int cnt;
813 
814 			BTreeDatabaseConfig btreeDBConfig =
815 			    new BTreeDatabaseConfig();
816 			btreeDBConfig.Creation = CreatePolicy.ALWAYS;
817 			btreeDBConfig.Duplicates = DuplicatesPolicy.UNSORTED;
818 			btreeDBConfig.PageSize = 1024;
819 			using (BTreeDatabase btreeDB = GetMultipleDB(
820 			    btreeDBFileName, btreeDBName, btreeDBConfig)) {
821 				key = new DatabaseEntry(BitConverter.GetBytes(100));
822 				data = new DatabaseEntry(BitConverter.GetBytes(100));
823 
824 				kvp = btreeDB.GetBothMultiple(key, data);
825 				cnt = 0;
826 				foreach (DatabaseEntry dbt in kvp.Value)
827 					cnt++;
828 				Assert.AreEqual(cnt, 10);
829 
830 				kvp = btreeDB.GetBothMultiple(key, data, 1024);
831 				cnt = 0;
832 				foreach (DatabaseEntry dbt in kvp.Value)
833 					cnt++;
834 				Assert.AreEqual(cnt, 10);
835 			}
836 		}
837 
838 		[Test]
TestGetMultiple()839 		public void TestGetMultiple()
840 		{
841 			testName = "TestGetMultiple";
842 			SetUpTest(true);
843 			string btreeDBFileName = testHome + "/" +
844 			    testName + ".db";
845 			string btreeDBName = testName;
846 
847 			BTreeDatabaseConfig btreeDBConfig =
848 			    new BTreeDatabaseConfig();
849 			btreeDBConfig.Creation = CreatePolicy.ALWAYS;
850 			btreeDBConfig.Duplicates = DuplicatesPolicy.UNSORTED;
851 			btreeDBConfig.PageSize = 512;
852 
853 			using (BTreeDatabase btreeDB = GetMultipleDB(
854 			    btreeDBFileName, btreeDBName, btreeDBConfig)) {
855 				DatabaseEntry key = new DatabaseEntry(
856                                     BitConverter.GetBytes(10));
857 				KeyValuePair<DatabaseEntry, MultipleDatabaseEntry> kvp =
858                                     btreeDB.GetMultiple(key, 1024);
859 				int cnt = 0;
860 				foreach (DatabaseEntry dbt in kvp.Value)
861 					cnt++;
862 				Assert.AreEqual(cnt, 10);
863 
864 				key = new DatabaseEntry(
865                                     BitConverter.GetBytes(102));
866 				kvp = btreeDB.GetMultiple(key, 1024);
867 				cnt = 0;
868 				foreach (DatabaseEntry dbt in kvp.Value)
869 					cnt++;
870 				Assert.AreEqual(cnt, 1);
871 			}
872 		}
873 
874 		[Test]
TestGetMultipleByRecno()875 		public void TestGetMultipleByRecno()
876 		{
877 			testName = "TestGetMultipleByRecno";
878 			SetUpTest(true);
879 			string btreeDBFileName = testHome + "/" +
880 			    testName + ".db";
881 			string btreeDBName =
882 			    Path.GetFileNameWithoutExtension(btreeDBFileName);
883 
884 			BTreeDatabaseConfig btreeDBConfig =
885 			    new BTreeDatabaseConfig();
886 			btreeDBConfig.Creation = CreatePolicy.ALWAYS;
887 			btreeDBConfig.Duplicates = DuplicatesPolicy.NONE;
888 			btreeDBConfig.UseRecordNumbers = true;
889 			using (BTreeDatabase btreeDB = GetMultipleDB(
890 			    btreeDBFileName, btreeDBName, btreeDBConfig)) {
891 				int recno = 44;
892 				KeyValuePair<DatabaseEntry, MultipleDatabaseEntry> kvp =
893                                     btreeDB.GetMultiple((uint)recno);
894 				int cnt = 0;
895 				int kdata = BitConverter.ToInt32(kvp.Key.Data, 0);
896 				Assert.AreEqual(kdata, recno);
897 				foreach (DatabaseEntry dbt in kvp.Value) {
898 					cnt++;
899 					int ddata = BitConverter.ToInt32(dbt.Data, 0);
900 					Assert.AreEqual(ddata, recno);
901 				}
902 				Assert.AreEqual(cnt, 1);
903 			}
904 		}
905 
906 		[Test]
TestGetMultipleByRecnoInSize()907 		public void TestGetMultipleByRecnoInSize()
908 		{
909 			testName = "TestGetMultipleByRecnoInSize";
910 			SetUpTest(true);
911 			string btreeDBFileName = testHome + "/" +
912 			    testName + ".db";
913 			string btreeDBName =
914 			    Path.GetFileNameWithoutExtension(btreeDBFileName);
915 
916 			BTreeDatabaseConfig btreeDBConfig =
917 			    new BTreeDatabaseConfig();
918 			btreeDBConfig.Creation = CreatePolicy.ALWAYS;
919 			btreeDBConfig.Duplicates = DuplicatesPolicy.NONE;
920 			btreeDBConfig.UseRecordNumbers = true;
921 			btreeDBConfig.PageSize = 512;
922 			using (BTreeDatabase btreeDB = GetMultipleDB(
923 			    btreeDBFileName, btreeDBName, btreeDBConfig)) {
924 				int recno = 100;
925 				int bufferSize = 1024;
926 				KeyValuePair<DatabaseEntry, MultipleDatabaseEntry> kvp =
927                                     btreeDB.GetMultiple((uint)recno, bufferSize);
928 				int cnt = 0;
929 				int kdata = BitConverter.ToInt32(kvp.Key.Data, 0);
930 				Assert.AreEqual(kdata, recno);
931 				foreach (DatabaseEntry dbt in kvp.Value) {
932 					cnt++;
933 					Assert.AreEqual(dbt.Data.Length, 111);
934 				}
935 				Assert.AreEqual(1, cnt);
936 			}
937 		}
938 
939 		[Test]
TestGetMultipleInSize()940 		public void TestGetMultipleInSize()
941 		{
942 			testName = "TestGetMultipleInSize";
943 			SetUpTest(true);
944 			string btreeDBFileName = testHome + "/" +
945 			    testName + ".db";
946 			string btreeDBName =
947 			    Path.GetFileNameWithoutExtension(btreeDBFileName);
948 
949 			BTreeDatabaseConfig btreeDBConfig =
950 			    new BTreeDatabaseConfig();
951 			btreeDBConfig.Creation = CreatePolicy.ALWAYS;
952 			btreeDBConfig.Duplicates = DuplicatesPolicy.UNSORTED;
953 			btreeDBConfig.PageSize = 1024;
954 			using (BTreeDatabase btreeDB = GetMultipleDB(
955 			    btreeDBFileName, btreeDBName, btreeDBConfig)) {
956 
957 				int num = 101;
958 				DatabaseEntry key = new DatabaseEntry(
959                                     BitConverter.GetBytes(num));
960 				int bufferSize = 10240;
961 				KeyValuePair<DatabaseEntry, MultipleDatabaseEntry> kvp =
962                                     btreeDB.GetMultiple(key, bufferSize);
963 				int cnt = 0;
964 				foreach (DatabaseEntry dbt in kvp.Value) {
965 					cnt++;
966 					Assert.AreEqual(BitConverter.ToInt32(
967                                             dbt.Data, 0), num);
968 					num++;
969 				}
970 				Assert.AreEqual(cnt, 923);
971 			}
972 		}
973 
974 		[Test]
TestGetWithTxn()975 		public void TestGetWithTxn()
976 		{
977 			testName = "TestGetWithTxn";
978 			SetUpTest(true);
979 
980 			DatabaseEnvironmentConfig envConfig =
981 			    new DatabaseEnvironmentConfig();
982 			envConfig.Create = true;
983 			envConfig.UseLogging = true;
984 			envConfig.UseMPool = true;
985 			envConfig.UseTxns = true;
986 			DatabaseEnvironment env = DatabaseEnvironment.Open(
987 			    testHome, envConfig);
988 
989 			try
990 			{
991 				Transaction openTxn = env.BeginTransaction();
992 				BTreeDatabaseConfig dbConfig =
993 				    new BTreeDatabaseConfig();
994 				dbConfig.Env = env;
995 				dbConfig.Creation = CreatePolicy.IF_NEEDED;
996 				BTreeDatabase db = BTreeDatabase.Open(
997 				    testName + ".db", dbConfig, openTxn);
998 				openTxn.Commit();
999 
1000 				Transaction putTxn = env.BeginTransaction();
1001 				try
1002 				{
1003 					for (int i = 0; i < 20; i++)
1004 						db.Put(new DatabaseEntry(
1005 						    BitConverter.GetBytes(i)),
1006 						    new DatabaseEntry(
1007 						    BitConverter.GetBytes(i)), putTxn);
1008 					putTxn.Commit();
1009 				}
1010 				catch (DatabaseException e)
1011 				{
1012 					putTxn.Abort();
1013 					db.Close();
1014 					throw e;
1015 				}
1016 
1017 				Transaction getTxn = env.BeginTransaction();
1018 				KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
1019 				try
1020 				{
1021 					for (int i = 0; i < 20; i++)
1022 					{
1023 						pair = db.Get(new DatabaseEntry(
1024 						    BitConverter.GetBytes(i)), getTxn);
1025 						Assert.AreEqual(BitConverter.GetBytes(i),
1026 						    pair.Key.Data);
1027 					}
1028 
1029 					getTxn.Commit();
1030 					db.Close();
1031 				}
1032 				catch (DatabaseException)
1033 				{
1034 					getTxn.Abort();
1035 					db.Close();
1036 					throw new TestException();
1037 				}
1038 			}
1039 			catch (DatabaseException)
1040 			{
1041 			}
1042 			finally
1043 			{
1044 				env.Close();
1045 			}
1046 		}
1047 
1048 		[Test]
TestKeyRange()1049 		public void TestKeyRange()
1050 		{
1051 			testName = "TestKeyRange";
1052 			SetUpTest(true);
1053 			string btreeDBFileName = testHome + "/" +
1054 			    testName + ".db";
1055 			string btreeDBName = Path.GetFileNameWithoutExtension(
1056 			    btreeDBFileName);
1057 
1058 			BTreeDatabaseConfig btreeDBConfig =
1059 			    new BTreeDatabaseConfig();
1060 			btreeDBConfig.Creation = CreatePolicy.ALWAYS;
1061 			BTreeDatabase btreeDB = BTreeDatabase.Open(
1062 			    btreeDBFileName, btreeDBName, btreeDBConfig);
1063 
1064 			DatabaseEntry key = new DatabaseEntry();
1065 			DatabaseEntry data = new DatabaseEntry();
1066 			uint recno;
1067 			for (recno = 1; recno <= 10; recno++)
1068 			{
1069 				Configuration.dbtFromString(key,
1070 				    Convert.ToString(recno));
1071 				Configuration.dbtFromString(data,
1072 				    Convert.ToString(recno));
1073 				btreeDB.Put(key, data);
1074 			}
1075 
1076 			Configuration.dbtFromString(key, Convert.ToString(5));
1077 			KeyRange keyRange = btreeDB.KeyRange(key);
1078 			Assert.AreEqual(0.5, keyRange.Less);
1079 			Assert.AreEqual(0.1, keyRange.Equal);
1080 			Assert.AreEqual(0.4, keyRange.Greater);
1081 
1082 			btreeDB.Close();
1083 		}
1084 
1085 		[Test]
TestNoWaitDbExclusiveLock()1086 		public void TestNoWaitDbExclusiveLock()
1087 		{
1088 			testName = "TestNoWaitDbExclusiveLock";
1089 			SetUpTest(true);
1090 
1091 			// Open an environment.
1092 			DatabaseEnvironmentConfig envConfig =
1093 			    new DatabaseEnvironmentConfig();
1094 			envConfig.AutoCommit = true;
1095 			envConfig.Create = true;
1096 			envConfig.UseMPool = true;
1097 			envConfig.UseLocking = true;
1098 			envConfig.UseLogging = true;
1099 			envConfig.UseTxns = true;
1100 			DatabaseEnvironment env = DatabaseEnvironment.Open(
1101 			    testHome, envConfig);
1102 
1103 			// Open a database.
1104 			BTreeDatabaseConfig btreeDBConfig =
1105 			    new BTreeDatabaseConfig();
1106 			btreeDBConfig.Env = env;
1107  			string btreeDBFileName = testName + ".db";
1108 			BTreeDatabase btreeDB;
1109 
1110  			btreeDBConfig.Creation = CreatePolicy.IF_NEEDED;
1111 			btreeDB = BTreeDatabase.Open(
1112 			    btreeDBFileName, btreeDBConfig);
1113 			Assert.IsNull(btreeDB.NoWaitDbExclusiveLock);
1114 			btreeDB.Close();
1115 
1116 			btreeDBConfig.NoWaitDbExclusiveLock = false;
1117 			btreeDB = BTreeDatabase.Open(
1118 			    btreeDBFileName, btreeDBConfig);
1119 			Assert.AreEqual(btreeDB.NoWaitDbExclusiveLock, false);
1120 			btreeDB.Close();
1121 
1122 			btreeDBConfig.NoWaitDbExclusiveLock = true;
1123 			btreeDB = BTreeDatabase.Open(
1124 			    btreeDBFileName, btreeDBConfig);
1125 			Assert.AreEqual(btreeDB.NoWaitDbExclusiveLock, true);
1126 			btreeDB.Close();
1127 			env.Close();
1128 		}
1129 
1130 		[Test]
TestOpenExistingBtreeDB()1131 		public void TestOpenExistingBtreeDB()
1132 		{
1133 			testName = "TestOpenExistingBtreeDB";
1134 			SetUpTest(true);
1135 			string btreeDBFileName = testHome + "/" +
1136 			     testName + ".db";
1137 
1138 			BTreeDatabaseConfig btreeConfig =
1139 			    new BTreeDatabaseConfig();
1140 			btreeConfig.Creation = CreatePolicy.ALWAYS;
1141 			BTreeDatabase btreeDB = BTreeDatabase.Open(
1142 			    btreeDBFileName, btreeConfig);
1143 			btreeDB.Close();
1144 
1145 			DatabaseConfig dbConfig = new DatabaseConfig();
1146 			Database db = Database.Open(btreeDBFileName,
1147 			    dbConfig);
1148 			Assert.AreEqual(db.Type, DatabaseType.BTREE);
1149 			Assert.AreEqual(db.Creation, CreatePolicy.NEVER);
1150 			db.Close();
1151 		}
1152 
1153 		[Test]
TestOpenNewBtreeDB()1154 		public void TestOpenNewBtreeDB()
1155 		{
1156 			testName = "TestOpenNewBtreeDB";
1157 			SetUpTest(true);
1158 			string btreeDBFileName = testHome + "/" +
1159 			    testName + ".db";
1160 
1161 			XmlElement xmlElem = Configuration.TestSetUp(
1162 			    testFixtureName, testName);
1163 			BTreeDatabaseConfig btreeConfig =
1164 			    new BTreeDatabaseConfig();
1165 			BTreeDatabaseConfigTest.Config(xmlElem,
1166 			    ref btreeConfig, true);
1167 			BTreeDatabase btreeDB = BTreeDatabase.Open(
1168 			    btreeDBFileName, btreeConfig);
1169 			Confirm(xmlElem, btreeDB, true);
1170 			btreeDB.Close();
1171 		}
1172 
1173 		[Test]
TestOpenMulDBInSingleFile()1174 		public void TestOpenMulDBInSingleFile()
1175 		{
1176 			testName = "TestOpenMulDBInSingleFile";
1177 			SetUpTest(true);
1178 			string btreeDBFileName = testHome + "/" +
1179 			    testName + ".db";
1180 			string[] btreeDBArr = new string[4];
1181 
1182 			for (int i = 0; i < 4; i++)
1183 				btreeDBArr[i] = Path.GetFileNameWithoutExtension(
1184 				    btreeDBFileName) + i;
1185 
1186 			Configuration.ClearDir(testHome);
1187 
1188 			BTreeDatabaseConfig btreeDBConfig =
1189 			    new BTreeDatabaseConfig();
1190 			btreeDBConfig.Creation = CreatePolicy.IF_NEEDED;
1191 
1192 			BTreeDatabase btreeDB;
1193 			for (int i = 0; i < 4; i++)
1194 			{
1195 				btreeDB = BTreeDatabase.Open(btreeDBFileName,
1196 				    btreeDBArr[i], btreeDBConfig);
1197 				Assert.AreEqual(CreatePolicy.IF_NEEDED, btreeDB.Creation);
1198 				btreeDB.Close();
1199 			}
1200 
1201 			DatabaseConfig dbConfig = new DatabaseConfig();
1202 			Database db;
1203 			for (int i = 0; i < 4; i++)
1204 			{
1205 				using (db = Database.Open(btreeDBFileName,
1206 				    btreeDBArr[i], dbConfig))
1207 				{
1208 					Assert.AreEqual(btreeDBArr[i],
1209 					    db.DatabaseName);
1210 					Assert.AreEqual(DatabaseType.BTREE,
1211 					    db.Type);
1212 				}
1213 			}
1214 		}
1215 
1216 		[Test]
TestOpenWithTxn()1217 		public void TestOpenWithTxn()
1218 		{
1219 			testName = "TestOpenWithTxn";
1220 			SetUpTest(true);
1221 			string btreeDBName = testName + ".db";
1222 
1223 			DatabaseEnvironmentConfig envConfig =
1224 			    new DatabaseEnvironmentConfig();
1225 			envConfig.Create = true;
1226 			envConfig.UseTxns = true;
1227 			envConfig.UseMPool = true;
1228 
1229 			DatabaseEnvironment env = DatabaseEnvironment.Open(
1230 			    testHome, envConfig);
1231 			Transaction txn = env.BeginTransaction(
1232 			    new TransactionConfig());
1233 
1234 			BTreeDatabaseConfig btreeConfig =
1235 			    new BTreeDatabaseConfig();
1236 			btreeConfig.Creation = CreatePolicy.ALWAYS;
1237 			btreeConfig.Env = env;
1238 
1239 			/*
1240 			 * If environmnet home is set, the file name in Open()
1241 			 * is the relative path.
1242 			 */
1243 			BTreeDatabase btreeDB = BTreeDatabase.Open(
1244 			    btreeDBName, btreeConfig, txn);
1245 			Assert.IsTrue(btreeDB.Transactional);
1246 			btreeDB.Close();
1247 			txn.Commit();
1248 			env.Close();
1249 		}
1250 
1251 		[Test]
TestPartialGet()1252 		public void TestPartialGet()
1253 		{
1254 			testName = "TestPartialGet";
1255 			SetUpTest(true);
1256 
1257 			DatabaseEnvironmentConfig envConfig =
1258 			    new DatabaseEnvironmentConfig();
1259 			envConfig.Create = true;
1260 			envConfig.UseTxns = true;
1261 			envConfig.UseMPool = true;
1262 			DatabaseEnvironment env = DatabaseEnvironment.Open(
1263 			    testHome, envConfig);
1264 
1265 			BTreeDatabase db;
1266 			PopulateDb(env, out db);
1267 
1268 			// Partially get the first byte and verify it is 'h'.
1269 			DatabaseEntry key, data;
1270 			KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
1271 			Transaction txn = env.BeginTransaction();
1272 			for (int i = 0; i < 100; i++) {
1273 				key = new DatabaseEntry(BitConverter.GetBytes(i));
1274 				data = new DatabaseEntry(0, 1);
1275 				pair = db.Get(key, data, txn);
1276 				Assert.AreEqual(1, pair.Value.Data.Length);
1277 				Assert.AreEqual((byte)'h', pair.Value.Data[0]);
1278 			}
1279 			txn.Commit();
1280 			db.Close();
1281 			env.Close();
1282 
1283 			/*
1284 			 * Open the existing database and partially get
1285 			 * non-existing data.
1286 			 */
1287 			using (Database edb = Database.Open(
1288 			    testHome + "/" + testName + ".db",
1289 			    new DatabaseConfig())) {
1290 				key = new DatabaseEntry(BitConverter.GetBytes(0));
1291 				data = new DatabaseEntry(10, 1);
1292 				pair = edb.Get(key, data);
1293 				Assert.AreEqual(null, pair.Value.Data);
1294 			}
1295 		}
1296 
1297 		[Test]
TestPartialPut()1298 		public void TestPartialPut()
1299 		{
1300 			testName = "TestPartialPut";
1301 			SetUpTest(true);
1302 
1303 			BTreeDatabase db;
1304 			PopulateDb(null, out db);
1305 
1306 			// Partially update the records.
1307 			DatabaseEntry key, data;
1308 			KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
1309 			byte[] partialBytes = ASCIIEncoding.ASCII.GetBytes("aa");
1310 			byte[] valueBytes;
1311 			for (int i = 0; i < 100; i++) {
1312 				key = new DatabaseEntry(BitConverter.GetBytes(i));
1313 				if (i < 50)
1314 					data = new DatabaseEntry(
1315 					    partialBytes, 0, 2);
1316 				else {
1317 					data = new DatabaseEntry(partialBytes);
1318 					data.Partial = true;
1319 					data.PartialLen = 2;
1320 					data.PartialOffset = 0;
1321 				}
1322 				Assert.AreEqual(0, data.PartialOffset);
1323 				Assert.AreEqual(2, data.PartialLen);
1324 				Assert.AreEqual(true, data.Partial);
1325 				db.Put(key, data);
1326 			}
1327 			// Verify that the records have been partially changed.
1328 			valueBytes = ASCIIEncoding.ASCII.GetBytes("hello");
1329 			valueBytes[0] = (byte)'a';
1330 			valueBytes[1] = (byte)'a';
1331 			for (int i = 0; i < 100; i++) {
1332 				key = new DatabaseEntry(BitConverter.GetBytes(i));
1333 				pair = db.Get(key);
1334 				Assert.AreEqual(
1335 				    BitConverter.GetBytes(i), pair.Key.Data);
1336 				Assert.AreEqual(valueBytes, pair.Value.Data);
1337 			}
1338 
1339 			// Partial put from non-existing offset.
1340 			key = new DatabaseEntry(BitConverter.GetBytes(0));
1341 			data = new DatabaseEntry(partialBytes, 100, 2);
1342 			db.Put(key, data);
1343 
1344 			// Verify that the records have been partially changed.
1345 			pair = db.Get(key);
1346 			Assert.AreEqual(102, pair.Value.Data.Length);
1347 			Assert.AreEqual(valueBytes[0],
1348 			    pair.Value.Data[100]);
1349 			Assert.AreEqual(valueBytes[0],
1350 			    pair.Value.Data[101]);
1351 
1352 			/*
1353 			 * Reuse the DatabaseEntry for non-partial. The partial
1354 			 * length and offset should be ignored.
1355 			 */
1356 			key = new DatabaseEntry(BitConverter.GetBytes(0));
1357 			data.Partial = false;
1358 			db.Put(key, data);
1359 			pair = db.Get(key);
1360 			Assert.AreEqual(2, pair.Value.Data.Length);
1361 
1362 			db.Close();
1363 		}
1364 
PopulateDb(DatabaseEnvironment env, out BTreeDatabase db)1365 		private void PopulateDb(DatabaseEnvironment env,
1366 		    out BTreeDatabase db)
1367 		{
1368 			DatabaseEntry key, data;
1369 			Transaction txn = null;
1370 			string dbName;
1371 
1372 			if (env != null) {
1373 				txn = env.BeginTransaction();
1374 				dbName = testName + ".db";
1375 			} else
1376 				dbName = testHome + "/" + testName + ".db";
1377 
1378 			OpenBtreeDB(env, txn, dbName, out db);
1379 
1380 			for (int i = 0; i < 100; i++) {
1381 				key = new DatabaseEntry(
1382 				    BitConverter.GetBytes(i));
1383 				data = new DatabaseEntry(
1384 				    ASCIIEncoding.ASCII.GetBytes("hello"));
1385 				db.Put(key, data, txn);
1386 			}
1387 
1388 			if (txn != null)
1389 				txn.Commit();
1390 		}
1391 
1392 		[Test]
TestPrefixCompare()1393 		public void TestPrefixCompare()
1394 		{
1395 			testName = "TestPrefixCompare";
1396 			SetUpTest(true);
1397 			string btreeDBFileName = testHome + "/" +
1398 			     testName + ".db";
1399 
1400 			BTreeDatabaseConfig dbConfig =
1401 			    new BTreeDatabaseConfig();
1402 			dbConfig.Creation = CreatePolicy.IF_NEEDED;
1403 			dbConfig.Duplicates = DuplicatesPolicy.SORTED;
1404 			dbConfig.BTreeCompare =
1405 			    new EntryComparisonDelegate(dbIntCompare);
1406 			dbConfig.BTreePrefixCompare =
1407 			    new EntryPrefixComparisonDelegate(dbPrefixCompare);
1408 			BTreeDatabase db = BTreeDatabase.Open(
1409 			    btreeDBFileName, dbConfig);
1410 
1411 			Assert.AreEqual(3, db.PrefixCompare(new DatabaseEntry(
1412 			    BitConverter.GetBytes((Int16)255)), new DatabaseEntry(
1413 			    BitConverter.GetBytes((Int32)65791))));
1414 
1415 			Assert.AreEqual(1, db.PrefixCompare(new DatabaseEntry(
1416 			BitConverter.GetBytes((Int64)255)), new DatabaseEntry(
1417 			BitConverter.GetBytes((Int64)4294967552))));
1418 
1419 			db.Close();
1420 		}
1421 
1422 		[Test]
TestPutMultiple()1423 		public void TestPutMultiple()
1424 		{
1425 			testName = "TestPutMultiple";
1426 			SetUpTest(true);
1427 
1428 			PutMultiple(null);
1429 
1430 			Configuration.ClearDir(testHome);
1431 			DatabaseEnvironmentConfig cfg =
1432 			    new DatabaseEnvironmentConfig();
1433 			cfg.Create = true;
1434 			cfg.UseLogging = true;
1435 			cfg.UseMPool = true;
1436 			cfg.UseTxns = true;
1437 			DatabaseEnvironment env = DatabaseEnvironment.Open(
1438 			    testHome, cfg);
1439 			PutMultiple(env);
1440 			env.Close();
1441 		}
1442 
PutMultiple(DatabaseEnvironment env)1443 		private void PutMultiple(DatabaseEnvironment env)
1444 		{
1445 			List<DatabaseEntry> kList = new List<DatabaseEntry>();
1446 			List<DatabaseEntry> vList = new List<DatabaseEntry>();
1447 			BTreeDatabase db;
1448 			DatabaseEntry key, value;
1449 			Transaction txn;
1450 			string dbFileName = (env == null) ? testHome +
1451 			    "/" + testName + ".db" : testName + ".db";
1452 			int i;
1453 
1454 			BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
1455 			dbConfig.Creation = CreatePolicy.IF_NEEDED;
1456 			if (env != null) {
1457 				dbConfig.Env = env;
1458 				txn = env.BeginTransaction();
1459 				db = BTreeDatabase.Open(
1460 				    dbFileName, dbConfig, txn);
1461 				txn.Commit();
1462 			} else
1463 				db = BTreeDatabase.Open(dbFileName, dbConfig);
1464 
1465 			for (i = 0; i < 100; i++) {
1466 				key = new DatabaseEntry(
1467 				    BitConverter.GetBytes(i));
1468 				value = new DatabaseEntry(
1469 				    ASCIIEncoding.ASCII.GetBytes("data" + i +
1470 				    Configuration.RandomString(512)));
1471 				kList.Add(key);
1472 				vList.Add(value);
1473 			}
1474 
1475 			// Create bulk buffer for non-recno based keys.
1476 			MultipleDatabaseEntry keyBuff =
1477 			    new MultipleDatabaseEntry(kList, false);
1478 			Assert.IsFalse(keyBuff.Recno);
1479 
1480 			// Create bulk buffer for values.
1481 			MultipleDatabaseEntry valBuff =
1482 			    new MultipleDatabaseEntry(vList, false);
1483 			i = 0;
1484 			foreach (DatabaseEntry dbt in valBuff) {
1485 				Assert.AreEqual(vList[i].Data, dbt.Data);
1486 				i++;
1487 			}
1488 			Assert.AreEqual(100, i);
1489 
1490 			// Create bulk buffer from another key buffer.
1491 			MultipleDatabaseEntry keyBuff1 =
1492 			    new MultipleDatabaseEntry(
1493 			    keyBuff.Data, keyBuff.Recno);
1494 			i = 0;
1495 			foreach (DatabaseEntry dbt in keyBuff1) {
1496 				Assert.AreEqual(kList[i].Data, dbt.Data);
1497 				i++;
1498 			}
1499 			Assert.AreEqual(100, i);
1500 
1501 			if (env != null) {
1502 				txn = env.BeginTransaction();
1503 				db.Put(keyBuff, valBuff, txn);
1504 				Assert.AreEqual(100, db.Truncate(txn));
1505 				txn.Commit();
1506 			} else {
1507 				/*
1508 				 * Bulk insert to database with key and value
1509 				 * buffers.
1510 				 */
1511 				db.Put(keyBuff, valBuff);
1512 
1513 				// Verify all records exist as expected.
1514 				Cursor cursor = db.Cursor();
1515 				i = 99;
1516 				Assert.IsTrue(cursor.MoveLast());
1517 				Assert.AreEqual(kList[i].Data,
1518 				    cursor.Current.Key.Data);
1519 				Assert.AreEqual(vList[i].Data,
1520 				    cursor.Current.Value.Data);
1521 				while (cursor.MovePrev()) {
1522 					i--;
1523 					Assert.AreEqual(kList[i].Data,
1524 					    cursor.Current.Key.Data);
1525 					Assert.AreEqual(vList[i].Data,
1526 					    cursor.Current.Value.Data);
1527 				}
1528 				Assert.AreEqual(0, i);
1529 				cursor.Close();
1530 				/*
1531 				 * Dumped all records. The number of records
1532 				 * should be 100.
1533 				 */
1534 				Assert.AreEqual(100, db.Truncate());
1535 
1536 				/*
1537 				 * Bulk insert to database with a copied key
1538 				 * buffer and a value buffer.
1539 				 */
1540 				db.Put(keyBuff1, valBuff);
1541 				cursor = db.Cursor();
1542 				Assert.IsTrue(cursor.MoveLast());
1543 				i = 99;
1544 				Assert.AreEqual(kList[i].Data,
1545 				    cursor.Current.Key.Data);
1546 				Assert.AreEqual(vList[i].Data,
1547 				    cursor.Current.Value.Data);
1548 				while (cursor.MovePrev()) {
1549 					i--;
1550 					Assert.AreEqual(kList[i].Data,
1551 					    cursor.Current.Key.Data);
1552 					Assert.AreEqual(vList[i].Data,
1553 					    cursor.Current.Value.Data);
1554 				}
1555 				cursor.Close();
1556 				Assert.AreEqual(0, i);
1557 				/*
1558 				 * Dumped all records. The number of records
1559 				 * should be 100.
1560 				 */
1561 				Assert.AreEqual(100, db.Truncate());
1562 			}
1563 
1564 			db.Close();
1565 		}
1566 
1567 		[Test]
TestPutMultipleKey()1568 		public void TestPutMultipleKey()
1569 		{
1570 			testName = "TestPutMultipleKey";
1571 			SetUpTest(true);
1572 
1573 			PutMultipleKey(null);
1574 
1575 			Configuration.ClearDir(testHome);
1576 			DatabaseEnvironmentConfig cfg =
1577 			    new DatabaseEnvironmentConfig();
1578 			cfg.Create = true;
1579 			cfg.UseLogging = true;
1580 			cfg.UseMPool = true;
1581 			cfg.UseTxns = true;
1582 			DatabaseEnvironment env = DatabaseEnvironment.Open(
1583 			    testHome, cfg);
1584 			PutMultipleKey(env);
1585 			env.Close();
1586 		}
1587 
PutMultipleKey(DatabaseEnvironment env)1588 		private void PutMultipleKey(DatabaseEnvironment env)
1589 		{
1590 			List<KeyValuePair<DatabaseEntry, DatabaseEntry>> pList =
1591 			    new List<KeyValuePair<
1592 			    DatabaseEntry, DatabaseEntry>>();
1593 			BTreeDatabase db;
1594 			DatabaseEntry key, value;
1595 			Transaction txn;
1596 			string dbFileName = (env == null) ? testHome +
1597 			    "/" + testName + ".db" : testName + ".db";
1598 			int i;
1599 
1600 			BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
1601 			dbConfig.Creation = CreatePolicy.IF_NEEDED;
1602 			if (env != null) {
1603 				dbConfig.Env = env;
1604 				txn = env.BeginTransaction();
1605 				db = BTreeDatabase.Open(
1606 				    dbFileName, dbConfig, txn);
1607 				txn.Commit();
1608 			} else
1609 				db = BTreeDatabase.Open(dbFileName, dbConfig);
1610 
1611 			for (i = 0; i < 100; i++) {
1612 				key = new DatabaseEntry(
1613 				    BitConverter.GetBytes(i));
1614 				value = new DatabaseEntry(
1615 				    ASCIIEncoding.ASCII.GetBytes("data" +
1616 				    i + Configuration.RandomString(512)));
1617 				pList.Add(new KeyValuePair<
1618 				    DatabaseEntry, DatabaseEntry>(key, value));
1619 			}
1620 
1621 			// Create btree bulk buffer for key/value pairs.
1622 			MultipleKeyDatabaseEntry pairBuff =
1623 			    new MultipleKeyDatabaseEntry(pList, false);
1624 			i = 0;
1625 			foreach (KeyValuePair<DatabaseEntry, DatabaseEntry>
1626 			    pair in pairBuff) {
1627 				Assert.AreEqual(pList[i].Key.Data,
1628 				    pair.Key.Data);
1629 				Assert.AreEqual(pList[i].Value.Data,
1630 				    pair.Value.Data);
1631 				i++;
1632 			}
1633 			Assert.AreEqual(100, i);
1634 
1635 			/*
1636 			 * Create bulk buffer from another key/value pairs
1637 			 * bulk buffer.
1638 			 */
1639 			MultipleKeyDatabaseEntry pairBuff1 =
1640 			    new MultipleKeyDatabaseEntry(
1641 			    pairBuff.Data, false);
1642 			Assert.AreEqual(false, pairBuff1.Recno);
1643 			i = 0;
1644 			foreach (KeyValuePair<DatabaseEntry, DatabaseEntry>
1645 			    pair in pairBuff1) {
1646 				Assert.AreEqual(pList[i].Key.Data,
1647 				    pair.Key.Data);
1648 				Assert.AreEqual(pList[i].Value.Data,
1649 				    pair.Value.Data);
1650 				i++;
1651 			}
1652 			Assert.AreEqual(100, i);
1653 
1654 			if (env == null) {
1655 				// Bulk insert with key/value pair bulk buffer.
1656 				db.Put(pairBuff);
1657 				Cursor cursor = db.Cursor();
1658 				Assert.IsTrue(cursor.MoveFirst());
1659 				i = 0;
1660 				Assert.AreEqual(pList[i].Key.Data,
1661 				     cursor.Current.Key.Data);
1662 				Assert.AreEqual(pList[i].Value.Data,
1663 				     cursor.Current.Value.Data);
1664 				while (cursor.MoveNext()) {
1665 					i++;
1666 					Assert.AreEqual(pList[i].Key.Data,
1667 					    cursor.Current.Key.Data);
1668 					Assert.AreEqual(pList[i].Value.Data,
1669 					    cursor.Current.Value.Data);
1670 				}
1671 				Assert.AreEqual(99, i);
1672 				cursor.Close();
1673 				/*
1674 				 * Dump all records from the database. The
1675 				 * number of records should be 100.
1676 				 */
1677 				Assert.AreEqual(100, db.Truncate());
1678 
1679 				// Bulk insert with copied key/value pair buffer.
1680 				db.Put(pairBuff1);
1681 				cursor = db.Cursor();
1682 				Assert.IsTrue(cursor.MoveFirst());
1683 				i = 0;
1684 				Assert.AreEqual(pList[i].Key.Data,
1685 				    cursor.Current.Key.Data);
1686 				Assert.AreEqual(pList[i].Value.Data,
1687 				    cursor.Current.Value.Data);
1688 				while (cursor.MoveNext()) {
1689 					i++;
1690 					Assert.AreEqual(pList[i].Key.Data,
1691 					    cursor.Current.Key.Data);
1692 					Assert.AreEqual(pList[i].Value.Data,
1693 					    cursor.Current.Value.Data);
1694 				}
1695 				Assert.AreEqual(99, i);
1696 				cursor.Close();
1697 				Assert.AreEqual(100, db.Truncate());
1698 			} else {
1699 				txn = env.BeginTransaction();
1700 				db.Put(pairBuff, txn);
1701 				Assert.AreEqual(100, db.Truncate(txn));
1702 				txn.Commit();
1703 			}
1704 
1705 			db.Close();
1706 		}
1707 
1708 		[Test]
TestPutWithoutTxn()1709 		public void TestPutWithoutTxn()
1710 		{
1711 			testName = "TestPutWithoutTxn";
1712 			SetUpTest(true);
1713 			string btreeDBFileName = testHome + "/" +
1714 			    testName + ".db";
1715 
1716 			BTreeDatabaseConfig btreeDBConfig =
1717 			    new BTreeDatabaseConfig();
1718 			btreeDBConfig.Creation = CreatePolicy.ALWAYS;
1719 			DatabaseEntry key, data;
1720 			KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
1721 			using (BTreeDatabase btreeDB = BTreeDatabase.Open(
1722 			    btreeDBFileName, btreeDBConfig))
1723 			{
1724 				// Put integer into database
1725 				key = new DatabaseEntry(
1726 				    BitConverter.GetBytes((int)0));
1727 				data = new DatabaseEntry(
1728 				    BitConverter.GetBytes((int)0));
1729 				btreeDB.Put(key, data);
1730 				pair = btreeDB.Get(key);
1731 				Assert.AreEqual(key.Data, pair.Key.Data);
1732 				Assert.AreEqual(data.Data, pair.Value.Data);
1733 
1734  				// Partial put to update the existing pair.
1735 				data.Partial = true;
1736 				data.PartialLen = 4;
1737 				data.PartialOffset = 4;
1738 				btreeDB.Put(key, data);
1739 				pair = btreeDB.Get(key);
1740 				Assert.AreEqual(key.Data, pair.Key.Data);
1741 				Assert.AreEqual(8, pair.Value.Data.Length);
1742 			}
1743 		}
1744 
1745 		[Test, ExpectedException(typeof(KeyExistException))]
TestPutNoOverWrite()1746 		public void TestPutNoOverWrite()
1747 		{
1748 			testName = "TestPutNoOverWrite";
1749 			SetUpTest(true);
1750 			string btreeDBFileName = testHome + "/" +
1751 			    testName + ".db";
1752 
1753 			BTreeDatabaseConfig btreeDBConfig =
1754 			    new BTreeDatabaseConfig();
1755 			btreeDBConfig.Creation = CreatePolicy.ALWAYS;
1756 			DatabaseEntry key, data, newData;
1757 			using (BTreeDatabase btreeDB = BTreeDatabase.Open(
1758 			    btreeDBFileName, btreeDBConfig))
1759 			{
1760 				key = new DatabaseEntry(
1761 				    BitConverter.GetBytes((int)0));
1762 				data = new DatabaseEntry(
1763 				    BitConverter.GetBytes((int)0));
1764 				newData = new DatabaseEntry(
1765 				    BitConverter.GetBytes((int)1));
1766 
1767 				btreeDB.Put(key, data);
1768 				btreeDB.PutNoOverwrite(key, newData);
1769 			}
1770 		}
1771 
1772 		[Test, ExpectedException(typeof(ExpectedTestException))]
TestPutNoDuplicateWithTxn()1773 		public void TestPutNoDuplicateWithTxn()
1774 		{
1775 			testName = "TestPutNoDuplicateWithTxn";
1776 			SetUpTest(true);
1777 
1778 			DatabaseEnvironmentConfig envConfig =
1779 			    new DatabaseEnvironmentConfig();
1780 			envConfig.Create = true;
1781 			envConfig.UseLogging = true;
1782 			envConfig.UseMPool = true;
1783 			envConfig.UseTxns = true;
1784 			DatabaseEnvironment env = DatabaseEnvironment.Open(
1785 			    testHome, envConfig);
1786 
1787 			Transaction txn = env.BeginTransaction();
1788 			BTreeDatabaseConfig btreeDBConfig =
1789 			    new BTreeDatabaseConfig();
1790 			btreeDBConfig.Creation = CreatePolicy.ALWAYS;
1791 			btreeDBConfig.Env = env;
1792 			btreeDBConfig.Duplicates = DuplicatesPolicy.SORTED;
1793 
1794 			DatabaseEntry key, data;
1795 			try
1796 			{
1797 				using (BTreeDatabase btreeDB =
1798 				    BTreeDatabase.Open(
1799 				    testName + ".db", btreeDBConfig, txn))
1800 				{
1801 					key = new DatabaseEntry(
1802 					    BitConverter.GetBytes((int)0));
1803 					data = new DatabaseEntry(
1804 					    BitConverter.GetBytes((int)0));
1805 
1806 					btreeDB.Put(key, data, txn);
1807 					btreeDB.PutNoDuplicate(key, data, txn);
1808 				}
1809 				txn.Commit();
1810 			}
1811 			catch (KeyExistException)
1812 			{
1813 				txn.Abort();
1814 				throw new ExpectedTestException();
1815 			}
1816 			finally
1817 			{
1818 				env.Close();
1819 			}
1820 		}
1821 
1822 		[Test, ExpectedException(typeof(ExpectedTestException))]
TestRemoveDBFile()1823 		public void TestRemoveDBFile()
1824 		{
1825 			testName = "TestRemoveDBFile";
1826 			SetUpTest(true);
1827 
1828 
1829 			RemoveDBWithoutEnv(testHome, testName, false);
1830 		}
1831 
1832 		[Test, ExpectedException(typeof(ExpectedTestException))]
TestRemoveOneDBFromDBFile()1833 		public void TestRemoveOneDBFromDBFile()
1834 		{
1835 			testName = "TestRemoveOneDBFromDBFile";
1836 			SetUpTest(true);
1837 
1838 			RemoveDBWithoutEnv(testHome, testName, true);
1839 		}
1840 
RemoveDBWithoutEnv(string home, string dbName, bool ifDBName)1841 		public void RemoveDBWithoutEnv(string home, string dbName, bool ifDBName)
1842 		{
1843 			string dbFileName = home + "/" + dbName + ".db";
1844 
1845 			Configuration.ClearDir(home);
1846 
1847 			BTreeDatabaseConfig btreeDBConfig =
1848 			    new BTreeDatabaseConfig();
1849 			btreeDBConfig.Creation = CreatePolicy.IF_NEEDED;
1850 
1851 			BTreeDatabase btreeDB;
1852 			if (ifDBName == false)
1853 			{
1854 				btreeDB = BTreeDatabase.Open(dbFileName, btreeDBConfig);
1855 				btreeDB.Close();
1856 				BTreeDatabase.Remove(dbFileName);
1857 				throw new ExpectedTestException();
1858 			}
1859 			else
1860 			{
1861 				btreeDB = BTreeDatabase.Open(dbFileName, dbName, btreeDBConfig);
1862 				btreeDB.Close();
1863 				BTreeDatabase.Remove(dbFileName, dbName);
1864 				Assert.IsTrue(File.Exists(dbFileName));
1865 				try
1866 				{
1867 					btreeDB = BTreeDatabase.Open(dbFileName, dbName, new BTreeDatabaseConfig());
1868 					btreeDB.Close();
1869 				}
1870 				catch (DatabaseException)
1871 				{
1872 					throw new ExpectedTestException();
1873 				}
1874 			}
1875 		}
1876 
1877 		[Test]
TestRemoveDBFromFileInEnv()1878 		public void TestRemoveDBFromFileInEnv()
1879 		{
1880 			testName = "TestRemoveDBFromFileInEnv";
1881 			SetUpTest(true);
1882 
1883 			RemoveDatabase(testHome, testName, true, true);
1884 		}
1885 
1886 		[Test]
TestRemoveDBFromEnv()1887 		public void TestRemoveDBFromEnv()
1888 		{
1889 			testName = "TestRemoveDBFromEnv";
1890 			SetUpTest(true);
1891 
1892 			RemoveDatabase(testHome, testName, true, false);
1893 		}
1894 
RemoveDatabase(string home, string dbName, bool ifEnv, bool ifDBName)1895 		public void RemoveDatabase(string home, string dbName,
1896 		    bool ifEnv, bool ifDBName)
1897 		{
1898 			string dbFileName = dbName + ".db";
1899 
1900 			Configuration.ClearDir(home);
1901 
1902 			DatabaseEnvironmentConfig envConfig =
1903 			    new DatabaseEnvironmentConfig();
1904 			envConfig.Create = true;
1905 			envConfig.UseCDB = true;
1906 			envConfig.UseMPool = true;
1907 
1908 			DatabaseEnvironment env;
1909 			env = DatabaseEnvironment.Open(home, envConfig);
1910 
1911 			try
1912 			{
1913 				BTreeDatabaseConfig btreeDBConfig =
1914 				    new BTreeDatabaseConfig();
1915 				btreeDBConfig.Creation = CreatePolicy.ALWAYS;
1916 				btreeDBConfig.Env = env;
1917 				BTreeDatabase btreeDB = BTreeDatabase.Open(
1918 				    dbFileName, dbName, btreeDBConfig);
1919 				btreeDB.Close();
1920 
1921 				if (ifEnv == true && ifDBName == true)
1922 					BTreeDatabase.Remove(dbFileName, dbName, env);
1923 				else if (ifEnv == true)
1924 					BTreeDatabase.Remove(dbFileName, env);
1925 			}
1926 			catch (DatabaseException)
1927 			{
1928 				throw new TestException();
1929 			}
1930 			finally
1931 			{
1932 				try
1933 				{
1934 					BTreeDatabaseConfig dbConfig =
1935 					    new BTreeDatabaseConfig();
1936 					dbConfig.Creation = CreatePolicy.NEVER;
1937 					dbConfig.Env = env;
1938 					BTreeDatabase db = BTreeDatabase.Open(
1939 					    dbFileName, dbName, dbConfig);
1940 					Assert.AreEqual(db.Creation, CreatePolicy.NEVER);
1941 					db.Close();
1942 					throw new TestException();
1943 				}
1944 				catch (DatabaseException)
1945 				{
1946 				}
1947 				finally
1948 				{
1949 					env.Close();
1950 				}
1951 			}
1952 		}
1953 
1954 		[Test]
TestRenameDB()1955 		public void TestRenameDB()
1956 		{
1957 			testName = "TestRenameDB";
1958 			SetUpTest(true);
1959 			string btreeDBFileName = testHome + "/" + testName + ".db";
1960 			string btreeDBName = testName;
1961 			string newBtreeDBName = btreeDBName + "1" + ".db";
1962 
1963 			try
1964 			{
1965 				BTreeDatabaseConfig btreeDBConfig =
1966 				    new BTreeDatabaseConfig();
1967 				btreeDBConfig.Creation = CreatePolicy.ALWAYS;
1968 				BTreeDatabase btreeDB = BTreeDatabase.Open(
1969 				    btreeDBFileName, btreeDBName, btreeDBConfig);
1970 				btreeDB.Close();
1971 				BTreeDatabase.Rename(btreeDBFileName,
1972 				    btreeDBName, newBtreeDBName);
1973 
1974 				BTreeDatabaseConfig dbConfig =
1975 				    new BTreeDatabaseConfig();
1976 				dbConfig.Creation = CreatePolicy.NEVER;
1977 				BTreeDatabase newDB = BTreeDatabase.Open(
1978 				    btreeDBFileName, newBtreeDBName, dbConfig);
1979 				newDB.Close();
1980 			}
1981 			catch (DatabaseException e)
1982 			{
1983 				throw new TestException(e.Message);
1984 			}
1985 			finally
1986 			{
1987 				try
1988 				{
1989 					BTreeDatabaseConfig dbConfig =
1990 					    new BTreeDatabaseConfig();
1991 					dbConfig.Creation = CreatePolicy.NEVER;
1992 					BTreeDatabase db = BTreeDatabase.Open(
1993 					    btreeDBFileName, btreeDBName,
1994 					    dbConfig);
1995 					throw new TestException(testName);
1996 				}
1997 				catch (DatabaseException)
1998 				{
1999 				}
2000 			}
2001 		}
2002 
2003 		[Test]
TestRenameDBFile()2004 		public void TestRenameDBFile()
2005 		{
2006 			testName = "TestRenameDB";
2007 			SetUpTest(true);
2008 			string btreeDBFileName = testHome + "/" +
2009 			    testName + ".db";
2010 			string newBtreeDBFileName = testHome + "/" +
2011 			    testName + "1.db";
2012 
2013 			BTreeDatabaseConfig btreeDBConfig =
2014 			    new BTreeDatabaseConfig();
2015 			btreeDBConfig.Creation = CreatePolicy.ALWAYS;
2016 			BTreeDatabase btreeDB = BTreeDatabase.Open(
2017 			    btreeDBFileName, btreeDBConfig);
2018 			btreeDB.Close();
2019 
2020 			BTreeDatabase.Rename(btreeDBFileName,
2021 			    newBtreeDBFileName);
2022 			Assert.IsFalse(File.Exists(btreeDBFileName));
2023 			Assert.IsTrue(File.Exists(newBtreeDBFileName));
2024 		}
2025 
2026 		[Test]
TestSync()2027 		public void TestSync()
2028 		{
2029 			testName = "TestSync";
2030 			SetUpTest(true);
2031 			string btreeDBName = testName + ".db";
2032 
2033 			DatabaseEnvironmentConfig envConfig =
2034 			    new DatabaseEnvironmentConfig();
2035 			envConfig.Create = true;
2036 			envConfig.ForceFlush = true;
2037 			envConfig.UseTxns = true;
2038 			envConfig.UseMPool = true;
2039 			envConfig.UseLogging = true;
2040 			envConfig.LogSystemCfg = new LogConfig();
2041 			envConfig.LogSystemCfg.ForceSync = false;
2042 			envConfig.LogSystemCfg.AutoRemove = true;
2043 			DatabaseEnvironment env = DatabaseEnvironment.Open(
2044 			    testHome, envConfig);
2045 
2046 			TransactionConfig txnConfig = new TransactionConfig();
2047 			txnConfig.SyncAction =
2048 			    TransactionConfig.LogFlush.WRITE_NOSYNC;
2049 			Transaction txn = env.BeginTransaction(txnConfig);
2050 
2051 			BTreeDatabaseConfig btreeConfig =
2052 			    new BTreeDatabaseConfig();
2053 			btreeConfig.Creation = CreatePolicy.ALWAYS;
2054 			btreeConfig.Env = env;
2055 
2056 			BTreeDatabase btreeDB = BTreeDatabase.Open(
2057 			    btreeDBName, btreeConfig, txn);
2058 
2059 			DatabaseEntry key = new DatabaseEntry(
2060 			    ASCIIEncoding.ASCII.GetBytes("key"));
2061 			DatabaseEntry data = new DatabaseEntry(
2062 			    ASCIIEncoding.ASCII.GetBytes("data"));
2063 			Assert.IsFalse(btreeDB.Exists(key, txn));
2064 			btreeDB.Put(key, data, txn);
2065 			btreeDB.Sync();
2066 			btreeDB.Close(false);
2067 			txn.Commit();
2068 			env.Close();
2069 
2070 			BTreeDatabaseConfig dbConfig =
2071 			    new BTreeDatabaseConfig();
2072 			dbConfig.Creation = CreatePolicy.NEVER;
2073 			using (BTreeDatabase db = BTreeDatabase.Open(
2074 			    testHome + "/" + btreeDBName, dbConfig))
2075 			{
2076 				Assert.IsTrue(db.Exists(key));
2077 			}
2078 		}
2079 
2080 		[Test]
TestTruncate()2081 		public void TestTruncate()
2082 		{
2083 			testName = "TestTruncate";
2084 			SetUpTest(true);
2085 			string btreeDBFileName = testHome + "/" +
2086 			    testName + ".db";
2087 
2088 			BTreeDatabaseConfig btreeDBConfig =
2089 			    new BTreeDatabaseConfig();
2090 			btreeDBConfig.Creation = CreatePolicy.ALWAYS;
2091 			btreeDBConfig.CacheSize =
2092 			    new CacheInfo(0, 30 * 1024, 1);
2093 			BTreeDatabase btreeDB = BTreeDatabase.Open(
2094 			    btreeDBFileName, btreeDBConfig);
2095 			DatabaseEntry key;
2096 			DatabaseEntry data;
2097 			for (int i = 0; i < 100; i++)
2098 			{
2099 				key = new DatabaseEntry(
2100 				    BitConverter.GetBytes(i));
2101 				data = new DatabaseEntry(
2102 				    BitConverter.GetBytes(i));
2103 				btreeDB.Put(key, data);
2104 			}
2105 			uint count = btreeDB.Truncate();
2106 			Assert.AreEqual(100, count);
2107 			Assert.IsFalse(btreeDB.Exists(new DatabaseEntry(
2108 			    BitConverter.GetBytes((int)50))));
2109 			btreeDB.Close();
2110 		}
2111 
2112 		[Test]
TestTruncateInTxn()2113 		public void TestTruncateInTxn()
2114 		{
2115 			testName = "TestTruncateInTxn";
2116 			SetUpTest(true);
2117 
2118 			DatabaseEnvironmentConfig envConfig =
2119 			    new DatabaseEnvironmentConfig();
2120 			envConfig.Create = true;
2121 			envConfig.UseMPool = true;
2122 			envConfig.UseTxns = true;
2123 			DatabaseEnvironment env = DatabaseEnvironment.Open(
2124 			    testHome, envConfig);
2125 
2126 			try
2127 			{
2128 				Transaction openTxn = env.BeginTransaction();
2129 				BTreeDatabaseConfig dbConfig =
2130 				    new BTreeDatabaseConfig();
2131 				dbConfig.Creation = CreatePolicy.IF_NEEDED;
2132 				dbConfig.Env = env;
2133 				BTreeDatabase db = BTreeDatabase.Open(
2134 				    testName + ".db", dbConfig, openTxn);
2135 				openTxn.Commit();
2136 
2137 				Transaction putTxn = env.BeginTransaction();
2138 				try
2139 				{
2140 					DatabaseEntry key, data;
2141 					for (int i = 0; i < 10; i++)
2142 					{
2143 						key = new DatabaseEntry(
2144 						    BitConverter.GetBytes(i));
2145 						data = new DatabaseEntry(
2146 						    BitConverter.GetBytes(i));
2147 						db.Put(key, data, putTxn);
2148 					}
2149 
2150 					putTxn.Commit();
2151 				}
2152 				catch (DatabaseException e)
2153 				{
2154 					putTxn.Abort();
2155 					db.Close();
2156 					throw e;
2157 				}
2158 
2159 				Transaction trunTxn = env.BeginTransaction();
2160 				try
2161 				{
2162 					uint count = db.Truncate(trunTxn);
2163 					Assert.AreEqual(10, count);
2164 					Assert.IsFalse(db.Exists(
2165 					    new DatabaseEntry(
2166 					    BitConverter.GetBytes((int)5)), trunTxn));
2167 					trunTxn.Commit();
2168 					db.Close();
2169 				}
2170 				catch (DatabaseException)
2171 				{
2172 					trunTxn.Abort();
2173 					db.Close();
2174 					throw new TestException();
2175 				}
2176 			}
2177 			catch (DatabaseException)
2178 			{
2179 			}
2180 			finally
2181 			{
2182 				env.Close();
2183 			}
2184 		}
2185 
2186 		[Test]
TestTruncateUnusedPages()2187 		public void TestTruncateUnusedPages()
2188 		{
2189 			testName = "TestTruncateUnusedPages";
2190 			SetUpTest(true);
2191 			string dbFileName = testHome + "/" + testName + ".db";
2192 
2193 			BTreeDatabaseConfig dbConfig =
2194 			    new BTreeDatabaseConfig();
2195 			dbConfig.Creation = CreatePolicy.ALWAYS;
2196 			dbConfig.PageSize = 512;
2197 			BTreeDatabase db = BTreeDatabase.Open(
2198 			    dbFileName, dbConfig);
2199 			DatabaseEntry key, data;
2200 			for (int i = 0; i < 100; i++)
2201 			{
2202 				key = new DatabaseEntry(
2203 				    BitConverter.GetBytes(i));
2204 				data = new DatabaseEntry(
2205 				    BitConverter.GetBytes(i));
2206 				db.Put(key, data);
2207 			}
2208 
2209 			for (int i = 0; i < 80; i++)
2210 				db.Delete(new DatabaseEntry(
2211 				    BitConverter.GetBytes(i)));
2212 
2213 			uint count = db.TruncateUnusedPages();
2214 			Assert.LessOrEqual(0, count);
2215 
2216 			db.Close();
2217 		}
2218 
2219 		[Test]
TestTruncateUnusedPagesWithTxn()2220 		public void TestTruncateUnusedPagesWithTxn()
2221 		{
2222 			testName = "TestTruncateUnusedPagesWithTxn";
2223 			SetUpTest(true);
2224 
2225 			DatabaseEnvironmentConfig envConfig =
2226 			    new DatabaseEnvironmentConfig();
2227 			envConfig.Create = true;
2228 			envConfig.UseMPool = true;
2229 			envConfig.UseTxns = true;
2230 			DatabaseEnvironment env = DatabaseEnvironment.Open(
2231 			    testHome, envConfig);
2232 
2233 			BTreeDatabase db;
2234 			try
2235 			{
2236 				Transaction openTxn = env.BeginTransaction();
2237 				try
2238 				{
2239 					BTreeDatabaseConfig dbConfig =
2240 					    new BTreeDatabaseConfig();
2241 					dbConfig.Creation = CreatePolicy.IF_NEEDED;
2242 					dbConfig.Env = env;
2243 					dbConfig.PageSize = 512;
2244 					db = BTreeDatabase.Open(
2245 					    testName + ".db", dbConfig, openTxn);
2246 					openTxn.Commit();
2247 					Assert.AreEqual(512, db.Pagesize);
2248 				}
2249 				catch (DatabaseException e)
2250 				{
2251 					openTxn.Abort();
2252 					throw e;
2253 				}
2254 
2255 				Transaction putTxn = env.BeginTransaction();
2256 				try
2257 				{
2258 					DatabaseEntry key, data;
2259 					for (int i = 0; i < 100; i++)
2260 					{
2261 						key = new DatabaseEntry(
2262 						    BitConverter.GetBytes(i));
2263 						data = new DatabaseEntry(
2264 						    BitConverter.GetBytes(i));
2265 						db.Put(key, data, putTxn);
2266 					}
2267 
2268 					putTxn.Commit();
2269 				}
2270 				catch (DatabaseException e)
2271 				{
2272 					putTxn.Abort();
2273 					db.Close();
2274 					throw e;
2275 				}
2276 
2277 				Transaction delTxn = env.BeginTransaction();
2278 				try
2279 				{
2280 					for (int i = 20; i <= 80; i++)
2281 						db.Delete(new DatabaseEntry(
2282 						    BitConverter.GetBytes(i)), delTxn);
2283 					delTxn.Commit();
2284 				}
2285 				catch (DatabaseException e)
2286 				{
2287 					delTxn.Abort();
2288 					db.Close();
2289 					throw e;
2290 				}
2291 
2292 				Transaction trunTxn = env.BeginTransaction();
2293 				try
2294 				{
2295 					uint trunPages = db.TruncateUnusedPages(
2296 					    trunTxn);
2297 					Assert.LessOrEqual(0, trunPages);
2298 					trunTxn.Commit();
2299 					db.Close();
2300 				}
2301 				catch (DatabaseException)
2302 				{
2303 					trunTxn.Abort();
2304 					db.Close();
2305 					throw new Exception();
2306 				}
2307 			}
2308 			catch (DatabaseException)
2309 			{
2310 			}
2311 			finally
2312 			{
2313 				env.Close();
2314 			}
2315 		}
2316 
2317 		[Test]
TestSalvage()2318 		public void TestSalvage()
2319 		{
2320 			testName = "TestSalvage";
2321 			SetUpTest(true);
2322 			string btreeDBFileName = testHome + "/" +
2323 			    testName + ".db";
2324 			string printableOutPut = testHome + "/" +
2325 			    "printableOutPut";
2326 			string inprintableOutPut = testHome + "/" +
2327 			    "inprintableOutPut";
2328 
2329 			BTreeDatabaseConfig btreeDBConfig =
2330 			    new BTreeDatabaseConfig();
2331 			btreeDBConfig.Creation = CreatePolicy.ALWAYS;
2332 			BTreeDatabase btreeDB = BTreeDatabase.Open(
2333 			    btreeDBFileName, btreeDBConfig);
2334 
2335 			DatabaseEntry key;
2336 			DatabaseEntry data;
2337 
2338 			for (uint i = 0; i < 10; i++)
2339 			{
2340 				key = new DatabaseEntry(
2341 				    ASCIIEncoding.ASCII.GetBytes(i.ToString()));
2342 				data = new DatabaseEntry(
2343 				    ASCIIEncoding.ASCII.GetBytes(i.ToString()));
2344 				btreeDB.Put(key, data);
2345 			}
2346 
2347 			btreeDB.Close();
2348 
2349 			StreamWriter sw1 = new StreamWriter(printableOutPut);
2350 			StreamWriter sw2 = new StreamWriter(inprintableOutPut);
2351 			BTreeDatabase.Salvage(btreeDBFileName, btreeDBConfig,
2352 			    true, true, sw1);
2353 			BTreeDatabase.Salvage(btreeDBFileName, btreeDBConfig,
2354 			    false, true, sw2);
2355 			sw1.Close();
2356 			sw2.Close();
2357 
2358 			FileStream file1 = new FileStream(printableOutPut,
2359 			    FileMode.Open);
2360 			FileStream file2 = new FileStream(inprintableOutPut,
2361 			    FileMode.Open);
2362 			if (file1.Length == file2.Length)
2363 			{
2364 				int filebyte1 = 0;
2365 				int filebyte2 = 0;
2366 				do
2367 				{
2368 					filebyte1 = file1.ReadByte();
2369 					filebyte2 = file2.ReadByte();
2370 				} while ((filebyte1 == filebyte2) &&
2371 				    (filebyte1 != -1));
2372 				Assert.AreNotEqual(filebyte1, filebyte2);
2373 			}
2374 
2375 			file1.Close();
2376 			file2.Close();
2377 		}
2378 
2379 		[Test]
TestUpgrade()2380 		public void TestUpgrade()
2381 		{
2382 			testName = "TestUpgrade";
2383 			SetUpTest(true);
2384 
2385 			string srcDBFileName = "../../bdb4.7.db";
2386 			string testDBFileName = testHome + "/bdb4.7.db";
2387 
2388 			FileInfo srcDBFileInfo = new FileInfo(srcDBFileName);
2389 
2390 			//Copy the file.
2391 			srcDBFileInfo.CopyTo(testDBFileName);
2392 			Assert.IsTrue(File.Exists(testDBFileName));
2393 
2394 			BTreeDatabase.Upgrade(testDBFileName,
2395 			    new DatabaseConfig(), true);
2396 
2397 			// Open the upgraded database file.
2398 			BTreeDatabase db = BTreeDatabase.Open(
2399 			    testDBFileName, new BTreeDatabaseConfig());
2400 			db.Close();
2401 		}
2402 
2403 		[Test, ExpectedException(typeof(TestException))]
TestVerify()2404 		public void TestVerify()
2405 		{
2406 			testName = "TestVerify";
2407 			SetUpTest(true);
2408 			string btreeDBFileName = testHome + "/" +
2409 			    testName + ".db";
2410 			string btreeDBName =
2411 			    Path.GetFileNameWithoutExtension(btreeDBFileName);
2412 
2413 			BTreeDatabaseConfig btreeDBConfig =
2414 			    new BTreeDatabaseConfig();
2415 			btreeDBConfig.Creation = CreatePolicy.ALWAYS;
2416 			BTreeDatabase btreeDB = BTreeDatabase.Open(
2417 			    btreeDBFileName, btreeDBName, btreeDBConfig);
2418 			btreeDB.Close();
2419 			btreeDBConfig.Duplicates = DuplicatesPolicy.SORTED;
2420 			BTreeDatabase.Verify(btreeDBFileName, btreeDBConfig,
2421 			    Database.VerifyOperation.NO_ORDER_CHECK);
2422 			try
2423 			{
2424 				BTreeDatabase.Verify(btreeDBFileName,
2425 				    btreeDBConfig,
2426 				    Database.VerifyOperation.ORDER_CHECK_ONLY);
2427 			}
2428 			catch (DatabaseException)
2429 			{
2430 				throw new TestException(testName);
2431 			}
2432 			finally
2433 			{
2434 				BTreeDatabase.Verify(btreeDBFileName,
2435 				    btreeDBName, btreeDBConfig,
2436 				    Database.VerifyOperation.ORDER_CHECK_ONLY);
2437 			}
2438 
2439 		}
2440 
2441 		[Test]
TestStats()2442 		public void TestStats()
2443 		{
2444 			testName = "TestStats";
2445 			SetUpTest(true);
2446 			string dbFileName = testHome + "/" +
2447 			    testName + ".db";
2448 
2449 			BTreeDatabaseConfig dbConfig =
2450 			    new BTreeDatabaseConfig();
2451 			ConfigCase1(dbConfig);
2452 			BTreeDatabase db = BTreeDatabase.Open(dbFileName,
2453 			    dbConfig);
2454 
2455 			BTreeStats stats = db.Stats();
2456 			ConfirmStatsPart1Case1(stats);
2457 
2458 			// Put 500 records into the database.
2459 			PutRecordCase1(db, null);
2460 
2461 			stats = db.Stats();
2462 			ConfirmStatsPart2Case1(stats);
2463 
2464 			// Delete some data to get some free pages.
2465 			byte[] bigArray = new byte[10240];
2466 			db.Delete(new DatabaseEntry(bigArray));
2467 
2468 			db.PrintStats();
2469 			db.PrintFastStats();
2470 
2471 			db.Close();
2472 		}
2473 
2474 		[Test]
TestStatsInTxn()2475 		public void TestStatsInTxn()
2476 		{
2477 			testName = "TestStatsInTxn";
2478 			SetUpTest(true);
2479 
2480 			StatsInTxn(testHome, testName, false);
2481 		}
2482 
2483 		[Test]
TestStatsWithIsolation()2484 		public void TestStatsWithIsolation()
2485 		{
2486 			testName = "TestStatsWithIsolation";
2487 			SetUpTest(true);
2488 
2489 			StatsInTxn(testHome, testName, true);
2490 		}
2491 
2492         [Test]
TestMultipleDBSingleFile()2493         public void TestMultipleDBSingleFile()
2494         {
2495             testName = "TestMultipleDBSingleFile";
2496             SetUpTest(true);
2497             string btreeDBName = testHome + "/" + testName + ".db";
2498 
2499             string dbName = "test";
2500 
2501             /* Create and initialize database object, open the database. */
2502             BTreeDatabaseConfig btreeDBconfig = new BTreeDatabaseConfig();
2503             btreeDBconfig.Creation = CreatePolicy.IF_NEEDED;
2504             btreeDBconfig.ErrorPrefix = testName;
2505             btreeDBconfig.UseRecordNumbers = true;
2506 
2507             BTreeDatabase btreeDB = BTreeDatabase.Open(btreeDBName, dbName,
2508                 btreeDBconfig);
2509             btreeDB.Close();
2510             btreeDB = BTreeDatabase.Open(btreeDBName, dbName + "2",
2511                 btreeDBconfig);
2512             btreeDB.Close();
2513 
2514             BTreeDatabaseConfig dbcfg = new BTreeDatabaseConfig();
2515             dbcfg.ReadOnly = true;
2516             BTreeDatabase newDb = BTreeDatabase.Open(btreeDBName, dbcfg);
2517             Boolean val = newDb.HasMultiple;
2518             Assert.IsTrue(val);
2519             newDb.Close();
2520         }
2521 
StatsInTxn(string home, string name, bool ifIsolation)2522 		public void StatsInTxn(string home, string name, bool ifIsolation)
2523 		{
2524 			DatabaseEnvironmentConfig envConfig =
2525 			    new DatabaseEnvironmentConfig();
2526 			EnvConfigCase1(envConfig);
2527 			DatabaseEnvironment env = DatabaseEnvironment.Open(
2528 			    home, envConfig);
2529 
2530 			Transaction openTxn = env.BeginTransaction();
2531 			BTreeDatabaseConfig dbConfig =
2532 			    new BTreeDatabaseConfig();
2533 			ConfigCase1(dbConfig);
2534 			dbConfig.Env = env;
2535 			BTreeDatabase db = BTreeDatabase.Open(name + ".db",
2536 			    dbConfig, openTxn);
2537 			openTxn.Commit();
2538 
2539 			Transaction statsTxn = env.BeginTransaction();
2540 			BTreeStats stats;
2541 			BTreeStats fastStats;
2542 			if (ifIsolation == false)
2543 			{
2544 				stats = db.Stats(statsTxn);
2545 				fastStats = db.FastStats(statsTxn);
2546 			}
2547 			else
2548 			{
2549 				stats = db.Stats(statsTxn, Isolation.DEGREE_ONE);
2550 				fastStats = db.FastStats(statsTxn,
2551 				    Isolation.DEGREE_ONE);
2552 			}
2553 			ConfirmStatsPart1Case1(stats);
2554 
2555 			// Put 500 records into the database.
2556 			PutRecordCase1(db, statsTxn);
2557 
2558 			if (ifIsolation == false)
2559 				stats = db.Stats(statsTxn);
2560 			else
2561 				stats = db.Stats(statsTxn, Isolation.DEGREE_TWO);
2562 			ConfirmStatsPart2Case1(stats);
2563 
2564 			// Delete some data to get some free pages.
2565 			byte[] bigArray = new byte[10240];
2566 			db.Delete(new DatabaseEntry(bigArray), statsTxn);
2567 			if (ifIsolation == false)
2568 				stats = db.Stats(statsTxn);
2569 			else
2570 				stats = db.Stats(statsTxn, Isolation.DEGREE_THREE);
2571 			ConfirmStatsPart3Case1(stats);
2572 
2573 			db.PrintStats(true);
2574 			Assert.AreEqual(0, stats.EmptyPages);
2575 
2576 			statsTxn.Commit();
2577 			db.Close();
2578 			env.Close();
2579 		}
2580 
EnvConfigCase1(DatabaseEnvironmentConfig cfg)2581 		public void EnvConfigCase1(DatabaseEnvironmentConfig cfg)
2582 		{
2583 			cfg.Create = true;
2584 			cfg.UseTxns = true;
2585 			cfg.UseMPool = true;
2586 			cfg.UseLogging = true;
2587 		}
2588 
ConfigCase1(BTreeDatabaseConfig dbConfig)2589 		public void ConfigCase1(BTreeDatabaseConfig dbConfig)
2590 		{
2591 			dbConfig.Creation = CreatePolicy.IF_NEEDED;
2592 			dbConfig.Duplicates = DuplicatesPolicy.UNSORTED;
2593 			dbConfig.PageSize = 4096;
2594 			dbConfig.MinKeysPerPage = 10;
2595 		}
2596 
PutRecordCase1(BTreeDatabase db, Transaction txn)2597 		public void PutRecordCase1(BTreeDatabase db, Transaction txn)
2598 		{
2599 			byte[] bigArray = new byte[10240];
2600 			for (int i = 0; i < 100; i++)
2601 			{
2602 				if (txn == null)
2603 					db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
2604 					    new DatabaseEntry(BitConverter.GetBytes(i)));
2605 				else
2606 					db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
2607 					    new DatabaseEntry(BitConverter.GetBytes(i)), txn);
2608 			}
2609 			for (int i = 100; i < 500; i++)
2610 			{
2611 				if (txn == null)
2612 					db.Put(new DatabaseEntry(bigArray),
2613 					    new DatabaseEntry(bigArray));
2614 				else
2615 					db.Put(new DatabaseEntry(bigArray),
2616 					    new DatabaseEntry(bigArray), txn);
2617 			}
2618 		}
2619 
ConfirmStatsPart1Case1(BTreeStats stats)2620 		public void ConfirmStatsPart1Case1(BTreeStats stats)
2621 		{
2622 			Assert.AreEqual(1, stats.EmptyPages);
2623 			Assert.AreNotEqual(0, stats.LeafPagesFreeBytes);
2624 			Assert.AreEqual(1, stats.Levels);
2625 			Assert.AreNotEqual(0, stats.MagicNumber);
2626 			Assert.AreEqual(1, stats.MetadataFlags);
2627 			Assert.AreEqual(10, stats.MinKey);
2628 			Assert.AreEqual(2, stats.nPages);
2629 			Assert.AreEqual(4096, stats.PageSize);
2630 			Assert.AreEqual(9, stats.Version);
2631 		}
2632 
ConfirmStatsPart2Case1(BTreeStats stats)2633 		public void ConfirmStatsPart2Case1(BTreeStats stats)
2634 		{
2635 			Assert.AreNotEqual(0, stats.DuplicatePages);
2636 			Assert.AreNotEqual(0, stats.DuplicatePagesFreeBytes);
2637 			Assert.AreNotEqual(0, stats.InternalPages);
2638 			Assert.AreNotEqual(0, stats.InternalPagesFreeBytes);
2639 			Assert.AreNotEqual(0, stats.LeafPages);
2640 			Assert.AreEqual(500, stats.nData);
2641 			Assert.AreEqual(101, stats.nKeys);
2642 			Assert.AreNotEqual(0, stats.OverflowPages);
2643 			Assert.AreNotEqual(0, stats.OverflowPagesFreeBytes);
2644 		}
2645 
ConfirmStatsPart3Case1(BTreeStats stats)2646 		public void ConfirmStatsPart3Case1(BTreeStats stats)
2647 		{
2648 			Assert.AreNotEqual(0, stats.FreePages);
2649 		}
2650 
dbIntCompare(DatabaseEntry dbt1, DatabaseEntry dbt2)2651 		private int dbIntCompare(DatabaseEntry dbt1,
2652 		    DatabaseEntry dbt2)
2653 		{
2654 			int a, b;
2655 			a = BitConverter.ToInt32(dbt1.Data, 0);
2656 			b = BitConverter.ToInt32(dbt2.Data, 0);
2657 			return a - b;
2658 		}
2659 
dbPrefixCompare(DatabaseEntry dbt1, DatabaseEntry dbt2)2660 		private uint dbPrefixCompare(DatabaseEntry dbt1,
2661 		    DatabaseEntry dbt2)
2662 		{
2663 			uint cnt, len;
2664 
2665 			len = Math.Min((uint)dbt1.Data.Length, (uint)dbt2.Data.Length);
2666 			for (cnt = 0; cnt < len; cnt++)
2667 			{
2668 				if (dbt1.Data[cnt] != dbt2.Data[cnt])
2669 					return cnt + 1;
2670 			}
2671 			if (dbt1.Data.Length > dbt2.Data.Length)
2672 				return (uint)dbt2.Data.Length + 1;
2673 			else if (dbt1.Data.Length < dbt2.Data.Length)
2674 				return (uint)dbt1.Data.Length + 1;
2675 			else
2676 				return (uint)dbt1.Data.Length;
2677 		}
2678 
SetUpEnvAndTxn(string home, out DatabaseEnvironment env, out Transaction txn)2679 		public void SetUpEnvAndTxn(string home,
2680 		    out DatabaseEnvironment env, out Transaction txn)
2681 		{
2682 			DatabaseEnvironmentConfig envConfig =
2683 				new DatabaseEnvironmentConfig();
2684 			envConfig.Create = true;
2685 			envConfig.UseTxns = true;
2686 			envConfig.UseMPool = true;
2687 			env = DatabaseEnvironment.Open(home, envConfig);
2688 			txn = env.BeginTransaction();
2689 		}
2690 
OpenBtreeDB(DatabaseEnvironment env, Transaction txn, string dbFileName, out BTreeDatabase db)2691 		public void OpenBtreeDB(DatabaseEnvironment env,
2692 		    Transaction txn, string dbFileName,
2693 		    out BTreeDatabase db)
2694 		{
2695 			BTreeDatabaseConfig dbConfig =
2696 			    new BTreeDatabaseConfig();
2697 			dbConfig.Creation = CreatePolicy.IF_NEEDED;
2698 			if (env != null)
2699 			{
2700 				dbConfig.Env = env;
2701 				dbConfig.NoMMap = false;
2702 				db = BTreeDatabase.Open(dbFileName, dbConfig, txn);
2703 			}
2704 			else
2705 			{
2706 				db = BTreeDatabase.Open(dbFileName, dbConfig);
2707 			}
2708 		}
2709 
GetMultipleDB( string filename, string dbname, BTreeDatabaseConfig cfg)2710                 private BTreeDatabase GetMultipleDB(
2711                     string filename, string dbname, BTreeDatabaseConfig cfg) {
2712                         BTreeDatabase ret;
2713                         DatabaseEntry data, key;
2714 
2715                         ret = BTreeDatabase.Open(filename, dbname, cfg);
2716                         key = null;
2717                         if (cfg.UseRecordNumbers) {
2718                                 /*
2719                                  * Dups aren't allowed with record numbers, so
2720                                  * we have to put different data.  Also, record
2721                                  * numbers start at 1, so we do too, which makes
2722                                  * checking results easier.
2723                                  */
2724                                 for (int i = 1; i < 100; i++) {
2725                                         key = new DatabaseEntry(
2726                                             BitConverter.GetBytes(i));
2727                                         data = new DatabaseEntry(
2728                                             BitConverter.GetBytes(i));
2729                                         ret.Put(key, data);
2730                                 }
2731 
2732                                 key = new DatabaseEntry(
2733                                     BitConverter.GetBytes(100));
2734                                 data = new DatabaseEntry();
2735                                 data.Data = new byte[111];
2736                                 for (int i = 0; i < 111; i++)
2737                                         data.Data[i] = (byte)i;
2738                                         ret.Put(key, data);
2739                         } else {
2740                                 for (int i = 0; i < 100; i++) {
2741                                         if (i % 10 == 0)
2742                                         key = new DatabaseEntry(
2743                                             BitConverter.GetBytes(i));
2744                                         data = new DatabaseEntry(
2745                                             BitConverter.GetBytes(i));
2746                                         /* Don't put nulls into the db. */
2747                                         Assert.IsFalse(key == null);
2748                                         Assert.IsFalse(data == null);
2749                                         ret.Put(key, data);
2750                                 }
2751 
2752                                 if (cfg.Duplicates == DuplicatesPolicy.UNSORTED) {
2753                                         /* Add in duplicates to check GetBothMultiple */
2754                                         key = new DatabaseEntry(
2755                                             BitConverter.GetBytes(100));
2756                                         data = new DatabaseEntry(
2757                                             BitConverter.GetBytes(100));
2758                                         for (int i = 0; i < 10; i++)
2759                                                 ret.Put(key, data);
2760 
2761                                         /*
2762                                          * Add duplicates to check GetMultiple
2763                                          * with given buffer size.
2764                                          */
2765                                         for (int i = 101; i < 1024; i++) {
2766                                                 key = new DatabaseEntry(
2767                                                     BitConverter.GetBytes(101));
2768                                                 data = new DatabaseEntry(
2769                                                     BitConverter.GetBytes(i));
2770                                                 ret.Put(key, data);
2771                                         }
2772 
2773                                         key = new DatabaseEntry(
2774                                             BitConverter.GetBytes(102));
2775                                         data = new DatabaseEntry();
2776                                         data.Data = new byte[112];
2777                                         for (int i = 0; i < 112; i++)
2778 			                     data.Data[i] = (byte)i;
2779                                         ret.Put(key, data);
2780                                 }
2781                         }
2782 	               return ret;
2783                 }
2784 
Confirm(XmlElement xmlElem, BTreeDatabase btreeDB, bool compulsory)2785 		public static void Confirm(XmlElement xmlElem,
2786 		    BTreeDatabase btreeDB, bool compulsory)
2787 		{
2788 			DatabaseTest.Confirm(xmlElem, btreeDB, compulsory);
2789 			Configuration.ConfirmDuplicatesPolicy(xmlElem,
2790 			    "Duplicates", btreeDB.Duplicates, compulsory);
2791 			Configuration.ConfirmUint(xmlElem, "MinKeysPerPage",
2792 			    btreeDB.MinKeysPerPage, compulsory);
2793 			/*
2794 			 * BTreeDatabase.RecordNumbers is the value of
2795 			 * BTreeDatabaseConfig.UseRecordNumbers.
2796 			 */
2797 			Configuration.ConfirmBool(xmlElem, "UseRecordNumbers",
2798 			    btreeDB.RecordNumbers, compulsory);
2799 			/*
2800 			 * BTreeDatabase.ReverseSplit is the value of
2801 			 * BTreeDatabaseConfig.NoReverseSplitting.
2802 			 */
2803 			Configuration.ConfirmBool(xmlElem, "NoReverseSplitting",
2804 			    btreeDB.ReverseSplit, compulsory);
2805 			Assert.AreEqual(DatabaseType.BTREE, btreeDB.Type);
2806 			string type = btreeDB.ToString();
2807 			Assert.IsNotNull(type);
2808 		}
2809 	}
2810 }
2811 
2812