context: /*-
   * See the file LICENSE for redistribution information.
   *
   * Copyright (c) 2009 Oracle.  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 SecondaryDatabaseTest
      {
          private string testFixtureHome;
          private string testFixtureName;
          private string testName;
          private string testHome;
  
          [TestFixtureSetUp]
          public void RunBeforeTests()
          {
              testFixtureName = "SecondaryDatabaseTest";
              testFixtureHome = "./TestOut/" + testFixtureName;
  
              Configuration.ClearDir(testFixtureHome);
          }
  
          [Test]
          public void TestKeyGen()
          {
              testName = "TestKeyGen";
              testHome = testFixtureHome + "/" + testName;
              string dbFileName = testHome + "/" + testName + ".db";
  
              Configuration.ClearDir(testHome);
  
              // Open primary database.
              BTreeDatabaseConfig primaryDBConfig =
                  new BTreeDatabaseConfig();
              primaryDBConfig.Creation = CreatePolicy.IF_NEEDED;
              BTreeDatabase primaryDB =
                  BTreeDatabase.Open(dbFileName, primaryDBConfig);
  
              // Open secondary database.
              SecondaryBTreeDatabaseConfig secDBConfig =
                  new SecondaryBTreeDatabaseConfig(primaryDB,
                  new SecondaryKeyGenDelegate(SecondaryKeyGen));
              SecondaryBTreeDatabase secDB =
                  SecondaryBTreeDatabase.Open(dbFileName,
                  secDBConfig);
  
              primaryDB.Put(new DatabaseEntry(
                  BitConverter.GetBytes((int)1)),
                  new DatabaseEntry(BitConverter.GetBytes((int)11)));
  
              KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
              pair = secDB.Get(new DatabaseEntry(
                  BitConverter.GetBytes((int)11)));
              Assert.IsNotNull(pair.Value);
  
              // Close secondary database.
              secDB.Close();
  
              // Close primary database.
              primaryDB.Close();
          }
  
          [Test]
          public void TestSecondaryCursor()
          {
              testName = "TestSecondaryCursor";
              testHome = testFixtureHome + "/" + testName;
              string dbFileName = testHome + "/" + testName + ".db";
  
              Configuration.ClearDir(testHome);
  
              // Open primary database.
              BTreeDatabaseConfig primaryDBConfig =
                  new BTreeDatabaseConfig();
              primaryDBConfig.Creation = CreatePolicy.IF_NEEDED;
              BTreeDatabase primaryDB =
                  BTreeDatabase.Open(dbFileName, primaryDBConfig);
  
              // Open secondary database.
              SecondaryBTreeDatabaseConfig secDBConfig =
                  new SecondaryBTreeDatabaseConfig(primaryDB,
                  new SecondaryKeyGenDelegate(SecondaryKeyGen));
              SecondaryBTreeDatabase secDB =
                  SecondaryBTreeDatabase.Open(dbFileName,
                  secDBConfig);
  
              primaryDB.Put(new DatabaseEntry(
                  BitConverter.GetBytes((int)1)),
                  new DatabaseEntry(BitConverter.GetBytes((int)11)));
  
  
              SecondaryCursor cursor = secDB.SecondaryCursor();
              cursor.Move(new DatabaseEntry(
                  BitConverter.GetBytes((int)11)), true);
              Assert.AreEqual(BitConverter.GetBytes((int)11),
                  cursor.Current.Key.Data);
  
              // Close the cursor.
              cursor.Close();
  
              // Close secondary database.
              secDB.Close();
  
              // Close primary database.
              primaryDB.Close();
          }
  
          [Test]
          public void TestSecondaryCursorWithConfig()
          {
              testName = "TestSecondaryCursorWithConfig";
              testHome = testFixtureHome + "/" + testName;
              string dbFileName = testHome + "/" + testName + ".db";
  
              Configuration.ClearDir(testHome);
  
              BTreeDatabase db;
              SecondaryBTreeDatabase secDB;
              OpenPrimaryAndSecondaryDB(dbFileName, out db, out secDB);
  
              for (int i = 0; i < 10; i++)
                  db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
                      new DatabaseEntry(BitConverter.GetBytes((int)i)));
  
              CursorConfig cursorConfig = new CursorConfig();
              cursorConfig.WriteCursor = false;
              SecondaryCursor cursor =
                  secDB.SecondaryCursor(cursorConfig);
  
              cursor.Move(new DatabaseEntry(
                  BitConverter.GetBytes((int)5)), true);
  
              Assert.AreEqual(1, cursor.Count());
  
              // Close the cursor.
              cursor.Close();
  
              // Close secondary database.
              secDB.Close();
  
              // Close primary database.
              db.Close();
          }
  
          [Test]
          public void TestSecondaryCursorWithTxn()
          {
              testName = "TestSecondaryCursorWithTxn";
              testHome = testFixtureHome + "/" + testName;
              string dbFileName = testHome + "/" + testName + ".db";
  
              Configuration.ClearDir(testHome);
  
              GetSecondaryCursurWithTxn(testHome, testName, false);
          }
  
          [Test]
          public void TestSecondaryCursorWithConfigAndTxn()
          {
              testName = "TestSecondaryCursorWithConfigAndTxn";
              testHome = testFixtureHome + "/" + testName;
              string dbFileName = testHome + "/" + testName + ".db";
  
              Configuration.ClearDir(testHome);
              GetSecondaryCursurWithTxn(testHome, testName, true);
          }
  
          public void GetSecondaryCursurWithTxn(string home,
              string name, bool ifCfg)
          {
              string dbFileName = name + ".db";
              SecondaryCursor cursor;
  
              // Open env.
              DatabaseEnvironmentConfig envConfig =
                  new DatabaseEnvironmentConfig();
              envConfig.Create = true;
              envConfig.UseTxns = true;
              envConfig.UseMPool = true;
              DatabaseEnvironment env = DatabaseEnvironment.Open(home,
                  envConfig);
  
  
              // Open primary/secondary database.
              Transaction txn = env.BeginTransaction();
              BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
              dbConfig.Creation = CreatePolicy.IF_NEEDED;
              dbConfig.Env = env;
              BTreeDatabase db = BTreeDatabase.Open(dbFileName,
                  dbConfig, txn);
  
              SecondaryBTreeDatabaseConfig secDBConfig = new
                  SecondaryBTreeDatabaseConfig(db,
                  new SecondaryKeyGenDelegate(SecondaryKeyGen));
              secDBConfig.Env = env;
              SecondaryBTreeDatabase secDB =
                  SecondaryBTreeDatabase.Open(dbFileName,
                  secDBConfig, txn);
  
              for (int i = 0; i < 10; i++)
                  db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
                      new DatabaseEntry(BitConverter.GetBytes((int)i)), txn);
  
  
              // Create secondary cursor.
              if (ifCfg == false)
                  secDB.SecondaryCursor(txn);
              else if (ifCfg == true)
              {
                  CursorConfig cursorConfig = new CursorConfig();
                  cursorConfig.WriteCursor = false;
                  cursor = secDB.SecondaryCursor(cursorConfig, txn);
                  cursor.Close();
              }
  
              secDB.Close();
              db.Close();
              txn.Commit();
              env.Close();
          }
  
          [Test]
          public void TestOpen()
          {
              testName = "TestOpen";
              testHome = testFixtureHome + "/" + testName;
              string dbFileName = testHome + "/" + testName + ".db";
              string dbSecFileName = testHome + "/" +
                  testName + "_sec.db";
  
              Configuration.ClearDir(testHome);
  
              OpenSecQueueDB(dbFileName, dbSecFileName, false);
          }
  
          [Test]
          public void TestOpenWithDBName()
          {
              testName = "TestOpenWithDBName";
              testHome = testFixtureHome + "/" + testName;
              string dbFileName = testHome + "/" + testName + ".db";
              string dbSecFileName = testHome + "/" +
                  testName + "_sec.db";
  
              Configuration.ClearDir(testHome);
              OpenSecQueueDB(dbFileName, dbSecFileName, true);
          }
  
          public void OpenSecQueueDB(string dbFileName, 
              string dbSecFileName, bool ifDBName)
          {
              // Open a primary btree database.
              BTreeDatabaseConfig primaryDBConfig =
                  new BTreeDatabaseConfig();
              primaryDBConfig.Creation = CreatePolicy.IF_NEEDED;
              BTreeDatabase primaryDB;
  
              /*
               * If secondary database name is given, the primary 
               * database is also opened with database name.
               */
              if (ifDBName == false)
                  primaryDB = BTreeDatabase.Open(dbFileName,
                      primaryDBConfig);
              else
                  primaryDB = BTreeDatabase.Open(dbFileName,
                      "primary", primaryDBConfig);
  
              try
              {
                  // Open a new secondary database.
                  SecondaryBTreeDatabaseConfig secBTDBConfig =
                      new SecondaryBTreeDatabaseConfig(
                      primaryDB, null);
                  secBTDBConfig.Creation =
                      CreatePolicy.IF_NEEDED;
  
                  SecondaryBTreeDatabase secBTDB;
                  if (ifDBName == false)
                      secBTDB = SecondaryBTreeDatabase.Open(
                          dbSecFileName, secBTDBConfig);
                  else
                      secBTDB = SecondaryBTreeDatabase.Open(
                          dbSecFileName, "secondary",
                          secBTDBConfig);
  
                  // Close the secondary database.
                  secBTDB.Close();
  
                  // Open the existing secondary database.
                  SecondaryDatabaseConfig secDBConfig =
                      new SecondaryDatabaseConfig(
                      primaryDB, null);
  
                  SecondaryDatabase secDB;
                  if (ifDBName == false)
                      secDB = SecondaryBTreeDatabase.Open(
                          dbSecFileName, secDBConfig);
                  else
                      secDB = SecondaryBTreeDatabase.Open(
                          dbSecFileName, "secondary", secDBConfig);
  
                  // Close secondary database.
                  secDB.Close();
              }
              catch (DatabaseException)
              {
                  throw new TestException();
              }
              finally
              {
                  // Close primary database.
                  primaryDB.Close();
              }
          }
  
          [Test]
          public void TestOpenWithinTxn()
          {
              testName = "TestOpenWithinTxn";
  
gt:             testHome = testFixtureHome + "/" + testName;