00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "fennel/common/CommonPreamble.h"
00025 #include "fennel/common/FileSystem.h"
00026 #include "fennel/test/SnapshotSegmentTestBase.h"
00027 #include "fennel/cache/PagePredicate.h"
00028 #include "fennel/txn/LogicalTxn.h"
00029 #include "fennel/txn/LogicalTxnLog.h"
00030 #include "fennel/segment/VersionedRandomAllocationSegment.h"
00031 #include "fennel/segment/SnapshotRandomAllocationSegment.h"
00032 #include "fennel/segment/SegPageBackupRestoreDevice.h"
00033 #include "fennel/db/Database.h"
00034
00035 #include <boost/test/test_tools.hpp>
00036
00037 using namespace fennel;
00038
00043 class BackupRestoreTest : virtual public SnapshotSegmentTestBase
00044 {
00045 struct TestNode : public StoredNode
00046 {
00047 static const MagicNumber MAGIC_NUMBER = 0xa496c71bff0d41bdLL;
00048
00049 uint x;
00050 };
00051
00052 typedef SegNodeLock<TestNode> TestPageLock;
00053
00054 SharedDatabase pDatabase;
00055 PageId persistentPageId;
00056
00057 void createSnapshotData();
00058 void executeSnapshotTxn(int i);
00059 void verifySnapshotData(uint x);
00060
00061 void testBackupRestore(bool isCompressed);
00062 void backup(
00063 std::string backupFileName,
00064 TxnId lowerBoundCsn,
00065 TxnId upperBoundCsn,
00066 bool isCompressed);
00067 void restore(
00068 std::string backupFileName,
00069 TxnId lowerBoundCsn,
00070 TxnId upperBoundCsn,
00071 bool isCompressed);
00072 std::string getCompressionProgram(bool isCompressed);
00073 void verifyData();
00074
00075 public:
00076 explicit BackupRestoreTest()
00077 {
00078 FENNEL_UNIT_TEST_CASE(BackupRestoreTest, testHeaderBackupRestore);
00079 FENNEL_UNIT_TEST_CASE(BackupRestoreTest, testBackupCleanup);
00080 FENNEL_UNIT_TEST_CASE(BackupRestoreTest, testBackupRestoreUncompressed);
00081 FENNEL_UNIT_TEST_CASE(BackupRestoreTest, testBackupRestoreCompressed);
00082 }
00083
00087 void testHeaderBackupRestore();
00088
00092 void testBackupCleanup();
00093
00097 void testBackupRestoreUncompressed();
00098
00102 void testBackupRestoreCompressed();
00103 };
00104
00105 void BackupRestoreTest::testBackupRestoreUncompressed()
00106 {
00107 testBackupRestore(false);
00108 }
00109
00110 void BackupRestoreTest::testBackupRestoreCompressed()
00111 {
00112 testBackupRestore(true);
00113 }
00114
00115 void BackupRestoreTest::createSnapshotData()
00116 {
00117
00118 pDatabase = Database::newDatabase(
00119 pCache,
00120 configMap,
00121 DeviceMode::createNew,
00122 shared_from_this());
00123
00124 SharedLogicalTxn pTxn = pDatabase->getTxnLog()->newLogicalTxn(pCache);
00125 SharedSegment pSegment =
00126 pDatabase->getSegmentFactory()->newSnapshotRandomAllocationSegment(
00127 pDatabase->getDataSegment(),
00128 pDatabase->getDataSegment(),
00129 pTxn->getTxnId());
00130 SnapshotRandomAllocationSegment *pSnapshotSegment =
00131 SegmentFactory::dynamicCast<SnapshotRandomAllocationSegment *>(
00132 pSegment);
00133 SegmentAccessor segmentAccessor(pSegment,pCache);
00134
00135 TestPageLock pageLock(segmentAccessor);
00136 persistentPageId = pageLock.allocatePage();
00137 pageLock.getNodeForWrite().x = 0;
00138 pageLock.unlock();
00139 pTxn->commit();
00140 pTxn = pDatabase->getTxnLog()->newLogicalTxn(pCache);
00141 pSnapshotSegment->commitChanges(pTxn->getTxnId());
00142 pSnapshotSegment->checkpoint(CHECKPOINT_FLUSH_ALL);
00143 pTxn->commit();
00144 pDatabase->checkpointImpl();
00145
00146
00147 executeSnapshotTxn(5);
00148 }
00149
00150 void BackupRestoreTest::testHeaderBackupRestore()
00151 {
00152 configMap.setStringParam(
00153 Database::paramDatabaseDir,".");
00154 configMap.setStringParam(
00155 "databaseInitSize","1000");
00156 configMap.setStringParam(
00157 "tempInitSize","1000");
00158 configMap.setStringParam(
00159 "databaseShadowLogInitSize","1000");
00160 configMap.setStringParam(
00161 "databaseTxnLogInitSize","1000");
00162 configMap.setStringParam(
00163 "forceTxns","true");
00164 configMap.setStringParam(
00165 "disableSnapshots","false");
00166
00167 CacheParams cacheParams;
00168 cacheParams.readConfig(configMap);
00169 pCache = Cache::newCache(cacheParams);
00170
00171
00172
00173
00174 createSnapshotData();
00175 pDatabase->checkpointImpl();
00176 verifySnapshotData(5);
00177
00178
00179 std::string fullBackup = "fullBackup.dat";
00180 FileSize dataDeviceSize;
00181 bool aborted = false;
00182 TxnId fullTxnId =
00183 pDatabase->initiateBackup(
00184 fullBackup,
00185 false,
00186 0,
00187 NULL_TXN_ID,
00188 "",
00189 dataDeviceSize,
00190 aborted);
00191 pDatabase->completeBackup(NULL_TXN_ID, fullTxnId, aborted);
00192
00193
00194 executeSnapshotTxn(10);
00195 verifySnapshotData(15);
00196
00197
00198 std::string incrBackup1 = "incrBackup1.dat";
00199 TxnId incrTxnId1 =
00200 pDatabase->initiateBackup(
00201 incrBackup1,
00202 true,
00203 0,
00204 fullTxnId,
00205 "",
00206 dataDeviceSize,
00207 aborted);
00208
00209
00210 uint nPagesBefore =
00211 pDatabase->getDataSegment()->getAllocatedSizeInPages();
00212 pDatabase->deallocateOldPages(incrTxnId1);
00213 uint nPagesAfter =
00214 pDatabase->getDataSegment()->getAllocatedSizeInPages();
00215 BOOST_REQUIRE(nPagesBefore == nPagesAfter);
00216
00217 pDatabase->completeBackup(fullTxnId, incrTxnId1, aborted);
00218
00219
00220 pDatabase->deallocateOldPages(incrTxnId1);
00221 nPagesAfter = pDatabase->getDataSegment()->getAllocatedSizeInPages();
00222 BOOST_REQUIRE(nPagesBefore > nPagesAfter);
00223
00224
00225 executeSnapshotTxn(20);
00226 verifySnapshotData(35);
00227
00228
00229 std::string incrBackup2 = "incrBackup2.dat";
00230 TxnId incrTxnId2 =
00231 pDatabase->initiateBackup(
00232 incrBackup2,
00233 true,
00234 4096,
00235 incrTxnId1,
00236 "",
00237 dataDeviceSize,
00238 aborted);
00239 pDatabase->completeBackup(incrTxnId1, incrTxnId2, aborted);
00240
00241
00242 pDatabase->restoreFromBackup(
00243 fullBackup,
00244 1002 * pCache->getPageSize(),
00245 "",
00246 NULL_TXN_ID,
00247 fullTxnId,
00248 aborted);
00249 verifySnapshotData(5);
00250
00251
00252 pDatabase->restoreFromBackup(
00253 incrBackup1,
00254 1002 * pCache->getPageSize(),
00255 "",
00256 fullTxnId,
00257 incrTxnId1,
00258 aborted);
00259 verifySnapshotData(15);
00260
00261
00262 pDatabase->restoreFromBackup(
00263 incrBackup2,
00264 1002 * pCache->getPageSize(),
00265 "",
00266 incrTxnId1,
00267 incrTxnId2,
00268 aborted);
00269 verifySnapshotData(35);
00270
00271 pDatabase.reset();
00272 }
00273
00274 void BackupRestoreTest::testBackupCleanup()
00275 {
00276 configMap.setStringParam(
00277 Database::paramDatabaseDir,".");
00278 configMap.setStringParam(
00279 "databaseInitSize","1000");
00280 configMap.setStringParam(
00281 "tempInitSize","1000");
00282 configMap.setStringParam(
00283 "databaseShadowLogInitSize","1000");
00284 configMap.setStringParam(
00285 "databaseTxnLogInitSize","1000");
00286 configMap.setStringParam(
00287 "forceTxns","true");
00288 configMap.setStringParam(
00289 "disableSnapshots","false");
00290
00291 CacheParams cacheParams;
00292 cacheParams.readConfig(configMap);
00293 pCache = Cache::newCache(cacheParams);
00294
00295
00296
00297
00298 createSnapshotData();
00299 pDatabase->checkpointImpl();
00300 verifySnapshotData(5);
00301
00302
00303 executeSnapshotTxn(10);
00304 verifySnapshotData(15);
00305
00306 std::string fullBackup = "fullBackup.dat";
00307
00308
00309
00310
00311
00312
00313
00314
00315 FileSystem::remove(fullBackup.c_str());
00316 FileSize spaceAvailable;
00317 FileSystem::getDiskFreeSpace(".", spaceAvailable);
00318 FileSize dataDeviceSize;
00319 bool aborted = false;
00320 try {
00321 pDatabase->initiateBackup(
00322 fullBackup,
00323 true,
00324 spaceAvailable * 1000,
00325 NULL_TXN_ID,
00326 "",
00327 dataDeviceSize,
00328 aborted);
00329 BOOST_FAIL("Out of space exception not returned");
00330 } catch (FennelExcn &ex) {
00331 std::string errMsg = ex.getMessage();
00332 if (errMsg.find("Insufficient space") != 0) {
00333 BOOST_FAIL("Wrong exception returned");
00334 }
00335 }
00336
00337
00338
00339 uint nPagesBefore =
00340 pDatabase->getDataSegment()->getAllocatedSizeInPages();
00341 pDatabase->deallocateOldPages(pDatabase->getLastCommittedTxnId());
00342 uint nPagesAfter =
00343 pDatabase->getDataSegment()->getAllocatedSizeInPages();
00344 BOOST_REQUIRE(nPagesBefore > nPagesAfter);
00345
00346
00347 executeSnapshotTxn(20);
00348 verifySnapshotData(35);
00349
00350
00351 pDatabase->initiateBackup(
00352 fullBackup,
00353 false,
00354 0,
00355 NULL_TXN_ID,
00356 getCompressionProgram(true),
00357 dataDeviceSize,
00358 aborted);
00359 pDatabase->abortBackup();
00360
00361
00362
00363 nPagesBefore =
00364 pDatabase->getDataSegment()->getAllocatedSizeInPages();
00365 pDatabase->deallocateOldPages(pDatabase->getLastCommittedTxnId());
00366 nPagesAfter =
00367 pDatabase->getDataSegment()->getAllocatedSizeInPages();
00368 BOOST_REQUIRE(nPagesBefore > nPagesAfter);
00369
00370
00371 pDatabase->abortBackup();
00372
00373 pDatabase.reset();
00374 }
00375
00376 void BackupRestoreTest::executeSnapshotTxn(int i)
00377 {
00378 SharedLogicalTxn pTxn = pDatabase->getTxnLog()->newLogicalTxn(pCache);
00379 SharedSegment pSegment =
00380 pDatabase->getSegmentFactory()->newSnapshotRandomAllocationSegment(
00381 pDatabase->getDataSegment(),
00382 pDatabase->getDataSegment(),
00383 pTxn->getTxnId());
00384 SnapshotRandomAllocationSegment *pSnapshotSegment =
00385 SegmentFactory::dynamicCast<SnapshotRandomAllocationSegment *>(
00386 pSegment);
00387
00388
00389 SegmentAccessor segmentAccessor(pSegment, pCache);
00390 TestPageLock pageLock(segmentAccessor);
00391 pageLock.lockExclusive(persistentPageId);
00392 pageLock.getNodeForWrite().x += i;
00393 pageLock.unlock();
00394 pTxn->commit();
00395
00396
00397 pTxn = pDatabase->getTxnLog()->newLogicalTxn(pCache);
00398 pSnapshotSegment->commitChanges(pTxn->getTxnId());
00399 pSnapshotSegment->checkpoint(CHECKPOINT_FLUSH_ALL);
00400 pTxn->commit();
00401 pDatabase->checkpointImpl();
00402 }
00403
00404 void BackupRestoreTest::verifySnapshotData(uint x)
00405 {
00406
00407
00408
00409 SharedSegment pSegment =
00410 pDatabase->getSegmentFactory()->newSnapshotRandomAllocationSegment(
00411 pDatabase->getDataSegment(),
00412 pDatabase->getDataSegment(),
00413 pDatabase->getLastCommittedTxnId());
00414 SegmentAccessor segmentAccessor(pSegment,pCache);
00415 TestPageLock pageLock(segmentAccessor);
00416 pageLock.lockShared(persistentPageId);
00417 BOOST_CHECK_EQUAL(pageLock.getNodeForRead().x,x);
00418 }
00419
00420 void BackupRestoreTest::testBackupRestore(bool isCompressed)
00421 {
00422
00423
00424 currCsn = TxnId(0);
00425 openStorage(DeviceMode::createNew);
00426 testAllocateAll();
00427 closeStorage();
00428
00429
00430 currCsn = TxnId(5);
00431 updatedCsns.push_back(currCsn);
00432 openStorage(DeviceMode::load);
00433 testSkipWrite(5);
00434 closeStorage();
00435
00436
00437 std::string backup5 = "backupTxnId5.dat";
00438 backup(backup5, NULL_TXN_ID, TxnId(5), isCompressed);
00439
00440
00441 currCsn = TxnId(7);
00442 updatedCsns.push_back(currCsn);
00443 openStorage(DeviceMode::load);
00444 testSkipWrite(7);
00445 closeStorage();
00446
00447
00448 std::string backup5to7 = "backupTxnId5to7.dat";
00449 backup(backup5to7, TxnId(5), TxnId(7), isCompressed);
00450
00451
00452 currCsn = TxnId(11);
00453 updatedCsns.push_back(currCsn);
00454 openStorage(DeviceMode::load);
00455 testSkipWrite(11);
00456 closeStorage();
00457
00458
00459 std::string backup7to11 = "backupTxnId7to11.dat";
00460 backup(backup7to11, TxnId(7), TxnId(11), isCompressed);
00461
00462
00463 std::string backup5to11 = "backupTxnId5to11.dat";
00464 backup(backup5to11, TxnId(5), TxnId(11), isCompressed);
00465
00466
00467 restore(backup5, NULL_TXN_ID, TxnId(5), isCompressed);
00468
00469
00470
00471
00472 updatedCsns.clear();
00473 updatedCsns.push_back(TxnId(5));
00474 verifyData();
00475
00476
00477
00478 restore(backup5to7, TxnId(5), TxnId(7), isCompressed);
00479 updatedCsns.push_back(TxnId(7));
00480 verifyData();
00481
00482
00483
00484 restore(backup7to11, TxnId(7), TxnId(11), isCompressed);
00485 updatedCsns.push_back(TxnId(11));
00486 verifyData();
00487
00488
00489
00490 restore(backup5, NULL_TXN_ID, TxnId(5), isCompressed);
00491 updatedCsns.clear();
00492 updatedCsns.push_back(TxnId(5));
00493 verifyData();
00494 restore(backup5to11, TxnId(5), TxnId(11), isCompressed);
00495 updatedCsns.push_back(TxnId(7));
00496 updatedCsns.push_back(TxnId(11));
00497 verifyData();
00498 }
00499
00500 void BackupRestoreTest::backup(
00501 std::string backupFileName,
00502 TxnId lowerBoundCsn,
00503 TxnId upperBoundCsn,
00504 bool isCompressed)
00505 {
00506 openStorage(DeviceMode::load);
00507 VersionedRandomAllocationSegment *pVRSegment =
00508 SegmentFactory::dynamicCast<VersionedRandomAllocationSegment *>(
00509 pVersionedRandomSegment);
00510 SegmentAccessor scratchAccessor =
00511 pSegmentFactory->newScratchSegment(pCache, 12);
00512
00513 if (isCompressed) {
00514 backupFileName.append(".gz");
00515 }
00516 SharedSegPageBackupRestoreDevice pBackupDevice =
00517 SegPageBackupRestoreDevice::newSegPageBackupRestoreDevice(
00518 backupFileName,
00519 "w",
00520 getCompressionProgram(isCompressed),
00521 10,
00522 2,
00523 scratchAccessor,
00524 pCache->getDeviceAccessScheduler(*pRandomAccessDevice),
00525 pRandomAccessDevice);
00526 bool abortFlag = false;
00527 pVRSegment->backupAllocationNodes(
00528 pBackupDevice,
00529 false,
00530 lowerBoundCsn,
00531 upperBoundCsn,
00532 abortFlag);
00533 pVRSegment->backupDataPages(
00534 pBackupDevice,
00535 lowerBoundCsn,
00536 upperBoundCsn,
00537 abortFlag);
00538
00539 assert(pBackupDevice.unique());
00540 pBackupDevice.reset();
00541
00542 scratchAccessor.reset();
00543 closeStorage();
00544 }
00545
00546 void BackupRestoreTest::restore(
00547 std::string backupFileName,
00548 TxnId lowerBoundCsn,
00549 TxnId upperBoundCsn,
00550 bool isCompressed)
00551 {
00552 openStorage(DeviceMode::load);
00553 VersionedRandomAllocationSegment *pVRSegment =
00554 SegmentFactory::dynamicCast<VersionedRandomAllocationSegment *>(
00555 pVersionedRandomSegment);
00556 SegmentAccessor scratchAccessor =
00557 pSegmentFactory->newScratchSegment(pCache, 10);
00558
00559
00560
00561 MappedPageListenerPredicate pagePredicate(*pVRSegment);
00562 pCache->checkpointPages(pagePredicate, CHECKPOINT_FLUSH_AND_UNMAP);
00563
00564 if (isCompressed) {
00565 backupFileName.append(".gz");
00566 }
00567 SharedSegPageBackupRestoreDevice pBackupDevice =
00568 SegPageBackupRestoreDevice::newSegPageBackupRestoreDevice(
00569 backupFileName,
00570 "r",
00571 getCompressionProgram(isCompressed),
00572 10,
00573 0,
00574 scratchAccessor,
00575 pCache->getDeviceAccessScheduler(*pRandomAccessDevice),
00576 pRandomAccessDevice);
00577 bool abortFlag = false;
00578 pVRSegment->restoreFromBackup(
00579 pBackupDevice,
00580 lowerBoundCsn,
00581 upperBoundCsn,
00582 abortFlag);
00583
00584 assert(pBackupDevice.unique());
00585 pBackupDevice.reset();
00586
00587 scratchAccessor.reset();
00588 closeStorage();
00589 }
00590
00591 std::string BackupRestoreTest::getCompressionProgram(bool isCompressed)
00592 {
00593 if (!isCompressed) {
00594 return "";
00595 } else {
00596 return "gzip";
00597 }
00598 }
00599
00600 void BackupRestoreTest::verifyData()
00601 {
00602 openStorage(DeviceMode::load);
00603 testSequentialRead();
00604 closeStorage();
00605 }
00606
00607 FENNEL_UNIT_TEST_SUITE(BackupRestoreTest);
00608
00609