switched to region allocator, but TpageAlloc currently grabs its own region...
This commit is contained in:
parent
3bd79f4e24
commit
ffd3bd960b
11 changed files with 165 additions and 486 deletions
|
@ -84,7 +84,8 @@ terms specified in this license.
|
||||||
/*#define MAX_BUFFER_SIZE 20029 */
|
/*#define MAX_BUFFER_SIZE 20029 */
|
||||||
//#define MAX_BUFFER_SIZE 10007
|
//#define MAX_BUFFER_SIZE 10007
|
||||||
//#define MAX_BUFFER_SIZE 5003
|
//#define MAX_BUFFER_SIZE 5003
|
||||||
#define MAX_BUFFER_SIZE 2003
|
//#define MAX_BUFFER_SIZE 2003
|
||||||
|
#define MAX_BUFFER_SIZE 4006
|
||||||
/* #define MAX_BUFFER_SIZE 71 */
|
/* #define MAX_BUFFER_SIZE 71 */
|
||||||
/*#define MAX_BUFFER_SIZE 7 */
|
/*#define MAX_BUFFER_SIZE 7 */
|
||||||
|
|
||||||
|
@ -143,6 +144,9 @@ terms specified in this license.
|
||||||
#define OPERATION_OASYS_SEMIDIFF_DO 78
|
#define OPERATION_OASYS_SEMIDIFF_DO 78
|
||||||
#define OPERATION_OASYS_SEMIDIFF_REDO 79
|
#define OPERATION_OASYS_SEMIDIFF_REDO 79
|
||||||
|
|
||||||
|
#define STORAGE_MANAGER_NAIVE_PAGE_ALLOC 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* number above should be less than number below */
|
/* number above should be less than number below */
|
||||||
#define MAX_OPERATIONS 80
|
#define MAX_OPERATIONS 80
|
||||||
|
|
|
@ -9,9 +9,28 @@
|
||||||
a newly allocated region are undefined.
|
a newly allocated region are undefined.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int TregionAlloc(int xid, int pageCount, int allocaionManager);
|
typedef struct boundary_tag {
|
||||||
void TregionFree(int xid, int firstPage);
|
unsigned int size;
|
||||||
int TregionSize(int xid, int firstPage);
|
unsigned int prev_size;
|
||||||
|
int status;
|
||||||
|
int region_xid;
|
||||||
|
int allocation_manager;
|
||||||
|
} boundary_tag;
|
||||||
|
|
||||||
|
#define REGION_BASE (123)
|
||||||
|
#define REGION_VACANT (REGION_BASE + 0)
|
||||||
|
#define REGION_ZONED (REGION_BASE + 1)
|
||||||
|
#define REGION_OCCUPIED (REGION_BASE + 2)
|
||||||
|
#define REGION_CONDEMNED (REGION_BASE + 3)
|
||||||
|
|
||||||
|
void regionsInit();
|
||||||
|
|
||||||
|
unsigned int TregionAlloc(int xid, unsigned int pageCount, int allocaionManager);
|
||||||
|
void TregionDealloc(int xid, unsigned int firstPage);
|
||||||
|
unsigned int TregionSize(int xid, unsigned int firstPage);
|
||||||
|
|
||||||
|
/** Currently, this function is O(n) in the number of regions, so be careful! */
|
||||||
|
void TregionFindNthActive(int xid, unsigned int n, unsigned int * firstPage, unsigned int * size);
|
||||||
|
|
||||||
Operation getAllocBoundaryTag();
|
Operation getAllocBoundaryTag();
|
||||||
|
|
||||||
|
|
|
@ -144,69 +144,6 @@ void TallocInit() {
|
||||||
lastFreepage = UINT64_MAX;
|
lastFreepage = UINT64_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*compensated_function recordid TallocOld(int xid, long size) {
|
|
||||||
recordid rid;
|
|
||||||
|
|
||||||
|
|
||||||
// @todo How should blobs be handled? Should Talloc do it? If not,
|
|
||||||
// it's hard for apps to to use it... Similarly, with hints, Talloc
|
|
||||||
// may need to route certain sizes to certain types of pages (eg;
|
|
||||||
// small sizes go to fixed page implementations...)
|
|
||||||
|
|
||||||
int isBlob = size >= BLOB_THRESHOLD_SIZE && size != BLOB_SLOT;
|
|
||||||
|
|
||||||
if(isBlob) {
|
|
||||||
try_ret(NULLRID) {
|
|
||||||
rid = preAllocBlob(xid, size);
|
|
||||||
Tupdate(xid,rid, NULL, OPERATION_ALLOC);
|
|
||||||
} end_ret(NULLRID);
|
|
||||||
} else {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Page * p = NULL;
|
|
||||||
|
|
||||||
begin_action_ret(pthread_mutex_unlock, &talloc_mutex, NULLRID) {
|
|
||||||
pthread_mutex_lock(&talloc_mutex);
|
|
||||||
|
|
||||||
if(lastFreepage == UINT64_MAX) {
|
|
||||||
try_ret(NULLRID) {
|
|
||||||
lastFreepage = TpageAlloc(xid);
|
|
||||||
} end_ret(NULLRID);
|
|
||||||
try_ret(NULLRID) {
|
|
||||||
p = loadPage(xid, lastFreepage);
|
|
||||||
} end_ret(NULLRID);
|
|
||||||
assert(*page_type_ptr(p) == UNINITIALIZED_PAGE);
|
|
||||||
slottedPageInitialize(p);
|
|
||||||
} else {
|
|
||||||
try_ret(NULLRID) {
|
|
||||||
p = loadPage(xid, lastFreepage);
|
|
||||||
} end_ret(NULLRID);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if(slottedFreespace(p) < size ) {
|
|
||||||
releasePage(p);
|
|
||||||
try_ret(NULLRID) {
|
|
||||||
lastFreepage = TpageAlloc(xid);
|
|
||||||
} end_ret(NULLRID);
|
|
||||||
try_ret(NULLRID) {
|
|
||||||
p = loadPage(xid, lastFreepage);
|
|
||||||
} end_ret(NULLRID);
|
|
||||||
slottedPageInitialize(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
rid = slottedRawRalloc(p, size); // <--- Important part.
|
|
||||||
Tupdate(xid, rid, NULL, OPERATION_ALLOC); // <--- This hardcodes "slotted" Should we use TallocFromPage() instead?
|
|
||||||
// @todo does releasePage do the correct error checking? <- Why is this comment here?
|
|
||||||
releasePage(p);
|
|
||||||
} compensate_ret(NULLRID);
|
|
||||||
|
|
||||||
}
|
|
||||||
return rid;
|
|
||||||
|
|
||||||
}*/
|
|
||||||
|
|
||||||
static compensated_function recordid TallocFromPageInternal(int xid, Page * p, unsigned long size);
|
static compensated_function recordid TallocFromPageInternal(int xid, Page * p, unsigned long size);
|
||||||
|
|
||||||
compensated_function recordid Talloc(int xid, unsigned long size) {
|
compensated_function recordid Talloc(int xid, unsigned long size) {
|
||||||
|
|
|
@ -10,110 +10,14 @@
|
||||||
#include "../page/fixed.h"
|
#include "../page/fixed.h"
|
||||||
#include <alloca.h>
|
#include <alloca.h>
|
||||||
|
|
||||||
#ifdef REUSE_PAGES
|
|
||||||
static int freelist;
|
|
||||||
#endif
|
|
||||||
static int freepage;
|
|
||||||
static pthread_mutex_t pageAllocMutex;
|
static pthread_mutex_t pageAllocMutex;
|
||||||
|
|
||||||
/*int __pageAlloc(int xid, Page * p, lsn_t lsn, recordid r, const void * d) {
|
|
||||||
int type = *(int*)d;
|
|
||||||
|
|
||||||
*page_type_ptr(p) = type;
|
|
||||||
/ ** @todo this sort of thing should be done in a centralized way. * /
|
|
||||||
if(type == SLOTTED_PAGE) {
|
|
||||||
slottedPageInitialize(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
int __pageDealloc(int xid, Page * p, lsn_t lsn, recordid r, const void * d) {
|
|
||||||
*page_type_ptr(p) = UNINITIALIZED_PAGE;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
int __pageSet(int xid, Page * p, lsn_t lsn, recordid r, const void * d) {
|
int __pageSet(int xid, Page * p, lsn_t lsn, recordid r, const void * d) {
|
||||||
memcpy(p->memAddr, d, PAGE_SIZE);
|
memcpy(p->memAddr, d, PAGE_SIZE);
|
||||||
pageWriteLSN(xid, p, lsn);
|
pageWriteLSN(xid, p, lsn);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int before;
|
|
||||||
int after;
|
|
||||||
} update_tuple;
|
|
||||||
|
|
||||||
int __update_freepage(int xid, Page * p, lsn_t lsn, recordid r, const void * d) {
|
|
||||||
assert(r.page == 0);
|
|
||||||
const update_tuple * t = d;
|
|
||||||
/* printf("freepage %d -> %d\n", t->before, t->after);
|
|
||||||
fflush(NULL); */
|
|
||||||
* headerFreepage_ptr(p) = t->after;
|
|
||||||
freepage = t->after;
|
|
||||||
pageWriteLSN(xid, p, lsn);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int __update_freespace_inverse(int xid, Page * p, lsn_t lsn, recordid r, const void * d) {
|
|
||||||
#ifdef REUSE_PAGES
|
|
||||||
assert(r.page == 0);
|
|
||||||
const update_tuple * t = d;
|
|
||||||
/* ("freespace %d <- %d\n", t->before, t->after);
|
|
||||||
fflush(NULL); */
|
|
||||||
|
|
||||||
* headerFreepage_ptr(p) = t->before;
|
|
||||||
freepage = t->before;
|
|
||||||
#endif
|
|
||||||
pageWriteLSN(xid, p, lsn);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#ifdef REUSE_PAGES
|
|
||||||
/** @todo need to hold mutex here... */
|
|
||||||
int __update_freelist(int xid, Page * p, lsn_t lsn, recordid r, const void * d) {
|
|
||||||
assert(r.page == 0);
|
|
||||||
|
|
||||||
const update_tuple * t = d;
|
|
||||||
|
|
||||||
/* printf("freelist %d -> %d\n", t->before, t->after);
|
|
||||||
fflush(NULL); */
|
|
||||||
|
|
||||||
* headerFreepagelist_ptr(p) = t->after;
|
|
||||||
freelist = t->after;
|
|
||||||
pageWriteLSN(p, lsn);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int __update_freelist_inverse(int xid, Page * p, lsn_t lsn, recordid r, const void * d) {
|
|
||||||
assert(r.page == 0);
|
|
||||||
const update_tuple * t = d;
|
|
||||||
|
|
||||||
/* printf("freelist %d <- %d\n", t->before, t->after);
|
|
||||||
fflush(NULL); */
|
|
||||||
|
|
||||||
* headerFreepagelist_ptr(p) = t->before;
|
|
||||||
freelist = t->before;
|
|
||||||
pageWriteLSN(p, lsn);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
int __free_page(int xid, Page * p, lsn_t lsn, recordid r, const void * d) {
|
|
||||||
const int * successor = d;
|
|
||||||
/*printf("Unallocing page %d\n", r.page);
|
|
||||||
fflush(NULL); */
|
|
||||||
memset(p->memAddr, 0, PAGE_SIZE);
|
|
||||||
*page_type_ptr(p) = LLADD_FREE_PAGE;
|
|
||||||
*nextfreepage_ptr(p) = *successor;
|
|
||||||
pageWriteLSN(xid, p, lsn);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int __alloc_freed(int xid, Page * p, lsn_t lsn, recordid r, const void * d) {
|
|
||||||
memset(p->memAddr, 0, PAGE_SIZE);
|
|
||||||
pageWriteLSN(xid, p, lsn);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
compensated_function int TpageGet(int xid, int pageid, byte *memAddr) {
|
compensated_function int TpageGet(int xid, int pageid, byte *memAddr) {
|
||||||
Page * q = 0;
|
Page * q = 0;
|
||||||
try_ret(compensation_error()) {
|
try_ret(compensation_error()) {
|
||||||
|
@ -135,35 +39,13 @@ compensated_function int TpageSet(int xid, int pageid, byte * memAddr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** This needs to be called immediately after the storefile is opened,
|
/**
|
||||||
since it needs to perform raw, synchronous I/O on the pagefile for
|
This calls loadPage and releasePage directly, and bypasses the
|
||||||
bootstrapping purposes. */
|
logger.
|
||||||
|
*/
|
||||||
compensated_function void pageOperationsInit() {
|
compensated_function void pageOperationsInit() {
|
||||||
/* Page p;
|
|
||||||
p.rwlatch = initlock();
|
|
||||||
p.loadlatch = initlock();
|
|
||||||
// assert(!posix_memalign((void **)&(p.memAddr), PAGE_SIZE, PAGE_SIZE));
|
|
||||||
p.id = 0;*/
|
|
||||||
Page * p;
|
|
||||||
try {
|
|
||||||
p = loadPage(-1, 0);
|
|
||||||
assert(!compensation_error());
|
|
||||||
} end;
|
|
||||||
/** Release lock on page zero. */
|
|
||||||
|
|
||||||
if(*page_type_ptr(p) != LLADD_HEADER_PAGE) {
|
|
||||||
/*printf("Writing new LLADD header\n"); fflush(NULL); */
|
|
||||||
headerPageInitialize(p);
|
|
||||||
} else {
|
|
||||||
/*printf("Found LLADD header.\n"); fflush(NULL);*/
|
|
||||||
}
|
|
||||||
#ifdef REUSE_PAGES
|
|
||||||
freelist = *headerFreepagelist_ptr(p);
|
|
||||||
#endif
|
|
||||||
freepage = *headerFreepage_ptr(p);
|
|
||||||
|
|
||||||
assert(freepage);
|
regionsInit();
|
||||||
releasePage(p);
|
|
||||||
|
|
||||||
pthread_mutex_init(&pageAllocMutex, NULL);
|
pthread_mutex_init(&pageAllocMutex, NULL);
|
||||||
}
|
}
|
||||||
|
@ -201,104 +83,14 @@ compensated_function void pageOperationsInit() {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
compensated_function int TpageDealloc(int xid, int pageid) {
|
compensated_function int TpageDealloc(int xid, int pageid) {
|
||||||
#ifdef REUSE_PAGES
|
TregionDealloc(xid, pageid); // @todo inefficient hack!
|
||||||
|
|
||||||
begin_action_ret(pthread_mutex_unlock, &pageAllocMutex, -1) {
|
|
||||||
recordid rid;
|
|
||||||
|
|
||||||
update_tuple t;
|
|
||||||
pthread_mutex_lock(&pageAllocMutex);
|
|
||||||
|
|
||||||
rid.page = pageid;
|
|
||||||
rid.slot = 0;
|
|
||||||
rid.size = 0;
|
|
||||||
|
|
||||||
assert(freelist != pageid);
|
|
||||||
t.before = freelist;
|
|
||||||
|
|
||||||
Tupdate(xid, rid, &freelist, OPERATION_FREE_PAGE);
|
|
||||||
|
|
||||||
t.after = pageid;
|
|
||||||
freelist = pageid;
|
|
||||||
rid.page = 0;
|
|
||||||
Tupdate(xid, rid, &t, OPERATION_UPDATE_FREELIST);
|
|
||||||
pthread_mutex_unlock(&pageAllocMutex);
|
|
||||||
} end_action_ret(-1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
compensated_function int TpageAlloc(int xid /*, int type */) {
|
compensated_function int TpageAlloc(int xid /*, int type */) {
|
||||||
recordid rid;
|
return TregionAlloc(xid, 1, STORAGE_MANAGER_NAIVE_PAGE_ALLOC);
|
||||||
update_tuple t;
|
|
||||||
rid.slot = 0;
|
|
||||||
rid.size = 0;
|
|
||||||
|
|
||||||
pthread_mutex_lock(&pageAllocMutex);
|
|
||||||
int newpage;
|
|
||||||
/*printf("TpageAlloc\n"); fflush(NULL); */
|
|
||||||
#ifdef REUSE_PAGES
|
|
||||||
if(freelist) {
|
|
||||||
|
|
||||||
DEBUG("Re-using old page: %d\n", freelist);
|
|
||||||
|
|
||||||
newpage = freelist;
|
|
||||||
|
|
||||||
Page * p;
|
|
||||||
begin_action_ret(pthread_mutex_unlock, &pageAllocMutex, compensation_error()) {
|
|
||||||
p = loadPage(newpage); /* Could obtain write lock here,
|
|
||||||
but this is the only function
|
|
||||||
that should ever touch pages of
|
|
||||||
type LLADD_FREE_PAGE, and we
|
|
||||||
already hold a mutex... */
|
|
||||||
} end_ret(compensation_error());
|
|
||||||
assert(*page_type_ptr(p) == LLADD_FREE_PAGE);
|
|
||||||
t.before = freelist;
|
|
||||||
freelist = *nextfreepage_ptr(p);
|
|
||||||
t.after = freelist;
|
|
||||||
assert(newpage != freelist);
|
|
||||||
releasePage(p);
|
|
||||||
|
|
||||||
begin_action_ret(pthread_mutex_unlock, &pageAllocMutex, compensation_error()) {
|
|
||||||
rid.page = newpage;
|
|
||||||
Tupdate(xid, rid, &freelist, OPERATION_ALLOC_FREED);
|
|
||||||
|
|
||||||
rid.page = 0;
|
|
||||||
Tupdate(xid, rid, &t, OPERATION_UPDATE_FREELIST);
|
|
||||||
} end_ret;
|
|
||||||
rid.page = newpage;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
#endif
|
|
||||||
/*printf("Allocing new page: %d\n", freepage);
|
|
||||||
fflush(NULL); */
|
|
||||||
|
|
||||||
t.before = freepage;
|
|
||||||
newpage = freepage;
|
|
||||||
freepage++;
|
|
||||||
t.after = freepage;
|
|
||||||
|
|
||||||
/*printf("next freepage: %d\n", freepage); */
|
|
||||||
/* Don't need to touch the new page. */
|
|
||||||
|
|
||||||
rid.page = 0;
|
|
||||||
|
|
||||||
begin_action_ret(pthread_mutex_unlock, &pageAllocMutex, compensation_error()) {
|
|
||||||
Tupdate(xid, rid, &t, OPERATION_UPDATE_FREESPACE);
|
|
||||||
} end_action_ret(compensation_error());
|
|
||||||
|
|
||||||
rid.page = newpage;
|
|
||||||
#ifdef REUSE_PAGES
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pthread_mutex_unlock(&pageAllocMutex);
|
|
||||||
/*printf("TpageAlloc alloced page %d\n", newpage); fflush(NULL); */
|
|
||||||
return newpage;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int __fixedPageAlloc(int xid, Page * p, lsn_t lsn, recordid r, const void * d) {
|
int __fixedPageAlloc(int xid, Page * p, lsn_t lsn, recordid r, const void * d) {
|
||||||
fixedPageInitialize(p, r.size, recordsPerPage(r.size));
|
fixedPageInitialize(p, r.size, recordsPerPage(r.size));
|
||||||
pageWriteLSN(xid, p, lsn);
|
pageWriteLSN(xid, p, lsn);
|
||||||
|
@ -307,9 +99,6 @@ int __fixedPageAlloc(int xid, Page * p, lsn_t lsn, recordid r, const void * d) {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@todo TfixedPageAlloc is a huge hack, and it writes an extra 4k to
|
|
||||||
the log each time it is called.
|
|
||||||
|
|
||||||
@return a recordid. The page field contains the page that was
|
@return a recordid. The page field contains the page that was
|
||||||
allocated, the slot field contains the number of slots on the
|
allocated, the slot field contains the number of slots on the
|
||||||
apge, and the size field contains the size of each slot.
|
apge, and the size field contains the size of each slot.
|
||||||
|
@ -318,20 +107,10 @@ recordid TfixedPageAlloc(int xid, int size) {
|
||||||
int page = TpageAlloc(xid);
|
int page = TpageAlloc(xid);
|
||||||
recordid rid = {page, recordsPerPage(size), size};
|
recordid rid = {page, recordsPerPage(size), size};
|
||||||
Tupdate(xid, rid, 0, OPERATION_FIXED_PAGE_ALLOC);
|
Tupdate(xid, rid, 0, OPERATION_FIXED_PAGE_ALLOC);
|
||||||
/* Page * p = loadPage(xid, page);
|
|
||||||
fixedPageInitialize(p , size, recordsPerPage(size));
|
|
||||||
byte * tmpMemAddr = alloca(PAGE_SIZE);
|
|
||||||
memcpy(tmpMemAddr, p->memAddr, PAGE_SIZE);
|
|
||||||
TpageSet(xid, page, tmpMemAddr);
|
|
||||||
releasePage(p);
|
|
||||||
recordid rid;
|
|
||||||
rid.page = page;
|
|
||||||
rid.slot = recordsPerPage(size);
|
|
||||||
rid.size = size; */
|
|
||||||
return rid;
|
return rid;
|
||||||
}
|
}
|
||||||
|
|
||||||
Operation getFixedPageAlloc() {
|
Operation getFixedPageAlloc() {
|
||||||
Operation o = {
|
Operation o = {
|
||||||
OPERATION_FIXED_PAGE_ALLOC,
|
OPERATION_FIXED_PAGE_ALLOC,
|
||||||
0,
|
0,
|
||||||
|
@ -342,29 +121,8 @@ Operation getFixedPageAlloc() {
|
||||||
}
|
}
|
||||||
|
|
||||||
compensated_function int TpageAllocMany(int xid, int count /*, int type*/) {
|
compensated_function int TpageAllocMany(int xid, int count /*, int type*/) {
|
||||||
/* int firstPage = -1;
|
return TregionAlloc(xid, count, STORAGE_MANAGER_NAIVE_PAGE_ALLOC);
|
||||||
int lastPage = -1; */
|
// return 0;//newpage;
|
||||||
recordid rid;
|
|
||||||
rid.slot = 0;
|
|
||||||
rid.size = 0;
|
|
||||||
|
|
||||||
update_tuple t;
|
|
||||||
pthread_mutex_lock(&pageAllocMutex);
|
|
||||||
|
|
||||||
t.before = freepage;
|
|
||||||
int newpage = freepage;
|
|
||||||
freepage += count;
|
|
||||||
t.after = freepage;
|
|
||||||
|
|
||||||
/* Don't need to touch the new pages. */
|
|
||||||
|
|
||||||
rid.page = 0;
|
|
||||||
begin_action_ret(pthread_mutex_unlock, &pageAllocMutex, compensation_error()) {
|
|
||||||
Tupdate(xid, rid, &t, OPERATION_UPDATE_FREESPACE);
|
|
||||||
rid.page = newpage;
|
|
||||||
} compensate_ret(compensation_error());
|
|
||||||
|
|
||||||
return newpage;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Safely allocating and freeing pages is suprisingly complex. Here is a summary of the process:
|
/** Safely allocating and freeing pages is suprisingly complex. Here is a summary of the process:
|
||||||
|
@ -391,111 +149,19 @@ compensated_function int TpageAllocMany(int xid, int count /*, int type*/) {
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Operation getUpdateFreespace() {
|
|
||||||
Operation o = {
|
|
||||||
OPERATION_UPDATE_FREESPACE,
|
|
||||||
sizeof(update_tuple),
|
|
||||||
/* OPERATION_UPDATE_FREESPACE_INVERSE, */ OPERATION_NOOP,
|
|
||||||
&__update_freepage
|
|
||||||
};
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
|
|
||||||
Operation getUpdateFreespaceInverse() {
|
|
||||||
Operation o = {
|
|
||||||
OPERATION_UPDATE_FREESPACE_INVERSE,
|
|
||||||
sizeof(update_tuple),
|
|
||||||
OPERATION_UPDATE_FREESPACE,
|
|
||||||
&__update_freespace_inverse
|
|
||||||
};
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
|
|
||||||
Operation getUpdateFreelist() {
|
|
||||||
Operation o = {
|
|
||||||
OPERATION_UPDATE_FREELIST,
|
|
||||||
sizeof(update_tuple),
|
|
||||||
OPERATION_NOOP,
|
|
||||||
#ifdef REUSE_PAGES
|
|
||||||
&__update_freelist
|
|
||||||
#else
|
|
||||||
NULL
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
|
|
||||||
Operation getUpdateFreelistInverse() {
|
|
||||||
Operation o = {
|
|
||||||
OPERATION_UPDATE_FREELIST_INVERSE,
|
|
||||||
sizeof(update_tuple),
|
|
||||||
OPERATION_UPDATE_FREELIST,
|
|
||||||
#ifdef REUSE_PAGES
|
|
||||||
&__update_freelist_inverse
|
|
||||||
#else
|
|
||||||
NULL
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** frees a page by zeroing it, setting its type to LLADD_FREE_PAGE,
|
/** frees a page by zeroing it, setting its type to LLADD_FREE_PAGE,
|
||||||
and setting the successor pointer. This operation physically logs
|
and setting the successor pointer. This operation physically logs
|
||||||
a whole page, which makes it expensive. Doing so is necessary in
|
a whole page, which makes it expensive. Doing so is necessary in
|
||||||
general, but it is possible that application specific logic could
|
general, but it is possible that application specific logic could
|
||||||
avoid the physical logging here. */
|
avoid the physical logging here.
|
||||||
Operation getFreePageOperation() {
|
|
||||||
Operation o = {
|
Instead, we should just record the fact that the page was freed
|
||||||
OPERATION_FREE_PAGE,
|
somewhere. That way, we don't need to read the page in, or write
|
||||||
sizeof(int),
|
out information about it. If we lock the page against
|
||||||
NO_INVERSE_WHOLE_PAGE,
|
reallocation until the current transaction commits, then we're
|
||||||
&__free_page
|
fine.
|
||||||
};
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** allocs a page that was once freed by zeroing it. */
|
*/
|
||||||
Operation getAllocFreedPage() {
|
|
||||||
Operation o = {
|
|
||||||
OPERATION_ALLOC_FREED,
|
|
||||||
sizeof(int),
|
|
||||||
OPERATION_UNALLOC_FREED,
|
|
||||||
&__alloc_freed
|
|
||||||
};
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
/** does the same thing as getFreePageOperation, but doesn't log a preimage. (Used to undo an alloc of a freed page.) */
|
|
||||||
Operation getUnallocFreedPage() {
|
|
||||||
Operation o = {
|
|
||||||
OPERATION_UNALLOC_FREED,
|
|
||||||
sizeof(int),
|
|
||||||
OPERATION_ALLOC_FREED,
|
|
||||||
&__free_page
|
|
||||||
};
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*Operation getPageAlloc() {
|
|
||||||
Operation o = {
|
|
||||||
OPERATION_PAGE_ALLOC,
|
|
||||||
sizeof(int),
|
|
||||||
OPERATION_PAGE_DEALLOC,
|
|
||||||
&__pageAlloc
|
|
||||||
};
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
|
|
||||||
Operation getPageDealloc() {
|
|
||||||
Operation o = {
|
|
||||||
OPERATION_PAGE_DEALLOC,
|
|
||||||
sizeof(int),
|
|
||||||
OPERATION_PAGE_ALLOC,
|
|
||||||
&__pageDealloc
|
|
||||||
};
|
|
||||||
return o;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
Operation getPageSet() {
|
Operation getPageSet() {
|
||||||
Operation o = {
|
Operation o = {
|
||||||
|
|
|
@ -2,23 +2,11 @@
|
||||||
#include <lladd/operations.h>
|
#include <lladd/operations.h>
|
||||||
#include "../page/slotted.h"
|
#include "../page/slotted.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#define REGION_BASE (123)
|
|
||||||
#define REGION_VACANT (REGION_BASE + 0)
|
|
||||||
#define REGION_ZONED (REGION_BASE + 1)
|
|
||||||
#define REGION_OCCUPIED (REGION_BASE + 2)
|
|
||||||
#define REGION_CONDEMNED (REGION_BASE + 3)
|
|
||||||
|
|
||||||
#define INVALID_XID (-1)
|
#define INVALID_XID (-1)
|
||||||
|
|
||||||
#define boundary_tag_ptr(p) (((byte*)end_of_usable_space_ptr((p)))-sizeof(boundary_tag_t))
|
#define boundary_tag_ptr(p) (((byte*)end_of_usable_space_ptr((p)))-sizeof(boundary_tag_t))
|
||||||
|
|
||||||
typedef struct boundary_tag {
|
|
||||||
int size;
|
|
||||||
int prev_size;
|
|
||||||
int status;
|
|
||||||
int region_xid;
|
|
||||||
int allocation_manager;
|
|
||||||
} boundary_tag;
|
|
||||||
|
|
||||||
static int operate_alloc_boundary_tag(int xid, Page * p, lsn_t lsn, recordid rid, const void * dat) {
|
static int operate_alloc_boundary_tag(int xid, Page * p, lsn_t lsn, recordid rid, const void * dat) {
|
||||||
slottedPageInitialize(p);
|
slottedPageInitialize(p);
|
||||||
|
@ -29,19 +17,26 @@ static int operate_alloc_boundary_tag(int xid, Page * p, lsn_t lsn, recordid rid
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Implement these four functions.
|
// TODO: Implement these four functions.
|
||||||
static void TallocBoundaryTag(int xid, int page, boundary_tag* tag) {
|
static void TallocBoundaryTag(int xid, unsigned int page, boundary_tag* tag) {
|
||||||
|
// printf("Alloc boundary tag at %d\n", page);
|
||||||
recordid rid = {page, 0, sizeof(boundary_tag)};
|
recordid rid = {page, 0, sizeof(boundary_tag)};
|
||||||
Tupdate(xid, rid, tag, OPERATION_ALLOC_BOUNDARY_TAG);
|
Tupdate(xid, rid, tag, OPERATION_ALLOC_BOUNDARY_TAG);
|
||||||
}
|
}
|
||||||
static void TdeallocBoundaryTag(int xid, int page) {
|
static void TdeallocBoundaryTag(int xid, unsigned int page) {
|
||||||
// no-op
|
//no-op
|
||||||
}
|
}
|
||||||
|
|
||||||
static void TreadBoundaryTag(int xid, int page, boundary_tag* tag) {
|
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) };
|
recordid rid = { page, 0, sizeof(boundary_tag) };
|
||||||
Tread(xid, rid, tag);
|
Tread(xid, rid, tag);
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
static void TsetBoundaryTag(int xid, int page, boundary_tag* tag) {
|
static void TsetBoundaryTag(int xid, unsigned int page, boundary_tag* tag) {
|
||||||
|
// printf("Writing boundary tag at %d\n", page);
|
||||||
recordid rid = { page, 0, sizeof(boundary_tag) };
|
recordid rid = { page, 0, sizeof(boundary_tag) };
|
||||||
Tset(xid, rid, tag);
|
Tset(xid, rid, tag);
|
||||||
}
|
}
|
||||||
|
@ -52,60 +47,70 @@ void regionsInit() {
|
||||||
releasePage(p);
|
releasePage(p);
|
||||||
if(pageType != BOUNDARY_TAG_PAGE) {
|
if(pageType != BOUNDARY_TAG_PAGE) {
|
||||||
boundary_tag t;
|
boundary_tag t;
|
||||||
t.size = INT32_MAX;
|
t.size = UINT32_MAX;
|
||||||
t.prev_size = INT32_MAX;
|
t.prev_size = UINT32_MAX;
|
||||||
t.status = REGION_VACANT;
|
t.status = REGION_VACANT;
|
||||||
t.region_xid = INVALID_XID;
|
t.region_xid = INVALID_XID;
|
||||||
t.allocation_manager = 0;
|
t.allocation_manager = 0;
|
||||||
TallocBoundaryTag(-1, 0, &t);
|
|
||||||
|
// This does what TallocBoundaryTag(-1, 0, &t); would do, but it
|
||||||
|
// doesn't produce a log entry. The log entry would be invalid
|
||||||
|
// since we haven't initialized everything yet. We don't need to
|
||||||
|
// flush the page, since this code is deterministic, and will be
|
||||||
|
// re-run before recovery if this update doesn't make it to disk
|
||||||
|
// 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_t region_mutex = PTHREAD_MUTEX_INITIALIZER;
|
pthread_mutex_t region_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
int TregionAlloc(int xid, int pageCount, int allocationManager) {
|
unsigned int TregionAlloc(int xid, unsigned int pageCount, int allocationManager) {
|
||||||
// Initial implementation. Naive first fit.
|
// Initial implementation. Naive first fit.
|
||||||
|
|
||||||
pthread_mutex_lock(®ion_mutex);
|
pthread_mutex_lock(®ion_mutex);
|
||||||
|
|
||||||
int pageid = 0;
|
unsigned int pageid = 0;
|
||||||
boundary_tag t;
|
boundary_tag t;
|
||||||
int prev_size = INT32_MAX;
|
unsigned int prev_size = UINT32_MAX;
|
||||||
|
|
||||||
|
|
||||||
TreadBoundaryTag(xid, pageid, &t); // XXX need to check if there is a boundary tag there or not!
|
TreadBoundaryTag(xid, pageid, &t); // XXX need to check if there is a boundary tag there or not!
|
||||||
|
|
||||||
while(t.status != REGION_VACANT || t.size < pageCount) { // TODO: This while loop and the boundary tag manipulation below should be factored into two submodules.
|
while(t.status != REGION_VACANT || t.size < pageCount) { // TODO: This while loop and the boundary tag manipulation below should be factored into two submodules.
|
||||||
|
// printf("t.status = %d, REGION_VACANT = %d, t.size = %d, pageCount = %d\n", t.status, REGION_VACANT, t.size, pageCount);
|
||||||
|
assert(t.prev_size == prev_size);
|
||||||
prev_size = t.size;
|
prev_size = t.size;
|
||||||
pageid += ( t.size + 1 );
|
pageid += ( t.size + 1 );
|
||||||
TreadBoundaryTag(xid, pageid, &t);
|
TreadBoundaryTag(xid, pageid, &t);
|
||||||
}
|
}
|
||||||
|
// printf("page = %d, t.status = %d, REGION_VACANT = %d, t.size = %d, pageCount = %d (alloced)\n", pageid, t.status, REGION_VACANT, t.size, pageCount);
|
||||||
|
|
||||||
t.status = REGION_ZONED;
|
assert(t.prev_size == prev_size);
|
||||||
t.region_xid = xid;
|
|
||||||
t.allocation_manager = allocationManager;
|
|
||||||
assert(t.prev_size = prev_size);
|
|
||||||
if(t.size != pageCount) {
|
if(t.size != pageCount) {
|
||||||
// need to split region
|
// need to split region
|
||||||
|
|
||||||
// allocate new boundary tag.
|
// allocate new boundary tag.
|
||||||
|
|
||||||
int newPageid = pageid + pageCount + 1;
|
unsigned int newPageid = pageid + pageCount + 1;
|
||||||
boundary_tag new_tag;
|
boundary_tag new_tag;
|
||||||
|
|
||||||
if(t.size != INT32_MAX) {
|
if(t.size != UINT32_MAX) {
|
||||||
|
|
||||||
new_tag.size = t.size - pageCount - 1; // pageCount must be strictly less than t->size, so this is non-negative.
|
new_tag.size = t.size - pageCount - 1; // pageCount must be strictly less than t->size, so this is non-negative.
|
||||||
|
|
||||||
boundary_tag succ_tag;
|
boundary_tag succ_tag;
|
||||||
|
|
||||||
TreadBoundaryTag(xid, pageid + t.size + 1, &succ_tag);
|
TreadBoundaryTag(xid, pageid + t.size + 1, &succ_tag);
|
||||||
succ_tag.prev_size = pageCount;
|
succ_tag.prev_size = new_tag.size;
|
||||||
TsetBoundaryTag(xid, pageid + t.size + 1, &succ_tag);
|
TsetBoundaryTag(xid, pageid + t.size + 1, &succ_tag);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
new_tag.size = INT32_MAX;
|
new_tag.size = UINT32_MAX;
|
||||||
|
|
||||||
}
|
}
|
||||||
new_tag.prev_size = pageCount;
|
new_tag.prev_size = pageCount;
|
||||||
|
@ -121,14 +126,19 @@ int TregionAlloc(int xid, int pageCount, int allocationManager) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t.status = REGION_ZONED;
|
||||||
|
t.region_xid = xid;
|
||||||
|
t.allocation_manager = allocationManager;
|
||||||
|
t.size = pageCount;
|
||||||
|
|
||||||
TsetBoundaryTag(xid, pageid, &t);
|
TsetBoundaryTag(xid, pageid, &t);
|
||||||
|
|
||||||
pthread_mutex_unlock(®ion_mutex);
|
pthread_mutex_unlock(®ion_mutex);
|
||||||
|
|
||||||
return pageid;
|
return pageid+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TregionFree(int xid, int firstPage) {
|
void TregionDealloc(int xid, unsigned int firstPage) {
|
||||||
|
|
||||||
// Note that firstPage is the first *caller visible* page in the
|
// Note that firstPage is the first *caller visible* page in the
|
||||||
// region. The boundary tag is stored on firstPage - 1. Also, note
|
// region. The boundary tag is stored on firstPage - 1. Also, note
|
||||||
|
@ -141,15 +151,18 @@ void TregionFree(int xid, int firstPage) {
|
||||||
boundary_tag t;
|
boundary_tag t;
|
||||||
TreadBoundaryTag(xid, firstPage - 1, &t);
|
TreadBoundaryTag(xid, firstPage - 1, &t);
|
||||||
|
|
||||||
|
assert(t.status != REGION_VACANT);
|
||||||
|
t.status = REGION_VACANT;
|
||||||
|
|
||||||
// If successor is vacant, merge.
|
// If successor is vacant, merge.
|
||||||
if(t.size != INT32_MAX) { // is there a successor?
|
if(t.size != UINT32_MAX) { // is there a successor?
|
||||||
int succ_page = firstPage + t.size;
|
unsigned int succ_page = firstPage + t.size;
|
||||||
boundary_tag succ_tag;
|
boundary_tag succ_tag;
|
||||||
TreadBoundaryTag(xid, succ_page, &succ_tag);
|
TreadBoundaryTag(xid, succ_page, &succ_tag);
|
||||||
|
|
||||||
// TODO: Check page_type_ptr()...
|
// TODO: Check page_type_ptr()...
|
||||||
if(succ_tag.size == INT32_MAX) {
|
if(succ_tag.size == UINT32_MAX) {
|
||||||
t.size = INT32_MAX;
|
t.size = UINT32_MAX;
|
||||||
|
|
||||||
// TODO: Truncate page file.
|
// TODO: Truncate page file.
|
||||||
TdeallocBoundaryTag(xid, succ_page);
|
TdeallocBoundaryTag(xid, succ_page);
|
||||||
|
@ -157,7 +170,7 @@ void TregionFree(int xid, int firstPage) {
|
||||||
} else if(succ_tag.status == REGION_VACANT) {
|
} else if(succ_tag.status == REGION_VACANT) {
|
||||||
|
|
||||||
t.size = t.size + succ_tag.size + 1;
|
t.size = t.size + succ_tag.size + 1;
|
||||||
int succ_succ_page = succ_page + succ_tag.size + 1;
|
unsigned int succ_succ_page = succ_page + succ_tag.size + 1;
|
||||||
|
|
||||||
boundary_tag succ_succ_tag;
|
boundary_tag succ_succ_tag;
|
||||||
|
|
||||||
|
@ -175,16 +188,16 @@ void TregionFree(int xid, int firstPage) {
|
||||||
// creates a situation where the current page is not a boundary
|
// creates a situation where the current page is not a boundary
|
||||||
// tag...)
|
// tag...)
|
||||||
|
|
||||||
if(t.prev_size != INT32_MAX) {
|
if(t.prev_size != UINT32_MAX) {
|
||||||
|
|
||||||
int pred_page = (firstPage - 2) - t.prev_size; // If the predecessor is length zero, then it's boundary tag is two pages before this region's tag.
|
unsigned int pred_page = (firstPage - 2) - t.prev_size; // If the predecessor is length zero, then it's boundary tag is two pages before this region's tag.
|
||||||
|
|
||||||
boundary_tag pred_tag;
|
boundary_tag pred_tag;
|
||||||
TreadBoundaryTag(xid, pred_page, &pred_tag);
|
TreadBoundaryTag(xid, pred_page, &pred_tag);
|
||||||
|
|
||||||
if(pred_tag.status == REGION_VACANT) {
|
if(pred_tag.status == REGION_VACANT) {
|
||||||
if(t.size == INT32_MAX) {
|
if(t.size == UINT32_MAX) {
|
||||||
pred_tag.size = INT32_MAX;
|
pred_tag.size = UINT32_MAX;
|
||||||
|
|
||||||
// TODO: truncate region
|
// TODO: truncate region
|
||||||
|
|
||||||
|
@ -192,15 +205,16 @@ void TregionFree(int xid, int firstPage) {
|
||||||
|
|
||||||
pred_tag.size += (t.size + 1);
|
pred_tag.size += (t.size + 1);
|
||||||
|
|
||||||
int succ_page = firstPage + t.size;
|
unsigned int succ_page = firstPage + t.size;
|
||||||
|
assert(pred_page + pred_tag.size + 1 == succ_page);
|
||||||
|
|
||||||
boundary_tag succ_tag;
|
boundary_tag succ_tag;
|
||||||
TreadBoundaryTag(xid, succ_page, &succ_tag);
|
TreadBoundaryTag(xid, succ_page, &succ_tag);
|
||||||
succ_tag.prev_size = pred_tag.size;
|
succ_tag.prev_size = pred_tag.size;
|
||||||
TsetBoundaryTag(xid, succ_page, &succ_tag);
|
TsetBoundaryTag(xid, succ_page, &succ_tag);
|
||||||
|
|
||||||
assert(succ_tag.status != REGION_VACANT);
|
assert(succ_tag.status != REGION_VACANT);
|
||||||
assert(succ_page - pred_page == pred_tag.size);
|
assert(succ_page - pred_page - 1 == pred_tag.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
TsetBoundaryTag(xid, pred_page, &pred_tag);
|
TsetBoundaryTag(xid, pred_page, &pred_tag);
|
||||||
|
@ -219,13 +233,39 @@ void TregionFree(int xid, int firstPage) {
|
||||||
Operation getAllocBoundaryTag() {
|
Operation getAllocBoundaryTag() {
|
||||||
Operation o = {
|
Operation o = {
|
||||||
OPERATION_ALLOC_BOUNDARY_TAG,
|
OPERATION_ALLOC_BOUNDARY_TAG,
|
||||||
sizeof(int),
|
sizeof(boundary_tag),
|
||||||
OPERATION_NOOP,
|
OPERATION_NOOP,
|
||||||
&operate_alloc_boundary_tag
|
&operate_alloc_boundary_tag
|
||||||
};
|
};
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TregionFindNthActive(int xid, unsigned int regionNumber, unsigned int * firstPage, unsigned int * size) {
|
||||||
|
boundary_tag t;
|
||||||
|
recordid rid = {0, 0, sizeof(boundary_tag)};
|
||||||
|
Tread(xid, rid, &t);
|
||||||
|
unsigned int prevSize = 0;
|
||||||
|
while(t.status == REGION_VACANT) {
|
||||||
|
rid.page += (t.size + 1);
|
||||||
|
Tread(xid, rid, &t);
|
||||||
|
assert(t.size != UINT_MAX);
|
||||||
|
assert(t.prev_size != UINT_MAX);
|
||||||
|
assert(prevSize == t.prev_size || !prevSize);
|
||||||
|
prevSize = t.size;
|
||||||
|
}
|
||||||
|
for(int i = 0; i < regionNumber; i++) {
|
||||||
|
rid.page += (t.size + 1);
|
||||||
|
Tread(xid, rid, &t);
|
||||||
|
if(t.status == REGION_VACANT) { i--; }
|
||||||
|
assert(t.size != UINT_MAX);
|
||||||
|
assert(t.prev_size != UINT_MAX || i == 0);
|
||||||
|
assert(prevSize == t.prev_size || !prevSize);
|
||||||
|
prevSize = t.size;
|
||||||
|
}
|
||||||
|
*firstPage = rid.page+1;
|
||||||
|
*size = t.size;
|
||||||
|
}
|
||||||
|
|
||||||
/*Operation getAllocRegion() {
|
/*Operation getAllocRegion() {
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,26 @@
|
||||||
#include "../page.h"
|
#include "../page.h"
|
||||||
#include "header.h"
|
#include "header.h"
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
int headerPageInitialize() {
|
||||||
void headerPageInitialize(Page * page) {
|
Page * p;
|
||||||
memset(page->memAddr, 0, PAGE_SIZE);
|
try_ret(0) {
|
||||||
*page_type_ptr(page) = LLADD_HEADER_PAGE;
|
p = loadPage(-1, 0);
|
||||||
*headerFreepage_ptr(page) = 1;
|
assert(!compensation_error());
|
||||||
*headerFreepagelist_ptr(page) = 0;
|
} end_ret(0);
|
||||||
|
int freePage;
|
||||||
|
if(*page_type_ptr(p) != LLADD_HEADER_PAGE) {
|
||||||
|
assert(*page_type_ptr(p) == 0) ;
|
||||||
|
memset(p->memAddr, 0, PAGE_SIZE);
|
||||||
|
*page_type_ptr(p) = LLADD_HEADER_PAGE;
|
||||||
|
*headerFreepage_ptr(p) = 1;
|
||||||
|
*headerFreepagelist_ptr(p) = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
freePage = *headerFreepage_ptr(p);
|
||||||
|
releasePage(p);
|
||||||
|
assert(freePage);
|
||||||
|
return freePage;
|
||||||
}
|
}
|
||||||
|
|
||||||
void freePage(Page * freepage, long freepage_id, Page * headerpage) {
|
void freePage(Page * freepage, long freepage_id, Page * headerpage) {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
|
|
||||||
void headerPageInitialize(Page * p);
|
//void headerPageInitialize(Page * p);
|
||||||
|
int headerPageInitialize();
|
||||||
void freePageInitialize(Page * freepage, Page *headerpage);
|
void freePageInitialize(Page * freepage, Page *headerpage);
|
||||||
#define headerFreepage_ptr(page) ints_from_end((page), 1)
|
#define headerFreepage_ptr(page) ints_from_end((page), 1)
|
||||||
#define headerFreepagelist_ptr(page) ints_from_end((page), 2)
|
#define headerFreepagelist_ptr(page) ints_from_end((page), 2)
|
||||||
|
|
|
@ -51,14 +51,14 @@ void setupOperationsTable() {
|
||||||
operationsTable[OPERATION_PAGE_DEALLOC] = getPageDealloc(); */
|
operationsTable[OPERATION_PAGE_DEALLOC] = getPageDealloc(); */
|
||||||
operationsTable[OPERATION_PAGE_SET] = getPageSet();
|
operationsTable[OPERATION_PAGE_SET] = getPageSet();
|
||||||
|
|
||||||
operationsTable[OPERATION_UPDATE_FREESPACE] = getUpdateFreespace();
|
/* operationsTable[OPERATION_UPDATE_FREESPACE] = getUpdateFreespace();
|
||||||
operationsTable[OPERATION_UPDATE_FREESPACE_INVERSE] = getUpdateFreespaceInverse();
|
operationsTable[OPERATION_UPDATE_FREESPACE_INVERSE] = getUpdateFreespaceInverse();
|
||||||
operationsTable[OPERATION_UPDATE_FREELIST] = getUpdateFreelist();
|
operationsTable[OPERATION_UPDATE_FREELIST] = getUpdateFreelist();
|
||||||
operationsTable[OPERATION_UPDATE_FREELIST_INVERSE] = getUpdateFreelistInverse();
|
operationsTable[OPERATION_UPDATE_FREELIST_INVERSE] = getUpdateFreelistInverse();
|
||||||
|
|
||||||
operationsTable[OPERATION_FREE_PAGE] = getFreePageOperation();
|
operationsTable[OPERATION_FREE_PAGE] = getFreePageOperation();
|
||||||
operationsTable[OPERATION_ALLOC_FREED] = getAllocFreedPage();
|
operationsTable[OPERATION_ALLOC_FREED] = getAllocFreedPage();
|
||||||
operationsTable[OPERATION_UNALLOC_FREED] = getUnallocFreedPage();
|
operationsTable[OPERATION_UNALLOC_FREED] = getUnallocFreedPage(); */
|
||||||
operationsTable[OPERATION_NOOP] = getNoop();
|
operationsTable[OPERATION_NOOP] = getNoop();
|
||||||
operationsTable[OPERATION_INSTANT_SET] = getInstantSet();
|
operationsTable[OPERATION_INSTANT_SET] = getInstantSet();
|
||||||
operationsTable[OPERATION_ARRAY_LIST_ALLOC] = getArrayListAlloc();
|
operationsTable[OPERATION_ARRAY_LIST_ALLOC] = getArrayListAlloc();
|
||||||
|
@ -109,7 +109,6 @@ int Tinit() {
|
||||||
|
|
||||||
LogInit(loggerType);
|
LogInit(loggerType);
|
||||||
|
|
||||||
|
|
||||||
try_ret(compensation_error()) {
|
try_ret(compensation_error()) {
|
||||||
pageOperationsInit();
|
pageOperationsInit();
|
||||||
} end_ret(compensation_error());
|
} end_ret(compensation_error());
|
||||||
|
@ -126,10 +125,10 @@ int Tinit() {
|
||||||
|
|
||||||
InitiateRecovery();
|
InitiateRecovery();
|
||||||
|
|
||||||
truncationInit();
|
/*truncationInit();
|
||||||
if(lladd_enableAutoTruncation) {
|
if(lladd_enableAutoTruncation) {
|
||||||
autoTruncate(); // should this be before InitiateRecovery?
|
autoTruncate(); // should this be before InitiateRecovery?
|
||||||
}
|
}*/
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
if HAVE_LIBCHECK
|
if HAVE_LIBCHECK
|
||||||
## Had to disable check_lht because lht needs to be rewritten.
|
## Had to disable check_lht because lht needs to be rewritten.
|
||||||
TESTS = check_lhtable check_logEntry check_logWriter check_page check_operations check_transactional2 check_recovery check_blobRecovery check_bufferManager check_indirect check_pageOperations check_linearHash check_logicalLinearHash check_header check_linkedListNTA check_linearHashNTA check_pageOrientedList check_lockManager check_compensations check_errorHandling check_ringbuffer check_iterator check_multiplexer check_bTree
|
TESTS = check_lhtable check_logEntry check_logWriter check_page check_operations check_transactional2 check_recovery check_blobRecovery check_bufferManager check_indirect check_pageOperations check_linearHash check_logicalLinearHash check_header check_linkedListNTA check_linearHashNTA check_pageOrientedList check_lockManager check_compensations check_errorHandling check_ringbuffer check_iterator check_multiplexer check_bTree check_regions
|
||||||
#check_lladdhash
|
#check_lladdhash
|
||||||
else
|
else
|
||||||
TESTS =
|
TESTS =
|
||||||
|
|
|
@ -29,7 +29,7 @@ void initializePages() {
|
||||||
for(i = 0 ; i < NUM_PAGES; i++) {
|
for(i = 0 ; i < NUM_PAGES; i++) {
|
||||||
Page * p;
|
Page * p;
|
||||||
recordid rid;
|
recordid rid;
|
||||||
rid.page = i;
|
rid.page = i+1;
|
||||||
rid.slot = 0;
|
rid.slot = 0;
|
||||||
rid.size = sizeof(int);
|
rid.size = sizeof(int);
|
||||||
p = loadPage(-1, rid.page);
|
p = loadPage(-1, rid.page);
|
||||||
|
@ -61,7 +61,7 @@ void * workerThread(void * p) {
|
||||||
printf("%d", i / 50); fflush(NULL);
|
printf("%d", i / 50); fflush(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
rid.page = k;
|
rid.page = k+1;
|
||||||
rid.slot = 0;
|
rid.slot = 0;
|
||||||
rid.size = sizeof(int);
|
rid.size = sizeof(int);
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ void * workerThread(void * p) {
|
||||||
|
|
||||||
readRecord(1, p, rid, &j);
|
readRecord(1, p, rid, &j);
|
||||||
|
|
||||||
assert(rid.page == k);
|
assert(rid.page == k+1);
|
||||||
|
|
||||||
p->LSN = 0;
|
p->LSN = 0;
|
||||||
*lsn_ptr(p) = 0;
|
*lsn_ptr(p) = 0;
|
||||||
|
|
|
@ -110,8 +110,6 @@ long myrandom(long x) {
|
||||||
return (long)((r/max));
|
return (long)((r/max));
|
||||||
}
|
}
|
||||||
|
|
||||||
//#define myrandom(x)(
|
|
||||||
// (long) ( ((double)x) * ((double)random()) / ((double)RAND_MAX) ) )
|
|
||||||
|
|
||||||
#define MAXSETS 1000
|
#define MAXSETS 1000
|
||||||
#define MAXSETLEN 10000
|
#define MAXSETLEN 10000
|
||||||
|
@ -125,10 +123,11 @@ char * itoa(int i) {
|
||||||
START_TEST(lhtableRandomized) {
|
START_TEST(lhtableRandomized) {
|
||||||
for(int jjj = 0; jjj < NUM_ITERS; jjj++) {
|
for(int jjj = 0; jjj < NUM_ITERS; jjj++) {
|
||||||
time_t seed = time(0);
|
time_t seed = time(0);
|
||||||
printf("\nSeed = %ld\n", seed);
|
|
||||||
if(jjj) {
|
if(jjj) {
|
||||||
|
printf("\nSeed = %ld\n", seed);
|
||||||
srandom(seed);
|
srandom(seed);
|
||||||
} else {
|
} else {
|
||||||
|
printf("\nSeed = %d\n", 1150241705);
|
||||||
srandom(1150241705); // This seed gets the random number generator to hit RAND_MAX, which makes a good test for myrandom()
|
srandom(1150241705); // This seed gets the random number generator to hit RAND_MAX, which makes a good test for myrandom()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue