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

196 lines
4.9 KiB
C
Raw Normal View History

#include <config.h>
#include <lladd/common.h>
2005-01-20 21:19:47 +00:00
#include <lladd/operations.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 && rid.size != BLOB_SLOT) {
2004-07-26 20:37:04 +00:00
allocBlob(xid, p, lsn, rid);
} else {
slottedPostRalloc(xid, p, lsn, rid);
}
2004-06-24 21:10:31 +00:00
return 0;
}
/** @todo Currently, we leak empty pages on dealloc. */
static int deoperate(int xid, Page * p, lsn_t lsn, recordid rid, const void * dat) {
assert(rid.page == p->id);
slottedDeRalloc(xid, p, lsn, rid);
return 0;
}
static int reoperate(int xid, Page *p, lsn_t lsn, recordid rid, const void * dat) {
if(rid.size >= BLOB_THRESHOLD_SIZE && rid.size != BLOB_SLOT) {
// rid.size = BLOB_REC_SIZE; /* Don't reuse blob space yet... */
rid.size = sizeof(blob_record_t);
}
slottedPostRalloc(xid, p, lsn, rid);
/** @todo dat should be the pointer to the space in the blob store. */
writeRecord(xid, p, lsn, rid, dat);
2004-06-24 21:10:31 +00:00
return 0;
}
static pthread_mutex_t talloc_mutex;
2004-06-24 21:10:31 +00:00
Operation getAlloc() {
pthread_mutex_init(&talloc_mutex, NULL);
2004-06-24 21:10:31 +00:00
Operation o = {
OPERATION_ALLOC, /* ID */
0,
OPERATION_DEALLOC, /* OPERATION_NOOP, */
2004-06-24 21:10:31 +00:00
&operate
};
return o;
}
Operation getDealloc() {
Operation o = {
OPERATION_DEALLOC,
SIZEOF_RECORD,
OPERATION_REALLOC, /* OPERATION_NOOP, */
&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;
Page * p = NULL;
if(size >= BLOB_THRESHOLD_SIZE && size != BLOB_SLOT) {
/**@todo is it OK that Talloc doesn't pin the page when a blob is alloced?*/
rid = preAllocBlob(xid, size);
} else {
pthread_mutex_lock(&talloc_mutex);
rid = slottedPreRalloc(xid, size, &p);
assert(p != NULL);
}
2004-06-24 21:10:31 +00:00
Tupdate(xid,rid, NULL, OPERATION_ALLOC);
if(p != NULL) {
/* release the page that preAllocBlob pinned for us. */
/* @todo alloc.c pins multiple pages -> Will deadlock with small buffer sizes.. */
releasePage(p);
pthread_mutex_unlock(&talloc_mutex);
}
2004-06-24 21:10:31 +00:00
return rid;
}
recordid TallocFromPage(int xid, long page, long size) {
recordid rid;
Page * p = NULL;
if(size >= BLOB_THRESHOLD_SIZE && size != BLOB_SLOT) {
rid = preAllocBlobFromPage(xid, page, size);
} else {
pthread_mutex_lock(&talloc_mutex);
rid = slottedPreRallocFromPage(xid, page, size, &p);
if(p == NULL) {
assert(rid.size == -1);
pthread_mutex_unlock(&talloc_mutex);
return rid;
}
}
Tupdate(xid,rid, NULL, OPERATION_ALLOC);
if(p != NULL) {
/* release the page that preRallocFromPage pinned for us. */
/* @todo alloc.c pins multiple pages -> Will deadlock with small buffer sizes.. */
releasePage(p);
pthread_mutex_unlock(&talloc_mutex);
}
return rid;
}
2004-06-24 21:10:31 +00:00
void Tdealloc(int xid, recordid rid) {
void * preimage = malloc(rid.size);
Page * p = loadPage(xid, rid.page);
readRecord(xid, p, rid, preimage);
/** @todo race in Tdealloc; do we care, or is this something that the log manager should cope with? */
Tupdate(xid, rid, preimage, OPERATION_DEALLOC);
releasePage(p);
free(preimage);
2004-06-24 21:10:31 +00:00
}
2004-12-01 01:26:25 +00:00
int TrecordType(int xid, recordid rid) {
Page * p = loadPage(xid, rid.page);
2004-12-01 01:26:25 +00:00
int ret = getRecordType(xid, p, rid);
releasePage(p);
return ret;
}
int TrecordSize(int xid, recordid rid) {
int ret;
Page * p = loadPage(xid, rid.page);
ret = getRecordSize(xid, p, rid);
releasePage(p);
return ret;
}
int TrecordsInPage(int xid, int pageid) {
Page * p = loadPage(xid, pageid);
readlock(p->rwlatch, 187);
int ret = *numslots_ptr(p);
unlock(p->rwlatch);
releasePage(p);
return ret;
}