1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 2009 Oracle. All rights reserved. 5 * 6 */ 7using System; 8using System.Collections; 9using System.Collections.Generic; 10using System.IO; 11using System.Text; 12using System.Threading; 13using System.Xml; 14using NUnit.Framework; 15using BerkeleyDB; 16 17namespace CsharpAPITest 18{ 19 [TestFixture] 20 public class SecondaryDatabaseTest 21 { 22 private string testFixtureHome; 23 private string testFixtureName; 24 private string testName; 25 private string testHome; 26 27 [TestFixtureSetUp] 28 public void RunBeforeTests() 29 { 30 testFixtureName = "SecondaryDatabaseTest"; 31 testFixtureHome = "./TestOut/" + testFixtureName; 32 33 Configuration.ClearDir(testFixtureHome); 34 } 35 36 [Test] 37 public void TestKeyGen() 38 { 39 testName = "TestKeyGen"; 40 testHome = testFixtureHome + "/" + testName; 41 string dbFileName = testHome + "/" + testName + ".db"; 42 43 Configuration.ClearDir(testHome); 44 45 // Open primary database. 46 BTreeDatabaseConfig primaryDBConfig = 47 new BTreeDatabaseConfig(); 48 primaryDBConfig.Creation = CreatePolicy.IF_NEEDED; 49 BTreeDatabase primaryDB = 50 BTreeDatabase.Open(dbFileName, primaryDBConfig); 51 52 // Open secondary database. 53 SecondaryBTreeDatabaseConfig secDBConfig = 54 new SecondaryBTreeDatabaseConfig(primaryDB, 55 new SecondaryKeyGenDelegate(SecondaryKeyGen)); 56 SecondaryBTreeDatabase secDB = 57 SecondaryBTreeDatabase.Open(dbFileName, 58 secDBConfig); 59 60 primaryDB.Put(new DatabaseEntry( 61 BitConverter.GetBytes((int)1)), 62 new DatabaseEntry(BitConverter.GetBytes((int)11))); 63 64 KeyValuePair<DatabaseEntry, DatabaseEntry> pair; 65 pair = secDB.Get(new DatabaseEntry( 66 BitConverter.GetBytes((int)11))); 67 Assert.IsNotNull(pair.Value); 68 69 // Close secondary database. 70 secDB.Close(); 71 72 // Close primary database. 73 primaryDB.Close(); 74 } 75 76 [Test] 77 public void TestSecondaryCursor() 78 { 79 testName = "TestSecondaryCursor"; 80 testHome = testFixtureHome + "/" + testName; 81 string dbFileName = testHome + "/" + testName + ".db"; 82 83 Configuration.ClearDir(testHome); 84 85 // Open primary database. 86 BTreeDatabaseConfig primaryDBConfig = 87 new BTreeDatabaseConfig(); 88 primaryDBConfig.Creation = CreatePolicy.IF_NEEDED; 89 BTreeDatabase primaryDB = 90 BTreeDatabase.Open(dbFileName, primaryDBConfig); 91 92 // Open secondary database. 93 SecondaryBTreeDatabaseConfig secDBConfig = 94 new SecondaryBTreeDatabaseConfig(primaryDB, 95 new SecondaryKeyGenDelegate(SecondaryKeyGen)); 96 SecondaryBTreeDatabase secDB = 97 SecondaryBTreeDatabase.Open(dbFileName, 98 secDBConfig); 99 100 primaryDB.Put(new DatabaseEntry( 101 BitConverter.GetBytes((int)1)), 102 new DatabaseEntry(BitConverter.GetBytes((int)11))); 103 104 105 SecondaryCursor cursor = secDB.SecondaryCursor(); 106 cursor.Move(new DatabaseEntry( 107 BitConverter.GetBytes((int)11)), true); 108 Assert.AreEqual(BitConverter.GetBytes((int)11), 109 cursor.Current.Key.Data); 110 111 // Close the cursor. 112 cursor.Close(); 113 114 // Close secondary database. 115 secDB.Close(); 116 117 // Close primary database. 118 primaryDB.Close(); 119 } 120 121 [Test] 122 public void TestSecondaryCursorWithConfig() 123 { 124 testName = "TestSecondaryCursorWithConfig"; 125 testHome = testFixtureHome + "/" + testName; 126 string dbFileName = testHome + "/" + testName + ".db"; 127 128 Configuration.ClearDir(testHome); 129 130 BTreeDatabase db; 131 SecondaryBTreeDatabase secDB; 132 OpenPrimaryAndSecondaryDB(dbFileName, out db, out secDB); 133 134 for (int i = 0; i < 10; i++) 135 db.Put(new DatabaseEntry(BitConverter.GetBytes(i)), 136 new DatabaseEntry(BitConverter.GetBytes((int)i))); 137 138 CursorConfig cursorConfig = new CursorConfig(); 139 cursorConfig.WriteCursor = false; 140 SecondaryCursor cursor = 141 secDB.SecondaryCursor(cursorConfig); 142 143 cursor.Move(new DatabaseEntry( 144 BitConverter.GetBytes((int)5)), true); 145 146 Assert.AreEqual(1, cursor.Count()); 147 148 // Close the cursor. 149 cursor.Close(); 150 151 // Close secondary database. 152 secDB.Close(); 153 154 // Close primary database. 155 db.Close(); 156 } 157 158 [Test] 159 public void TestSecondaryCursorWithTxn() 160 { 161 testName = "TestSecondaryCursorWithTxn"; 162 testHome = testFixtureHome + "/" + testName; 163 string dbFileName = testHome + "/" + testName + ".db"; 164 165 Configuration.ClearDir(testHome); 166 167 GetSecondaryCursurWithTxn(testHome, testName, false); 168 } 169 170 [Test] 171 public void TestSecondaryCursorWithConfigAndTxn() 172 { 173 testName = "TestSecondaryCursorWithConfigAndTxn"; 174 testHome = testFixtureHome + "/" + testName; 175 string dbFileName = testHome + "/" + testName + ".db"; 176 177 Configuration.ClearDir(testHome); 178 GetSecondaryCursurWithTxn(testHome, testName, true); 179 } 180 181 public void GetSecondaryCursurWithTxn(string home, 182 string name, bool ifCfg) 183 { 184 string dbFileName = name + ".db"; 185 SecondaryCursor cursor; 186 187 // Open env. 188 DatabaseEnvironmentConfig envConfig = 189 new DatabaseEnvironmentConfig(); 190 envConfig.Create = true; 191 envConfig.UseTxns = true; 192 envConfig.UseMPool = true; 193 DatabaseEnvironment env = DatabaseEnvironment.Open(home, 194 envConfig); 195 196 197 // Open primary/secondary database. 198 Transaction txn = env.BeginTransaction(); 199 BTreeDatabaseConfig dbConfig = new BTreeDatabaseConfig(); 200 dbConfig.Creation = CreatePolicy.IF_NEEDED; 201 dbConfig.Env = env; 202 BTreeDatabase db = BTreeDatabase.Open(dbFileName, 203 dbConfig, txn); 204 205 SecondaryBTreeDatabaseConfig secDBConfig = new 206 SecondaryBTreeDatabaseConfig(db, 207 new SecondaryKeyGenDelegate(SecondaryKeyGen)); 208 secDBConfig.Env = env; 209 SecondaryBTreeDatabase secDB = 210 SecondaryBTreeDatabase.Open(dbFileName, 211 secDBConfig, txn); 212 213 for (int i = 0; i < 10; i++) 214 db.Put(new DatabaseEntry(BitConverter.GetBytes(i)), 215 new DatabaseEntry(BitConverter.GetBytes((int)i)), txn); 216 217 218 // Create secondary cursor. 219 if (ifCfg == false) 220 secDB.SecondaryCursor(txn); 221 else if (ifCfg == true) 222 { 223 CursorConfig cursorConfig = new CursorConfig(); 224 cursorConfig.WriteCursor = false; 225 cursor = secDB.SecondaryCursor(cursorConfig, txn); 226 cursor.Close(); 227 } 228 229 secDB.Close(); 230 db.Close(); 231 txn.Commit(); 232 env.Close(); 233 } 234 235 [Test] 236 public void TestOpen() 237 { 238 testName = "TestOpen"; 239 testHome = testFixtureHome + "/" + testName; 240 string dbFileName = testHome + "/" + testName + ".db"; 241 string dbSecFileName = testHome + "/" + 242 testName + "_sec.db"; 243 244 Configuration.ClearDir(testHome); 245 246 OpenSecQueueDB(dbFileName, dbSecFileName, false); 247 } 248 249 [Test] 250 public void TestOpenWithDBName() 251 { 252 testName = "TestOpenWithDBName"; 253 testHome = testFixtureHome + "/" + testName; 254 string dbFileName = testHome + "/" + testName + ".db"; 255 string dbSecFileName = testHome + "/" + 256 testName + "_sec.db"; 257 258 Configuration.ClearDir(testHome); 259 OpenSecQueueDB(dbFileName, dbSecFileName, true); 260 } 261 262 public void OpenSecQueueDB(string dbFileName, 263 string dbSecFileName, bool ifDBName) 264 { 265 // Open a primary btree database. 266 BTreeDatabaseConfig primaryDBConfig = 267 new BTreeDatabaseConfig(); 268 primaryDBConfig.Creation = CreatePolicy.IF_NEEDED; 269 BTreeDatabase primaryDB; 270 271 /* 272 * If secondary database name is given, the primary 273 * database is also opened with database name. 274 */ 275 if (ifDBName == false) 276 primaryDB = BTreeDatabase.Open(dbFileName, 277 primaryDBConfig); 278 else 279 primaryDB = BTreeDatabase.Open(dbFileName, 280 "primary", primaryDBConfig); 281 282 try 283 { 284 // Open a new secondary database. 285 SecondaryBTreeDatabaseConfig secBTDBConfig = 286 new SecondaryBTreeDatabaseConfig( 287 primaryDB, null); 288 secBTDBConfig.Creation = 289 CreatePolicy.IF_NEEDED; 290 291 SecondaryBTreeDatabase secBTDB; 292 if (ifDBName == false) 293 secBTDB = SecondaryBTreeDatabase.Open( 294 dbSecFileName, secBTDBConfig); 295 else 296 secBTDB = SecondaryBTreeDatabase.Open( 297 dbSecFileName, "secondary", 298 secBTDBConfig); 299 300 // Close the secondary database. 301 secBTDB.Close(); 302 303 // Open the existing secondary database. 304 SecondaryDatabaseConfig secDBConfig = 305 new SecondaryDatabaseConfig( 306 primaryDB, null); 307 308 SecondaryDatabase secDB; 309 if (ifDBName == false) 310 secDB = SecondaryBTreeDatabase.Open( 311 dbSecFileName, secDBConfig); 312 else 313 secDB = SecondaryBTreeDatabase.Open( 314 dbSecFileName, "secondary", secDBConfig); 315 316 // Close secondary database. 317 secDB.Close(); 318 } 319 catch (DatabaseException) 320 { 321 throw new TestException(); 322 } 323 finally 324 { 325 // Close primary database. 326 primaryDB.Close(); 327 } 328 } 329 330 [Test] 331 public void TestOpenWithinTxn() 332 { 333 testName = "TestOpenWithinTxn"; 334 testHome = testFixtureHome + "/" + testName; 335 string dbFileName = testName + ".db"; 336 string dbSecFileName = testName + "_sec.db"; 337 338 Configuration.ClearDir(testHome); 339 340 OpenSecQueueDBWithinTxn(testHome, dbFileName, 341 dbSecFileName, false); 342 } 343 344 [Test] 345 public void TestOpenDBNameWithinTxn() 346 { 347 testName = "TestOpenDBNameWithinTxn"; 348 testHome = testFixtureHome + "/" + testName; 349 string dbFileName = testName + ".db"; 350 string dbSecFileName = testName + "_sec.db"; 351 352 Configuration.ClearDir(testHome); 353 354 OpenSecQueueDBWithinTxn(testHome, dbFileName, 355 dbSecFileName, true); 356 } 357 358 public void OpenSecQueueDBWithinTxn(string home, 359 string dbFileName, string dbSecFileName, bool ifDbName) 360 { 361 // Open an environment. 362 DatabaseEnvironmentConfig envConfig = 363 new DatabaseEnvironmentConfig(); 364 envConfig.Create = true; 365 envConfig.UseTxns = true; 366 envConfig.UseMPool = true; 367 envConfig.UseLogging = true; 368 DatabaseEnvironment env = DatabaseEnvironment.Open( 369 home, envConfig); 370 371 // Open a primary btree database. 372 Transaction openDBTxn = env.BeginTransaction(); 373 BTreeDatabaseConfig dbConfig = 374 new BTreeDatabaseConfig(); 375 dbConfig.Creation = CreatePolicy.IF_NEEDED; 376 dbConfig.Env = env; 377 BTreeDatabase db = BTreeDatabase.Open( 378 dbFileName, dbConfig, openDBTxn); 379 openDBTxn.Commit(); 380 381 // Open a secondary btree database. 382 Transaction openSecTxn = env.BeginTransaction(); 383 SecondaryBTreeDatabaseConfig secDBConfig = 384 new SecondaryBTreeDatabaseConfig(db, 385 new SecondaryKeyGenDelegate(SecondaryKeyGen)); 386 secDBConfig.Env = env; 387 secDBConfig.Creation = CreatePolicy.IF_NEEDED; 388 389 SecondaryBTreeDatabase secDB; 390 if (ifDbName == false) 391 secDB = SecondaryBTreeDatabase.Open( 392 dbSecFileName, secDBConfig, openSecTxn); 393 else 394 secDB = SecondaryBTreeDatabase.Open( 395 dbSecFileName, "secondary", secDBConfig, 396 openSecTxn); 397 openSecTxn.Commit(); 398 secDB.Close(); 399 400 // Open the existing secondary database. 401 Transaction secTxn = env.BeginTransaction(); 402 SecondaryDatabaseConfig secConfig = 403 new SecondaryDatabaseConfig(db, 404 new SecondaryKeyGenDelegate(SecondaryKeyGen)); 405 secConfig.Env = env; 406 407 SecondaryDatabase secExDB; 408 if (ifDbName == false) 409 secExDB = SecondaryBTreeDatabase.Open( 410 dbSecFileName, secConfig, secTxn); 411 else 412 secExDB = SecondaryBTreeDatabase.Open( 413 dbSecFileName, "secondary", secConfig, 414 secTxn); 415 secExDB.Close(); 416 secTxn.Commit(); 417 418 db.Close(); 419 env.Close(); 420 } 421 422 public void OpenPrimaryAndSecondaryDB(string dbFileName, 423 out BTreeDatabase primaryDB, 424 out SecondaryBTreeDatabase secDB) 425 { 426 // Open primary database. 427 BTreeDatabaseConfig primaryDBConfig = 428 new BTreeDatabaseConfig(); 429 primaryDBConfig.Creation = CreatePolicy.IF_NEEDED; 430 primaryDB = 431 BTreeDatabase.Open(dbFileName, primaryDBConfig); 432 433 // Open secondary database. 434 SecondaryBTreeDatabaseConfig secDBConfig = 435 new SecondaryBTreeDatabaseConfig(primaryDB, 436 new SecondaryKeyGenDelegate(SecondaryKeyGen)); 437 secDB = SecondaryBTreeDatabase.Open(dbFileName, 438 secDBConfig); 439 } 440 441 [Test, ExpectedException(typeof(ExpectedTestException))] 442 public void TestBadSecondaryException() 443 { 444 testName = "TestBadSecondaryException"; 445 testHome = testFixtureHome + "/" + testName; 446 string dbFileName = testHome + "/" + testName + ".db"; 447 string secDBFileName = testHome + "/" + 448 testName + "_sec.db"; 449 450 Configuration.ClearDir(testHome); 451 452 // Open primary database. 453 BTreeDatabaseConfig btreeDBConfig = 454 new BTreeDatabaseConfig(); 455 btreeDBConfig.Creation = CreatePolicy.IF_NEEDED; 456 BTreeDatabase btreeDB = 457 BTreeDatabase.Open(dbFileName, btreeDBConfig); 458 459 // Open secondary database. 460 SecondaryBTreeDatabaseConfig secBtDbConfig = 461 new SecondaryBTreeDatabaseConfig(btreeDB, 462 new SecondaryKeyGenDelegate(SecondaryKeyGen)); 463 secBtDbConfig.Creation = CreatePolicy.IF_NEEDED; 464 SecondaryBTreeDatabase secBtDb = 465 SecondaryBTreeDatabase.Open(secDBFileName, 466 secBtDbConfig); 467 468 // Put some data into primary database. 469 for (int i = 0; i < 10; i++) 470 btreeDB.Put(new DatabaseEntry( 471 BitConverter.GetBytes(i)), 472 new DatabaseEntry(BitConverter.GetBytes(i))); 473 474 // Close the secondary database. 475 secBtDb.Close(); 476 477 // Delete record(5, 5) in primary database. 478 btreeDB.Delete(new DatabaseEntry( 479 BitConverter.GetBytes((int)5))); 480 481 // Reopen the secondary database. 482 SecondaryDatabase secDB = SecondaryDatabase.Open( 483 secDBFileName, 484 new SecondaryDatabaseConfig(btreeDB, 485 new SecondaryKeyGenDelegate(SecondaryKeyGen))); 486 487 /* 488 * Getting record(5, 5) by secondary database should 489 * throw BadSecondaryException since it has been 490 * deleted in the primary database. 491 */ 492 try 493 { 494 secDB.Exists(new DatabaseEntry( 495 BitConverter.GetBytes((int)5))); 496 } 497 catch (BadSecondaryException) 498 { 499 throw new ExpectedTestException(); 500 } 501 finally 502 { 503 secDB.Close(); 504 btreeDB.Close(); 505 } 506 } 507 508 public DatabaseEntry SecondaryKeyGen( 509 DatabaseEntry key, DatabaseEntry data) 510 { 511 DatabaseEntry dbtGen; 512 dbtGen = new DatabaseEntry(data.Data); 513 return dbtGen; 514 } 515 516 } 517 518}