/*- * See the file LICENSE for redistribution information. * * Copyright (c) 2009, 2015 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 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 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( 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 rList = new List(); List kList = new List(); List vList = new List(); 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> pList = new List>(); 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 pair; pair = new KeyValuePair( 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 TestMessageFile() { testName = "TestMessageFile"; SetUpTest(true); // Configure and open an environment. DatabaseEnvironmentConfig envConfig = new DatabaseEnvironmentConfig(); envConfig.Create = true; envConfig.UseMPool = true; DatabaseEnvironment env = DatabaseEnvironment.Open( testHome, envConfig); // Configure and open a database. QueueDatabaseConfig DBConfig = new QueueDatabaseConfig(); DBConfig.Env = env; DBConfig.Creation = CreatePolicy.IF_NEEDED; string DBFileName = testName + ".db"; QueueDatabase db = QueueDatabase.Open( DBFileName, DBConfig); // Confirm message file does not exist. string messageFile = testHome + "/" + "msgfile"; Assert.AreEqual(false, File.Exists(messageFile)); // Call set_msgfile() of db. db.Msgfile = messageFile; // Print db statistic to message file. db.PrintStats(true); // Confirm message file exists now. Assert.AreEqual(true, File.Exists(messageFile)); db.Msgfile = ""; string line = null; // Read the third line of message file. System.IO.StreamReader file = new System.IO.StreamReader(@"" + messageFile); line = file.ReadLine(); line = file.ReadLine(); line = file.ReadLine(); // Confirm the message file is not empty. Assert.AreEqual(line, "DB handle information:"); file.Close(); // Close database and environment. db.Close(); 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 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 kList = new List(); List vList = new List(); 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 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.Msgfile = testHome + "/" + testName+ ".log"; 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.Msgfile = home + "/" + name+ ".log"; 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); } } }