Fixed page leak in Talloc().

This commit is contained in:
Sears Russell 2006-07-21 01:07:09 +00:00
parent eb13531c0f
commit 0725af91be
6 changed files with 81 additions and 51 deletions

View file

@ -80,12 +80,12 @@ terms specified in this license.
#define PAGE_SIZE 4096
//#define MAX_BUFFER_SIZE 100003
#define MAX_BUFFER_SIZE 100003
/*#define MAX_BUFFER_SIZE 20029 */
//#define MAX_BUFFER_SIZE 10007
//#define MAX_BUFFER_SIZE 5003
//#define MAX_BUFFER_SIZE 2003
#define MAX_BUFFER_SIZE 4006
//#define MAX_BUFFER_SIZE 4006
/* #define MAX_BUFFER_SIZE 71 */
/*#define MAX_BUFFER_SIZE 7 */

View file

@ -187,6 +187,7 @@ compensated_function recordid Talloc(int xid, unsigned long size) {
slottedPageInitialize(p);
}
rid = TallocFromPageInternal(xid, p, size);
releasePage(p);
} compensate_ret(NULLRID);
return rid;
}
@ -221,7 +222,7 @@ static compensated_function recordid TallocFromPageInternal(int xid, Page * p, u
if(slottedFreespace(p) < slotSize) {
slottedCompact(p);
}
}
if(slottedFreespace(p) < slotSize) {
rid = NULLRID;
} else {

View file

@ -38,6 +38,8 @@ compensated_function int TpageSet(int xid, int pageid, byte * memAddr) {
return 0;
}
/** @todo this should be dynamic. */
#define TALLOC_PAGE_REGION_SIZE 128 // 512K
/**
This calls loadPage and releasePage directly, and bypasses the
@ -47,6 +49,12 @@ compensated_function void pageOperationsInit() {
regionsInit();
boundary_tag t;
recordid rid = {0, 0, sizeof(boundary_tag)};
// Need to find a region with some free pages in it.
Tread(-1, rid, &t);
pthread_mutex_init(&pageAllocMutex, NULL);
}

View file

@ -30,10 +30,10 @@ static void TreadBoundaryTag(int xid, unsigned int page, boundary_tag* tag) {
// printf("Reading boundary tag at %d\n", page);
recordid rid = { page, 0, sizeof(boundary_tag) };
Tread(xid, rid, tag);
Page * p = loadPage(xid, page);
// Page * p = loadPage(xid, page);
// printf("regions.c: %d\n", *page_type_ptr(p)); fflush(NULL);
assert(*page_type_ptr(p) == BOUNDARY_TAG_PAGE);
releasePage(p);
// assert(*page_type_ptr(p) == BOUNDARY_TAG_PAGE);
// releasePage(p);
}
static void TsetBoundaryTag(int xid, unsigned int page, boundary_tag* tag) {
// printf("Writing boundary tag at %d\n", page);
@ -44,7 +44,6 @@ static void TsetBoundaryTag(int xid, unsigned int page, boundary_tag* tag) {
void regionsInit() {
Page * p = loadPage(-1, 0);
int pageType = *page_type_ptr(p);
releasePage(p);
if(pageType != BOUNDARY_TAG_PAGE) {
boundary_tag t;
t.size = UINT32_MAX;
@ -61,10 +60,9 @@ void regionsInit() {
// after a crash.
recordid rid = {0,0,sizeof(boundary_tag)};
Page * p = loadPage (-1, 0);
operate_alloc_boundary_tag(0,p,0,rid,&t);
releasePage(p);
}
releasePage(p);
}
pthread_mutex_t region_mutex = PTHREAD_MUTEX_INITIALIZER;

View file

@ -7,7 +7,7 @@
#include <assert.h>
static void really_do_ralloc(Page * page, recordid rid) ;
size_t slottedFreespaceForSlot(Page * page, int slot);
/**
Move all of the records to the beginning of the page in order to
@ -92,6 +92,9 @@ void slottedCompact(Page * page) {
}
memcpy(page->memAddr, buffer, PAGE_SIZE);
assert(slottedFreespaceForSlot(page, -1) || 1);
}
/**
@ -128,7 +131,7 @@ void slottedPageDeInit() {
void slottedPageInitialize(Page * page) {
/*printf("Initializing page %d\n", page->id);
fflush(NULL); */
memset(page->memAddr, 0, PAGE_SIZE);
// memset(page->memAddr, 0, PAGE_SIZE);
*page_type_ptr(page) = SLOTTED_PAGE;
*freespace_ptr(page) = 0;
*numslots_ptr(page) = 0;
@ -144,10 +147,13 @@ size_t slottedFreespaceUnlocked(Page * page);
size_t slottedFreespaceForSlot(Page * page, int slot) {
size_t slotOverhead;
if(slot >= 0 && slot < *numslots_ptr(page)) {
if(slot == -1) {
slotOverhead = (*freelist_ptr(page) == INVALID_SLOT) ? SLOTTED_PAGE_OVERHEAD_PER_RECORD : 0;
} else if(slot < *numslots_ptr(page)) {
slotOverhead = 0;
} else {
slotOverhead = SLOTTED_PAGE_OVERHEAD_PER_RECORD * (*numslots_ptr(page) - slot);
// slotOverhead = SLOTTED_PAGE_OVERHEAD_PER_RECORD * (*numslots_ptr(page) - slot);
slotOverhead = SLOTTED_PAGE_OVERHEAD_PER_RECORD * ((slot+1) - *numslots_ptr(page));
}
// end_of_free_space points to the beginning of the slot header at the bottom of the page header.
byte* end_of_free_space = (byte*)slot_length_ptr(page, (*numslots_ptr(page))-1);
@ -204,7 +210,7 @@ recordid slottedRawRalloc(Page * page, int size) {
if(*freelist_ptr(page) != INVALID_SLOT) {
rid.slot = *freelist_ptr(page);
*freelist_ptr(page) = *slot_length_ptr(page, rid.slot);
*slot_length_ptr(page, rid.slot) = 0;
*slot_length_ptr(page, rid.slot) = INVALID_SLOT;
}
really_do_ralloc(page, rid);
@ -237,13 +243,6 @@ static void really_do_ralloc(Page * page, recordid rid) {
short freeSpace;
/* int isBlob = 0;
if(rid.size == BLOB_SLOT) {
isBlob = 1;
rid.size = sizeof(blob_record_t);
} */
// Compact the page if we don't have enough room.
if(slottedFreespaceForSlot(page, rid.slot) < physical_slot_length(rid.size)) {
slottedCompact(page);
@ -269,6 +268,8 @@ static void really_do_ralloc(Page * page, recordid rid) {
}
while(next != INVALID_SLOT && next != rid.slot) {
last = next;
short next_slot_ptr = *slot_ptr(page, next);
assert(next_slot_ptr == INVALID_SLOT);
next = *slot_length_ptr(page, next);
}
if(next == rid.slot) {
@ -285,40 +286,51 @@ static void really_do_ralloc(Page * page, recordid rid) {
// promote the reuse of free slot numbers, we go out of our way to make sure
// that we put them in the list in increasing order. (Note: slottedCompact's
// correctness depends on this behavior!)
short lastFree = INVALID_SLOT;
while(*numslots_ptr(page) < rid.slot) {
int slot = *numslots_ptr(page);
short successor;
if(lastFree == INVALID_SLOT) {
// The first time through, get our successor pointer from the
// page's freelist pointer.
if(rid.slot > *numslots_ptr(page)) {
short lastSlot;
short numSlots = *numslots_ptr(page);
if(*freelist_ptr(page) == INVALID_SLOT) {
// @todo Grab this from the *end* of the freelist, since we
// know that each slot we are about to insert has a higher number
// than anything in the list.
*freelist_ptr(page) = numSlots;
lastSlot = numSlots;
successor = *freelist_ptr(page);
*freelist_ptr(page) = slot;
} else {
// Put this page after the last page we inserted into the list
successor = *slot_length_ptr(page, lastFree);
*slot_length_ptr(page, lastFree) = slot;
*slot_ptr(page, lastSlot) = INVALID_SLOT;
// will set slot_length_ptr on next iteration.
(*numslots_ptr(page))++;
} else {
lastSlot = INVALID_SLOT;
short next = *freelist_ptr(page);
while(next != INVALID_SLOT) {
lastSlot = next;
next = *slot_length_ptr(page, lastSlot);
assert(lastSlot < *numslots_ptr(page));
assert(*slot_ptr(page, lastSlot) == INVALID_SLOT);
}
*slot_ptr(page, lastSlot) = INVALID_SLOT;
// Make sure that we didn't just find an allocated page on the free list.
assert(*slot_ptr(page, lastFree) == INVALID_SLOT);
}
// Update the pointers in the new slot header.
*slot_length_ptr(page, slot) = successor;
*slot_ptr(page, slot) = INVALID_SLOT;
(*numslots_ptr(page))++;
lastFree = slot;
// lastSlot now contains the tail of the free list. We can start adding slots to the list starting at *numslots_ptr.
while(*numslots_ptr(page) < rid.slot) {
*slot_length_ptr(page, lastSlot) = *numslots_ptr(page);
lastSlot = *numslots_ptr(page);
*slot_ptr(page, lastSlot) = INVALID_SLOT;
(*numslots_ptr(page))++;
}
// Terminate the end of the list.
*slot_length_ptr(page, lastSlot) = INVALID_SLOT;
}
// Increment numslots_ptr if necessary.
if(*numslots_ptr(page) == rid.slot) {
(*numslots_ptr(page))++;
}
*numslots_ptr(page) = rid.slot+1;
}
DEBUG("Num slots %d\trid.slot %d\n", *numslots_ptr(page), rid.slot);
@ -333,6 +345,7 @@ static void really_do_ralloc(Page * page, recordid rid) {
//} else {
*slot_length_ptr(page, rid.slot) = rid.size;
//}
assert(slottedFreespaceForSlot(page, -1) || 1);
}
/**
@ -398,8 +411,11 @@ recordid slottedPostRalloc(int xid, Page * page, lsn_t lsn, recordid rid) {
pageWriteLSN(xid, page, lsn);
assert(slottedFreespaceForSlot(page, -1) || 1);
writeunlock(page->rwlatch);
return rid;
}
@ -408,6 +424,7 @@ void slottedDeRalloc(int xid, Page * page, lsn_t lsn, recordid rid) {
// readlock(page->rwlatch, 443);
size_t oldFreeLen = slottedFreespaceUnlocked(page);
*slot_ptr(page, rid.slot) = INVALID_SLOT;
assert(*freelist_ptr(page) < *numslots_ptr(page));
*slot_length_ptr(page, rid.slot) = *freelist_ptr(page);
*freelist_ptr(page) = rid.slot;
/* *slot_length_ptr(page, rid.slot) = 0; */

View file

@ -133,7 +133,7 @@ START_TEST(linearHashNTAVariableSizetest)
recordid hashHeader = ThashCreate(xid, VARIABLE_LENGTH, VARIABLE_LENGTH);
recordid * val2;
int i;
printf("\n"); fflush(stdout);
printf("\nstart test\n"); fflush(stdout);
for(i = 0; i < NUM_ENTRIES; i++) {
if(!(i % (NUM_ENTRIES/10))) {
printf("."); fflush(stdout);
@ -141,21 +141,25 @@ START_TEST(linearHashNTAVariableSizetest)
val.page = i * NUM_ENTRIES;
val.slot = val.page * NUM_ENTRIES;
val.size = val.slot * NUM_ENTRIES;
val2 = 0;
val2 = 0;
int found = ThashLookup(xid, hashHeader, (byte*)&i, sizeof(int), (byte**)&val2);
assert(-1 == found);
ThashInsert(xid, hashHeader, (byte*)&i, sizeof(int), (byte*)&val, sizeof(recordid));
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);
free(val2);
}
printf("\nCalling commit"); fflush(NULL);
Tcommit(xid);
printf("\n"); fflush(stdout);
printf("committed\n"); fflush(NULL);
xid = Tbegin();
for(i = 0; i < NUM_ENTRIES; i+=10){
@ -186,8 +190,10 @@ START_TEST(linearHashNTAVariableSizetest)
assert(val2->size == val2->slot * NUM_ENTRIES);
free(val2);
}
printf("Begin shutdown.\n"); fflush(NULL);
Tcommit(xid);
Tdeinit();
printf("Test completed.\n"); fflush(NULL);
} END_TEST
@ -416,7 +422,7 @@ Suite * check_suite(void) {
tcase_add_test(tc, linearHashNTAIteratortest);
tcase_add_test(tc, linearHashNTAtest);
tcase_add_test(tc, linearHashNTAThreadedTest);
/* --------------------------------------------- */
tcase_add_checked_fixture(tc, setup, teardown);