Add more tests for LSM log file recovery. Fix a problem in recovering log
files that contain range deletes. FossilOrigin-Name: e34eafd4c5b2bbf2735e136ad69b67bb4288ad4d01a0128d8e107ac46209a182
This commit is contained in:
@@ -81,12 +81,12 @@ struct Datatest2 {
|
||||
** Generate a unique name for the test case pTest with database system
|
||||
** zSystem.
|
||||
*/
|
||||
static char *getName(const char *zSystem, Datatest1 *pTest){
|
||||
static char *getName(const char *zSystem, int bRecover, Datatest1 *pTest){
|
||||
char *zRet;
|
||||
char *zData;
|
||||
zData = testDatasourceName(&pTest->defn);
|
||||
zRet = testMallocPrintf("data.%s.%s.%d.%d",
|
||||
zSystem, zData, pTest->nRow, pTest->nVerify
|
||||
zRet = testMallocPrintf("data.%s.%s.rec=%d.%d.%d",
|
||||
zSystem, zData, bRecover, pTest->nRow, pTest->nVerify
|
||||
);
|
||||
testFree(zData);
|
||||
return zRet;
|
||||
@@ -251,8 +251,21 @@ static void printScanCb(
|
||||
}
|
||||
#endif
|
||||
|
||||
void testReopenRecover(TestDb **ppDb, int *pRc){
|
||||
if( *pRc==0 ){
|
||||
const char *zLib = tdb_library_name(*ppDb);
|
||||
const char *zDflt = tdb_default_db(zLib);
|
||||
testCopyLsmdb(zDflt, "bak.db");
|
||||
testClose(ppDb);
|
||||
testCopyLsmdb("bak.db", zDflt);
|
||||
*pRc = tdb_open(zLib, 0, 0, ppDb);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void doDataTest1(
|
||||
const char *zSystem, /* Database system to test */
|
||||
int bRecover,
|
||||
Datatest1 *p, /* Structure containing test parameters */
|
||||
int *pRc /* OUT: Error code */
|
||||
){
|
||||
@@ -277,8 +290,11 @@ static void doDataTest1(
|
||||
/* Check that the db content is correct. */
|
||||
testDbContents(pDb, pData, p->nRow, 0, i-1, p->nTest, p->bTestScan, &rc);
|
||||
|
||||
/* Close and reopen the database. */
|
||||
testReopen(&pDb, &rc);
|
||||
if( bRecover ){
|
||||
testReopenRecover(&pDb, &rc);
|
||||
}else{
|
||||
testReopen(&pDb, &rc);
|
||||
}
|
||||
|
||||
/* Check that the db content is still correct. */
|
||||
testDbContents(pDb, pData, p->nRow, 0, i-1, p->nTest, p->bTestScan, &rc);
|
||||
@@ -299,7 +315,11 @@ static void doDataTest1(
|
||||
testDbContents(pDb, pData, p->nRow, i, p->nRow-1,p->nTest,p->bTestScan,&rc);
|
||||
|
||||
/* Close and reopen the database. */
|
||||
testReopen(&pDb, &rc);
|
||||
if( bRecover ){
|
||||
testReopenRecover(&pDb, &rc);
|
||||
}else{
|
||||
testReopen(&pDb, &rc);
|
||||
}
|
||||
|
||||
/* Check that the db content is still correct. */
|
||||
testDbContents(pDb, pData, p->nRow, i, p->nRow-1,p->nTest,p->bTestScan,&rc);
|
||||
@@ -339,13 +359,17 @@ void test_data_1(
|
||||
};
|
||||
|
||||
int i;
|
||||
int bRecover;
|
||||
|
||||
for(i=0; *pRc==LSM_OK && i<ArraySize(aTest); i++){
|
||||
char *zName = getName(zSystem, &aTest[i]);
|
||||
if( testCaseBegin(pRc, zPattern, "%s", zName) ){
|
||||
doDataTest1(zSystem, &aTest[i], pRc);
|
||||
for(bRecover=0; bRecover<2; bRecover++){
|
||||
if( bRecover==1 && memcmp(zSystem, "lsm", 3) ) break;
|
||||
for(i=0; *pRc==LSM_OK && i<ArraySize(aTest); i++){
|
||||
char *zName = getName(zSystem, bRecover, &aTest[i]);
|
||||
if( testCaseBegin(pRc, zPattern, "%s", zName) ){
|
||||
doDataTest1(zSystem, bRecover, &aTest[i], pRc);
|
||||
}
|
||||
testFree(zName);
|
||||
}
|
||||
testFree(zName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -396,6 +420,7 @@ void testCompareDb(
|
||||
|
||||
static void doDataTest2(
|
||||
const char *zSystem, /* Database system to test */
|
||||
int bRecover,
|
||||
Datatest2 *p, /* Structure containing test parameters */
|
||||
int *pRc /* OUT: Error code */
|
||||
){
|
||||
@@ -437,7 +462,11 @@ static void doDataTest2(
|
||||
testFree(pKey1);
|
||||
|
||||
testCompareDb(pData, nRange, i, pControl, pDb, &rc);
|
||||
testReopen(&pDb, &rc);
|
||||
if( bRecover ){
|
||||
testReopenRecover(&pDb, &rc);
|
||||
}else{
|
||||
testReopen(&pDb, &rc);
|
||||
}
|
||||
testCompareDb(pData, nRange, i, pControl, pDb, &rc);
|
||||
|
||||
/* Update the progress dots... */
|
||||
@@ -451,12 +480,12 @@ static void doDataTest2(
|
||||
*pRc = rc;
|
||||
}
|
||||
|
||||
static char *getName2(const char *zSystem, Datatest2 *pTest){
|
||||
static char *getName2(const char *zSystem, int bRecover, Datatest2 *pTest){
|
||||
char *zRet;
|
||||
char *zData;
|
||||
zData = testDatasourceName(&pTest->defn);
|
||||
zRet = testMallocPrintf("data2.%s.%s.%d.%d.%d",
|
||||
zSystem, zData, pTest->nRange, pTest->nWrite, pTest->nIter
|
||||
zRet = testMallocPrintf("data2.%s.%s.rec=%d.%d.%d.%d",
|
||||
zSystem, zData, bRecover, pTest->nRange, pTest->nWrite, pTest->nIter
|
||||
);
|
||||
testFree(zData);
|
||||
return zRet;
|
||||
@@ -476,13 +505,17 @@ void test_data_2(
|
||||
};
|
||||
|
||||
int i;
|
||||
int bRecover;
|
||||
|
||||
for(i=0; *pRc==LSM_OK && i<ArraySize(aTest); i++){
|
||||
char *zName = getName2(zSystem, &aTest[i]);
|
||||
if( testCaseBegin(pRc, zPattern, "%s", zName) ){
|
||||
doDataTest2(zSystem, &aTest[i], pRc);
|
||||
for(bRecover=0; bRecover<2; bRecover++){
|
||||
if( bRecover==1 && memcmp(zSystem, "lsm", 3) ) break;
|
||||
for(i=0; *pRc==LSM_OK && i<ArraySize(aTest); i++){
|
||||
char *zName = getName2(zSystem, bRecover, &aTest[i]);
|
||||
if( testCaseBegin(pRc, zPattern, "%s", zName) ){
|
||||
doDataTest2(zSystem, bRecover, &aTest[i], pRc);
|
||||
}
|
||||
testFree(zName);
|
||||
}
|
||||
testFree(zName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ void test_failed(){
|
||||
static void testSetErrorFunc(int rc, int *pRc, const char *zFile, int iLine){
|
||||
if( rc ){
|
||||
*pRc = rc;
|
||||
printf("FAILED (%s:%d) rc=%d ", zFile, iLine, rc);
|
||||
fprintf(stderr, "FAILED (%s:%d) rc=%d ", zFile, iLine, rc);
|
||||
test_failed();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -745,6 +745,14 @@ const char *tdb_system_name(int i){
|
||||
return aLib[i].zName;
|
||||
}
|
||||
|
||||
const char *tdb_default_db(const char *zSys){
|
||||
int i;
|
||||
for(i=0; i<ArraySize(aLib); i++){
|
||||
if( strcmp(aLib[i].zName, zSys)==0 ) return aLib[i].zDefaultDb;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tdb_open(const char *zLib, const char *zDb, int bClear, TestDb **ppDb){
|
||||
int i;
|
||||
int rc = 1;
|
||||
|
||||
@@ -125,6 +125,7 @@ int tdb_scan(
|
||||
);
|
||||
|
||||
const char *tdb_system_name(int i);
|
||||
const char *tdb_default_db(const char *zSys);
|
||||
|
||||
int tdb_lsm_open(const char *zCfg, const char *zDb, int bClear, TestDb **ppDb);
|
||||
|
||||
|
||||
+5
-1
@@ -864,7 +864,7 @@ int lsmInfoFreelist(lsm_db *pDb, char **pzOut);
|
||||
** Functions from file "lsm_log.c".
|
||||
*/
|
||||
int lsmLogBegin(lsm_db *pDb);
|
||||
int lsmLogWrite(lsm_db *, void *, int, void *, int);
|
||||
int lsmLogWrite(lsm_db *, int, void *, int, void *, int);
|
||||
int lsmLogCommit(lsm_db *);
|
||||
void lsmLogEnd(lsm_db *pDb, int bCommit);
|
||||
void lsmLogTell(lsm_db *, LogMark *);
|
||||
@@ -874,6 +874,10 @@ void lsmLogClose(lsm_db *);
|
||||
int lsmLogRecover(lsm_db *);
|
||||
int lsmInfoLogStructure(lsm_db *pDb, char **pzVal);
|
||||
|
||||
/* Valid values for the second argument to lsmLogWrite(). */
|
||||
#define LSM_WRITE 0x06
|
||||
#define LSM_DELETE 0x08
|
||||
#define LSM_DRANGE 0x0A
|
||||
|
||||
/**************************************************************************
|
||||
** Functions from file "lsm_shared.c".
|
||||
|
||||
+24
-6
@@ -199,9 +199,13 @@
|
||||
|
||||
#define LSM_LOG_WRITE 0x06
|
||||
#define LSM_LOG_WRITE_CKSUM 0x07
|
||||
|
||||
#define LSM_LOG_DELETE 0x08
|
||||
#define LSM_LOG_DELETE_CKSUM 0x09
|
||||
|
||||
#define LSM_LOG_DRANGE 0x0A
|
||||
#define LSM_LOG_DRANGE_CKSUM 0x0B
|
||||
|
||||
/* Require a checksum every 32KB. */
|
||||
#define LSM_CKSUM_MAXDATA (32*1024)
|
||||
|
||||
@@ -653,6 +657,7 @@ static int logFlush(lsm_db *pDb, int eType){
|
||||
*/
|
||||
int lsmLogWrite(
|
||||
lsm_db *pDb, /* Database handle */
|
||||
int eType,
|
||||
void *pKey, int nKey, /* Database key to write to log */
|
||||
void *pVal, int nVal /* Database value (or nVal<0) to write */
|
||||
){
|
||||
@@ -661,13 +666,19 @@ int lsmLogWrite(
|
||||
int nReq; /* Bytes of space required in log */
|
||||
int bCksum = 0; /* True to embed a checksum in this record */
|
||||
|
||||
assert( eType==LSM_WRITE || eType==LSM_DELETE || eType==LSM_DRANGE );
|
||||
assert( LSM_LOG_WRITE==LSM_WRITE );
|
||||
assert( LSM_LOG_DELETE==LSM_DELETE );
|
||||
assert( LSM_LOG_DRANGE==LSM_DRANGE );
|
||||
assert( (eType==LSM_LOG_DELETE)==(nVal<0) );
|
||||
|
||||
if( pDb->bUseLog==0 ) return LSM_OK;
|
||||
pLog = pDb->pLogWriter;
|
||||
|
||||
/* Determine how many bytes of space are required, assuming that a checksum
|
||||
** will be embedded in this record (even though it may not be). */
|
||||
nReq = 1 + lsmVarintLen32(nKey) + 8 + nKey;
|
||||
if( nVal>=0 ) nReq += lsmVarintLen32(nVal) + nVal;
|
||||
if( eType!=LSM_LOG_DELETE ) nReq += lsmVarintLen32(nVal) + nVal;
|
||||
|
||||
/* Jump over the jump region if required. Set bCksum to true to tell the
|
||||
** code below to include a checksum in the record if either (a) writing
|
||||
@@ -687,9 +698,10 @@ int lsmLogWrite(
|
||||
** DELETE) or 2 (for WRITE) varints. */
|
||||
assert( LSM_LOG_WRITE_CKSUM == (LSM_LOG_WRITE | 0x0001) );
|
||||
assert( LSM_LOG_DELETE_CKSUM == (LSM_LOG_DELETE | 0x0001) );
|
||||
*(a++) = (nVal>=0 ? LSM_LOG_WRITE : LSM_LOG_DELETE) | (u8)bCksum;
|
||||
assert( LSM_LOG_DRANGE_CKSUM == (LSM_LOG_DRANGE | 0x0001) );
|
||||
*(a++) = (u8)eType | (u8)bCksum;
|
||||
a += lsmVarintPut32(a, nKey);
|
||||
if( nVal>=0 ) a += lsmVarintPut32(a, nVal);
|
||||
if( eType!=LSM_LOG_DELETE ) a += lsmVarintPut32(a, nVal);
|
||||
|
||||
if( bCksum ){
|
||||
pLog->buf.n = (a - (u8 *)pLog->buf.z);
|
||||
@@ -699,7 +711,7 @@ int lsmLogWrite(
|
||||
|
||||
memcpy(a, pKey, nKey);
|
||||
a += nKey;
|
||||
if( nVal>=0 ){
|
||||
if( eType!=LSM_LOG_DELETE ){
|
||||
memcpy(a, pVal, nVal);
|
||||
a += nVal;
|
||||
}
|
||||
@@ -1005,6 +1017,8 @@ int lsmLogRecover(lsm_db *pDb){
|
||||
break;
|
||||
}
|
||||
|
||||
case LSM_LOG_DRANGE:
|
||||
case LSM_LOG_DRANGE_CKSUM:
|
||||
case LSM_LOG_WRITE:
|
||||
case LSM_LOG_WRITE_CKSUM: {
|
||||
int nKey;
|
||||
@@ -1013,7 +1027,7 @@ int lsmLogRecover(lsm_db *pDb){
|
||||
logReaderVarint(&reader, &buf1, &nKey, &rc);
|
||||
logReaderVarint(&reader, &buf2, &nVal, &rc);
|
||||
|
||||
if( eType==LSM_LOG_WRITE_CKSUM ){
|
||||
if( eType==LSM_LOG_WRITE_CKSUM || eType==LSM_LOG_DRANGE_CKSUM ){
|
||||
logReaderCksum(&reader, &buf1, &bEof, &rc);
|
||||
}else{
|
||||
bEof = logRequireCksum(&reader, nKey+nVal);
|
||||
@@ -1023,7 +1037,11 @@ int lsmLogRecover(lsm_db *pDb){
|
||||
logReaderBlob(&reader, &buf1, nKey, 0, &rc);
|
||||
logReaderBlob(&reader, &buf2, nVal, &aVal, &rc);
|
||||
if( iPass==1 && rc==LSM_OK ){
|
||||
rc = lsmTreeInsert(pDb, (u8 *)buf1.z, nKey, aVal, nVal);
|
||||
if( eType==LSM_LOG_WRITE || eType==LSM_LOG_WRITE_CKSUM ){
|
||||
rc = lsmTreeInsert(pDb, (u8 *)buf1.z, nKey, aVal, nVal);
|
||||
}else{
|
||||
rc = lsmTreeDelete(pDb, (u8 *)buf1.z, nKey, aVal, nVal);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
+2
-5
@@ -669,11 +669,8 @@ static int doWriteOp(
|
||||
}
|
||||
|
||||
if( rc==LSM_OK ){
|
||||
if( bDeleteRange==0 ){
|
||||
rc = lsmLogWrite(pDb, (void *)pKey, nKey, (void *)pVal, nVal);
|
||||
}else{
|
||||
/* TODO */
|
||||
}
|
||||
int eType = (bDeleteRange ? LSM_DRANGE : (nVal>=0?LSM_WRITE:LSM_DELETE));
|
||||
rc = lsmLogWrite(pDb, eType, (void *)pKey, nKey, (void *)pVal, nVal);
|
||||
}
|
||||
|
||||
lsmSortedSaveTreeCursors(pDb);
|
||||
|
||||
Reference in New Issue
Block a user