diff --git a/configure.in b/configure.in index c1aa6b6..723e7f1 100644 --- a/configure.in +++ b/configure.in @@ -16,7 +16,7 @@ AC_PROG_LN_S AC_PROG_MAKE_SET ## Need AC_PROG_LIBTOOL AC_PROG_LIBTOOL -AC_PROG_RANLIB +#AC_PROG_RANLIB # Checks for libraries. diff --git a/lladd/operations/noop.h b/lladd/operations/noop.h index f19f016..f1465d7 100644 --- a/lladd/operations/noop.h +++ b/lladd/operations/noop.h @@ -55,5 +55,5 @@ terms specified in this license. #define __NOOP_H__ Operation getNoop(); - +int noop(int xid, Page *p, lsn_t lsn, recordid rid, const void *dat); #endif diff --git a/src/lladd/operations.c b/src/lladd/operations.c index 1b0a311..b2d9246 100644 --- a/src/lladd/operations.c +++ b/src/lladd/operations.c @@ -73,7 +73,12 @@ void redoUpdate(const LogEntry * e) { if(e->LSN > pageLSN) { DEBUG("OPERATION Redo, %ld > %ld {%d %d %ld}\n", e->LSN, pageLSN, rid.page, rid.slot, rid.size); - doUpdate(e, p); + // doUpdate(e, p); + // Need to check the id field to find out what the _REDO_ action is for this log type. + // contrast with doUpdate(), which doesn't use the .id field. + operationsTable[operationsTable[e->contents.update.funcID].id] + .run(e->xid, p, e->LSN, e->contents.update.rid, getUpdateArgs(e)); + } else { DEBUG("OPERATION Skipping redo, %ld <= %ld {%d %d %ld}\n", e->LSN, pageLSN, rid.page, rid.slot, rid.size); } @@ -82,17 +87,20 @@ void redoUpdate(const LogEntry * e) { } else if(e->type == CLRLOG) { LogEntry * f = readLSNEntry(e->contents.clr.thisUpdateLSN); recordid rid = f->contents.update.rid; - Page * p; - try { - p = loadPage(e->xid, rid.page); - } end; - - assert(rid.page == e->contents.update.rid.page); /* @todo Should this always hold? */ + Page * p = NULL; + int isNullRid = !memcmp(&rid, &NULLRID, sizeof(recordid)); + if(!isNullRid) { + try { + p = loadPage(e->xid, rid.page); + } end; + } + // assert(rid.page == e->contents.update.rid.page); /* @todo Should this always hold? */ + /* See if the page contains the result of the undo that this CLR is supposed to perform. If it doesn't, then undo the original operation. */ /* if(f->LSN > pageReadLSN(e->contents.update.rid.page)) { */ - if(f->LSN > pageReadLSN(p)) { + if(isNullRid || f->LSN > pageReadLSN(p)) { DEBUG("OPERATION Undoing for clr, %ld {%d %d %ld}\n", f->LSN, rid.page, rid.slot, rid.size); undoUpdate(f, p, e->LSN); diff --git a/src/lladd/operations/linearHashNTA.c b/src/lladd/operations/linearHashNTA.c index 0dbdc2c..5b14f0e 100644 --- a/src/lladd/operations/linearHashNTA.c +++ b/src/lladd/operations/linearHashNTA.c @@ -8,6 +8,7 @@ #include #include #include +#include static pthread_mutex_t linear_hash_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; @@ -60,9 +61,11 @@ compensated_function recordid ThashCreate(int xid, int keySize, int valueSize) { recordid rid = TpagedListAlloc(xid); bucket.slot = i; Tset(xid, bucket, &rid); + // printf("paged list alloced at rid {%d %d %d}\n", rid.page, rid.slot, rid.size); } end_ret(NULLRID); - + } + } else { byte * entry = calloc(1, lhh.buckets.size); for(i = 0; i < HASH_INIT_ARRAY_LIST_COUNT; i++) { @@ -108,6 +111,8 @@ compensated_function static int operateInsert(int xid, Page *p, lsn_t lsn, reco int keySize = args->keySize; int valueSize = args->valueSize; + assert(valueSize >= 0); + byte * key = (byte*)(args+1); byte * value = ((byte*)(args+1))+ keySize; begin_action_ret(pthread_mutex_unlock, &linear_hash_mutex, compensation_error()) { @@ -131,19 +136,23 @@ compensated_function static int operateRemove(int xid, Page *p, lsn_t lsn, reco } Operation getLinearHashInsert() { Operation o = { - OPERATION_NOOP, + // OPERATION_LINEAR_HASH_INSERT, + OPERATION_NOOP, SIZEIS_PAGEID, OPERATION_LINEAR_HASH_REMOVE, &operateInsert + // &noop }; return o; } Operation getLinearHashRemove() { Operation o = { - OPERATION_NOOP, + // OPERATION_LINEAR_HASH_REMOVE, + OPERATION_NOOP, SIZEIS_PAGEID, OPERATION_LINEAR_HASH_INSERT, &operateRemove + //&noop }; return o; } @@ -155,7 +164,7 @@ compensated_function int ThashInsert(int xid, recordid hashHeader, const byte* k arg->hashHeader = hashHeader; arg->keySize = keySize; memcpy(arg+1, key, keySize); - + int ret; /** @todo MEMORY LEAK arg, handle on pthread_cancel.. */ @@ -387,9 +396,13 @@ lladd_hash_iterator * ThashIterator(int xid, recordid hashHeader, int keySize, i it->bucket.slot = 0; it->keySize = keySize; it->valueSize = valueSize; + assert(keySize == lhh.keySize); + assert(valueSize == lhh.valueSize); if(keySize == VARIABLE_LENGTH || valueSize == VARIABLE_LENGTH) { it->it = NULL; - it->pit= TpagedListIterator(xid, it->bucket); + recordid bucketList; + Tread(xid, it->bucket, &bucketList); + it->pit= TpagedListIterator(xid, bucketList); } else { it->pit = NULL; it->it = TlinkedListIterator(xid, it->bucket, it->keySize, it->valueSize); diff --git a/src/lladd/operations/noop.c b/src/lladd/operations/noop.c index 1a71d97..4597c96 100644 --- a/src/lladd/operations/noop.c +++ b/src/lladd/operations/noop.c @@ -48,7 +48,7 @@ terms specified in this license. #include #include "../page.h" -static int operate(int xid, Page *p, lsn_t lsn, recordid rid, const void *dat) { +int noop(int xid, Page *p, lsn_t lsn, recordid rid, const void *dat) { /* If p is null, then this is a logical no-op that spans pages, so do nothing. Otherwise, write the LSN to the appropriate page (to keep recovery happy) and return */ @@ -61,7 +61,7 @@ Operation getNoop() { OPERATION_NOOP, 0, OPERATION_NOOP, - &operate + &noop }; return o; } diff --git a/src/lladd/operations/pageOrientedListNTA.c b/src/lladd/operations/pageOrientedListNTA.c index d9cdb10..a2e778f 100644 --- a/src/lladd/operations/pageOrientedListNTA.c +++ b/src/lladd/operations/pageOrientedListNTA.c @@ -196,6 +196,7 @@ compensated_function int TpagedListMove(int xid, recordid start_list, recordid e compensated_function lladd_pagedList_iterator * TpagedListIterator(int xid, recordid list) { pagedListHeader header; + assert(list.size == sizeof(pagedListHeader)); try_ret(NULL) { Tread(xid, list, &header); } end_ret(NULL); @@ -206,7 +207,7 @@ compensated_function lladd_pagedList_iterator * TpagedListIterator(int xid, reco it->entryRid = list; // printf("slot <- %d\n", header.thisPage); it->entryRid.slot = header.thisPage; - + return it; } diff --git a/src/lladd/transactional2.c b/src/lladd/transactional2.c index 0e4b2e7..5d7d492 100644 --- a/src/lladd/transactional2.c +++ b/src/lladd/transactional2.c @@ -78,7 +78,15 @@ void setupOperationsTable() { operationsTable[OPERATION_LINEAR_HASH_INSERT] = getLinearHashInsert(); operationsTable[OPERATION_LINEAR_HASH_REMOVE] = getLinearHashRemove(); + + int i; + /* for(i = 0; i <= OPERATION_LINEAR_HASH_REMOVE; i++) { + if(operationsTable[i].id != i) { + printf("mismatch %d -> %d\n", i, operationsTable[i].id); + } + } + */ } diff --git a/test/lladd/check_linearHashNTA.c b/test/lladd/check_linearHashNTA.c index 0ecaee4..6b6bf38 100644 --- a/test/lladd/check_linearHashNTA.c +++ b/test/lladd/check_linearHashNTA.c @@ -311,6 +311,53 @@ START_TEST(linearHashNTAIteratortest) { Tdeinit(); } END_TEST +START_TEST(emptyHashIterator) { + Tinit(); + int xid = Tbegin(); + + recordid hash = ThashCreate(xid, sizeof(int), sizeof(recordid)); + + lladd_hash_iterator * it = ThashIterator(xid, hash, sizeof(int), sizeof(recordid)); + + byte * key; + byte * value; + int keySize; + int valueSize; + + while(ThashNext(xid, it, &key, &keySize, &value, &valueSize)) { + abort(); + } + + Tabort(xid); + + Tdeinit(); + + +} END_TEST +START_TEST(emptyHashIterator2) { + Tinit(); + int xid = Tbegin(); + + recordid hash = ThashCreate(xid, sizeof(int), VARIABLE_LENGTH); + + lladd_hash_iterator * it = ThashIterator(xid, hash, sizeof(int), VARIABLE_LENGTH); + + byte * key; + byte * value; + int keySize; + int valueSize; + + while(ThashNext(xid, it, &key, &keySize, &value, &valueSize)) { + abort(); + } + + Tabort(xid); + + Tdeinit(); + + +} END_TEST + Suite * check_suite(void) { Suite *s = suite_create("linearHashNTA"); /* Begin a new test */ @@ -318,6 +365,8 @@ Suite * check_suite(void) { /* Sub tests are added, one per line, here */ + tcase_add_test(tc, emptyHashIterator); + tcase_add_test(tc, emptyHashIterator2); tcase_add_test(tc, linearHashNTAVariableSizetest); tcase_add_test(tc, linearHashNTAIteratortest); tcase_add_test(tc, linearHashNTAtest); diff --git a/test/lladd/check_pageOrientedList.c b/test/lladd/check_pageOrientedList.c index bb89d21..0b10277 100644 --- a/test/lladd/check_pageOrientedList.c +++ b/test/lladd/check_pageOrientedList.c @@ -51,6 +51,23 @@ terms specified in this license. #define LOG_NAME "check_pageOrientedListNTA.log" /** @test */ #define NUM_ENTRIES 3000 +START_TEST(emptyIterator) { + Tinit(); + int xid = Tbegin(); + recordid list = TpagedListAlloc(xid); + lladd_pagedList_iterator * it = TpagedListIterator(xid, list); + + int keySize; + int valueSize; + int * key = 0; + recordid * value = 0; + + while(TpagedListNext(xid, it, (byte**)&key, &keySize, (byte**)&value, &valueSize)) { + abort(); + } + Tcommit(xid); +} END_TEST + START_TEST(pagedListCheck) { Tinit(); @@ -182,6 +199,7 @@ Suite * check_suite(void) { /* Sub tests are added, one per line, here */ + tcase_add_test(tc, emptyIterator); tcase_add_test(tc, pagedListCheck); /* --------------------------------------------- */ diff --git a/test/lladd/check_recovery.c b/test/lladd/check_recovery.c index cd3b120..d1a71d7 100644 --- a/test/lladd/check_recovery.c +++ b/test/lladd/check_recovery.c @@ -482,6 +482,7 @@ START_TEST (recovery_multiple_xacts) { fail_unless(j2 == 2, NULL); fail_unless(j3 == 4, NULL); fail_unless(j4 == 4, NULL); + assert(j4 == 4); Tdeinit(); } END_TEST