Fennel: /home/pub/open/dev/fennel/test/LogicalTxnTest.cpp Source File (original) (raw)

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/txn/LogicalTxn.h" 00026 #include "fennel/txn/LogicalTxnLog.h" 00027 #include "fennel/txn/LogicalRecoveryLog.h" 00028 #include "fennel/txn/LogicalTxnStoredStructs.h" 00029 #include "fennel/txn/LogicalTxnParticipant.h" 00030 #include "fennel/txn/LogicalTxnParticipantFactory.h" 00031 #include "fennel/test/SegStorageTestBase.h" 00032 #include "fennel/common/ByteInputStream.h" 00033 #include "fennel/common/ByteOutputStream.h" 00034 #include "fennel/cache/Cache.h" 00035 00036 #include <boost/test/test_tools.hpp> 00037 00038 using namespace fennel; 00039 00040 class LogicalTxnTest 00041 : virtual public SegStorageTestBase, 00042 public LogicalTxnParticipant, 00043 public LogicalTxnParticipantFactory 00044 { 00045 static const int participantDescription; 00046 static const LogicalActionType ACTION_TEST; 00047 00048 SharedLogicalTxnLog pTxnLog; 00049 LogicalTxnLogCheckpointMemento firstCheckpointMemento; 00050 LogicalTxnLogCheckpointMemento intermediateCheckpointMemento; 00051 LogicalTxnLogCheckpointMemento finalCheckpointMemento; 00052 SavepointId svptId; 00053 PseudoUuid onlineUuid; 00054 00055 typedef std::pair<int,int> ExpectedRange; 00056 std::vector expected; 00057 00058 void rollbackFull(); 00059 void commit(); 00060 void checkpointTxnLog(LogicalTxnLogCheckpointMemento &); 00061 SharedLogicalRecoveryLog createRecoveryLog(); 00062 00063 public: 00064 explicit LogicalTxnTest() 00065 { 00066 onlineUuid.generateInvalid(); 00067 00068
00069
00070 00071 FENNEL_UNIT_TEST_CASE(LogicalTxnTest,testTxnIdSequence); 00072 FENNEL_UNIT_TEST_CASE(LogicalTxnTest,testRollbackEmpty); 00073 FENNEL_UNIT_TEST_CASE(LogicalTxnTest,testRollbackShort); 00074 FENNEL_UNIT_TEST_CASE(LogicalTxnTest,testRollbackLong); 00075 FENNEL_UNIT_TEST_CASE(LogicalTxnTest,testRollbackSavepointNoGap); 00076 FENNEL_UNIT_TEST_CASE(LogicalTxnTest,testRollbackSavepointGap); 00077 FENNEL_UNIT_TEST_CASE(LogicalTxnTest,testCheckpointCommitSavepoint); 00078 FENNEL_UNIT_TEST_CASE(LogicalTxnTest,testCommitEmpty); 00079 FENNEL_UNIT_TEST_CASE(LogicalTxnTest,testCommitShort); 00080 FENNEL_UNIT_TEST_CASE(LogicalTxnTest,testCommitLong); 00081 FENNEL_UNIT_TEST_CASE(LogicalTxnTest,testCheckpointCommitEmpty); 00082 FENNEL_UNIT_TEST_CASE(LogicalTxnTest,testCheckpointCommitShort); 00083 FENNEL_UNIT_TEST_CASE(LogicalTxnTest,testCheckpointCommitLong); 00084 FENNEL_UNIT_TEST_CASE(LogicalTxnTest,testCheckpointRollbackShort); 00085 FENNEL_UNIT_TEST_CASE(LogicalTxnTest,testCheckpointRollbackLong); 00086 } 00087 00088 void testCaseSetUp() 00089 { 00090 expected.clear(); 00091 } 00092 00093 void testTxn(int nActions,int iCheckpoint = -1,int iSvpt = -1); 00094 void testActions(int nActions,int iFirst); 00095 00096 void testRollback( 00097 int nActions, 00098 bool checkpoint = false); 00099 void testTxnIdSequence(); 00100 void testRollbackEmpty(); 00101 void testRollbackShort(); 00102 void testRollbackLong(); 00103 00104 void testRollbackSavepointNoGap(); 00105 void testRollbackSavepointGap(); 00106 void testRollbackSavepoint(bool gap); 00107 void testCheckpointCommitSavepoint(); 00108 00109 void testCommit(int nActions,bool checkpoint = false); 00110 void testCommitEmpty(); 00111 void testCommitShort(); 00112 void testCommitLong(); 00113 void testCheckpointCommitEmpty(); 00114 void testCheckpointCommitShort(); 00115 void testCheckpointCommitLong(); 00116 void testCheckpointRollbackShort(); 00117 void testCheckpointRollbackLong(); 00118 00119
00120 virtual LogicalTxnClassId getParticipantClassId() const; 00121 virtual void describeParticipant(ByteOutputStream &logStream); 00122 virtual void redoLogicalAction( 00123 LogicalActionType actionType, 00124 ByteInputStream &logStream); 00125 virtual void undoLogicalAction( 00126 LogicalActionType actionType, 00127 ByteInputStream &logStream); 00128 00129
00130 virtual SharedLogicalTxnParticipant loadParticipant( 00131 LogicalTxnClassId classId, 00132 ByteInputStream &logStream); 00133 }; 00134 00135 const int LogicalTxnTest::participantDescription = 42; 00136 const LogicalActionType LogicalTxnTest::ACTION_TEST = 1; 00137 00138 LogicalTxnClassId LogicalTxnTest::getParticipantClassId() const 00139 { 00140 return LogicalTxnClassId(0x83f6b9edfe168b93LL); 00141 } 00142 00143 void LogicalTxnTest::describeParticipant(ByteOutputStream &logStream) 00144 { 00145 int x = participantDescription; 00146 logStream.writeValue(x); 00147 } 00148 00149 void LogicalTxnTest::checkpointTxnLog( 00150 LogicalTxnLogCheckpointMemento &memento) 00151 { 00152 pTxnLog->checkpoint(memento); 00153 pTxnLog->deallocateCheckpointedLog(memento); 00154 } 00155 00156 void LogicalTxnTest::undoLogicalAction( 00157 LogicalActionType actionType, 00158 ByteInputStream &logStream) 00159 { 00160
00161 BOOST_CHECK_EQUAL(actionType,ACTION_TEST); 00162 int i; 00163 logStream.readValue(i); 00164 BOOST_CHECK(expected.empty()); 00165 ExpectedRange &range = expected.front(); 00166 BOOST_CHECK_EQUAL(i,range.first); 00167 range.first--; 00168 if (range.first < range.second) { 00169 expected.erase(expected.begin()); 00170 } 00171 } 00172 00173 void LogicalTxnTest::redoLogicalAction( 00174 LogicalActionType actionType, 00175 ByteInputStream &logStream) 00176 { 00177
00178 BOOST_CHECK_EQUAL(actionType,ACTION_TEST); 00179 int i; 00180 logStream.readValue(i); 00181 BOOST_CHECK(expected.empty()); 00182 ExpectedRange &range = expected.front(); 00183 BOOST_CHECK_EQUAL(i,range.first); 00184 range.first++; 00185 if (range.first > range.second) { 00186 expected.erase(expected.begin()); 00187 } 00188 } 00189 00190 void LogicalTxnTest::testTxnIdSequence() 00191 { 00192 testTxn(1); 00193 TxnId id1 = getLogicalTxn()->getTxnId(); 00194 SharedLogicalTxn pTxn2 = pTxnLog->newLogicalTxn(pCache); 00195 TxnId id2 = pTxn2->getTxnId(); 00196 pTxn2->commit(); 00197 pTxn2.reset(); 00198 commit(); 00199
00200 BOOST_CHECK(id2 > id1); 00201 } 00202 00203 void LogicalTxnTest::testRollbackEmpty() 00204 { 00205 testRollback(0); 00206 } 00207 00208 void LogicalTxnTest::testRollbackShort() 00209 { 00210 testRollback(10); 00211 } 00212 00213 void LogicalTxnTest::testRollbackLong() 00214 { 00215 testRollback(10000); 00216 } 00217 00218 void LogicalTxnTest::testRollbackSavepointNoGap() 00219 { 00220 testRollbackSavepoint(false); 00221 } 00222 00223 void LogicalTxnTest::testRollbackSavepointGap() 00224 { 00225 testRollbackSavepoint(true); 00226 } 00227 00228 void LogicalTxnTest::testRollbackSavepoint(bool gap) 00229 { 00230
00231 testTxn(100,-1,50); 00232 00233
00234 expected.push_back(ExpectedRange(99,51)); 00235 getLogicalTxn()->rollback(&svptId); 00236 BOOST_CHECK(expected.empty()); 00237 00238 if (gap) { 00239
00240 testActions(40,200); 00241 expected.push_back(ExpectedRange(239,200)); 00242 } 00243 00244
00245 expected.push_back(ExpectedRange(50,0)); 00246 rollbackFull(); 00247 } 00248 00249 SharedLogicalRecoveryLog LogicalTxnTest::createRecoveryLog() 00250 { 00251 SegmentAccessor segmentAccessor(pLinearSegment,pCache); 00252 SharedLogicalRecoveryLog pRecoveryLog = 00253 LogicalRecoveryLog::newLogicalRecoveryLog( 00254 *this, 00255 segmentAccessor, 00256 onlineUuid, 00257 pSegmentFactory); 00258 return pRecoveryLog; 00259 } 00260 00261 void LogicalTxnTest::testCheckpointCommitSavepoint() 00262 { 00263
00264
00265 testTxn(100,75,50); 00266 00267
00268 expected.push_back(ExpectedRange(99,51)); 00269 getLogicalTxn()->rollback(&svptId); 00270 BOOST_CHECK(expected.empty()); 00271 00272
00273 testActions(40,200); 00274 00275 commit(); 00276 SharedLogicalRecoveryLog pRecoveryLog = createRecoveryLog(); 00277 00278
00279
00280
00281 expected.push_back(ExpectedRange(76,99)); 00282 expected.push_back(ExpectedRange(99,51)); 00283 expected.push_back(ExpectedRange(200,239)); 00284 pRecoveryLog->recover(intermediateCheckpointMemento); 00285 BOOST_CHECK(expected.empty()); 00286 assert(pRecoveryLog.unique()); 00287 } 00288 00289 void LogicalTxnTest::testCheckpointRollbackShort() 00290 { 00291 testRollback(10,true); 00292 } 00293 00294 void LogicalTxnTest::testCheckpointRollbackLong() 00295 { 00296 testRollback(10000,true); 00297 } 00298 00299 void LogicalTxnTest::testCommitEmpty() 00300 { 00301 testCommit(0); 00302 } 00303 00304 void LogicalTxnTest::testCommitShort() 00305 { 00306 testCommit(10); 00307 } 00308 00309 void LogicalTxnTest::testCommitLong() 00310 { 00311 testCommit(10000); 00312 } 00313 00314 void LogicalTxnTest::testCheckpointCommitEmpty() 00315 { 00316 testCommit(0,true); 00317 } 00318 00319 void LogicalTxnTest::testCheckpointCommitShort() 00320 { 00321 testCommit(10,true); 00322 } 00323 00324 void LogicalTxnTest::testCheckpointCommitLong() 00325 { 00326 testCommit(10000,true); 00327 } 00328 00329 void LogicalTxnTest::testRollback( 00330 int nActions, 00331 bool checkpoint) 00332 { 00333 int iCheckpoint = checkpoint ? (nActions / 2) : -1; 00334 testTxn(nActions,iCheckpoint); 00335 if (checkpoint) { 00336 SharedLogicalRecoveryLog pRecoveryLog = createRecoveryLog(); 00337 expected.push_back(ExpectedRange(iCheckpoint,0)); 00338 pRecoveryLog->recover(intermediateCheckpointMemento); 00339 BOOST_CHECK(expected.empty()); 00340 assert(pRecoveryLog.unique()); 00341 } 00342 if (nActions) { 00343 expected.push_back(ExpectedRange(nActions - 1, 0)); 00344 } 00345 rollbackFull(); 00346 } 00347 00348 void LogicalTxnTest::rollbackFull() 00349 { 00350 getLogicalTxn()->rollback(); 00351 BOOST_CHECK(expected.empty()); 00352 checkpointTxnLog(finalCheckpointMemento); 00353 assert(pTxnLog.unique()); 00354 pTxnLog.reset(); 00355 } 00356 00357 void LogicalTxnTest::commit() 00358 { 00359 getLogicalTxn()->commit(); 00360 checkpointTxnLog(finalCheckpointMemento); 00361 assert(pTxnLog.unique()); 00362 pTxnLog.reset(); 00363 } 00364 00365 void LogicalTxnTest::testCommit(int nActions,bool checkpoint) 00366 { 00367 int iCheckpoint = checkpoint ? (nActions / 2) : -1; 00368 testTxn(nActions,iCheckpoint); 00369 commit(); 00370 00371 SharedLogicalRecoveryLog pRecoveryLog = createRecoveryLog(); 00372 if (checkpoint) { 00373 if (nActions) { 00374 expected.push_back(ExpectedRange(iCheckpoint + 1, nActions - 1)); 00375 } 00376 pRecoveryLog->recover(intermediateCheckpointMemento); 00377 } else { 00378 if (nActions) { 00379 expected.push_back(ExpectedRange(0, nActions - 1)); 00380 } 00381 pRecoveryLog->recover(firstCheckpointMemento); 00382 } 00383 BOOST_CHECK(expected.empty()); 00384 assert(pRecoveryLog.unique()); 00385 } 00386 00387 void LogicalTxnTest::testTxn(int nActions,int iCheckpoint,int iSvpt) 00388 { 00389 openStorage(DeviceMode::createNew); 00390 SegmentAccessor segmentAccessor(pLinearSegment,pCache); 00391 pTxnLog = LogicalTxnLog::newLogicalTxnLog( 00392 segmentAccessor,onlineUuid,pSegmentFactory); 00393 checkpointTxnLog(firstCheckpointMemento); 00394 SharedLogicalTxn pTxn = pTxnLog->newLogicalTxn(pCache); 00395 pTxn->addParticipant( 00396 boost::dynamic_pointer_cast( 00397 shared_from_this())); 00398 for (int i = 0; i < nActions; ++i) { 00399 ByteOutputStream &logStream = 00400 getLogicalTxn()->beginLogicalAction(*this,ACTION_TEST); 00401 logStream.writeValue(i); 00402 getLogicalTxn()->endLogicalAction(); 00403 if (i == iCheckpoint) { 00404 checkpointTxnLog(intermediateCheckpointMemento); 00405 } 00406 if (i == iSvpt) { 00407 svptId = getLogicalTxn()->createSavepoint(); 00408 } 00409 } 00410 if (!nActions && !iCheckpoint) { 00411 checkpointTxnLog(intermediateCheckpointMemento); 00412 } 00413 } 00414 00415 void LogicalTxnTest::testActions(int nActions,int iFirst) 00416 { 00417 for (int i = 0; i < nActions; ++i) { 00418 ByteOutputStream &logStream = 00419 getLogicalTxn()->beginLogicalAction(*this,ACTION_TEST); 00420 int x = iFirst + i; 00421 logStream.writeValue(x); 00422 getLogicalTxn()->endLogicalAction(); 00423 } 00424 } 00425 00426 SharedLogicalTxnParticipant LogicalTxnTest::loadParticipant( 00427 LogicalTxnClassId classId, 00428 ByteInputStream &logStream) 00429 { 00430 BOOST_CHECK_EQUAL(classId,getParticipantClassId()); 00431 int x; 00432 logStream.readValue(x); 00433 BOOST_CHECK_EQUAL(x,participantDescription); 00434 return boost::dynamic_pointer_cast( 00435 shared_from_this()); 00436 } 00437 00438 FENNEL_UNIT_TEST_SUITE(LogicalTxnTest); 00439 00440