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