📄 t_recoverbadlog.java
字号:
page[i][j] = t_util.t_getPage(c[i],pagenum[i][j]);
t[i].resetContext();
}
//////////////////////// check ////////////////////////
for (i = 1; i < numtrans; i++)
{
t[i].switchTransactionContext();
for (j = 0; j < numpages; j++)
t_util.t_checkFetch(page[i][j], rh[i][j], REC_003);
t[i].resetContext();
}
t[0].switchTransactionContext();
for (j = 0; j < numpages; j++)
t_util.t_checkFetch(page[0][j], rh[0][j], REC_005);
t[0].resetContext();
///////////////////////////////////////////
//// log switch without checkpoint here ///
///////////////////////////////////////////
factory.checkpoint();
//////////////////////// step 8 ////////////////////////
T_RawStoreRow row6 = new T_RawStoreRow(REC_006);
for (i = 0; i < numtrans; i++)
{
t[i].switchTransactionContext();
for (j = 0; j < numpages; j++)
page[i][j].update(rh[i][j], row6.getRow(), (FormatableBitSet) null); // step 8
t[i].resetContext();
}
//////////////////////// step 9 ////////////////////////
// unlatch relavante pages
t[0].switchTransactionContext();
for (j = 0; j < numpages; j++)
page[0][j].unlatch();
t[0].rollbackToSavePoint(SP1, null);
// relatch relevant pages
for (j = 0; j < numpages; j++)
page[0][j] = t_util.t_getPage(c[0], pagenum[0][j]);
t[0].resetContext();
//////////////////////// check ////////////////////////
for (i = 1; i < numtrans; i++)
{
t[i].switchTransactionContext();
for (j = 0; j < numpages; j++)
{
t_util.t_checkFetch(page[i][j], rh[i][j], REC_006);
t_util.t_checkRecordCount(page[i][j], 1, 1);
}
t[i].resetContext();
}
t[0].switchTransactionContext();
for (j = 0; j < numpages; j++)
{
t_util.t_checkFetch(page[0][j], rh[0][j], REC_001);
t_util.t_checkRecordCount(page[0][j], 1, 1);
}
t[0].resetContext();
//////////////////////// step 10 ////////////////////////
// unlatch all pages
for (i = 0; i < numtrans; i++)
{
t[i].switchTransactionContext();
for (j = 0; j < numpages; j++)
page[i][j].unlatch();
t[i].resetContext();
}
// t[0] incomplete
t_util.t_abort(t[1]);
t_util.t_commit(t[2]);
// t[3] incomplete
t_util.t_commit(t[4]);
// reopen containers 1, 2, and 4, where were closed when the
// transaction terminated.
c[1] = t_util.t_openContainer(t[1], 0, cid[1], false);
c[2] = t_util.t_openContainer(t[2], 0, cid[2], false);
c[4] = t_util.t_openContainer(t[4], 0, cid[4], false);
//////////////////////// check ////////////////////////
for (j = 0; j < numpages; j++)
{
t[0].switchTransactionContext();
t_util.t_checkFetch(c[0], rh[0][j], REC_001);
t[0].resetContext();
// t[1] has been aborted
// rh[1][j] (REC_001) is deleted
t[1].switchTransactionContext();
page[1][j] = t_util.t_getPage(c[1], pagenum[1][j]);
t_util.t_checkRecordCount(page[1][j], 1, 0);
t_util.t_checkFetchBySlot(page[1][j], Page.FIRST_SLOT_NUMBER,
REC_001, true, false);
page[1][j].unlatch();
t[1].resetContext();
t[2].switchTransactionContext();
t_util.t_checkFetch(c[2], rh[2][j], REC_006);
t[2].resetContext();
t[3].switchTransactionContext();
t_util.t_checkFetch(c[3], rh[3][j], REC_006);
t[3].resetContext();
t[4].switchTransactionContext();
t_util.t_checkFetch(c[4], rh[4][j], REC_006);
t[4].resetContext();
}
///////////////////////////////////////////////////////////
//// now write a 1/2 log record to the end of the log
//////////////////////////////////////////////////////////
t[3].switchTransactionContext();// this is going to be an
// incomplete transaction
// make a full page and then copy and purge it to another page
Page badPage1 = t_util.t_addPage(c[3]);
Page badPage2 = t_util.t_addPage(c[3]);
T_RawStoreRow row;
for (i = 0, row = new T_RawStoreRow("row at slot " + i);
badPage1.spaceForInsert();
i++, row = new T_RawStoreRow("row at slot " + i))
{
if (t_util.t_insertAtSlot(badPage1, i, row, Page.INSERT_UNDO_WITH_PURGE) == null)
break;
}
//////////////////////////////////////////////////////////
// writing 200 bytes of the log record to the end of the log -
// NO MORE LOG RECORD SHOULD BE WRITTEN,
//////////////////////////////////////////////////////////
if(!checksumTest)
{
SanityManager.DEBUG_SET(LogToFile.TEST_LOG_INCOMPLETE_LOG_WRITE);
System.getProperties().put(LogToFile.TEST_LOG_PARTIAL_LOG_WRITE_NUM_BYTES, "200");
}
logFactory.flushAll();
// RESOLVE:
// copy and purge actually generates 2 log records, this is
// actually not a good operation to use for this test. Just make
// sure the first log record is > 400 or else the log will be hosed
//
badPage1.copyAndPurge(badPage2, 0, i, 0);
t[3].resetContext();
if(checksumTest)
simulateLogFileCorruption();
////////////////////////////////////////////////////////
REPORT("badlog test3: numtrans " + numtrans + " numpages " + numpages);
for (i = 0; i < numtrans; i++)
{
register(key(3, i+10), cid[i]);
String str = "container " + i + ":" + find(key(3,i+10)) + " pages: ";
for (j = 0; j < numpages; j++)
{
str += pagenum[i][j] + " ";
register(key(3, (i+1)*1000+j), pagenum[i][j]);
}
REPORT("\t" + str);
}
register(key(3,1), numtrans);
register(key(3,2), numpages);
register(key(3,3), badPage1.getPageNumber());
register(key(3,4), badPage2.getPageNumber());
}
finally
{
SanityManager.DEBUG_CLEAR(LogToFile.TEST_LOG_INCOMPLETE_LOG_WRITE);
}
}
/*
* test recovery of test3
*/
void RTest3() throws T_Fail, StandardException
{
int numtrans = (int)find(key(3,1));
if (numtrans < 0)
{
REPORT("bad log test3 not run");
return;
}
int numpages = (int)find(key(3,2));
long badPagenum1 = find(key(3,3)); // these two pages are involved in
// the 1/2 written log record, make
// sure they are not corrupted
long badPagenum2 = find(key(3,4));
Transaction t = t_util.t_startTransaction();
long[] cid = new long[numtrans];
ContainerHandle[] c = new ContainerHandle[numtrans];
long[][] pagenum = new long[numtrans][numpages];
Page[][] page = new Page[numtrans][numpages];
int i,j;
for (i = 0; i < numtrans; i++)
{
cid[i] = find(key(3, i+10));
c[i] = t_util.t_openContainer(t, 0, cid[i], true);
for (j = 0; j < numpages; j++)
{
pagenum[i][j] = find(key(3, (i+1)*1000+j));
page[i][j] = t_util.t_getPage(c[i], pagenum[i][j]);
}
}
// transactions were left in the following state
// t0 - incomplete (rolled back)
// t1 - abort
// t2 - commit
// t3 - incomplete (rolled back)
// t4 - commit
// any other transactions - incomplete
//
// all the rolled back transaction should have a deleted REC_001
// all the committed transactions should have a REC_006
//
try
{
for (j = 0; j < numpages; j++)
{
t_util.t_checkRecordCount(page[0][j], 1, 0);
t_util.t_checkFetchBySlot(page[0][j], Page.FIRST_SLOT_NUMBER,
REC_001, true, true);
t_util.t_checkRecordCount(page[1][j], 1, 0);
t_util.t_checkFetchBySlot(page[1][j], Page.FIRST_SLOT_NUMBER,
REC_001, true, true);
t_util.t_checkRecordCount(page[2][j], 1, 1);
t_util.t_checkFetchBySlot(page[2][j], Page.FIRST_SLOT_NUMBER,
REC_006, false, true);
t_util.t_checkRecordCount(page[3][j], 1, 0);
t_util.t_checkFetchBySlot(page[3][j], Page.FIRST_SLOT_NUMBER,
REC_001, true, true);
t_util.t_checkRecordCount(page[4][j], 1, 1);
t_util.t_checkFetchBySlot(page[4][j], Page.FIRST_SLOT_NUMBER,
REC_006, false, true);
}
// now check the two bad pages - they are in c[3] and should be empty
Page badPage1 = t_util.t_getPage(c[3], badPagenum1);
Page badPage2 = t_util.t_getPage(c[3], badPagenum2);
t_util.t_checkRecordCount(badPage1, 0, 0);
t_util.t_checkRecordCount(badPage2, 0, 0);
REPORT("RTest3 passed: numtrans " + numtrans + " numpages " + numpages);
for (i = 0; i < numtrans; i++)
{
String str = "container " + i + ":" + cid[i] + " pages: ";
for (j = 0; j < numpages; j++)
str += pagenum[i][j] + " ";
REPORT("\t" + str);
}
}
finally
{
t_util.t_commit(t);
t.close();
}
}
/*
* test4 manufactures a log with the following recoverable 'defects':
* - a log file that only has the partial log instance(7 bytes instead of 8
* bytes writtne) of a log record written
*/
protected void STest4() throws T_Fail, StandardException
{
Transaction t = t_util.t_startTransaction();
try
{
long cid = t_util.t_addContainer(t, 0);
ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
// make a really big record - fill 80% of the page
int numcol = (int)((RawStoreFactory.PAGE_SIZE_MINIMUM*8)/(10*20));
T_RawStoreRow bigrow = new T_RawStoreRow(numcol);
String string1 = "01234567890123456789"; // 20 char string
for (int i = 0; i < numcol; i++)
bigrow.setColumn(i, string1);
// if overhead is > 80%, then reduce the row size until it fits
RecordHandle rh = null;
while(numcol > 0)
{
try {
rh = t_util.t_insert(page, bigrow);
break;
} catch (StandardException se) {
bigrow.setColumn(--numcol, (String) null);
}
}
if (numcol == 0)
throw T_Fail.testFailMsg("cannot fit any column into the page");
t_util.t_commit(t);
// make a big log record - update row
String string2 = "abcdefghijklmnopqrst"; // 20 char string
for (int i = 0; i < numcol; i++)
bigrow.setColumn(i, string2);
c = t_util.t_openContainer(t, 0, cid, true);
page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
Page p2 = t_util.t_addPage(c); // do something so we get the beginXact log
// record out of the way
t_util.t_insert(p2, new T_RawStoreRow(REC_001));
//////////////////////////////////////////////////////////
// writing approx 1/2 of log record instance to the end of the log -
// NO MORE LOG RECORD SHOULD BE WRITTEN,
// Length 4 bytes + 7(8) bytes of log record instance
//////////////////////////////////////////////////////////
if(!checksumTest)
{
SanityManager.DEBUG_SET(LogToFile.TEST_LOG_INCOMPLETE_LOG_WRITE);
System.getProperties().put(LogToFile.TEST_LOG_PARTIAL_LOG_WRITE_NUM_BYTES, Integer.toString(11));
}
logFactory.flushAll();
page.update(rh, bigrow.getRow(), (FormatableBitSet) null);
if(checksumTest)
simulateLogFileCorruption();
////////////////////////////////////////////////////////
REPORT("badlog test4: cid = " + cid + " numcol " + numcol);
register(key(4,1), cid);
register(key(4,2), numcol);
}
finally
{
SanityManager.DEBUG_CLEAR(LogToFile.TEST_LOG_INCOMPLETE_LOG_WRITE);
}
}
/*
* test recovery of test 4
*/
void RTest4() throws T_Fail, StandardException
{
long cid = find(key(4, 1));
if (cid < 0)
{
REPORT("bad log test4 not run");
return;
}
int numcol = (int)find(key(4,2));
Transaction t = t_util.t_startTransaction();
try
{
ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
int optimisticNumcol = (int)((RawStoreFactory.PAGE_SIZE_MINIMUM*8)/(10*20));
T_RawStoreRow bigrow = new T_RawStoreRow(optimisticNumcol);
for (int i = 0; i < optimisticNumcol; i++)
bigrow.setColumn(i, (String) null);
page.fetchFromSlot(
(RecordHandle) null, 0, bigrow.getRow(),
(FetchDescriptor) null,
false);
Storable column;
String string1 = "01234567890123456789"; // the original 20 char string
for (int i = 0; i < numcol; i++)
{
column = bigrow.getStorableColumn(i);
if (!(column.toString().equals(string1)))
throw T_Fail.testFailMsg("Column " + i + " value incorrect, got :" + column.toString());
}
for (int i = numcol; i < optimisticNumcol; i++)
{
column = bigrow.getStorableColumn(i);
if (!column.isNull())
throw T_Fail.testFailMsg("Column " + i +
" expect Null, got : " + column.toString());
}
REPORT("RTest4 passed");
}
finally
{
t_util.t_commit(t);
t.close();
}
}
/*
* test5 manufactures a log with the following recoverable 'defects':
* - a log file that only has the partial log record length (3 bytes instead of 4
* bytes writtne) of a log record written in the beginning
*/
protected void STest5() throws T_Fail, StandardException
{
Transaction t = t_util.t_startTransaction();
try
{
long cid = t_util.t_addContainer(t, 0);
ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
// make a really big record - fill 80% of the page
int numcol = (int)((RawStoreFactory.PAGE_SIZE_MINIMUM*8)/(10*20));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -