From 7cf5fdee6e6ab0f57069bbe46de11a925dd1c748 Mon Sep 17 00:00:00 2001 From: Sears Russell Date: Sat, 29 Jan 2005 01:17:37 +0000 Subject: [PATCH] Re-implemented pageOrientedListNTA from scratch. It's now more flexible, but relies on features that are not provided by Talloc/Tdealloc, so performance isn't as good as it could be. --- lladd/operations/pageOrientedListNTA.h | 26 +- src/lladd/operations/alloc.c | 6 +- src/lladd/operations/linearHashNTA.c | 52 ++- src/lladd/operations/pageOrientedListNTA.c | 408 +++++++++------------ src/lladd/page/slotted.c | 14 +- src/lladd/page/slotted.h | 2 + test/lladd/Makefile.am | 2 +- test/lladd/check_linearHashNTA.c | 5 +- test/lladd/check_pageOrientedList.c | 2 +- 9 files changed, 251 insertions(+), 266 deletions(-) diff --git a/lladd/operations/pageOrientedListNTA.h b/lladd/operations/pageOrientedListNTA.h index 5ff6530..5904086 100644 --- a/lladd/operations/pageOrientedListNTA.h +++ b/lladd/operations/pageOrientedListNTA.h @@ -43,8 +43,13 @@ terms specified in this license. /** @file - A linked list implementation designed to handle variable length entries, and - minimize the number of pages spanned by each list. + A linked list implementation designed to handle variable length + entries, and minimize the number of pages spanned by each list. + This linked list implementation is currently used to implement + buckets for the linear hash table. Unfortunately, due to + limitations in the allocation mechanisms, the full benefits of this + linked list implementation are not available to the linear hash + table. The data is stored using the slotted page implementation. @@ -59,12 +64,23 @@ terms specified in this license. #define __pageOrientedListNTA_H -typedef struct { - long page; +//typedef struct { +// long page; /* The slot of the next record to be returned. */ - int slot; +// int slot; +//} lladd_pagedList_iterator; + +typedef struct { + recordid headerRid; + recordid entryRid; } lladd_pagedList_iterator; +typedef struct { + short thisPage; + recordid nextPage; +} pagedListHeader; + + //recordid dereferencePagedListRID(int xid, recordid rid); /** @return 1 if the key was already in the list. */ int TpagedListInsert(int xid, recordid list, const byte * key, int keySize, const byte * value, int valueSize); diff --git a/src/lladd/operations/alloc.c b/src/lladd/operations/alloc.c index ddb93c0..1d14d7e 100644 --- a/src/lladd/operations/alloc.c +++ b/src/lladd/operations/alloc.c @@ -143,7 +143,11 @@ recordid TallocFromPage(int xid, long page, long size) { } else { pthread_mutex_lock(&talloc_mutex); rid = slottedPreRallocFromPage(xid, page, size, &p); - assert(p != NULL); + if(p == NULL) { + assert(rid.size == -1); + pthread_mutex_unlock(&talloc_mutex); + return rid; + } } Tupdate(xid,rid, NULL, OPERATION_ALLOC); diff --git a/src/lladd/operations/linearHashNTA.c b/src/lladd/operations/linearHashNTA.c index 2f554f2..63cf945 100644 --- a/src/lladd/operations/linearHashNTA.c +++ b/src/lladd/operations/linearHashNTA.c @@ -1,10 +1,13 @@ +#define __USE_GNU +#define _GNU_SOURCE +#include #include #include +#include "../page.h" +#include "../page/slotted.h" #include #include #include -#define __USE_GNU -#include static pthread_mutex_t linear_hash_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; @@ -38,7 +41,7 @@ recordid ThashCreate(int xid, int keySize, int valueSize) { recordid hashHeader = Talloc(xid, sizeof(lladd_hash_header)); lladd_hash_header lhh; if(keySize == VARIABLE_LENGTH || valueSize == VARIABLE_LENGTH) { - lhh.buckets = TarrayListAlloc(xid, HASH_INIT_ARRAY_LIST_COUNT, HASH_INIT_ARRAY_LIST_MULT, sizeof(long)); + lhh.buckets = TarrayListAlloc(xid, HASH_INIT_ARRAY_LIST_COUNT, HASH_INIT_ARRAY_LIST_MULT, sizeof(pagedListHeader)); } else { lhh.buckets = TarrayListAlloc(xid, HASH_INIT_ARRAY_LIST_COUNT, HASH_INIT_ARRAY_LIST_MULT, sizeof(lladd_linkedList_entry) + keySize + valueSize); } @@ -49,7 +52,7 @@ recordid ThashCreate(int xid, int keySize, int valueSize) { for(i = 0; i < HASH_INIT_ARRAY_LIST_COUNT; i++) { recordid rid = TpagedListAlloc(xid); bucket.slot = i; - Tset(xid, bucket, &(rid.page)); + Tset(xid, bucket, &rid); } } else { byte * entry = calloc(1, lhh.buckets.size); @@ -152,9 +155,9 @@ static int __ThashInsert(int xid, recordid hashHeader, const byte* key, int keyS lhh.numEntries ++; if(lhh.keySize == VARIABLE_LENGTH || lhh.valueSize == VARIABLE_LENGTH) { - /* if(lhh.numEntries > (int)((double)(lhh.nextSplit + twoToThe(lhh.bits-1)) * (HASH_FILL_FACTOR * 40))) { + if(lhh.numEntries > (int)((double)(lhh.nextSplit + twoToThe(lhh.bits-1)) * (HASH_FILL_FACTOR))) { ThashSplitBucket(xid, hashHeader, &lhh); - } */ + } } else { if(lhh.numEntries > (int)((double)(lhh.nextSplit + twoToThe(lhh.bits-1)) * HASH_FILL_FACTOR)) { ThashSplitBucket(xid, hashHeader, &lhh); @@ -168,15 +171,15 @@ static int __ThashInsert(int xid, recordid hashHeader, const byte* key, int keyS if(lhh.keySize == VARIABLE_LENGTH || lhh.valueSize == VARIABLE_LENGTH) { recordid bucketList; - Tread(xid, bucket, &(bucketList.page)); - bucketList.slot = 0; - bucketList.size = 0; - // int before = TpagedListSpansPages(xid, bucketList); + Tread(xid, bucket, &bucketList); + + // int before = TpagedListSpansPages(xid, bucketList); ret = TpagedListInsert(xid, bucketList, key, keySize, value, valueSize); - int after = TpagedListSpansPages(xid, bucketList); - if(after) { // Page overflowed... - ThashSplitBucket(xid, hashHeader, &lhh); - } + // int after = TpagedListSpansPages(xid, bucketList); + // if(before != after) { // Page overflowed... + // ThashSplitBucket(xid, hashHeader, &lhh); + // ThashSplitBucket(xid, hashHeader, &lhh); + // } } else { assert(lhh.keySize == keySize); assert(lhh.valueSize == valueSize); @@ -229,9 +232,7 @@ static int __ThashRemove(int xid, recordid hashHeader, const byte * key, int key int ret; if(lhh.keySize == VARIABLE_LENGTH || lhh.valueSize == VARIABLE_LENGTH) { recordid bucketList; - Tread(xid, bucket, &(bucketList.page)); - bucketList.slot = 0; - bucketList.size = 0; + Tread(xid, bucket, &bucketList); ret = TpagedListRemove(xid, bucketList, key, keySize); } else { assert(lhh.keySize == keySize); @@ -252,9 +253,7 @@ int ThashLookup(int xid, recordid hashHeader, const byte * key, int keySize, byt int ret; if(lhh.keySize == VARIABLE_LENGTH || lhh.valueSize == VARIABLE_LENGTH) { recordid bucketList; - Tread(xid, bucket, &(bucketList.page)); - bucketList.slot = 0; - bucketList.size = 0; + Tread(xid, bucket, &bucketList); ret = TpagedListFind(xid, bucketList, key, keySize, value); } else { assert(lhh.keySize == keySize); @@ -264,7 +263,7 @@ int ThashLookup(int xid, recordid hashHeader, const byte * key, int keySize, byt return ret; } static void ThashSplitBucket(int xid, recordid hashHeader, lladd_hash_header * lhh) { - // if(1) { return; } + // if(1) { return; } long old_bucket = lhh->nextSplit; long new_bucket = old_bucket + twoToThe(lhh->bits-1); recordid old_bucket_rid = lhh->buckets; @@ -276,7 +275,7 @@ static void ThashSplitBucket(int xid, recordid hashHeader, lladd_hash_header * l recordid new_bucket_list; // will be uninitialized if we have fixed length entries. if(lhh->keySize == VARIABLE_LENGTH || lhh->valueSize == VARIABLE_LENGTH) { new_bucket_list = TpagedListAlloc(xid); - Tset(xid, new_bucket_rid, &(new_bucket_list.page)); + Tset(xid, new_bucket_rid, &new_bucket_list); } else { byte * entry = calloc(1, lhh->buckets.size); Tset(xid, new_bucket_rid, entry); @@ -292,9 +291,8 @@ static void ThashSplitBucket(int xid, recordid hashHeader, lladd_hash_header * l if(lhh->keySize == VARIABLE_LENGTH || lhh->valueSize == VARIABLE_LENGTH) { recordid old_bucket_list; // recordid new_bucket_list; - Tread(xid, old_bucket_rid, &(old_bucket_list.page)); - old_bucket_list.slot = 0; - old_bucket_list.size = 0; + Tread(xid, old_bucket_rid, &old_bucket_list); + // Tread(xid, new_bucket_rid, &(new_bucket_list.page)); // @todo could remember value from above. lladd_pagedList_iterator * pit = TpagedListIterator(xid, old_bucket_list); byte *key, *value; @@ -363,9 +361,7 @@ int ThashNext(int xid, lladd_hash_iterator * it, byte ** key, int * keySize, byt it->bucket.slot++; if(it->bucket.slot < it->numBuckets) { recordid bucketList; - Tread(xid, it->bucket, &(bucketList.page)); - bucketList.slot =0; - bucketList.size =0; + Tread(xid, it->bucket, &bucketList); it->pit = TpagedListIterator(xid, bucketList); } else { free(it); diff --git a/src/lladd/operations/pageOrientedListNTA.c b/src/lladd/operations/pageOrientedListNTA.c index 7848a74..6ad0471 100644 --- a/src/lladd/operations/pageOrientedListNTA.c +++ b/src/lladd/operations/pageOrientedListNTA.c @@ -1,216 +1,173 @@ #include -#include "../blobManager.h" -#include "../page.h" -#include "../page/slotted.h" + + +#include #include #include -/** - Low level function that looks at the page structure, and finds the 'real' recordid - of a page oriented list rid */ -/*recordid dereferencePagedListRID(int xid, recordid rid) { - Page * p = loadPage(rid.page); - while((*numslots_ptr(p)-POLL_NUM_RESERVED) <= rid.slot) { - int oldSlot = rid.slot; - oldSlot -= (*numslots_ptr(p) - POLL_NUM_RESERVED); - rid.slot = POLL_NEXT; - readRecord(xid, p , rid, &rid); - rid.slot = oldSlot; - releasePage(p); - p = loadPage(rid.page); - } - releasePage(p); - rid.slot+=POLL_NUM_RESERVED; - return rid; -}*/ + +typedef struct { + short nextEntry; + short keySize; +} pagedListEntry; recordid TpagedListAlloc(int xid) { - long page = TpageAlloc(xid); - recordid list = TallocFromPage(xid, page, sizeof(long)); - long zero = 0; - Tset(xid, list, &zero); - assert(list.slot == 0); - assert(list.size == sizeof(long)); - return list; -} -int TpagedListSpansPages(int xid, recordid list) { - // TpagedListCompact(int xid, recordid list); + recordid NULLRID; + NULLRID.page = 0; + NULLRID.slot = 0; + NULLRID.size = -1; - list.slot = 0; - list.size = sizeof(long); - long nextPage; - Tread(xid, list, &nextPage); - return nextPage != 0; -} - -/** Should have write lock on page for this whole function. */ -int TpagedListInsert(int xid, recordid list, const byte * key, int keySize, const byte * value, int valueSize) { - int ret = 0; - // if find in list, return 1 - byte * val; - if(-1 != TpagedListFind(xid, list, key, keySize, &val)) { - free(val); - ret = 1; - int removed = TpagedListRemove(xid, list, key, keySize); - assert(removed); - } - Page * p = loadPage(list.page); - int recordSize = (sizeof(short)+keySize+valueSize); - int isBlob = recordSize >= BLOB_THRESHOLD_SIZE; - int realSize = recordSize; - if(isBlob) { - recordSize = sizeof(blob_record_t); - } - - while(slottedFreespace(p) < recordSize) { - // load next page, update some rid somewhere - list.slot = 0; - list.size = sizeof(long); - long nextPage; - readRecord(xid, p, list, &nextPage); - // printf("+ page = %d nextpage=%ld freespace: %d recordsize: %d\n", list.page, nextPage, slottedFreespace(p), recordSize); fflush(stdout); - if(nextPage == 0) { - releasePage(p); - nextPage = TpageAlloc(xid); - Tset(xid, list, &nextPage); - p = loadPage(nextPage); - //slottedPageInitialize(p); - // ** @todo shouldn't a log entry be generated here?? */ - list.page = nextPage; - assert(slottedFreespace(p) >= recordSize); - long zero = 0; - recordid rid = TallocFromPage(xid, list.page, sizeof(long)); - Tset(xid, rid, &zero); - } else { - releasePage(p); - list.page = nextPage; - p = loadPage(nextPage); - - } - } - - if(isBlob) { - recordSize = realSize; - } - - releasePage(p); - // printf("recordsize = %d\n", recordSize); - recordid rid = TallocFromPage(xid, list.page, recordSize); // Allocates a record at a location given by the caller - short* record = malloc(recordSize); - *record = keySize; - memcpy((record+1), key, keySize); - memcpy(((char*)(record+1))+keySize, value, valueSize); - Tset(xid, rid, record); - + recordid ret = Talloc(xid, sizeof(pagedListHeader)); + pagedListHeader header; + header.thisPage = 0; + header.nextPage = NULLRID; + Tset(xid, ret, &header); return ret; } -int TpagedListFind(int xid, recordid list, const byte * key, int keySize, byte ** value) { - long nextPage = 1; - - while (nextPage) { - int i; +int TpagedListInsert(int xid, recordid list, const byte * key, int keySize, const byte * value, int valueSize) { + pagedListHeader header; + Tread(xid, list, &header); + recordid headerRid = list; - Page * p = loadPage(list.page); - - // int pageCount = TrecordsInPage(xid, list.page); - int pageCount = *numslots_ptr(p); - - // printf("%ld\n", nextPage); - //fflush(stdout); + byte * garbage; + int ret = (TpagedListFind(xid, list, key, keySize, &garbage) != -1); + if(ret) { + TpagedListRemove(xid, list, key, keySize); + free(garbage); + } + int entrySize = sizeof(pagedListEntry) + keySize + valueSize; - for(i = 1; i < pageCount; i++) { - recordid entry = list; - entry.slot = i; - // int length = TrecordSize(xid, entry); - int length = getRecordSize(xid,p,entry); - if(length != -1) { // then entry is defined. - short * dat = malloc(length); - entry.size = length; - // Tread(xid, entry, dat); - slottedRead(xid, p, entry, (byte*)dat); - if(*dat == keySize && !memcmp(dat+1, key, keySize)) { - int valueSize = length-keySize-sizeof(short); - *value = malloc(valueSize); - - memcpy(*value, ((byte*)(dat+1))+keySize, valueSize); - - free(dat); - releasePage(p); - return valueSize; - } - free(dat); - } + recordid rid = TallocFromPage(xid, headerRid.page, entrySize); + DEBUG("Alloced rid: {%d %d %d}", rid.page, rid.slot, rid.size); + + // When the loop completes, header will contain the contents of the page header the entry will be inserted into, + // headerrid will contain the rid of that header, and rid will contain the newly allocated recordid + while(rid.size == -1) { + if(header.nextPage.size == -1) { + header.nextPage = Talloc(xid, sizeof(pagedListHeader)); + DEBUG("allocing on new page %d\n", header.nextPage.page); + Tset(xid, headerRid, &header); + pagedListHeader newHead; + newHead.thisPage = 0; + newHead.nextPage.page =0; + newHead.nextPage.slot =0; + newHead.nextPage.size =-1; + Tset(xid, header.nextPage, &newHead); } + headerRid = header.nextPage; + Tread(xid, header.nextPage, &header); + rid = TallocFromPage(xid, headerRid.page, entrySize); + DEBUG("Alloced rid: {%d %d %d}", rid.page, rid.slot, rid.size); + } - // recordid rid = list; + pagedListEntry * dat = malloc(entrySize); + + dat->keySize = keySize; + dat->nextEntry = header.thisPage; + memcpy(dat+1, key, keySize); + memcpy(((byte*)(dat+1))+keySize, value, valueSize); + Tset(xid, rid, dat); + + header.thisPage = rid.slot; + DEBUG("Header.thisPage = %d\n", rid.slot); + Tset(xid, headerRid, &header); + free(dat); + + return ret; +} + +int TpagedListFind(int xid, recordid list, const byte * key, int keySize, byte ** value) { + pagedListHeader header; + Tread(xid, list, &header); + + recordid rid; + rid.page = list.page; + rid.slot = header.thisPage; + + while(rid.slot || header.nextPage.size != -1) { + rid.size = TrecordSize(xid, rid); + + pagedListEntry * dat = malloc(rid.size); + Tread(xid, rid, dat); - list.slot = 0; - list.size = sizeof(long); + if(!memcmp(dat+1, key, keySize)) { + int valueSize = rid.size - keySize - sizeof(pagedListEntry); + *value = malloc(valueSize); + memcpy(*value, ((byte*)(dat+1))+keySize, valueSize); + free(dat); + return valueSize; + } + if(dat->nextEntry) { // another entry on this page + rid.slot = dat->nextEntry; + } else if (header.nextPage.size != -1) { // another page + rid.page = header.nextPage.page; + Tread(xid, header.nextPage, &header); + rid.slot = header.thisPage; + } else { // we've reached the end of the last page + rid.slot = 0; + } + + free(dat); + } - // Tread(xid, list, &nextPage); - slottedRead(xid, p, list, (byte*)&nextPage); - - list.page = nextPage; - - releasePage(p); - - - } return -1; } + int TpagedListRemove(int xid, recordid list, const byte * key, int keySize) { - long nextPage = 1; - - while (nextPage) { - int i; + pagedListHeader header; + Tread(xid, list, &header); + recordid headerRid; + recordid rid; + rid.page = list.page; + rid.slot = header.thisPage; + short lastSlot = -1; + headerRid = list; + while(rid.slot || header.nextPage.size != -1) { + rid.size = TrecordSize(xid, rid); + pagedListEntry * dat = malloc(rid.size); + Tread(xid, rid, dat); + + if(!memcmp(dat+1, key, keySize)) { - Page * p = loadPage(list.page); - - // int pageCount = TrecordsInPage(xid, list.page); - int pageCount = *numslots_ptr(p); - - // printf("%ld\n", nextPage); - fflush(stdout); - - for(i = 1; i < pageCount; i++) { - recordid entry = list; - entry.slot = i; - // int length = TrecordSize(xid, entry); - int length = getRecordSize(xid, p, entry); - if(length != -1) { // then entry is defined. - short * dat = malloc(length); - entry.size = length; - - slottedRead(xid,p,entry,(byte*)dat); - - // Tread(xid, entry, dat); - - if(*dat == keySize && !memcmp(dat+1, key, keySize)) { - releasePage(p); - Tdealloc(xid, entry); - // assert(-1 == TrecordSize(xid, entry)); - free(dat); - return 1; - } - free(dat); + if(lastSlot != -1) { + recordid lastRid = rid; + lastRid.slot = lastSlot; + lastRid.size = TrecordSize(xid, lastRid); + pagedListEntry * lastRidBuf = malloc(lastRid.size); + Tread(xid, lastRid, lastRidBuf); + lastRidBuf->nextEntry = dat->nextEntry; + Tset(xid, lastRid, lastRidBuf); + free(lastRidBuf); + } else { + header.thisPage = dat->nextEntry; + Tset(xid, headerRid, &header); } + Tdealloc(xid, rid); + free(dat); + return 1; + } + if(dat->nextEntry) { // another entry on this page + lastSlot = rid.slot; + rid.slot = dat->nextEntry; + } else if (header.nextPage.size != -1) { // another page + lastSlot = -1; + rid.page = header.nextPage.page; + headerRid = header.nextPage; + Tread(xid, header.nextPage, &header); + rid.slot = header.thisPage; + } else { // we've reached the end of the last page + rid.slot = 0; } - list.slot = 0; - list.size = sizeof(long); + free(dat); + } - // Tread(xid, list, &nextPage); - slottedRead(xid,p,list, (byte*)&nextPage); - - list.page = nextPage; - releasePage(p); - } return 0; - } -int TpagedListMove(int xid, recordid start_list, recordid end_list, const byte *key, int keySize) { + +int TpagedListMove(int xid, recordid start_list, recordid end_list, const byte * key, int keySize) { byte * value; int valueSize = TpagedListFind(xid, start_list, key, keySize, &value); if(valueSize != -1) { @@ -225,57 +182,54 @@ int TpagedListMove(int xid, recordid start_list, recordid end_list, const byte * } } -lladd_pagedList_iterator * TpagedListIterator(int xid, recordid list) { - lladd_pagedList_iterator * ret = malloc(sizeof(lladd_pagedList_iterator)); +lladd_pagedList_iterator * TpagedListIterator(int xid, recordid list) { + pagedListHeader header; + Tread(xid, list, &header); + lladd_pagedList_iterator * it = malloc(sizeof(lladd_pagedList_iterator)); - ret->page = list.page; - ret->slot = 1; + it->headerRid = header.nextPage; + it->entryRid = list; + // printf("slot <- %d\n", header.thisPage); + it->entryRid.slot = header.thisPage; - return ret; + return it; } int TpagedListNext(int xid, lladd_pagedList_iterator * it, - byte ** key, int * keySize, + byte ** key, int * keySize, byte ** value, int * valueSize) { - // printf("next: page %d slot %d\n", it->page, it->slot); - recordid rid; - while(it->page) { - while(it->slot < TrecordsInPage(xid, it->page)) { - rid.page = it->page; - rid.slot = it->slot; - rid.size=TrecordSize(xid, rid); - if(rid.size != -1) { - // found entry! - - byte * dat = malloc(rid.size); - Tread(xid, rid, dat); - - // populate / alloc pointers passed in by caller. - - *keySize = *(short*)dat; - *valueSize = rid.size - *keySize - sizeof(short); + while(it->entryRid.slot || it->headerRid.size != -1) { + if(it->entryRid.slot) { + it->entryRid.size = TrecordSize(xid, it->entryRid); + assert(it->entryRid.size != -1); - *key = malloc(*keySize); - *value = malloc(*valueSize); + pagedListEntry * entry = malloc(it->entryRid.size); + + Tread(xid, it->entryRid, entry); + + *keySize = entry->keySize; + *valueSize = it->entryRid.size - *keySize - sizeof(pagedListEntry); - memcpy(*key, ((short*)dat)+1, *keySize); - memcpy(*value, ((byte*)(((short*)dat)+1)) + *keySize, *valueSize); + *key = malloc(*keySize); + *value = malloc(*valueSize); - free(dat); - it->slot++; - return 1; - } - it->slot++; + memcpy(*key, entry+1, *keySize); + memcpy(*value, ((byte*)(entry+1))+*keySize, *valueSize); + + it->entryRid.slot = entry->nextEntry; + // printf("slotA <- %d\n", it->entryRid.slot); + + free(entry); + return 1; + + } else { // move to next page. + pagedListHeader header; + Tread(xid, it->headerRid, &header); + it->entryRid.page = it->headerRid.page; + it->headerRid = header.nextPage; + it->entryRid.slot = header.thisPage; + // printf("slotB <- %d\n", it->entryRid.slot); } - rid.page = it->page; - rid.slot = 0; - rid.size = sizeof(long); - Tread(xid, rid, &(it->page)); - it->slot = 1; - } - free(it); - return 0; - } diff --git a/src/lladd/page/slotted.c b/src/lladd/page/slotted.c index da2f281..0c2bb0f 100644 --- a/src/lladd/page/slotted.c +++ b/src/lladd/page/slotted.c @@ -18,7 +18,8 @@ increase the available free space. The caller of this function must have a writelock on the page. */ -static void slottedCompact(Page * page) { + +void slottedCompact(Page * page) { int i; Page bufPage; @@ -192,7 +193,16 @@ recordid slottedPreRallocFromPage(int xid, long page, long size, Page **pp) { *pp = loadPage(page); - assert(slottedFreespace(*pp) >= size); + if(slottedFreespace(*pp) < size) { + releasePage(*pp); + *pp = NULL; + recordid rid; + rid.page = 0; + rid.slot = 0; + rid.size = -1; + return rid; + } + if(*page_type_ptr(*pp) == UNINITIALIZED_PAGE) { slottedPageInitialize(*pp); } diff --git a/src/lladd/page/slotted.h b/src/lladd/page/slotted.h index 7d80467..be8f835 100644 --- a/src/lladd/page/slotted.h +++ b/src/lladd/page/slotted.h @@ -206,3 +206,5 @@ int slottedGetType(Page * p, int slot); * */ void slottedSetType(Page * p, int slot, int type); +/** The caller of this function must have a write lock on the page. */ +void slottedCompact(Page * page); diff --git a/test/lladd/Makefile.am b/test/lladd/Makefile.am index 7fc1397..36f218d 100644 --- a/test/lladd/Makefile.am +++ b/test/lladd/Makefile.am @@ -6,6 +6,6 @@ else TESTS = endif noinst_PROGRAMS = $(TESTS) -LDADD = @CHECK_LIBS@ $(top_builddir)/src/lladd/liblladd.a $(top_builddir)/src/pbl/libpbl.a $(top_builddir)/src/libdfa/librw.a # -lefence +LDADD = @CHECK_LIBS@ $(top_builddir)/src/lladd/liblladd.a $(top_builddir)/src/pbl/libpbl.a $(top_builddir)/src/libdfa/librw.a #-lefence CLEANFILES = check_lht.log check_logEntry.log storefile.txt logfile.txt blob0_file.txt blob1_file.txt check_blobRecovery.log check_logWriter.log check_operations.log check_recovery.log check_transactional2.log check_page.log check_bufferManager.log check_indirect.log check_bufferMananger.log check_lladdhash.log check_pageOperations.log check_linearhash.log check_linkedListNTA.log check_linearHashNTA.log check_pageOrientedListNTA.log AM_CFLAGS= -g -Wall -pedantic -std=gnu99 diff --git a/test/lladd/check_linearHashNTA.c b/test/lladd/check_linearHashNTA.c index 8e07fea..ae18d88 100644 --- a/test/lladd/check_linearHashNTA.c +++ b/test/lladd/check_linearHashNTA.c @@ -130,9 +130,12 @@ START_TEST(linearHashNTAVariableSizetest) val.page = i * NUM_ENTRIES; val.slot = val.page * NUM_ENTRIES; val.size = val.slot * NUM_ENTRIES; + val2 = 0; assert(-1 == ThashLookup(xid, hashHeader, (byte*)&i, sizeof(int), (byte**)&val2)); ThashInsert(xid, hashHeader, (byte*)&i, sizeof(int), (byte*)&val, sizeof(recordid)); - assert(sizeof(recordid) == ThashLookup(xid, hashHeader, (byte*)&i, sizeof(int), (byte**)&val2)); + val2 =0; + int ret = ThashLookup(xid, hashHeader, (byte*)&i, sizeof(int), (byte**)&val2); + assert(sizeof(recordid) == ret); assert(val2->page == i * NUM_ENTRIES); assert(val2->slot == val2->page * NUM_ENTRIES); assert(val2->size == val2->slot * NUM_ENTRIES); diff --git a/test/lladd/check_pageOrientedList.c b/test/lladd/check_pageOrientedList.c index cdba14a..ccd93bd 100644 --- a/test/lladd/check_pageOrientedList.c +++ b/test/lladd/check_pageOrientedList.c @@ -116,7 +116,7 @@ START_TEST(pagedListCheck) { ret = TpagedListFind(xid, list, (byte*)&a, sizeof(int), (byte**)&bb); - assert(!ret); + assert(-1==ret); assert(!bb); } }