1 8 package com.sleepycat.je.tree; 9 10 import java.io.File ; 11 import java.io.IOException ; 12 import java.util.Enumeration ; 13 14 import junit.framework.Test; 15 import junit.framework.TestCase; 16 import junit.framework.TestSuite; 17 18 import com.sleepycat.bind.tuple.IntegerBinding; 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.RunRecoveryException; 31 import com.sleepycat.je.config.EnvironmentParams; 32 import com.sleepycat.je.dbi.EnvironmentImpl; 33 import com.sleepycat.je.latch.LatchSupport; 34 import com.sleepycat.je.log.FileManager; 35 import com.sleepycat.je.util.TestUtils; 36 import com.sleepycat.je.utilint.TestHook; 37 38 41 public class ReleaseLatchesTest extends TestCase { 42 private static final boolean DEBUG = false; 43 44 private Environment env; 45 private File envHome; 46 private Database db; 47 private TestDescriptor testActivity; 48 49 55 public static TestDescriptor [] OPERATIONS = { 56 57 65 new TestDescriptor("database put", 6, 30, false) { 66 void doAction(ReleaseLatchesTest test, int exceptionCount) 67 throws DatabaseException { 68 69 test.populate(false); 70 } 71 72 void reinit(ReleaseLatchesTest test) 73 throws DatabaseException{ 74 75 test.closeDb(); 76 test.getEnv().truncateDatabase(null, "foo", false); 77 } 78 }, 79 new TestDescriptor("cursor scan", 31, 20, false) { 80 void doAction(ReleaseLatchesTest test, int exceptionCount) 81 throws DatabaseException { 82 83 test.scan(); 84 } 85 }, 86 new TestDescriptor("cursor scan duplicates", 23, 3, true) { 87 void doAction(ReleaseLatchesTest test, int exceptionCount) 88 throws DatabaseException { 89 90 test.scan(); 91 } 92 }, 93 new TestDescriptor("database get", 31, 20, false) { 94 void doAction(ReleaseLatchesTest test, int exceptionCount) 95 throws DatabaseException { 96 97 test.get(); 98 } 99 }, 100 new TestDescriptor("database delete", 40, 30, false) { 101 void doAction(ReleaseLatchesTest test, int exceptionCount) 102 throws DatabaseException { 103 104 test.delete(); 105 } 106 107 void reinit(ReleaseLatchesTest test) 108 throws DatabaseException{ 109 110 test.populate(false); 111 } 112 }, 113 new TestDescriptor("checkpoint", 40, 10, false) { 114 void doAction(ReleaseLatchesTest test, int exceptionCount) 115 throws DatabaseException { 116 117 test.modify(exceptionCount); 118 CheckpointConfig config = new CheckpointConfig(); 119 config.setForce(true); 120 if (DEBUG) { 121 System.out.println("Got to checkpoint"); 122 } 123 test.getEnv().checkpoint(config); 124 } 125 }, 126 new TestDescriptor("clean", 100, 5, false) { 127 void doAction(ReleaseLatchesTest test, int exceptionCount) 128 throws DatabaseException { 129 130 test.modify(exceptionCount); 131 CheckpointConfig config = new CheckpointConfig(); 132 config.setForce(true); 133 if (DEBUG) { 134 System.out.println("Got to cleaning"); 135 } 136 test.getEnv().cleanLog(); 137 } 138 }, 139 new TestDescriptor("compress", 20, 10, false) { 140 void doAction(ReleaseLatchesTest test, int exceptionCount) 141 throws DatabaseException { 142 143 test.delete(); 144 if (DEBUG) { 145 System.out.println("Got to compress"); 146 } 147 test.getEnv().compress(); 148 } 149 150 void reinit(ReleaseLatchesTest test) 151 throws DatabaseException{ 152 153 test.populate(false); 154 } 155 } 156 }; 157 158 public static Test suite() { 159 TestSuite allTests = new TestSuite(); 160 for (int i = 0; i < OPERATIONS.length; i++) { 161 TestSuite suite = new TestSuite(ReleaseLatchesTest.class); 162 Enumeration e = suite.tests(); 163 while (e.hasMoreElements()) { 164 ReleaseLatchesTest t = (ReleaseLatchesTest) e.nextElement(); 165 t.initTest(OPERATIONS[i]); 166 allTests.addTest(t); 167 } 168 } 169 return allTests; 170 } 171 172 public ReleaseLatchesTest() { 173 174 envHome = new File (System.getProperty(TestUtils.DEST_DIR)); 175 } 176 177 public void setUp() 178 throws IOException , DatabaseException { 179 180 TestUtils.removeFiles("Setup", envHome, FileManager.JE_SUFFIX); 181 } 182 183 public void tearDown() 184 throws IOException , DatabaseException { 185 186 setName(getName() + ":" + testActivity.getName()); 187 TestUtils.removeFiles("TearDown", envHome, 188 FileManager.JE_SUFFIX, true); 189 } 190 191 private void init(boolean duplicates) 192 throws DatabaseException { 193 194 openEnvAndDb(); 195 196 populate(duplicates); 197 env.checkpoint(null); 198 db.close(); 199 db = null; 200 env.close(); 201 env = null; 202 } 203 204 private void openEnvAndDb() 205 throws DatabaseException { 206 207 210 EnvironmentConfig envConfig = TestUtils.initEnvConfig(); 211 DbInternal.disableParameterValidation(envConfig); 212 envConfig.setAllowCreate(true); 213 envConfig.setConfigParam(EnvironmentParams.NODE_MAX.getName(), "4"); 214 envConfig.setConfigParam("je.env.runEvictor", "false"); 215 envConfig.setConfigParam("je.env.runCheckpointer", "false"); 216 envConfig.setConfigParam("je.env.runCleaner", "false"); 217 envConfig.setConfigParam("je.env.runINCompressor", "false"); 218 envConfig.setConfigParam 219 (EnvironmentParams.CLEANER_MIN_UTILIZATION.getName(), "90"); 220 envConfig.setConfigParam(EnvironmentParams.LOG_FILE_MAX.getName(), 221 Integer.toString(20000)); 222 223 env = new Environment(envHome, envConfig); 224 225 DatabaseConfig dbConfig = new DatabaseConfig(); 226 dbConfig.setAllowCreate(true); 227 dbConfig.setSortedDuplicates(true); 228 db = env.openDatabase(null, "foo", dbConfig); 229 } 230 231 232 private void doCloseAndCheckLeaks() 233 throws Throwable { 234 235 try { 236 if (db != null) { 237 db.close(); 238 db = null; 239 } 240 241 if (env != null) { 242 env.close(); 243 env = null; 244 } 245 } catch (Throwable t) { 246 System.out.println("operation = " + testActivity.name); 247 t.printStackTrace(); 248 throw t; 249 } 250 } 251 252 private void closeDb() 253 throws DatabaseException { 254 255 if (db != null) { 256 db.close(); 257 db = null; 258 } 259 } 260 261 private Environment getEnv() { 262 return env; 263 } 264 265 private void initTest(TestDescriptor action) { 266 this.testActivity = action; 267 } 268 269 275 public void testCheckLatchLeaks() 276 throws Throwable { 277 278 int maxExceptionCount = testActivity.getNumExceptions(); 279 if (DEBUG) { 280 System.out.println("Starting test: " + testActivity.getName()); 281 } 282 283 try { 284 init(testActivity.getDuplicates()); 285 286 290 for (int i = 1; i <= maxExceptionCount; i++) { 291 292 296 openEnvAndDb(); 297 EnvironmentImpl envImpl = 298 DbInternal.envGetEnvironmentImpl(env); 299 boolean exceptionOccurred = false; 300 301 try { 302 ReadIOExceptionHook readHook = new ReadIOExceptionHook(i); 303 envImpl.getLogManager().setReadHook(readHook); 304 testActivity.doAction(this, i); 305 } catch (RunRecoveryException e) { 306 307 314 checkLatchCount(e, i); 315 env.close(); 316 openEnvAndDb(); 317 exceptionOccurred = true; 318 } catch (DatabaseException e) { 319 checkLatchCount(e, i); 320 exceptionOccurred = true; 321 } 322 323 if (DEBUG && !exceptionOccurred) { 324 System.out.println("Don't need ex count " + i + 325 " for test activity " + 326 testActivity.getName()); 327 } 328 329 envImpl.getLogManager().setReadHook(null); 330 testActivity.reinit(this); 331 doCloseAndCheckLeaks(); 332 } 333 } catch (Throwable t) { 334 t.printStackTrace(); 335 throw t; 336 } 337 } 338 339 private void checkLatchCount(DatabaseException e, 340 int exceptionCount) 341 throws DatabaseException { 342 343 344 if (LatchSupport.countLatchesHeld() > 0) { 345 LatchSupport.dumpLatchesHeld(); 346 System.out.println("Operation = " + testActivity.getName() + 347 " exception count=" + exceptionCount + 348 " Held latches = " + 349 LatchSupport.countLatchesHeld()); 350 351 e.printStackTrace(); 352 throw e; 353 } 354 } 355 356 357 private void populate(boolean duplicates) 358 throws DatabaseException { 359 360 DatabaseEntry key = new DatabaseEntry(); 361 DatabaseEntry data = new DatabaseEntry(); 362 DatabaseEntry data1 = new DatabaseEntry(); 363 DatabaseEntry data2 = new DatabaseEntry(); 364 DatabaseEntry data3 = new DatabaseEntry(); 365 DatabaseEntry data4 = new DatabaseEntry(); 366 IntegerBinding.intToEntry(0, data); 367 IntegerBinding.intToEntry(1, data1); 368 IntegerBinding.intToEntry(2, data2); 369 IntegerBinding.intToEntry(3, data3); 370 IntegerBinding.intToEntry(4, data4); 371 372 for (int i = 0; i < testActivity.getNumRecords(); i++) { 373 IntegerBinding.intToEntry(i, key); 374 assertEquals(OperationStatus.SUCCESS, db.put(null, key, data)); 375 if (duplicates) { 376 assertEquals(OperationStatus.SUCCESS, 377 db.put(null, key, data1)); 378 assertEquals(OperationStatus.SUCCESS, 379 db.put(null, key, data2)); 380 assertEquals(OperationStatus.SUCCESS, 381 db.put(null, key, data3)); 382 assertEquals(OperationStatus.SUCCESS, 383 db.put(null, key, data4)); 384 } 385 } 386 } 387 388 389 private void modify(int dataVal) 390 throws DatabaseException { 391 392 DatabaseEntry key = new DatabaseEntry(); 393 DatabaseEntry data = new DatabaseEntry(); 394 IntegerBinding.intToEntry(dataVal, data); 395 396 for (int i = 0; i < testActivity.getNumRecords(); i++) { 397 IntegerBinding.intToEntry(i, key); 398 assertEquals(OperationStatus.SUCCESS, db.put(null, key, data)); 399 } 400 } 401 402 403 private void scan() 404 throws DatabaseException { 405 406 Cursor cursor = null; 407 try { 408 cursor = db.openCursor(null, null); 409 DatabaseEntry key = new DatabaseEntry(); 410 DatabaseEntry data = new DatabaseEntry(); 411 412 while (cursor.getNext(key, data, LockMode.DEFAULT) == 413 OperationStatus.SUCCESS) { 414 } 415 } finally { 416 if (cursor != null) { 417 cursor.close(); 418 } 419 } 420 } 421 422 423 private void get() 424 throws DatabaseException { 425 426 DatabaseEntry key = new DatabaseEntry(); 427 DatabaseEntry data = new DatabaseEntry(); 428 for (int i = 0; i < testActivity.getNumRecords(); i++) { 429 IntegerBinding.intToEntry(i, key); 430 assertEquals(OperationStatus.SUCCESS, 431 db.get(null, key, data, LockMode.DEFAULT)); 432 } 433 } 434 435 436 private void delete() 437 throws DatabaseException { 438 439 DatabaseEntry key = new DatabaseEntry(); 440 for (int i = 0; i < testActivity.getNumRecords(); i++) { 441 IntegerBinding.intToEntry(i, key); 442 assertEquals("key = " + IntegerBinding.entryToInt(key), 443 OperationStatus.SUCCESS, db.delete(null, key)); 444 } 445 } 446 449 static class ReadIOExceptionHook implements TestHook { 450 private int counter = 0; 451 private int throwCount; 452 453 ReadIOExceptionHook(int throwCount) { 454 this.throwCount = throwCount; 455 } 456 457 public void doIOHook() 458 throws IOException { 459 460 if (throwCount == counter) { 461 counter++; 462 throw new IOException ("Generated exception: " + 463 this.getClass().getName()); 464 } else { 465 counter++; 466 } 467 } 468 469 public void doHook() {} 470 471 public Object getHookValue() { 472 return null; 473 } 474 } 475 476 static abstract class TestDescriptor { 477 private String name; 478 private int numExceptions; 479 private int numRecords; 480 private boolean duplicates; 481 482 TestDescriptor(String name, 483 int numExceptions, 484 int numRecords, 485 boolean duplicates) { 486 this.name = name; 487 this.numExceptions = numExceptions; 488 this.numRecords = numRecords; 489 this.duplicates = duplicates; 490 } 491 492 int getNumRecords() { 493 return numRecords; 494 } 495 496 int getNumExceptions() { 497 return numExceptions; 498 } 499 500 String getName() { 501 return name; 502 } 503 504 boolean getDuplicates() { 505 return duplicates; 506 } 507 508 509 abstract void doAction(ReleaseLatchesTest test, 510 int exceptionCount) 511 throws DatabaseException; 512 513 514 void reinit(ReleaseLatchesTest test) 515 throws DatabaseException { 516 517 } 518 } 519 } 520 | Popular Tags |