context: /*-
   * See the file LICENSE for redistribution information.
   *
   * Copyright (c) 2009, 2014 Oracle and/or its affiliates.  All rights reserved.
   *
   */
  using System;
  using System.Collections;
  using System.Collections.Generic;
  using System.Diagnostics;
  using System.IO;
  using System.Text;
  using System.Threading;
  using System.Xml;
  using NUnit.Framework;
  using BerkeleyDB;
  
  namespace CsharpAPITest
  {
      class BackupWriter : IBackup {
          FileStream f;
          public int Close(string dbname) {
              f.Close();
              return 0;
          }
          public int Open(string dbname, string target) {
              string path = Path.Combine(target, dbname);
              f = new FileStream(path, FileMode.Create);
              return 0;
          }
          public int Write(byte[] data, long offset, int count) {
              f.Seek(offset, SeekOrigin.Begin);
              f.Write(data, 0, count);
              return 0;
          }
      }
  	[TestFixture]
  	public class DatabaseEnvironmentTest : CSharpTestFixture
  	{
  
  		private DatabaseEnvironment testBeginTransactionEnv;
  		private BTreeDatabase testBeginTransactionDB;
  
  		private DatabaseEnvironment testCheckpointEnv;
  		private BTreeDatabase testCheckpointDB;
  
  		private DatabaseEnvironment testDetectDeadlocksEnv;
  		private BTreeDatabase testDetectDeadlocksDB;
  
  		private DatabaseEnvironment testFailCheckEnv;
  
  		private EventWaitHandle signal;
  
  		[TestFixtureSetUp]
  		public void SetUp()
  		{
  			testFixtureName = "DatabaseEnvironmentTest";
  			base.SetUpTestfixture();
  		}
  
  		[Test]
  		public void TestArchivableDatabaseFiles()
  		{
  			testName = "TestArchivableDatabaseFiles";
  			SetUpTest(true);
  			string dbFileName1 = testName + "1.db";
  			string dbFileName2 = testName + "2.db";
  
  			// Open an environment.
  			DatabaseEnvironmentConfig envConfig =
  			    new DatabaseEnvironmentConfig();
  			envConfig.AutoCommit = true;
  			envConfig.Create = true;
  			envConfig.UseMPool = true;
  			envConfig.UseLogging = true;
  			envConfig.UseTxns = true;
  			DatabaseEnvironment env = DatabaseEnvironment.Open(
  			    testHome, envConfig);
  
  			// Open two databases.
  			BTreeDatabaseConfig dbConfig =
  			    new BTreeDatabaseConfig();
  			dbConfig.Creation = CreatePolicy.IF_NEEDED;
  			dbConfig.Env = env;
  			BTreeDatabase db1 = BTreeDatabase.Open(dbFileName1, dbConfig);
  			db1.Close();
  			BTreeDatabase db2 = BTreeDatabase.Open(dbFileName2, dbConfig);
  			db2.Close();
  
  			/*
  			 * Get all database files name in the environment.
  			 * Two database file name should be returned and
  			 * the same as the ones when opening the databases.
  			 */
  			List<string> dbFiles = env.ArchivableDatabaseFiles(false);
  			Assert.AreEqual(2, dbFiles.Count);
  			Assert.IsTrue(dbFiles.Contains(dbFileName1));
  			Assert.IsTrue(dbFiles.Contains(dbFileName2));
  
  			/*
  			 * Get all database file's abosolute path in the
  			 * environment. Confirm those files exist.
  			 */
  			List<string> dbFilesPath = env.ArchivableDatabaseFiles(true);
  			Assert.IsTrue(File.Exists(dbFilesPath[0]));
  			Assert.IsTrue(File.Exists(dbFilesPath[1]));
  
  			env.Close();
  		}
  
  		[Test]
  		public void TestArchivableLogFiles()
  		{
  			testName = "TestArchivableLogFiles";
  			SetUpTest(true);
  			string dbFileName = testName + ".db";
  
  			// Open an environment.
  			DatabaseEnvironmentConfig envConfig =
  			    new DatabaseEnvironmentConfig();
  			envConfig.AutoCommit = true;
  			envConfig.Create = true;
  			envConfig.UseMPool = true;
  			envConfig.UseLogging = true;
  			envConfig.UseTxns = true;
  			DatabaseEnvironment env = DatabaseEnvironment.Open(
  			    testHome, envConfig);
  
  			// Open a databases.
  			BTreeDatabaseConfig dbConfig =
  			    new BTreeDatabaseConfig();
  			dbConfig.Creation = CreatePolicy.IF_NEEDED;
  			dbConfig.Env = env;
  			BTreeDatabase db = BTreeDatabase.Open(
  			    dbFileName, dbConfig);
  
  			/*
  			 * Put 1000 records into the database to generate
  			 * more than one log files.
  			 */
  			byte[] byteArr = new byte[1024];
  			for (int i = 0; i < 1000; i++)
  				db.Put(new DatabaseEntry(
  				    BitConverter.GetBytes(i)),
  				    new DatabaseEntry(byteArr));
  
  			db.Close();
  
  			List<string> logFiles = env.ArchivableLogFiles(false);
  
  			List<string> logFilesPath =
  			    env.ArchivableLogFiles(true);
  			for (int i = 0; i < logFilesPath.Count; i++)
  				Assert.IsTrue(File.Exists(logFilesPath[i]));
  
  			env.Close();
  		}
  
          [Test]
          public void TestBackup() {
              testName = "TestBackup";
              SetUpTest(true);
              string dbFileName = testName + ".db";
  
              // Open an environment.
              DatabaseEnvironmentConfig envConfig =
                  new DatabaseEnvironmentConfig();
              envConfig.AutoCommit = true;
              envConfig.Create = true;
              envConfig.UseMPool = true;
              envConfig.UseLogging = true;
              envConfig.UseTxns = true;
              DatabaseEnvironment env = DatabaseEnvironment.Open(
                  testHome, envConfig);
  
              // Open a databases.
              BTreeDatabaseConfig dbConfig =
                  new BTreeDatabaseConfig();
              dbConfig.Creation = CreatePolicy.IF_NEEDED;
              dbConfig.Env = env;
              BTreeDatabase db = BTreeDatabase.Open(
                  dbFileName, dbConfig);
  
              /*
               * Put 1000 records into the database to generate
               * more than one log file.
               */
              byte[] byteArr = new byte[1024];
              for (int i = 0; i < 1000; i++)
                  db.Put(new DatabaseEntry(
                      BitConverter.GetBytes(i)),
                      new DatabaseEntry(byteArr));
  
              db.Close();
  
              /* Set up the target directory for the backup. */
              string target = testFixtureHome + "/" + testName + "_backup";
              Configuration.ClearDir(target);
              
              BackupOptions opt = new BackupOptions();
              opt.Creation = CreatePolicy.ALWAYS;
              env.Backup(target, opt);
              Assert.Greater(Directory.GetFiles(target).Length, 0);
              Directory.Delete(target, true);
              env.Close();
          }
  
          [Test]
          public void TestBackupCallbacks() {
              testName = "TestBackupCallbacks";
              SetUpTest(true);
              string dbFileName = testName + ".db";
  
              // Open an environment.
              DatabaseEnvironmentConfig envConfig =
                  new DatabaseEnvironmentConfig();
              envConfig.AutoCommit = true;
              envConfig.Create = true;
              envConfig.UseMPool = true;
              envConfig.UseLogging = true;
              envConfig.UseTxns = true;
              DatabaseEnvironment env = DatabaseEnvironment.Open(
                  testHome, envConfig);
  
              // Open a databases.
              BTreeDatabaseConfig dbConfig =
                  new BTreeDatabaseConfig();
              dbConfig.Creation = CreatePolicy.IF_NEEDED;
              dbConfig.Env = env;
              BTreeDatabase db = BTreeDatabase.Open(
                  dbFileName, dbConfig);
  
              /*
               * Populate the database but keep it small, we're going to do a 
               * byte-by-byte comparison at the end.
               */
              byte[] byteArr = new byte[1024];
              for (int i = 0; i < 10; i++)
                  db.Put(new DatabaseEntry(
                      BitConverter.GetBytes(i)),
                      new DatabaseEntry(byteArr));
  
              db.Close();
  
              /* Set up the target directory for the backup. */
              string target = testFixtureHome + "/" + testName + "_backup";
              Configuration.ClearDir(target);
              
              BackupWriter backup = new BackupWriter();
              env.BackupHandler = backup;
  
              BackupOptions opt = new BackupOptions();
              opt.Creation = CreatePolicy.ALWAYS;
              env.Backup(target, opt);
              Assert.Greater(Directory.GetFiles(target).Length, 0);
              
              /* Check that our callbacks wrote the file correctly. */
              FileStream orig = new FileStream(Path.Combine(testHome, dbFileName), FileMode.Open, FileAccess.Read);
              FileStream bak = new FileStream(Path.Combine(target, dbFileName), FileMode.Open, FileAccess.Read);
              int orig_byte, bak_byte;
              do {
                  orig_byte = orig.ReadByte();
                  bak_byte = bak.ReadByte();
                  Assert.AreEqual(orig_byte, bak_byte);
              } while (orig_byte != -1 && bak_byte != -1);
              orig.Close();
              bak.Close();
              Directory.Delete(target, true);
              env.Close();
          }
  
          [Test]
          public void TestBackupDatabase() {
              testName = "TestBackupDatabase";
              SetUpTest(true);
              string dbFileName = testName + ".db";
  
              // Open an environment.
              DatabaseEnvironmentConfig envConfig =
                  new DatabaseEnvironmentConfig();
              envConfig.AutoCommit = true;
              envConfig.Create = true;
              envConfig.UseMPool = true;
              envConfig.UseLogging = true;
              envConfig.UseTxns = true;
              DatabaseEnvironment env = DatabaseEnvironment.Open(
                  testHome, envConfig);
  
              // Open a databases.
              BTreeDatabaseConfig dbConfig =
                  new BTreeDatabaseConfig();
              dbConfig.Creation = CreatePolicy.IF_NEEDED;
              dbConfig.Env = env;
              BTreeDatabase db = BTreeDatabase.Open(
                  dbFileName, dbConfig);
              
              /*
               * Put 1000 records into the database to generate
               * more than one log file.
               */
              byte[] byteArr = new byte[1024];
              for (int i = 0; i < 1000; i++)
                  db.Put(new DatabaseEntry(
                      BitConverter.GetBytes(i)),
                      new DatabaseEntry(byteArr));
              
              db.Close();
  
              /* Set up the target directory for the backup. */
              string target = testFixtureHome + "/" + testName + "_backup";
              Configuration.ClearDir(target);
              
              /* We should only copy one file, the database. */
              env.BackupDatabase(target, dbFileName, true);
              Assert.AreEqual(1, Directory.GetFiles(target).Length);
              
              Directory.Delete(target, true);
              env.Close();
          }
  
          [Test]
          public void TestBackupOptions() {
              testName = "TestBackupOptions";
              SetUpTest(true);
              
              // Open an environment.
              DatabaseEnvironmentConfig envConfig =
                  new DatabaseEnvironmentConfig();
              envConfig.AutoCommit = true;
              envConfig.Create = true;
              envConfig.UseMPool = true;
              envConfig.UseLogging = true;
              envConfig.UseTxns = true;
              DatabaseEnvironment env = DatabaseEnvironment.Open(
                  testHome, envConfig);
  
              /* 
               * Check that we can get and set backup options successfully.  There
               * are other tests to check that the backup options are obeyed.
               */
              env.BackupBufferSize = (uint)1024;
              Assert.AreEqual((uint)1024, env.BackupBufferSize);
              
              env.BackupReadCount = (uint)4096;
              Assert.AreEqual((uint)4096, env.BackupReadCount);
              
              env.BackupReadSleepDuration = (uint)1000;
              Assert.AreEqual((uint)1000, env.BackupReadSleepDuration);
              
              env.BackupWriteDirect = true;
              Assert.IsTrue(env.BackupWriteDirect);
          }
  
  		[Test]
  		public void TestBeginCDSGroup()
  		{
  			testName = "TestBeginCDSGroup";
  			SetUpTest(true);
  
  			DatabaseEnvironmentConfig cfg =
  			    new DatabaseEnvironmentConfig();
  			cfg.Create = true;
  			cfg.UseCDB = true;
  			cfg.UseMPool = true;
  			DatabaseEnvironment env = DatabaseEnvironment.Open(testHome, cfg);
  			Transaction txn = env.BeginCDSGroup();
  			BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
  			dbConfig.Creation = CreatePolicy.IF_NEEDED;
  			dbConfig.Env = env;
  			BTreeDatabase db = BTreeDatabase.Open(
  			    testName + ".db", dbConfig, txn);
  			db.Put(new DatabaseEntry(
  			    ASCIIEncoding.ASCII.GetBytes("key")),
  			    new DatabaseEntry(
  			    ASCIIEncoding.ASCII.GetBytes("data")), txn);
  			db.Close();
  			txn.Commit();
  			env.Close();
  		}
  
  		[Test]
  		public void TestBeginTransaction()
  		{
  			testName = "TestBeginTransaction";
  			SetUpTest(true);
  
  			// Open an environment.
  			DatabaseEnvironmentConfig cfg =
  			    new DatabaseEnvironmentConfig();
  			cfg.Create = true;
  			cfg.UseTxns = true;
  			cfg.UseMPool = true;
  			cfg.UseLogging = true;
  			cfg.UseLocking = true;
  			cfg.NoLocking = false;
  			cfg.FreeThreaded = true;
  			testBeginTransactionEnv = DatabaseEnvironment.Open(testHome, cfg);
  			testBeginTransactionEnv.DeadlockResolution = DeadlockPolicy.OLDEST;
  
  			// Open btree database.
  			BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
  			dbConfig.AutoCommit = true;
  			dbConfig.Creation = CreatePolicy.IF_NEEDED;
  			dbConfig.Env = testBeginTransactionEnv;
  			dbConfig.Duplicates = DuplicatesPolicy.NONE;
  			dbConfig.FreeThreaded = true;
  			testBeginTransactionDB = BTreeDatabase.Open(
  			    testName + ".db", dbConfig);
  
  			testBeginTransactionDB.Put(
  			    new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key")),
  			    new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data")));
  
  			// Begin two threads to run dead lock detection.
  			Thread thread1 = new Thread(new ThreadStart(
  			    DeadLockThreadWithLockTimeOut));
  			Thread thread2 = new Thread(new ThreadStart(
  			    DeadLockThreadWithTxnTimeout));
  			signal = new EventWaitHandle(false, EventResetMode.ManualReset);
  			thread1.Start();
  			thread2.Start();
  			Thread.Sleep(1000);
  			signal.Set();
  			thread1.Join();
  			thread2.Join();
  
  			// Close all.
  			testBeginTransactionDB.Close();
  			testBeginTransactionEnv.Close();
  		}
  
  		public void DeadLockThreadWithLockTimeOut()
  		{
  			// Configure and begin a transaction.
  			TransactionConfig txnConfig = new TransactionConfig();
  			txnConfig.LockTimeout = 5000;
  			txnConfig.Name = "DeadLockThreadWithLockTimeOut";
  			Transaction txn = 
  			    testBeginTransactionEnv.BeginTransaction(txnConfig, null);
  			try
  			{
  				testBeginTransactionDB.Put(
  				    new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key")),
  				    new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data")));
  				signal.WaitOne();
  				testBeginTransactionDB.Put(
  				    new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("newkey")),
  				    new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("newdata")),
  				    txn);
  				txn.Commit();
  			}
  			catch (DeadlockException)
  			{
  				try
  				{
  					txn.Abort();
  				}
  				catch (DatabaseException)
  				{
  					throw new TestException();
  				}
  			}
  			catch (DatabaseException)
  			{
  				try
  				{
  					txn.Abort();
  				}
  				catch (DatabaseException)
  				{
  					throw new TestException();
  				}
  			}
  		}
  
  		public void DeadLockThreadWithTxnTimeout()
  		{
  			// Configure and begin a transaction.
  			TransactionConfig txnConfig = new TransactionConfig();
  			txnConfig.TxnTimeout = 5000;
  			txnConfig.Name = "DeadLockThreadWithTxnTimeout";
  			Transaction txn =
  			    testBeginTransactionEnv.BeginTransaction(txnConfig, null);
  			try
  			{
  				testBeginTransactionDB.Put(
  				    new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key")),
  				    new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data")));
  				signal.WaitOne();
  				testBeginTransactionDB.Put(
  				    new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("newkey")),
  				    new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("newdata")),
  				    txn);
  				txn.Commit();
  			}
  			catch (DeadlockException)
  			{
  				try
  				{
  					txn.Abort();
  				}
  				catch (DatabaseException)
  				{
  					throw new TestException();
  				}
  			}
  			catch (DatabaseException)
  			{
  				try
  				{
  					txn.Abort();
  				}
  				catch (DatabaseException)
  				{
  					throw new TestException();
  				}
  			}
  		}
  
  		[Test]
  		public void TestBlob()
  		{
  			testName = "TestBlob";
  			SetUpTest(true);
  
  			DatabaseEnvironmentConfig envConfig =
  			    new DatabaseEnvironmentConfig();
  			envConfig.AutoCommit = true;
  			envConfig.Create = true;
  			envConfig.UseMPool = true;
  			envConfig.UseLogging = true;
  			envConfig.UseTxns = true;
  
  			// Not set the blob file directory when enabling blob.
  			envConfig.BlobThreshold = 10485760;
  			DatabaseEnvironment env = DatabaseEnvironment.Open(
  			    testHome, envConfig);
  			Assert.AreEqual(null, env.BlobDir);
  			Assert.AreEqual(10485760, env.BlobThreshold);
  			env.Close();
  
  			Configuration.ClearDir(testHome);
  
  			// Set the blob file directory with an empty string.
  			envConfig.BlobDir = "";
  			env = DatabaseEnvironment.Open(testHome, envConfig);
  			Assert.AreEqual("", env.BlobDir);
  			Assert.AreEqual(10485760, env.BlobThreshold);
  			env.Close();
  
  			Configuration.ClearDir(testHome);
  
  			// Set the blob file directory with a non-emptry
  			// string.
  			envConfig.BlobDir = "BLOBDIR";
  			env = DatabaseEnvironment.Open(testHome, envConfig);
  			Assert.AreEqual("BLOBDIR", env.BlobDir);
  			Assert.AreEqual(10485760, env.BlobThreshold);
  			env.Close();
  		}
  
  		[Test]
  		public void TestCheckpoint()
  		{
  			testName = "TestCheckpoint";
  			SetUpTest(true);
  
  			// Open an environment.
  			DatabaseEnvironmentConfig cfg =
  			    new DatabaseEnvironmentConfig();
  			cfg.Create = true;
  			cfg.UseTxns = true;
  			cfg.UseMPool = true;
  			cfg.UseLogging = true;
  			cfg.UseLocking = true;
  			cfg.NoLocking = false;
  			cfg.FreeThreaded = true;
  			testCheckpointEnv = DatabaseEnvironment.Open(testHome, cfg);
  
  			// Open btree database.
  			BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
  			dbConfig.AutoCommit = true;
  			dbConfig.Creation = CreatePolicy.IF_NEEDED;
  			dbConfig.Env = testCheckpointEnv;
  			dbConfig.FreeThreaded = true;
  			testCheckpointDB = BTreeDatabase.Open(testName + ".db", dbConfig);
  
  			// Run a thread to put records into database.
  			Thread thread1 = new Thread(new ThreadStart(PutRecordsThread));
  
  			/*
  			 * Run a thread to do checkpoint periodically and
  			 * finally do a checkpoint to flush all in memory pool
  			 * to log files.
  			 */
  			Thread thread2 = new Thread(new ThreadStart(CheckpointThread));
  
  			thread1.Start();
  			thread2.Start();
  			thread1.Join();
  			thread2.Join();
  
  			// Close all.
  			testCheckpointDB.Close();
  			testCheckpointEnv.Close();
  		}
  
  		public void PutRecordsThread()
  		{
  			Transaction txn = testCheckpointEnv.BeginTransaction();
  			byte[] byteArr = new byte[1024];
  			for (int i = 0; i < 1000; i++)
  				testCheckpointDB.Put(
  				    new DatabaseEntry(BitConverter.GetBytes(i)),
  				    new DatabaseEntry(byteArr), txn);
  			txn.Commit();
  		}
  
  		public void CheckpointThread()
  		{
  			uint bytes = 64;
  			uint minutes = 1;
  			uint count = 1;
  			while (count < 3)
  			{
  				testCheckpointEnv.Checkpoint(bytes, minutes);
  				count++;
  			}
  			Thread.Sleep(500);
  			testCheckpointEnv.Checkpoint();
  		}
  
  		[Test]
  		public void TestClose()
  		{
  			testName = "TestClose";
  			SetUpTest(true);
  
  			DatabaseEnvironmentConfig cfg =
  			    new DatabaseEnvironmentConfig();
  			cfg.Create = true;
  			DatabaseEnvironment env = DatabaseEnvironment.Open(
  			    testHome, cfg);
  			env.Close();
  		}
  
  		[Test]
  		public void TestConfigAll()
  		{
  			testName = "TestConfigAll";
  			SetUpTest(true);
  
  			XmlElement xmlElem = Configuration.TestSetUp(
  			    testFixtureName, testName);
  
  			/*
  			 * Open a new environment with all properties,
  			 * fields and subsystems configured.
  			 */
  			DatabaseEnvironmentConfig envConig =
  			    new DatabaseEnvironmentConfig();
  			Config(xmlElem, ref envConig, true, true, true,
  			    true, true, true);
  
  			// Configure with methods.
  			ReplicationHostAddress address =
  			    new ReplicationHostAddress("127.0.0.0", 11111);
  			envConig.RepSystemCfg.Clockskew(102, 100);
  			envConig.RepSystemCfg.RetransmissionRequest(10, 100);
  			envConig.RepSystemCfg.TransmitLimit(1, 1024);
  
  			// Open the environment.
  			DatabaseEnvironment env = DatabaseEnvironment.Open(
  			    testHome, envConig);
  
  			// Confirm environment status with its configuration.
  			Confirm(xmlElem, env, true, true, true, true, true, true);
  
  			// Print statistics of the current environment.
  			env.Msgfile = testHome + "/" + testName+ ".log";
  			env.PrintStats(true, true);
  
  			// Print statistics of all subsytems.
  			env.PrintSubsystemStats(true, true);
  
  			env.Close();
  		}
  
  		[Test]
  		public void TestDeadlockPolicy()
  		{
  			testName = "TestDeadlockPolicy";
  			SetUpTest(true);
  
  			DetectDeadlockPolicy(testHome + "_DEFAULT",
  			    DeadlockPolicy.DEFAULT);
  
  			DetectDeadlockPolicy(testHome + "_EXPIRE",
  			    DeadlockPolicy.EXPIRE);
  			DetectDeadlockPolicy(testHome + "_MAX_LOCKS",
  			    DeadlockPolicy.MAX_LOCKS);
  			DetectDeadlockPolicy(testHome + "_MAX_WRITE",
  			    DeadlockPolicy.MAX_WRITE);
  			DetectDeadlockPolicy(testHome + "_MIN_LOCKS",
  			    DeadlockPolicy.MIN_LOCKS);
  			DetectDeadlockPolicy(testHome + "_MIN_WRITE",
  			    DeadlockPolicy.MIN_WRITE);
  			DetectDeadlockPolicy(testHome + "_OLDEST",
  			    DeadlockPolicy.OLDEST);
  			DetectDeadlockPolicy(testHome + "_RANDOM",
  			    DeadlockPolicy.RANDOM);
  			DetectDeadlockPolicy(testHome + "_YOUNGEST",
  			    DeadlockPolicy.YOUNGEST);
  		}
  
  		public void DetectDeadlockPolicy(
  		    string home, DeadlockPolicy deadlock)
  		{
  			Configuration.ClearDir(home);
  			DatabaseEnvironmentConfig envConfig =
  			    new DatabaseEnvironmentConfig();
  			envConfig.Create = true;
  			envConfig.UseLocking = true;
  			envConfig.UseLogging = true;
  			envConfig.UseMPool = true;
  			envConfig.UseTxns = true;
  			DatabaseEnvironment env = DatabaseEnvironment.Open(
  			    home, envConfig);
  			env.DeadlockResolution = deadlock;
  			Assert.AreEqual(deadlock, env.DeadlockResolution);
  			env.DetectDeadlocks(deadlock);
  			env.Close();
  		}
  
  		[Test]
  		public void TestDetectDeadlocks()
  		{
  			testName = "TestDetectDeadlocks";
  			SetUpTest(true);
  
  			// Open an environment.
  			DatabaseEnvironmentConfig cfg =
  			    new DatabaseEnvironmentConfig();
  			cfg.Create = true;
  			cfg.UseTxns = true;
  			cfg.UseMPool = true;
  			cfg.UseLogging = true;
  			cfg.UseLocking = true;
  			cfg.FreeThreaded = true;
  			testDetectDeadlocksEnv = DatabaseEnvironment.Open(
  			    testHome, cfg);
  
  			// Open btree database.
  			BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
  			dbConfig.AutoCommit = true;
  			dbConfig.Creation = CreatePolicy.IF_NEEDED;
  			dbConfig.Env = testDetectDeadlocksEnv;
  			dbConfig.Duplicates = DuplicatesPolicy.NONE;
  			dbConfig.FreeThreaded = true;
  			testDetectDeadlocksDB = BTreeDatabase.Open(
  			    testName + ".db", dbConfig);
  
  			// Put one record("key", "data") into database.
  			testDetectDeadlocksDB.Put(
  			    new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key")),
  			    new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data")));
  
  			// Begin two threads to read and write record.
  			Thread thread1 = new Thread(new ThreadStart(ReadAndPutRecordThread));
  			Thread thread2 = new Thread(new ThreadStart(ReadAndPutRecordThread));
  			signal = new EventWaitHandle(false, EventResetMode.ManualReset);
  			thread1.Start();
  			thread2.Start();
  
  			// Give enough time for threads to read record.
  			Thread.Sleep(1000);
  
  			/*
  			 * Let the two threads apply for write lock
  			 * synchronously.
  			 */
  			signal.Set();
  
  			// Confirm that there is deadlock in the environment.
  			Thread.Sleep(1000);
  			uint deadlockNum = testDetectDeadlocksEnv.DetectDeadlocks(
  			    DeadlockPolicy.DEFAULT);
  			Assert.Less(0, deadlockNum);
  
  			thread1.Join();
  			thread2.Join();
  
  			// Close all.
  			testDetectDeadlocksDB.Close(false);
  			testDetectDeadlocksEnv.Close();
  		}
  
  		public void ReadAndPutRecordThread()
  		{
  			Transaction txn =
  			    testDetectDeadlocksEnv.BeginTransaction();
  			try
  			{
  				testDetectDeadlocksDB.GetBoth(
  				    new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key")),
  				    new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data")), txn);
  				signal.WaitOne();
  				testDetectDeadlocksDB.Put(
  				    new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("newKey")),
  				    new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("newData")),
  				    txn);
  				txn.Commit();
  			}
  			catch (DeadlockException)
  			{
  				txn.Abort();
  			}
  		}
  
  		[Test]
  		public void TestEncryption() 
  		{
  			testName = "TestEncryption";
  			SetUpTest(true);
  
  			// Open an encrypted environment.
  			DatabaseEnvironmentConfig envCfg =
  			    new DatabaseEnvironmentConfig();
  			envCfg.Create = true;
  			envCfg.UseMPool = true;
  			envCfg.UseLogging = true;
  			envCfg.UseTxns = true;
  			envCfg.SetEncryption("bdb", EncryptionAlgorithm.AES);
  			DatabaseEnvironment env =
  			DatabaseEnvironment.Open(testHome, envCfg);
  			Transaction txn = env.BeginTransaction();
  
  			// Open a non-encrypted database in the environment.
  			BTreeDatabaseConfig dbCfg =
  			    new BTreeDatabaseConfig();
  			dbCfg.Creation = CreatePolicy.IF_NEEDED;
  			dbCfg.Env = env;
  			BTreeDatabase db1 = BTreeDatabase.Open(
  			    testName + "1.db", dbCfg, txn);
  			Assert.IsFalse(db1.Encrypted);
  			for (int i = 0; i < 10; i++)
  				db1.Put(new DatabaseEntry(
  				    BitConverter.GetBytes(i)),
  				    new DatabaseEntry(
  				    BitConverter.GetBytes(i)), txn);
  
  			// Open an encrypted database in the environment.
  			dbCfg.Encrypted = true;
  			BTreeDatabase db2 = BTreeDatabase.Open(
  			    testName + "2.db", dbCfg, txn);
  			Assert.IsTrue(db2.Encrypted);
  			for (int i = 0; i < 10; i++)
  			db2.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
  			    new DatabaseEntry(BitConverter.GetBytes(i)), txn);
  
  			// Close all.
  			txn.Commit();
  			db1.Close();
  			db2.Close();
  			env.Close();
  
  			// Verify the environment is encrypted.
  			DatabaseEnvironmentConfig verifyEnvCfg =
  			    new DatabaseEnvironmentConfig();
  			verifyEnvCfg.Create = true;
  			verifyEnvCfg.UseMPool = true;
  			verifyEnvCfg.UseLogging = true;
  			verifyEnvCfg.UseTxns = true;
  			try {
  				env = DatabaseEnvironment.Open(
  				    testHome, verifyEnvCfg);
  				// Do nothing
  				env.Close();
  				throw new TestException();
  			} catch (DatabaseException) {
  			}
  
  			// Verify the non-encrypted database is not encrypted.
  			BTreeDatabaseConfig verifyDbCfg =
  			    new BTreeDatabaseConfig();
  			verifyDbCfg.Creation = CreatePolicy.IF_NEEDED;
  
  			using (db1 = BTreeDatabase.Open(
  			    testHome + "/" + testName + "1.db", verifyDbCfg)) {
  
gt: 				for (int i = 0; i < 10; i++)