mirror of
https://github.com/berkeleydb/libdb.git
synced 2024-11-16 09:06:25 +00:00
2811 lines
79 KiB
C#
2811 lines
79 KiB
C#
/*-
|
|
* See the file LICENSE for redistribution information.
|
|
*
|
|
* Copyright (c) 2009, 2012 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.Xml;
|
|
using NUnit.Framework;
|
|
using BerkeleyDB;
|
|
|
|
namespace CsharpAPITest
|
|
{
|
|
[TestFixture]
|
|
public class BTreeDatabaseTest : DatabaseTest
|
|
{
|
|
|
|
[TestFixtureSetUp]
|
|
public void SetUpTestFixture()
|
|
{
|
|
testFixtureName = "BTreeDatabaseTest";
|
|
base.SetUpTestfixture();
|
|
}
|
|
|
|
[Test]
|
|
public void TestCompactWithoutTxn()
|
|
{
|
|
int i, nRecs;
|
|
nRecs = 1000;
|
|
testName = "TestCompactWithoutTxn";
|
|
SetUpTest(true);
|
|
string btreeDBFileName = testHome + "/" +
|
|
testName + ".db";
|
|
|
|
BTreeDatabaseConfig btreeDBConfig =
|
|
new BTreeDatabaseConfig();
|
|
btreeDBConfig.Creation = CreatePolicy.ALWAYS;
|
|
// The minimum page size
|
|
btreeDBConfig.PageSize = 512;
|
|
btreeDBConfig.BTreeCompare =
|
|
new EntryComparisonDelegate(dbIntCompare);
|
|
using (BTreeDatabase btreeDB = BTreeDatabase.Open(
|
|
btreeDBFileName, btreeDBConfig))
|
|
{
|
|
DatabaseEntry key;
|
|
DatabaseEntry data;
|
|
|
|
// Fill the database with entries from 0 to 999
|
|
for (i = 0; i < nRecs; i++)
|
|
{
|
|
key = new DatabaseEntry(
|
|
BitConverter.GetBytes(i));
|
|
data = new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes(Configuration.RandomString(100)));
|
|
btreeDB.Put(key, data);
|
|
}
|
|
|
|
/*
|
|
* Delete entries below 50, between 300 and
|
|
* 500 and above 700
|
|
*/
|
|
for (i = 0; i < nRecs; i++)
|
|
if (i < (int)(nRecs * 0.05) ||
|
|
i > (int)(nRecs * 0.7) ||
|
|
(i < (int)(nRecs * 0.5) &&
|
|
i > (int)(nRecs * 0.3)))
|
|
{
|
|
key = new DatabaseEntry(
|
|
BitConverter.GetBytes(i));
|
|
btreeDB.Delete(key);
|
|
}
|
|
|
|
btreeDB.Sync();
|
|
long fileSize = new FileInfo(
|
|
btreeDBFileName).Length;
|
|
|
|
// Compact database
|
|
CompactConfig cCfg = new CompactConfig();
|
|
cCfg.FillPercentage = 80;
|
|
cCfg.Pages = 4;
|
|
cCfg.Timeout = 1000;
|
|
cCfg.TruncatePages = true;
|
|
cCfg.start = new DatabaseEntry(
|
|
BitConverter.GetBytes(1));
|
|
cCfg.stop = new DatabaseEntry(
|
|
BitConverter.GetBytes(7000));
|
|
CompactData compactData = btreeDB.Compact(cCfg);
|
|
// Verify output statistics fields.
|
|
Assert.AreEqual(0, compactData.Deadlocks);
|
|
Assert.LessOrEqual(0, compactData.EmptyBuckets);
|
|
Assert.LessOrEqual(0, compactData.Levels);
|
|
Assert.Less(0, compactData.PagesExamined);
|
|
Assert.Less(0, compactData.PagesFreed);
|
|
Assert.Less(compactData.PagesFreed,
|
|
compactData.PagesTruncated);
|
|
|
|
btreeDB.Sync();
|
|
long compactedFileSize =
|
|
new FileInfo(btreeDBFileName).Length;
|
|
Assert.Less(compactedFileSize, fileSize);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void TestCompression() {
|
|
testName = "TestCompression";
|
|
SetUpTest(true);
|
|
string btreeDBName = testHome + "/" + testName + ".db";
|
|
|
|
BTreeDatabaseConfig cfg = new BTreeDatabaseConfig();
|
|
cfg.Creation = CreatePolicy.ALWAYS;
|
|
cfg.SetCompression(compress, decompress);
|
|
BTreeDatabase db = BTreeDatabase.Open(btreeDBName, cfg);
|
|
DatabaseEntry key, data;
|
|
char[] keyData = { 'A', 'A', 'A', 'A' };
|
|
data = new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes("abcdefghij"));
|
|
int i;
|
|
for (i = 0; i < 2000; i++) {
|
|
// Write random data
|
|
key = new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes(keyData));
|
|
db.Put(key, data);
|
|
|
|
// Bump the key. Rollover from Z to A if necessary
|
|
int j = keyData.Length;
|
|
do {
|
|
j--;
|
|
if (keyData[j]++ == 'Z')
|
|
keyData[j] = 'A';
|
|
} while (keyData[j] == 'A');
|
|
}
|
|
db.Close();
|
|
}
|
|
|
|
bool compress(DatabaseEntry prevKey, DatabaseEntry prevData,
|
|
DatabaseEntry key, DatabaseEntry data, ref byte[] dest, out int size) {
|
|
/*
|
|
* Just a dummy function that doesn't do any compression. It just
|
|
* writes the 5 byte key and 10 byte data to the buffer.
|
|
*/
|
|
size = key.Data.Length + data.Data.Length;
|
|
if (size > dest.Length)
|
|
return false;
|
|
key.Data.CopyTo(dest, 0);
|
|
data.Data.CopyTo(dest, key.Data.Length);
|
|
return true;
|
|
}
|
|
|
|
KeyValuePair<DatabaseEntry, DatabaseEntry> decompress(
|
|
DatabaseEntry prevKey, DatabaseEntry prevData, byte[] compressed, out uint bytesRead) {
|
|
byte[] keyData = new byte[4];
|
|
byte[] dataData = new byte[10];
|
|
Array.ConstrainedCopy(compressed, 0, keyData, 0, 4);
|
|
Array.ConstrainedCopy(compressed, 4, dataData, 0, 10);
|
|
DatabaseEntry key = new DatabaseEntry(keyData);
|
|
DatabaseEntry data = new DatabaseEntry(dataData);
|
|
bytesRead = (uint)(key.Data.Length + data.Data.Length);
|
|
return new KeyValuePair<DatabaseEntry, DatabaseEntry>(key, data);
|
|
}
|
|
|
|
/*
|
|
* Test the default compression - which is prefix compression
|
|
* of keys. This should work well with ordered keys and short
|
|
* data items.
|
|
*/
|
|
[Test]
|
|
public void TestCompressionDefault() {
|
|
testName = "TestCompressionDefault";
|
|
SetUpTest(true);
|
|
string btreeDBName = testHome + "/" + testName + ".db";
|
|
|
|
BTreeDatabaseConfig cfg = new BTreeDatabaseConfig();
|
|
cfg.Creation = CreatePolicy.ALWAYS;
|
|
BTreeDatabase db = BTreeDatabase.Open(btreeDBName, cfg);
|
|
DatabaseEntry key, data;
|
|
char[] keyData = { 'A', 'A', 'A', 'A' };
|
|
data = new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes("A"));
|
|
int i;
|
|
for (i = 0; i < 5000; i++) {
|
|
// Write random data
|
|
key = new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes(keyData));
|
|
db.Put(key, data);
|
|
|
|
// Bump the key.
|
|
int j = keyData.Length;
|
|
do {
|
|
j--;
|
|
if (keyData[j]++ == 'Z')
|
|
keyData[j] = 'A';
|
|
} while (keyData[j] == 'A');
|
|
}
|
|
db.Close();
|
|
|
|
FileInfo dbInfo = new FileInfo(btreeDBName);
|
|
long uncompressedSize = dbInfo.Length;
|
|
Configuration.ClearDir(testHome);
|
|
|
|
cfg = new BTreeDatabaseConfig();
|
|
cfg.Creation = CreatePolicy.ALWAYS;
|
|
cfg.SetCompression();
|
|
db = BTreeDatabase.Open(btreeDBName, cfg);
|
|
keyData = new char[]{ 'A', 'A', 'A', 'A' };
|
|
data = new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes("A"));
|
|
for (i = 0; i < 5000; i++) {
|
|
// Write random data
|
|
key = new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes(keyData));
|
|
db.Put(key, data);
|
|
|
|
// Bump the key.
|
|
int j = keyData.Length;
|
|
do {
|
|
j--;
|
|
if (keyData[j]++ == 'Z')
|
|
keyData[j] = 'A';
|
|
} while (keyData[j] == 'A');
|
|
}
|
|
Cursor dbc = db.Cursor();
|
|
foreach (KeyValuePair<DatabaseEntry, DatabaseEntry> kvp
|
|
in dbc)
|
|
i--;
|
|
dbc.Close();
|
|
Assert.AreEqual(i, 0);
|
|
db.Close();
|
|
|
|
dbInfo = new FileInfo(btreeDBName);
|
|
Assert.Less(dbInfo.Length, uncompressedSize);
|
|
Console.WriteLine(
|
|
"Uncompressed: {0}", uncompressedSize);
|
|
Console.WriteLine("Compressed: {0}", dbInfo.Length);
|
|
|
|
Configuration.ClearDir(testHome);
|
|
|
|
cfg = new BTreeDatabaseConfig();
|
|
cfg.Creation = CreatePolicy.ALWAYS;
|
|
cfg.SetCompression();
|
|
db = BTreeDatabase.Open(btreeDBName, cfg);
|
|
for (i = 1023; i < 1124; i++){
|
|
key = new DatabaseEntry(BitConverter.GetBytes(i));
|
|
data = new DatabaseEntry(BitConverter.GetBytes(i + 3));
|
|
db.Put(key, data);
|
|
}
|
|
dbc = db.Cursor();
|
|
foreach (KeyValuePair<DatabaseEntry, DatabaseEntry> kvp in dbc){
|
|
int keyInt = BitConverter.ToInt32(kvp.Key.Data, 0);
|
|
int dataInt = BitConverter.ToInt32(kvp.Value.Data, 0);
|
|
Assert.AreEqual(3, dataInt - keyInt);
|
|
}
|
|
dbc.Close();
|
|
|
|
db.Close();
|
|
}
|
|
|
|
[Test, ExpectedException(typeof(AccessViolationException))]
|
|
public void TestClose()
|
|
{
|
|
testName = "TestClose";
|
|
SetUpTest(true);
|
|
string btreeDBFileName = testHome + "/" +
|
|
testName + ".db";
|
|
|
|
BTreeDatabaseConfig btreeDBConfig =
|
|
new BTreeDatabaseConfig();
|
|
btreeDBConfig.Creation = CreatePolicy.ALWAYS;
|
|
BTreeDatabase btreeDB = BTreeDatabase.Open(
|
|
btreeDBFileName, btreeDBConfig);
|
|
btreeDB.Close();
|
|
DatabaseEntry key = new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes("hi"));
|
|
DatabaseEntry data = new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes("hi"));
|
|
btreeDB.Put(key, data);
|
|
}
|
|
|
|
[Test]
|
|
public void TestCloseWithoutSync()
|
|
{
|
|
testName = "TestCloseWithoutSync";
|
|
SetUpTest(true);
|
|
string btreeDBName = testName + ".db";
|
|
|
|
DatabaseEnvironmentConfig envConfig =
|
|
new DatabaseEnvironmentConfig();
|
|
envConfig.Create = true;
|
|
envConfig.ForceFlush = true;
|
|
envConfig.UseTxns = true;
|
|
envConfig.UseMPool = true;
|
|
envConfig.UseLogging = true;
|
|
envConfig.LogSystemCfg = new LogConfig();
|
|
envConfig.LogSystemCfg.ForceSync = false;
|
|
envConfig.LogSystemCfg.AutoRemove = true;
|
|
DatabaseEnvironment env = DatabaseEnvironment.Open(
|
|
testHome, envConfig);
|
|
|
|
TransactionConfig txnConfig = new TransactionConfig();
|
|
txnConfig.SyncAction =
|
|
TransactionConfig.LogFlush.WRITE_NOSYNC;
|
|
Transaction txn = env.BeginTransaction(txnConfig);
|
|
|
|
BTreeDatabaseConfig btreeConfig =
|
|
new BTreeDatabaseConfig();
|
|
btreeConfig.Creation = CreatePolicy.ALWAYS;
|
|
btreeConfig.Env = env;
|
|
|
|
BTreeDatabase btreeDB = BTreeDatabase.Open(
|
|
btreeDBName, btreeConfig, txn);
|
|
|
|
DatabaseEntry key = new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes("key"));
|
|
DatabaseEntry data = new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes("data"));
|
|
Assert.IsFalse(btreeDB.Exists(key, txn));
|
|
btreeDB.Put(key, data, txn);
|
|
btreeDB.Close(false);
|
|
txn.Commit();
|
|
env.Close();
|
|
|
|
BTreeDatabaseConfig dbConfig =
|
|
new BTreeDatabaseConfig();
|
|
dbConfig.Creation = CreatePolicy.NEVER;
|
|
using (BTreeDatabase db = BTreeDatabase.Open(
|
|
testHome + "/" + btreeDBName, dbConfig))
|
|
{
|
|
Assert.IsFalse(db.Exists(key));
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void TestCursorWithoutEnv()
|
|
{
|
|
BTreeCursor cursor;
|
|
BTreeDatabase db;
|
|
string dbFileName;
|
|
|
|
testName = "TestCursorWithoutEnv";
|
|
SetUpTest(true);
|
|
dbFileName = testHome + "/" + testName + ".db";
|
|
|
|
// Open btree database.
|
|
OpenBtreeDB(null, null, dbFileName, out db);
|
|
|
|
// Get a cursor.
|
|
cursor = db.Cursor();
|
|
|
|
/*
|
|
* Add a record to the database with cursor and
|
|
* confirm that the record exists in the database.
|
|
*/
|
|
CursorTest.AddOneByCursor(db, cursor);
|
|
|
|
// Close cursor and database.
|
|
cursor.Close();
|
|
db.Close();
|
|
}
|
|
|
|
[Test]
|
|
public void TestCursorWithConfigInTxn()
|
|
{
|
|
BTreeCursor cursor;
|
|
BTreeDatabase db;
|
|
DatabaseEnvironment env;
|
|
Transaction txn;
|
|
string dbFileName;
|
|
|
|
testName = "TestCursorWithConfigInTxn";
|
|
SetUpTest(true);
|
|
dbFileName = testName + ".db";
|
|
|
|
// Open environment and begin a transaction.
|
|
|
|
SetUpEnvAndTxn(testHome, out env, out txn);
|
|
OpenBtreeDB(env, txn, dbFileName, out db);
|
|
|
|
// Config and get a cursor.
|
|
cursor = db.Cursor(new CursorConfig(), txn);
|
|
|
|
/*
|
|
* Add a record to the database with cursor and
|
|
* confirm that the record exists in the database.
|
|
*/
|
|
CursorTest.AddOneByCursor(db, cursor);
|
|
|
|
/*
|
|
* Close cursor, database, commit the transaction
|
|
* and close the environment.
|
|
*/
|
|
cursor.Close();
|
|
db.Close();
|
|
txn.Commit();
|
|
env.Close();
|
|
}
|
|
|
|
[Test]
|
|
public void TestCursorWithoutConfigInTxn()
|
|
{
|
|
BTreeCursor cursor;
|
|
BTreeDatabase db;
|
|
DatabaseEnvironment env;
|
|
Transaction txn;
|
|
string dbFileName;
|
|
|
|
testName = "TestCursorWithoutConfigInTxn";
|
|
SetUpTest(true);
|
|
dbFileName = testName + ".db";
|
|
|
|
// Open environment and begin a transaction.
|
|
SetUpEnvAndTxn(testHome, out env, out txn);
|
|
OpenBtreeDB(env, txn, dbFileName, out db);
|
|
|
|
// Get a cursor in the transaction.
|
|
cursor = db.Cursor(txn);
|
|
|
|
/*
|
|
* Add a record to the database with cursor and
|
|
* confirm that the record exists in the database.
|
|
*/
|
|
CursorTest.AddOneByCursor(db, cursor);
|
|
|
|
/*
|
|
* Close cursor, database, commit the transaction
|
|
* and close the environment.
|
|
*/
|
|
cursor.Close();
|
|
db.Close();
|
|
txn.Commit();
|
|
env.Close();
|
|
}
|
|
|
|
[Test, ExpectedException(typeof(ExpectedTestException))]
|
|
public void TestDelete()
|
|
{
|
|
testName = "TestDelete";
|
|
SetUpTest(true);
|
|
string btreeDBFileName = testHome + "/" +
|
|
testName + ".db";
|
|
|
|
BTreeDatabaseConfig btreeDBConfig =
|
|
new BTreeDatabaseConfig();
|
|
btreeDBConfig.Creation = CreatePolicy.ALWAYS;
|
|
BTreeDatabase btreeDB = BTreeDatabase.Open(
|
|
btreeDBFileName, btreeDBConfig);
|
|
DatabaseEntry key = new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes("key"));
|
|
DatabaseEntry data = new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes("data"));
|
|
btreeDB.Put(key, data);
|
|
btreeDB.Delete(key);
|
|
try
|
|
{
|
|
btreeDB.Get(key);
|
|
}
|
|
catch (NotFoundException)
|
|
{
|
|
throw new ExpectedTestException();
|
|
}
|
|
finally
|
|
{
|
|
btreeDB.Close();
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void TestDupCompare()
|
|
{
|
|
testName = "TestDupCompare";
|
|
SetUpTest(true);
|
|
|
|
BTreeDatabaseConfig cfg = new BTreeDatabaseConfig();
|
|
cfg.Creation = CreatePolicy.IF_NEEDED;
|
|
cfg.Duplicates = DuplicatesPolicy.UNSORTED;
|
|
|
|
// Do not set the duplicate comparison delegate.
|
|
using (BTreeDatabase db = BTreeDatabase.Open(
|
|
testHome + "/" + testName + ".db", cfg)) {
|
|
try {
|
|
int ret = db.DupCompare(
|
|
new DatabaseEntry(
|
|
BitConverter.GetBytes(255)),
|
|
new DatabaseEntry(
|
|
BitConverter.GetBytes(257)));
|
|
throw new TestException();
|
|
} catch(NullReferenceException) {
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Set the duplicate comparison delegate, and verify
|
|
* the comparison delegate.
|
|
*/
|
|
cfg.DuplicateCompare =
|
|
new EntryComparisonDelegate(dbIntCompare);
|
|
using (BTreeDatabase db = BTreeDatabase.Open(
|
|
testHome + "/" + testName + "1.db", cfg)) {
|
|
int ret = db.DupCompare(
|
|
new DatabaseEntry(BitConverter.GetBytes(255)),
|
|
new DatabaseEntry(BitConverter.GetBytes(257)));
|
|
Assert.Greater(0, ret);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void TestEncryption() {
|
|
testName = "TestEncryption";
|
|
SetUpTest(true);
|
|
|
|
BTreeDatabase db1;
|
|
|
|
BTreeDatabaseConfig dbCfg =
|
|
new BTreeDatabaseConfig();
|
|
dbCfg.Creation = CreatePolicy.IF_NEEDED;
|
|
|
|
// Open an encrypted database.
|
|
dbCfg.SetEncryption("bdb", EncryptionAlgorithm.AES);
|
|
using (db1 = BTreeDatabase.Open(
|
|
testHome + "/" + testName + ".db", dbCfg)) {
|
|
Assert.IsTrue(db1.Encrypted);
|
|
for (int i = 0; i < 10; i++)
|
|
db1.Put(new DatabaseEntry
|
|
(BitConverter.GetBytes(i)),
|
|
new DatabaseEntry(
|
|
BitConverter.GetBytes(i)));
|
|
}
|
|
|
|
// Verify the database is encrypted.
|
|
BTreeDatabaseConfig verifyDbCfg =
|
|
new BTreeDatabaseConfig();
|
|
verifyDbCfg.Creation = CreatePolicy.IF_NEEDED;
|
|
verifyDbCfg.SetEncryption(
|
|
dbCfg.EncryptionPassword,
|
|
dbCfg.EncryptAlgorithm);
|
|
verifyDbCfg.Encrypted = true;
|
|
using (db1 = BTreeDatabase.Open(
|
|
testHome + "/" + testName + ".db",
|
|
verifyDbCfg)) {
|
|
for (int i = 0; i < 10; i++)
|
|
db1.Get(new DatabaseEntry(
|
|
BitConverter.GetBytes(i)));
|
|
};
|
|
}
|
|
|
|
[Test]
|
|
public void TestExist()
|
|
{
|
|
testName = "TestExist";
|
|
SetUpTest(true);
|
|
string dbFileName = testHome + "/" + testName + ".db";
|
|
|
|
BTreeDatabaseConfig btreeDBConfig =
|
|
new BTreeDatabaseConfig();
|
|
btreeDBConfig.Creation = CreatePolicy.IF_NEEDED;
|
|
BTreeDatabase btreeDB;
|
|
using (btreeDB = BTreeDatabase.Open(
|
|
dbFileName, btreeDBConfig))
|
|
{
|
|
DatabaseEntry key = new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes("key"));
|
|
DatabaseEntry data = new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes("data"));
|
|
|
|
btreeDB.Put(key, data);
|
|
Assert.IsTrue(btreeDB.Exists(
|
|
new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes("key"))));
|
|
Assert.IsFalse(btreeDB.Exists(
|
|
new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes("data"))));
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void TestExistWithTxn()
|
|
{
|
|
BTreeDatabase btreeDB;
|
|
Transaction txn;
|
|
DatabaseEnvironmentConfig envConfig;
|
|
DatabaseEnvironment env;
|
|
DatabaseEntry key, data;
|
|
|
|
testName = "TestExistWithTxn";
|
|
SetUpTest(true);
|
|
|
|
// Open an environment.
|
|
envConfig = new DatabaseEnvironmentConfig();
|
|
envConfig.Create = true;
|
|
envConfig.UseMPool = true;
|
|
envConfig.UseTxns = true;
|
|
env = DatabaseEnvironment.Open(testHome, envConfig);
|
|
|
|
// Begin a transaction.
|
|
txn = env.BeginTransaction();
|
|
|
|
// Open a database.
|
|
BTreeDatabaseConfig btreeDBConfig =
|
|
new BTreeDatabaseConfig();
|
|
btreeDBConfig.Creation = CreatePolicy.IF_NEEDED;
|
|
btreeDBConfig.Env = env;
|
|
btreeDB = BTreeDatabase.Open(testName + ".db",
|
|
btreeDBConfig, txn);
|
|
|
|
// Put key data pair into database.
|
|
key = new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes("key"));
|
|
data = new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes("data"));
|
|
btreeDB.Put(key, data, txn);
|
|
|
|
// Confirm that the pair exists in the database.
|
|
Assert.IsTrue(btreeDB.Exists(new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes("key")), txn));
|
|
Assert.IsFalse(btreeDB.Exists(new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes("data")), txn));
|
|
|
|
// Dispose all.
|
|
btreeDB.Close();
|
|
txn.Commit();
|
|
env.Close();
|
|
}
|
|
|
|
[Test]
|
|
public void TestExistWithLockingInfo()
|
|
{
|
|
BTreeDatabase btreeDB;
|
|
DatabaseEnvironment env;
|
|
DatabaseEntry key, data;
|
|
|
|
testName = "TestExistWithLockingInfo";
|
|
SetUpTest(true);
|
|
|
|
// 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;
|
|
env = DatabaseEnvironment.Open(
|
|
testHome, envCfg);
|
|
|
|
// Open database in transaction.
|
|
Transaction openTxn = env.BeginTransaction();
|
|
BTreeDatabaseConfig cfg =
|
|
new BTreeDatabaseConfig();
|
|
cfg.Creation = CreatePolicy.ALWAYS;
|
|
cfg.Env = env;
|
|
cfg.FreeThreaded = true;
|
|
cfg.PageSize = 4096;
|
|
cfg.Duplicates = DuplicatesPolicy.UNSORTED;
|
|
btreeDB = BTreeDatabase.Open(testName + ".db",
|
|
cfg, openTxn);
|
|
openTxn.Commit();
|
|
|
|
// Put key data pair into database.
|
|
Transaction txn = env.BeginTransaction();
|
|
key = new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes("key"));
|
|
data = new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes("data"));
|
|
btreeDB.Put(key, data, txn);
|
|
|
|
// Confirm that the pair exists in the database with LockingInfo.
|
|
LockingInfo lockingInfo = new LockingInfo();
|
|
lockingInfo.ReadModifyWrite = true;
|
|
|
|
// Confirm that the pair exists in the database.
|
|
Assert.IsTrue(btreeDB.Exists(new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes("key")), txn, lockingInfo));
|
|
Assert.IsFalse(btreeDB.Exists(new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes("data")), txn, lockingInfo));
|
|
txn.Commit();
|
|
|
|
btreeDB.Close();
|
|
env.Close();
|
|
}
|
|
|
|
[Test]
|
|
public void TestGetByKey()
|
|
{
|
|
testName = "TestGetByKey";
|
|
SetUpTest(true);
|
|
string btreeDBFileName = testHome + "/" +
|
|
testName + ".db";
|
|
string btreeDBName =
|
|
Path.GetFileNameWithoutExtension(btreeDBFileName);
|
|
|
|
BTreeDatabaseConfig btreeDBConfig =
|
|
new BTreeDatabaseConfig();
|
|
btreeDBConfig.Creation = CreatePolicy.ALWAYS;
|
|
BTreeDatabase btreeDB = BTreeDatabase.Open(
|
|
btreeDBFileName, btreeDBName, btreeDBConfig);
|
|
|
|
DatabaseEntry key = new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes("key"));
|
|
DatabaseEntry data = new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes("data"));
|
|
btreeDB.Put(key, data);
|
|
|
|
KeyValuePair<DatabaseEntry, DatabaseEntry> pair =
|
|
new KeyValuePair<DatabaseEntry, DatabaseEntry>();
|
|
pair = btreeDB.Get(key);
|
|
Assert.AreEqual(pair.Key.Data, key.Data);
|
|
Assert.AreEqual(pair.Value.Data, data.Data);
|
|
btreeDB.Close();
|
|
}
|
|
|
|
[Test]
|
|
public void TestGetByRecno()
|
|
{
|
|
testName = "TestGetByRecno";
|
|
SetUpTest(true);
|
|
string btreeDBFileName = testHome + "/" +
|
|
testName + ".db";
|
|
string btreeDBName =
|
|
Path.GetFileNameWithoutExtension(btreeDBFileName);
|
|
|
|
BTreeDatabaseConfig btreeDBConfig =
|
|
new BTreeDatabaseConfig();
|
|
btreeDBConfig.Creation = CreatePolicy.ALWAYS;
|
|
btreeDBConfig.UseRecordNumbers = true;
|
|
BTreeDatabase btreeDB = BTreeDatabase.Open(
|
|
btreeDBFileName, btreeDBName, btreeDBConfig);
|
|
Assert.IsTrue(btreeDB.RecordNumbers);
|
|
|
|
DatabaseEntry key = new DatabaseEntry();
|
|
DatabaseEntry data = new DatabaseEntry();
|
|
uint recno, count, value;
|
|
for (recno = 1; recno <= 100; recno++)
|
|
{
|
|
value = 200 - recno;
|
|
Configuration.dbtFromString(key,
|
|
Convert.ToString(value));
|
|
Configuration.dbtFromString(data,
|
|
Convert.ToString(value));
|
|
btreeDB.Put(key, data);
|
|
}
|
|
|
|
KeyValuePair<DatabaseEntry, DatabaseEntry> pair =
|
|
new KeyValuePair<DatabaseEntry, DatabaseEntry>();
|
|
|
|
for (count = 1; ; count++)
|
|
{
|
|
try
|
|
{
|
|
pair = btreeDB.Get(count);
|
|
}
|
|
catch (NotFoundException)
|
|
{
|
|
Assert.AreEqual(101, count);
|
|
break;
|
|
}
|
|
value = 299 - 200 + count;
|
|
Assert.AreEqual(value.ToString(),
|
|
Configuration.strFromDBT(pair.Key));
|
|
}
|
|
|
|
btreeDB.Close();
|
|
}
|
|
|
|
[Test, ExpectedException(typeof(NotFoundException))]
|
|
public void TestGetBoth()
|
|
{
|
|
testName = "TestGetBoth";
|
|
SetUpTest(true);
|
|
string btreeDBFileName = testHome + "/" +
|
|
testName + ".db";
|
|
string btreeDBName =
|
|
Path.GetFileNameWithoutExtension(btreeDBFileName);
|
|
|
|
BTreeDatabaseConfig btreeDBConfig =
|
|
new BTreeDatabaseConfig();
|
|
btreeDBConfig.Creation = CreatePolicy.ALWAYS;
|
|
using (BTreeDatabase btreeDB = BTreeDatabase.Open(
|
|
btreeDBFileName, btreeDBName, btreeDBConfig))
|
|
{
|
|
DatabaseEntry key = new DatabaseEntry();
|
|
DatabaseEntry data = new DatabaseEntry();
|
|
|
|
Configuration.dbtFromString(key, "key");
|
|
Configuration.dbtFromString(data, "data");
|
|
btreeDB.Put(key, data);
|
|
KeyValuePair<DatabaseEntry, DatabaseEntry> pair =
|
|
new KeyValuePair<DatabaseEntry, DatabaseEntry>();
|
|
pair = btreeDB.GetBoth(key, data);
|
|
Assert.AreEqual(key.Data, pair.Key.Data);
|
|
Assert.AreEqual(data.Data, pair.Value.Data);
|
|
|
|
Configuration.dbtFromString(key, "key");
|
|
Configuration.dbtFromString(data, "key");
|
|
btreeDB.GetBoth(key, data);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void TestGetBothMultiple()
|
|
{
|
|
testName = "TestGetBothMultiple";
|
|
SetUpTest(true);
|
|
string btreeDBFileName = testHome + "/" +
|
|
testName + ".db";
|
|
string btreeDBName = testName;
|
|
DatabaseEntry key, data;
|
|
KeyValuePair<DatabaseEntry, MultipleDatabaseEntry> kvp;
|
|
int cnt;
|
|
|
|
BTreeDatabaseConfig btreeDBConfig =
|
|
new BTreeDatabaseConfig();
|
|
btreeDBConfig.Creation = CreatePolicy.ALWAYS;
|
|
btreeDBConfig.Duplicates = DuplicatesPolicy.UNSORTED;
|
|
btreeDBConfig.PageSize = 1024;
|
|
using (BTreeDatabase btreeDB = GetMultipleDB(
|
|
btreeDBFileName, btreeDBName, btreeDBConfig)) {
|
|
key = new DatabaseEntry(BitConverter.GetBytes(100));
|
|
data = new DatabaseEntry(BitConverter.GetBytes(100));
|
|
|
|
kvp = btreeDB.GetBothMultiple(key, data);
|
|
cnt = 0;
|
|
foreach (DatabaseEntry dbt in kvp.Value)
|
|
cnt++;
|
|
Assert.AreEqual(cnt, 10);
|
|
|
|
kvp = btreeDB.GetBothMultiple(key, data, 1024);
|
|
cnt = 0;
|
|
foreach (DatabaseEntry dbt in kvp.Value)
|
|
cnt++;
|
|
Assert.AreEqual(cnt, 10);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void TestGetMultiple()
|
|
{
|
|
testName = "TestGetMultiple";
|
|
SetUpTest(true);
|
|
string btreeDBFileName = testHome + "/" +
|
|
testName + ".db";
|
|
string btreeDBName = testName;
|
|
|
|
BTreeDatabaseConfig btreeDBConfig =
|
|
new BTreeDatabaseConfig();
|
|
btreeDBConfig.Creation = CreatePolicy.ALWAYS;
|
|
btreeDBConfig.Duplicates = DuplicatesPolicy.UNSORTED;
|
|
btreeDBConfig.PageSize = 512;
|
|
|
|
using (BTreeDatabase btreeDB = GetMultipleDB(
|
|
btreeDBFileName, btreeDBName, btreeDBConfig)) {
|
|
DatabaseEntry key = new DatabaseEntry(
|
|
BitConverter.GetBytes(10));
|
|
KeyValuePair<DatabaseEntry, MultipleDatabaseEntry> kvp =
|
|
btreeDB.GetMultiple(key, 1024);
|
|
int cnt = 0;
|
|
foreach (DatabaseEntry dbt in kvp.Value)
|
|
cnt++;
|
|
Assert.AreEqual(cnt, 10);
|
|
|
|
key = new DatabaseEntry(
|
|
BitConverter.GetBytes(102));
|
|
kvp = btreeDB.GetMultiple(key, 1024);
|
|
cnt = 0;
|
|
foreach (DatabaseEntry dbt in kvp.Value)
|
|
cnt++;
|
|
Assert.AreEqual(cnt, 1);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void TestGetMultipleByRecno()
|
|
{
|
|
testName = "TestGetMultipleByRecno";
|
|
SetUpTest(true);
|
|
string btreeDBFileName = testHome + "/" +
|
|
testName + ".db";
|
|
string btreeDBName =
|
|
Path.GetFileNameWithoutExtension(btreeDBFileName);
|
|
|
|
BTreeDatabaseConfig btreeDBConfig =
|
|
new BTreeDatabaseConfig();
|
|
btreeDBConfig.Creation = CreatePolicy.ALWAYS;
|
|
btreeDBConfig.Duplicates = DuplicatesPolicy.NONE;
|
|
btreeDBConfig.UseRecordNumbers = true;
|
|
using (BTreeDatabase btreeDB = GetMultipleDB(
|
|
btreeDBFileName, btreeDBName, btreeDBConfig)) {
|
|
int recno = 44;
|
|
KeyValuePair<DatabaseEntry, MultipleDatabaseEntry> kvp =
|
|
btreeDB.GetMultiple((uint)recno);
|
|
int cnt = 0;
|
|
int kdata = BitConverter.ToInt32(kvp.Key.Data, 0);
|
|
Assert.AreEqual(kdata, recno);
|
|
foreach (DatabaseEntry dbt in kvp.Value) {
|
|
cnt++;
|
|
int ddata = BitConverter.ToInt32(dbt.Data, 0);
|
|
Assert.AreEqual(ddata, recno);
|
|
}
|
|
Assert.AreEqual(cnt, 1);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void TestGetMultipleByRecnoInSize()
|
|
{
|
|
testName = "TestGetMultipleByRecnoInSize";
|
|
SetUpTest(true);
|
|
string btreeDBFileName = testHome + "/" +
|
|
testName + ".db";
|
|
string btreeDBName =
|
|
Path.GetFileNameWithoutExtension(btreeDBFileName);
|
|
|
|
BTreeDatabaseConfig btreeDBConfig =
|
|
new BTreeDatabaseConfig();
|
|
btreeDBConfig.Creation = CreatePolicy.ALWAYS;
|
|
btreeDBConfig.Duplicates = DuplicatesPolicy.NONE;
|
|
btreeDBConfig.UseRecordNumbers = true;
|
|
btreeDBConfig.PageSize = 512;
|
|
using (BTreeDatabase btreeDB = GetMultipleDB(
|
|
btreeDBFileName, btreeDBName, btreeDBConfig)) {
|
|
int recno = 100;
|
|
int bufferSize = 1024;
|
|
KeyValuePair<DatabaseEntry, MultipleDatabaseEntry> kvp =
|
|
btreeDB.GetMultiple((uint)recno, bufferSize);
|
|
int cnt = 0;
|
|
int kdata = BitConverter.ToInt32(kvp.Key.Data, 0);
|
|
Assert.AreEqual(kdata, recno);
|
|
foreach (DatabaseEntry dbt in kvp.Value) {
|
|
cnt++;
|
|
Assert.AreEqual(dbt.Data.Length, 111);
|
|
}
|
|
Assert.AreEqual(1, cnt);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void TestGetMultipleInSize()
|
|
{
|
|
testName = "TestGetMultipleInSize";
|
|
SetUpTest(true);
|
|
string btreeDBFileName = testHome + "/" +
|
|
testName + ".db";
|
|
string btreeDBName =
|
|
Path.GetFileNameWithoutExtension(btreeDBFileName);
|
|
|
|
BTreeDatabaseConfig btreeDBConfig =
|
|
new BTreeDatabaseConfig();
|
|
btreeDBConfig.Creation = CreatePolicy.ALWAYS;
|
|
btreeDBConfig.Duplicates = DuplicatesPolicy.UNSORTED;
|
|
btreeDBConfig.PageSize = 1024;
|
|
using (BTreeDatabase btreeDB = GetMultipleDB(
|
|
btreeDBFileName, btreeDBName, btreeDBConfig)) {
|
|
|
|
int num = 101;
|
|
DatabaseEntry key = new DatabaseEntry(
|
|
BitConverter.GetBytes(num));
|
|
int bufferSize = 10240;
|
|
KeyValuePair<DatabaseEntry, MultipleDatabaseEntry> kvp =
|
|
btreeDB.GetMultiple(key, bufferSize);
|
|
int cnt = 0;
|
|
foreach (DatabaseEntry dbt in kvp.Value) {
|
|
cnt++;
|
|
Assert.AreEqual(BitConverter.ToInt32(
|
|
dbt.Data, 0), num);
|
|
num++;
|
|
}
|
|
Assert.AreEqual(cnt, 923);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void TestGetWithTxn()
|
|
{
|
|
testName = "TestGetWithTxn";
|
|
SetUpTest(true);
|
|
|
|
DatabaseEnvironmentConfig envConfig =
|
|
new DatabaseEnvironmentConfig();
|
|
envConfig.Create = true;
|
|
envConfig.UseLogging = true;
|
|
envConfig.UseMPool = true;
|
|
envConfig.UseTxns = true;
|
|
DatabaseEnvironment env = DatabaseEnvironment.Open(
|
|
testHome, envConfig);
|
|
|
|
try
|
|
{
|
|
Transaction openTxn = env.BeginTransaction();
|
|
BTreeDatabaseConfig dbConfig =
|
|
new BTreeDatabaseConfig();
|
|
dbConfig.Env = env;
|
|
dbConfig.Creation = CreatePolicy.IF_NEEDED;
|
|
BTreeDatabase db = BTreeDatabase.Open(
|
|
testName + ".db", dbConfig, openTxn);
|
|
openTxn.Commit();
|
|
|
|
Transaction putTxn = env.BeginTransaction();
|
|
try
|
|
{
|
|
for (int i = 0; i < 20; i++)
|
|
db.Put(new DatabaseEntry(
|
|
BitConverter.GetBytes(i)),
|
|
new DatabaseEntry(
|
|
BitConverter.GetBytes(i)), putTxn);
|
|
putTxn.Commit();
|
|
}
|
|
catch (DatabaseException e)
|
|
{
|
|
putTxn.Abort();
|
|
db.Close();
|
|
throw e;
|
|
}
|
|
|
|
Transaction getTxn = env.BeginTransaction();
|
|
KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
|
|
try
|
|
{
|
|
for (int i = 0; i < 20; i++)
|
|
{
|
|
pair = db.Get(new DatabaseEntry(
|
|
BitConverter.GetBytes(i)), getTxn);
|
|
Assert.AreEqual(BitConverter.GetBytes(i),
|
|
pair.Key.Data);
|
|
}
|
|
|
|
getTxn.Commit();
|
|
db.Close();
|
|
}
|
|
catch (DatabaseException)
|
|
{
|
|
getTxn.Abort();
|
|
db.Close();
|
|
throw new TestException();
|
|
}
|
|
}
|
|
catch (DatabaseException)
|
|
{
|
|
}
|
|
finally
|
|
{
|
|
env.Close();
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void TestKeyRange()
|
|
{
|
|
testName = "TestKeyRange";
|
|
SetUpTest(true);
|
|
string btreeDBFileName = testHome + "/" +
|
|
testName + ".db";
|
|
string btreeDBName = Path.GetFileNameWithoutExtension(
|
|
btreeDBFileName);
|
|
|
|
BTreeDatabaseConfig btreeDBConfig =
|
|
new BTreeDatabaseConfig();
|
|
btreeDBConfig.Creation = CreatePolicy.ALWAYS;
|
|
BTreeDatabase btreeDB = BTreeDatabase.Open(
|
|
btreeDBFileName, btreeDBName, btreeDBConfig);
|
|
|
|
DatabaseEntry key = new DatabaseEntry();
|
|
DatabaseEntry data = new DatabaseEntry();
|
|
uint recno;
|
|
for (recno = 1; recno <= 10; recno++)
|
|
{
|
|
Configuration.dbtFromString(key,
|
|
Convert.ToString(recno));
|
|
Configuration.dbtFromString(data,
|
|
Convert.ToString(recno));
|
|
btreeDB.Put(key, data);
|
|
}
|
|
|
|
Configuration.dbtFromString(key, Convert.ToString(5));
|
|
KeyRange keyRange = btreeDB.KeyRange(key);
|
|
Assert.AreEqual(0.5, keyRange.Less);
|
|
Assert.AreEqual(0.1, keyRange.Equal);
|
|
Assert.AreEqual(0.4, keyRange.Greater);
|
|
|
|
btreeDB.Close();
|
|
}
|
|
|
|
[Test]
|
|
public void TestNoWaitDbExclusiveLock()
|
|
{
|
|
testName = "TestNoWaitDbExclusiveLock";
|
|
SetUpTest(true);
|
|
|
|
// Open an environment.
|
|
DatabaseEnvironmentConfig envConfig =
|
|
new DatabaseEnvironmentConfig();
|
|
envConfig.AutoCommit = true;
|
|
envConfig.Create = true;
|
|
envConfig.UseMPool = true;
|
|
envConfig.UseLocking = true;
|
|
envConfig.UseLogging = true;
|
|
envConfig.UseTxns = true;
|
|
DatabaseEnvironment env = DatabaseEnvironment.Open(
|
|
testHome, envConfig);
|
|
|
|
// Open a database.
|
|
BTreeDatabaseConfig btreeDBConfig =
|
|
new BTreeDatabaseConfig();
|
|
btreeDBConfig.Env = env;
|
|
string btreeDBFileName = testName + ".db";
|
|
BTreeDatabase btreeDB;
|
|
|
|
btreeDBConfig.Creation = CreatePolicy.IF_NEEDED;
|
|
btreeDB = BTreeDatabase.Open(
|
|
btreeDBFileName, btreeDBConfig);
|
|
Assert.IsNull(btreeDB.NoWaitDbExclusiveLock);
|
|
btreeDB.Close();
|
|
|
|
btreeDBConfig.NoWaitDbExclusiveLock = false;
|
|
btreeDB = BTreeDatabase.Open(
|
|
btreeDBFileName, btreeDBConfig);
|
|
Assert.AreEqual(btreeDB.NoWaitDbExclusiveLock, false);
|
|
btreeDB.Close();
|
|
|
|
btreeDBConfig.NoWaitDbExclusiveLock = true;
|
|
btreeDB = BTreeDatabase.Open(
|
|
btreeDBFileName, btreeDBConfig);
|
|
Assert.AreEqual(btreeDB.NoWaitDbExclusiveLock, true);
|
|
btreeDB.Close();
|
|
env.Close();
|
|
}
|
|
|
|
[Test]
|
|
public void TestOpenExistingBtreeDB()
|
|
{
|
|
testName = "TestOpenExistingBtreeDB";
|
|
SetUpTest(true);
|
|
string btreeDBFileName = testHome + "/" +
|
|
testName + ".db";
|
|
|
|
BTreeDatabaseConfig btreeConfig =
|
|
new BTreeDatabaseConfig();
|
|
btreeConfig.Creation = CreatePolicy.ALWAYS;
|
|
BTreeDatabase btreeDB = BTreeDatabase.Open(
|
|
btreeDBFileName, btreeConfig);
|
|
btreeDB.Close();
|
|
|
|
DatabaseConfig dbConfig = new DatabaseConfig();
|
|
Database db = Database.Open(btreeDBFileName,
|
|
dbConfig);
|
|
Assert.AreEqual(db.Type, DatabaseType.BTREE);
|
|
Assert.AreEqual(db.Creation, CreatePolicy.NEVER);
|
|
db.Close();
|
|
}
|
|
|
|
[Test]
|
|
public void TestOpenNewBtreeDB()
|
|
{
|
|
testName = "TestOpenNewBtreeDB";
|
|
SetUpTest(true);
|
|
string btreeDBFileName = testHome + "/" +
|
|
testName + ".db";
|
|
|
|
XmlElement xmlElem = Configuration.TestSetUp(
|
|
testFixtureName, testName);
|
|
BTreeDatabaseConfig btreeConfig =
|
|
new BTreeDatabaseConfig();
|
|
BTreeDatabaseConfigTest.Config(xmlElem,
|
|
ref btreeConfig, true);
|
|
BTreeDatabase btreeDB = BTreeDatabase.Open(
|
|
btreeDBFileName, btreeConfig);
|
|
Confirm(xmlElem, btreeDB, true);
|
|
btreeDB.Close();
|
|
}
|
|
|
|
[Test]
|
|
public void TestOpenMulDBInSingleFile()
|
|
{
|
|
testName = "TestOpenMulDBInSingleFile";
|
|
SetUpTest(true);
|
|
string btreeDBFileName = testHome + "/" +
|
|
testName + ".db";
|
|
string[] btreeDBArr = new string[4];
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
btreeDBArr[i] = Path.GetFileNameWithoutExtension(
|
|
btreeDBFileName) + i;
|
|
|
|
Configuration.ClearDir(testHome);
|
|
|
|
BTreeDatabaseConfig btreeDBConfig =
|
|
new BTreeDatabaseConfig();
|
|
btreeDBConfig.Creation = CreatePolicy.IF_NEEDED;
|
|
|
|
BTreeDatabase btreeDB;
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
btreeDB = BTreeDatabase.Open(btreeDBFileName,
|
|
btreeDBArr[i], btreeDBConfig);
|
|
Assert.AreEqual(CreatePolicy.IF_NEEDED, btreeDB.Creation);
|
|
btreeDB.Close();
|
|
}
|
|
|
|
DatabaseConfig dbConfig = new DatabaseConfig();
|
|
Database db;
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
using (db = Database.Open(btreeDBFileName,
|
|
btreeDBArr[i], dbConfig))
|
|
{
|
|
Assert.AreEqual(btreeDBArr[i],
|
|
db.DatabaseName);
|
|
Assert.AreEqual(DatabaseType.BTREE,
|
|
db.Type);
|
|
}
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void TestOpenWithTxn()
|
|
{
|
|
testName = "TestOpenWithTxn";
|
|
SetUpTest(true);
|
|
string btreeDBName = testName + ".db";
|
|
|
|
DatabaseEnvironmentConfig envConfig =
|
|
new DatabaseEnvironmentConfig();
|
|
envConfig.Create = true;
|
|
envConfig.UseTxns = true;
|
|
envConfig.UseMPool = true;
|
|
|
|
DatabaseEnvironment env = DatabaseEnvironment.Open(
|
|
testHome, envConfig);
|
|
Transaction txn = env.BeginTransaction(
|
|
new TransactionConfig());
|
|
|
|
BTreeDatabaseConfig btreeConfig =
|
|
new BTreeDatabaseConfig();
|
|
btreeConfig.Creation = CreatePolicy.ALWAYS;
|
|
btreeConfig.Env = env;
|
|
|
|
/*
|
|
* If environmnet home is set, the file name in Open()
|
|
* is the relative path.
|
|
*/
|
|
BTreeDatabase btreeDB = BTreeDatabase.Open(
|
|
btreeDBName, btreeConfig, txn);
|
|
Assert.IsTrue(btreeDB.Transactional);
|
|
btreeDB.Close();
|
|
txn.Commit();
|
|
env.Close();
|
|
}
|
|
|
|
[Test]
|
|
public void TestPartialGet()
|
|
{
|
|
testName = "TestPartialGet";
|
|
SetUpTest(true);
|
|
|
|
DatabaseEnvironmentConfig envConfig =
|
|
new DatabaseEnvironmentConfig();
|
|
envConfig.Create = true;
|
|
envConfig.UseTxns = true;
|
|
envConfig.UseMPool = true;
|
|
DatabaseEnvironment env = DatabaseEnvironment.Open(
|
|
testHome, envConfig);
|
|
|
|
BTreeDatabase db;
|
|
PopulateDb(env, out db);
|
|
|
|
// Partially get the first byte and verify it is 'h'.
|
|
DatabaseEntry key, data;
|
|
KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
|
|
Transaction txn = env.BeginTransaction();
|
|
for (int i = 0; i < 100; i++) {
|
|
key = new DatabaseEntry(BitConverter.GetBytes(i));
|
|
data = new DatabaseEntry(0, 1);
|
|
pair = db.Get(key, data, txn);
|
|
Assert.AreEqual(1, pair.Value.Data.Length);
|
|
Assert.AreEqual((byte)'h', pair.Value.Data[0]);
|
|
}
|
|
txn.Commit();
|
|
db.Close();
|
|
env.Close();
|
|
|
|
/*
|
|
* Open the existing database and partially get
|
|
* non-existing data.
|
|
*/
|
|
using (Database edb = Database.Open(
|
|
testHome + "/" + testName + ".db",
|
|
new DatabaseConfig())) {
|
|
key = new DatabaseEntry(BitConverter.GetBytes(0));
|
|
data = new DatabaseEntry(10, 1);
|
|
pair = edb.Get(key, data);
|
|
Assert.AreEqual(null, pair.Value.Data);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void TestPartialPut()
|
|
{
|
|
testName = "TestPartialPut";
|
|
SetUpTest(true);
|
|
|
|
BTreeDatabase db;
|
|
PopulateDb(null, out db);
|
|
|
|
// Partially update the records.
|
|
DatabaseEntry key, data;
|
|
KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
|
|
byte[] partialBytes = ASCIIEncoding.ASCII.GetBytes("aa");
|
|
byte[] valueBytes;
|
|
for (int i = 0; i < 100; i++) {
|
|
key = new DatabaseEntry(BitConverter.GetBytes(i));
|
|
if (i < 50)
|
|
data = new DatabaseEntry(
|
|
partialBytes, 0, 2);
|
|
else {
|
|
data = new DatabaseEntry(partialBytes);
|
|
data.Partial = true;
|
|
data.PartialLen = 2;
|
|
data.PartialOffset = 0;
|
|
}
|
|
Assert.AreEqual(0, data.PartialOffset);
|
|
Assert.AreEqual(2, data.PartialLen);
|
|
Assert.AreEqual(true, data.Partial);
|
|
db.Put(key, data);
|
|
}
|
|
// Verify that the records have been partially changed.
|
|
valueBytes = ASCIIEncoding.ASCII.GetBytes("hello");
|
|
valueBytes[0] = (byte)'a';
|
|
valueBytes[1] = (byte)'a';
|
|
for (int i = 0; i < 100; i++) {
|
|
key = new DatabaseEntry(BitConverter.GetBytes(i));
|
|
pair = db.Get(key);
|
|
Assert.AreEqual(
|
|
BitConverter.GetBytes(i), pair.Key.Data);
|
|
Assert.AreEqual(valueBytes, pair.Value.Data);
|
|
}
|
|
|
|
// Partial put from non-existing offset.
|
|
key = new DatabaseEntry(BitConverter.GetBytes(0));
|
|
data = new DatabaseEntry(partialBytes, 100, 2);
|
|
db.Put(key, data);
|
|
|
|
// Verify that the records have been partially changed.
|
|
pair = db.Get(key);
|
|
Assert.AreEqual(102, pair.Value.Data.Length);
|
|
Assert.AreEqual(valueBytes[0],
|
|
pair.Value.Data[100]);
|
|
Assert.AreEqual(valueBytes[0],
|
|
pair.Value.Data[101]);
|
|
|
|
/*
|
|
* Reuse the DatabaseEntry for non-partial. The partial
|
|
* length and offset should be ignored.
|
|
*/
|
|
key = new DatabaseEntry(BitConverter.GetBytes(0));
|
|
data.Partial = false;
|
|
db.Put(key, data);
|
|
pair = db.Get(key);
|
|
Assert.AreEqual(2, pair.Value.Data.Length);
|
|
|
|
db.Close();
|
|
}
|
|
|
|
private void PopulateDb(DatabaseEnvironment env,
|
|
out BTreeDatabase db)
|
|
{
|
|
DatabaseEntry key, data;
|
|
Transaction txn = null;
|
|
string dbName;
|
|
|
|
if (env != null) {
|
|
txn = env.BeginTransaction();
|
|
dbName = testName + ".db";
|
|
} else
|
|
dbName = testHome + "/" + testName + ".db";
|
|
|
|
OpenBtreeDB(env, txn, dbName, out db);
|
|
|
|
for (int i = 0; i < 100; i++) {
|
|
key = new DatabaseEntry(
|
|
BitConverter.GetBytes(i));
|
|
data = new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes("hello"));
|
|
db.Put(key, data, txn);
|
|
}
|
|
|
|
if (txn != null)
|
|
txn.Commit();
|
|
}
|
|
|
|
[Test]
|
|
public void TestPrefixCompare()
|
|
{
|
|
testName = "TestPrefixCompare";
|
|
SetUpTest(true);
|
|
string btreeDBFileName = testHome + "/" +
|
|
testName + ".db";
|
|
|
|
BTreeDatabaseConfig dbConfig =
|
|
new BTreeDatabaseConfig();
|
|
dbConfig.Creation = CreatePolicy.IF_NEEDED;
|
|
dbConfig.Duplicates = DuplicatesPolicy.SORTED;
|
|
dbConfig.BTreeCompare =
|
|
new EntryComparisonDelegate(dbIntCompare);
|
|
dbConfig.BTreePrefixCompare =
|
|
new EntryPrefixComparisonDelegate(dbPrefixCompare);
|
|
BTreeDatabase db = BTreeDatabase.Open(
|
|
btreeDBFileName, dbConfig);
|
|
|
|
Assert.AreEqual(3, db.PrefixCompare(new DatabaseEntry(
|
|
BitConverter.GetBytes((Int16)255)), new DatabaseEntry(
|
|
BitConverter.GetBytes((Int32)65791))));
|
|
|
|
Assert.AreEqual(1, db.PrefixCompare(new DatabaseEntry(
|
|
BitConverter.GetBytes((Int64)255)), new DatabaseEntry(
|
|
BitConverter.GetBytes((Int64)4294967552))));
|
|
|
|
db.Close();
|
|
}
|
|
|
|
[Test]
|
|
public void TestPutMultiple()
|
|
{
|
|
testName = "TestPutMultiple";
|
|
SetUpTest(true);
|
|
|
|
PutMultiple(null);
|
|
|
|
Configuration.ClearDir(testHome);
|
|
DatabaseEnvironmentConfig cfg =
|
|
new DatabaseEnvironmentConfig();
|
|
cfg.Create = true;
|
|
cfg.UseLogging = true;
|
|
cfg.UseMPool = true;
|
|
cfg.UseTxns = true;
|
|
DatabaseEnvironment env = DatabaseEnvironment.Open(
|
|
testHome, cfg);
|
|
PutMultiple(env);
|
|
env.Close();
|
|
}
|
|
|
|
private void PutMultiple(DatabaseEnvironment env)
|
|
{
|
|
List<DatabaseEntry> kList = new List<DatabaseEntry>();
|
|
List<DatabaseEntry> vList = new List<DatabaseEntry>();
|
|
BTreeDatabase db;
|
|
DatabaseEntry key, value;
|
|
Transaction txn;
|
|
string dbFileName = (env == null) ? testHome +
|
|
"/" + testName + ".db" : testName + ".db";
|
|
int i;
|
|
|
|
BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
|
|
dbConfig.Creation = CreatePolicy.IF_NEEDED;
|
|
if (env != null) {
|
|
dbConfig.Env = env;
|
|
txn = env.BeginTransaction();
|
|
db = BTreeDatabase.Open(
|
|
dbFileName, dbConfig, txn);
|
|
txn.Commit();
|
|
} else
|
|
db = BTreeDatabase.Open(dbFileName, dbConfig);
|
|
|
|
for (i = 0; i < 100; i++) {
|
|
key = new DatabaseEntry(
|
|
BitConverter.GetBytes(i));
|
|
value = new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes("data" + i +
|
|
Configuration.RandomString(512)));
|
|
kList.Add(key);
|
|
vList.Add(value);
|
|
}
|
|
|
|
// Create bulk buffer for non-recno based keys.
|
|
MultipleDatabaseEntry keyBuff =
|
|
new MultipleDatabaseEntry(kList, false);
|
|
Assert.IsFalse(keyBuff.Recno);
|
|
|
|
// Create bulk buffer for values.
|
|
MultipleDatabaseEntry valBuff =
|
|
new MultipleDatabaseEntry(vList, false);
|
|
i = 0;
|
|
foreach (DatabaseEntry dbt in valBuff) {
|
|
Assert.AreEqual(vList[i].Data, dbt.Data);
|
|
i++;
|
|
}
|
|
Assert.AreEqual(100, i);
|
|
|
|
// Create bulk buffer from another key buffer.
|
|
MultipleDatabaseEntry keyBuff1 =
|
|
new MultipleDatabaseEntry(
|
|
keyBuff.Data, keyBuff.Recno);
|
|
i = 0;
|
|
foreach (DatabaseEntry dbt in keyBuff1) {
|
|
Assert.AreEqual(kList[i].Data, dbt.Data);
|
|
i++;
|
|
}
|
|
Assert.AreEqual(100, i);
|
|
|
|
if (env != null) {
|
|
txn = env.BeginTransaction();
|
|
db.Put(keyBuff, valBuff, txn);
|
|
Assert.AreEqual(100, db.Truncate(txn));
|
|
txn.Commit();
|
|
} else {
|
|
/*
|
|
* Bulk insert to database with key and value
|
|
* buffers.
|
|
*/
|
|
db.Put(keyBuff, valBuff);
|
|
|
|
// Verify all records exist as expected.
|
|
Cursor cursor = db.Cursor();
|
|
i = 99;
|
|
Assert.IsTrue(cursor.MoveLast());
|
|
Assert.AreEqual(kList[i].Data,
|
|
cursor.Current.Key.Data);
|
|
Assert.AreEqual(vList[i].Data,
|
|
cursor.Current.Value.Data);
|
|
while (cursor.MovePrev()) {
|
|
i--;
|
|
Assert.AreEqual(kList[i].Data,
|
|
cursor.Current.Key.Data);
|
|
Assert.AreEqual(vList[i].Data,
|
|
cursor.Current.Value.Data);
|
|
}
|
|
Assert.AreEqual(0, i);
|
|
cursor.Close();
|
|
/*
|
|
* Dumped all records. The number of records
|
|
* should be 100.
|
|
*/
|
|
Assert.AreEqual(100, db.Truncate());
|
|
|
|
/*
|
|
* Bulk insert to database with a copied key
|
|
* buffer and a value buffer.
|
|
*/
|
|
db.Put(keyBuff1, valBuff);
|
|
cursor = db.Cursor();
|
|
Assert.IsTrue(cursor.MoveLast());
|
|
i = 99;
|
|
Assert.AreEqual(kList[i].Data,
|
|
cursor.Current.Key.Data);
|
|
Assert.AreEqual(vList[i].Data,
|
|
cursor.Current.Value.Data);
|
|
while (cursor.MovePrev()) {
|
|
i--;
|
|
Assert.AreEqual(kList[i].Data,
|
|
cursor.Current.Key.Data);
|
|
Assert.AreEqual(vList[i].Data,
|
|
cursor.Current.Value.Data);
|
|
}
|
|
cursor.Close();
|
|
Assert.AreEqual(0, i);
|
|
/*
|
|
* Dumped all records. The number of records
|
|
* should be 100.
|
|
*/
|
|
Assert.AreEqual(100, db.Truncate());
|
|
}
|
|
|
|
db.Close();
|
|
}
|
|
|
|
[Test]
|
|
public void TestPutMultipleKey()
|
|
{
|
|
testName = "TestPutMultipleKey";
|
|
SetUpTest(true);
|
|
|
|
PutMultipleKey(null);
|
|
|
|
Configuration.ClearDir(testHome);
|
|
DatabaseEnvironmentConfig cfg =
|
|
new DatabaseEnvironmentConfig();
|
|
cfg.Create = true;
|
|
cfg.UseLogging = true;
|
|
cfg.UseMPool = true;
|
|
cfg.UseTxns = true;
|
|
DatabaseEnvironment env = DatabaseEnvironment.Open(
|
|
testHome, cfg);
|
|
PutMultipleKey(env);
|
|
env.Close();
|
|
}
|
|
|
|
private void PutMultipleKey(DatabaseEnvironment env)
|
|
{
|
|
List<KeyValuePair<DatabaseEntry, DatabaseEntry>> pList =
|
|
new List<KeyValuePair<
|
|
DatabaseEntry, DatabaseEntry>>();
|
|
BTreeDatabase db;
|
|
DatabaseEntry key, value;
|
|
Transaction txn;
|
|
string dbFileName = (env == null) ? testHome +
|
|
"/" + testName + ".db" : testName + ".db";
|
|
int i;
|
|
|
|
BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig();
|
|
dbConfig.Creation = CreatePolicy.IF_NEEDED;
|
|
if (env != null) {
|
|
dbConfig.Env = env;
|
|
txn = env.BeginTransaction();
|
|
db = BTreeDatabase.Open(
|
|
dbFileName, dbConfig, txn);
|
|
txn.Commit();
|
|
} else
|
|
db = BTreeDatabase.Open(dbFileName, dbConfig);
|
|
|
|
for (i = 0; i < 100; i++) {
|
|
key = new DatabaseEntry(
|
|
BitConverter.GetBytes(i));
|
|
value = new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes("data" +
|
|
i + Configuration.RandomString(512)));
|
|
pList.Add(new KeyValuePair<
|
|
DatabaseEntry, DatabaseEntry>(key, value));
|
|
}
|
|
|
|
// Create btree bulk buffer for key/value pairs.
|
|
MultipleKeyDatabaseEntry pairBuff =
|
|
new MultipleKeyDatabaseEntry(pList, false);
|
|
i = 0;
|
|
foreach (KeyValuePair<DatabaseEntry, DatabaseEntry>
|
|
pair in pairBuff) {
|
|
Assert.AreEqual(pList[i].Key.Data,
|
|
pair.Key.Data);
|
|
Assert.AreEqual(pList[i].Value.Data,
|
|
pair.Value.Data);
|
|
i++;
|
|
}
|
|
Assert.AreEqual(100, i);
|
|
|
|
/*
|
|
* Create bulk buffer from another key/value pairs
|
|
* bulk buffer.
|
|
*/
|
|
MultipleKeyDatabaseEntry pairBuff1 =
|
|
new MultipleKeyDatabaseEntry(
|
|
pairBuff.Data, false);
|
|
Assert.AreEqual(false, pairBuff1.Recno);
|
|
i = 0;
|
|
foreach (KeyValuePair<DatabaseEntry, DatabaseEntry>
|
|
pair in pairBuff1) {
|
|
Assert.AreEqual(pList[i].Key.Data,
|
|
pair.Key.Data);
|
|
Assert.AreEqual(pList[i].Value.Data,
|
|
pair.Value.Data);
|
|
i++;
|
|
}
|
|
Assert.AreEqual(100, i);
|
|
|
|
if (env == null) {
|
|
// Bulk insert with key/value pair bulk buffer.
|
|
db.Put(pairBuff);
|
|
Cursor cursor = db.Cursor();
|
|
Assert.IsTrue(cursor.MoveFirst());
|
|
i = 0;
|
|
Assert.AreEqual(pList[i].Key.Data,
|
|
cursor.Current.Key.Data);
|
|
Assert.AreEqual(pList[i].Value.Data,
|
|
cursor.Current.Value.Data);
|
|
while (cursor.MoveNext()) {
|
|
i++;
|
|
Assert.AreEqual(pList[i].Key.Data,
|
|
cursor.Current.Key.Data);
|
|
Assert.AreEqual(pList[i].Value.Data,
|
|
cursor.Current.Value.Data);
|
|
}
|
|
Assert.AreEqual(99, i);
|
|
cursor.Close();
|
|
/*
|
|
* Dump all records from the database. The
|
|
* number of records should be 100.
|
|
*/
|
|
Assert.AreEqual(100, db.Truncate());
|
|
|
|
// Bulk insert with copied key/value pair buffer.
|
|
db.Put(pairBuff1);
|
|
cursor = db.Cursor();
|
|
Assert.IsTrue(cursor.MoveFirst());
|
|
i = 0;
|
|
Assert.AreEqual(pList[i].Key.Data,
|
|
cursor.Current.Key.Data);
|
|
Assert.AreEqual(pList[i].Value.Data,
|
|
cursor.Current.Value.Data);
|
|
while (cursor.MoveNext()) {
|
|
i++;
|
|
Assert.AreEqual(pList[i].Key.Data,
|
|
cursor.Current.Key.Data);
|
|
Assert.AreEqual(pList[i].Value.Data,
|
|
cursor.Current.Value.Data);
|
|
}
|
|
Assert.AreEqual(99, i);
|
|
cursor.Close();
|
|
Assert.AreEqual(100, db.Truncate());
|
|
} else {
|
|
txn = env.BeginTransaction();
|
|
db.Put(pairBuff, txn);
|
|
Assert.AreEqual(100, db.Truncate(txn));
|
|
txn.Commit();
|
|
}
|
|
|
|
db.Close();
|
|
}
|
|
|
|
[Test]
|
|
public void TestPutWithoutTxn()
|
|
{
|
|
testName = "TestPutWithoutTxn";
|
|
SetUpTest(true);
|
|
string btreeDBFileName = testHome + "/" +
|
|
testName + ".db";
|
|
|
|
BTreeDatabaseConfig btreeDBConfig =
|
|
new BTreeDatabaseConfig();
|
|
btreeDBConfig.Creation = CreatePolicy.ALWAYS;
|
|
DatabaseEntry key, data;
|
|
KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
|
|
using (BTreeDatabase btreeDB = BTreeDatabase.Open(
|
|
btreeDBFileName, btreeDBConfig))
|
|
{
|
|
// Put integer into database
|
|
key = new DatabaseEntry(
|
|
BitConverter.GetBytes((int)0));
|
|
data = new DatabaseEntry(
|
|
BitConverter.GetBytes((int)0));
|
|
btreeDB.Put(key, data);
|
|
pair = btreeDB.Get(key);
|
|
Assert.AreEqual(key.Data, pair.Key.Data);
|
|
Assert.AreEqual(data.Data, pair.Value.Data);
|
|
|
|
// Partial put to update the existing pair.
|
|
data.Partial = true;
|
|
data.PartialLen = 4;
|
|
data.PartialOffset = 4;
|
|
btreeDB.Put(key, data);
|
|
pair = btreeDB.Get(key);
|
|
Assert.AreEqual(key.Data, pair.Key.Data);
|
|
Assert.AreEqual(8, pair.Value.Data.Length);
|
|
}
|
|
}
|
|
|
|
[Test, ExpectedException(typeof(KeyExistException))]
|
|
public void TestPutNoOverWrite()
|
|
{
|
|
testName = "TestPutNoOverWrite";
|
|
SetUpTest(true);
|
|
string btreeDBFileName = testHome + "/" +
|
|
testName + ".db";
|
|
|
|
BTreeDatabaseConfig btreeDBConfig =
|
|
new BTreeDatabaseConfig();
|
|
btreeDBConfig.Creation = CreatePolicy.ALWAYS;
|
|
DatabaseEntry key, data, newData;
|
|
using (BTreeDatabase btreeDB = BTreeDatabase.Open(
|
|
btreeDBFileName, btreeDBConfig))
|
|
{
|
|
key = new DatabaseEntry(
|
|
BitConverter.GetBytes((int)0));
|
|
data = new DatabaseEntry(
|
|
BitConverter.GetBytes((int)0));
|
|
newData = new DatabaseEntry(
|
|
BitConverter.GetBytes((int)1));
|
|
|
|
btreeDB.Put(key, data);
|
|
btreeDB.PutNoOverwrite(key, newData);
|
|
}
|
|
}
|
|
|
|
[Test, ExpectedException(typeof(ExpectedTestException))]
|
|
public void TestPutNoDuplicateWithTxn()
|
|
{
|
|
testName = "TestPutNoDuplicateWithTxn";
|
|
SetUpTest(true);
|
|
|
|
DatabaseEnvironmentConfig envConfig =
|
|
new DatabaseEnvironmentConfig();
|
|
envConfig.Create = true;
|
|
envConfig.UseLogging = true;
|
|
envConfig.UseMPool = true;
|
|
envConfig.UseTxns = true;
|
|
DatabaseEnvironment env = DatabaseEnvironment.Open(
|
|
testHome, envConfig);
|
|
|
|
Transaction txn = env.BeginTransaction();
|
|
BTreeDatabaseConfig btreeDBConfig =
|
|
new BTreeDatabaseConfig();
|
|
btreeDBConfig.Creation = CreatePolicy.ALWAYS;
|
|
btreeDBConfig.Env = env;
|
|
btreeDBConfig.Duplicates = DuplicatesPolicy.SORTED;
|
|
|
|
DatabaseEntry key, data;
|
|
try
|
|
{
|
|
using (BTreeDatabase btreeDB =
|
|
BTreeDatabase.Open(
|
|
testName + ".db", btreeDBConfig, txn))
|
|
{
|
|
key = new DatabaseEntry(
|
|
BitConverter.GetBytes((int)0));
|
|
data = new DatabaseEntry(
|
|
BitConverter.GetBytes((int)0));
|
|
|
|
btreeDB.Put(key, data, txn);
|
|
btreeDB.PutNoDuplicate(key, data, txn);
|
|
}
|
|
txn.Commit();
|
|
}
|
|
catch (KeyExistException)
|
|
{
|
|
txn.Abort();
|
|
throw new ExpectedTestException();
|
|
}
|
|
finally
|
|
{
|
|
env.Close();
|
|
}
|
|
}
|
|
|
|
[Test, ExpectedException(typeof(ExpectedTestException))]
|
|
public void TestRemoveDBFile()
|
|
{
|
|
testName = "TestRemoveDBFile";
|
|
SetUpTest(true);
|
|
|
|
|
|
RemoveDBWithoutEnv(testHome, testName, false);
|
|
}
|
|
|
|
[Test, ExpectedException(typeof(ExpectedTestException))]
|
|
public void TestRemoveOneDBFromDBFile()
|
|
{
|
|
testName = "TestRemoveOneDBFromDBFile";
|
|
SetUpTest(true);
|
|
|
|
RemoveDBWithoutEnv(testHome, testName, true);
|
|
}
|
|
|
|
public void RemoveDBWithoutEnv(string home, string dbName, bool ifDBName)
|
|
{
|
|
string dbFileName = home + "/" + dbName + ".db";
|
|
|
|
Configuration.ClearDir(home);
|
|
|
|
BTreeDatabaseConfig btreeDBConfig =
|
|
new BTreeDatabaseConfig();
|
|
btreeDBConfig.Creation = CreatePolicy.IF_NEEDED;
|
|
|
|
BTreeDatabase btreeDB;
|
|
if (ifDBName == false)
|
|
{
|
|
btreeDB = BTreeDatabase.Open(dbFileName, btreeDBConfig);
|
|
btreeDB.Close();
|
|
BTreeDatabase.Remove(dbFileName);
|
|
throw new ExpectedTestException();
|
|
}
|
|
else
|
|
{
|
|
btreeDB = BTreeDatabase.Open(dbFileName, dbName, btreeDBConfig);
|
|
btreeDB.Close();
|
|
BTreeDatabase.Remove(dbFileName, dbName);
|
|
Assert.IsTrue(File.Exists(dbFileName));
|
|
try
|
|
{
|
|
btreeDB = BTreeDatabase.Open(dbFileName, dbName, new BTreeDatabaseConfig());
|
|
btreeDB.Close();
|
|
}
|
|
catch (DatabaseException)
|
|
{
|
|
throw new ExpectedTestException();
|
|
}
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void TestRemoveDBFromFileInEnv()
|
|
{
|
|
testName = "TestRemoveDBFromFileInEnv";
|
|
SetUpTest(true);
|
|
|
|
RemoveDatabase(testHome, testName, true, true);
|
|
}
|
|
|
|
[Test]
|
|
public void TestRemoveDBFromEnv()
|
|
{
|
|
testName = "TestRemoveDBFromEnv";
|
|
SetUpTest(true);
|
|
|
|
RemoveDatabase(testHome, testName, true, false);
|
|
}
|
|
|
|
public void RemoveDatabase(string home, string dbName,
|
|
bool ifEnv, bool ifDBName)
|
|
{
|
|
string dbFileName = dbName + ".db";
|
|
|
|
Configuration.ClearDir(home);
|
|
|
|
DatabaseEnvironmentConfig envConfig =
|
|
new DatabaseEnvironmentConfig();
|
|
envConfig.Create = true;
|
|
envConfig.UseCDB = true;
|
|
envConfig.UseMPool = true;
|
|
|
|
DatabaseEnvironment env;
|
|
env = DatabaseEnvironment.Open(home, envConfig);
|
|
|
|
try
|
|
{
|
|
BTreeDatabaseConfig btreeDBConfig =
|
|
new BTreeDatabaseConfig();
|
|
btreeDBConfig.Creation = CreatePolicy.ALWAYS;
|
|
btreeDBConfig.Env = env;
|
|
BTreeDatabase btreeDB = BTreeDatabase.Open(
|
|
dbFileName, dbName, btreeDBConfig);
|
|
btreeDB.Close();
|
|
|
|
if (ifEnv == true && ifDBName == true)
|
|
BTreeDatabase.Remove(dbFileName, dbName, env);
|
|
else if (ifEnv == true)
|
|
BTreeDatabase.Remove(dbFileName, env);
|
|
}
|
|
catch (DatabaseException)
|
|
{
|
|
throw new TestException();
|
|
}
|
|
finally
|
|
{
|
|
try
|
|
{
|
|
BTreeDatabaseConfig dbConfig =
|
|
new BTreeDatabaseConfig();
|
|
dbConfig.Creation = CreatePolicy.NEVER;
|
|
dbConfig.Env = env;
|
|
BTreeDatabase db = BTreeDatabase.Open(
|
|
dbFileName, dbName, dbConfig);
|
|
Assert.AreEqual(db.Creation, CreatePolicy.NEVER);
|
|
db.Close();
|
|
throw new TestException();
|
|
}
|
|
catch (DatabaseException)
|
|
{
|
|
}
|
|
finally
|
|
{
|
|
env.Close();
|
|
}
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void TestRenameDB()
|
|
{
|
|
testName = "TestRenameDB";
|
|
SetUpTest(true);
|
|
string btreeDBFileName = testHome + "/" + testName + ".db";
|
|
string btreeDBName = testName;
|
|
string newBtreeDBName = btreeDBName + "1" + ".db";
|
|
|
|
try
|
|
{
|
|
BTreeDatabaseConfig btreeDBConfig =
|
|
new BTreeDatabaseConfig();
|
|
btreeDBConfig.Creation = CreatePolicy.ALWAYS;
|
|
BTreeDatabase btreeDB = BTreeDatabase.Open(
|
|
btreeDBFileName, btreeDBName, btreeDBConfig);
|
|
btreeDB.Close();
|
|
BTreeDatabase.Rename(btreeDBFileName,
|
|
btreeDBName, newBtreeDBName);
|
|
|
|
BTreeDatabaseConfig dbConfig =
|
|
new BTreeDatabaseConfig();
|
|
dbConfig.Creation = CreatePolicy.NEVER;
|
|
BTreeDatabase newDB = BTreeDatabase.Open(
|
|
btreeDBFileName, newBtreeDBName, dbConfig);
|
|
newDB.Close();
|
|
}
|
|
catch (DatabaseException e)
|
|
{
|
|
throw new TestException(e.Message);
|
|
}
|
|
finally
|
|
{
|
|
try
|
|
{
|
|
BTreeDatabaseConfig dbConfig =
|
|
new BTreeDatabaseConfig();
|
|
dbConfig.Creation = CreatePolicy.NEVER;
|
|
BTreeDatabase db = BTreeDatabase.Open(
|
|
btreeDBFileName, btreeDBName,
|
|
dbConfig);
|
|
throw new TestException(testName);
|
|
}
|
|
catch (DatabaseException)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void TestRenameDBFile()
|
|
{
|
|
testName = "TestRenameDB";
|
|
SetUpTest(true);
|
|
string btreeDBFileName = testHome + "/" +
|
|
testName + ".db";
|
|
string newBtreeDBFileName = testHome + "/" +
|
|
testName + "1.db";
|
|
|
|
BTreeDatabaseConfig btreeDBConfig =
|
|
new BTreeDatabaseConfig();
|
|
btreeDBConfig.Creation = CreatePolicy.ALWAYS;
|
|
BTreeDatabase btreeDB = BTreeDatabase.Open(
|
|
btreeDBFileName, btreeDBConfig);
|
|
btreeDB.Close();
|
|
|
|
BTreeDatabase.Rename(btreeDBFileName,
|
|
newBtreeDBFileName);
|
|
Assert.IsFalse(File.Exists(btreeDBFileName));
|
|
Assert.IsTrue(File.Exists(newBtreeDBFileName));
|
|
}
|
|
|
|
[Test]
|
|
public void TestSync()
|
|
{
|
|
testName = "TestSync";
|
|
SetUpTest(true);
|
|
string btreeDBName = testName + ".db";
|
|
|
|
DatabaseEnvironmentConfig envConfig =
|
|
new DatabaseEnvironmentConfig();
|
|
envConfig.Create = true;
|
|
envConfig.ForceFlush = true;
|
|
envConfig.UseTxns = true;
|
|
envConfig.UseMPool = true;
|
|
envConfig.UseLogging = true;
|
|
envConfig.LogSystemCfg = new LogConfig();
|
|
envConfig.LogSystemCfg.ForceSync = false;
|
|
envConfig.LogSystemCfg.AutoRemove = true;
|
|
DatabaseEnvironment env = DatabaseEnvironment.Open(
|
|
testHome, envConfig);
|
|
|
|
TransactionConfig txnConfig = new TransactionConfig();
|
|
txnConfig.SyncAction =
|
|
TransactionConfig.LogFlush.WRITE_NOSYNC;
|
|
Transaction txn = env.BeginTransaction(txnConfig);
|
|
|
|
BTreeDatabaseConfig btreeConfig =
|
|
new BTreeDatabaseConfig();
|
|
btreeConfig.Creation = CreatePolicy.ALWAYS;
|
|
btreeConfig.Env = env;
|
|
|
|
BTreeDatabase btreeDB = BTreeDatabase.Open(
|
|
btreeDBName, btreeConfig, txn);
|
|
|
|
DatabaseEntry key = new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes("key"));
|
|
DatabaseEntry data = new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes("data"));
|
|
Assert.IsFalse(btreeDB.Exists(key, txn));
|
|
btreeDB.Put(key, data, txn);
|
|
btreeDB.Sync();
|
|
btreeDB.Close(false);
|
|
txn.Commit();
|
|
env.Close();
|
|
|
|
BTreeDatabaseConfig dbConfig =
|
|
new BTreeDatabaseConfig();
|
|
dbConfig.Creation = CreatePolicy.NEVER;
|
|
using (BTreeDatabase db = BTreeDatabase.Open(
|
|
testHome + "/" + btreeDBName, dbConfig))
|
|
{
|
|
Assert.IsTrue(db.Exists(key));
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void TestTruncate()
|
|
{
|
|
testName = "TestTruncate";
|
|
SetUpTest(true);
|
|
string btreeDBFileName = testHome + "/" +
|
|
testName + ".db";
|
|
|
|
BTreeDatabaseConfig btreeDBConfig =
|
|
new BTreeDatabaseConfig();
|
|
btreeDBConfig.Creation = CreatePolicy.ALWAYS;
|
|
btreeDBConfig.CacheSize =
|
|
new CacheInfo(0, 30 * 1024, 1);
|
|
BTreeDatabase btreeDB = BTreeDatabase.Open(
|
|
btreeDBFileName, btreeDBConfig);
|
|
DatabaseEntry key;
|
|
DatabaseEntry data;
|
|
for (int i = 0; i < 100; i++)
|
|
{
|
|
key = new DatabaseEntry(
|
|
BitConverter.GetBytes(i));
|
|
data = new DatabaseEntry(
|
|
BitConverter.GetBytes(i));
|
|
btreeDB.Put(key, data);
|
|
}
|
|
uint count = btreeDB.Truncate();
|
|
Assert.AreEqual(100, count);
|
|
Assert.IsFalse(btreeDB.Exists(new DatabaseEntry(
|
|
BitConverter.GetBytes((int)50))));
|
|
btreeDB.Close();
|
|
}
|
|
|
|
[Test]
|
|
public void TestTruncateInTxn()
|
|
{
|
|
testName = "TestTruncateInTxn";
|
|
SetUpTest(true);
|
|
|
|
DatabaseEnvironmentConfig envConfig =
|
|
new DatabaseEnvironmentConfig();
|
|
envConfig.Create = true;
|
|
envConfig.UseMPool = true;
|
|
envConfig.UseTxns = true;
|
|
DatabaseEnvironment env = DatabaseEnvironment.Open(
|
|
testHome, envConfig);
|
|
|
|
try
|
|
{
|
|
Transaction openTxn = env.BeginTransaction();
|
|
BTreeDatabaseConfig dbConfig =
|
|
new BTreeDatabaseConfig();
|
|
dbConfig.Creation = CreatePolicy.IF_NEEDED;
|
|
dbConfig.Env = env;
|
|
BTreeDatabase db = BTreeDatabase.Open(
|
|
testName + ".db", dbConfig, openTxn);
|
|
openTxn.Commit();
|
|
|
|
Transaction putTxn = env.BeginTransaction();
|
|
try
|
|
{
|
|
DatabaseEntry key, data;
|
|
for (int i = 0; i < 10; i++)
|
|
{
|
|
key = new DatabaseEntry(
|
|
BitConverter.GetBytes(i));
|
|
data = new DatabaseEntry(
|
|
BitConverter.GetBytes(i));
|
|
db.Put(key, data, putTxn);
|
|
}
|
|
|
|
putTxn.Commit();
|
|
}
|
|
catch (DatabaseException e)
|
|
{
|
|
putTxn.Abort();
|
|
db.Close();
|
|
throw e;
|
|
}
|
|
|
|
Transaction trunTxn = env.BeginTransaction();
|
|
try
|
|
{
|
|
uint count = db.Truncate(trunTxn);
|
|
Assert.AreEqual(10, count);
|
|
Assert.IsFalse(db.Exists(
|
|
new DatabaseEntry(
|
|
BitConverter.GetBytes((int)5)), trunTxn));
|
|
trunTxn.Commit();
|
|
db.Close();
|
|
}
|
|
catch (DatabaseException)
|
|
{
|
|
trunTxn.Abort();
|
|
db.Close();
|
|
throw new TestException();
|
|
}
|
|
}
|
|
catch (DatabaseException)
|
|
{
|
|
}
|
|
finally
|
|
{
|
|
env.Close();
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void TestTruncateUnusedPages()
|
|
{
|
|
testName = "TestTruncateUnusedPages";
|
|
SetUpTest(true);
|
|
string dbFileName = testHome + "/" + testName + ".db";
|
|
|
|
BTreeDatabaseConfig dbConfig =
|
|
new BTreeDatabaseConfig();
|
|
dbConfig.Creation = CreatePolicy.ALWAYS;
|
|
dbConfig.PageSize = 512;
|
|
BTreeDatabase db = BTreeDatabase.Open(
|
|
dbFileName, dbConfig);
|
|
DatabaseEntry key, data;
|
|
for (int i = 0; i < 100; i++)
|
|
{
|
|
key = new DatabaseEntry(
|
|
BitConverter.GetBytes(i));
|
|
data = new DatabaseEntry(
|
|
BitConverter.GetBytes(i));
|
|
db.Put(key, data);
|
|
}
|
|
|
|
for (int i = 0; i < 80; i++)
|
|
db.Delete(new DatabaseEntry(
|
|
BitConverter.GetBytes(i)));
|
|
|
|
uint count = db.TruncateUnusedPages();
|
|
Assert.LessOrEqual(0, count);
|
|
|
|
db.Close();
|
|
}
|
|
|
|
[Test]
|
|
public void TestTruncateUnusedPagesWithTxn()
|
|
{
|
|
testName = "TestTruncateUnusedPagesWithTxn";
|
|
SetUpTest(true);
|
|
|
|
DatabaseEnvironmentConfig envConfig =
|
|
new DatabaseEnvironmentConfig();
|
|
envConfig.Create = true;
|
|
envConfig.UseMPool = true;
|
|
envConfig.UseTxns = true;
|
|
DatabaseEnvironment env = DatabaseEnvironment.Open(
|
|
testHome, envConfig);
|
|
|
|
BTreeDatabase db;
|
|
try
|
|
{
|
|
Transaction openTxn = env.BeginTransaction();
|
|
try
|
|
{
|
|
BTreeDatabaseConfig dbConfig =
|
|
new BTreeDatabaseConfig();
|
|
dbConfig.Creation = CreatePolicy.IF_NEEDED;
|
|
dbConfig.Env = env;
|
|
dbConfig.PageSize = 512;
|
|
db = BTreeDatabase.Open(
|
|
testName + ".db", dbConfig, openTxn);
|
|
openTxn.Commit();
|
|
Assert.AreEqual(512, db.Pagesize);
|
|
}
|
|
catch (DatabaseException e)
|
|
{
|
|
openTxn.Abort();
|
|
throw e;
|
|
}
|
|
|
|
Transaction putTxn = env.BeginTransaction();
|
|
try
|
|
{
|
|
DatabaseEntry key, data;
|
|
for (int i = 0; i < 100; i++)
|
|
{
|
|
key = new DatabaseEntry(
|
|
BitConverter.GetBytes(i));
|
|
data = new DatabaseEntry(
|
|
BitConverter.GetBytes(i));
|
|
db.Put(key, data, putTxn);
|
|
}
|
|
|
|
putTxn.Commit();
|
|
}
|
|
catch (DatabaseException e)
|
|
{
|
|
putTxn.Abort();
|
|
db.Close();
|
|
throw e;
|
|
}
|
|
|
|
Transaction delTxn = env.BeginTransaction();
|
|
try
|
|
{
|
|
for (int i = 20; i <= 80; i++)
|
|
db.Delete(new DatabaseEntry(
|
|
BitConverter.GetBytes(i)), delTxn);
|
|
delTxn.Commit();
|
|
}
|
|
catch (DatabaseException e)
|
|
{
|
|
delTxn.Abort();
|
|
db.Close();
|
|
throw e;
|
|
}
|
|
|
|
Transaction trunTxn = env.BeginTransaction();
|
|
try
|
|
{
|
|
uint trunPages = db.TruncateUnusedPages(
|
|
trunTxn);
|
|
Assert.LessOrEqual(0, trunPages);
|
|
trunTxn.Commit();
|
|
db.Close();
|
|
}
|
|
catch (DatabaseException)
|
|
{
|
|
trunTxn.Abort();
|
|
db.Close();
|
|
throw new Exception();
|
|
}
|
|
}
|
|
catch (DatabaseException)
|
|
{
|
|
}
|
|
finally
|
|
{
|
|
env.Close();
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void TestSalvage()
|
|
{
|
|
testName = "TestSalvage";
|
|
SetUpTest(true);
|
|
string btreeDBFileName = testHome + "/" +
|
|
testName + ".db";
|
|
string printableOutPut = testHome + "/" +
|
|
"printableOutPut";
|
|
string inprintableOutPut = testHome + "/" +
|
|
"inprintableOutPut";
|
|
|
|
BTreeDatabaseConfig btreeDBConfig =
|
|
new BTreeDatabaseConfig();
|
|
btreeDBConfig.Creation = CreatePolicy.ALWAYS;
|
|
BTreeDatabase btreeDB = BTreeDatabase.Open(
|
|
btreeDBFileName, btreeDBConfig);
|
|
|
|
DatabaseEntry key;
|
|
DatabaseEntry data;
|
|
|
|
for (uint i = 0; i < 10; i++)
|
|
{
|
|
key = new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes(i.ToString()));
|
|
data = new DatabaseEntry(
|
|
ASCIIEncoding.ASCII.GetBytes(i.ToString()));
|
|
btreeDB.Put(key, data);
|
|
}
|
|
|
|
btreeDB.Close();
|
|
|
|
StreamWriter sw1 = new StreamWriter(printableOutPut);
|
|
StreamWriter sw2 = new StreamWriter(inprintableOutPut);
|
|
BTreeDatabase.Salvage(btreeDBFileName, btreeDBConfig,
|
|
true, true, sw1);
|
|
BTreeDatabase.Salvage(btreeDBFileName, btreeDBConfig,
|
|
false, true, sw2);
|
|
sw1.Close();
|
|
sw2.Close();
|
|
|
|
FileStream file1 = new FileStream(printableOutPut,
|
|
FileMode.Open);
|
|
FileStream file2 = new FileStream(inprintableOutPut,
|
|
FileMode.Open);
|
|
if (file1.Length == file2.Length)
|
|
{
|
|
int filebyte1 = 0;
|
|
int filebyte2 = 0;
|
|
do
|
|
{
|
|
filebyte1 = file1.ReadByte();
|
|
filebyte2 = file2.ReadByte();
|
|
} while ((filebyte1 == filebyte2) &&
|
|
(filebyte1 != -1));
|
|
Assert.AreNotEqual(filebyte1, filebyte2);
|
|
}
|
|
|
|
file1.Close();
|
|
file2.Close();
|
|
}
|
|
|
|
[Test]
|
|
public void TestUpgrade()
|
|
{
|
|
testName = "TestUpgrade";
|
|
SetUpTest(true);
|
|
|
|
string srcDBFileName = "../../bdb4.7.db";
|
|
string testDBFileName = testHome + "/bdb4.7.db";
|
|
|
|
FileInfo srcDBFileInfo = new FileInfo(srcDBFileName);
|
|
|
|
//Copy the file.
|
|
srcDBFileInfo.CopyTo(testDBFileName);
|
|
Assert.IsTrue(File.Exists(testDBFileName));
|
|
|
|
BTreeDatabase.Upgrade(testDBFileName,
|
|
new DatabaseConfig(), true);
|
|
|
|
// Open the upgraded database file.
|
|
BTreeDatabase db = BTreeDatabase.Open(
|
|
testDBFileName, new BTreeDatabaseConfig());
|
|
db.Close();
|
|
}
|
|
|
|
[Test, ExpectedException(typeof(TestException))]
|
|
public void TestVerify()
|
|
{
|
|
testName = "TestVerify";
|
|
SetUpTest(true);
|
|
string btreeDBFileName = testHome + "/" +
|
|
testName + ".db";
|
|
string btreeDBName =
|
|
Path.GetFileNameWithoutExtension(btreeDBFileName);
|
|
|
|
BTreeDatabaseConfig btreeDBConfig =
|
|
new BTreeDatabaseConfig();
|
|
btreeDBConfig.Creation = CreatePolicy.ALWAYS;
|
|
BTreeDatabase btreeDB = BTreeDatabase.Open(
|
|
btreeDBFileName, btreeDBName, btreeDBConfig);
|
|
btreeDB.Close();
|
|
btreeDBConfig.Duplicates = DuplicatesPolicy.SORTED;
|
|
BTreeDatabase.Verify(btreeDBFileName, btreeDBConfig,
|
|
Database.VerifyOperation.NO_ORDER_CHECK);
|
|
try
|
|
{
|
|
BTreeDatabase.Verify(btreeDBFileName,
|
|
btreeDBConfig,
|
|
Database.VerifyOperation.ORDER_CHECK_ONLY);
|
|
}
|
|
catch (DatabaseException)
|
|
{
|
|
throw new TestException(testName);
|
|
}
|
|
finally
|
|
{
|
|
BTreeDatabase.Verify(btreeDBFileName,
|
|
btreeDBName, btreeDBConfig,
|
|
Database.VerifyOperation.ORDER_CHECK_ONLY);
|
|
}
|
|
|
|
}
|
|
|
|
[Test]
|
|
public void TestStats()
|
|
{
|
|
testName = "TestStats";
|
|
SetUpTest(true);
|
|
string dbFileName = testHome + "/" +
|
|
testName + ".db";
|
|
|
|
BTreeDatabaseConfig dbConfig =
|
|
new BTreeDatabaseConfig();
|
|
ConfigCase1(dbConfig);
|
|
BTreeDatabase db = BTreeDatabase.Open(dbFileName,
|
|
dbConfig);
|
|
|
|
BTreeStats stats = db.Stats();
|
|
ConfirmStatsPart1Case1(stats);
|
|
|
|
// Put 500 records into the database.
|
|
PutRecordCase1(db, null);
|
|
|
|
stats = db.Stats();
|
|
ConfirmStatsPart2Case1(stats);
|
|
|
|
// Delete some data to get some free pages.
|
|
byte[] bigArray = new byte[10240];
|
|
db.Delete(new DatabaseEntry(bigArray));
|
|
|
|
db.PrintStats();
|
|
db.PrintFastStats();
|
|
|
|
db.Close();
|
|
}
|
|
|
|
[Test]
|
|
public void TestStatsInTxn()
|
|
{
|
|
testName = "TestStatsInTxn";
|
|
SetUpTest(true);
|
|
|
|
StatsInTxn(testHome, testName, false);
|
|
}
|
|
|
|
[Test]
|
|
public void TestStatsWithIsolation()
|
|
{
|
|
testName = "TestStatsWithIsolation";
|
|
SetUpTest(true);
|
|
|
|
StatsInTxn(testHome, testName, true);
|
|
}
|
|
|
|
[Test]
|
|
public void TestMultipleDBSingleFile()
|
|
{
|
|
testName = "TestMultipleDBSingleFile";
|
|
SetUpTest(true);
|
|
string btreeDBName = testHome + "/" + testName + ".db";
|
|
|
|
string dbName = "test";
|
|
|
|
/* Create and initialize database object, open the database. */
|
|
BTreeDatabaseConfig btreeDBconfig = new BTreeDatabaseConfig();
|
|
btreeDBconfig.Creation = CreatePolicy.IF_NEEDED;
|
|
btreeDBconfig.ErrorPrefix = testName;
|
|
btreeDBconfig.UseRecordNumbers = true;
|
|
|
|
BTreeDatabase btreeDB = BTreeDatabase.Open(btreeDBName, dbName,
|
|
btreeDBconfig);
|
|
btreeDB.Close();
|
|
btreeDB = BTreeDatabase.Open(btreeDBName, dbName + "2",
|
|
btreeDBconfig);
|
|
btreeDB.Close();
|
|
|
|
BTreeDatabaseConfig dbcfg = new BTreeDatabaseConfig();
|
|
dbcfg.ReadOnly = true;
|
|
BTreeDatabase newDb = BTreeDatabase.Open(btreeDBName, dbcfg);
|
|
Boolean val = newDb.HasMultiple;
|
|
Assert.IsTrue(val);
|
|
newDb.Close();
|
|
}
|
|
|
|
public void StatsInTxn(string home, string name, bool ifIsolation)
|
|
{
|
|
DatabaseEnvironmentConfig envConfig =
|
|
new DatabaseEnvironmentConfig();
|
|
EnvConfigCase1(envConfig);
|
|
DatabaseEnvironment env = DatabaseEnvironment.Open(
|
|
home, envConfig);
|
|
|
|
Transaction openTxn = env.BeginTransaction();
|
|
BTreeDatabaseConfig dbConfig =
|
|
new BTreeDatabaseConfig();
|
|
ConfigCase1(dbConfig);
|
|
dbConfig.Env = env;
|
|
BTreeDatabase db = BTreeDatabase.Open(name + ".db",
|
|
dbConfig, openTxn);
|
|
openTxn.Commit();
|
|
|
|
Transaction statsTxn = env.BeginTransaction();
|
|
BTreeStats stats;
|
|
BTreeStats fastStats;
|
|
if (ifIsolation == false)
|
|
{
|
|
stats = db.Stats(statsTxn);
|
|
fastStats = db.FastStats(statsTxn);
|
|
}
|
|
else
|
|
{
|
|
stats = db.Stats(statsTxn, Isolation.DEGREE_ONE);
|
|
fastStats = db.FastStats(statsTxn,
|
|
Isolation.DEGREE_ONE);
|
|
}
|
|
ConfirmStatsPart1Case1(stats);
|
|
|
|
// Put 500 records into the database.
|
|
PutRecordCase1(db, statsTxn);
|
|
|
|
if (ifIsolation == false)
|
|
stats = db.Stats(statsTxn);
|
|
else
|
|
stats = db.Stats(statsTxn, Isolation.DEGREE_TWO);
|
|
ConfirmStatsPart2Case1(stats);
|
|
|
|
// Delete some data to get some free pages.
|
|
byte[] bigArray = new byte[10240];
|
|
db.Delete(new DatabaseEntry(bigArray), statsTxn);
|
|
if (ifIsolation == false)
|
|
stats = db.Stats(statsTxn);
|
|
else
|
|
stats = db.Stats(statsTxn, Isolation.DEGREE_THREE);
|
|
ConfirmStatsPart3Case1(stats);
|
|
|
|
db.PrintStats(true);
|
|
Assert.AreEqual(0, stats.EmptyPages);
|
|
|
|
statsTxn.Commit();
|
|
db.Close();
|
|
env.Close();
|
|
}
|
|
|
|
public void EnvConfigCase1(DatabaseEnvironmentConfig cfg)
|
|
{
|
|
cfg.Create = true;
|
|
cfg.UseTxns = true;
|
|
cfg.UseMPool = true;
|
|
cfg.UseLogging = true;
|
|
}
|
|
|
|
public void ConfigCase1(BTreeDatabaseConfig dbConfig)
|
|
{
|
|
dbConfig.Creation = CreatePolicy.IF_NEEDED;
|
|
dbConfig.Duplicates = DuplicatesPolicy.UNSORTED;
|
|
dbConfig.PageSize = 4096;
|
|
dbConfig.MinKeysPerPage = 10;
|
|
}
|
|
|
|
public void PutRecordCase1(BTreeDatabase db, Transaction txn)
|
|
{
|
|
byte[] bigArray = new byte[10240];
|
|
for (int i = 0; i < 100; i++)
|
|
{
|
|
if (txn == null)
|
|
db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
|
|
new DatabaseEntry(BitConverter.GetBytes(i)));
|
|
else
|
|
db.Put(new DatabaseEntry(BitConverter.GetBytes(i)),
|
|
new DatabaseEntry(BitConverter.GetBytes(i)), txn);
|
|
}
|
|
for (int i = 100; i < 500; i++)
|
|
{
|
|
if (txn == null)
|
|
db.Put(new DatabaseEntry(bigArray),
|
|
new DatabaseEntry(bigArray));
|
|
else
|
|
db.Put(new DatabaseEntry(bigArray),
|
|
new DatabaseEntry(bigArray), txn);
|
|
}
|
|
}
|
|
|
|
public void ConfirmStatsPart1Case1(BTreeStats stats)
|
|
{
|
|
Assert.AreEqual(1, stats.EmptyPages);
|
|
Assert.AreNotEqual(0, stats.LeafPagesFreeBytes);
|
|
Assert.AreEqual(1, stats.Levels);
|
|
Assert.AreNotEqual(0, stats.MagicNumber);
|
|
Assert.AreEqual(1, stats.MetadataFlags);
|
|
Assert.AreEqual(10, stats.MinKey);
|
|
Assert.AreEqual(2, stats.nPages);
|
|
Assert.AreEqual(4096, stats.PageSize);
|
|
Assert.AreEqual(9, stats.Version);
|
|
}
|
|
|
|
public void ConfirmStatsPart2Case1(BTreeStats stats)
|
|
{
|
|
Assert.AreNotEqual(0, stats.DuplicatePages);
|
|
Assert.AreNotEqual(0, stats.DuplicatePagesFreeBytes);
|
|
Assert.AreNotEqual(0, stats.InternalPages);
|
|
Assert.AreNotEqual(0, stats.InternalPagesFreeBytes);
|
|
Assert.AreNotEqual(0, stats.LeafPages);
|
|
Assert.AreEqual(500, stats.nData);
|
|
Assert.AreEqual(101, stats.nKeys);
|
|
Assert.AreNotEqual(0, stats.OverflowPages);
|
|
Assert.AreNotEqual(0, stats.OverflowPagesFreeBytes);
|
|
}
|
|
|
|
public void ConfirmStatsPart3Case1(BTreeStats stats)
|
|
{
|
|
Assert.AreNotEqual(0, stats.FreePages);
|
|
}
|
|
|
|
private int dbIntCompare(DatabaseEntry dbt1,
|
|
DatabaseEntry dbt2)
|
|
{
|
|
int a, b;
|
|
a = BitConverter.ToInt32(dbt1.Data, 0);
|
|
b = BitConverter.ToInt32(dbt2.Data, 0);
|
|
return a - b;
|
|
}
|
|
|
|
private uint dbPrefixCompare(DatabaseEntry dbt1,
|
|
DatabaseEntry dbt2)
|
|
{
|
|
uint cnt, len;
|
|
|
|
len = Math.Min((uint)dbt1.Data.Length, (uint)dbt2.Data.Length);
|
|
for (cnt = 0; cnt < len; cnt++)
|
|
{
|
|
if (dbt1.Data[cnt] != dbt2.Data[cnt])
|
|
return cnt + 1;
|
|
}
|
|
if (dbt1.Data.Length > dbt2.Data.Length)
|
|
return (uint)dbt2.Data.Length + 1;
|
|
else if (dbt1.Data.Length < dbt2.Data.Length)
|
|
return (uint)dbt1.Data.Length + 1;
|
|
else
|
|
return (uint)dbt1.Data.Length;
|
|
}
|
|
|
|
public void SetUpEnvAndTxn(string home,
|
|
out DatabaseEnvironment env, out Transaction txn)
|
|
{
|
|
DatabaseEnvironmentConfig envConfig =
|
|
new DatabaseEnvironmentConfig();
|
|
envConfig.Create = true;
|
|
envConfig.UseTxns = true;
|
|
envConfig.UseMPool = true;
|
|
env = DatabaseEnvironment.Open(home, envConfig);
|
|
txn = env.BeginTransaction();
|
|
}
|
|
|
|
public void OpenBtreeDB(DatabaseEnvironment env,
|
|
Transaction txn, string dbFileName,
|
|
out BTreeDatabase db)
|
|
{
|
|
BTreeDatabaseConfig dbConfig =
|
|
new BTreeDatabaseConfig();
|
|
dbConfig.Creation = CreatePolicy.IF_NEEDED;
|
|
if (env != null)
|
|
{
|
|
dbConfig.Env = env;
|
|
dbConfig.NoMMap = false;
|
|
db = BTreeDatabase.Open(dbFileName, dbConfig, txn);
|
|
}
|
|
else
|
|
{
|
|
db = BTreeDatabase.Open(dbFileName, dbConfig);
|
|
}
|
|
}
|
|
|
|
private BTreeDatabase GetMultipleDB(
|
|
string filename, string dbname, BTreeDatabaseConfig cfg) {
|
|
BTreeDatabase ret;
|
|
DatabaseEntry data, key;
|
|
|
|
ret = BTreeDatabase.Open(filename, dbname, cfg);
|
|
key = null;
|
|
if (cfg.UseRecordNumbers) {
|
|
/*
|
|
* Dups aren't allowed with record numbers, so
|
|
* we have to put different data. Also, record
|
|
* numbers start at 1, so we do too, which makes
|
|
* checking results easier.
|
|
*/
|
|
for (int i = 1; i < 100; i++) {
|
|
key = new DatabaseEntry(
|
|
BitConverter.GetBytes(i));
|
|
data = new DatabaseEntry(
|
|
BitConverter.GetBytes(i));
|
|
ret.Put(key, data);
|
|
}
|
|
|
|
key = new DatabaseEntry(
|
|
BitConverter.GetBytes(100));
|
|
data = new DatabaseEntry();
|
|
data.Data = new byte[111];
|
|
for (int i = 0; i < 111; i++)
|
|
data.Data[i] = (byte)i;
|
|
ret.Put(key, data);
|
|
} else {
|
|
for (int i = 0; i < 100; i++) {
|
|
if (i % 10 == 0)
|
|
key = new DatabaseEntry(
|
|
BitConverter.GetBytes(i));
|
|
data = new DatabaseEntry(
|
|
BitConverter.GetBytes(i));
|
|
/* Don't put nulls into the db. */
|
|
Assert.IsFalse(key == null);
|
|
Assert.IsFalse(data == null);
|
|
ret.Put(key, data);
|
|
}
|
|
|
|
if (cfg.Duplicates == DuplicatesPolicy.UNSORTED) {
|
|
/* Add in duplicates to check GetBothMultiple */
|
|
key = new DatabaseEntry(
|
|
BitConverter.GetBytes(100));
|
|
data = new DatabaseEntry(
|
|
BitConverter.GetBytes(100));
|
|
for (int i = 0; i < 10; i++)
|
|
ret.Put(key, data);
|
|
|
|
/*
|
|
* Add duplicates to check GetMultiple
|
|
* with given buffer size.
|
|
*/
|
|
for (int i = 101; i < 1024; i++) {
|
|
key = new DatabaseEntry(
|
|
BitConverter.GetBytes(101));
|
|
data = new DatabaseEntry(
|
|
BitConverter.GetBytes(i));
|
|
ret.Put(key, data);
|
|
}
|
|
|
|
key = new DatabaseEntry(
|
|
BitConverter.GetBytes(102));
|
|
data = new DatabaseEntry();
|
|
data.Data = new byte[112];
|
|
for (int i = 0; i < 112; i++)
|
|
data.Data[i] = (byte)i;
|
|
ret.Put(key, data);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
public static void Confirm(XmlElement xmlElem,
|
|
BTreeDatabase btreeDB, bool compulsory)
|
|
{
|
|
DatabaseTest.Confirm(xmlElem, btreeDB, compulsory);
|
|
Configuration.ConfirmDuplicatesPolicy(xmlElem,
|
|
"Duplicates", btreeDB.Duplicates, compulsory);
|
|
Configuration.ConfirmUint(xmlElem, "MinKeysPerPage",
|
|
btreeDB.MinKeysPerPage, compulsory);
|
|
/*
|
|
* BTreeDatabase.RecordNumbers is the value of
|
|
* BTreeDatabaseConfig.UseRecordNumbers.
|
|
*/
|
|
Configuration.ConfirmBool(xmlElem, "UseRecordNumbers",
|
|
btreeDB.RecordNumbers, compulsory);
|
|
/*
|
|
* BTreeDatabase.ReverseSplit is the value of
|
|
* BTreeDatabaseConfig.NoReverseSplitting.
|
|
*/
|
|
Configuration.ConfirmBool(xmlElem, "NoReverseSplitting",
|
|
btreeDB.ReverseSplit, compulsory);
|
|
Assert.AreEqual(DatabaseType.BTREE, btreeDB.Type);
|
|
string type = btreeDB.ToString();
|
|
Assert.IsNotNull(type);
|
|
}
|
|
}
|
|
}
|
|
|