stasis-aries-wal/src/lladd/operations/alloc.c

135 lines
3.2 KiB
C
Raw Normal View History

#include <config.h>
#include <lladd/common.h>
2004-06-24 21:10:31 +00:00
#include <lladd/operations/alloc.h>
#include <lladd/transactional.h>
2004-06-24 21:10:31 +00:00
#include <lladd/bufferManager.h>
#include "../blobManager.h"
#include "../page.h"
#include "../page/slotted.h"
#include <assert.h>
2004-06-24 21:10:31 +00:00
/**
@file
2004-06-24 21:10:31 +00:00
Implementation of Talloc() as an operation
This is a bit strange compared to other operations, as it happens
in two phases. The buffer manager reserves space for a record
before the log entry is allocated. Then, the recordid of this
space is written to the log. Finally, alloc tells bufferManager
that it will use the space.
@todo Currently, if the system crashes during an alloc, (before the
log is flushed, but after bufferManager returns a rid), then the
space alloced during the crash is leaked. This doesn't seem to be
too big of a deal, but it should be fixed someday. A more serious
problem results from crashes during blob allocation.
@ingroup OPERATIONS
$Id$
2004-06-24 21:10:31 +00:00
*/
static int operate(int xid, Page * p, lsn_t lsn, recordid rid, const void * dat) {
/* * @ todo Currently, Talloc() needs to clean up the page type (for recovery). Should this be elsewhere? */
/* if(*page_type_ptr(p) == UNINITIALIZED_PAGE) {
*page_type_ptr(p) = SLOTTED_PAGE;
} */
/* assert(*page_type_ptr(p) == SLOTTED_PAGE); */
if(rid.size >= BLOB_THRESHOLD_SIZE) {
2004-07-26 20:37:04 +00:00
allocBlob(xid, p, lsn, rid);
} else {
slottedPostRalloc(p, lsn, rid);
}
2004-06-24 21:10:31 +00:00
return 0;
}
/** @todo Currently, we just leak store space on dealloc. */
static int deoperate(int xid, Page * p, lsn_t lsn, recordid rid, const void * dat) {
/* Page * loadedPage = loadPage(rid.page); */
/** Has no effect during normal operation, other than updating the LSN. */
/* slottedPostRalloc(p, lsn, rid); */
/* Page * loadedPage = loadPage(rid.page); */
assert(rid.page == p->id);
slottedDeRalloc(p, lsn, rid);
/* releasePage(loadedPage); */
return 0;
}
static int reoperate(int xid, Page *p, lsn_t lsn, recordid rid, const void * dat) {
/* operate(xid, p, lsn, rid, dat); */
if(rid.size >= BLOB_THRESHOLD_SIZE) {
rid.size = BLOB_REC_SIZE; /* Don't reuse blob space yet... */
}
slottedPostRalloc(p, lsn, rid);
writeRecord(xid, p, lsn, rid, dat);
2004-06-24 21:10:31 +00:00
return 0;
}
Operation getAlloc() {
Operation o = {
OPERATION_ALLOC, /* ID */
0,
OPERATION_DEALLOC,
&operate
};
return o;
}
Operation getDealloc() {
Operation o = {
OPERATION_DEALLOC,
SIZEOF_RECORD,
OPERATION_REALLOC,
&deoperate
};
return o;
}
/*This is only used to undo deallocs... */
Operation getRealloc() {
Operation o = {
OPERATION_REALLOC,
0,
OPERATION_NOOP,
&reoperate
};
return o;
}
recordid Talloc(int xid, long size) {
2004-06-24 21:10:31 +00:00
recordid rid;
if(size >= BLOB_THRESHOLD_SIZE) {
rid = preAllocBlob(xid, size);
} else {
rid = slottedPreRalloc(xid, size);
}
2004-06-24 21:10:31 +00:00
Tupdate(xid,rid, NULL, OPERATION_ALLOC);
return rid;
}
void Tdealloc(int xid, recordid rid) {
void * preimage = malloc(rid.size);
Page * p = loadPage(rid.page);
readRecord(xid, p, rid, preimage);
releasePage(p); /** @todo race in Tdealloc; do we care? */
Tupdate(xid, rid, preimage, OPERATION_DEALLOC);
free(preimage);
2004-06-24 21:10:31 +00:00
}