1 8 9 package com.sleepycat.je.util; 10 11 import java.io.File ; 12 import java.io.FileInputStream ; 13 import java.io.FileOutputStream ; 14 import java.io.IOException ; 15 import java.nio.channels.FileChannel ; 16 17 import junit.framework.TestCase; 18 19 import com.sleepycat.bind.tuple.IntegerBinding; 20 import com.sleepycat.je.CheckpointConfig; 21 import com.sleepycat.je.Cursor; 22 import com.sleepycat.je.Database; 23 import com.sleepycat.je.DatabaseConfig; 24 import com.sleepycat.je.DatabaseEntry; 25 import com.sleepycat.je.DatabaseException; 26 import com.sleepycat.je.DbInternal; 27 import com.sleepycat.je.Environment; 28 import com.sleepycat.je.EnvironmentConfig; 29 import com.sleepycat.je.EnvironmentStats; 30 import com.sleepycat.je.LockMode; 31 import com.sleepycat.je.OperationStatus; 32 import com.sleepycat.je.StatsConfig; 33 import com.sleepycat.je.config.EnvironmentParams; 34 import com.sleepycat.je.dbi.EnvironmentImpl; 35 import com.sleepycat.je.log.FileManager; 36 import com.sleepycat.je.utilint.DbLsn; 37 38 public class DbBackupTest extends TestCase { 39 40 private static StatsConfig CLEAR_CONFIG = new StatsConfig(); 41 static { 42 CLEAR_CONFIG.setClear(true); 43 } 44 45 private static CheckpointConfig FORCE_CONFIG = new CheckpointConfig(); 46 static { 47 FORCE_CONFIG.setForce(true); 48 } 49 50 private static final String SAVE1 = "save1"; 51 private static final String SAVE2 = "save2"; 52 private static final String SAVE3 = "save3"; 53 private static final int NUM_RECS = 50; 54 55 private File envHome; 56 private Environment env; 57 private FileManager fileManager; 58 59 public DbBackupTest() { 60 envHome = new File (System.getProperty(TestUtils.DEST_DIR)); 61 } 62 63 public void setUp() 64 throws IOException { 65 66 TestUtils.removeLogFiles("Setup", envHome, false); 67 deleteSaveDir(SAVE1); 68 deleteSaveDir(SAVE2); 69 deleteSaveDir(SAVE3); 70 } 71 72 public void tearDown() 73 throws Exception { 74 75 TestUtils.removeLogFiles("TearDown", envHome, false); 76 deleteSaveDir(SAVE1); 77 deleteSaveDir(SAVE2); 78 deleteSaveDir(SAVE3); 79 } 80 81 84 public void testBackupVsCleaning() 85 throws Throwable { 86 87 env = createEnv(false, envHome); 88 EnvironmentImpl envImpl = DbInternal.envGetEnvironmentImpl(env); 89 fileManager = envImpl.getFileManager(); 90 91 try { 92 93 97 growFiles("db1", env, 8); 98 99 100 DbBackup backupHelper = new DbBackup(env); 101 backupHelper.startBackup(); 102 103 long lastFileNum = backupHelper.getLastFileInBackupSet(); 104 long checkLastFileNum = lastFileNum; 105 106 107 saveFiles(backupHelper, -1, lastFileNum, SAVE1); 108 109 113 batchClean(0); 114 long newLastFileNum = (fileManager.getLastFileNum()).longValue(); 115 assertTrue(checkLastFileNum < newLastFileNum); 116 checkLastFileNum = newLastFileNum; 117 118 119 saveFiles(backupHelper, -1, lastFileNum, SAVE2); 120 121 122 growFiles("db2", env, 8); 123 124 128 batchClean(0); 129 newLastFileNum = fileManager.getLastFileNum().longValue(); 130 assertTrue(checkLastFileNum < newLastFileNum); 131 checkLastFileNum = newLastFileNum; 132 133 134 saveFiles(backupHelper, -1, lastFileNum, SAVE3); 135 136 137 long lastFile = backupHelper.getLastFileInBackupSet(); 138 String [] backupSet = backupHelper.getLogFilesInBackupSet(); 139 assertEquals((lastFile + 1), backupSet.length); 140 141 142 backupHelper.endBackup(); 143 144 147 long numCleaned = batchClean(100); 148 assertTrue(numCleaned > 5); 149 env.close(); 150 env = null; 151 152 153 TestUtils.removeLogFiles("Verify", envHome, false); 154 verifyDb1(SAVE1, true); 155 TestUtils.removeLogFiles("Verify", envHome, false); 156 verifyDb1(SAVE2, true); 157 TestUtils.removeLogFiles("Verify", envHome, false); 158 verifyDb1(SAVE3, true); 159 } finally { 160 if (env != null) { 161 env.close(); 162 } 163 } 164 } 165 166 169 public void testIncrementalBackup() 170 throws Throwable { 171 172 env = createEnv(false, envHome); 173 EnvironmentImpl envImpl = DbInternal.envGetEnvironmentImpl(env); 174 fileManager = envImpl.getFileManager(); 175 176 try { 177 178 182 growFiles("db1", env, 8); 183 184 185 DbBackup backupHelper = new DbBackup(env); 186 backupHelper.startBackup(); 187 long b1LastFile = backupHelper.getLastFileInBackupSet(); 188 saveFiles(backupHelper, -1, b1LastFile, SAVE1); 189 String lastName = fileManager.getFullFileName(b1LastFile, 190 FileManager.JE_SUFFIX); 191 File f = new File (lastName); 192 long savedLength = f.length(); 193 backupHelper.endBackup(); 194 195 199 growFiles("db2", env, 8); 200 checkFileLen(b1LastFile, savedLength); 201 202 203 backupHelper.startBackup(); 204 long b2LastFile = backupHelper.getLastFileInBackupSet(); 205 saveFiles(backupHelper, b1LastFile, b2LastFile, SAVE2); 206 backupHelper.endBackup(); 207 208 env.close(); 209 env = null; 210 211 212 TestUtils.removeLogFiles("Verify", envHome, false); 213 verifyDb1(SAVE1, false); 214 TestUtils.removeLogFiles("Verify", envHome, false); 215 verifyBothDbs(SAVE1, SAVE2); 216 } finally { 217 if (env != null) { 218 env.close(); 219 } 220 } 221 } 222 223 public void testBadUsage() 224 throws Exception { 225 226 Environment env = createEnv(false, envHome); 227 228 try { 229 DbBackup backup = new DbBackup(env); 230 231 232 try { 233 backup.endBackup(); 234 fail("should fail"); 235 } catch (DatabaseException expected) { 236 } 237 238 239 backup.startBackup(); 240 try { 241 backup.startBackup(); 242 fail("should fail"); 243 } catch (DatabaseException expected) { 244 } 245 246 250 backup.endBackup(); 251 252 try { 253 backup.getLastFileInBackupSet(); 254 fail("should fail"); 255 } catch (DatabaseException expected) { 256 } 257 258 try { 259 backup.getLogFilesInBackupSet(); 260 fail("should fail"); 261 } catch (DatabaseException expected) { 262 } 263 264 try { 265 backup.getLogFilesInBackupSet(0); 266 fail("should fail"); 267 } catch (DatabaseException expected) { 268 } 269 } finally { 270 env.close(); 271 } 272 } 273 274 279 public void xtestReadOnly() 280 throws Exception { 281 282 283 Environment env = createEnv(true, envHome); 284 285 try { 286 DbBackup backup = new DbBackup(env); 287 fail("Should fail because env is read/only."); 288 } catch (DatabaseException expected) { 289 } 290 291 env.close(); 292 293 298 File tempEnvDir = new File (envHome, SAVE1); 299 assertTrue(tempEnvDir.mkdirs()); 300 env = createEnv(false, tempEnvDir); 301 growFiles("db1", env, 8); 302 env.close(); 303 305 env = createEnv(true, tempEnvDir); 306 307 DbBackup backupHelper = new DbBackup(env); 308 backupHelper.startBackup(); 309 310 FileManager fileManager = 311 DbInternal.envGetEnvironmentImpl(env).getFileManager(); 312 long lastFile = fileManager.getLastFileNum().longValue(); 313 assertEquals(lastFile, backupHelper.getLastFileInBackupSet()); 314 315 backupHelper.endBackup(); 316 env.close(); 317 assertTrue(tempEnvDir.delete()); 318 } 319 320 private Environment createEnv(boolean readOnly, File envDir) 321 throws DatabaseException { 322 323 EnvironmentConfig envConfig = TestUtils.initEnvConfig(); 324 DbInternal.disableParameterValidation(envConfig); 325 envConfig.setAllowCreate(true); 326 envConfig.setReadOnly(readOnly); 327 envConfig.setConfigParam(EnvironmentParams.LOG_FILE_MAX.getName(), 328 "400"); 329 envConfig.setConfigParam(EnvironmentParams.ENV_RUN_CLEANER.getName(), 330 "false"); 331 332 Environment env = new Environment(envDir, envConfig); 333 334 return env; 335 } 336 337 private long growFiles(String dbName, 338 Environment env, 339 int minNumFiles) 340 throws DatabaseException { 341 342 DatabaseConfig dbConfig = new DatabaseConfig(); 343 dbConfig.setAllowCreate(true); 344 Database db = env.openDatabase(null, dbName, dbConfig); 345 FileManager fileManager = 346 DbInternal.envGetEnvironmentImpl(env).getFileManager(); 347 long startLastFileNum = 348 DbLsn.getFileNumber(fileManager.getLastUsedLsn()); 349 350 DatabaseEntry key = new DatabaseEntry(); 351 DatabaseEntry data = new DatabaseEntry(); 352 353 for (int i = 0; i < NUM_RECS; i++) { 354 IntegerBinding.intToEntry(i, key); 355 IntegerBinding.intToEntry(i, data); 356 assertEquals(OperationStatus.SUCCESS, db.put(null, key, data)); 357 } 358 359 for (int i = 0; i < NUM_RECS; i++) { 360 IntegerBinding.intToEntry(i, key); 361 IntegerBinding.intToEntry(i+5, data); 362 assertEquals(OperationStatus.SUCCESS, db.put(null, key, data)); 363 } 364 365 db.close(); 366 367 long endLastFileNum = 368 DbLsn.getFileNumber(fileManager.getLastUsedLsn()); 369 assertTrue((endLastFileNum - 370 startLastFileNum) >= minNumFiles); 371 return endLastFileNum; 372 } 373 374 private int batchClean(int expectedDeletions) 375 throws DatabaseException { 376 377 EnvironmentStats stats = env.getStats(CLEAR_CONFIG); 378 while (env.cleanLog() > 0) { 379 } 380 env.checkpoint(FORCE_CONFIG); 381 stats = env.getStats(CLEAR_CONFIG); 382 assertTrue(stats.getNCleanerDeletions() <= expectedDeletions); 383 384 return stats.getNCleanerDeletions(); 385 } 386 387 private void saveFiles(DbBackup backupHelper, 388 long lastFileFromPrevBackup, 389 long lastFileNum, 390 String saveDirName) 391 throws IOException , DatabaseException { 392 393 394 String [] fileList = 395 backupHelper.getLogFilesInBackupSet(lastFileFromPrevBackup); 396 assertEquals(lastFileNum, 397 fileManager.getNumFromName(fileList[fileList.length-1]). 398 longValue()); 399 400 401 File saveDir = new File (envHome, saveDirName); 402 assertTrue(saveDir.mkdir()); 403 copyFiles(envHome, saveDir, fileList); 404 } 405 406 private void copyFiles(File sourceDir, File destDir, String [] fileList) 407 throws DatabaseException { 408 409 try { 410 for (int i = 0; i < fileList.length; i++) { 411 File source = new File (sourceDir, fileList[i]); 412 FileChannel sourceChannel = 413 new FileInputStream (source).getChannel(); 414 File save = new File (destDir, fileList[i]); 415 FileChannel saveChannel = 416 new FileOutputStream (save).getChannel(); 417 418 saveChannel.transferFrom(sourceChannel, 0, 419 sourceChannel.size()); 420 421 sourceChannel.close(); 423 saveChannel.close(); 424 } 425 } catch (IOException e) { 426 throw new DatabaseException(e); 427 } 428 } 429 430 433 private void deleteSaveDir(String saveDirName) 434 throws IOException { 435 436 File saveDir = new File (envHome, saveDirName); 437 if (saveDir.exists()) { 438 String [] savedFiles = saveDir.list(); 439 if (savedFiles != null) { 440 for (int i = 0; i < savedFiles.length; i++) { 441 File f = new File (saveDir, savedFiles[i]); 442 assertTrue(f.delete()); 443 } 444 assertTrue(saveDir.delete()); 445 } 446 } 447 } 448 449 452 private void verifyDb1(String saveDirName, boolean rename) 453 throws DatabaseException { 454 455 File saveDir = new File (envHome, saveDirName); 456 String [] savedFiles = saveDir.list(); 457 if (rename){ 458 for (int i = 0; i < savedFiles.length; i++) { 459 File saved = new File (saveDir, savedFiles[i]); 460 File dest = new File (envHome, savedFiles[i]); 461 assertTrue(saved.renameTo(dest)); 462 } 463 } else { 464 465 copyFiles(saveDir, envHome, savedFiles); 466 } 467 env = createEnv(false, envHome); 468 try { 469 checkDb("db1"); 470 471 472 DatabaseConfig dbConfig = new DatabaseConfig(); 473 try { 474 Database db = env.openDatabase(null, "db2", dbConfig); 475 fail("db2 should not exist"); 476 } catch (DatabaseException expected) { 477 } 478 479 } finally { 480 env.close(); 481 env = null; 482 } 483 } 484 485 488 private void verifyBothDbs(String saveDirName1, String saveDirName2) 489 throws DatabaseException { 490 491 File saveDir = new File (envHome, saveDirName1); 492 String [] savedFiles = saveDir.list(); 493 for (int i = 0; i < savedFiles.length; i++) { 494 File saved = new File (saveDir, savedFiles[i]); 495 File dest = new File (envHome, savedFiles[i]); 496 assertTrue(saved.renameTo(dest)); 497 } 498 499 saveDir = new File (envHome, saveDirName2); 500 savedFiles = saveDir.list(); 501 for (int i = 0; i < savedFiles.length; i++) { 502 File saved = new File (saveDir, savedFiles[i]); 503 File dest = new File (envHome, savedFiles[i]); 504 assertTrue(saved.renameTo(dest)); 505 } 506 507 env = createEnv(false, envHome); 508 try { 509 checkDb("db1"); 510 checkDb("db2"); 511 } finally { 512 env.close(); 513 env = null; 514 } 515 } 516 517 private void checkDb(String dbName) 518 throws DatabaseException { 519 520 DatabaseConfig dbConfig = new DatabaseConfig(); 521 Database db = env.openDatabase(null, dbName, dbConfig); 522 Cursor c = null; 523 try { 524 DatabaseEntry key = new DatabaseEntry(); 525 DatabaseEntry data = new DatabaseEntry(); 526 c = db.openCursor(null, null); 527 528 for (int i = 0; i < NUM_RECS; i++) { 529 assertEquals(OperationStatus.SUCCESS, 530 c.getNext(key, data, LockMode.DEFAULT)); 531 assertEquals(i, IntegerBinding.entryToInt(key)); 532 assertEquals(i + 5, IntegerBinding.entryToInt(data)); 533 } 534 assertEquals(OperationStatus.NOTFOUND, 535 c.getNext(key, data, LockMode.DEFAULT)); 536 } finally { 537 if (c != null) 538 c.close(); 539 db.close(); 540 } 541 } 542 543 private void checkFileLen(long fileNum, long length) 544 throws IOException { 545 String fileName = fileManager.getFullFileName(fileNum, 546 FileManager.JE_SUFFIX); 547 File f = new File (fileName); 548 assertEquals(length, f.length()); 549 } 550 } 551 552 553 | Popular Tags |