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