1 8 9 package com.sleepycat.je.incomp; 10 11 import java.io.File ; 12 import java.io.IOException ; 13 import java.util.Enumeration ; 14 15 import junit.framework.Test; 16 import junit.framework.TestCase; 17 import junit.framework.TestSuite; 18 19 import com.sleepycat.je.CheckpointConfig; 20 import com.sleepycat.je.Cursor; 21 import com.sleepycat.je.Database; 22 import com.sleepycat.je.DatabaseConfig; 23 import com.sleepycat.je.DatabaseEntry; 24 import com.sleepycat.je.DatabaseException; 25 import com.sleepycat.je.DbInternal; 26 import com.sleepycat.je.Environment; 27 import com.sleepycat.je.EnvironmentConfig; 28 import com.sleepycat.je.LockMode; 29 import com.sleepycat.je.OperationStatus; 30 import com.sleepycat.je.config.EnvironmentParams; 31 import com.sleepycat.je.dbi.CursorImpl; 32 import com.sleepycat.je.util.TestUtils; 33 import com.sleepycat.je.utilint.TestHook; 34 35 39 public class EmptyBINTest extends TestCase { 40 private static final boolean DEBUG = false; 41 42 private static final byte DEFAULT_VAL = 100; 43 private File envHome; 44 private Environment env; 45 private Database db; 46 47 private boolean useDups; 48 private boolean doPruningAtCursorLevel; 49 private boolean doPruningAtTreeLevel; 50 51 public EmptyBINTest() { 52 envHome = new File (System.getProperty(TestUtils.DEST_DIR)); 53 } 54 55 public void setUp() 56 throws IOException { 57 58 TestUtils.removeLogFiles("Setup", envHome, false); 59 } 60 61 public void tearDown() 62 throws Exception { 63 64 if (db != null) { 65 try { 66 db.close(); 67 } catch (DatabaseException ignore) { 68 } 69 } 70 71 if (env != null) { 72 try { 73 env.close(); 74 } catch (DatabaseException ignore) { 75 } 76 } 77 env = null; 78 db = null; 79 setName(getName() + "-" + 80 (useDups ? "DUPS" : "!DUPS") + 81 "/" + 82 (doPruningAtCursorLevel ? "CURSORPRUNE" : "!CURSORPRUNE") + 83 "/" + 84 (doPruningAtTreeLevel ? "TREEPRUNE" : "!TREEPRUNE")); 85 super.tearDown(); 86 TestUtils.removeLogFiles("TearDown", envHome, false); 87 } 88 89 93 public static Test suite() { 94 TestSuite allTests = new TestSuite(); 95 boolean[] dupCombo = new boolean[] {true, false}; 96 boolean[] pruneCombo = new boolean[] {true, false}; 97 for (int dup = 0; dup < dupCombo.length; dup++) { 98 for (int pruneCursor = 0; 99 pruneCursor < pruneCombo.length; 100 pruneCursor++) { 101 for (int pruneTree = 0; 102 pruneTree < pruneCombo.length; 103 pruneTree++) { 104 TestSuite suite = new TestSuite(EmptyBINTest.class); 105 Enumeration e = suite.tests(); 106 while (e.hasMoreElements()) { 107 EmptyBINTest test = (EmptyBINTest) e.nextElement(); 108 boolean pruneC = pruneCombo[pruneCursor]; 109 boolean pruneT = pruneCombo[pruneTree]; 110 if (pruneC && pruneT) { 111 112 break; 113 } 114 test.init(dupCombo[dup], pruneC, pruneT); 115 allTests.addTest(test); 116 } 117 } 118 } 119 } 120 return allTests; 121 } 122 123 private void init(boolean useDups, 124 boolean doPruningAtCursorLevel, 125 boolean doPruningAtTreeLevel) { 126 this.useDups = useDups; 127 this.doPruningAtCursorLevel = doPruningAtCursorLevel; 128 this.doPruningAtTreeLevel = doPruningAtTreeLevel; 129 if (DEBUG) { 130 System.out.println("useDups=" + useDups + 131 " doPruningAtCursorLevel=" + 132 doPruningAtCursorLevel + 133 " doPruningAtTreeLevel=" + 134 doPruningAtTreeLevel); 135 } 136 } 137 138 139 public void testScanFromEndOfFirstBin() 140 throws DatabaseException { 141 142 148 doScanAcrossEmptyBin(true, (byte) 4, new byte[] {4,8,9,10}); } 152 153 public void testScanFromLeftSideOfEmptyBin() 154 throws DatabaseException { 155 156 162 doScanAcrossEmptyBin(true, (byte) 5, new byte[] {8,9,10}); } 166 167 public void testScanFromRightSideOfEmptyBin() 168 throws DatabaseException { 169 170 176 doScanAcrossEmptyBin(false, (byte) 7, new byte[] {8,4,3,2,1,0}); } 180 181 public void testScanFromBeginningOfLastBin() 182 throws DatabaseException { 183 184 189 doScanAcrossEmptyBin(false, (byte) 8, new byte[] {8,4,3,2,1,0}); } 193 194 public void testScanForward() 195 throws DatabaseException { 196 197 201 doScanAcrossEmptyBin(true, (byte) -1, 203 new byte[] {0,1,2,3,4,8,9,10}); 204 } 205 206 public void testScanBackwards() 207 throws DatabaseException { 208 209 213 doScanAcrossEmptyBin(false, (byte) -1, 215 new byte[] {10,9,8,4,3,2,1,0}); 216 } 217 218 225 private void doScanAcrossEmptyBin(boolean forward, 226 byte startKey, 227 byte[] expectVals) 228 throws DatabaseException { 229 230 int deleteStartVal = 5; 231 int deleteEndVal = 7; 232 openAndInitEmptyMiddleBIN(deleteStartVal, deleteEndVal); 233 234 if (DEBUG) { 235 DbInternal.dbGetDatabaseImpl(db).getTree().dump(); 236 } 237 238 DatabaseEntry key = new DatabaseEntry(); 239 DatabaseEntry data = new DatabaseEntry(); 240 241 244 int cnt = 0; 245 Cursor cursor = db.openCursor(null, null); 246 CursorImpl cursorImpl = DbInternal.getCursorImpl(cursor); 247 248 if (doPruningAtCursorLevel) { 249 cursorImpl.setTestHook(new PruningHook(env)); 250 } 251 252 if (doPruningAtTreeLevel) { 253 DbInternal.dbGetDatabaseImpl(db).getTree(). 254 setSearchHook(new PruningHook(env)); 255 } 256 257 int expectIndex = 0; 258 if (startKey < 0) { 259 if (forward) { 260 assertEquals(OperationStatus.SUCCESS, 261 cursor.getFirst(key, data, null)); 262 } else { 263 assertEquals(OperationStatus.SUCCESS, 264 cursor.getLast(key, data, null)); 265 } 266 } else { 267 if (useDups) { 268 key.setData(new byte[] {DEFAULT_VAL}); 269 data.setData(new byte[] {startKey}); 270 } else { 271 key.setData(new byte[] { startKey }); 272 } 273 274 if ((startKey >= deleteStartVal) && 275 (startKey <= deleteEndVal)) { 276 277 if (useDups) { 278 assertEquals(OperationStatus.SUCCESS, 279 cursor.getSearchBothRange(key, data, null)); 280 } else { 281 assertEquals(OperationStatus.SUCCESS, 282 cursor.getSearchKeyRange(key, data, null)); 283 } 284 } else { 285 286 if (useDups) { 287 assertEquals(OperationStatus.SUCCESS, 288 cursor.getSearchBoth(key, data, null)); 289 } else { 290 assertEquals(OperationStatus.SUCCESS, 291 cursor.getSearchKey(key, data, null)); 292 } 293 } 294 } 295 296 OperationStatus status; 297 do { 298 cnt++; 299 300 301 if (DEBUG) { 302 System.out.println("=>key=" + key.getData()[0] + 303 " data=" + data.getData()[0]); 304 } 305 if (useDups) { 306 assertEquals(expectVals[expectIndex++], data.getData()[0]); 307 } else { 308 assertEquals(expectVals[expectIndex++], key.getData()[0]); 309 } 310 311 if (forward) { 312 status = cursor.getNext(key, data, null); 313 } else { 314 status = cursor.getPrev(key, data, null); 315 } 316 } while (status == OperationStatus.SUCCESS); 317 318 assertEquals(expectVals.length, cnt); 319 cursor.close(); 320 closeEnv(); 321 } 322 323 337 private void openAndInitEmptyMiddleBIN(int deleteStartVal, 338 int deleteEndVal) 339 throws DatabaseException { 340 341 openEnv(false, "4"); 342 DatabaseEntry data = new DatabaseEntry(); 343 data.setData(new byte[] {DEFAULT_VAL}); 344 DatabaseEntry key = new DatabaseEntry(); 345 key.setData(new byte[] {DEFAULT_VAL}); 346 347 348 OperationStatus status; 349 for (int i = 0; i < 11; i++) { 350 if (useDups) { 351 data = new DatabaseEntry(new byte[] { (byte) i }); 352 } else { 353 key = new DatabaseEntry(new byte[] { (byte) i }); 354 } 355 status = db.put(null, key, data); 356 assertEquals(OperationStatus.SUCCESS, status); 357 } 358 359 360 if (useDups) { 361 Cursor cursor = db.openCursor(null, null); 362 data = new DatabaseEntry(new byte[] { (byte) deleteStartVal }); 363 assertEquals(OperationStatus.SUCCESS, 364 cursor.getSearchBoth(key, data, LockMode.DEFAULT)); 365 for (int i = deleteStartVal; i <= deleteEndVal; i++) { 366 assertEquals(OperationStatus.SUCCESS, 367 cursor.delete()); 368 assertEquals(OperationStatus.SUCCESS, 369 cursor.getNext(key, data, LockMode.DEFAULT)); 370 } 371 cursor.close(); 372 } else { 373 for (int i = deleteStartVal; i <= deleteEndVal; i++) { 374 key = new DatabaseEntry(new byte[] { (byte) i }); 375 status = db.delete(null, key); 376 assertEquals(OperationStatus.SUCCESS, status); 377 } 378 } 379 380 CheckpointConfig config = new CheckpointConfig(); 381 config.setForce(true); 382 env.checkpoint(config); 383 } 384 385 388 private void openEnv(boolean transactional, String nodeMax) 389 throws DatabaseException { 390 391 EnvironmentConfig envConfig = TestUtils.initEnvConfig(); 392 envConfig.setTransactional(transactional); 393 envConfig.setConfigParam 394 (EnvironmentParams.ENV_RUN_INCOMPRESSOR.getName(), "true"); 395 if (nodeMax != null) { 396 envConfig.setConfigParam 397 (EnvironmentParams.NODE_MAX.getName(), nodeMax); 398 envConfig.setConfigParam 399 (EnvironmentParams.NODE_MAX_DUPTREE.getName(), nodeMax); 400 } 401 envConfig.setAllowCreate(true); 402 env = new Environment(envHome, envConfig); 403 404 405 DatabaseConfig dbConfig = new DatabaseConfig(); 406 dbConfig.setTransactional(transactional); 407 dbConfig.setSortedDuplicates(useDups); 408 dbConfig.setAllowCreate(true); 409 db = env.openDatabase(null, "testDB", dbConfig); 410 } 411 412 415 private void closeEnv() 416 throws DatabaseException { 417 418 db.close(); 419 db = null; 420 env.close(); 421 env = null; 422 } 423 424 private static class PruningHook implements TestHook { 425 Environment env; 426 427 PruningHook(Environment env) { 428 this.env = env; 429 } 430 431 public void doIOHook() throws IOException {} 432 433 public void doHook() { 434 DbInternal.envGetEnvironmentImpl(env).getINCompressor(). 435 wakeup(); 436 Thread.yield(); 437 try { 438 Thread.sleep(100); 439 } catch (Throwable T) { 440 } 441 } 442 443 public Object getHookValue() { 444 return null; 445 } 446 } 447 } 448 | Popular Tags |