1 8 9 package com.sleepycat.je.dbi; 10 11 import java.io.File ; 12 import java.io.IOException ; 13 import java.util.Comparator ; 14 import java.util.Enumeration ; 15 import java.util.Hashtable ; 16 import java.util.Random ; 17 18 import junit.framework.TestCase; 19 20 import com.sleepycat.je.Cursor; 21 import com.sleepycat.je.Database; 22 import com.sleepycat.je.DatabaseConfig; 23 import com.sleepycat.je.DatabaseException; 24 import com.sleepycat.je.DbInternal; 25 import com.sleepycat.je.DbTestProxy; 26 import com.sleepycat.je.Environment; 27 import com.sleepycat.je.EnvironmentConfig; 28 import com.sleepycat.je.LockMode; 29 import com.sleepycat.je.LockStats; 30 import com.sleepycat.je.OperationStatus; 31 import com.sleepycat.je.VerifyConfig; 32 import com.sleepycat.je.config.EnvironmentParams; 33 import com.sleepycat.je.tree.BIN; 34 import com.sleepycat.je.tree.DuplicateEntryException; 35 import com.sleepycat.je.tree.Node; 36 import com.sleepycat.je.tree.Tree; 37 import com.sleepycat.je.util.StringDbt; 38 import com.sleepycat.je.util.TestUtils; 39 40 43 public class DbCursorTestBase extends TestCase { 44 protected File envHome; 45 protected Cursor cursor; 46 protected Cursor cursor2; 47 protected Database exampleDb; 48 protected Environment exampleEnv; 49 protected Hashtable simpleDataMap; 50 protected Comparator btreeComparisonFunction = null; 51 protected Comparator duplicateComparisonFunction = null; 52 protected StringDbt[] simpleKeys; 53 protected StringDbt[] simpleData; 54 protected boolean duplicatesAllowed; 55 56 protected static final int N_KEY_BYTES = 10; 57 protected static final int N_ITERS = 2; 58 protected static final int N_KEYS = 5000; 59 protected static final int N_TOP_LEVEL_KEYS = 10; 60 protected static final int N_DUPLICATES_PER_KEY = 2500; 61 protected static final int N_COUNT_DUPLICATES_PER_KEY = 500; 62 protected static final int N_COUNT_TOP_KEYS = 1; 63 64 protected static int dbCnt = 0; 65 66 public DbCursorTestBase() 67 throws DatabaseException { 68 69 envHome = new File (System.getProperty(TestUtils.DEST_DIR)); 70 } 71 72 public void setUp() 73 throws IOException , DatabaseException { 74 75 TestUtils.removeLogFiles("Setup", envHome, false); 76 } 77 78 protected void initEnv(boolean duplicatesAllowed) 79 throws DatabaseException { 80 81 initEnvInternal(duplicatesAllowed, false); 82 } 83 84 protected void initEnvTransactional(boolean duplicatesAllowed) 85 throws DatabaseException { 86 87 initEnvInternal(duplicatesAllowed, true); 88 } 89 90 private void initEnvInternal(boolean duplicatesAllowed, 91 boolean transactionalDatabase) 92 throws DatabaseException { 93 94 this.duplicatesAllowed = duplicatesAllowed; 95 96 int nKeys = simpleKeyStrings.length; 98 simpleKeys = new StringDbt[nKeys]; 99 simpleData = new StringDbt[nKeys]; 100 for (int i = 0; i < nKeys; i++) { 101 simpleKeys[i] = new StringDbt(simpleKeyStrings[i]); 102 simpleData[i] = new StringDbt(simpleDataStrings[i]); 103 } 104 105 EnvironmentConfig envConfig = TestUtils.initEnvConfig(); 107 envConfig.setTxnNoSync(Boolean.getBoolean(TestUtils.NO_SYNC)); 108 envConfig.setTransactional(true); 109 envConfig.setConfigParam(EnvironmentParams.NODE_MAX.getName(), "6"); 110 envConfig.setConfigParam(EnvironmentParams.MAX_MEMORY.getName(), 111 new Long (1 << 24).toString()); 112 envConfig.setAllowCreate(true); 113 exampleEnv = new Environment(envHome, envConfig); 114 115 String databaseName = "simpleDb" + dbCnt++; 117 DatabaseConfig dbConfig = new DatabaseConfig(); 118 if (btreeComparisonFunction != null) { 119 dbConfig.setBtreeComparator(btreeComparisonFunction.getClass()); 120 } 121 if (duplicateComparisonFunction != null) { 122 dbConfig.setDuplicateComparator 123 (duplicateComparisonFunction.getClass()); 124 } 125 dbConfig.setAllowCreate(true); 126 dbConfig.setSortedDuplicates(duplicatesAllowed); 127 dbConfig.setTransactional(transactionalDatabase); 128 exampleDb = exampleEnv.openDatabase(null, databaseName, dbConfig); 129 130 cursor = exampleDb.openCursor(null, null); 132 cursor2 = exampleDb.openCursor(null, null); 133 simpleDataMap = new Hashtable (); 134 } 135 136 public void tearDown() 137 throws IOException , DatabaseException { 138 139 simpleKeys = null; 140 simpleData = null; 141 142 try { 143 if (cursor != null) { 144 cursor.close(); 145 cursor = null; 146 } 147 } catch (DatabaseException DBE) { 148 154 } 155 156 try { 157 if (cursor2 != null) { 158 cursor2.close(); 159 cursor2 = null; 160 } 161 } catch (DatabaseException DBE) { 162 163 } 164 165 if (exampleDb != null) { 166 try { 167 exampleDb.close(); 168 } catch (Throwable e) { 169 System.out.println("tearDown: " + e); 170 } 171 exampleDb = null; 172 } 173 if (exampleEnv != null) { 174 try { 175 exampleEnv.close(); 176 } catch (DatabaseException DE) { 177 183 } 184 exampleEnv = null; 185 } 186 187 simpleDataMap = null; 188 189 TestUtils.removeLogFiles("TearDown", envHome, false); 190 } 191 192 protected String [] simpleKeyStrings = { 193 "foo", "bar", "baz", "aaa", "fubar", 194 "foobar", "quux", "mumble", "froboy" }; 195 196 protected String [] simpleDataStrings = { 197 "one", "two", "three", "four", "five", 198 "six", "seven", "eight", "nine" }; 199 200 protected void doSimpleCursorPuts() 201 throws DatabaseException { 202 203 for (int i = 0; i < simpleKeyStrings.length; i++) { 204 putAndVerifyCursor(cursor, simpleKeys[i], simpleData[i], true); 205 simpleDataMap.put(simpleKeyStrings[i], simpleDataStrings[i]); 206 } 207 } 208 209 215 protected class DataWalker { 216 String prevKey = ""; 217 String prevData = ""; 218 int nEntries = 0; 219 int deletedEntries = 0; 220 int extraVisibleEntries = 0; 221 protected int nHandleEndOfSet = 0; 222 String whenFoundDoInsert; 223 String newKey; 224 String deletedEntry = null; 225 Hashtable dataMap; 226 Hashtable addedDataMap; 227 Random rnd = new Random (); 228 230 boolean ignoreDataMap = false; 231 232 DataWalker(Hashtable dataMap) { 233 this.dataMap = dataMap; 234 this.addedDataMap = null; 235 } 236 237 DataWalker(Hashtable dataMap, 238 Hashtable addedDataMap) { 239 this.dataMap = dataMap; 240 this.addedDataMap = addedDataMap; 241 } 242 243 DataWalker() { 244 this.dataMap = simpleDataMap; 245 this.addedDataMap = null; 246 } 247 248 DataWalker(String whenFoundDoInsert, 249 String newKey, 250 Hashtable dataMap) { 251 this.whenFoundDoInsert = whenFoundDoInsert; 252 this.newKey = newKey; 253 this.dataMap = dataMap; 254 this.addedDataMap = null; 255 } 256 257 void setIgnoreDataMap(boolean ignoreDataMap) { 258 this.ignoreDataMap = ignoreDataMap; 259 } 260 261 OperationStatus getFirst(StringDbt foundKey, StringDbt foundData) 262 throws DatabaseException { 263 264 return cursor.getFirst(foundKey, foundData, 265 LockMode.DEFAULT); 266 } 267 268 OperationStatus getData(StringDbt foundKey, StringDbt foundData) 269 throws DatabaseException { 270 271 return cursor.getNext(foundKey, foundData, 272 LockMode.DEFAULT); 273 } 274 275 StringDbt foundKey = new StringDbt(); 276 StringDbt foundData = new StringDbt(); 277 278 void walkData() 279 throws DatabaseException { 280 281 282 OperationStatus status = getFirst(foundKey, foundData); 283 284 while (status == OperationStatus.SUCCESS) { 285 String foundKeyString = foundKey.getString(); 286 String foundDataString = foundData.getString(); 287 288 if (!ignoreDataMap) { 289 if (dataMap.get(foundKeyString) != null) { 290 assertTrue(((String ) dataMap.get(foundKeyString)). 291 equals(foundDataString)); 292 } else if (addedDataMap != null && 293 addedDataMap.get(foundKeyString) != null) { 294 assertTrue(((String ) addedDataMap.get(foundKeyString)). 295 equals(foundDataString)); 296 } else { 297 fail("didn't find key in either map (" + 298 foundKeyString + 299 ")"); 300 } 301 } 302 303 LockStats stat = 304 DbTestProxy.dbcGetCursorImpl(cursor).getLockStats(); 305 assertEquals(1, stat.getNReadLocks()); 306 assertEquals(0, stat.getNWriteLocks()); 307 perData(foundKeyString, foundDataString); 308 nEntries++; 309 status = getData(foundKey, foundData); 310 if (status != OperationStatus.SUCCESS) { 311 nHandleEndOfSet++; 312 status = handleEndOfSet(status); 313 } 314 } 315 TestUtils.validateNodeMemUsage(DbInternal. 316 envGetEnvironmentImpl(exampleEnv), 317 false); 318 } 319 320 void perData(String foundKey, String foundData) 321 throws DatabaseException { 322 323 324 } 325 326 OperationStatus handleEndOfSet(OperationStatus status) 327 throws DatabaseException { 328 329 return status; 330 } 331 332 void close() 333 throws DatabaseException { 334 335 cursor.close(); 336 } 337 } 338 339 protected class BackwardsDataWalker extends DataWalker { 340 BackwardsDataWalker(Hashtable dataMap) { 341 super(dataMap); 342 } 343 344 BackwardsDataWalker(Hashtable dataMap, 345 Hashtable addedDataMap) { 346 super(dataMap, addedDataMap); 347 } 348 349 BackwardsDataWalker(String whenFoundDoInsert, 350 String newKey, 351 Hashtable dataMap) { 352 super(whenFoundDoInsert, newKey, dataMap); 353 } 354 355 OperationStatus getFirst(StringDbt foundKey, StringDbt foundData) 356 throws DatabaseException { 357 358 return cursor.getLast(foundKey, foundData, 359 LockMode.DEFAULT); 360 } 361 362 OperationStatus getData(StringDbt foundKey, StringDbt foundData) 363 throws DatabaseException { 364 365 return cursor.getPrev(foundKey, foundData, 366 LockMode.DEFAULT); 367 } 368 } 369 370 protected class DupDataWalker extends DataWalker { 371 DupDataWalker(Hashtable dataMap) { 372 super(dataMap); 373 } 374 375 DupDataWalker(Hashtable dataMap, 376 Hashtable addedDataMap) { 377 super(dataMap, addedDataMap); 378 } 379 380 DupDataWalker(String whenFoundDoInsert, 381 String newKey, 382 Hashtable dataMap) { 383 super(whenFoundDoInsert, newKey, dataMap); 384 } 385 386 OperationStatus getData(StringDbt foundKey, StringDbt foundData) 387 throws DatabaseException { 388 389 return cursor.getNextDup(foundKey, foundData, 390 LockMode.DEFAULT); 391 } 392 } 393 394 protected class BackwardsDupDataWalker extends BackwardsDataWalker { 395 BackwardsDupDataWalker(Hashtable dataMap) { 396 super(dataMap); 397 } 398 399 BackwardsDupDataWalker(Hashtable dataMap, 400 Hashtable addedDataMap) { 401 super(dataMap, addedDataMap); 402 } 403 404 BackwardsDupDataWalker(String whenFoundDoInsert, 405 String newKey, 406 Hashtable dataMap) { 407 super(whenFoundDoInsert, newKey, dataMap); 408 } 409 410 OperationStatus getData(StringDbt foundKey, StringDbt foundData) 411 throws DatabaseException { 412 413 return cursor.getPrevDup(foundKey, foundData, 414 LockMode.DEFAULT); 415 } 416 } 417 418 protected class NoDupDataWalker extends DataWalker { 419 NoDupDataWalker(Hashtable dataMap) { 420 super(dataMap); 421 } 422 423 NoDupDataWalker(Hashtable dataMap, 424 Hashtable addedDataMap) { 425 super(dataMap, addedDataMap); 426 } 427 428 NoDupDataWalker(String whenFoundDoInsert, 429 String newKey, 430 Hashtable dataMap) { 431 super(whenFoundDoInsert, newKey, dataMap); 432 } 433 434 OperationStatus getData(StringDbt foundKey, StringDbt foundData) 435 throws DatabaseException { 436 437 return cursor.getNextNoDup(foundKey, foundData, 438 LockMode.DEFAULT); 439 } 440 } 441 442 protected class NoDupBackwardsDataWalker extends BackwardsDataWalker { 443 NoDupBackwardsDataWalker(Hashtable dataMap) { 444 super(dataMap); 445 } 446 447 NoDupBackwardsDataWalker(Hashtable dataMap, 448 Hashtable addedDataMap) { 449 super(dataMap, addedDataMap); 450 } 451 452 NoDupBackwardsDataWalker(String whenFoundDoInsert, 453 String newKey, 454 Hashtable dataMap) { 455 super(whenFoundDoInsert, newKey, dataMap); 456 } 457 458 OperationStatus getData(StringDbt foundKey, StringDbt foundData) 459 throws DatabaseException { 460 461 return cursor.getPrevNoDup(foundKey, foundData, 462 LockMode.DEFAULT); 463 } 464 } 465 466 469 protected String nextKey(String key) { 470 byte[] sb = key.getBytes(); 471 sb[sb.length - 1]++; 472 return new String (sb); 473 } 474 475 478 protected String prevKey(String key) { 479 byte[] sb = key.getBytes(); 480 sb[sb.length - 1]--; 481 return new String (sb); 482 } 483 484 487 protected void doLargePut(Hashtable dataMap, int nKeys) 488 throws DatabaseException { 489 490 for (int i = 0; i < nKeys; i++) { 491 byte[] key = new byte[N_KEY_BYTES]; 492 TestUtils.generateRandomAlphaBytes(key); 493 String keyString = new String (key); 494 String dataString = Integer.toString(i); 495 putAndVerifyCursor(cursor, new StringDbt(keyString), 496 new StringDbt(dataString), true); 497 if (dataMap != null) { 498 dataMap.put(keyString, dataString); 499 } 500 } 501 } 502 503 506 protected void doLargePutPerf(int nKeys) 507 throws DatabaseException { 508 509 byte[][] keys = new byte[nKeys][]; 510 for (int i = 0; i < nKeys; i++) { 511 byte[] key = new byte[20]; 512 keys[i] = key; 513 TestUtils.generateRandomAlphaBytes(key); 514 String keyString = new String (key); 515 byte[] dataBytes = new byte[120]; 516 TestUtils.generateRandomAlphaBytes(dataBytes); 517 String dataString = new String (dataBytes); 518 putAndVerifyCursor(cursor, new StringDbt(keyString), 519 new StringDbt(dataString), true); 520 } 521 } 522 523 526 protected void doSimpleDuplicatePuts() 527 throws DatabaseException { 528 529 for (int i = 0; i < simpleKeyStrings.length; i++) { 530 for (int j = 0; j < simpleKeyStrings.length; j++) { 531 putAndVerifyCursor(cursor, simpleKeys[i], simpleData[j], true); 532 } 533 } 534 } 535 536 547 protected void createRandomDuplicateData(Hashtable dataMap, 548 boolean putVariant) 549 throws DatabaseException { 550 551 createRandomDuplicateData(N_TOP_LEVEL_KEYS, 552 N_DUPLICATES_PER_KEY, 553 dataMap, 554 putVariant, 555 false); 556 } 557 558 575 protected void createRandomDuplicateData(int nTopKeys, 576 int nDup, 577 Hashtable dataMap, 578 boolean putVariant, 579 boolean verifyCount) 580 throws DatabaseException { 581 582 boolean createSomeNonDupes = false; 583 if (nTopKeys < 0) { 584 nTopKeys = Math.abs(nTopKeys); 585 nTopKeys <<= 1; 586 createSomeNonDupes = true; 587 } 588 589 byte[][] keys = new byte[nTopKeys][]; 590 for (int i = 0; i < nTopKeys; i++) { 591 byte[] key = new byte[N_KEY_BYTES]; 592 keys[i] = key; 593 TestUtils.generateRandomAlphaBytes(key); 594 String keyString = new String (key); 595 Hashtable ht = new Hashtable (); 596 if (dataMap != null) { 597 dataMap.put(keyString, ht); 598 } 599 int nDupesThisTime = nDup; 600 if (createSomeNonDupes && (i % 2) == 0) { 601 nDupesThisTime = 1; 602 } 603 for (int j = 1; j <= nDupesThisTime; j++) { 604 byte[] data = new byte[N_KEY_BYTES]; 605 TestUtils.generateRandomAlphaBytes(data); 606 OperationStatus status = 607 putAndVerifyCursor(cursor, new StringDbt(keyString), 608 new StringDbt(data), putVariant); 609 610 if (verifyCount) { 611 assertTrue(cursor.count() == j); 612 } 613 614 if (status != OperationStatus.SUCCESS) { 615 throw new DuplicateEntryException 616 ("Duplicate Entry"); 617 } 618 String dataString = new String (data); 619 ht.put(dataString, dataString); 620 } 621 } 622 } 623 624 629 protected void verifyEntries(Hashtable dataMap) 630 throws DatabaseException { 631 632 Tree tree = DbInternal.dbGetDatabaseImpl(exampleDb).getTree(); 633 Enumeration e = dataMap.keys(); 634 while (e.hasMoreElements()) { 635 String key = (String ) e.nextElement(); 636 if (!retrieveData(tree, key.getBytes())) { 637 System.out.println("Couldn't find: " + key); 638 } 639 } 640 } 641 642 643 protected void validateDatabase() 644 throws DatabaseException { 645 646 DatabaseImpl dbImpl = DbInternal.dbGetDatabaseImpl(exampleDb); 647 assertTrue(dbImpl.verify(new VerifyConfig(), dbImpl.getEmptyStats())); 648 } 649 650 653 protected boolean retrieveData(Tree tree, byte[] key) 654 throws DatabaseException { 655 656 TestUtils.checkLatchCount(); 657 Node n = 658 tree.search(key, Tree.SearchType.NORMAL, -1, null, true); 659 if (!(n instanceof BIN)) { 660 fail("search didn't return a BIN for key: " + key); 661 } 662 BIN bin = (BIN) n; 663 try { 664 int index = bin.findEntry(key, false, true); 665 if (index == -1) { 666 return false; 667 } 668 return true; 669 } finally { 670 bin.releaseLatch(); 671 TestUtils.checkLatchCount(); 672 } 673 } 674 675 protected OperationStatus putAndVerifyCursor(Cursor cursor, StringDbt key, 676 StringDbt data, 677 boolean putVariant) 678 throws DatabaseException { 679 680 OperationStatus status; 681 if (duplicatesAllowed) { 682 status = cursor.putNoDupData(key, data); 683 } else { 684 status = cursor.putNoOverwrite(key, data); 685 } 686 687 if (status == OperationStatus.SUCCESS) { 688 StringDbt keyCheck = new StringDbt(); 689 StringDbt dataCheck = new StringDbt(); 690 691 assertEquals(OperationStatus.SUCCESS, cursor.getCurrent 692 (keyCheck, dataCheck, LockMode.DEFAULT)); 693 assertEquals(key.getString(), keyCheck.getString()); 694 assertEquals(data.getString(), dataCheck.getString()); 695 } 696 697 return status; 698 } 699 700 protected static class BtreeComparator implements Comparator { 701 protected boolean ascendingComparison = true; 702 703 protected BtreeComparator() { 704 } 705 706 public int compare(Object o1, Object o2) { 707 byte[] arg1; 708 byte[] arg2; 709 if (ascendingComparison) { 710 arg1 = (byte[]) o1; 711 arg2 = (byte[]) o2; 712 } else { 713 arg1 = (byte[]) o2; 714 arg2 = (byte[]) o1; 715 } 716 int a1Len = arg1.length; 717 int a2Len = arg2.length; 718 719 int limit = Math.min(a1Len, a2Len); 720 721 for (int i = 0; i < limit; i++) { 722 byte b1 = arg1[i]; 723 byte b2 = arg2[i]; 724 if (b1 == b2) { 725 continue; 726 } else { 727 729 short s1 = (short) (b1 & 0x7F); 730 short s2 = (short) (b2 & 0x7F); 731 if (b1 < 0) { 732 s1 |= 0x80; 733 } 734 if (b2 < 0) { 735 s2 |= 0x80; 736 } 737 return (s1 - s2); 738 } 739 } 740 741 return (a1Len - a2Len); 742 } 743 } 744 745 protected static class ReverseBtreeComparator extends BtreeComparator { 746 protected ReverseBtreeComparator() { 747 ascendingComparison = false; 748 } 749 } 750 } 751 | Popular Tags |