libdb/test/csharp/DatabaseEnvironmentTest.cs

1987 lines
58 KiB
C#
Raw Normal View History

2011-09-13 17:44:24 +00:00
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2009, 2011 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
{
[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 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 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.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)) {
for (int i = 0; i < 10; i++)
db1.Get(new DatabaseEntry(
BitConverter.GetBytes(i)));
};
/// Verify the encrypted database is encrypted.
verifyDbCfg.SetEncryption(envCfg.EncryptionPassword,
envCfg.EncryptAlgorithm);
verifyDbCfg.Encrypted = true;
using (db1 = BTreeDatabase.Open(
testHome + "/" + testName + "2.db",
verifyDbCfg)) {
for (int i = 0; i < 10; i++)
db1.Get(new DatabaseEntry(
BitConverter.GetBytes(i)));
};
}
[Test]
public void TestFailCheck()
{
testName = "TestFailCheck";
SetUpTest(true);
DatabaseEnvironmentConfig cfg =
new DatabaseEnvironmentConfig();
cfg.Create = true;
cfg.UseTxns = true;
cfg.UseMPool = true;
cfg.UseLogging = true;
cfg.UseLocking = true;
cfg.FreeThreaded = true;
cfg.ThreadIsAlive = new ThreadIsAliveDelegate(ThrdAlive);
cfg.SetThreadID = new SetThreadIDDelegate(SetThrdID);
cfg.ThreadCount = 10;
testFailCheckEnv = DatabaseEnvironment.Open(testHome, cfg);
Thread thread = new Thread(new ThreadStart(WriteThreadWithoutTxnCommit));
thread.Start();
thread.Join();
testFailCheckEnv.FailCheck();
testFailCheckEnv.Close();
}
public void WriteThreadWithoutTxnCommit()
{
Transaction txn = testFailCheckEnv.BeginTransaction();
BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
dbConfig.Creation = CreatePolicy.IF_NEEDED;
dbConfig.Env = testFailCheckEnv;
BTreeDatabase db = BTreeDatabase.Open("TestFailCheck.db", dbConfig, txn);
db.Close();
txn.Commit();
}
public bool ThrdAlive(DbThreadID info, bool procOnly)
{
Process pcs = Process.GetProcessById(info.processID);
if (pcs.HasExited == true)
return false;
else if (procOnly)
return true;
ProcessThreadCollection thrds = pcs.Threads;
foreach (ProcessThread pcsThrd in thrds)
{
if (pcsThrd.Id == info.threadID)
{
/*
* We have to use the fully qualified name, ThreadState
* defaults to System.Threading.ThreadState.
*/
return (pcsThrd.ThreadState !=
System.Diagnostics.ThreadState.Terminated);
}
}
// If we can't find the thread, we say it's not alive
return false;
}
public DbThreadID SetThrdID()
{
DbThreadID threadID;
int pid = Process.GetCurrentProcess().Id;
uint tid = (uint)AppDomain.GetCurrentThreadId();
threadID = new DbThreadID(pid, tid);
return threadID;
}
[Test]
public void TestFeedback()
{
testName = "TestFeedback";
SetUpTest(true);
// Open the environment.
DatabaseEnvironmentConfig cfg =
new DatabaseEnvironmentConfig();
cfg.AutoCommit = true;
cfg.UseLocking = true;
cfg.UseLogging = true;
cfg.UseMPool = true;
cfg.UseTxns = true;
cfg.Create = true;
DatabaseEnvironment env = DatabaseEnvironment.Open(testHome, cfg);
env.Feedback = new EnvironmentFeedbackDelegate(
EnvRecovery10PercentFeedback);
env.Feedback(EnvironmentFeedbackEvent.RECOVERY, 10);
env.Close();
}
public void EnvRecovery10PercentFeedback(
EnvironmentFeedbackEvent opcode, int percent)
{
Assert.AreEqual(opcode, EnvironmentFeedbackEvent.RECOVERY);
Assert.AreEqual(10, percent);
}
[Test]
public void TestMutexSystemStats()
{
testName = "TestMutexSystemStats";
SetUpTest(true);
DatabaseEnvironmentConfig cfg =
new DatabaseEnvironmentConfig();
cfg.Create = true;
cfg.UseLogging = true;
cfg.UseLocking = true;
cfg.UseMPool = true;
cfg.UseTxns = true;
cfg.MutexSystemCfg = new MutexConfig();
cfg.MutexSystemCfg.Alignment = 512;
cfg.MutexSystemCfg.Increment = 128;
cfg.MutexSystemCfg.MaxMutexes = 150;
cfg.MutexSystemCfg.NumTestAndSetSpins = 10;
DatabaseEnvironment env = DatabaseEnvironment.Open(testHome, cfg);
MutexStats stats = env.MutexSystemStats();
env.PrintMutexSystemStats(true, true);
Assert.AreEqual(512, stats.Alignment);
Assert.AreEqual(stats.Count, stats.Available + stats.InUse);
Assert.LessOrEqual(stats.InUse, stats.MaxInUse);
Assert.AreNotEqual(0, stats.InitCount);
Assert.AreNotEqual(0, stats.Max);
Assert.AreNotEqual(0, stats.RegionMax);
Assert.AreNotEqual(0, stats.RegionSize);
Assert.AreEqual(0, stats.RegionWait);
Assert.AreEqual(10, stats.TASSpins);
ulong regionNoWait = stats.RegionNoWait;
BTreeDatabaseConfig dbCfg = new BTreeDatabaseConfig();
dbCfg.Creation = CreatePolicy.IF_NEEDED;
dbCfg.Env = env;
BTreeDatabase db = BTreeDatabase.Open(testName + ".db", dbCfg);
for (int i = 0; i < 1000; i++)
{
db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
new DatabaseEntry(BitConverter.GetBytes(i)));
stats = env.MutexSystemStats();
}
Assert.LessOrEqual(regionNoWait, stats.RegionNoWait);
regionNoWait = stats.RegionNoWait;
stats = env.MutexSystemStats(true);
env.PrintMutexSystemStats();
stats = env.MutexSystemStats();
Assert.GreaterOrEqual(regionNoWait, stats.RegionNoWait);
db.Close();
env.Close();
}
[Test]
public void TestLogFile()
{
testName = "TestLogFile";
SetUpTest(true);
// Open environment and configure logging subsystem.
DatabaseEnvironmentConfig cfg =
new DatabaseEnvironmentConfig();
cfg.Create = true;
cfg.UseTxns = true;
cfg.AutoCommit = true;
cfg.UseLocking = true;
cfg.UseMPool = true;
cfg.UseLogging = true;
cfg.MPoolSystemCfg = new MPoolConfig();
cfg.MPoolSystemCfg.CacheSize =
new CacheInfo(0, 1048576, 1);
cfg.LogSystemCfg = new LogConfig();
cfg.LogSystemCfg.AutoRemove = false;
cfg.LogSystemCfg.BufferSize = 10240;
cfg.LogSystemCfg.Dir = "./";
cfg.LogSystemCfg.FileMode = 755;
cfg.LogSystemCfg.ForceSync = true;
cfg.LogSystemCfg.InMemory = false;
cfg.LogSystemCfg.MaxFileSize = 1048576;
cfg.LogSystemCfg.NoBuffer = false;
cfg.LogSystemCfg.RegionSize = 204800;
cfg.LogSystemCfg.ZeroOnCreate = true;
DatabaseEnvironment env = DatabaseEnvironment.Open(testHome, cfg);
// Open database.
Transaction allTxn = env.BeginTransaction();
TransactionConfig txnConfig = new TransactionConfig();
txnConfig.Name = "OpenTransaction";
Transaction openTxn = env.BeginTransaction(txnConfig, allTxn);
BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
dbConfig.Creation = CreatePolicy.IF_NEEDED;
dbConfig.Env = env;
BTreeDatabase db = BTreeDatabase.Open(
testName + ".db", dbConfig, openTxn);
List<ActiveTransaction> activeTxns =
env.TransactionSystemStats().Transactions;
for (int i = 0; i < activeTxns.Count; i++)
if (activeTxns[i].Name == "OpenTransaction")
{
LSN lsn = new LSN(
activeTxns[i].Begun.LogFileNumber,
activeTxns[i].Begun.Offset);
env.LogFlush(lsn);
string fileName = env.LogFile(lsn);
}
openTxn.Commit();
// Write "##" to log before putting data into database.
env.WriteToLog("##");
// Write 1000 records into database.
TransactionConfig writeTxnConfig = new TransactionConfig();
writeTxnConfig.Name = "WriteTxn";
Transaction writeTxn = env.BeginTransaction(writeTxnConfig, allTxn);
byte[] byteArr = new byte[1024];
for (int i = 0; i < 1000; i++)
{
db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
new DatabaseEntry(byteArr), writeTxn);
env.LogFlush();
env.WriteToLog("#" + i.ToString(), writeTxn);
}
activeTxns = env.TransactionSystemStats().Transactions;
for (int i = 0; i < activeTxns.Count; i++)
if (activeTxns[i].Name == "WriteTxn")
{
LSN lsn = new LSN(
activeTxns[i].Begun.LogFileNumber,
activeTxns[i].Begun.Offset);
env.LogFlush(lsn);
string fileName = env.LogFile(lsn);
}
writeTxn.Commit();
db.Close();
// Write "##" after data has been put.
env.WriteToLog("##");
List<string> logFiles = env.LogFiles(true);
env.LogWrite(new DatabaseEntry(), true);
env.RemoveUnusedLogFiles();
allTxn.Commit();
env.Close();
}
[Test]
public void TestLogVerifyConfig()
{
testName = "TestLogVerifyConfig";
SetUpTest(true);
// Open enviornment.
DatabaseEnvironmentConfig cfg =
new DatabaseEnvironmentConfig();
cfg.Create = true;
cfg.UseLocking = true;
cfg.UseLogging = true;
cfg.UseMPool = true;
cfg.UseTxns = true;
DatabaseEnvironment env = DatabaseEnvironment.Open(
testHome, cfg);
// Open database.
Transaction txn = env.BeginTransaction();
BTreeDatabaseConfig dbCfg = new BTreeDatabaseConfig();
dbCfg.Env = env;
dbCfg.Creation = CreatePolicy.IF_NEEDED;
dbCfg.Duplicates = DuplicatesPolicy.UNSORTED;
BTreeDatabase db = BTreeDatabase.Open(
testName, dbCfg, txn);
txn.Commit();
// Do a lot of transactional operations to create logs.
DatabaseEntry key, data;
for (int i = 0; i < 5; i++) {
txn = env.BeginTransaction();
switch (i) {
case 0:
/*
* Put 1000 records and commit the
* transaction.
*/
for (int j = 0; j < 1000;j++) {
key = new DatabaseEntry(
BitConverter.GetBytes(j));
data = new DatabaseEntry(
BitConverter.GetBytes(j));
db.Put(key, data, txn);
}
txn.Commit();
break;
case 1:
/*
* Put 10 overflow records and commit
* the transaction.
*/
for (int j = 0; j < 10;j++) {
key = new DatabaseEntry(
BitConverter.GetBytes(j));
data = new DatabaseEntry(
new byte[1024 * 4]);
db.Put(key, data, txn);
}
txn.Commit();
break;
case 2:
/*
* Put 1000 records and abort the
* transaction.
*/
for (int j = 0; j < 1000;j++) {
key = new DatabaseEntry(
BitConverter.GetBytes(j));
data = new DatabaseEntry(
BitConverter.GetBytes(j + 1));
db.Put(key, data, txn);
}
txn.Abort();
break;
case 3:
/*
* Put 10 overflow records and abort the
* transaction.
*/
for (int j = 10; j < 20;j++) {
key = new DatabaseEntry(
BitConverter.GetBytes(j));
data = new DatabaseEntry(
new byte[1024 * 4]);
db.Put(key, data, txn);
}
txn.Abort();
break;
case 4:
// Get 100 records.
for (int j = 100; j < 200; j++) {
key = new DatabaseEntry(
BitConverter.GetBytes(j));
data = new DatabaseEntry(
BitConverter.GetBytes(j));
db.GetBoth(key, data, txn);
}
txn.Commit();
break;
}
}
// Verfiy entire log.
string tempHome = testHome + "_tmp";
Configuration.ClearDir(tempHome);
LogVerifyConfig logVerifyCfg = new LogVerifyConfig();
logVerifyCfg.CacheSize = 1024 * 10;
logVerifyCfg.ContinueAfterFail = true;
logVerifyCfg.EnvHome = tempHome;
logVerifyCfg.Verbose = true;
Assert.AreEqual(0, env.LogVerify(logVerifyCfg));
db.Close();
env.Close();
// Verify specific database.
logVerifyCfg.DbFile = testName + ".db";
logVerifyCfg.DbName = testName;
Assert.AreEqual(0, env.LogVerify(logVerifyCfg));
// Verify partial log.
DateTime time = DateTime.Now;
DateTime startTime = time.AddMinutes(-2);
DateTime endTime = time.AddMinutes(-1);
logVerifyCfg.StartTime = startTime;
logVerifyCfg.EndTime = endTime;
Assert.AreEqual(0, env.LogVerify(logVerifyCfg));
// Verfiy unexisting log.
logVerifyCfg.StartLsn = new LSN(1, 3);
logVerifyCfg.EndLsn = new LSN(2, 100);
Assert.AreEqual(0, env.LogVerify(logVerifyCfg));
Assert.AreEqual(logVerifyCfg.CacheSize, 1024 * 10);
Assert.AreEqual(logVerifyCfg.ContinueAfterFail, true);
Assert.AreEqual(logVerifyCfg.DbFile, testName + ".db");
Assert.AreEqual(logVerifyCfg.DbName, testName);
Assert.AreEqual(logVerifyCfg.EndLsn.LogFileNumber, 2);
Assert.AreEqual(logVerifyCfg.EndLsn.Offset, 100);
Assert.AreEqual(logVerifyCfg.EndTime, endTime);
Assert.AreEqual(logVerifyCfg.EnvHome, testHome + "_tmp");
Assert.AreEqual(logVerifyCfg.StartLsn.LogFileNumber, 1);
Assert.AreEqual(logVerifyCfg.StartLsn.Offset, 3);
Assert.AreEqual(logVerifyCfg.StartTime, startTime);
Assert.AreEqual(logVerifyCfg.Verbose, true);
}
[Test]
public void TestOpen()
{
testName = "TestOpen";
SetUpTest(true);
DatabaseEnvironmentConfig cfg =
new DatabaseEnvironmentConfig();
cfg.Create = true;
DatabaseEnvironment env = DatabaseEnvironment.Open(testHome, cfg);
// Confirm that the environment is initialized.
Assert.IsNotNull(env);
// Confirm the environment home directory.
Assert.AreEqual(testHome, env.Home);
// Print statistics of the current environment.
env.PrintStats();
// Print statistics of all subsytems.
env.PrintSubsystemStats();
env.Close();
}
[Test]
public void TestMPoolSystemStats()
{
testName = "TestMPoolSystemStats";
SetUpTest(true);
DatabaseEnvironmentConfig envConfig =
new DatabaseEnvironmentConfig();
envConfig.AutoCommit = true;
envConfig.MPoolSystemCfg = new MPoolConfig();
envConfig.MPoolSystemCfg.CacheSize =
new CacheInfo(0, 1048576, 3);
envConfig.Create = true;
envConfig.UseLocking = true;
envConfig.UseLogging = true;
envConfig.UseMPool = true;
envConfig.UseTxns = true;
DatabaseEnvironment env = DatabaseEnvironment.Open(
testHome, envConfig);
MPoolStats stats = env.MPoolSystemStats();
env.PrintMPoolSystemStats();
Assert.AreEqual(0, stats.BlockedOperations);
Assert.AreEqual(0, stats.BucketsCheckedDuringAlloc);
Assert.AreEqual(3, stats.CacheRegions);
Assert.LessOrEqual(1048576, stats.CacheSettings.Bytes);
Assert.AreEqual(0, stats.CacheSettings.Gigabytes);
Assert.AreEqual(3, stats.CacheSettings.NCaches);
Assert.AreEqual(0, stats.CleanPages);
Assert.AreEqual(0, stats.CleanPagesEvicted);
Assert.AreEqual(0, stats.DirtyPages);
Assert.AreEqual(0, stats.DirtyPagesEvicted);
Assert.IsNotNull(stats.Files);
Assert.AreEqual(0, stats.FrozenBuffers);
Assert.AreEqual(0, stats.FrozenBuffersFreed);
Assert.LessOrEqual(stats.HashBuckets,
stats.HashBucketMutexes);
Assert.LessOrEqual(37, stats.HashBuckets);
Assert.LessOrEqual(0, stats.HashChainSearches);
Assert.AreEqual(0, stats.HashEntriesSearched);
Assert.AreEqual(0, stats.HashLockNoWait);
Assert.AreEqual(0, stats.HashLockWait);
Assert.AreEqual(0, stats.LongestHashChainSearch);
Assert.AreEqual(0, stats.MappedPages);
Assert.AreEqual(0, stats.MaxBucketsCheckedDuringAlloc);
Assert.AreEqual(0, stats.MaxBufferWrites);
Assert.AreEqual(0, stats.MaxBufferWritesSleep);
Assert.AreEqual(0, stats.MaxHashLockNoWait);
Assert.AreEqual(0, stats.MaxHashLockWait);
Assert.AreEqual(0, stats.MaxMMapSize);
Assert.AreEqual(0, stats.MaxOpenFileDescriptors);
Assert.AreEqual(0, stats.MaxPagesCheckedDuringAlloc);
Assert.AreEqual(0, stats.PageAllocations);
Assert.AreEqual(0, stats.Pages);
Assert.AreEqual(0, stats.PagesCheckedDuringAlloc);
Assert.LessOrEqual(0, stats.PagesCreatedInCache);
Assert.AreEqual(0, stats.PagesInCache);
Assert.AreEqual(0, stats.PagesNotInCache);
Assert.AreEqual(0, stats.PagesRead);
Assert.AreEqual(0, stats.PagesTrickled);
Assert.AreEqual(0, stats.PagesWritten);
Assert.AreNotEqual(0, stats.RegionLockNoWait);
Assert.AreEqual(0, stats.RegionLockWait);
Assert.LessOrEqual(0, stats.RegionSize);
Assert.AreNotEqual(0, stats.RegionMax);
Assert.AreEqual(0, stats.ThawedBuffers);
Transaction txn = env.BeginTransaction();
BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
dbConfig.Creation = CreatePolicy.IF_NEEDED;
dbConfig.Env = env;
dbConfig.PageSize = 4096;
BTreeDatabase db = BTreeDatabase.Open(
testName + ".db", dbConfig, txn);
stats = env.MPoolSystemStats();
Assert.AreEqual(1, stats.Files.Count);
Assert.AreEqual(testName + ".db", stats.Files[0].FileName);
Assert.AreEqual(0, stats.Files[0].MappedPages);
Assert.AreEqual(0, stats.Files[0].PagesCreatedInCache);
Assert.AreEqual(0, stats.Files[0].PagesInCache);
Assert.AreEqual(4096, stats.Files[0].PageSize);
Assert.LessOrEqual(1, stats.Files[0].PagesNotInCache);
Assert.AreEqual(1, stats.Files[0].PagesRead);
Assert.AreEqual(0, stats.Files[0].PagesWritten);
byte[] largeByte = new byte[1088576];
for (int i = 0; i < 10; i++)
db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
new DatabaseEntry(largeByte), txn);
db.Put(new DatabaseEntry(largeByte),
new DatabaseEntry(largeByte), txn);
stats = env.MPoolSystemStats();
Assert.Less(0, stats.Files[0].PagesCreatedInCache);
Assert.Less(0, stats.Files[0].PagesInCache);
Assert.LessOrEqual(1, stats.Files[0].PagesNotInCache);
Assert.LessOrEqual(1, stats.Files[0].PagesRead);
Assert.Less(0, stats.Files[0].PagesWritten);
txn.Commit();
db.Close();
// Clean the stats after printing.
stats = env.MPoolSystemStats(true);
env.PrintMPoolSystemStats(true, true);
stats = env.MPoolSystemStats();
env.PrintMPoolSystemStats(true, true, true);
env.Close();
}
[Test]
public void TestRemove()
{
testName = "TestRemove";
SetUpTest(true);
// Open new environment.
DatabaseEnvironmentConfig envConig =
new DatabaseEnvironmentConfig();
envConig.Create = true;
envConig.ErrorPrefix = testFixtureName + ":" + testName;
DatabaseEnvironment env = DatabaseEnvironment.Open(
testHome, envConig);
env.Close();
// Remove the existing environment.
DatabaseEnvironment.Remove(testHome);
// Confirm that the __db.001 is removed.
Assert.IsFalse(File.Exists(testHome + "__db.001"));
}
[Test]
public void TestRemoveCorruptedEnv()
{
testName = "TestRemoveCorruptedEnv";
SetUpTest(true);
// Open new environment.
DatabaseEnvironmentConfig envConig =
new DatabaseEnvironmentConfig();
envConig.Create = true;
envConig.ErrorPrefix = testFixtureName + ":" + testName;
DatabaseEnvironment env = DatabaseEnvironment.Open(testHome, envConig);
// Panic the environment.
env.Panic();
// Remove the corrupted environment.
DatabaseEnvironment.Remove(testHome, true);
// Confirm that the __db.001 is removed.
Assert.IsFalse(File.Exists(testHome + "__db.001"));
}
[Test, ExpectedException(typeof(ExpectedTestException))]
public void TestRenameDB()
{
testName = "TestRenameDB";
SetUpTest(true);
RenameDB(testHome, testName, false);
}
[Test, ExpectedException(typeof(ExpectedTestException))]
public void TestRenameDBWithTxn()
{
testName = "TestRenameDBWithTxn";
SetUpTest(true);
RenameDB(testHome, testName, true);
}
public void RenameDB(string home, string name, bool ifTxn)
{
string dbFileName = name + ".db";
string dbName = "db1";
string dbNewName = "db2";
Configuration.ClearDir(home);
DatabaseEnvironmentConfig envConig =
new DatabaseEnvironmentConfig();
envConig.Create = true;
envConig.UseTxns = true;
envConig.UseLogging = true;
envConig.UseMPool = true;
DatabaseEnvironment env = DatabaseEnvironment.Open(
home, envConig);
Transaction openTxn = env.BeginTransaction();
BTreeDatabaseConfig dbConfig =
new BTreeDatabaseConfig();
dbConfig.Creation = CreatePolicy.IF_NEEDED;
dbConfig.Env = env;
BTreeDatabase db = BTreeDatabase.Open(
dbFileName, dbName, dbConfig, openTxn);
db.Close();
openTxn.Commit();
// Open the database.
if (ifTxn == false)
env.RenameDB(dbFileName, dbName, dbNewName, true);
else
{
Transaction renameTxn = env.BeginTransaction();
env.RenameDB(dbFileName, dbName, dbNewName, false, renameTxn);
renameTxn.Commit();
}
// Confirm that the database are renamed.
Transaction reopenTxn = env.BeginTransaction();
try
{
Database db1 = Database.Open(
dbFileName, new DatabaseConfig());
db1.Close();
}
catch (DatabaseException)
{
throw new ExpectedTestException();
}
finally
{
reopenTxn.Commit();
env.Close();
}
}
[Test]
public void TestResetFileID()
{
testName = "TestResetFileID";
SetUpTest(true);
string dbFileName = testName + ".db";
string dbNewFileName = testName + "_new.db";
DatabaseEnvironmentConfig envConfig =
new DatabaseEnvironmentConfig();
envConfig.Create = true;
envConfig.UseMPool = true;
DatabaseEnvironment env = DatabaseEnvironment.Open(
testHome, envConfig);
// Opening a new database.
BTreeDatabaseConfig dbConfig =
new BTreeDatabaseConfig();
dbConfig.Creation = CreatePolicy.IF_NEEDED;
dbConfig.Env = env;
BTreeDatabase db = BTreeDatabase.Open(
dbFileName, dbConfig);
db.Close();
// Copy the physical database file.
File.Copy(testHome + "/" + dbFileName,
testHome + "/" + dbNewFileName);
// Reset the file ID.
env.ResetFileID(dbNewFileName, false);
// Open the exisiting database in copied database file.
BTreeDatabaseConfig cfg = new BTreeDatabaseConfig();
cfg.Creation = CreatePolicy.NEVER;
cfg.Env = env;
BTreeDatabase newDB = BTreeDatabase.Open(
dbNewFileName, cfg);
newDB.Close();
env.Close();
}
[Test, ExpectedException(typeof(ExpectedTestException))]
public void TestRemoveDB()
{
testName = "TestRemoveDB";
SetUpTest(true);
RmDBWithoutTxn(testHome, testName, false);
}
[Test, ExpectedException(typeof(ExpectedTestException))]
public void TestRemoveDBWithAutoCommit()
{
testName = "TestRemoveDBWithAutoCommit";
SetUpTest(true);
RmDBWithoutTxn(testHome, testName, true);
}
[Test, ExpectedException(typeof(ExpectedTestException))]
public void TestRemoveDBWithinTxn()
{
testName = "TestRemoveDBWithinTxn";
SetUpTest(true);
string dbFileName = testName + ".db";
string dbName1 = testName + "1";
string dbName2 = testName + "2";
// Open environment.
DatabaseEnvironmentConfig envConfig =
new DatabaseEnvironmentConfig();
envConfig.Create = true;
envConfig.UseMPool = true;
envConfig.UseTxns = true;
envConfig.UseLogging = true;
DatabaseEnvironment env = DatabaseEnvironment.Open(
testHome, envConfig);
Transaction txn = env.BeginTransaction();
// Create two databases in the environment.
BTreeDatabaseConfig dbConfig =
new BTreeDatabaseConfig();
dbConfig.Creation = CreatePolicy.IF_NEEDED;
dbConfig.Env = env;
BTreeDatabase btreeDB1 = BTreeDatabase.Open(
dbFileName, dbName1, dbConfig, txn);
btreeDB1.Close();
BTreeDatabase btreeDB2 = BTreeDatabase.Open(
dbFileName, dbName2, dbConfig, txn);
btreeDB2.Close();
// Remove one database from the environment.
env.RemoveDB(dbFileName, dbName2, false, txn);
// Try to open the existing database.
DatabaseConfig cfg = new DatabaseConfig();
cfg.Env = env;
Database db1 = Database.Open(dbFileName, dbName1, cfg, txn);
db1.Close();
/*
* Attempting to open the removed database should
* cause error.
*/
try
{
Database db2 = Database.Open(
dbFileName, dbName2, cfg, txn);
db2.Close();
}
catch (DatabaseException)
{
throw new ExpectedTestException();
}
finally
{
txn.Commit();
env.Close();
}
}
public void RmDBWithoutTxn(string home, string dbName,
bool ifAutoCommit)
{
string dbFileName = dbName + ".db";
string dbName1 = dbName + "1";
string dbName2 = dbName + "2";
// Open environment.
DatabaseEnvironmentConfig envConfig =
new DatabaseEnvironmentConfig();
envConfig.Create = true;
envConfig.UseMPool = true;
if (ifAutoCommit == true)
{
envConfig.AutoCommit = true;
envConfig.UseTxns = true;
}
DatabaseEnvironment env = DatabaseEnvironment.Open(
home, envConfig);
// Create two databases in the environment.
BTreeDatabaseConfig dbConfig =
new BTreeDatabaseConfig();
dbConfig.Creation = CreatePolicy.IF_NEEDED;
dbConfig.Env = env;
BTreeDatabase btreeDB1 = BTreeDatabase.Open(
dbFileName, dbName1, dbConfig);
btreeDB1.Close();
BTreeDatabase btreeDB2 = BTreeDatabase.Open(
dbFileName, dbName2, dbConfig);
btreeDB2.Close();
// Remove one database from the environment.
env.RemoveDB(dbFileName, dbName2, false);
// Try to open the existing database.
DatabaseConfig cfg = new DatabaseConfig();
cfg.Env = env;
Database db1 = Database.Open(dbFileName, dbName1, cfg);
db1.Close();
/*
* Attempting to open the removed database should
* cause error.
*/
try
{
Database db2 = Database.Open(
dbFileName, dbName2, cfg);
db2.Close();
}
catch (DatabaseException)
{
throw new ExpectedTestException();
}
finally
{
env.Close();
}
}
[Test]
public void TestTransactionSystemStats()
{
testName = "TestTransactionSystemStats";
SetUpTest(true);
TransactionStats stats;
BTreeDatabase db;
Transaction openTxn = null;
// Open an environment.
long dateTime;
DatabaseEnvironmentConfig envConfig =
new DatabaseEnvironmentConfig();
envConfig.Create = true;
envConfig.MaxTransactions = 50;
envConfig.UseLogging = true;
envConfig.UseLocking = true;
envConfig.UseMPool = true;
envConfig.UseTxns = true;
envConfig.TxnNoSync = false;
envConfig.TxnNoWait = true;
envConfig.TxnSnapshot = true;
envConfig.TxnTimestamp = DateTime.Now;
envConfig.TxnWriteNoSync = false;
DatabaseEnvironment env = DatabaseEnvironment.Open(
testHome, envConfig);
try
{
try
{
// Confirm initial transaction subsystem statistics.
stats = env.TransactionSystemStats();
env.PrintTransactionSystemStats(true, true);
Assert.AreEqual(0, stats.Aborted);
Assert.AreEqual(0, stats.Active);
Assert.AreEqual(0, stats.Begun);
Assert.AreEqual(0, stats.Committed);
Assert.AreEqual(0, stats.InitTxns);
Assert.AreEqual(0, stats.LastCheckpoint.LogFileNumber);
Assert.AreEqual(0, stats.LastCheckpoint.Offset);
Assert.AreEqual(50, stats.MaxTransactions);
Assert.AreNotEqual(0, stats.RegionSize);
Assert.AreEqual(0, stats.Transactions.Count);
}
catch (AssertionException e)
{
throw e;
}
try
{
//Begin a transaction called openTxn and open a database.
TransactionConfig openTxnCfg = new TransactionConfig();
openTxnCfg.Name = "openTxn";
openTxn = env.BeginTransaction(openTxnCfg);
openTxn.Priority = 50;
BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
dbConfig.Creation = CreatePolicy.IF_NEEDED;
dbConfig.Env = env;
db = BTreeDatabase.Open(testName + ".db", dbConfig, openTxn);
}
catch (DatabaseException e)
{
if (openTxn != null)
openTxn.Abort();
throw e;
}
try
{
// At least there is one transaction that is alive.
env.Checkpoint();
stats = env.TransactionSystemStats();
env.PrintTransactionSystemStats();
Assert.AreNotEqual(0, stats.Active);
Assert.AreNotEqual(0, stats.Transactions.Count);
Assert.AreNotEqual(0, stats.Transactions.Capacity);
Assert.AreNotEqual(0, stats.RegionLockNoWait);
dateTime = stats.LastCheckpointTime;
// Begin an embedded transaction called putTxn.
TransactionConfig putTxnCfg =
new TransactionConfig();
putTxnCfg.Name = "putTxn";
putTxnCfg.NoWait = false;
Transaction putTxn = env.BeginTransaction(
putTxnCfg, openTxn);
putTxn.Priority = 50;
try
{
// Put some records into database within putTxn.
for (int i = 0; i < 50; i++)
db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
new DatabaseEntry(BitConverter.GetBytes(i)), putTxn);
stats = env.TransactionSystemStats();
Assert.AreNotEqual(0, stats.MaxActive);
Assert.AreNotEqual(0, stats.MaxTransactions);
Assert.AreEqual(0, stats.MaxSnapshot);
Assert.AreEqual(0, stats.Snapshot);
Assert.AreEqual(stats.Begun,
stats.Aborted + stats.Active + stats.Committed);
Assert.AreEqual(2, stats.Transactions.Count);
/*
* Both of LogFileNumber and Offset in active transaction
* couldn't be 0.
*/
uint logFileNumbers = 0;
uint offSets = 0;
for (int i = 0; i < stats.Transactions.Count;i++)
{
logFileNumbers += stats.Transactions[i].Begun.LogFileNumber;
offSets += stats.Transactions[i].Begun.Offset;
}
Assert.AreNotEqual(0, logFileNumbers);
Assert.AreNotEqual(0, offSets);
// All active transactions are run by the same process and thread.
Assert.AreEqual(stats.Transactions[0].ThreadID,
stats.Transactions[1].ThreadID);
Assert.AreEqual(stats.Transactions[0].ProcessID,
stats.Transactions[1].ProcessID);
// All transactions are alive.
Assert.AreEqual(ActiveTransaction.TransactionStatus.RUNNING,
stats.Transactions[0].Status);
Assert.AreEqual(ActiveTransaction.TransactionStatus.RUNNING,
stats.Transactions[1].Status);
Assert.AreEqual(50, stats.Transactions[0].Priority);
Assert.AreEqual(50, stats.Transactions[1].Priority);
/*
* Find the openTxn in active transactions, which is the
* parent transaction of putTxn.
*/
int parentPos = 0;
if (stats.Transactions[0].Name == "putTxn")
parentPos = 1;
// putTxn's parent id should be the openTxn.
Assert.AreEqual(stats.Transactions[parentPos].ID,
stats.Transactions[1 - parentPos].ParentID);
// Other stats should be an positive integer.
for (int i = 0; i < stats.Transactions.Count - 1; i++)
{
Assert.LessOrEqual(0,
stats.Transactions[i].BufferCopiesInCache);
Assert.LessOrEqual(0,
stats.Transactions[i].SnapshotReads.LogFileNumber);
Assert.LessOrEqual(0,
stats.Transactions[i].SnapshotReads.Offset);
Assert.IsNotNull(stats.Transactions[i].GlobalID);
}
// Commit putTxn.
putTxn.Commit();
}
catch (DatabaseException e)
{
putTxn.Abort();
throw e;
}
stats = env.TransactionSystemStats();
Assert.AreNotEqual(0, stats.LastCheckpoint.LogFileNumber);
Assert.AreNotEqual(0, stats.LastCheckpoint.Offset);
Assert.AreEqual(dateTime, stats.LastCheckpointTime);
openTxn.Commit();
}
catch (DatabaseException e)
{
openTxn.Abort();
throw e;
}
finally
{
db.Close();
}
}
finally
{
env.Close();
}
}
/*
* Configure an environment. Here only configure those that could be
* set before environment open.
*/
public void Config(XmlElement xmlElem,
ref DatabaseEnvironmentConfig envConfig, bool compulsory,
bool logging, bool locking, bool mutex, bool mpool, bool replication)
{
XmlNode childNode;
// Configure environment without any subsystems.
DatabaseEnvironmentConfigTest.Config(xmlElem, ref envConfig, compulsory);
// Configure environment with logging subsystem.
if (logging == true)
{
childNode = XMLReader.GetNode(xmlElem, "LogConfig");
envConfig.LogSystemCfg = new LogConfig();
LogConfigTest.Config((XmlElement)childNode,
ref envConfig.LogSystemCfg, compulsory);
}
// Configure environment with locking subsystem.
if (locking == true)
{
childNode = XMLReader.GetNode(xmlElem, "LockingConfig");
envConfig.LockSystemCfg = new LockingConfig();
LockingConfigTest.Config((XmlElement)childNode,
ref envConfig.LockSystemCfg, compulsory);
}
// Configure environment with mutex subsystem.
if (mutex == true)
{
childNode = XMLReader.GetNode(xmlElem, "MutexConfig");
envConfig.MutexSystemCfg = new MutexConfig();
MutexConfigTest.Config((XmlElement)childNode,
ref envConfig.MutexSystemCfg, compulsory);
}
if (mpool == true)
{
childNode = XMLReader.GetNode(xmlElem, "MPoolConfig");
envConfig.MPoolSystemCfg = new MPoolConfig();
MPoolConfigTest.Config((XmlElement)childNode,
ref envConfig.MPoolSystemCfg, compulsory);
}
// Configure environment with replication.
if (replication == true)
{
childNode = XMLReader.GetNode(xmlElem, "ReplicationConfig");
envConfig.RepSystemCfg = new ReplicationConfig();
ReplicationConfigTest.Config((XmlElement)childNode,
ref envConfig.RepSystemCfg, compulsory);
}
}
/*
* Confirm the fields/properties in the environment.
* Those set by setting functions are not checked here.
*/
public static void Confirm(XmlElement xmlElement,
DatabaseEnvironment env, bool compulsory,
bool logging, bool locking, bool mutex, bool mpool,
bool replication)
{
XmlElement childElem;
CacheInfo cacheInfo = new CacheInfo(0, 0, 0);
// Confirm environment configuration.
Configuration.ConfirmBool(xmlElement, "AutoCommit",
env.AutoCommit, compulsory);
Configuration.ConfirmBool(xmlElement, "CDB_ALLDB",
env.CDB_ALLDB, compulsory);
Configuration.ConfirmBool(xmlElement, "Create",
env.Create, compulsory);
Configuration.ConfirmStringList(xmlElement, "DataDirs",
env.DataDirs, compulsory);
Configuration.ConfirmString(xmlElement, "ErrorPrefix",
env.ErrorPrefix, compulsory);
Configuration.ConfirmBool(xmlElement, "ForceFlush",
env.ForceFlush, compulsory);
Configuration.ConfirmBool(xmlElement, "FreeThreaded",
env.FreeThreaded, compulsory);
Configuration.ConfirmBool(xmlElement, "InitRegions",
env.InitRegions, compulsory);
Configuration.ConfirmString(xmlElement, "IntermediateDirMode",
env.IntermediateDirMode, compulsory);
Configuration.ConfirmBool(xmlElement, "Lockdown",
env.Lockdown, compulsory);
Configuration.ConfirmUint(xmlElement, "LockTimeout",
env.LockTimeout, compulsory);
Configuration.ConfirmUint(xmlElement, "MaxTransactions",
env.MaxTransactions, compulsory);
Configuration.ConfirmBool(xmlElement, "NoBuffer",
env.NoBuffer, compulsory);
Configuration.ConfirmBool(xmlElement, "NoLocking",
env.NoLocking, compulsory);
Configuration.ConfirmBool(xmlElement, "NoMMap",
env.NoMMap, compulsory);
Configuration.ConfirmBool(xmlElement, "NoPanic",
env.NoPanic, compulsory);
Configuration.ConfirmBool(xmlElement, "Overwrite",
env.Overwrite, compulsory);
Configuration.ConfirmBool(xmlElement, "Private",
env.Private, compulsory);
Configuration.ConfirmBool(xmlElement, "Register",
env.Register, compulsory);
Configuration.ConfirmBool(xmlElement, "RunFatalRecovery",
env.RunFatalRecovery, compulsory);
Configuration.ConfirmBool(xmlElement, "RunRecovery",
env.RunRecovery, compulsory);
Configuration.ConfirmBool(xmlElement, "SystemMemory",
env.SystemMemory, compulsory);
Configuration.ConfirmString(xmlElement, "TempDir",
env.TempDir, compulsory);
Configuration.ConfirmBool(xmlElement, "TimeNotGranted",
env.TimeNotGranted, compulsory);
Configuration.ConfirmBool(xmlElement, "TxnNoSync",
env.TxnNoSync, compulsory);
Configuration.ConfirmBool(xmlElement, "TxnNoWait",
env.TxnNoWait, compulsory);
Configuration.ConfirmBool(xmlElement, "TxnSnapshot",
env.TxnSnapshot, compulsory);
Configuration.ConfirmDateTime(xmlElement, "TxnTimestamp",
env.TxnTimestamp, compulsory);
Configuration.ConfirmBool(xmlElement, "TxnWriteNoSync",
env.TxnWriteNoSync, compulsory);
Configuration.ConfirmBool(xmlElement, "UseMVCC",
env.UseMVCC, compulsory);
Configuration.ConfirmBool(xmlElement, "UseCDB",
env.UsingCDB, compulsory);
Configuration.ConfirmBool(xmlElement, "UseLocking",
env.UsingLocking, compulsory);
Configuration.ConfirmBool(xmlElement, "UseLogging",
env.UsingLogging, compulsory);
Configuration.ConfirmBool(xmlElement, "UseMPool",
env.UsingMPool, compulsory);
Configuration.ConfirmBool(xmlElement, "UseReplication",
env.UsingReplication, compulsory);
Configuration.ConfirmBool(xmlElement, "UseTxns",
env.UsingTxns, compulsory);
env.Verbosity = new VerboseMessages();
Configuration.ConfirmVerboseMessages(xmlElement,
"Verbosity", env.Verbosity, compulsory);
Configuration.ConfirmBool(xmlElement, "YieldCPU",
env.YieldCPU, compulsory);
/*
* If the locking subsystem is set, check the
* field/properties set in LockingConfig.
*/
if (locking == true)
{
childElem = (XmlElement)XMLReader.GetNode(
xmlElement, "LockingConfig");
Configuration.ConfirmByteMatrix(childElem,
"Conflicts", env.LockConflictMatrix,
compulsory);
Configuration.ConfirmDeadlockPolicy(
childElem, "DeadlockResolution",
env.DeadlockResolution, compulsory);
Configuration.ConfirmUint(childElem,
"Partitions", env.LockPartitions,
compulsory);
Configuration.ConfirmUint(childElem,
"MaxLockers", env.MaxLockers, compulsory);
Configuration.ConfirmUint(childElem,
"MaxLocks", env.MaxLocks, compulsory);
Configuration.ConfirmUint(childElem,
"MaxObjects", env.MaxObjects, compulsory);
}
/*
* If the locking subsystem is set, check the
* field/properties set in LogConfig.
*/
if (logging == true)
{
childElem = (XmlElement)XMLReader.GetNode(
xmlElement, "LogConfig");
Configuration.ConfirmBool(childElem,
"AutoRemove", env.LogAutoRemove,
compulsory);
Configuration.ConfirmUint(childElem,
"BufferSize", env.LogBufferSize,
compulsory);
Configuration.ConfirmString(childElem,
"Dir", env.LogDir, compulsory);
Configuration.ConfirmInt(childElem,
"FileMode", env.LogFileMode, compulsory);
Configuration.ConfirmBool(childElem,
"ForceSync", env.LogForceSync, compulsory);
Configuration.ConfirmBool(childElem,
"InMemory", env.LogInMemory, compulsory);
Configuration.ConfirmBool(childElem,
"NoBuffer", env.LogNoBuffer, compulsory);
Configuration.ConfirmUint(childElem,
"RegionSize", env.LogRegionSize,
compulsory);
Configuration.ConfirmBool(childElem,
"ZeroOnCreate", env.LogZeroOnCreate,
compulsory);
Configuration.ConfirmUint(childElem,
"MaxFileSize", env.MaxLogFileSize,
compulsory);
}
/*
* If the locking subsystem is set, check the
* field/properties set in MutexConfig.
*/
if (mutex == true)
{
childElem = (XmlElement)XMLReader.GetNode(
xmlElement, "MutexConfig");
Configuration.ConfirmUint(childElem,
"Alignment", env.MutexAlignment,
compulsory);
Configuration.ConfirmUint(childElem,
"MaxMutexes", env.MaxMutexes, compulsory);
try
{
Configuration.ConfirmUint(childElem,
"Increment", env.MutexIncrement,
compulsory);
}
catch (AssertionException)
{
Assert.AreEqual(0, env.MutexIncrement);
}
Configuration.ConfirmUint(childElem,
"NumTestAndSetSpins",
env.NumTestAndSetSpins, compulsory);
}
if (mpool == true)
{
childElem = (XmlElement)XMLReader.GetNode(
xmlElement, "MPoolConfig");
Configuration.ConfirmCacheSize(childElem,
"CacheSize", env.CacheSize, compulsory);
if (env.UsingMPool == false)
Configuration.ConfirmCacheSize(childElem,
"MaxCacheSize", env.MaxCacheSize, compulsory);
Configuration.ConfirmInt(childElem,
"MaxOpenFiles", env.MaxOpenFiles, compulsory);
Configuration.ConfirmMaxSequentialWrites(childElem,
"MaxSequentialWrites", env.SequentialWritePause,
env.MaxSequentialWrites, compulsory);
Configuration.ConfirmUint(childElem,
"MMapSize", env.MMapSize, compulsory);
}
if (replication == true)
{
childElem = (XmlElement)XMLReader.GetNode(
xmlElement, "ReplicationConfig");
Configuration.ConfirmUint(childElem,
"AckTimeout", env.RepAckTimeout, compulsory);
Configuration.ConfirmBool(childElem,
"BulkTransfer", env.RepBulkTransfer, compulsory);
Configuration.ConfirmUint(childElem,
"CheckpointDelay", env.RepCheckpointDelay, compulsory);
Configuration.ConfirmUint(childElem,
"ConnectionRetry", env.RepConnectionRetry, compulsory);
Configuration.ConfirmBool(childElem,
"DelayClientSync", env.RepDelayClientSync, compulsory);
Configuration.ConfirmUint(childElem,
"ElectionRetry", env.RepElectionRetry, compulsory);
Configuration.ConfirmUint(childElem,
"ElectionTimeout", env.RepElectionTimeout, compulsory);
Configuration.ConfirmUint(childElem,
"FullElectionTimeout", env.RepFullElectionTimeout,compulsory);
Configuration.ConfirmUint(childElem,
"HeartbeatMonitor", env.RepHeartbeatMonitor, compulsory);
Configuration.ConfirmUint(childElem,
"HeartbeatSend", env.RepHeartbeatSend, compulsory);
Configuration.ConfirmUint(childElem,
"LeaseTimeout", env.RepLeaseTimeout, compulsory);
Configuration.ConfirmBool(childElem,
"AutoInit", env.RepAutoInit, compulsory);
Configuration.ConfirmBool(childElem,
"NoBlocking", env.RepNoBlocking, compulsory);
Configuration.ConfirmUint(childElem,
"Priority", env.RepPriority, compulsory);
Configuration.ConfirmAckPolicy(childElem,
"RepMgrAckPolicy", env.RepMgrAckPolicy, compulsory);
Configuration.ConfirmBool(childElem,
"Strict2Site", env.RepStrict2Site, compulsory);
Configuration.ConfirmBool(childElem,
"UseMasterLeases", env.RepUseMasterLeases, compulsory);
}
}
}
}