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

771 lines
20 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.Generic;
using System.IO;
using System.Text;
using System.Xml;
using NUnit.Framework;
using BerkeleyDB;
namespace CsharpAPITest
{
[TestFixture]
public class QueueDatabaseTest : DatabaseTest
{
[TestFixtureSetUp]
public void SetUpTestFixture()
{
testFixtureName = "QueueDatabaseTest";
base.SetUpTestfixture();
}
[Test]
public void TestAppendWithoutTxn()
{
testName = "TestAppendWithoutTxn";
SetUpTest(true);
string queueDBFileName = testHome + "/" + testName + ".db";
QueueDatabaseConfig queueConfig = new QueueDatabaseConfig();
queueConfig.Creation = CreatePolicy.ALWAYS;
queueConfig.Length = 1000;
QueueDatabase queueDB = QueueDatabase.Open(
queueDBFileName, queueConfig);
byte[] byteArr = new byte[4];
byteArr = BitConverter.GetBytes((int)1);
DatabaseEntry data = new DatabaseEntry(byteArr);
uint recno = queueDB.Append(data);
// Confirm that the recno is larger than 0.
Assert.AreNotEqual(0, recno);
// Confirm that the record exists in the database.
byteArr = BitConverter.GetBytes(recno);
DatabaseEntry key = new DatabaseEntry();
key.Data = byteArr;
Assert.IsTrue(queueDB.Exists(key));
queueDB.Close();
}
[Test]
public void TestAppendWithTxn()
{
testName = "TestAppendWithTxn";
SetUpTest(true);
string queueDBFileName = testHome + "/" + testName + ".db";
string queueDBName =
Path.GetFileNameWithoutExtension(queueDBFileName);
DatabaseEnvironmentConfig envConfig =
new DatabaseEnvironmentConfig();
envConfig.Create = true;
envConfig.UseTxns = true;
envConfig.UseMPool = true;
DatabaseEnvironment env = DatabaseEnvironment.Open(
testHome, envConfig);
Transaction txn = env.BeginTransaction();
QueueDatabaseConfig queueConfig = new QueueDatabaseConfig();
queueConfig.Creation = CreatePolicy.ALWAYS;
queueConfig.Env = env;
queueConfig.Length = 1000;
/* If environmnet home is set, the file name in
* Open() is the relative path.
*/
QueueDatabase queueDB = QueueDatabase.Open(
queueDBName, queueConfig, txn);
DatabaseEntry data;
int i = 1000;
try
{
while (i > 0)
{
data = new DatabaseEntry(
BitConverter.GetBytes(i));
queueDB.Append(data, txn);
i--;
}
txn.Commit();
}
catch
{
txn.Abort();
}
finally
{
queueDB.Close();
env.Close();
}
}
[Test, ExpectedException(typeof(ExpectedTestException))]
public void TestConsumeWithTxn()
{
testName = "TestConsumeWithTxn";
SetUpTest(true);
string queueDBFileName = testHome + "/" + testName + ".db";
string queueDBName = Path.GetFileName(queueDBFileName);
DatabaseEnvironmentConfig envConfig =
new DatabaseEnvironmentConfig();
envConfig.Create = true;
envConfig.UseTxns = true;
envConfig.UseMPool = true;
DatabaseEnvironment env = DatabaseEnvironment.Open(
testHome, envConfig);
Transaction txn = env.BeginTransaction();
QueueDatabaseConfig queueConfig =
new QueueDatabaseConfig();
queueConfig.Creation = CreatePolicy.ALWAYS;
queueConfig.Env = env;
queueConfig.Length = 1000;
QueueDatabase queueDB = QueueDatabase.Open(
queueDBName, queueConfig, txn);
int i = 1;
DatabaseEntry data;
DatabaseEntry getData = new DatabaseEntry();
while (i <= 10)
{
data = new DatabaseEntry(
ASCIIEncoding.ASCII.GetBytes(i.ToString()));
queueDB.Append(data, txn);
if (i == 5)
{
getData = data;
}
i++;
}
KeyValuePair<uint, DatabaseEntry> pair = queueDB.Consume(false, txn);
queueDB.Close();
txn.Commit();
env.Close();
Database db = Database.Open(queueDBFileName,
new QueueDatabaseConfig());
try
{
DatabaseEntry key =
new DatabaseEntry(BitConverter.GetBytes(pair.Key));
db.Get(key);
}
catch (NotFoundException)
{
throw new ExpectedTestException();
}
finally
{
db.Close();
}
}
[Test, ExpectedException(typeof(ExpectedTestException))]
public void TestConsumeWithoutTxn()
{
testName = "TestConsumeWithoutTxn";
SetUpTest(true);
string queueDBFileName = testHome + "/" +
testName + ".db";
QueueDatabaseConfig queueConfig =
new QueueDatabaseConfig();
queueConfig.Creation = CreatePolicy.ALWAYS;
queueConfig.ErrorPrefix = testName;
queueConfig.Length = 1000;
QueueDatabase queueDB = QueueDatabase.Open(
queueDBFileName, queueConfig);
DatabaseEntry data = new DatabaseEntry(
ASCIIEncoding.ASCII.GetBytes("data"));
queueDB.Append(data);
DatabaseEntry consumeData = new DatabaseEntry();
KeyValuePair<uint, DatabaseEntry> pair = queueDB.Consume(false);
try
{
DatabaseEntry key =
new DatabaseEntry(BitConverter.GetBytes(pair.Key));
queueDB.Get(key);
}
catch (NotFoundException)
{
throw new ExpectedTestException();
}
finally
{
queueDB.Close();
}
}
public void TestCursor()
{
testName = "TestCursor";
SetUpTest(true);
GetCursur(testHome + "/" + testName + ".db", false);
}
public void TestCursorWithConfig()
{
testName = "TestCursorWithConfig";
SetUpTest(true);
GetCursur(testHome + "/" + testName + ".db", true);
}
public void GetCursur(string dbFileName, bool ifConfig)
{
QueueDatabaseConfig dbConfig = new QueueDatabaseConfig();
dbConfig.Creation = CreatePolicy.IF_NEEDED;
dbConfig.Length = 100;
QueueDatabase db = QueueDatabase.Open(dbFileName, dbConfig);
Cursor cursor;
CursorConfig cursorConfig = new CursorConfig();
cursorConfig.Priority = CachePriority.HIGH;
if (ifConfig == false)
cursor = db.Cursor();
else
cursor = db.Cursor(cursorConfig);
cursor.Add(new KeyValuePair<DatabaseEntry,DatabaseEntry>(
new DatabaseEntry(BitConverter.GetBytes((int)1)),
new DatabaseEntry(BitConverter.GetBytes((int)1))));
Cursor dupCursor = cursor.Duplicate(false);
Assert.IsNull(dupCursor.Current.Key);
Assert.AreEqual(CachePriority.HIGH, dupCursor.Priority);
dupCursor.Close();
cursor.Close();
db.Close();
}
[Test]
public void TestDeleteMultiple()
{
testName = "TestDeleteMultiple";
SetUpTest(true);
QueueDatabaseConfig dbConfig = new QueueDatabaseConfig();
dbConfig.Creation = CreatePolicy.IF_NEEDED;
dbConfig.ExtentSize = 1024;
dbConfig.Length = 270;
QueueDatabase db = QueueDatabase.Open(testHome + "/" +
testName + ".db", dbConfig);
List<uint> rList = new List<uint>();
List<DatabaseEntry> kList = new List<DatabaseEntry>();
List<DatabaseEntry> vList = new List<DatabaseEntry>();
DatabaseEntry key, data;
for (uint i = 1; i <= 100; i++) {
key = new DatabaseEntry(BitConverter.GetBytes(i));
data = new DatabaseEntry(
ASCIIEncoding.ASCII.GetBytes(
"data" + i.ToString() +
Configuration.RandomString(256)));
rList.Add(i);
kList.Add(key);
vList.Add(data);
db.Put(key, data);
}
// Bulk delete all records with recno in rList.
db.Delete(new MultipleDatabaseEntry(rList));
Cursor cursor = db.Cursor();
Assert.IsFalse(cursor.MoveFirst());
/*
* Bulk insert records whose key bulk buffer is
* constructed by recno lists, then delete all.
*/
db.Put(new MultipleDatabaseEntry(rList),
new MultipleDatabaseEntry(vList, false));
Assert.IsTrue(cursor.MoveFirst());
db.Delete(new MultipleDatabaseEntry(kList, true));
Assert.IsFalse(cursor.MoveFirst());
/*
* Bulk insert records whose key bulk buffer is
* constructed by DatabaseEntry lists, then delete all.
*/
db.Put(new MultipleDatabaseEntry(kList, true),
new MultipleDatabaseEntry(vList, false));
Assert.IsTrue(cursor.MoveFirst());
db.Delete(new MultipleDatabaseEntry(kList, true));
Assert.IsFalse(cursor.MoveFirst());
cursor.Close();
db.Close();
}
[Test]
public void TestDeleteMultipleKey()
{
testName = "TestDeleteMultipleKey";
SetUpTest(true);
QueueDatabaseConfig dbConfig = new QueueDatabaseConfig();
dbConfig.Creation = CreatePolicy.IF_NEEDED;
dbConfig.ExtentSize = 1024;
dbConfig.Length = 520;
QueueDatabase db = QueueDatabase.Open(testHome + "/" +
testName + ".db", dbConfig);
List<KeyValuePair<DatabaseEntry, DatabaseEntry>> pList =
new List<KeyValuePair<DatabaseEntry, DatabaseEntry>>();
DatabaseEntry key, data;
for (uint i = 1; i <= 100; i++)
{
key = new DatabaseEntry(
BitConverter.GetBytes(i));
data = new DatabaseEntry(
ASCIIEncoding.ASCII.GetBytes(
"data" + i.ToString() +
Configuration.RandomString(512)));
pList.Add(new KeyValuePair<
DatabaseEntry, DatabaseEntry>(key, data));
db.Put(key, data);
}
// Create key/value pair bulk buffer and delete all.
db.Delete(new MultipleKeyDatabaseEntry(pList, true));
// Verify that the database is empty.
Assert.AreEqual(0, db.Truncate());
db.Close();
}
[Test, ExpectedException(typeof(ExpectedTestException))]
public void TestKeyEmptyException()
{
testName = "TestKeyEmptyException";
SetUpTest(true);
DatabaseEnvironmentConfig envConfig =
new DatabaseEnvironmentConfig();
envConfig.Create = true;
envConfig.UseLocking = true;
envConfig.UseLogging = true;
envConfig.UseMPool = true;
envConfig.UseTxns = true;
DatabaseEnvironment env = DatabaseEnvironment.Open(
testHome, envConfig);
QueueDatabase db;
try
{
Transaction openTxn = env.BeginTransaction();
try
{
QueueDatabaseConfig queueConfig =
new QueueDatabaseConfig();
queueConfig.Creation = CreatePolicy.IF_NEEDED;
queueConfig.Length = 10;
queueConfig.Env = env;
db = QueueDatabase.Open(testName + ".db",
queueConfig, openTxn);
openTxn.Commit();
}
catch (DatabaseException e)
{
openTxn.Abort();
throw e;
}
Transaction cursorTxn = env.BeginTransaction();
Cursor cursor;
try
{
/*
* Put a record into queue database with
* cursor and abort the operation.
*/
cursor = db.Cursor(cursorTxn);
KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
pair = new KeyValuePair<DatabaseEntry, DatabaseEntry>(
new DatabaseEntry(BitConverter.GetBytes((int)10)),
new DatabaseEntry(ASCIIEncoding.ASCII.GetBytes("data")));
cursor.Add(pair);
cursor.Close();
cursorTxn.Abort();
}
catch (DatabaseException e)
{
cursorTxn.Abort();
db.Close();
throw e;
}
Transaction delTxn = env.BeginTransaction();
try
{
/*
* The put operation is aborted in the queue
* database so querying if the record still exists
* throws KeyEmptyException.
*/
db.Exists(new DatabaseEntry(
BitConverter.GetBytes((int)10)), delTxn);
delTxn.Commit();
}
catch (DatabaseException e)
{
delTxn.Abort();
throw e;
}
finally
{
db.Close();
}
}
catch (KeyEmptyException)
{
throw new ExpectedTestException();
}
finally
{
env.Close();
}
}
[Test]
public void TestOpenExistingQueueDB()
{
testName = "TestOpenExistingQueueDB";
SetUpTest(true);
string queueDBFileName = testHome + "/" + testName + ".db";
QueueDatabaseConfig queueConfig = new QueueDatabaseConfig();
queueConfig.Creation = CreatePolicy.ALWAYS;
QueueDatabase queueDB = QueueDatabase.Open(
queueDBFileName, queueConfig);
queueDB.Close();
DatabaseConfig dbConfig = new DatabaseConfig();
Database db = Database.Open(queueDBFileName, dbConfig);
Assert.AreEqual(db.Type, DatabaseType.QUEUE);
db.Close();
}
[Test]
public void TestOpenNewQueueDB()
{
testName = "TestOpenNewQueueDB";
SetUpTest(true);
string queueDBFileName = testHome + "/" + testName + ".db";
// Configure all fields/properties in queue database.
XmlElement xmlElem = Configuration.TestSetUp(
testFixtureName, testName);
QueueDatabaseConfig queueConfig = new QueueDatabaseConfig();
QueueDatabaseConfigTest.Config(xmlElem, ref queueConfig, true);
queueConfig.Feedback = new DatabaseFeedbackDelegate(DbFeedback);
// Open the queue database with above configuration.
QueueDatabase queueDB = QueueDatabase.Open(
queueDBFileName, queueConfig);
// Check the fields/properties in opened queue database.
Confirm(xmlElem, queueDB, true);
queueDB.Close();
}
private void DbFeedback(DatabaseFeedbackEvent opcode, int percent)
{
if (opcode == DatabaseFeedbackEvent.UPGRADE)
Console.WriteLine("Update for %d%", percent);
if (opcode == DatabaseFeedbackEvent.VERIFY)
Console.WriteLine("Vertify for %d", percent);
}
[Test, ExpectedException(typeof(NotFoundException))]
public void TestPutToQueue()
{
KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
testName = "TestPutQueue";
SetUpTest(true);
string queueDBFileName = testHome + "/" +
testName + ".db";
QueueDatabaseConfig queueConfig =
new QueueDatabaseConfig();
queueConfig.Length = 512;
queueConfig.Creation = CreatePolicy.ALWAYS;
using (QueueDatabase queueDB = QueueDatabase.Open(
queueDBFileName, queueConfig))
{
DatabaseEntry key = new DatabaseEntry();
key.Data = BitConverter.GetBytes((int)100);
DatabaseEntry data = new DatabaseEntry(
BitConverter.GetBytes((int)1));
queueDB.Put(key, data);
pair = queueDB.GetBoth(key, data);
}
}
[Test]
public void TestPutMultiple()
{
testName = "TestPutMultiple";
SetUpTest(true);
QueueDatabaseConfig dbConfig = new QueueDatabaseConfig();
dbConfig.Creation = CreatePolicy.IF_NEEDED;
dbConfig.ExtentSize = 1024;
dbConfig.Length = 520;
dbConfig.PadByte = 0;
QueueDatabase db = QueueDatabase.Open(testHome + "/" +
testName + ".db", dbConfig);
List<uint> kList = new List<uint>();
List<DatabaseEntry> vList = new List<DatabaseEntry>();
DatabaseEntry key, data;
for (uint i = 1; i <= 9;i++) {
key = new DatabaseEntry(BitConverter.GetBytes(i));
data = new DatabaseEntry(
ASCIIEncoding.ASCII.GetBytes("data" + i +
Configuration.RandomString(512)));
kList.Add(i);
vList.Add(data);
}
// Create bulk buffer for recno based keys.
MultipleDatabaseEntry kBuff =
new MultipleDatabaseEntry(kList);
Assert.IsTrue(kBuff.Recno);
int val = 0;
foreach (DatabaseEntry dbt in kBuff) {
Assert.AreEqual(
BitConverter.GetBytes(kList[val]),
dbt.Data);
val++;
}
Assert.AreEqual(9, val);
// Create bulk buffer for data.
MultipleDatabaseEntry vBuff =
new MultipleDatabaseEntry(vList, false);
/*
* Create recno bulk buffer from another recno bulk
* buffer.
*/
MultipleDatabaseEntry kBuff1 =
new MultipleDatabaseEntry(kBuff.Data, kBuff.Recno);
val = 0;
foreach (DatabaseEntry dbt in kBuff1) {
Assert.AreEqual(
BitConverter.GetBytes(kList[val]),
dbt.Data);
val++;
}
Assert.AreEqual(9, val);
// Bulk insert to database with key and value buffers.
db.Put(kBuff, vBuff);
Cursor cursor = db.Cursor();
KeyValuePair<DatabaseEntry, DatabaseEntry> pair;
val = 0;
while (cursor.MoveNext()) {
pair = cursor.Current;
Assert.AreEqual(
BitConverter.GetBytes(kList[val]),
pair.Key.Data);
for (int i = 0; i < 520; i++) {
if (i < vList[val].Data.Length)
Assert.AreEqual(vList[val].Data[i],
pair.Value.Data[i]);
else
// The pad byte is 0.
Assert.AreEqual(0, pair.Value.Data[i]);
}
Assert.IsFalse(cursor.MoveNextDuplicate());
val++;
}
Assert.AreEqual(9, val);
cursor.Close();
db.Close();
}
[Test]
public void TestStats()
{
testName = "TestStats";
SetUpTest(true);
string dbFileName = testHome + "/" +
testName + ".db";
QueueDatabaseConfig dbConfig =
new QueueDatabaseConfig();
ConfigCase1(dbConfig);
QueueDatabase db = QueueDatabase.Open(dbFileName, dbConfig);
QueueStats stats = db.Stats();
ConfirmStatsPart1Case1(stats);
db.PrintFastStats(true);
// Put 500 records into the database.
PutRecordCase1(db, null);
stats = db.Stats();
ConfirmStatsPart2Case1(stats);
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);
}
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();
QueueDatabaseConfig dbConfig =
new QueueDatabaseConfig();
ConfigCase1(dbConfig);
dbConfig.Env = env;
QueueDatabase db = QueueDatabase.Open(name + ".db",
dbConfig, openTxn);
openTxn.Commit();
Transaction statsTxn = env.BeginTransaction();
QueueStats stats;
if (ifIsolation == false)
stats = db.Stats(statsTxn);
else
stats = db.Stats(statsTxn, Isolation.DEGREE_ONE);
ConfirmStatsPart1Case1(stats);
db.PrintStats(true);
// 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);
db.PrintStats();
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(QueueDatabaseConfig dbConfig)
{
dbConfig.Creation = CreatePolicy.IF_NEEDED;
dbConfig.PageSize = 4096;
dbConfig.ExtentSize = 1024;
dbConfig.Length = 4000;
dbConfig.PadByte = 32;
}
public void PutRecordCase1(QueueDatabase db, Transaction txn)
{
byte[] bigArray = new byte[4000];
for (int i = 1; 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);
}
DatabaseEntry key = new DatabaseEntry(BitConverter.GetBytes((int)100));
for (int i = 100; i <= 500; i++)
{
if (txn == null)
db.Put(key, new DatabaseEntry(bigArray));
else
db.Put(key, new DatabaseEntry(bigArray), txn);
}
}
public void ConfirmStatsPart1Case1(QueueStats stats)
{
Assert.AreEqual(1, stats.FirstRecordNumber);
Assert.AreNotEqual(0, stats.MagicNumber);
Assert.AreEqual(1, stats.NextRecordNumber);
Assert.AreEqual(4096, stats.PageSize);
Assert.AreEqual(1024, stats.PagesPerExtent);
Assert.AreEqual(4000, stats.RecordLength);
Assert.AreEqual(32, stats.RecordPadByte);
Assert.AreEqual(4, stats.Version);
}
public void ConfirmStatsPart2Case1(QueueStats stats)
{
Assert.AreNotEqual(0, stats.DataPages);
Assert.AreEqual(0, stats.DataPagesBytesFree);
Assert.AreEqual(0, stats.MetadataFlags);
Assert.AreEqual(100, stats.nData);
Assert.AreEqual(100, stats.nKeys);
}
public static void Confirm(XmlElement xmlElem,
QueueDatabase queueDB, bool compulsory)
{
DatabaseTest.Confirm(xmlElem, queueDB, compulsory);
// Confirm queue database specific field/property
Configuration.ConfirmUint(xmlElem, "ExtentSize",
queueDB.ExtentSize, compulsory);
Configuration.ConfirmBool(xmlElem, "ConsumeInOrder",
queueDB.InOrder, compulsory);
Configuration.ConfirmInt(xmlElem, "PadByte",
queueDB.PadByte, compulsory);
Assert.AreEqual(DatabaseType.QUEUE, queueDB.Type);
string type = queueDB.Type.ToString();
Assert.IsNotNull(type);
}
}
}