1 8 9 package com.sleepycat.je.log; 10 11 import java.io.File ; 12 import java.io.IOException ; 13 import java.nio.ByteBuffer ; 14 15 import junit.framework.TestCase; 16 17 import com.sleepycat.je.CheckpointConfig; 18 import com.sleepycat.je.Database; 19 import com.sleepycat.je.DatabaseConfig; 20 import com.sleepycat.je.DatabaseEntry; 21 import com.sleepycat.je.DatabaseException; 22 import com.sleepycat.je.DbInternal; 23 import com.sleepycat.je.Environment; 24 import com.sleepycat.je.EnvironmentConfig; 25 import com.sleepycat.je.EnvironmentStats; 26 import com.sleepycat.je.LockMode; 27 import com.sleepycat.je.OperationStatus; 28 import com.sleepycat.je.Transaction; 29 import com.sleepycat.je.config.EnvironmentParams; 30 import com.sleepycat.je.util.TestUtils; 31 import com.sleepycat.je.utilint.DbLsn; 32 33 public class IOExceptionTest extends TestCase { 34 35 private Environment env; 36 private Database db; 37 private File envHome; 38 39 public IOExceptionTest() 40 throws Exception { 41 42 envHome = new File (System.getProperty(TestUtils.DEST_DIR)); 43 } 44 45 public void setUp() 46 throws IOException , DatabaseException { 47 48 TestUtils.removeFiles("Setup", envHome, FileManager.JE_SUFFIX); 49 } 50 51 public void tearDown() 52 throws IOException , DatabaseException { 53 54 FileManager.IO_EXCEPTION_TESTING = false; 55 db.close(); 56 env.close(); 57 TestUtils.removeFiles("TearDown", envHome, FileManager.JE_SUFFIX); 58 } 59 60 public void testIOExceptionNoRecovery() 61 throws Throwable { 62 63 doIOExceptionTest(false); 64 } 65 66 public void testIOExceptionWithRecovery() 67 throws Throwable { 68 69 doIOExceptionTest(true); 70 } 71 72 public void testEviction() 73 throws Exception { 74 75 try { 76 createDatabase(200000, 0); 77 78 final int N_RECS = 25; 79 80 CheckpointConfig chkConf = new CheckpointConfig(); 81 chkConf.setForce(true); 82 Transaction txn = env.beginTransaction(null, null); 83 int keyInt = 0; 84 FileManager.IO_EXCEPTION_TESTING = true; 85 for (int i = 0; i < N_RECS; i++) { 86 String keyStr = Integer.toString(keyInt); 87 DatabaseEntry key = 88 new DatabaseEntry(keyStr.getBytes()); 89 DatabaseEntry data = 90 new DatabaseEntry(("d" + keyStr).getBytes()); 91 try { 92 assertTrue(db.put(txn, key, data) == 93 OperationStatus.SUCCESS); 94 } catch (DatabaseException DE) { 95 fail("unexpected DatabaseException"); 96 break; 97 } 98 } 99 100 try { 101 env.checkpoint(chkConf); 102 fail("expected DatabaseException"); 103 } catch (DatabaseException DE) { 104 } 105 106 EnvironmentStats stats = env.getStats(null); 107 assertTrue((stats.getNFullINFlush() + 108 stats.getNFullBINFlush()) > 0); 109 110 111 for (int i = 0; i < N_RECS; i++) { 112 String keyStr = Integer.toString(keyInt); 113 DatabaseEntry key = 114 new DatabaseEntry(keyStr.getBytes()); 115 DatabaseEntry data = new DatabaseEntry(); 116 try { 117 assertTrue(db.get(txn, key, data, null) == 118 OperationStatus.SUCCESS); 119 assertEquals(new String (data.getData()), "d" + keyStr); 120 } catch (DatabaseException DE) { 121 fail("unexpected DatabaseException"); 122 break; 123 } 124 } 125 126 130 FileManager.IO_EXCEPTION_TESTING = false; 131 try { 132 txn.commit(); 133 } catch (DatabaseException DE) { 134 fail("unexpected DatabaseException"); 135 } 136 } catch (Exception E) { 137 E.printStackTrace(); 138 } 139 } 140 141 147 public void testIOExceptionReadBack() 148 throws Exception { 149 150 try { 151 createDatabase(100000, 1000); 152 153 final int N_RECS = 25; 154 155 CheckpointConfig chkConf = new CheckpointConfig(); 156 chkConf.setForce(true); 157 Transaction txn = env.beginTransaction(null, null); 158 int keyInt = 0; 159 for (int i = 0; i < N_RECS; i++) { 160 String keyStr = Integer.toString(i); 161 DatabaseEntry key = 162 new DatabaseEntry(keyStr.getBytes()); 163 DatabaseEntry data = 164 new DatabaseEntry(new byte[100]); 165 try { 166 assertTrue(db.put(txn, key, data) == 167 OperationStatus.SUCCESS); 168 } catch (DatabaseException DE) { 169 fail("unexpected DatabaseException"); 170 break; 171 } 172 try { 173 FileManager.IO_EXCEPTION_TESTING = true; 174 txn.commit(); 175 fail("expected DatabaseException"); 176 } catch (DatabaseException DE) { 177 } 178 FileManager.IO_EXCEPTION_TESTING = false; 179 txn = env.beginTransaction(null, null); 180 } 181 182 FileManager.IO_EXCEPTION_TESTING = false; 183 try { 184 env.checkpoint(chkConf); 185 } catch (DatabaseException DE) { 186 DE.printStackTrace(); 187 fail("unexpected DatabaseException"); 188 } 189 190 EnvironmentStats stats = env.getStats(null); 191 assertTrue((stats.getNFullINFlush() + 192 stats.getNFullBINFlush()) > 0); 193 long lastCheckpointLsn = stats.getLastCheckpointStart(); 194 195 try { 196 txn.commit(); 197 } catch (DatabaseException DE) { 198 fail("unexpected DatabaseException"); 199 } 200 201 FileReader reader = new FileReader 202 (DbInternal.envGetEnvironmentImpl(env), 203 4096, true, 0, null, DbLsn.NULL_LSN, DbLsn.NULL_LSN) { 204 protected boolean processEntry(ByteBuffer entryBuffer) 205 throws DatabaseException { 206 207 entryBuffer.position(entryBuffer.position() + 208 currentEntrySize); 209 return true; 210 } 211 }; 212 213 while (reader.readNextEntry()) { 214 } 215 } catch (Throwable E) { 216 E.printStackTrace(); 217 } 218 } 219 220 public void testLogBufferOverflowAbortNoDupes() 221 throws Exception { 222 223 doLogBufferOverflowTest(false, false); 224 } 225 226 public void testLogBufferOverflowCommitNoDupes() 227 throws Exception { 228 229 doLogBufferOverflowTest(true, false); 230 } 231 232 public void testLogBufferOverflowAbortDupes() 233 throws Exception { 234 235 doLogBufferOverflowTest(false, true); 236 } 237 238 public void testLogBufferOverflowCommitDupes() 239 throws Exception { 240 241 doLogBufferOverflowTest(true, true); 242 } 243 244 private void doLogBufferOverflowTest(boolean abort, boolean dupes) 245 throws Exception { 246 247 try { 248 EnvironmentConfig envConfig = TestUtils.initEnvConfig(); 249 envConfig.setTransactional(true); 250 envConfig.setAllowCreate(true); 251 envConfig.setCacheSize(100000); 252 envConfig.setConfigParam("java.util.logging.level", "OFF"); 253 env = new Environment(envHome, envConfig); 254 255 String databaseName = "ioexceptiondb"; 256 DatabaseConfig dbConfig = new DatabaseConfig(); 257 dbConfig.setAllowCreate(true); 258 dbConfig.setSortedDuplicates(true); 259 dbConfig.setTransactional(true); 260 db = env.openDatabase(null, databaseName, dbConfig); 261 262 Transaction txn = env.beginTransaction(null, null); 263 DatabaseEntry oneKey = 264 (dupes ? 265 new DatabaseEntry("2".getBytes()) : 266 new DatabaseEntry("1".getBytes())); 267 DatabaseEntry oneData = 268 new DatabaseEntry(new byte[10]); 269 DatabaseEntry twoKey = 270 new DatabaseEntry("2".getBytes()); 271 DatabaseEntry twoData = 272 new DatabaseEntry(new byte[100000]); 273 if (dupes) { 274 DatabaseEntry temp = oneKey; 275 oneKey = oneData; 276 oneData = temp; 277 temp = twoKey; 278 twoKey = twoData; 279 twoData = temp; 280 } 281 282 try { 283 assertTrue(db.put(txn, oneKey, oneData) == 284 OperationStatus.SUCCESS); 285 db.put(txn, twoKey, twoData); 286 } catch (DatabaseException DE) { 287 fail("unexpected DatabaseException"); 288 } 289 290 291 try { 292 assertTrue(db.get(txn, oneKey, oneData, null) == 293 OperationStatus.SUCCESS); 294 assertTrue(oneData.getData().length == (dupes ? 1 : 10)); 295 } catch (DatabaseException DE) { 296 fail("unexpected DatabaseException"); 297 } 298 299 try { 300 assertTrue(db.get(txn, twoKey, twoData, null) == 301 OperationStatus.SUCCESS); 302 } catch (DatabaseException DE) { 303 fail("unexpected DatabaseException"); 304 } 305 306 try { 307 if (abort) { 308 txn.abort(); 309 } else { 310 txn.commit(); 311 } 312 } catch (DatabaseException DE) { 313 fail("unexpected DatabaseException"); 314 } 315 316 317 try { 318 assertTrue(db.get(null, oneKey, oneData, null) == 319 (abort ? 320 OperationStatus.NOTFOUND : 321 OperationStatus.SUCCESS)); 322 assertTrue(oneData.getData().length == (dupes ? 1 : 10)); 323 } catch (DatabaseException DE) { 324 fail("unexpected DatabaseException"); 325 } 326 327 try { 328 assertTrue(db.get(null, twoKey, twoData, null) == 329 (abort ? 330 OperationStatus.NOTFOUND : 331 OperationStatus.SUCCESS)); 332 } catch (DatabaseException DE) { 333 fail("unexpected DatabaseException"); 334 } 335 336 } catch (Exception E) { 337 E.printStackTrace(); 338 } 339 } 340 341 public void testPutTransactionalWithIOException() 342 throws Throwable { 343 344 try { 345 createDatabase(100000, 0); 346 347 Transaction txn = env.beginTransaction(null, null); 348 int keyInt = 0; 349 String keyStr; 350 FileManager.IO_EXCEPTION_TESTING = true; 351 352 353 while (true) { 354 keyStr = Integer.toString(++keyInt); 355 DatabaseEntry key = new DatabaseEntry(keyStr.getBytes()); 356 DatabaseEntry data = 357 new DatabaseEntry(("d" + keyStr).getBytes()); 358 try { 359 assertTrue(db.put(txn, key, data) == 360 OperationStatus.SUCCESS); 361 } catch (DatabaseException DE) { 362 break; 363 } 364 } 365 366 367 try { 368 db.put(txn, 369 new DatabaseEntry("shouldFail".getBytes()), 370 new DatabaseEntry("shouldFailD".getBytes())); 371 fail("expected DatabaseException"); 372 } catch (DatabaseException DE) { 373 } 375 FileManager.IO_EXCEPTION_TESTING = false; 376 377 378 try { 379 db.put(txn, 380 new DatabaseEntry("shouldNotFail".getBytes()), 381 new DatabaseEntry("shouldNotFailD".getBytes())); 382 } catch (DatabaseException DE) { 383 fail("unexpected DatabaseException"); 384 } 385 txn.commit(); 386 387 DatabaseEntry data = new DatabaseEntry(); 388 assertTrue(db.get(null, 389 new DatabaseEntry("shouldNotFail".getBytes()), 390 data, 391 null) == OperationStatus.SUCCESS); 392 assertTrue(new String (data.getData()).equals("shouldNotFailD")); 393 394 assertTrue(db.get(null, 395 new DatabaseEntry("shouldFail".getBytes()), 396 data, 397 null) == OperationStatus.NOTFOUND); 398 399 assertTrue(db.get(null, 400 new DatabaseEntry("shouldFail".getBytes()), 401 data, 402 null) == OperationStatus.NOTFOUND); 403 404 assertTrue(db.get(null, 405 new DatabaseEntry(keyStr.getBytes()), 406 data, 407 null) == OperationStatus.NOTFOUND); 408 409 for (int i = --keyInt; i > 0; i--) { 410 keyStr = Integer.toString(i); 411 assertTrue(db.get(null, 412 new DatabaseEntry(keyStr.getBytes()), 413 data, 414 null) == OperationStatus.SUCCESS); 415 assertTrue(new String (data.getData()).equals("d" + keyStr)); 416 } 417 418 } catch (Throwable T) { 419 T.printStackTrace(); 420 } 421 } 422 423 private void doIOExceptionTest(boolean doRecovery) 424 throws Throwable { 425 426 Transaction txn = null; 427 createDatabase(0, 0); 428 writeAndVerify(null, false, "k1", "d1", doRecovery); 429 writeAndVerify(null, true, "k2", "d2", doRecovery); 430 writeAndVerify(null, false, "k3", "d3", doRecovery); 431 432 txn = env.beginTransaction(null, null); 433 writeAndVerify(txn, false, "k4", "d4", false); 434 txn.abort(); 435 verify(null, true, "k4", doRecovery); 436 verify(null, false, "k1", doRecovery); 437 verify(null, false, "k3", doRecovery); 438 439 txn = env.beginTransaction(null, null); 440 writeAndVerify(txn, false, "k4", "d4", false); 441 txn.commit(); 442 verify(null, false, "k4", doRecovery); 443 444 txn = env.beginTransaction(null, null); 445 writeAndVerify(txn, true, "k5", "d5", false); 446 447 writeAndVerify(txn, false, "k5a", "d5a", false); 448 txn.abort(); 449 verify(null, true, "k5", doRecovery); 450 verify(null, true, "k5a", doRecovery); 451 452 txn = env.beginTransaction(null, null); 453 writeAndVerify(txn, false, "k6", "d6", false); 454 writeAndVerify(txn, true, "k6a", "d6a", false); 455 456 FileManager.IO_EXCEPTION_TESTING = true; 457 try { 458 txn.commit(); 459 fail("expected DatabaseException"); 460 } catch (DatabaseException DE) { 461 } 462 verify(null, true, "k6", doRecovery); 463 verify(null, true, "k6a", doRecovery); 464 465 txn = env.beginTransaction(null, null); 466 writeAndVerify(txn, false, "k6", "d6", false); 467 writeAndVerify(txn, true, "k6a", "d6a", false); 468 writeAndVerify(txn, false, "k6b", "d6b", false); 469 470 try { 471 txn.commit(); 472 } catch (DatabaseException DE) { 473 fail("expected success"); 474 } 475 476 480 verify(null, false, "k6", doRecovery); 481 verify(null, false, "k6a", doRecovery); 482 verify(null, false, "k6b", doRecovery); 483 } 484 485 private void writeAndVerify(Transaction txn, 486 boolean throwIOException, 487 String keyString, 488 String dataString, 489 boolean doRecovery) 490 throws DatabaseException { 491 492 DatabaseEntry key = new DatabaseEntry(keyString.getBytes()); 494 DatabaseEntry data = new DatabaseEntry(dataString.getBytes()); 495 FileManager.IO_EXCEPTION_TESTING = throwIOException; 496 try { 497 assertTrue(db.put(txn, key, data) == OperationStatus.SUCCESS); 498 499 504 if (throwIOException && txn == null) { 505 fail("didn't catch DatabaseException."); 506 } 507 } catch (DatabaseException DE) { 508 if (!throwIOException) { 509 fail("caught DatabaseException."); 510 } 511 } 512 verify(txn, throwIOException, keyString, doRecovery); 513 } 514 515 private void verify(Transaction txn, 516 boolean expectFailure, 517 String keyString, 518 boolean doRecovery) 519 throws DatabaseException { 520 521 if (doRecovery) { 522 db.close(); 523 forceCloseEnvOnly(); 524 createDatabase(0, 0); 525 } 526 DatabaseEntry key = new DatabaseEntry(keyString.getBytes()); 527 DatabaseEntry returnedData = new DatabaseEntry(); 528 OperationStatus status = 529 db.get(txn, 530 key, 531 returnedData, 532 LockMode.DEFAULT); 533 assertTrue(status == ((expectFailure && txn == null) ? 535 OperationStatus.NOTFOUND : 536 OperationStatus.SUCCESS)); 537 } 538 539 private void createDatabase(long cacheSize, long maxFileSize) 540 throws DatabaseException { 541 542 EnvironmentConfig envConfig = TestUtils.initEnvConfig(); 543 envConfig.setTransactional(true); 544 envConfig.setAllowCreate(true); 545 envConfig.setConfigParam 546 (EnvironmentParams.NUM_LOG_BUFFERS.getName(), "2"); 547 envConfig.setConfigParam 548 (EnvironmentParams.LOG_MEM_SIZE.getName(), 549 EnvironmentParams.LOG_MEM_SIZE_MIN_STRING); 550 if (maxFileSize != 0) { 551 DbInternal.disableParameterValidation(envConfig); 552 envConfig.setConfigParam 553 (EnvironmentParams.LOG_FILE_MAX.getName(), "" + maxFileSize); 554 } 555 if (cacheSize != 0) { 556 envConfig.setCacheSize(cacheSize); 557 envConfig.setConfigParam("java.util.logging.level", "OFF"); 558 } 559 env = new Environment(envHome, envConfig); 560 561 String databaseName = "ioexceptiondb"; 562 DatabaseConfig dbConfig = new DatabaseConfig(); 563 dbConfig.setAllowCreate(true); 564 dbConfig.setSortedDuplicates(true); 565 dbConfig.setTransactional(true); 566 db = env.openDatabase(null, databaseName, dbConfig); 567 } 568 569 570 private void forceCloseEnvOnly() 571 throws DatabaseException { 572 573 574 try { 575 DbInternal.envGetEnvironmentImpl(env).close(false); 576 } catch (DatabaseException DE) { 577 if (!FileManager.IO_EXCEPTION_TESTING) { 578 throw DE; 579 } else { 580 581 } 582 } 583 env = null; 584 } 585 } 586 | Popular Tags |