context: /*-
   * See the file LICENSE for redistribution information.
   *
   * Copyright (c) 2009, 2015 Oracle and/or its affiliates.  All rights reserved.
   *
   */
  using System;
  using System.Collections;
  using System.Collections.Generic;
  using System.IO;
  using System.Text;
  using System.Threading;
  using System.Xml;
  using NUnit.Framework;
  using BerkeleyDB;
  
  namespace CsharpAPITest
  {
  	[TestFixture]
  	public class SecondaryBTreeDatabaseTest : CSharpTestFixture
  	{
  
  		[TestFixtureSetUp]
  		public void SetUpTestFixture()
  		{
  			testFixtureName = "SecondaryBTreeDatabaseTest";
  			base.SetUpTestfixture();
  		}
  
  		[Test]
  		public void TestOpen()
  		{
  			testName = "TestOpen";
  			SetUpTest(true);
  			string dbFileName = testHome + "/" + testName + ".db";
  			string dbSecFileName = testHome + "/" +
  			    testName + "_sec.db";
  
  			XmlElement xmlElem = Configuration.TestSetUp(
  			    testFixtureName, testName);
  
  			// Open a primary btree database.
  			BTreeDatabaseConfig btreeDBConfig =
  			    new BTreeDatabaseConfig();
  			btreeDBConfig.Creation = CreatePolicy.IF_NEEDED;
  			BTreeDatabase btreeDB = BTreeDatabase.Open(
  			    dbFileName, btreeDBConfig);
  
  			// Open a secondary btree database.
  			SecondaryBTreeDatabaseConfig secDBConfig =
  			    new SecondaryBTreeDatabaseConfig(btreeDB, null);
  
  			SecondaryBTreeDatabaseConfigTest.Config(xmlElem,
  			    ref secDBConfig, true);
  			SecondaryBTreeDatabase secDB =
  			   SecondaryBTreeDatabase.Open(dbSecFileName,
  			   secDBConfig);
  
  			// Confirm its flags configured in secDBConfig.
  			Confirm(xmlElem, secDB, true);
  
  			secDB.Close();
  			btreeDB.Close();
  		}
  
  		[Test]
  		public void TestCompare()
  		{
  			testName = "TestCompare";
  			SetUpTest(true);
  			string dbFileName = testHome + "/" + testName + ".db";
  
  			// Open a primary btree database.
  			BTreeDatabaseConfig btreeDBConfig =
  			    new BTreeDatabaseConfig();
  			btreeDBConfig.Creation = CreatePolicy.ALWAYS;
  			BTreeDatabase btreeDB = BTreeDatabase.Open(
  			    dbFileName, btreeDBConfig);
  
  			// Open a secondary btree database. 
  			SecondaryBTreeDatabaseConfig secBtreeDBConfig =
  			    new SecondaryBTreeDatabaseConfig(null, null);
  			secBtreeDBConfig.Primary = btreeDB;
  			secBtreeDBConfig.Compare =
  			    new EntryComparisonDelegate(
  			    SecondaryEntryComparison);
  			secBtreeDBConfig.KeyGen =
  			    new SecondaryKeyGenDelegate(SecondaryKeyGen);
  			SecondaryBTreeDatabase secDB =
  			    SecondaryBTreeDatabase.Open(
  			    dbFileName, secBtreeDBConfig);
  
  			/*
  			 * Get the compare function set in the configuration 
  			 * and run it in a comparison to see if it is alright.
  			 */
  			EntryComparisonDelegate cmp =
  			    secDB.Compare;
  			DatabaseEntry dbt1, dbt2;
  			dbt1 = new DatabaseEntry(
  			    BitConverter.GetBytes((int)257));
  			dbt2 = new DatabaseEntry(
  			    BitConverter.GetBytes((int)255));
  			Assert.Less(0, cmp(dbt1, dbt2));
  
  
  			for (int i = 0; i < 1000; i++)
  				btreeDB.Put(new DatabaseEntry(
  				    BitConverter.GetBytes(i)), new DatabaseEntry(
  				    BitConverter.GetBytes(i)));
  
  			secDB.Close();
  			btreeDB.Close();
  		}
  
  		[Test]
  		public void TestDupCompare() 
  		{
  			testName = "TestDupCompare";
  			SetUpTest(true);
  			string dbFileName = testHome + "/" + testName + ".db";
  
  			BTreeDatabaseConfig cfg =
  			    new BTreeDatabaseConfig();
  			cfg.Creation = CreatePolicy.ALWAYS;
  			BTreeDatabase pDb = BTreeDatabase.Open(
  			    dbFileName, "p", cfg);
  
  			SecondaryBTreeDatabaseConfig sCfg =
  			    new SecondaryBTreeDatabaseConfig(pDb,
  			    new SecondaryKeyGenDelegate(SecondaryKeyGen));
  			sCfg.Creation = CreatePolicy.IF_NEEDED;
  
  			DatabaseEntry dbt1, dbt2;
  			dbt1 = new DatabaseEntry(
  			    BitConverter.GetBytes((Int32)1));
  			dbt2 = new DatabaseEntry(
  			    BitConverter.GetBytes((Int64)4294967297));
  
  			// Do not set the duplicate comparison delegate.
  			using (SecondaryBTreeDatabase sDb =
  			    SecondaryBTreeDatabase.Open(dbFileName, "s1", sCfg)) {
  				try {
  					int ret = sDb.DupCompare(dbt1, dbt2);
  					throw new TestException();
  				} catch (NullReferenceException) {
  				}
  			}
  
  			sCfg.DuplicateCompare = new EntryComparisonDelegate(
  			    SecondaryEntryComparison);
  			using (SecondaryBTreeDatabase sDb =
  			    SecondaryBTreeDatabase.Open(dbFileName, "s2", sCfg)) {
  				/*
  				 * Get the dup compare function set in the 
  				 * configuration and run it in a comparison to 
  				 * see if it is alright.
  				 */
  				int ret = 1 - BitConverter.ToInt32(
  				    BitConverter.GetBytes((Int64)4294967297), 0);
  
  				Assert.AreEqual(ret, sDb.DupCompare(dbt1, dbt2));
  			}
  			pDb.Close();
  		}
  
  		[Test]
  		public void TestDuplicates()
  		{
  			testName = "TestDuplicates";
  			SetUpTest(true);
  			string dbFileName = testHome + "/" + testName + ".db";
  			string dbSecFileName = testHome + "/" + testName
  			    + "_sec.db";
  
  			// Open a primary btree database.
  			BTreeDatabaseConfig btreeDBConfig =
  			    new BTreeDatabaseConfig();
  			btreeDBConfig.Creation = CreatePolicy.IF_NEEDED;
  			BTreeDatabase btreeDB = BTreeDatabase.Open(
  			    dbFileName, btreeDBConfig);
  
  			// Open a secondary btree database. 
  			SecondaryBTreeDatabaseConfig secBtreeDBConfig =
  			    new SecondaryBTreeDatabaseConfig(btreeDB, null);
  			secBtreeDBConfig.Creation = CreatePolicy.IF_NEEDED;
  			secBtreeDBConfig.Duplicates = DuplicatesPolicy.SORTED;
  			SecondaryBTreeDatabase secDB =
  			    SecondaryBTreeDatabase.Open(dbSecFileName,
  			    secBtreeDBConfig);
  			Assert.AreEqual(DuplicatesPolicy.SORTED, secDB.Duplicates);
  
  			secDB.Close();
  			btreeDB.Close();
  		}
  
  		[Test]
  		public void TestPrefixCompare()
  		{
  			testName = "TestPrefixCompare";
  			SetUpTest(true);
  			string dbFileName = testHome + "/" + testName + ".db";
  
  			// Open a primary btree database.
  			BTreeDatabaseConfig btreeDBConfig =
  			    new BTreeDatabaseConfig();
  			btreeDBConfig.Creation = CreatePolicy.ALWAYS;
  			BTreeDatabase btreeDB = BTreeDatabase.Open(
  			    dbFileName, btreeDBConfig);
  
  			// Open a secondary btree database. 
  			SecondaryBTreeDatabaseConfig secBtreeDBConfig =
  			    new SecondaryBTreeDatabaseConfig(btreeDB, null);
  			secBtreeDBConfig.Primary = btreeDB;
  			secBtreeDBConfig.Compare =
  			    new EntryComparisonDelegate(
  			    SecondaryEntryComparison);
  			secBtreeDBConfig.PrefixCompare =
  			    new EntryPrefixComparisonDelegate(
  			    SecondaryPrefixEntryComparison);
  			secBtreeDBConfig.KeyGen =
  			    new SecondaryKeyGenDelegate(
  			    SecondaryKeyGen);
  			SecondaryBTreeDatabase secDB =
  			    SecondaryBTreeDatabase.Open(
  			    dbFileName, secBtreeDBConfig);
  
  			/*
  			 * Get the prefix compare function set in the 
  			 * configuration and run it in a comparison to 
  			 * see if it is alright.
  			 */
  			EntryPrefixComparisonDelegate cmp =
  			    secDB.PrefixCompare;
  			DatabaseEntry dbt1, dbt2;
  			dbt1 = new DatabaseEntry(
  			    BitConverter.GetBytes((Int32)1));
  			dbt2 = new DatabaseEntry(
  			    BitConverter.GetBytes((Int64)4294967297));
  			Assert.AreEqual(5, cmp(dbt1, dbt2));
  
  			secDB.Close();
  			btreeDB.Close();
  		}
  
  		public int SecondaryEntryComparison(
  		    DatabaseEntry dbt1, DatabaseEntry dbt2)
  		{
  			int a, b;
  			a = BitConverter.ToInt32(dbt1.Data, 0);
  			b = BitConverter.ToInt32(dbt2.Data, 0);
  			return a - b;
  		}
  
  		private uint SecondaryPrefixEntryComparison(DatabaseEntry dbt1,
  		    DatabaseEntry dbt2)
  		{
  			uint cnt, len;
  
  			len = Math.Min((uint)dbt1.Data.Length, (uint)dbt2.Data.Length);
  			for (cnt = 0; cnt < len; cnt++)
  			{
  				if (dbt1.Data[cnt] != dbt2.Data[cnt])
  					return cnt + 1;
  			}
  			if (dbt1.Data.Length > dbt2.Data.Length)
  				return (uint)dbt2.Data.Length + 1;
  
gt: 			else if (dbt1.Data.Length < dbt2.Data.Length)