libdb/test/csharp/BTreeCursorTest.cs
2011-09-13 13:44:24 -04:00

1258 lines
36 KiB
C#

/*-
* 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.IO;
using System.Text;
using System.Threading;
using NUnit.Framework;
using BerkeleyDB;
namespace CsharpAPITest
{
[TestFixture]
public class BTreeCursorTest : CSharpTestFixture
{
private DatabaseEnvironment paramEnv;
private BTreeDatabase paramDB;
private EventWaitHandle signal;
private delegate void BTCursorMoveFuncDelegate(
BTreeCursor cursor, LockingInfo lockingInfo);
private BTCursorMoveFuncDelegate btCursorFunc;
[TestFixtureSetUp]
public void SetUpTestFixture()
{
testFixtureName = "BTreeCursorTest";
base.SetUpTestfixture();
}
[Test]
public void TestAddKeyFirst()
{
BTreeDatabase db;
BTreeCursor cursor;
KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
testName = "TestAddKeyFirst";
SetUpTest(true);
// Add record("key", "data") into database.
CursorTest.GetCursorInBtreeDBWithoutEnv(
testHome, testName, out db, out cursor);
CursorTest.AddOneByCursor(db, cursor);
// Add record("key","data1") as the first of the data item of "key".
pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(
new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key")),
new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data1")));
cursor.Add(pair, Cursor.InsertLocation.FIRST);
// Confirm the record is added as the first of the data item of "key".
cursor.Move(new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key")), true);
Assert.AreEqual(ASCIIEncoding.ASCII.GetBytes("data1"),
cursor.Current.Value.Data);
cursor.Close();
db.Close();
}
[Test]
public void TestAddKeyLast()
{
BTreeDatabase db;
BTreeCursor cursor;
KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
testName = "TestAddKeyLast";
SetUpTest(true);
// Add record("key", "data") into database.
CursorTest.GetCursorInBtreeDBWithoutEnv(testHome, testName,
out db, out cursor);
CursorTest.AddOneByCursor(db, cursor);
// Add new record("key","data1") as the last of the data item of "key".
pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(
new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key")),
new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data1")));
cursor.Add(pair, Cursor.InsertLocation.LAST);
// Confirm the record is added as the first of the data item of "key".
cursor.Move(new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key")), true);
Assert.AreNotEqual(ASCIIEncoding.ASCII.GetBytes("data1"),
cursor.Current.Value.Data);
cursor.Close();
db.Close();
}
[Test]
public void TestAddUnique()
{
BTreeDatabase db;
BTreeCursor cursor;
KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
testName = "TestAddUnique";
SetUpTest(true);
// Open a database and cursor.
BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
dbConfig.Creation = CreatePolicy.IF_NEEDED;
// To put no duplicate data, the database should be set to be sorted.
dbConfig.Duplicates = DuplicatesPolicy.SORTED;
db = BTreeDatabase.Open(testHome + "/" + testName + ".db", dbConfig);
cursor = db.Cursor();
// Add record("key", "data") into database.
CursorTest.AddOneByCursor(db, cursor);
// Fail to add duplicate record("key","data").
pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(
new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key")),
new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data")));
try
{
cursor.AddUnique(pair);
}
catch (KeyExistException)
{
}
finally
{
cursor.Close();
db.Close();
}
}
[Test]
public void TestDuplicateWithSamePos()
{
BTreeDatabase db;
BTreeDatabaseConfig dbConfig;
BTreeCursor cursor, dupCursor;
DatabaseEnvironment env;
DatabaseEnvironmentConfig envConfig;
DatabaseEntry key, data;
KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
Transaction txn;
testName = "TestDuplicateWithSamePos";
SetUpTest(true);
envConfig = new DatabaseEnvironmentConfig();
envConfig.Create = true;
envConfig.UseMPool = true;
envConfig.UseTxns = true;
envConfig.NoMMap = false;
env = DatabaseEnvironment.Open(testHome, envConfig);
txn = env.BeginTransaction();
dbConfig = new BTreeDatabaseConfig();
dbConfig.Creation = CreatePolicy.IF_NEEDED;
dbConfig.Env = env;
db = BTreeDatabase.Open(testName + ".db", dbConfig, txn);
key = new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key"));
data = new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data"));
pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(key, data);
db.Put(key, data, txn);
txn.Commit();
txn = env.BeginTransaction();
cursor = db.Cursor(txn);
cursor.Move(key, true);
//Duplicate a new cursor to the same position.
dupCursor = cursor.Duplicate(true);
// Overwrite the record.
dupCursor.Overwrite(new DatabaseEntry(
ASCIIEncoding.ASCII.GetBytes("newdata")));
// Confirm that the original data doesn't exist.
Assert.IsFalse(dupCursor.Move(pair, true));
dupCursor.Close();
cursor.Close();
txn.Commit();
db.Close();
env.Close();
}
[Test, ExpectedException(typeof(ExpectedTestException))]
public void TestDuplicateToDifferentPos()
{
BTreeDatabase db;
BTreeDatabaseConfig dbConfig;
BTreeCursor cursor, dupCursor;
DatabaseEnvironment env;
DatabaseEnvironmentConfig envConfig;
DatabaseEntry key, data;
KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
Transaction txn;
testName = "TestDuplicateToDifferentPos";
SetUpTest(true);
envConfig = new DatabaseEnvironmentConfig();
envConfig.Create = true;
envConfig.UseMPool = true;
envConfig.UseTxns = true;
envConfig.NoMMap = false;
env = DatabaseEnvironment.Open(testHome, envConfig);
txn = env.BeginTransaction();
dbConfig = new BTreeDatabaseConfig();
dbConfig.Creation = CreatePolicy.IF_NEEDED;
dbConfig.Env = env;
db = BTreeDatabase.Open(testName + ".db", dbConfig, txn);
key = new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key"));
data = new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data"));
pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(key, data);
db.Put(key, data, txn);
txn.Commit();
txn = env.BeginTransaction();
cursor = db.Cursor(txn);
cursor.Move(key, true);
//Duplicate a new cursor to the same position.
dupCursor = cursor.Duplicate(false);
/*
* The duplicate cursor points to nothing so overwriting the
* record is not allowed.
*/
try
{
dupCursor.Overwrite(new DatabaseEntry(
ASCIIEncoding.ASCII.GetBytes("newdata")));
}
catch (DatabaseException)
{
throw new ExpectedTestException();
}
finally
{
dupCursor.Close();
cursor.Close();
txn.Commit();
db.Close();
env.Close();
}
}
[Test]
public void TestInsertAfter()
{
BTreeDatabase db;
BTreeCursor cursor;
DatabaseEntry data;
KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
testName = "TestInsertAfter";
SetUpTest(true);
// Add record("key", "data") into database.
CursorTest.GetCursorInBtreeDBWithoutEnv(testHome, testName,
out db, out cursor);
CursorTest.AddOneByCursor(db, cursor);
// Insert the new record("key","data1") after the record("key", "data").
data = new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data1"));
cursor.Insert(data, Cursor.InsertLocation.AFTER);
/*
* Move the cursor to the record("key", "data") and confirm that
* the next record is the one just inserted.
*/
pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(
new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key")),
new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data")));
Assert.IsTrue(cursor.Move(pair, true));
Assert.IsTrue(cursor.MoveNext());
Assert.AreEqual(ASCIIEncoding.ASCII.GetBytes("key"), cursor.Current.Key.Data);
Assert.AreEqual(ASCIIEncoding.ASCII.GetBytes("data1"), cursor.Current.Value.Data);
cursor.Close();
db.Close();
}
[Test]
public void TestMoveFirstMultipleAndMultipleKey()
{
testName = "TestMoveFirstMultipleAndMultipleKey";
SetUpTest(true);
string btreeDBFileName = testHome + "/" +
testName + ".db";
BTreeDatabase db;
BTreeCursor cursor;
KeyValuePair<DatabaseEntry, MultipleDatabaseEntry> pair;
MultipleKeyDatabaseEntry multiPair;
int cnt;
int[] size = new int[2];
size[0] = 0;
size[1] = 1024;
BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
dbConfig.Creation = CreatePolicy.ALWAYS;
dbConfig.Duplicates = DuplicatesPolicy.UNSORTED;
dbConfig.PageSize = 1024;
GetMultipleDB(btreeDBFileName, dbConfig, null, out db, out cursor);
for (int i = 0; i < 2; i++) {
cnt = 0;
if (size[i] == 0)
cursor.MoveFirstMultiple();
else
cursor.MoveFirstMultiple(size[i]);
pair = cursor.CurrentMultiple;
foreach (DatabaseEntry dbt in pair.Value)
cnt++;
Assert.AreEqual(1, cnt);
}
for (int i = 0; i < 2; i++) {
cnt = 0;
if (size[i] == 0)
cursor.MoveFirstMultipleKey();
else
cursor.MoveFirstMultipleKey(size[i]);
multiPair = cursor.CurrentMultipleKey;
foreach (KeyValuePair<DatabaseEntry, DatabaseEntry>
dbt in multiPair)
cnt++;
Assert.Less(1, cnt);
}
cursor.Close();
db.Close();
}
[Test]
public void TestMoveMultiple()
{
testName = "TestMoveMultiple";
SetUpTest(true);
string btreeDBFileName = testHome + "/" +
testName + ".db";
BTreeDatabase db;
BTreeCursor cursor;
DatabaseEntry key;
KeyValuePair<DatabaseEntry, MultipleDatabaseEntry> pair;
int cnt;
BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
dbConfig.Creation = CreatePolicy.ALWAYS;
dbConfig.Duplicates = DuplicatesPolicy.UNSORTED;
dbConfig.PageSize = 1024;
GetMultipleDB(btreeDBFileName, dbConfig, null, out db, out cursor);
// Move cursor to pairs with exact 99 as its key.
cnt = 0;
key = new DatabaseEntry(BitConverter.GetBytes((int)99));
cursor.MoveMultiple(key, true);
pair = cursor.CurrentMultiple;
Assert.AreEqual(99, BitConverter.ToInt32(pair.Key.Data, 0));
foreach (DatabaseEntry dbt in pair.Value)
cnt++;
Assert.AreEqual(2, cnt);
// Move cursor to pairs with the smallest key larger than 100.
cnt = 0;
key = new DatabaseEntry(BitConverter.GetBytes((int)100));
cursor.MoveMultiple(key, false);
pair = cursor.CurrentMultiple;
Assert.AreEqual(101, BitConverter.ToInt32(pair.Key.Data, 0));
foreach (DatabaseEntry dbt in pair.Value)
cnt++;
Assert.AreEqual(1, cnt);
cursor.Close();
db.Close();
}
[Test]
public void TestMoveMultipleKey()
{
testName = "TestMoveMultipleKey";
SetUpTest(true);
string btreeDBFileName = testHome + "/" +
testName + ".db";
BTreeDatabase db;
BTreeCursor cursor;
DatabaseEntry key;
MultipleKeyDatabaseEntry mulPair; ;
int cnt;
BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
dbConfig.Creation = CreatePolicy.ALWAYS;
dbConfig.Duplicates = DuplicatesPolicy.UNSORTED;
dbConfig.PageSize = 1024;
GetMultipleDB(btreeDBFileName, dbConfig, null, out db, out cursor);
/*
* Bulk retrieve key/value pair from the pair whose key
* is exact 99.
*/
cnt = 0;
key = new DatabaseEntry(BitConverter.GetBytes((int)99));
cursor.MoveMultipleKey(key, true);
mulPair = cursor.CurrentMultipleKey;
foreach (KeyValuePair<DatabaseEntry, DatabaseEntry>
pair in mulPair) {
Assert.GreaterOrEqual(3,
BitConverter.ToInt32(pair.Key.Data, 0) - 98);
cnt++;
}
Assert.AreEqual(3, cnt);
/*
* Bulk retrieve key/value pair from the pair whose key
* is the smallest one larger than 100.
*/
cnt = 0;
key = new DatabaseEntry(BitConverter.GetBytes((int)100));
cursor.MoveMultipleKey(key, false);
mulPair = cursor.CurrentMultipleKey;
foreach (KeyValuePair<DatabaseEntry, DatabaseEntry>
pair in mulPair) {
Assert.AreEqual(101,
BitConverter.ToInt32(pair.Key.Data, 0));
cnt++;
}
Assert.LessOrEqual(1, cnt);
cnt = 0;
key = new DatabaseEntry(BitConverter.GetBytes((int)100));
cursor.MoveMultipleKey(key, false, 1024);
mulPair = cursor.CurrentMultipleKey;
foreach (KeyValuePair<DatabaseEntry, DatabaseEntry>
pair in mulPair) {
Assert.AreEqual(101,
BitConverter.ToInt32(pair.Key.Data, 0));
Assert.AreEqual(101,
BitConverter.ToInt32(pair.Value.Data, 0));
cnt++;
}
Assert.LessOrEqual(1, cnt);
cursor.Close();
db.Close();
}
[Test]
public void TestMoveMultipleKeyWithRecno()
{
testName = "TestMoveMultipleKeyWithRecno";
SetUpTest(true);
string btreeDBFileName = testHome + "/" +
testName + ".db";
BTreeDatabase db;
BTreeCursor cursor;
MultipleKeyDatabaseEntry multiDBT;
int cnt;
BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
dbConfig.UseRecordNumbers = true;
dbConfig.Creation = CreatePolicy.IF_NEEDED;
dbConfig.PageSize = 1024;
GetMultipleDB(btreeDBFileName, dbConfig, null, out db, out cursor);
cnt = 0;
cursor.MoveMultipleKey(98);
multiDBT = cursor.CurrentMultipleKey;
foreach (KeyValuePair<DatabaseEntry, DatabaseEntry>
pair in multiDBT)
cnt++;
Assert.AreEqual(3, cnt);
cnt = 0;
cursor.MoveMultipleKey(98, 1024);
multiDBT = cursor.CurrentMultipleKey;
foreach (KeyValuePair<DatabaseEntry, DatabaseEntry>
pair in multiDBT)
cnt++;
Assert.AreEqual(3, cnt);
cursor.Close();
db.Close();
}
[Test]
public void TestMoveMultiplePairs()
{
testName = "TestMoveMultiplePairs";
SetUpTest(true);
string btreeDBFileName = testHome + "/" +
testName + ".db";
BTreeDatabase db;
BTreeCursor cursor;
DatabaseEntry key, data;
KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
MultipleKeyDatabaseEntry multiKeyDBTs1, multiKeyDBTs2;
int cnt;
BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
dbConfig.Creation = CreatePolicy.ALWAYS;
dbConfig.Duplicates = DuplicatesPolicy.SORTED;
dbConfig.PageSize = 1024;
GetMultipleDB(btreeDBFileName, dbConfig, null, out db, out cursor);
/*
* Bulk retrieve pairs from the pair whose key/data
* is exact 99/99.
*/
cnt = 0;
key = new DatabaseEntry(BitConverter.GetBytes((int)99));
data = new DatabaseEntry(BitConverter.GetBytes((int)99));
pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(key, data);
cursor.MoveMultipleKey(pair, true);
multiKeyDBTs1 = cursor.CurrentMultipleKey;
foreach (KeyValuePair<DatabaseEntry, DatabaseEntry>
p in multiKeyDBTs1)
cnt++;
Assert.AreEqual(3, cnt);
// Bulk retrieve pairs from the pair whose key is exact 99.
cnt = 0;
key = new DatabaseEntry(BitConverter.GetBytes((int)99));
data = new DatabaseEntry(BitConverter.GetBytes((int)98));
cursor.MoveMultipleKey(pair, true);
multiKeyDBTs2 = cursor.CurrentMultipleKey;
foreach (KeyValuePair<DatabaseEntry, DatabaseEntry>
dbts in multiKeyDBTs2)
cnt++;
Assert.AreEqual(3, cnt);
/*
* Bulk retrieve pairs from the pair whose key is
* exact 99 in buffer size of 1024k.
*/
cnt = 0;
key = new DatabaseEntry(BitConverter.GetBytes((int)99));
data = new DatabaseEntry(BitConverter.GetBytes((int)102));
cursor.MoveMultipleKey(pair, true, 1024);
multiKeyDBTs2 = cursor.CurrentMultipleKey;
foreach (KeyValuePair<DatabaseEntry, DatabaseEntry>
dbts in multiKeyDBTs2)
cnt++;
Assert.AreEqual(3, cnt);
cursor.Close();
db.Close();
}
[Test]
public void TestMoveMultiplePairWithKey()
{
testName = "TestMoveMultiplePairWithKey";
SetUpTest(true);
string btreeDBFileName = testHome + "/" +
testName + ".db";
BTreeDatabase db;
BTreeCursor cursor;
DatabaseEntry key, data;
KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
KeyValuePair<DatabaseEntry, MultipleDatabaseEntry> mulPair;
int cnt;
BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
dbConfig.Creation = CreatePolicy.ALWAYS;
dbConfig.Duplicates = DuplicatesPolicy.UNSORTED;
dbConfig.PageSize = 1024;
GetMultipleDB(btreeDBFileName, dbConfig, null, out db, out cursor);
/*
* Move the cursor to pairs with exact 99 as its key
* and 99 as its data.
*/
cnt = 0;
key = new DatabaseEntry(BitConverter.GetBytes((int)99));
data = new DatabaseEntry(BitConverter.GetBytes((int)99));
pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(key, data);
cursor.MoveMultiple(pair, true);
mulPair = cursor.CurrentMultiple;
Assert.AreEqual(99, BitConverter.ToInt32(mulPair.Key.Data, 0));
foreach (DatabaseEntry dbt in mulPair.Value) {
Assert.AreEqual(99, BitConverter.ToInt32(dbt.Data, 0));
cnt++;
}
Assert.AreEqual(1, cnt);
// Move cursor to pairs with the smallest key larger than 100.
cnt = 0;
key = new DatabaseEntry(BitConverter.GetBytes((int)100));
data = new DatabaseEntry(BitConverter.GetBytes((int)100));
cursor.MoveMultiple(pair, false);
mulPair = cursor.CurrentMultiple;
Assert.AreEqual(99, BitConverter.ToInt32(mulPair.Key.Data, 0));
foreach (DatabaseEntry dbt in mulPair.Value) {
Assert.GreaterOrEqual(1,
BitConverter.ToInt32(dbt.Data, 0) - 99);
cnt++;
}
Assert.AreEqual(1, cnt);
cursor.Close();
db.Close();
}
[Test]
public void TestMoveNextMultipleKey()
{
testName = "TestMoveNextMultipleKey";
SetUpTest(true);
BTreeDatabase db;
BTreeCursor cursor;
DatabaseEnvironment env;
Transaction txn;
int cnt = 0;
BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
dbConfig.Creation = CreatePolicy.ALWAYS;
dbConfig.Duplicates = DuplicatesPolicy.UNSORTED;
GetMultipleDB(testHome, testName + ".db", dbConfig,
out env, out txn, out db, out cursor);
/*
* Position the cursor to the first record, and bulk get
* all other records.
*/
Assert.True(cursor.MoveFirst());
Assert.True(cursor.MoveNextMultipleKey());
MultipleKeyDatabaseEntry pairs =
cursor.CurrentMultipleKey;
foreach (KeyValuePair<DatabaseEntry, DatabaseEntry> p
in pairs)
cnt++;
Assert.AreEqual(cnt, 100);
// Bulk read uncommitted records.
cnt = 0;
LockingInfo lockingInfo = new LockingInfo();
Assert.True(cursor.MoveFirst(lockingInfo));
lockingInfo.IsolationDegree = Isolation.DEGREE_ONE;
Assert.True(cursor.MoveNextMultipleKey(lockingInfo));
pairs = cursor.CurrentMultipleKey;
foreach (KeyValuePair<DatabaseEntry, DatabaseEntry> p
in pairs)
cnt++;
Assert.AreEqual(cnt, 100);
cursor.Dispose();
txn.Commit();
/*
* Insert duplicate records of the key in the last
* record.
*/
txn = env.BeginTransaction();
cursor = db.Cursor(txn);
Assert.IsTrue(cursor.MoveLast());
DatabaseEntry key = cursor.Current.Key;
for (int i = 200; i < 800; i++)
cursor.Insert(new DatabaseEntry(
BitConverter.GetBytes(i)),
Cursor.InsertLocation.AFTER);
/*
* Move to the first duplicate records, and bulk read
* all duplicate ones.
*/
cnt = 0;
Assert.True(cursor.Move(key, true));
while (cursor.MoveNextDuplicateMultipleKey(
(int)db.Pagesize)) {
pairs = cursor.CurrentMultipleKey;
foreach (KeyValuePair<
DatabaseEntry, DatabaseEntry> p in pairs) {
Assert.AreEqual(key.Data, p.Key.Data);
cnt++;
}
}
Assert.AreEqual(cnt, 600);
cursor.Close();
db.Close();
txn.Commit();
env.Close();
}
[Test]
public void TestMoveMultipleWithRecno()
{
testName = "TestMoveMultipleWithRecno";
SetUpTest(true);
string btreeDBFileName = testHome + "/" +
testName + ".db";
BTreeDatabase db;
BTreeCursor cursor;
KeyValuePair<DatabaseEntry, MultipleDatabaseEntry> pair;
int cnt;
BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
dbConfig.Creation = CreatePolicy.ALWAYS;
dbConfig.PageSize = 1024;
dbConfig.UseRecordNumbers = true;
GetMultipleDB(btreeDBFileName, dbConfig, null, out db, out cursor);
// Move cursor to the No.100 record.
cnt = 0;
cursor.MoveMultiple(100);
pair = cursor.CurrentMultiple;
Assert.AreEqual(100, BitConverter.ToInt32(pair.Key.Data, 0));
foreach (DatabaseEntry dbt in pair.Value)
cnt++;
Assert.AreEqual(1, cnt);
// Move cursor to the No.100 record with buffer size of 1024k.
cnt = 0;
cursor.MoveMultiple(100, 1024);
pair = cursor.CurrentMultiple;
Assert.AreEqual(100, BitConverter.ToInt32(pair.Key.Data, 0));
foreach (DatabaseEntry dbt in pair.Value)
cnt++;
Assert.AreEqual(1, cnt);
cursor.Close();
db.Close();
}
[Test]
public void TestMoveNextDuplicateMultipleAndMultipleKey()
{
testName = "TestMoveNextDuplicateMultipleAndMultipleKey";
SetUpTest(true);
string btreeDBFileName = testHome + "/" +
testName + ".db";
BTreeDatabase db;
BTreeCursor cursor;
DatabaseEntry key, data;
KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
KeyValuePair<DatabaseEntry, MultipleDatabaseEntry> pairs;
MultipleKeyDatabaseEntry multiPair;
int cnt;
int[] size = new int[2];
size[0] = 0;
size[1] = 1024;
BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
dbConfig.Creation = CreatePolicy.ALWAYS;
dbConfig.Duplicates = DuplicatesPolicy.SORTED;
dbConfig.PageSize = 1024;
GetMultipleDB(btreeDBFileName, dbConfig, null, out db, out cursor);
key = new DatabaseEntry(BitConverter.GetBytes(99));
data = new DatabaseEntry(BitConverter.GetBytes(99));
pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(key, data);
for (int j = 0; j < 2; j++) {
for (int i = 0; i < 2; i++) {
cnt = 0;
cursor.Move(pair, true);
if (j == 0) {
if (size[i] == 0)
Assert.IsTrue(cursor.MoveNextDuplicateMultiple());
else
Assert.IsTrue(cursor.MoveNextDuplicateMultiple(size[i]));
pairs = cursor.CurrentMultiple;
foreach (DatabaseEntry dbt in pairs.Value) {
Assert.AreEqual(100, BitConverter.ToInt32(dbt.Data, 0));
cnt++;
}
Assert.AreEqual(1, cnt);
} else {
if (size[i] == 0)
Assert.IsTrue(cursor.MoveNextDuplicateMultipleKey());
else
Assert.IsTrue(cursor.MoveNextDuplicateMultipleKey(size[i]));
multiPair = cursor.CurrentMultipleKey;
foreach (KeyValuePair<DatabaseEntry, DatabaseEntry> p in multiPair) {
Assert.AreEqual(100, BitConverter.ToInt32(p.Value.Data, 0));
cnt++;
}
Assert.AreEqual(1, cnt);
}
}
}
cursor.Close();
db.Close();
}
[Test]
public void TestMoveNextUniqueMultipleAndMultipleKey()
{
testName = "TestMoveNextUniqueMultipleAndMultipleKey";
SetUpTest(true);
string btreeDBFileName = testHome + "/" +
testName + ".db";
BTreeDatabase db;
BTreeCursor cursor;
DatabaseEntry key, data;
KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
KeyValuePair<DatabaseEntry, MultipleDatabaseEntry> pairs;
MultipleKeyDatabaseEntry multiPair;
int cnt;
int[] size = new int[2];
size[0] = 0;
size[1] = 1024;
BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
dbConfig.Creation = CreatePolicy.ALWAYS;
dbConfig.Duplicates = DuplicatesPolicy.UNSORTED;
dbConfig.PageSize = 1024;
GetMultipleDB(btreeDBFileName, dbConfig, null, out db, out cursor);
key = new DatabaseEntry(BitConverter.GetBytes(99));
data = new DatabaseEntry(BitConverter.GetBytes(99));
pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(key, data);
for (int j = 0; j < 2; j++) {
for (int i = 0; i < 2; i++) {
cnt = 0;
cursor.Move(pair, true);
if (j == 0) {
if (size[i] == 0)
Assert.IsTrue(cursor.MoveNextUniqueMultiple());
else
Assert.IsTrue(cursor.MoveNextUniqueMultiple(size[i]));
pairs = cursor.CurrentMultiple;
foreach (DatabaseEntry dbt in pairs.Value) {
Assert.AreEqual(101, BitConverter.ToInt32(dbt.Data, 0));
cnt++;
}
Assert.AreEqual(1, cnt);
} else {
if (size[i] == 0)
Assert.IsTrue(cursor.MoveNextUniqueMultipleKey());
else
Assert.IsTrue(cursor.MoveNextUniqueMultipleKey(size[i]));
multiPair = cursor.CurrentMultipleKey;
foreach (KeyValuePair<DatabaseEntry, DatabaseEntry> p in multiPair) {
Assert.AreEqual(101, BitConverter.ToInt32(p.Value.Data, 0));
cnt++;
}
Assert.AreEqual(1, cnt);
}
}
}
cursor.Close();
db.Close();
}
[Test]
public void TestRefreshMultipleAndMultipleKey()
{
testName = "TestRefreshMultipleAndMultipleKey";
SetUpTest(true);
string btreeDBFileName = testHome + "/" +
testName + ".db";
BTreeDatabase db;
BTreeCursor cursor;
DatabaseEntry key, data;
KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
KeyValuePair<DatabaseEntry, MultipleDatabaseEntry> pairs;
MultipleKeyDatabaseEntry multiPair;
int cnt;
int[] size = new int[2];
size[0] = 0;
size[1] = 1024;
BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
dbConfig.Creation = CreatePolicy.ALWAYS;
dbConfig.Duplicates = DuplicatesPolicy.SORTED;
dbConfig.PageSize = 1024;
GetMultipleDB(btreeDBFileName, dbConfig, null, out db, out cursor);
key = new DatabaseEntry(BitConverter.GetBytes(99));
data = new DatabaseEntry(BitConverter.GetBytes(99));
pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(key, data);
for (int j = 0; j < 2; j++) {
for (int i = 0; i < 2; i++) {
cnt = 0;
cursor.Move(pair, true);
if (j == 0) {
if (size[i] == 0)
Assert.IsTrue(cursor.RefreshMultiple());
else
Assert.IsTrue(cursor.RefreshMultiple(size[i]));
pairs = cursor.CurrentMultiple;
foreach (DatabaseEntry dbt in pairs.Value)
cnt++;
Assert.AreEqual(2, cnt);
} else {
if (size[i] == 0)
Assert.IsTrue(cursor.RefreshMultipleKey());
else
Assert.IsTrue(cursor.RefreshMultipleKey(size[i]));
multiPair = cursor.CurrentMultipleKey;
foreach (KeyValuePair<DatabaseEntry, DatabaseEntry> p in multiPair)
cnt++;
Assert.AreEqual(3, cnt);
}
}
}
cursor.Close();
db.Close();
}
private void GetMultipleDB(string dbFileName,
BTreeDatabaseConfig dbConfig, Transaction txn,
out BTreeDatabase db, out BTreeCursor cursor)
{
if (txn == null) {
db = BTreeDatabase.Open(dbFileName, dbConfig);
cursor = db.Cursor();
} else {
db = BTreeDatabase.Open(
dbFileName, dbConfig, txn);
CursorConfig cursorConfig = new CursorConfig();
cursor = db.Cursor(cursorConfig, txn);
}
KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
DatabaseEntry key, data;
for (int i = 1; i < 100; i++) {
key = new DatabaseEntry(BitConverter.GetBytes(i));
data = new DatabaseEntry(BitConverter.GetBytes(i));
pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(key, data);
cursor.Add(pair);
}
if (dbConfig.UseRecordNumbers == true) {
byte[] bytes = new byte[512];
for (int i = 0; i < 512; i++)
bytes[i] = (byte)i;
key = new DatabaseEntry(BitConverter.GetBytes(100));
data = new DatabaseEntry(bytes);
pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(key, data);
cursor.Add(pair);
} else {
if (dbConfig.Duplicates == DuplicatesPolicy.UNSORTED ||
dbConfig.Duplicates == DuplicatesPolicy.SORTED) {
key = new DatabaseEntry(BitConverter.GetBytes(99));
data = new DatabaseEntry(BitConverter.GetBytes(100));
pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(key, data);
cursor.Add(pair);
}
key = new DatabaseEntry(BitConverter.GetBytes(101));
data = new DatabaseEntry(BitConverter.GetBytes(101));
pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(key, data);
cursor.Add(pair);
}
}
private void GetMultipleDB(string home, string dbFileName,
BTreeDatabaseConfig dbConfig, out DatabaseEnvironment env,
out Transaction txn, out BTreeDatabase db,
out BTreeCursor cursor)
{
DatabaseEnvironmentConfig envConfig =
new DatabaseEnvironmentConfig();
envConfig.Create = true;
envConfig.UseTxns = true;
envConfig.UseLocking = true;
envConfig.UseLogging = true;
envConfig.UseMPool = true;
env = DatabaseEnvironment.Open(home, envConfig);
txn = env.BeginTransaction();
if (dbConfig == null)
dbConfig = new BTreeDatabaseConfig();
dbConfig.Env = env;
GetMultipleDB(dbFileName, dbConfig, txn, out db,
out cursor);
}
[Test]
public void TestInsertBefore()
{
BTreeDatabase db;
BTreeCursor cursor;
DatabaseEntry data;
KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
testName = "TestInsertBefore";
SetUpTest(true);
// Add record("key", "data") into database.
CursorTest.GetCursorInBtreeDBWithoutEnv(
testHome, testName, out db, out cursor);
CursorTest.AddOneByCursor(db, cursor);
// Insert the new record("key","data1") before the record("key", "data").
data = new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data1"));
cursor.Insert(data, Cursor.InsertLocation.BEFORE);
/*
* Move the cursor to the record("key", "data") and confirm
* that the previous record is the one just inserted.
*/
pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(
new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key")),
new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data")));
Assert.IsTrue(cursor.Move(pair, true));
Assert.IsTrue(cursor.MovePrev());
Assert.AreEqual(ASCIIEncoding.ASCII.GetBytes("key"),cursor.Current.Key.Data);
Assert.AreEqual(ASCIIEncoding.ASCII.GetBytes("data1"), cursor.Current.Value.Data);
cursor.Close();
db.Close();
}
[Test]
public void TestMoveToRecno()
{
BTreeDatabase db;
BTreeCursor cursor;
testName = "TestMoveToRecno";
SetUpTest(true);
GetCursorInBtreeDBUsingRecno(testHome, testName,
out db, out cursor);
for (int i = 0; i < 10; i++)
db.Put(
new DatabaseEntry(BitConverter.GetBytes(i)),
new DatabaseEntry(BitConverter.GetBytes(i)));
MoveCursorToRecno(cursor, null);
cursor.Close();
db.Close();
}
[Test]
public void TestMoveToRecnoWithRMW()
{
testName = "TestMoveToRecnoWithRMW";
SetUpTest(true);
btCursorFunc = new BTCursorMoveFuncDelegate(
MoveCursorToRecno);
// Move to a specified key and a key/data pair.
MoveWithRMW(testHome, testName);
}
[Test]
public void TestRecno()
{
BTreeDatabase db;
BTreeCursor cursor;
testName = "TestRecno";
SetUpTest(true);
GetCursorInBtreeDBUsingRecno(testHome, testName,
out db, out cursor);
for (int i = 0; i < 10; i++)
db.Put(
new DatabaseEntry(BitConverter.GetBytes(i)),
new DatabaseEntry(BitConverter.GetBytes(i)));
ReturnRecno(cursor, null);
cursor.Close();
db.Close();
}
[Test]
public void TestRecnoWithRMW()
{
testName = "TestRecnoWithRMW";
SetUpTest(true);
// Use MoveCursorToRecno() as its move function.
btCursorFunc = new BTCursorMoveFuncDelegate(
ReturnRecno);
// Move to a specified key and a key/data pair.
MoveWithRMW(testHome, testName);
}
/*
* Move the cursor according to recno. The recno
* starts from 1 and is increased by 1.
*/
public void MoveCursorToRecno(BTreeCursor cursor,
LockingInfo lck)
{
for (uint i = 1; i <= 5; i++)
if (lck == null)
Assert.IsTrue(cursor.Move(i));
else
Assert.IsTrue(cursor.Move(i, lck));
}
/*l
* Move the cursor according to a given recno and
* return the current record's recno. The given recno
* and the one got from the cursor should be the same.
*/
public void ReturnRecno(BTreeCursor cursor,
LockingInfo lck)
{
for (uint i = 1; i <= 5; i++)
if (lck == null)
{
if (cursor.Move(i) == true)
Assert.AreEqual(i, cursor.Recno());
}
else
{
if (cursor.Move(i, lck) == true)
Assert.AreEqual(i, cursor.Recno(lck));
}
}
public void GetCursorInBtreeDBUsingRecno(string home,
string name, out BTreeDatabase db,
out BTreeCursor cursor)
{
string dbFileName = home + "/" + name + ".db";
BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
dbConfig.UseRecordNumbers = true;
dbConfig.Creation = CreatePolicy.IF_NEEDED;
db = BTreeDatabase.Open(dbFileName, dbConfig);
cursor = db.Cursor();
}
public void RdMfWt()
{
Transaction txn = paramEnv.BeginTransaction();
BTreeCursor dbc = paramDB.Cursor(txn);
try
{
LockingInfo lck = new LockingInfo();
lck.ReadModifyWrite = true;
// Read record.
btCursorFunc(dbc, lck);
// Block the current thread until event is set.
signal.WaitOne();
// Write new records into database.
DatabaseEntry key = new DatabaseEntry(BitConverter.GetBytes(55));
DatabaseEntry data = new DatabaseEntry(BitConverter.GetBytes(55));
dbc.Add(new KeyValuePair<DatabaseEntry, DatabaseEntry>(key, data));
dbc.Close();
txn.Commit();
}
catch (DeadlockException)
{
dbc.Close();
txn.Abort();
}
}
public void MoveWithRMW(string home, string name)
{
paramEnv = null;
paramDB = null;
// Open the environment.
DatabaseEnvironmentConfig envCfg =
new DatabaseEnvironmentConfig();
envCfg.Create = true;
envCfg.FreeThreaded = true;
envCfg.UseLocking = true;
envCfg.UseLogging = true;
envCfg.UseMPool = true;
envCfg.UseTxns = true;
paramEnv = DatabaseEnvironment.Open(home, envCfg);
// Open database in transaction.
Transaction openTxn = paramEnv.BeginTransaction();
BTreeDatabaseConfig cfg = new BTreeDatabaseConfig();
cfg.Creation = CreatePolicy.ALWAYS;
cfg.Env = paramEnv;
cfg.FreeThreaded = true;
cfg.PageSize = 4096;
// Use record number.
cfg.UseRecordNumbers = true;
paramDB = BTreeDatabase.Open(name + ".db", cfg, openTxn);
openTxn.Commit();
/*
* Put 10 different, 2 duplicate and another different
* records into database.
*/
Transaction txn = paramEnv.BeginTransaction();
for (int i = 0; i < 13; i++)
{
DatabaseEntry key, data;
if (i == 10 || i == 11)
{
key = new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("key"));
data = new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data"));
}
else
{
key = new DatabaseEntry(BitConverter.GetBytes(i));
data = new DatabaseEntry(BitConverter.GetBytes(i));
}
paramDB.Put(key, data, txn);
}
txn.Commit();
// Get a event wait handle.
signal = new EventWaitHandle(false,
EventResetMode.ManualReset);
/*
* Start RdMfWt() in two threads. RdMfWt() reads
* and writes data into database.
*/
Thread t1 = new Thread(new ThreadStart(RdMfWt));
Thread t2 = new Thread(new ThreadStart(RdMfWt));
t1.Start();
t2.Start();
// Give both threads time to read before signalling them to write.
Thread.Sleep(1000);
// Invoke the write operation in both threads.
signal.Set();
// Return the number of deadlocks.
while (t1.IsAlive || t2.IsAlive)
{
/*
* Give both threads time to write before
* counting the number of deadlocks.
*/
Thread.Sleep(1000);
uint deadlocks = paramEnv.DetectDeadlocks(DeadlockPolicy.DEFAULT);
// Confirm that there won't be any deadlock.
Assert.AreEqual(0, deadlocks);
}
t1.Join();
t2.Join();
paramDB.Close();
paramEnv.Close();
}
}
}