Reimplemented allocationPolicy.c; updated API + added more cases to the unit tests.
This commit is contained in:
parent
beb14ec917
commit
5b10bcc63b
4 changed files with 527 additions and 509 deletions
|
@ -36,371 +36,456 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#define ALLOCATION_POLICY_SANITY_CHECKS
|
/**
|
||||||
|
* Allocation Policy maintains the following tables:
|
||||||
|
*
|
||||||
|
* AllPages: _pageid_, freespace, key1: pageid
|
||||||
|
*
|
||||||
|
* XidAlloced: _xid, pageid_ key1: xid,pageid, key2: pageid,xid
|
||||||
|
* XidDealloced: _xid, pageid_: key1: xid,pageid, key2: pageid,xid
|
||||||
|
*
|
||||||
|
* And the following views:
|
||||||
|
*
|
||||||
|
* AvailablePages: (_pageid_, freespace) The rows of AllPages with no entries in xidAllloced or xidDealloced. key1: pageid, key2: freespace, pageid
|
||||||
|
* PageOwners: (xid, freespace, _pageid_) The rows of AllPages with an entry in xidAlloced, and at most one entry in xidDealloced, key1: pageid, key2 = xid, freespace, pageid
|
||||||
|
*/
|
||||||
|
// Tables:
|
||||||
|
typedef struct {
|
||||||
|
pageid_t pageid;
|
||||||
|
size_t freespace;
|
||||||
|
} allPages_pageid_freespace;
|
||||||
|
typedef struct {
|
||||||
|
int xid;
|
||||||
|
pageid_t pageid;
|
||||||
|
} xidAllocedDealloced_xid_pageid;
|
||||||
|
|
||||||
// Each availablePage should either be in availablePages, or in
|
// Views:
|
||||||
// xidAlloced and pageOwners. If a transaction allocs and
|
|
||||||
// deallocs from the same page, then it only has an entry for that
|
|
||||||
// page in xidAlloced.
|
|
||||||
//
|
|
||||||
// xidAlloced is an lhtable of type (int xid) -> (rbtree of availablePage*)
|
|
||||||
// xidDealloced is an lhtable of type (int xid) -> (lhtable of int pageid -> availablePage *)
|
|
||||||
// pageOwners is an lhtable of type (int pageid) -> (int xid)
|
|
||||||
// availablePages is a rbtree of availablePage*.
|
|
||||||
|
|
||||||
struct allocationPolicy {
|
typedef struct {
|
||||||
struct LH_ENTRY(table) * xidAlloced;
|
pageid_t pageid;
|
||||||
struct LH_ENTRY(table) * xidDealloced;
|
size_t freespace;
|
||||||
struct RB_ENTRY(tree) * availablePages;
|
} availablePages_pageid_freespace;
|
||||||
struct LH_ENTRY(table) * pageOwners;
|
typedef struct {
|
||||||
struct LH_ENTRY(table) * allPages;
|
int xid;
|
||||||
|
size_t freespace;
|
||||||
|
pageid_t pageid;
|
||||||
|
} pageOwners_xid_freespace_pageid;
|
||||||
|
|
||||||
|
struct stasis_allocation_policy_t {
|
||||||
|
// views
|
||||||
|
struct rbtree * availablePages_key_pageid;
|
||||||
|
struct rbtree * availablePages_key_freespace_pageid;
|
||||||
|
struct rbtree * pageOwners_key_pageid;
|
||||||
|
struct rbtree * pageOwners_key_xid_freespace_pageid;
|
||||||
|
// tables
|
||||||
|
struct rbtree * allPages_key_pageid;
|
||||||
|
struct rbtree * xidAlloced_key_xid_pageid;
|
||||||
|
struct rbtree * xidAlloced_key_pageid_xid;
|
||||||
|
struct rbtree * xidDealloced_key_xid_pageid;
|
||||||
|
struct rbtree * xidDealloced_key_pageid_xid;
|
||||||
|
// flags
|
||||||
|
char reuseWithinXact;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline static int cmpPageid(const void * ap, const void * bp, const void * param) {
|
// View maintenance functions. Called by the table insertion functions.
|
||||||
const availablePage * a = (const availablePage *)ap;
|
|
||||||
const availablePage * b = (const availablePage *)bp;
|
|
||||||
|
|
||||||
if(a->pageid < b->pageid) {
|
// ######## Helpers ###############
|
||||||
return -1;
|
|
||||||
} else if (a->pageid > b->pageid) {
|
static int void_single_add(void * val, struct rbtree * a) {
|
||||||
|
const void * old = rbdelete(val, a);
|
||||||
|
rbsearch(val, a);
|
||||||
|
int found = (old != 0);
|
||||||
|
if(found) { free((void*)old); }
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int void_single_remove(void * val, struct rbtree * a) {
|
||||||
|
const void * old = rbdelete(val, a);
|
||||||
|
int found = (old != 0);
|
||||||
|
if(found) { free((void*)old); }
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
static int void_double_add(void * val, struct rbtree * a, struct rbtree * b) {
|
||||||
|
const void *old1, *old2 ;
|
||||||
|
|
||||||
|
old1 = rbdelete(val, a);
|
||||||
|
rbsearch(val, a);
|
||||||
|
int found1 = (old1 != 0);
|
||||||
|
|
||||||
|
old2 = rbdelete(val, b);
|
||||||
|
rbsearch(val,b);
|
||||||
|
assert(old1 == old2);
|
||||||
|
if(found1) { free((void*)old1); }
|
||||||
|
|
||||||
|
return found1;
|
||||||
|
}
|
||||||
|
static int void_double_remove(const void * val, struct rbtree * primary, struct rbtree * secondary) {
|
||||||
|
const void * fullTuple= rbdelete(val, primary);
|
||||||
|
int found1 = (fullTuple != 0);
|
||||||
|
if(found1) {
|
||||||
|
const void * old = rbdelete(fullTuple, secondary);
|
||||||
|
assert(old == fullTuple);
|
||||||
|
free((void*)fullTuple);
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ######## AvailablePages ###########
|
||||||
|
static int availablePages_remove(stasis_allocation_policy_t *ap, pageid_t pageid);
|
||||||
|
static int availablePages_add(stasis_allocation_policy_t *ap, pageid_t pageid, size_t freespace) {
|
||||||
|
int ret = availablePages_remove(ap, pageid);
|
||||||
|
availablePages_pageid_freespace* tup= malloc(sizeof(*tup));
|
||||||
|
tup->pageid = pageid;
|
||||||
|
tup->freespace = freespace;
|
||||||
|
void_double_add(tup, ap->availablePages_key_pageid, ap->availablePages_key_freespace_pageid);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
static int availablePages_remove(stasis_allocation_policy_t *ap, pageid_t pageid) {
|
||||||
|
availablePages_pageid_freespace tup = {pageid, -1};
|
||||||
|
return void_double_remove(&tup, ap->availablePages_key_pageid, ap->availablePages_key_freespace_pageid);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ######## PageOwners ###########
|
||||||
|
static int pageOwners_remove(stasis_allocation_policy_t *ap, pageid_t pageid);
|
||||||
|
static int pageOwners_add(stasis_allocation_policy_t *ap, int xid, size_t freespace, pageid_t pageid) {
|
||||||
|
|
||||||
|
int ret = pageOwners_remove(ap, pageid);
|
||||||
|
|
||||||
|
pageOwners_xid_freespace_pageid * tup = malloc(sizeof(*tup));
|
||||||
|
tup->xid = xid;
|
||||||
|
tup->freespace = freespace;
|
||||||
|
tup->pageid = pageid;
|
||||||
|
|
||||||
|
void_double_add(tup, ap->pageOwners_key_pageid, ap->pageOwners_key_xid_freespace_pageid);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pageOwners_remove(stasis_allocation_policy_t *ap, pageid_t pageid) {
|
||||||
|
pageOwners_xid_freespace_pageid tup = { INVALID_XID, -1, pageid };
|
||||||
|
return void_double_remove(&tup, ap->pageOwners_key_pageid, ap->pageOwners_key_xid_freespace_pageid);
|
||||||
|
}
|
||||||
|
int pageOwners_lookup_by_xid_freespace(stasis_allocation_policy_t *ap, int xid, size_t freespace, pageid_t* pageid) {
|
||||||
|
pageOwners_xid_freespace_pageid query = { xid, freespace, 0 };
|
||||||
|
// find lowest numbered page w/ enough freespace.
|
||||||
|
const pageOwners_xid_freespace_pageid *tup = rblookup(RB_LUGTEQ, &query, ap->pageOwners_key_xid_freespace_pageid);
|
||||||
|
if(tup && tup->xid == xid) {
|
||||||
|
assert(tup->freespace >= freespace);
|
||||||
|
*pageid = tup->pageid;
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int pageOwners_lookup_by_pageid(stasis_allocation_policy_t* ap, pageid_t pageid, int *xid, size_t *freespace) {
|
||||||
|
const pageOwners_xid_freespace_pageid query = { 0, 0, pageid };
|
||||||
|
const pageOwners_xid_freespace_pageid *tup = rbfind(&query, ap->pageOwners_key_pageid);
|
||||||
|
if(tup) {
|
||||||
|
*xid = tup->xid;
|
||||||
|
*freespace = tup->freespace;
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// TABLE METHODS FOLLOW. These functions perform view maintenance.
|
||||||
|
|
||||||
|
// ######## AllPages #############
|
||||||
|
static int allPages_lookup_by_pageid(stasis_allocation_policy_t *ap, pageid_t pageid, size_t *freespace) {
|
||||||
|
allPages_pageid_freespace query = {pageid, 0};
|
||||||
|
const allPages_pageid_freespace * tup = rbfind(&query, ap->allPages_key_pageid);
|
||||||
|
if(tup) {
|
||||||
|
assert(tup->pageid == pageid);
|
||||||
|
*freespace = tup->freespace;
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static int allPages_add(stasis_allocation_policy_t *ap, pageid_t pageid, size_t freespace) {
|
||||||
|
allPages_pageid_freespace * tup = malloc(sizeof(*tup));
|
||||||
|
tup->pageid = pageid;
|
||||||
|
tup->freespace = freespace;
|
||||||
|
int ret = void_single_add(tup, ap->allPages_key_pageid);
|
||||||
|
if(!ret) {
|
||||||
|
int ret2 = availablePages_add(ap, pageid, freespace);
|
||||||
|
assert(!ret2);
|
||||||
|
} else {
|
||||||
|
// page may or may not be in availablePages...
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
/** Assumes that the page is not in use by an outstanding xact */
|
||||||
|
static int allPages_remove(stasis_allocation_policy_t *ap, pageid_t pageid) {
|
||||||
|
allPages_pageid_freespace tup = { pageid, -1 };
|
||||||
|
int found = void_single_remove(&tup, ap->allPages_key_pageid);
|
||||||
|
int found2 = availablePages_remove(ap, pageid);
|
||||||
|
assert(found == found2);
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
static void allPages_removeAll(stasis_allocation_policy_t *ap) {
|
||||||
|
const allPages_pageid_freespace * tup;
|
||||||
|
while((tup = rbmin(ap->allPages_key_pageid))) {
|
||||||
|
allPages_remove(ap, tup->pageid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void allPages_set_freespace(stasis_allocation_policy_t *ap, pageid_t pageid, size_t freespace) {
|
||||||
|
allPages_pageid_freespace * tup = malloc(sizeof(*tup));
|
||||||
|
tup->pageid = pageid;
|
||||||
|
tup->freespace = freespace;
|
||||||
|
int existed = void_single_add(tup, ap->allPages_key_pageid);
|
||||||
|
assert(existed);
|
||||||
|
int availableExisted = availablePages_remove(ap, pageid);
|
||||||
|
if(availableExisted) {
|
||||||
|
availablePages_add(ap, pageid, freespace);
|
||||||
|
}
|
||||||
|
int xid;
|
||||||
|
size_t oldfreespace;
|
||||||
|
int ownerExisted = pageOwners_lookup_by_pageid(ap, pageid, &xid, &oldfreespace);
|
||||||
|
if(ownerExisted) {
|
||||||
|
pageOwners_add(ap, xid, freespace, pageid);
|
||||||
|
}
|
||||||
|
assert(!(ownerExisted && availableExisted));
|
||||||
|
}
|
||||||
|
static int xidAllocedDealloced_helper_lookup_by_xid(struct rbtree *t, int xid, pageid_t **pages, size_t*count) {
|
||||||
|
xidAllocedDealloced_xid_pageid query = {xid, -1};
|
||||||
|
const xidAllocedDealloced_xid_pageid *tup = rblookup(RB_LUGTEQ, &query, t);
|
||||||
|
int ret = 0;
|
||||||
|
*pages = 0;
|
||||||
|
*count = 0;
|
||||||
|
while(tup && tup->xid == xid) {
|
||||||
|
ret = 1;
|
||||||
|
// add pageid to ret value
|
||||||
|
(*count)++;
|
||||||
|
*pages = realloc(*pages, *count * sizeof(*pages[0]));
|
||||||
|
// printf("pages %x count %x *pages %x len %lld \n", pages, count, *pages, *count * sizeof(*pages[0]));
|
||||||
|
fflush(stdout);
|
||||||
|
(*pages)[(*count) - 1] = tup->pageid;
|
||||||
|
tup = rblookup(RB_LUGREAT, tup, t);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
static int xidAllocedDealloced_helper_lookup_by_pageid(struct rbtree *t, pageid_t pageid, int ** xids, size_t * count) {
|
||||||
|
xidAllocedDealloced_xid_pageid query = {-1, pageid};
|
||||||
|
const xidAllocedDealloced_xid_pageid *tup = rblookup(RB_LUGTEQ, &query, t);
|
||||||
|
int ret = 0;
|
||||||
|
*xids = 0;
|
||||||
|
*count = 0;
|
||||||
|
while (tup && tup->pageid == pageid) {
|
||||||
|
ret = 1;
|
||||||
|
// add xid to ret value.
|
||||||
|
(*count)++;
|
||||||
|
*xids = realloc(*xids, *count * sizeof(*xids[0]));
|
||||||
|
(*xids)[(*count) - 1] = tup->xid;
|
||||||
|
tup = rblookup(RB_LUGREAT, tup, t);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int xidAlloced_lookup_by_pageid(stasis_allocation_policy_t *ap, pageid_t pageid, int **xids, size_t * count);
|
||||||
|
static int xidDealloced_lookup_by_pageid(stasis_allocation_policy_t *ap, pageid_t pageid, int **xids, size_t * count);
|
||||||
|
|
||||||
|
static int update_views_for_page(stasis_allocation_policy_t *ap, pageid_t pageid) {
|
||||||
|
size_t xidAllocCount;
|
||||||
|
size_t xidDeallocCount;
|
||||||
|
int ret = 0;
|
||||||
|
int * allocXids;
|
||||||
|
int * deallocXids;
|
||||||
|
size_t freespace;
|
||||||
|
int inAllPages = allPages_lookup_by_pageid(ap, pageid, &freespace);
|
||||||
|
assert(inAllPages);
|
||||||
|
int inXidAlloced = xidAlloced_lookup_by_pageid(ap, pageid, &allocXids, &xidAllocCount);
|
||||||
|
int inXidDealloced = xidDealloced_lookup_by_pageid(ap, pageid, &deallocXids, &xidDeallocCount);
|
||||||
|
if(! inXidAlloced) { xidAllocCount = 0; allocXids = 0;}
|
||||||
|
if(! inXidDealloced) { xidDeallocCount = 0; deallocXids = 0; }
|
||||||
|
if(xidAllocCount == 0 && xidDeallocCount == 0) {
|
||||||
|
pageOwners_remove(ap, pageid);
|
||||||
|
availablePages_add(ap, pageid, freespace);
|
||||||
|
} else if ((xidAllocCount == 1 && xidDeallocCount == 0)
|
||||||
|
|| (xidAllocCount == 1 && xidDeallocCount == 1 && ap->reuseWithinXact && (allocXids[0] == deallocXids[0]))) {
|
||||||
|
pageOwners_add(ap, allocXids[0], freespace, pageid);
|
||||||
|
availablePages_remove(ap, pageid);
|
||||||
|
} else {
|
||||||
|
pageOwners_remove(ap, pageid);
|
||||||
|
availablePages_remove(ap, pageid);
|
||||||
|
}
|
||||||
|
if(allocXids) { free(allocXids); }
|
||||||
|
if(deallocXids) { free(deallocXids); }
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
static int xidAllocedDealloced_helper_add(stasis_allocation_policy_t *ap, struct rbtree *first, struct rbtree* second, int xid, pageid_t pageid) {
|
||||||
|
xidAllocedDealloced_xid_pageid * tup = malloc(sizeof(*tup));
|
||||||
|
tup->xid = xid;
|
||||||
|
tup->pageid = pageid;
|
||||||
|
int existed = void_double_add(tup, first, second);
|
||||||
|
if(!existed) {
|
||||||
|
update_views_for_page(ap, pageid);
|
||||||
|
}
|
||||||
|
return existed;
|
||||||
|
}
|
||||||
|
static int xidAllocedDealloced_helper_remove(stasis_allocation_policy_t *ap, struct rbtree *first, struct rbtree*second, int xid, pageid_t pageid) {
|
||||||
|
xidAllocedDealloced_xid_pageid query = { xid, pageid };
|
||||||
|
int existed = void_double_remove(&query, first, second);
|
||||||
|
if(existed) {
|
||||||
|
update_views_for_page(ap, pageid);
|
||||||
|
}
|
||||||
|
return existed;
|
||||||
|
}
|
||||||
|
static int xidAlloced_lookup_by_xid(stasis_allocation_policy_t *ap, int xid, pageid_t ** pages, size_t * count) {
|
||||||
|
return xidAllocedDealloced_helper_lookup_by_xid(ap->xidAlloced_key_xid_pageid, xid, pages, count);
|
||||||
|
}
|
||||||
|
static int xidAlloced_lookup_by_pageid(stasis_allocation_policy_t *ap, pageid_t pageid, int **xids, size_t * count) {
|
||||||
|
return xidAllocedDealloced_helper_lookup_by_pageid(ap->xidAlloced_key_pageid_xid, pageid, xids, count);
|
||||||
|
}
|
||||||
|
static int xidAlloced_add(stasis_allocation_policy_t * ap, int xid, pageid_t pageid) {
|
||||||
|
return xidAllocedDealloced_helper_add(ap, ap->xidAlloced_key_pageid_xid, ap->xidAlloced_key_xid_pageid, xid, pageid);
|
||||||
|
}
|
||||||
|
static int xidAlloced_remove(stasis_allocation_policy_t * ap, int xid, pageid_t pageid) {
|
||||||
|
return xidAllocedDealloced_helper_remove(ap, ap->xidAlloced_key_pageid_xid, ap->xidAlloced_key_xid_pageid, xid, pageid);
|
||||||
|
}
|
||||||
|
static int xidDealloced_lookup_by_xid(stasis_allocation_policy_t *ap, int xid, pageid_t ** pages, size_t * count) {
|
||||||
|
return xidAllocedDealloced_helper_lookup_by_xid(ap->xidDealloced_key_xid_pageid, xid, pages, count);
|
||||||
|
}
|
||||||
|
static int xidDealloced_lookup_by_pageid(stasis_allocation_policy_t *ap, pageid_t pageid, int **xids, size_t * count) {
|
||||||
|
return xidAllocedDealloced_helper_lookup_by_pageid(ap->xidDealloced_key_pageid_xid, pageid, xids, count);
|
||||||
|
}
|
||||||
|
static int xidDealloced_add(stasis_allocation_policy_t * ap, int xid, pageid_t pageid) {
|
||||||
|
return xidAllocedDealloced_helper_add(ap, ap->xidDealloced_key_pageid_xid, ap->xidDealloced_key_xid_pageid, xid, pageid);
|
||||||
|
}
|
||||||
|
static int xidDealloced_remove(stasis_allocation_policy_t * ap, int xid, pageid_t pageid) {
|
||||||
|
return xidAllocedDealloced_helper_remove(ap, ap->xidDealloced_key_pageid_xid, ap->xidDealloced_key_xid_pageid, xid, pageid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int availablePages_cmp_pageid(const void *ap, const void *bp, const void* ign) {
|
||||||
|
const availablePages_pageid_freespace *a = ap, *b = bp;
|
||||||
|
return a->pageid < b->pageid ? -1 : a->pageid > b->pageid ? 1 : 0;
|
||||||
|
}
|
||||||
|
static int availablePages_cmp_freespace_pageid(const void *ap, const void *bp, const void* ign) {
|
||||||
|
const availablePages_pageid_freespace *a = ap, *b = bp;
|
||||||
|
return a->freespace < b->freespace ? -1 : a->freespace > b->freespace ? 1 : a->pageid < b->pageid ? -1 : a->pageid > b->pageid ? 1 : 0;
|
||||||
|
}
|
||||||
|
int availablePages_lookup_by_freespace(stasis_allocation_policy_t *ap, size_t freespace, pageid_t *pageid) {
|
||||||
|
const availablePages_pageid_freespace query = { 0, freespace };
|
||||||
|
const availablePages_pageid_freespace *tup = rblookup(RB_LUGTEQ, &query, ap->availablePages_key_freespace_pageid);
|
||||||
|
if(tup && tup->freespace >= freespace ) {
|
||||||
|
*pageid = tup->pageid;
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cmpFreespace(const void * ap, const void * bp, const void * param) {
|
static int pageOwners_cmp_pageid(const void *ap, const void *bp, const void* ign) {
|
||||||
const availablePage * a = (const availablePage *) ap;
|
const pageOwners_xid_freespace_pageid *a = ap, *b = bp;
|
||||||
const availablePage * b = (const availablePage *) bp;
|
return a->pageid < b->pageid ? -1 : a->pageid > b->pageid ? 1 : 0;
|
||||||
|
|
||||||
if(a->freespace < b->freespace) {
|
|
||||||
return -1;
|
|
||||||
} else if (a->freespace > b->freespace) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
return cmpPageid(ap,bp,param);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
static int pageOwners_cmp_xid_freespace_pageid(const void *ap, const void *bp, const void* ign) {
|
||||||
inline static availablePage* getAvailablePage(stasis_allocation_policy_t * ap, pageid_t pageid) {
|
const pageOwners_xid_freespace_pageid *a = ap, *b = bp;
|
||||||
return (availablePage*) LH_ENTRY(find)(ap->allPages, &pageid, sizeof(pageid));
|
return a->xid < b->xid ? -1 : a->xid > b->xid ? 1 : a->freespace < b->freespace ? -1 : a->freespace > b->freespace ? 1 : a->pageid < b->pageid ? -1 : a->pageid > b->pageid ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
static int allPages_cmp_pageid(const void *ap, const void *bp, const void* ign) {
|
||||||
inline static void insert_xidAlloced(stasis_allocation_policy_t * ap, int xid, availablePage * p) {
|
const allPages_pageid_freespace *a = ap, *b = bp;
|
||||||
|
return a->pageid < b->pageid ? -1 : a->pageid > b->pageid ? 1 : 0;
|
||||||
struct RB_ENTRY(tree) * pages = LH_ENTRY(find)(ap->xidAlloced, &xid, sizeof(xid));
|
|
||||||
if(!pages) {
|
|
||||||
pages = RB_ENTRY(init)(cmpFreespace, 0);
|
|
||||||
LH_ENTRY(insert)(ap->xidAlloced, &xid, sizeof(xid), pages);
|
|
||||||
}
|
|
||||||
const availablePage * check = RB_ENTRY(search)(p, pages);
|
|
||||||
assert(check == p);
|
|
||||||
}
|
}
|
||||||
|
static int xidAllocedDealloced_cmp_pageid_xid(const void *ap, const void *bp, const void* ign) {
|
||||||
inline static void remove_xidAlloced(stasis_allocation_policy_t * ap, int xid, availablePage * p) {
|
const xidAllocedDealloced_xid_pageid *a = ap, *b = bp;
|
||||||
assert(p->lockCount);
|
return a->pageid < b->pageid ? -1 : a->pageid > b->pageid ? 1 : a->xid < b->xid ? -1 : a->xid > b->xid ? 1 : 0;
|
||||||
struct RB_ENTRY(tree) * pages = LH_ENTRY(find)(ap->xidAlloced, &xid, sizeof(xid));
|
|
||||||
assert(pages);
|
|
||||||
const availablePage * check = RB_ENTRY(delete)(p, pages);
|
|
||||||
assert(check == p); // sometimes fails
|
|
||||||
}
|
}
|
||||||
|
static int xidAllocedDealloced_cmp_xid_pageid(const void *ap, const void *bp, const void* ign) {
|
||||||
inline static void insert_xidDealloced(stasis_allocation_policy_t * ap, int xid, availablePage * p) {
|
const xidAllocedDealloced_xid_pageid *a = ap, *b = bp;
|
||||||
|
return a->xid < b->xid ? -1 : a->xid > b->xid ? 1 : a->pageid < b->pageid ? -1 : a->pageid > b->pageid ? 1 : 0;
|
||||||
struct RB_ENTRY(tree) * pages = LH_ENTRY(find)(ap->xidDealloced, &xid, sizeof(xid));
|
|
||||||
if(!pages) {
|
|
||||||
pages = RB_ENTRY(init)(cmpPageid, 0);
|
|
||||||
LH_ENTRY(insert)(ap->xidDealloced, &xid, sizeof(xid), pages);
|
|
||||||
}
|
|
||||||
assert(pages);
|
|
||||||
const availablePage * check = RB_ENTRY(search)(p, pages);
|
|
||||||
// XXX Assert that the page wasn't already there?
|
|
||||||
assert(check);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static void remove_xidDealloced(stasis_allocation_policy_t * ap, int xid, availablePage * p) {
|
|
||||||
|
|
||||||
struct RB_ENTRY(tree) * pages = LH_ENTRY(find)(ap->xidDealloced, &xid, sizeof(xid));
|
|
||||||
assert(pages);
|
|
||||||
const availablePage * check = RB_ENTRY(delete)(p, pages);
|
|
||||||
assert(check == p);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static int find_xidDealloced(stasis_allocation_policy_t * ap, int xid, availablePage * p) {
|
|
||||||
struct RB_ENTRY(tree) * pages = LH_ENTRY(find)(ap->xidDealloced, &xid, sizeof(xid));
|
|
||||||
if(!pages) { return 0; }
|
|
||||||
const availablePage * check = RB_ENTRY(find)(p, pages);
|
|
||||||
if(check) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static void lockAlloced(stasis_allocation_policy_t * ap, int xid, availablePage * p) {
|
|
||||||
const availablePage * check = RB_ENTRY(delete)(p, ap->availablePages);
|
|
||||||
assert(check == p);
|
|
||||||
|
|
||||||
assert(p->lockCount == 0);
|
|
||||||
p->lockCount = 1;
|
|
||||||
|
|
||||||
int * xidp = malloc(sizeof(int));
|
|
||||||
*xidp = xid;
|
|
||||||
LH_ENTRY(insert)(ap->pageOwners, &(p->pageid), sizeof(p->pageid), xidp);
|
|
||||||
insert_xidAlloced(ap, xid, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static void unlockAlloced(stasis_allocation_policy_t * ap, int xid, availablePage * p) {
|
|
||||||
remove_xidAlloced(ap, xid, p);
|
|
||||||
|
|
||||||
p->lockCount--;
|
|
||||||
// assert(p->lockCount == 1);
|
|
||||||
// p->lockCount = 0;
|
|
||||||
if(!p->lockCount) {
|
|
||||||
const availablePage * check = RB_ENTRY(search)(p, ap->availablePages);
|
|
||||||
assert(check == p);
|
|
||||||
}
|
|
||||||
int * xidp = LH_ENTRY(remove)(ap->pageOwners, &(p->pageid), sizeof(p->pageid));
|
|
||||||
//assert(*xidp == xid);
|
|
||||||
if(xidp) { free(xidp); }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static void lockDealloced(stasis_allocation_policy_t * ap, int xid, availablePage * p) {
|
|
||||||
if(p->lockCount == 0) {
|
|
||||||
// xid should own it
|
|
||||||
lockAlloced(ap, xid, p);
|
|
||||||
} else if(p->lockCount == 1) {
|
|
||||||
int * xidp = LH_ENTRY(find)(ap->pageOwners, &(p->pageid), sizeof(p->pageid));
|
|
||||||
if(!xidp) {
|
|
||||||
|
|
||||||
// The only active transaction that touched this page deallocated from it,
|
|
||||||
// so just add the page to our dealloced table.
|
|
||||||
|
|
||||||
p->lockCount++;
|
|
||||||
insert_xidDealloced(ap, xid, p);
|
|
||||||
|
|
||||||
} else if(*xidp != xid) {
|
|
||||||
|
|
||||||
// Remove from the other transaction's "alloced" table.
|
|
||||||
remove_xidAlloced(ap, *xidp, p);
|
|
||||||
assert(p->lockCount == 1);
|
|
||||||
|
|
||||||
// Place in other transaction's "dealloced" table.
|
|
||||||
insert_xidDealloced(ap, *xidp, p);
|
|
||||||
|
|
||||||
// This page no longer has an owner
|
|
||||||
LH_ENTRY(remove)(ap->pageOwners, &(p->pageid), sizeof(p->pageid));
|
|
||||||
free(xidp);
|
|
||||||
|
|
||||||
// Add to our "dealloced" table, increment lockCount.
|
|
||||||
p->lockCount++;
|
|
||||||
insert_xidDealloced(ap, xid, p);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// not owned by anyone... is it already in this xid's Dealloced table?
|
|
||||||
if(!find_xidDealloced(ap, xid, p)) {
|
|
||||||
p->lockCount++;
|
|
||||||
insert_xidDealloced(ap, xid, p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static void unlockDealloced(stasis_allocation_policy_t * ap, int xid, availablePage * p) {
|
|
||||||
assert(p->lockCount > 0);
|
|
||||||
p->lockCount--;
|
|
||||||
|
|
||||||
remove_xidDealloced(ap, xid, p);
|
|
||||||
if(!p->lockCount) {
|
|
||||||
// put it back into available pages.
|
|
||||||
LH_ENTRY(remove)(ap->pageOwners, &(p->pageid), sizeof(p->pageid)); // XXX new feb-29
|
|
||||||
|
|
||||||
const availablePage * check = RB_ENTRY(search)(p, ap->availablePages);
|
|
||||||
assert(check == p);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stasis_allocation_policy_t * stasis_allocation_policy_init() {
|
stasis_allocation_policy_t * stasis_allocation_policy_init() {
|
||||||
stasis_allocation_policy_t * ap = malloc(sizeof(stasis_allocation_policy_t));
|
stasis_allocation_policy_t * ap = malloc(sizeof(*ap));
|
||||||
|
ap->availablePages_key_pageid = rbinit(availablePages_cmp_pageid, 0);
|
||||||
ap->xidAlloced = LH_ENTRY(create)(10);
|
ap->availablePages_key_freespace_pageid = rbinit(availablePages_cmp_freespace_pageid, 0);
|
||||||
ap->xidDealloced = LH_ENTRY(create)(10);
|
ap->pageOwners_key_pageid = rbinit(pageOwners_cmp_pageid, 0);
|
||||||
ap->availablePages = RB_ENTRY(init)(cmpFreespace, 0);
|
ap->pageOwners_key_xid_freespace_pageid = rbinit(pageOwners_cmp_xid_freespace_pageid, 0);
|
||||||
ap->pageOwners = LH_ENTRY(create)(10);
|
ap->allPages_key_pageid = rbinit(allPages_cmp_pageid, 0);
|
||||||
ap->allPages = LH_ENTRY(create)(10);
|
ap->xidAlloced_key_pageid_xid = rbinit(xidAllocedDealloced_cmp_pageid_xid, 0);
|
||||||
|
ap->xidAlloced_key_xid_pageid = rbinit(xidAllocedDealloced_cmp_xid_pageid, 0);
|
||||||
|
ap->xidDealloced_key_pageid_xid = rbinit(xidAllocedDealloced_cmp_pageid_xid, 0);
|
||||||
|
ap->xidDealloced_key_xid_pageid = rbinit(xidAllocedDealloced_cmp_xid_pageid, 0);
|
||||||
|
ap->reuseWithinXact = 0;
|
||||||
return ap;
|
return ap;
|
||||||
}
|
}
|
||||||
|
|
||||||
void stasis_allocation_policy_deinit(stasis_allocation_policy_t * ap) {
|
void stasis_allocation_policy_deinit(stasis_allocation_policy_t * ap) {
|
||||||
|
allPages_removeAll(ap); // frees entries in availablePages, asserts that all pages are available.
|
||||||
const availablePage * next;
|
rbdestroy(ap->availablePages_key_pageid);
|
||||||
while(( next = RB_ENTRY(min)(ap->availablePages) )) {
|
rbdestroy(ap->availablePages_key_freespace_pageid);
|
||||||
RB_ENTRY(delete)(next, ap->availablePages);
|
rbdestroy(ap->pageOwners_key_pageid);
|
||||||
free((void*)next);
|
rbdestroy(ap->pageOwners_key_xid_freespace_pageid);
|
||||||
}
|
rbdestroy(ap->allPages_key_pageid);
|
||||||
LH_ENTRY(destroy)(ap->xidAlloced);
|
rbdestroy(ap->xidAlloced_key_pageid_xid);
|
||||||
LH_ENTRY(destroy)(ap->xidDealloced);
|
rbdestroy(ap->xidAlloced_key_xid_pageid);
|
||||||
RB_ENTRY(destroy)(ap->availablePages);
|
rbdestroy(ap->xidDealloced_key_pageid_xid);
|
||||||
LH_ENTRY(destroy)(ap->pageOwners);
|
rbdestroy(ap->xidDealloced_key_xid_pageid);
|
||||||
LH_ENTRY(destroy)(ap->allPages);
|
|
||||||
|
|
||||||
free(ap);
|
free(ap);
|
||||||
}
|
}
|
||||||
|
void stasis_allocation_policy_register_new_page(stasis_allocation_policy_t * ap, pageid_t pageid, size_t freespace) {
|
||||||
void stasis_allocation_policy_register_new_pages(stasis_allocation_policy_t * ap, availablePage** newPages) {
|
int existed = allPages_add(ap,pageid,freespace);
|
||||||
|
assert(!existed);
|
||||||
for(int i = 0; newPages[i] != 0; i++) {
|
|
||||||
const availablePage * ret = RB_ENTRY(search)(newPages[i], ap->availablePages);
|
|
||||||
assert(ret == newPages[i]);
|
|
||||||
LH_ENTRY(insert)(ap->allPages, &(newPages[i]->pageid), sizeof(newPages[i]->pageid), newPages[i]);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
pageid_t stasis_allocation_policy_pick_suitable_page(stasis_allocation_policy_t * ap, int xid, size_t freespace) {
|
||||||
/// XXX need updateAlloced, updateFree, which remove a page, change
|
// does the xid have a suitable page?
|
||||||
/// its freespace / lockCount, and then re-insert them into the tree.
|
pageid_t pageid;
|
||||||
|
int found = pageOwners_lookup_by_xid_freespace(ap, xid, freespace, &pageid);
|
||||||
availablePage * stasis_allocation_policy_pick_suitable_page(stasis_allocation_policy_t * ap, int xid, int freespace) {
|
if(found) { return pageid; }
|
||||||
// For the best fit amongst the pages in availablePages, call:
|
// pick one from global pool.
|
||||||
//
|
found = availablePages_lookup_by_freespace(ap, freespace, &pageid);
|
||||||
// rblookup(RB_LUGREAT, key, availablePages)
|
if(found) {
|
||||||
//
|
return pageid;
|
||||||
// For the page with the most freespace, call:
|
|
||||||
//
|
|
||||||
// rbmax(availablePages);
|
|
||||||
//
|
|
||||||
availablePage tmp = { .freespace = freespace, .pageid = 0, .lockCount = 0 };
|
|
||||||
|
|
||||||
struct RB_ENTRY(tree) * locks;
|
|
||||||
|
|
||||||
// If we haven't heard of this transaction yet, then create an entry
|
|
||||||
// for it.
|
|
||||||
|
|
||||||
if(0 == (locks = LH_ENTRY(find)(ap->xidAlloced, &xid, sizeof(xid)))) {
|
|
||||||
// Since this is cmpPageid, we can change the amount of freespace
|
|
||||||
// without modifying the tree.
|
|
||||||
locks = RB_ENTRY(init)(cmpFreespace, 0);
|
|
||||||
LH_ENTRY(insert)(ap->xidAlloced, &xid, sizeof(xid), locks);
|
|
||||||
}
|
|
||||||
|
|
||||||
const availablePage *ret;
|
|
||||||
|
|
||||||
// Does this transaction already have an appropriate page?
|
|
||||||
|
|
||||||
if(!(ret = RB_ENTRY(lookup)(RB_LUGREAT, &tmp, locks))) {
|
|
||||||
|
|
||||||
// No; get a page from the availablePages.
|
|
||||||
|
|
||||||
ret = RB_ENTRY(lookup)(RB_LUGREAT, &tmp, ap->availablePages);
|
|
||||||
/*if(ret) {
|
|
||||||
assert(ret->lockCount == 0);
|
|
||||||
lockAlloced(ap, xid, (availablePage*) ret);
|
|
||||||
} */
|
|
||||||
}
|
|
||||||
|
|
||||||
// Done. (If ret is null, then it's the caller's problem.)
|
|
||||||
return (availablePage*) ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int stasis_allocation_policy_can_xid_alloc_from_page(stasis_allocation_policy_t *ap, int xid, pageid_t page) {
|
|
||||||
availablePage * p = getAvailablePage(ap, page);
|
|
||||||
const availablePage * check1 = RB_ENTRY(find)(p, ap->availablePages);
|
|
||||||
int * xidp = LH_ENTRY(find)(ap->pageOwners, &(page), sizeof(page));
|
|
||||||
if(!(xidp || check1)) {
|
|
||||||
// the page is not available, and not owned.
|
|
||||||
return 0; // can't safely alloc from page
|
|
||||||
}
|
|
||||||
if(check1) {
|
|
||||||
// the page is available and unlocked
|
|
||||||
return 1; // can safely alloc from page
|
|
||||||
} else {
|
} else {
|
||||||
// someone owns the page. Is it this xid?
|
return INVALID_PAGE;
|
||||||
return (*xidp == xid);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void stasis_allocation_policy_transaction_completed(stasis_allocation_policy_t * ap, int xid) {
|
||||||
|
pageid_t *allocPages;
|
||||||
|
pageid_t *deallocPages;
|
||||||
|
size_t allocCount;
|
||||||
|
size_t deallocCount;
|
||||||
|
int alloced = xidAlloced_lookup_by_xid(ap, xid, &allocPages, &allocCount);
|
||||||
|
int dealloced = xidDealloced_lookup_by_xid(ap, xid, &deallocPages, &deallocCount);
|
||||||
|
|
||||||
void stasis_allocation_policy_alloced_from_page(stasis_allocation_policy_t *ap, int xid, pageid_t page) {
|
if(alloced) {
|
||||||
availablePage * p = getAvailablePage(ap, page);
|
for(size_t i = 0; i < allocCount; i++) {
|
||||||
const availablePage * check1 = RB_ENTRY(find)(p, ap->availablePages);
|
xidAlloced_remove(ap, xid, allocPages[i]);
|
||||||
int * xidp = LH_ENTRY(find)(ap->pageOwners, &(page), sizeof(page));
|
}
|
||||||
if(!(xidp || check1)) {
|
free(allocPages);
|
||||||
// the page is not available, and is not owned.
|
}
|
||||||
// this can happen if more than one transaction deallocs from the same page
|
if(dealloced) {
|
||||||
assert(p->lockCount);
|
for(size_t i = 0; i < deallocCount; i++) {
|
||||||
printf("Two transactions concurrently dealloced from page; now a "
|
xidDealloced_remove(ap, xid, deallocPages[i]);
|
||||||
"transaction has alloced from it. This leads to unrecoverable "
|
}
|
||||||
"schedules. Refusing to continue.");
|
free(deallocPages);
|
||||||
fflush(stdout);
|
}
|
||||||
|
}
|
||||||
|
void stasis_allocation_policy_update_freespace(stasis_allocation_policy_t *ap, pageid_t pageid, size_t freespace) {
|
||||||
|
allPages_set_freespace(ap, pageid, freespace);
|
||||||
|
}
|
||||||
|
void stasis_allocation_policy_dealloced_from_page(stasis_allocation_policy_t *ap, int xid, pageid_t pageid) {
|
||||||
|
xidDealloced_add(ap, xid, pageid);
|
||||||
|
}
|
||||||
|
void stasis_allocation_policy_alloced_from_page(stasis_allocation_policy_t * ap, int xid, pageid_t pageid) {
|
||||||
|
if(!stasis_allocation_policy_can_xid_alloc_from_page(ap, xid, pageid)) {
|
||||||
|
fprintf(stderr, "A transaction allocated space from a page that contains records deallocated by another active transaction. "
|
||||||
|
"This leads to unrecoverable schedules. Refusing to continue.");
|
||||||
|
fflush(stderr);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
if(check1) {
|
xidAlloced_add(ap, xid, pageid);
|
||||||
assert(p->lockCount == 0);
|
}
|
||||||
lockAlloced(ap, xid, (availablePage*)p);
|
int stasis_allocation_policy_can_xid_alloc_from_page(stasis_allocation_policy_t * ap, int xid, pageid_t pageid) {
|
||||||
} else {
|
int *xids;
|
||||||
// new: this xact is allocing on a page that an active xact alloced on.
|
size_t count;
|
||||||
// perhaps this is safe, but it's spooky.
|
int ret = 1;
|
||||||
assert(*xidp == xid);
|
int existed = xidDealloced_lookup_by_pageid(ap, pageid, &xids, &count);
|
||||||
|
if(!existed) { count = 0; xids = 0;}
|
||||||
|
for(size_t i = 0; i < count ; i++) {
|
||||||
|
if(xids[i] != xid) { ret = 0; }
|
||||||
}
|
}
|
||||||
}
|
if(xids) { free(xids); }
|
||||||
|
return ret;
|
||||||
void stasis_allocation_policy_lock_page(stasis_allocation_policy_t *ap, int xid, pageid_t page) {
|
|
||||||
|
|
||||||
availablePage * p = getAvailablePage(ap, page);
|
|
||||||
lockDealloced(ap, xid, p);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void stasis_allocation_policy_transaction_completed(stasis_allocation_policy_t * ap, int xid) {
|
|
||||||
|
|
||||||
struct RB_ENTRY(tree) * locks = LH_ENTRY(find)(ap->xidAlloced, &xid, sizeof(xid));
|
|
||||||
|
|
||||||
if(locks) {
|
|
||||||
|
|
||||||
availablePage * next;
|
|
||||||
|
|
||||||
while(( next = (void*)RB_ENTRY(min)(locks) )) {
|
|
||||||
unlockAlloced(ap, xid, (next)); // This is really inefficient. (We're wasting hashtable lookups. Also, an iterator would be faster.)
|
|
||||||
}
|
|
||||||
|
|
||||||
LH_ENTRY(remove)(ap->xidAlloced, &xid, sizeof(xid));
|
|
||||||
RB_ENTRY(destroy)(locks);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
locks = LH_ENTRY(find)(ap->xidDealloced, &xid, sizeof(xid));
|
|
||||||
|
|
||||||
if(locks) {
|
|
||||||
availablePage * next;
|
|
||||||
|
|
||||||
while(( next = (void*)RB_ENTRY(min)(locks) )) {
|
|
||||||
unlockDealloced(ap, xid, (availablePage*)next); // This is really inefficient. (We're wasting hashtable lookups. Also, an iterator would be faster.)
|
|
||||||
}
|
|
||||||
|
|
||||||
LH_ENTRY(remove)(ap->xidDealloced, &xid, sizeof(xid));
|
|
||||||
RB_ENTRY(destroy)(locks);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void stasis_allocation_policy_update_freespace_unlocked_page(stasis_allocation_policy_t * ap, availablePage * key, int newFree) {
|
|
||||||
availablePage * p = (availablePage*) RB_ENTRY(delete)(key, ap->availablePages);
|
|
||||||
assert(key == p);
|
|
||||||
p->freespace = newFree;
|
|
||||||
const availablePage * ret = RB_ENTRY(search)(p, ap->availablePages);
|
|
||||||
assert(ret == p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void stasis_allocation_policy_update_freespace_locked_page(stasis_allocation_policy_t * ap, int xid, availablePage * key, int newFree) {
|
|
||||||
struct RB_ENTRY(tree) * locks = LH_ENTRY(find)(ap->xidAlloced, &xid, sizeof(xid));
|
|
||||||
assert(key);
|
|
||||||
availablePage * p = (availablePage*) RB_ENTRY(delete)(key, locks);
|
|
||||||
assert(p); // sometimes fails
|
|
||||||
p->freespace = newFree;
|
|
||||||
key->freespace = newFree;
|
|
||||||
const availablePage * ret = RB_ENTRY(search)(p, locks);
|
|
||||||
assert(ret == p);
|
|
||||||
assert(p->lockCount == 1);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -222,26 +222,18 @@ static void stasis_alloc_register_old_regions() {
|
||||||
do {
|
do {
|
||||||
DEBUG("boundary tag %lld type %d\n", boundary, t.allocation_manager);
|
DEBUG("boundary tag %lld type %d\n", boundary, t.allocation_manager);
|
||||||
if(t.allocation_manager == STORAGE_MANAGER_TALLOC) {
|
if(t.allocation_manager == STORAGE_MANAGER_TALLOC) {
|
||||||
availablePage ** newPages = malloc(sizeof(availablePage*)*(t.size+1));
|
for(pageid_t i = 0; i < t.size; i++) {
|
||||||
for(pageid_t i = 0; i < t.size; i++) {
|
Page * p = loadPage(-1, boundary + i);
|
||||||
Page * p = loadPage(-1, boundary + i);
|
readlock(p->rwlatch,0);
|
||||||
readlock(p->rwlatch,0);
|
if(p->pageType == SLOTTED_PAGE) {
|
||||||
if(p->pageType == SLOTTED_PAGE) {
|
stasis_allocation_policy_register_new_page(allocPolicy, p->id, stasis_record_freespace(-1, p));
|
||||||
availablePage * next = malloc(sizeof(availablePage));
|
DEBUG("registered page %lld\n", boundary+i);
|
||||||
next->pageid = boundary+i;
|
} else {
|
||||||
next->freespace = stasis_record_freespace(-1, p);
|
abort();
|
||||||
next->lockCount = 0;
|
}
|
||||||
newPages[i] = next;
|
unlock(p->rwlatch);
|
||||||
DEBUG("registered page %lld\n", boundary+i);
|
releasePage(p);
|
||||||
} else {
|
}
|
||||||
abort();
|
|
||||||
}
|
|
||||||
unlock(p->rwlatch);
|
|
||||||
releasePage(p);
|
|
||||||
}
|
|
||||||
newPages[t.size]=0;
|
|
||||||
stasis_allocation_policy_register_new_pages(allocPolicy, newPages);
|
|
||||||
free(newPages);
|
|
||||||
}
|
}
|
||||||
} while(TregionNextBoundaryTag(-1, &boundary, &t, 0)); //STORAGE_MANAGER_TALLOC)) {
|
} while(TregionNextBoundaryTag(-1, &boundary, &t, 0)); //STORAGE_MANAGER_TALLOC)) {
|
||||||
}
|
}
|
||||||
|
@ -253,11 +245,7 @@ static void stasis_alloc_reserve_new_region(int xid) {
|
||||||
pageid_t firstPage = TregionAlloc(xid, TALLOC_REGION_SIZE, STORAGE_MANAGER_TALLOC);
|
pageid_t firstPage = TregionAlloc(xid, TALLOC_REGION_SIZE, STORAGE_MANAGER_TALLOC);
|
||||||
int initialFreespace = -1;
|
int initialFreespace = -1;
|
||||||
|
|
||||||
availablePage ** newPages = malloc(sizeof(availablePage*)*(TALLOC_REGION_SIZE+1));
|
|
||||||
|
|
||||||
for(pageid_t i = 0; i < TALLOC_REGION_SIZE; i++) {
|
for(pageid_t i = 0; i < TALLOC_REGION_SIZE; i++) {
|
||||||
availablePage * next = malloc(sizeof(availablePage)); // * TALLOC_REGION_SIZE);
|
|
||||||
|
|
||||||
TinitializeSlottedPage(xid, firstPage + i);
|
TinitializeSlottedPage(xid, firstPage + i);
|
||||||
if(initialFreespace == -1) {
|
if(initialFreespace == -1) {
|
||||||
Page * p = loadPage(xid, firstPage);
|
Page * p = loadPage(xid, firstPage);
|
||||||
|
@ -266,17 +254,10 @@ static void stasis_alloc_reserve_new_region(int xid) {
|
||||||
unlock(p->rwlatch);
|
unlock(p->rwlatch);
|
||||||
releasePage(p);
|
releasePage(p);
|
||||||
}
|
}
|
||||||
next->pageid = firstPage + i;
|
stasis_allocation_policy_register_new_page(allocPolicy, firstPage + i, initialFreespace);
|
||||||
next->freespace = initialFreespace;
|
|
||||||
next->lockCount = 0;
|
|
||||||
newPages[i] = next;
|
|
||||||
}
|
}
|
||||||
newPages[TALLOC_REGION_SIZE]= 0;
|
|
||||||
stasis_allocation_policy_register_new_pages(allocPolicy, newPages);
|
|
||||||
free(newPages); // Don't free the structs it points to; they are in use by the allocation policy.
|
|
||||||
|
|
||||||
TendNestedTopAction(xid, nta);
|
TendNestedTopAction(xid, nta);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
compensated_function recordid Talloc(int xid, unsigned long size) {
|
compensated_function recordid Talloc(int xid, unsigned long size) {
|
||||||
|
@ -293,16 +274,16 @@ compensated_function recordid Talloc(int xid, unsigned long size) {
|
||||||
begin_action_ret(pthread_mutex_unlock, &talloc_mutex, NULLRID) {
|
begin_action_ret(pthread_mutex_unlock, &talloc_mutex, NULLRID) {
|
||||||
pthread_mutex_lock(&talloc_mutex);
|
pthread_mutex_lock(&talloc_mutex);
|
||||||
|
|
||||||
availablePage * ap =
|
pageid_t pageid =
|
||||||
stasis_allocation_policy_pick_suitable_page(allocPolicy, xid,
|
stasis_allocation_policy_pick_suitable_page(allocPolicy, xid,
|
||||||
stasis_record_type_to_size(type));
|
stasis_record_type_to_size(type));
|
||||||
|
|
||||||
if(!ap) {
|
if(pageid == INVALID_PAGE) {
|
||||||
stasis_alloc_reserve_new_region(xid);
|
stasis_alloc_reserve_new_region(xid);
|
||||||
ap = stasis_allocation_policy_pick_suitable_page(allocPolicy, xid,
|
pageid = stasis_allocation_policy_pick_suitable_page(allocPolicy, xid,
|
||||||
stasis_record_type_to_size(type));
|
stasis_record_type_to_size(type));
|
||||||
}
|
}
|
||||||
lastFreepage = ap->pageid;
|
lastFreepage = pageid;
|
||||||
|
|
||||||
Page * p = loadPage(xid, lastFreepage);
|
Page * p = loadPage(xid, lastFreepage);
|
||||||
|
|
||||||
|
@ -316,25 +297,19 @@ compensated_function recordid Talloc(int xid, unsigned long size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
unlock(p->rwlatch);
|
unlock(p->rwlatch);
|
||||||
if(!ap->lockCount) {
|
stasis_allocation_policy_update_freespace(allocPolicy, pageid, newFreespace);
|
||||||
stasis_allocation_policy_update_freespace_unlocked_page(allocPolicy, ap,
|
|
||||||
newFreespace);
|
|
||||||
} else {
|
|
||||||
stasis_allocation_policy_update_freespace_locked_page(allocPolicy, xid, ap,
|
|
||||||
newFreespace);
|
|
||||||
}
|
|
||||||
releasePage(p);
|
releasePage(p);
|
||||||
|
|
||||||
ap = stasis_allocation_policy_pick_suitable_page(allocPolicy, xid,
|
pageid = stasis_allocation_policy_pick_suitable_page(allocPolicy, xid,
|
||||||
stasis_record_type_to_size(type));
|
stasis_record_type_to_size(type));
|
||||||
|
|
||||||
if(!ap) {
|
if(pageid == INVALID_PAGE) {
|
||||||
stasis_alloc_reserve_new_region(xid);
|
stasis_alloc_reserve_new_region(xid);
|
||||||
ap = stasis_allocation_policy_pick_suitable_page(allocPolicy, xid,
|
pageid = stasis_allocation_policy_pick_suitable_page(allocPolicy, xid,
|
||||||
stasis_record_type_to_size(type));
|
stasis_record_type_to_size(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
lastFreepage = ap->pageid;
|
lastFreepage = pageid;
|
||||||
|
|
||||||
p = loadPage(xid, lastFreepage);
|
p = loadPage(xid, lastFreepage);
|
||||||
writelock(p->rwlatch, 0);
|
writelock(p->rwlatch, 0);
|
||||||
|
@ -346,8 +321,8 @@ compensated_function recordid Talloc(int xid, unsigned long size) {
|
||||||
|
|
||||||
stasis_record_alloc_done(xid, p, rid);
|
stasis_record_alloc_done(xid, p, rid);
|
||||||
int newFreespace = stasis_record_freespace(xid, p);
|
int newFreespace = stasis_record_freespace(xid, p);
|
||||||
stasis_allocation_policy_alloced_from_page(allocPolicy, xid, ap->pageid);
|
stasis_allocation_policy_alloced_from_page(allocPolicy, xid, pageid);
|
||||||
stasis_allocation_policy_update_freespace_locked_page(allocPolicy, xid, ap, newFreespace);
|
stasis_allocation_policy_update_freespace(allocPolicy, pageid, newFreespace);
|
||||||
unlock(p->rwlatch);
|
unlock(p->rwlatch);
|
||||||
|
|
||||||
alloc_arg a = { rid.slot, type };
|
alloc_arg a = { rid.slot, type };
|
||||||
|
@ -431,7 +406,7 @@ compensated_function void Tdealloc(int xid, recordid rid) {
|
||||||
readlock(p->rwlatch,0);
|
readlock(p->rwlatch,0);
|
||||||
|
|
||||||
recordid newrid = stasis_record_dereference(xid, p, rid);
|
recordid newrid = stasis_record_dereference(xid, p, rid);
|
||||||
stasis_allocation_policy_lock_page(allocPolicy, xid, newrid.page);
|
stasis_allocation_policy_dealloced_from_page(allocPolicy, xid, newrid.page);
|
||||||
|
|
||||||
int64_t size = stasis_record_length_read(xid,p,rid);
|
int64_t size = stasis_record_length_read(xid,p,rid);
|
||||||
int64_t type = stasis_record_type_read(xid,p,rid);
|
int64_t type = stasis_record_type_read(xid,p,rid);
|
||||||
|
|
|
@ -3,23 +3,16 @@
|
||||||
|
|
||||||
#include <stasis/common.h>
|
#include <stasis/common.h>
|
||||||
|
|
||||||
struct allocationPolicy;
|
struct stasis_allocation_policy_t;
|
||||||
typedef struct allocationPolicy stasis_allocation_policy_t;
|
typedef struct stasis_allocation_policy_t stasis_allocation_policy_t;
|
||||||
|
|
||||||
typedef struct availablePage {
|
|
||||||
int freespace;
|
|
||||||
pageid_t pageid;
|
|
||||||
int lockCount; // Number of active transactions that have alloced or dealloced from this page.
|
|
||||||
} availablePage;
|
|
||||||
|
|
||||||
stasis_allocation_policy_t * stasis_allocation_policy_init();
|
stasis_allocation_policy_t * stasis_allocation_policy_init();
|
||||||
void stasis_allocation_policy_deinit(stasis_allocation_policy_t * ap);
|
void stasis_allocation_policy_deinit(stasis_allocation_policy_t * ap);
|
||||||
void stasis_allocation_policy_register_new_pages(stasis_allocation_policy_t * ap, availablePage** newPages);
|
void stasis_allocation_policy_register_new_page(stasis_allocation_policy_t * ap, pageid_t page, size_t freespace); //availablePage** newPages);
|
||||||
availablePage * stasis_allocation_policy_pick_suitable_page(stasis_allocation_policy_t * ap, int xid, int freespace);
|
pageid_t stasis_allocation_policy_pick_suitable_page(stasis_allocation_policy_t * ap, int xid, size_t freespace);
|
||||||
void stasis_allocation_policy_transaction_completed(stasis_allocation_policy_t * ap, int xid);
|
void stasis_allocation_policy_transaction_completed(stasis_allocation_policy_t * ap, int xid);
|
||||||
void stasis_allocation_policy_update_freespace_unlocked_page(stasis_allocation_policy_t * ap, availablePage * key, int newFree);
|
void stasis_allocation_policy_update_freespace(stasis_allocation_policy_t * ap, pageid_t pageid, size_t freespace);
|
||||||
void stasis_allocation_policy_update_freespace_locked_page(stasis_allocation_policy_t * ap, int xid, availablePage * key, int newFree);
|
void stasis_allocation_policy_dealloced_from_page(stasis_allocation_policy_t * ap, int xid, pageid_t page);
|
||||||
void stasis_allocation_policy_lock_page(stasis_allocation_policy_t * ap, int xid, pageid_t page);
|
|
||||||
void stasis_allocation_policy_alloced_from_page(stasis_allocation_policy_t * ap, int xid, pageid_t page);
|
void stasis_allocation_policy_alloced_from_page(stasis_allocation_policy_t * ap, int xid, pageid_t page);
|
||||||
/**
|
/**
|
||||||
Check to see if it is safe to allocate from a particular page.
|
Check to see if it is safe to allocate from a particular page.
|
||||||
|
|
|
@ -44,6 +44,7 @@ terms specified in this license.
|
||||||
|
|
||||||
#include <stasis/allocationPolicy.h>
|
#include <stasis/allocationPolicy.h>
|
||||||
#include <stasis/common.h>
|
#include <stasis/common.h>
|
||||||
|
#include <stasis/constants.h>
|
||||||
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
@ -58,89 +59,61 @@ terms specified in this license.
|
||||||
START_TEST(allocationPolicy_smokeTest)
|
START_TEST(allocationPolicy_smokeTest)
|
||||||
{
|
{
|
||||||
|
|
||||||
availablePage ** pages = malloc(5 * sizeof(availablePage*));
|
|
||||||
|
|
||||||
for(int i = 0; i < 4; i++) {
|
|
||||||
pages[i] = malloc(sizeof(availablePage));
|
|
||||||
}
|
|
||||||
|
|
||||||
availablePage p;
|
|
||||||
|
|
||||||
p.pageid = 0;
|
|
||||||
p.freespace = 100;
|
|
||||||
p.lockCount = 0;
|
|
||||||
(*pages[0]) = p;
|
|
||||||
|
|
||||||
p.pageid = 1;
|
|
||||||
p.freespace = 100;
|
|
||||||
(*pages[1]) = p;
|
|
||||||
|
|
||||||
p.pageid = 2;
|
|
||||||
p.freespace = 50;
|
|
||||||
(*pages[2]) = p;
|
|
||||||
|
|
||||||
p.pageid = 3;
|
|
||||||
p.freespace = 25;
|
|
||||||
(*pages[3]) = p;
|
|
||||||
|
|
||||||
pages[4] = 0;
|
|
||||||
|
|
||||||
stasis_allocation_policy_t * ap = stasis_allocation_policy_init();
|
stasis_allocation_policy_t * ap = stasis_allocation_policy_init();
|
||||||
stasis_allocation_policy_register_new_pages(ap, pages);
|
stasis_allocation_policy_register_new_page(ap, 0, 100);
|
||||||
|
stasis_allocation_policy_register_new_page(ap, 1, 100);
|
||||||
|
stasis_allocation_policy_register_new_page(ap, 2, 50);
|
||||||
|
stasis_allocation_policy_register_new_page(ap, 3, 25);
|
||||||
|
|
||||||
availablePage * p1 = stasis_allocation_policy_pick_suitable_page(ap, 1, 51);
|
pageid_t pageid1 = stasis_allocation_policy_pick_suitable_page(ap, 1, 51);
|
||||||
stasis_allocation_policy_alloced_from_page(ap, 1, p1->pageid);
|
assert(pageid1 != INVALID_PAGE);
|
||||||
|
stasis_allocation_policy_alloced_from_page(ap, 1, pageid1);
|
||||||
|
assert(pageid1 == 0 || pageid1 == 1);
|
||||||
|
stasis_allocation_policy_update_freespace(ap, pageid1, 0);
|
||||||
|
|
||||||
assert(p1);
|
pageid_t pageid2 = stasis_allocation_policy_pick_suitable_page(ap, 1, 21);
|
||||||
assert(p1->pageid == 0 || p1->pageid == 1);
|
assert(pageid2 != INVALID_PAGE);
|
||||||
stasis_allocation_policy_update_freespace_locked_page(ap, 1, p1, 0);
|
stasis_allocation_policy_alloced_from_page(ap, 1, pageid2);
|
||||||
|
assert(pageid2 == 3);
|
||||||
|
stasis_allocation_policy_update_freespace(ap, pageid2, 0);
|
||||||
|
|
||||||
availablePage * p2 = stasis_allocation_policy_pick_suitable_page(ap, 1, 21);
|
pageid_t pageid3 = stasis_allocation_policy_pick_suitable_page(ap, 2, 51);
|
||||||
stasis_allocation_policy_alloced_from_page(ap, 1, p2->pageid);
|
stasis_allocation_policy_alloced_from_page(ap, 2, pageid3);
|
||||||
|
assert(pageid1 != pageid3);
|
||||||
|
stasis_allocation_policy_update_freespace(ap, pageid3, 0);
|
||||||
|
|
||||||
assert(p2->pageid == 3);
|
pageid_t pageid4 = stasis_allocation_policy_pick_suitable_page(ap, 2, 51);
|
||||||
stasis_allocation_policy_update_freespace_locked_page(ap, 1, p2, 0);
|
assert(pageid4 == INVALID_PAGE);
|
||||||
|
|
||||||
availablePage * p3 = stasis_allocation_policy_pick_suitable_page(ap, 2, 51);
|
pageid_t pageid5 = stasis_allocation_policy_pick_suitable_page(ap, 2, 50);
|
||||||
stasis_allocation_policy_alloced_from_page(ap, 2, p3->pageid);
|
stasis_allocation_policy_alloced_from_page(ap, 2, pageid5);
|
||||||
assert(p1->pageid != p3->pageid);
|
assert(pageid5== 2);
|
||||||
stasis_allocation_policy_update_freespace_locked_page(ap, 2, p3, 0);
|
stasis_allocation_policy_update_freespace(ap, pageid5, 0);
|
||||||
|
|
||||||
availablePage * p4 = stasis_allocation_policy_pick_suitable_page(ap, 2, 51);
|
stasis_allocation_policy_update_freespace(ap, pageid1, 100);
|
||||||
assert(!p4);
|
|
||||||
|
|
||||||
availablePage * p5 = stasis_allocation_policy_pick_suitable_page(ap, 2, 50);
|
|
||||||
stasis_allocation_policy_alloced_from_page(ap, 2, p5->pageid);
|
|
||||||
assert(p5 && p5->pageid == 2);
|
|
||||||
stasis_allocation_policy_update_freespace_locked_page(ap, 2, p5, 0);
|
|
||||||
|
|
||||||
stasis_allocation_policy_update_freespace_locked_page(ap, 1, p1, 100);
|
|
||||||
stasis_allocation_policy_transaction_completed(ap, 1);
|
stasis_allocation_policy_transaction_completed(ap, 1);
|
||||||
stasis_allocation_policy_update_freespace_unlocked_page(ap, p2, 25);
|
stasis_allocation_policy_update_freespace(ap, pageid2, 25);
|
||||||
|
|
||||||
availablePage * p6 = stasis_allocation_policy_pick_suitable_page(ap, 2, 50);
|
pageid_t pageid6 = stasis_allocation_policy_pick_suitable_page(ap, 2, 50);
|
||||||
stasis_allocation_policy_alloced_from_page(ap, 2, p6->pageid);
|
stasis_allocation_policy_alloced_from_page(ap, 2, pageid6);
|
||||||
assert(p6->pageid == 1 || p6->pageid == 0);
|
assert(pageid6 == 1 || pageid6 == 0);
|
||||||
stasis_allocation_policy_update_freespace_locked_page(ap, 2, p6, 0);
|
stasis_allocation_policy_update_freespace(ap, pageid6, 0);
|
||||||
|
|
||||||
availablePage * p7 = stasis_allocation_policy_pick_suitable_page(ap, 2, 50);
|
pageid_t pageid7 = stasis_allocation_policy_pick_suitable_page(ap, 2, 50);
|
||||||
assert(!p7);
|
assert(pageid7 == INVALID_PAGE);
|
||||||
|
|
||||||
stasis_allocation_policy_update_freespace_unlocked_page(ap, pages[3], 51);
|
stasis_allocation_policy_update_freespace(ap, 3, 51);
|
||||||
|
|
||||||
availablePage * p8 =stasis_allocation_policy_pick_suitable_page(ap, 2, 51);
|
pageid_t pageid8 =stasis_allocation_policy_pick_suitable_page(ap, 2, 51);
|
||||||
assert(p8->pageid == 3);
|
assert(pageid8 == 3);
|
||||||
stasis_allocation_policy_alloced_from_page(ap, 2, p8->pageid);
|
stasis_allocation_policy_alloced_from_page(ap, 2, pageid8);
|
||||||
|
|
||||||
stasis_allocation_policy_update_freespace_locked_page(ap, 2, p8, 0);
|
stasis_allocation_policy_update_freespace(ap, pageid8, 0);
|
||||||
|
|
||||||
stasis_allocation_policy_transaction_completed(ap, 2);
|
stasis_allocation_policy_transaction_completed(ap, 2);
|
||||||
|
|
||||||
stasis_allocation_policy_deinit(ap);
|
stasis_allocation_policy_deinit(ap);
|
||||||
|
|
||||||
free(pages);
|
|
||||||
|
|
||||||
|
|
||||||
} END_TEST
|
} END_TEST
|
||||||
|
|
||||||
#define AVAILABLE_PAGE_COUNT_A 1000
|
#define AVAILABLE_PAGE_COUNT_A 1000
|
||||||
|
@ -155,8 +128,8 @@ static const int MAX_DESIRED_FREESPACE =
|
||||||
static int nextxid = 0;
|
static int nextxid = 0;
|
||||||
int activexidcount = 0;
|
int activexidcount = 0;
|
||||||
static void takeRandomAction(stasis_allocation_policy_t * ap, int * xids,
|
static void takeRandomAction(stasis_allocation_policy_t * ap, int * xids,
|
||||||
availablePage ** pages1, availablePage ** pages2) {
|
pageid_t * pages1, pageid_t * pages2) {
|
||||||
switch(myrandom(6)) {
|
switch(myrandom(5)) {
|
||||||
case 0 : { // find page
|
case 0 : { // find page
|
||||||
int thexid = myrandom(XACT_COUNT);
|
int thexid = myrandom(XACT_COUNT);
|
||||||
if(xids[thexid] == -1) {
|
if(xids[thexid] == -1) {
|
||||||
|
@ -166,9 +139,9 @@ static void takeRandomAction(stasis_allocation_policy_t * ap, int * xids,
|
||||||
DEBUG("xid begins\n");
|
DEBUG("xid begins\n");
|
||||||
}
|
}
|
||||||
int thefreespace = myrandom(MAX_DESIRED_FREESPACE);
|
int thefreespace = myrandom(MAX_DESIRED_FREESPACE);
|
||||||
availablePage * p =
|
pageid_t p =
|
||||||
stasis_allocation_policy_pick_suitable_page(ap, xids[thexid], thefreespace);
|
stasis_allocation_policy_pick_suitable_page(ap, xids[thexid], thefreespace);
|
||||||
if(p) {
|
if(p != INVALID_PAGE) {
|
||||||
DEBUG("alloc succeeds\n");
|
DEBUG("alloc succeeds\n");
|
||||||
// xxx validate returned value...
|
// xxx validate returned value...
|
||||||
} else {
|
} else {
|
||||||
|
@ -185,7 +158,7 @@ static void takeRandomAction(stasis_allocation_policy_t * ap, int * xids,
|
||||||
DEBUG("complete");
|
DEBUG("complete");
|
||||||
} break;
|
} break;
|
||||||
case 2 : { // update freespace unlocked
|
case 2 : { // update freespace unlocked
|
||||||
int thespacediff = myrandom(MAX_DESIRED_FREESPACE/2) - (MAX_DESIRED_FREESPACE/2);
|
int thespacediff = myrandom(MAX_DESIRED_FREESPACE) - (MAX_DESIRED_FREESPACE/2);
|
||||||
int thexid;
|
int thexid;
|
||||||
if(!activexidcount) { break; }
|
if(!activexidcount) { break; }
|
||||||
while(xids[thexid = myrandom(XACT_COUNT)] == -1) { }
|
while(xids[thexid = myrandom(XACT_COUNT)] == -1) { }
|
||||||
|
@ -195,33 +168,32 @@ static void takeRandomAction(stasis_allocation_policy_t * ap, int * xids,
|
||||||
} else {
|
} else {
|
||||||
minfreespace = 0;
|
minfreespace = 0;
|
||||||
}
|
}
|
||||||
availablePage * p = stasis_allocation_policy_pick_suitable_page(ap, xids[thexid],
|
pageid_t p = stasis_allocation_policy_pick_suitable_page(ap, xids[thexid],
|
||||||
minfreespace);
|
minfreespace);
|
||||||
if(p && p->lockCount == 0) {
|
if(p != INVALID_PAGE) {
|
||||||
int thenewfreespace = p->freespace+thespacediff;
|
int thenewfreespace = myrandom(MAX_DESIRED_FREESPACE/2)+thespacediff;
|
||||||
stasis_allocation_policy_update_freespace_unlocked_page(ap, p, thenewfreespace);
|
stasis_allocation_policy_update_freespace(ap, p, thenewfreespace);
|
||||||
// printf("updated freespace unlocked");
|
// printf("updated freespace unlocked");
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case 3 : { // update freespace locked
|
case 3 : { // dealloc from page
|
||||||
} break;
|
int thexid;
|
||||||
case 4 : { // lock page
|
|
||||||
} break;
|
|
||||||
case 5 : { // alloced from page
|
|
||||||
|
|
||||||
// xxx this case is nonsense. we pick a random page, alloc from it, and allocation policy correctly sees that we're violating protocol, and cores...
|
|
||||||
// xxx write better one..
|
|
||||||
/* int thexid;
|
|
||||||
if(!activexidcount) { break; }
|
if(!activexidcount) { break; }
|
||||||
while(xids[thexid = myrandom(XACT_COUNT)] == -1) { }
|
while(xids[thexid = myrandom(XACT_COUNT)] == -1) {}
|
||||||
pageid_t thepage=myrandom(AVAILABLE_PAGE_COUNT_A + pages2?AVAILABLE_PAGE_COUNT_B:0);
|
pageid_t p = pages1[myrandom(AVAILABLE_PAGE_COUNT_A)];
|
||||||
stasis_allocation_policy_alloced_from_page(ap,thexid,thepage); */
|
stasis_allocation_policy_dealloced_from_page(ap, xids[thexid], p);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
case 4 : { // alloced from page
|
||||||
|
int thexid;
|
||||||
|
if(!activexidcount) { break; }
|
||||||
|
while(xids[thexid = myrandom(XACT_COUNT)] == -1) {}
|
||||||
|
pageid_t p = pages1[myrandom(AVAILABLE_PAGE_COUNT_A)];
|
||||||
|
if(stasis_allocation_policy_can_xid_alloc_from_page(ap, xids[thexid], p)) {
|
||||||
|
stasis_allocation_policy_alloced_from_page(ap, xids[thexid], p);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
default: abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
START_TEST(allocationPolicy_randomTest) {
|
START_TEST(allocationPolicy_randomTest) {
|
||||||
|
@ -232,10 +204,8 @@ START_TEST(allocationPolicy_randomTest) {
|
||||||
printf("\nSeed = %ld\n", seed);
|
printf("\nSeed = %ld\n", seed);
|
||||||
srandom(seed);
|
srandom(seed);
|
||||||
|
|
||||||
availablePage ** pages1 =
|
pageid_t * pages1 = malloc(AVAILABLE_PAGE_COUNT_A * sizeof(pageid_t));
|
||||||
malloc((1+AVAILABLE_PAGE_COUNT_A) * sizeof(availablePage *));
|
pageid_t * pages2 = malloc(AVAILABLE_PAGE_COUNT_B * sizeof(pageid_t));
|
||||||
availablePage ** pages2 =
|
|
||||||
malloc((1+AVAILABLE_PAGE_COUNT_B) * sizeof(availablePage *));
|
|
||||||
|
|
||||||
int * xids = malloc(sizeof(int) * XACT_COUNT);
|
int * xids = malloc(sizeof(int) * XACT_COUNT);
|
||||||
|
|
||||||
|
@ -243,35 +213,30 @@ START_TEST(allocationPolicy_randomTest) {
|
||||||
xids[i] = -1;
|
xids[i] = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < AVAILABLE_PAGE_COUNT_A; i++) {
|
|
||||||
pages1[i] = malloc(sizeof(availablePage));
|
|
||||||
pages1[i]->pageid = i;
|
|
||||||
pages1[i]->freespace = i * FREE_MUL;
|
|
||||||
pages1[i]->lockCount = 0;
|
|
||||||
}
|
|
||||||
pages1[AVAILABLE_PAGE_COUNT_A] = 0;
|
|
||||||
for(int i = 0 ; i < AVAILABLE_PAGE_COUNT_B; i++) {
|
|
||||||
pages2[i] = malloc(sizeof(availablePage));
|
|
||||||
pages2[i]->pageid = AVAILABLE_PAGE_COUNT_A + i;
|
|
||||||
pages2[i]->freespace = (AVAILABLE_PAGE_COUNT_A + i) * FREE_MUL;
|
|
||||||
pages2[i]->lockCount = 0;
|
|
||||||
}
|
|
||||||
pages2[AVAILABLE_PAGE_COUNT_B] = 0;
|
|
||||||
|
|
||||||
stasis_allocation_policy_t * ap = stasis_allocation_policy_init();
|
stasis_allocation_policy_t * ap = stasis_allocation_policy_init();
|
||||||
|
|
||||||
stasis_allocation_policy_register_new_pages(ap, pages1);
|
for(int i = 0; i < AVAILABLE_PAGE_COUNT_A; i++) {
|
||||||
|
pages1[i] = i;
|
||||||
|
stasis_allocation_policy_register_new_page(ap, i, i * FREE_MUL);
|
||||||
|
}
|
||||||
|
|
||||||
for(int k = 0; k < PHASE_ONE_COUNT; k++) {
|
for(int k = 0; k < PHASE_ONE_COUNT; k++) {
|
||||||
// Don't pass in pages2; ap doesn't know about them yet!
|
// Don't pass in pages2; ap doesn't know about them yet!
|
||||||
takeRandomAction(ap, xids, pages1, 0);
|
takeRandomAction(ap, xids, pages1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
stasis_allocation_policy_register_new_pages(ap, pages2);
|
for(int i = 0 ; i < AVAILABLE_PAGE_COUNT_B; i++) {
|
||||||
|
pages2[i] = AVAILABLE_PAGE_COUNT_A + i;
|
||||||
|
stasis_allocation_policy_register_new_page(ap, pages2[i], (AVAILABLE_PAGE_COUNT_A + i) * FREE_MUL);
|
||||||
|
}
|
||||||
|
|
||||||
for(int k = 0; k < PHASE_TWO_COUNT; k++) {
|
for(int k = 0; k < PHASE_TWO_COUNT; k++) {
|
||||||
takeRandomAction(ap, xids, pages1, pages2);
|
takeRandomAction(ap, xids, pages1, pages2);
|
||||||
}
|
}
|
||||||
|
for(int i = 0; i < XACT_COUNT; i++) {
|
||||||
|
if(xids[i] != INVALID_XID) { stasis_allocation_policy_transaction_completed(ap, xids[i]); }
|
||||||
|
}
|
||||||
|
|
||||||
stasis_allocation_policy_deinit(ap);
|
stasis_allocation_policy_deinit(ap);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue