1 8 9 package com.sleepycat.je.recovery; 10 11 import java.io.File ; 12 import java.io.FileInputStream ; 13 import java.io.FileOutputStream ; 14 import java.io.IOException ; 15 import java.io.InputStream ; 16 import java.io.OutputStream ; 17 import java.util.ArrayList ; 18 import java.util.HashMap ; 19 import java.util.HashSet ; 20 import java.util.Iterator ; 21 import java.util.List ; 22 import java.util.Map ; 23 import java.util.Set ; 24 import java.util.logging.Level ; 25 26 import junit.framework.TestCase; 27 28 import com.sleepycat.bind.tuple.IntegerBinding; 29 import com.sleepycat.je.Cursor; 30 import com.sleepycat.je.Database; 31 import com.sleepycat.je.DatabaseConfig; 32 import com.sleepycat.je.DatabaseEntry; 33 import com.sleepycat.je.DatabaseException; 34 import com.sleepycat.je.DbInternal; 35 import com.sleepycat.je.Environment; 36 import com.sleepycat.je.EnvironmentConfig; 37 import com.sleepycat.je.OperationStatus; 38 import com.sleepycat.je.VerifyConfig; 39 import com.sleepycat.je.cleaner.VerifyUtils; 40 import com.sleepycat.je.config.EnvironmentParams; 41 import com.sleepycat.je.dbi.EnvironmentImpl; 42 import com.sleepycat.je.log.FileManager; 43 import com.sleepycat.je.recovery.stepwise.EntryTrackerReader; 44 import com.sleepycat.je.recovery.stepwise.LogEntryInfo; 45 import com.sleepycat.je.recovery.stepwise.TestData; 46 import com.sleepycat.je.util.TestUtils; 47 import com.sleepycat.je.utilint.CmdUtil; 48 import com.sleepycat.je.utilint.DbLsn; 49 import com.sleepycat.je.utilint.Tracer; 50 51 public class CheckBase extends TestCase { 52 53 private static final boolean DEBUG = false; 54 private HashSet expected; 55 private Set found; 56 57 File envHome; 58 Environment env; 59 60 private List logDescription; 61 private long stepwiseStartLsn; 62 63 private boolean checkLsns = true; 64 65 public CheckBase() { 66 envHome = new File (System.getProperty(TestUtils.DEST_DIR)); 67 } 68 69 public void setUp() 70 throws IOException { 71 72 TestUtils.removeLogFiles("Setup", envHome, false); 73 TestUtils.removeFiles("Setup", envHome, ".jdb_save"); 74 } 75 76 public void tearDown() { 77 if (env != null) { 78 try { 79 env.close(); 80 env = null; 81 } catch (Exception ignore) { 82 } 83 } 84 85 try { 86 TestUtils.removeLogFiles("TearDown", envHome, false); 87 TestUtils.removeFiles("TearDown", envHome, ".jdb_save"); 88 } catch (Exception ignore) { 89 } 90 } 91 92 97 protected void testOneCase(String dbName, 98 EnvironmentConfig startEnvConfig, 99 DatabaseConfig startDbConfig, 100 TestGenerator testGen, 101 EnvironmentConfig validateEnvConfig, 102 DatabaseConfig validateDbConfig) 103 throws Throwable { 104 105 try { 106 107 env = new Environment(envHome, startEnvConfig); 108 Database db = env.openDatabase(null, dbName, startDbConfig); 109 110 111 testGen.generateData(db); 112 113 114 loadExpectedData(db); 115 116 117 if (checkLsns) { 118 VerifyUtils.checkLsns(db); 119 } 120 121 122 db.close(); 123 DbInternal.envGetEnvironmentImpl(env).close(false); 124 env = null; 125 126 if (testGen.generateLogDescription) { 127 makeLogDescription(); 128 } 129 130 tryRecovery(validateEnvConfig, 131 validateDbConfig, 132 dbName, 133 expected); 134 } catch (Throwable t) { 135 136 t.printStackTrace(); 137 throw t; 138 } 139 } 140 141 142 private void tryRecovery(EnvironmentConfig validateEnvConfig, 143 DatabaseConfig validateDbConfig, 144 String dbName, 145 HashSet useExpected) 146 throws DatabaseException { 147 148 recoverAndLoadData(validateEnvConfig, 149 validateDbConfig, 150 dbName); 151 152 153 if (useExpected == null) { 154 useExpected = expected; 155 } 156 validate(useExpected); 157 158 159 recoverAndLoadData(validateEnvConfig, 160 validateDbConfig, 161 dbName); 162 163 validate(useExpected); 164 } 165 166 void setCheckLsns(boolean checkLsns) { 167 this.checkLsns = checkLsns; 168 } 169 170 174 void setStepwiseStart() { 175 176 181 Tracer.trace(Level.SEVERE, DbInternal.envGetEnvironmentImpl(env), 182 "StepwiseStart"); 183 FileManager fileManager = 184 DbInternal.envGetEnvironmentImpl(env).getFileManager(); 185 stepwiseStartLsn = fileManager.getLastUsedLsn(); 186 } 187 188 void stepwiseLoop(String dbName, 189 EnvironmentConfig validateEnvConfig, 190 DatabaseConfig validateDbConfig, 191 HashSet useExpected, 192 int startingIteration) 193 throws DatabaseException, IOException { 194 195 assertTrue(logDescription.size() > 0); 196 saveLogFiles(envHome); 197 198 199 Map newUncommittedRecords = new HashMap (); 200 Map deletedUncommittedRecords = new HashMap (); 201 202 203 String status = null; 204 try { 205 206 210 DatabaseEntry keyEntry = new DatabaseEntry(); 211 DatabaseEntry dataEntry = new DatabaseEntry(); 212 for (int i = startingIteration; i < logDescription.size(); i++ ) { 213 214 215 LogEntryInfo info = (LogEntryInfo) logDescription.get(i); 216 long lsn = info.getLsn(); 217 218 if (lsn == 0) { 219 continue; 220 } 221 222 status = "Iteration " + i + " out of " + 223 logDescription.size() + " truncate at 0x" + 224 DbLsn.getNoFormatString(lsn); 225 226 if (DEBUG) { 227 System.out.println(status); 228 } 229 230 231 resetLogFiles(envHome); 232 233 234 truncateAtOffset(envHome, lsn); 235 236 237 tryRecovery(validateEnvConfig, validateDbConfig, 238 dbName, useExpected); 239 240 241 info.updateExpectedSet(useExpected, newUncommittedRecords, 242 deletedUncommittedRecords); 243 } 244 } catch (Error e) { 245 System.err.println("Failure at step: " + status); 246 throw e; 247 } 248 } 249 250 protected void turnOffEnvDaemons(EnvironmentConfig envConfig) { 251 envConfig.setConfigParam(EnvironmentParams.ENV_RUN_CLEANER.getName(), 252 "false"); 253 envConfig.setConfigParam(EnvironmentParams. 254 ENV_RUN_CHECKPOINTER.getName(), 255 "false"); 256 envConfig.setConfigParam(EnvironmentParams.ENV_RUN_EVICTOR.getName(), 257 "false"); 258 envConfig.setConfigParam(EnvironmentParams. 259 ENV_RUN_INCOMPRESSOR.getName(), 260 "false"); 261 } 262 263 267 protected void recoverAndLoadData(EnvironmentConfig envConfig, 268 DatabaseConfig dbConfig, 269 String dbName) 270 throws DatabaseException { 271 272 env = new Environment(envHome, envConfig); 273 Database db = env.openDatabase(null, dbName, dbConfig); 274 275 276 if (checkLsns) { 277 VerifyUtils.checkLsns(db); 278 } 279 280 found = new HashSet (); 281 282 Cursor cursor = db.openCursor(null, null); 283 DatabaseEntry key = new DatabaseEntry(); 284 DatabaseEntry data = new DatabaseEntry(); 285 286 try { 287 while (cursor.getNext(key, data, null) == 288 OperationStatus.SUCCESS) { 289 TestData t = new TestData(key, data); 290 if (DEBUG) { 291 System.out.println("found k=" + 292 IntegerBinding.entryToInt(key) + 293 " d=" + 294 IntegerBinding.entryToInt(data)); 295 } 296 found.add(t); 297 } 298 } 299 finally { 300 cursor.close(); 301 } 302 303 db.close(); 304 305 assertTrue(env.verify(new VerifyConfig(), System.out)); 306 env.close(); 307 } 308 309 312 void validate(HashSet expected) 313 throws DatabaseException { 314 315 Set useExpected = (Set ) expected.clone(); 316 317 if (useExpected.size() != found.size()) { 318 System.err.println("expected---------"); 319 dumpHashSet(useExpected); 320 System.err.println("actual---------"); 321 dumpHashSet(found); 322 assertEquals("expected and found set sizes don't match" , 323 useExpected.size(), found.size()); 324 } 325 326 Iterator foundIter = found.iterator(); 327 while (foundIter.hasNext()) { 328 TestData t = (TestData) foundIter.next(); 329 assertTrue("Missing " + t + "from the expected set", 330 useExpected.remove(t)); 331 } 332 333 assertEquals("Expected has " + useExpected.size() + " items remaining", 334 0, useExpected.size()); 335 } 336 337 protected void putTestData(Database db, 338 DatabaseEntry key, 339 DatabaseEntry data) 340 throws DatabaseException { 341 342 assertEquals(OperationStatus.SUCCESS, db.put(null, key, data)); 343 } 344 345 private void loadExpectedData(Database db) 346 throws DatabaseException { 347 348 expected = new HashSet (); 349 350 Cursor cursor = db.openCursor(null, null); 351 DatabaseEntry key = new DatabaseEntry(); 352 DatabaseEntry data = new DatabaseEntry(); 353 354 try { 355 while (cursor.getNext(key, data, null) == 356 OperationStatus.SUCCESS) { 357 if (DEBUG) { 358 System.out.println("expect k=" + 359 IntegerBinding.entryToInt(key) + 360 " d=" + 361 IntegerBinding.entryToInt(data)); 362 } 363 TestData t = new TestData(key, data); 364 expected.add(t); 365 } 366 } 367 finally { 368 cursor.close(); 369 } 370 } 371 372 void dumpData(Database db) 373 throws DatabaseException { 374 375 Cursor cursor = db.openCursor(null, null); 376 DatabaseEntry key = new DatabaseEntry(); 377 DatabaseEntry data = new DatabaseEntry(); 378 int i = 0; 379 try { 380 while (cursor.getNext(key, data, null) == 381 OperationStatus.SUCCESS) { 382 TestData t = new TestData(key, data); 383 System.out.println(t); 384 i++; 385 } 386 } 387 finally { 388 cursor.close(); 389 } 390 System.out.println("scanned=" + i); 391 } 392 393 private void dumpHashSet(Set expected) { 394 Iterator iter = expected.iterator(); 395 System.err.println("size=" + expected.size()); 396 while (iter.hasNext()) { 397 System.err.println((TestData)iter.next()); 398 } 399 } 400 401 private void makeLogDescription() 402 throws DatabaseException { 403 404 EnvironmentImpl cmdEnvImpl = 405 CmdUtil.makeUtilityEnvironment(envHome, false); 406 logDescription = new ArrayList (); 407 408 try { 409 EntryTrackerReader reader = 410 new EntryTrackerReader(cmdEnvImpl, 411 stepwiseStartLsn, 412 logDescription); 413 while (reader.readNextEntry()) { 414 } 415 } catch (IOException e) { 416 throw new DatabaseException(e); 417 } finally { 418 cmdEnvImpl.close(); 419 } 420 421 if (DEBUG) { 422 Iterator iter = logDescription.iterator(); 423 while (iter.hasNext()) { 424 Object o = iter.next(); 425 LogEntryInfo entryInfo =(LogEntryInfo) o; 426 System.out.println(entryInfo); 427 } 428 } 429 } 430 431 434 private void truncateAtOffset(File envHome, long lsn) 435 throws DatabaseException, IOException { 436 437 EnvironmentImpl cmdEnvImpl = 438 CmdUtil.makeUtilityEnvironment(envHome, false); 439 440 cmdEnvImpl.getFileManager().truncateLog(DbLsn.getFileNumber(lsn), 441 DbLsn.getFileOffset(lsn)); 442 443 cmdEnvImpl.close(); 444 } 445 446 447 private void saveLogFiles(File envHome) 448 throws IOException { 449 450 String [] suffix = new String [] {".jdb"}; 451 String [] fileNames = FileManager.listFiles(envHome, suffix); 452 453 for (int i = 0; i < fileNames.length; i++) { 454 File src = new File (envHome, fileNames[i]); 455 File dst = new File (envHome, fileNames[i]+ "_save"); 456 copy(src, dst); 457 } 458 } 459 460 461 private void resetLogFiles(File envHome) 462 throws IOException { 463 String [] suffix = new String [] {".jdb_save"}; 464 String [] fileNames = FileManager.listFiles(envHome, suffix); 465 466 for (int i = 0; i < fileNames.length; i++) { 467 String srcName = fileNames[i]; 468 int end = srcName.indexOf("_save"); 469 String dstName = srcName.substring(0, end); 470 copy(new File (envHome, srcName), new File (envHome, dstName)); 471 } 472 } 473 474 private void copy(File src, File dst) 475 throws IOException { 476 477 InputStream in = new FileInputStream (src); 478 OutputStream out = new FileOutputStream (dst); 479 480 byte[] buf = new byte[1024]; 482 int len; 483 while ((len = in.read(buf)) > 0) { 484 out.write(buf, 0, len); 485 } 486 in.close(); 487 out.close(); 488 } 489 490 499 protected class TestGenerator { 500 501 502 boolean generateLogDescription; 503 504 508 public List operationList; 509 510 public TestGenerator() { 511 } 512 513 public TestGenerator(boolean generateLogDescription) { 514 this.generateLogDescription = generateLogDescription; 515 } 516 517 public TestGenerator(List operationList) { 518 this.operationList = operationList; 519 } 520 521 void generateData(Database db) 522 throws Exception { 523 } 524 } 525 } 526 | Popular Tags |