2006-06-21 00:45:18 +00:00
|
|
|
#include <string.h>
|
2007-06-11 21:36:57 +00:00
|
|
|
#include <stasis/transactional.h>
|
2008-04-13 04:02:57 +00:00
|
|
|
#include <stasis/page/raw.h>
|
2006-06-21 00:45:18 +00:00
|
|
|
#include <assert.h>
|
2004-07-27 21:30:54 +00:00
|
|
|
|
2004-07-26 20:37:04 +00:00
|
|
|
|
2009-05-08 06:53:30 +00:00
|
|
|
void stasis_blob_alloc(int xid, recordid rid) {
|
2006-06-21 00:45:18 +00:00
|
|
|
assert(rid.size>0);
|
2008-10-03 02:42:25 +00:00
|
|
|
pageid_t pageCount = (rid.size / USABLE_SIZE_OF_PAGE) + ((rid.size % USABLE_SIZE_OF_PAGE) ? 1 : 0);
|
2006-06-21 00:45:18 +00:00
|
|
|
long startPage = TpageAllocMany(xid, pageCount);
|
|
|
|
blob_record_t rec;
|
|
|
|
rec.offset = startPage;
|
|
|
|
rec.size = rid.size;
|
2008-11-13 04:18:50 +00:00
|
|
|
rid.size = sizeof(rec);
|
|
|
|
TsetRaw(xid, rid, (byte*)&rec);
|
|
|
|
DEBUG("Page start = %d, count = %d, rid.size=%d\n", rec.offset, pageCount, rid.size);
|
|
|
|
DEBUG("rid = {%d %d %d}\n", rid.page, rid.slot, rid.size);
|
2004-06-28 21:10:10 +00:00
|
|
|
}
|
|
|
|
|
2009-05-08 06:53:30 +00:00
|
|
|
void stasis_blob_dealloc(int xid, blob_record_t *r) {
|
2008-11-13 04:18:50 +00:00
|
|
|
TregionDealloc(xid, r->offset);
|
2008-11-13 00:13:11 +00:00
|
|
|
}
|
|
|
|
|
2009-05-08 06:53:30 +00:00
|
|
|
void stasis_blob_read(int xid, Page * p, recordid rid, byte * buf) {
|
2008-10-03 02:42:25 +00:00
|
|
|
pageid_t chunk;
|
2006-06-21 00:45:18 +00:00
|
|
|
recordid rawRid = rid;
|
|
|
|
rawRid.size = BLOB_SLOT;
|
|
|
|
byte * pbuf = alloca(PAGE_SIZE);
|
2004-06-28 21:10:10 +00:00
|
|
|
blob_record_t rec;
|
2009-05-08 06:53:30 +00:00
|
|
|
stasis_record_read(xid, p, rawRid, (byte*)&rec);
|
2007-07-18 20:09:14 +00:00
|
|
|
|
|
|
|
for(chunk = 0; (chunk+1) * USABLE_SIZE_OF_PAGE < rid.size; chunk++) {
|
2009-05-08 06:53:30 +00:00
|
|
|
DEBUG("Chunk = %d->%lld\n", chunk, (long long)rec.offset+chunk);
|
2006-06-21 00:45:18 +00:00
|
|
|
TpageGet(xid, rec.offset+chunk, pbuf);
|
|
|
|
memcpy(buf + (chunk * USABLE_SIZE_OF_PAGE), pbuf, USABLE_SIZE_OF_PAGE);
|
2004-06-26 02:05:24 +00:00
|
|
|
}
|
2004-06-28 21:10:10 +00:00
|
|
|
|
2006-06-21 00:45:18 +00:00
|
|
|
TpageGet(xid, rec.offset+chunk, pbuf);
|
|
|
|
memcpy(buf + (chunk * USABLE_SIZE_OF_PAGE), pbuf, rid.size % USABLE_SIZE_OF_PAGE);
|
2009-05-08 06:53:30 +00:00
|
|
|
DEBUG("Chunk = %d->%lld\n", chunk, (long long)rec.offset+chunk);
|
2004-07-27 21:30:54 +00:00
|
|
|
}
|
2004-08-21 00:03:30 +00:00
|
|
|
|
2009-05-08 06:53:30 +00:00
|
|
|
void stasis_blob_write(int xid, Page * p, recordid rid, const void* dat) {
|
2008-09-28 03:11:24 +00:00
|
|
|
blob_record_t rec;
|
|
|
|
recordid r = rid;
|
|
|
|
r.size = sizeof(blob_record_t);
|
|
|
|
stasis_record_read(xid, p, r, (byte*)&rec);
|
2004-07-27 21:30:54 +00:00
|
|
|
|
2008-09-28 03:11:24 +00:00
|
|
|
assert(rec.offset);
|
2008-10-03 02:42:25 +00:00
|
|
|
pageid_t chunk = 0;
|
2008-09-28 03:11:24 +00:00
|
|
|
for(; (chunk+1) * USABLE_SIZE_OF_PAGE < rid.size; chunk++) {
|
|
|
|
Page * cnk = loadPage(xid, rec.offset+chunk);
|
|
|
|
writelock(cnk->rwlatch,0);
|
|
|
|
if(*stasis_page_type_ptr(cnk) != BLOB_PAGE) {
|
2009-05-08 06:53:30 +00:00
|
|
|
stasis_page_blob_initialize(cnk);
|
2008-09-28 03:11:24 +00:00
|
|
|
}
|
|
|
|
unlock(cnk->rwlatch);
|
|
|
|
// Don't care about race; writes in race have undefined semantics...
|
|
|
|
TpageSetRange(xid,rec.offset+chunk,0,((const byte*)dat)+(chunk*USABLE_SIZE_OF_PAGE),USABLE_SIZE_OF_PAGE);
|
|
|
|
}
|
|
|
|
Page * cnk = loadPage(xid, rec.offset+chunk);
|
|
|
|
writelock(cnk->rwlatch,0);
|
|
|
|
if(*stasis_page_type_ptr(cnk) != BLOB_PAGE) {
|
2009-05-08 06:53:30 +00:00
|
|
|
stasis_page_blob_initialize(cnk);
|
2008-09-28 03:11:24 +00:00
|
|
|
}
|
|
|
|
unlock(cnk->rwlatch);
|
|
|
|
byte * buf = calloc(1,USABLE_SIZE_OF_PAGE);
|
|
|
|
memcpy(buf, ((const byte*)dat)+(chunk*USABLE_SIZE_OF_PAGE), rid.size % USABLE_SIZE_OF_PAGE);
|
|
|
|
TpageSetRange(xid,rec.offset+chunk,0,buf,USABLE_SIZE_OF_PAGE);
|
|
|
|
free(buf);
|
2007-07-18 20:09:14 +00:00
|
|
|
}
|
2009-05-08 06:53:30 +00:00
|
|
|
static int stasis_page_not_supported(int xid, Page * p) { return 0; }
|
2007-07-18 20:09:14 +00:00
|
|
|
|
2009-05-08 06:53:30 +00:00
|
|
|
static void stasis_page_blob_loaded(Page *p) {
|
2007-10-02 00:18:33 +00:00
|
|
|
p->LSN = *stasis_page_lsn_ptr(p);
|
2008-09-28 03:11:24 +00:00
|
|
|
DEBUG("load lsn: %lld\n", (long long)p->LSN);
|
2007-07-18 20:09:14 +00:00
|
|
|
}
|
2009-05-08 06:53:30 +00:00
|
|
|
static void stasis_page_blob_flushed(Page *p) {
|
2007-10-02 00:18:33 +00:00
|
|
|
*stasis_page_lsn_ptr(p) = p->LSN;
|
2008-09-28 03:11:24 +00:00
|
|
|
DEBUG("flush lsn: %lld\n", (long long)p->LSN);
|
2007-07-18 20:09:14 +00:00
|
|
|
}
|
2009-05-08 06:53:30 +00:00
|
|
|
static void stasis_page_blob_cleanup(Page *p) { }
|
2004-06-26 02:05:24 +00:00
|
|
|
|
2009-05-08 06:53:30 +00:00
|
|
|
page_impl stasis_page_blob_impl() {
|
|
|
|
page_impl pi = {
|
|
|
|
BLOB_PAGE,
|
|
|
|
0, //read,
|
|
|
|
0, //write,
|
|
|
|
0, //readDone
|
|
|
|
0, //writeDone
|
|
|
|
0, //getType,
|
|
|
|
0, //setType,
|
|
|
|
0, //getLength,
|
|
|
|
0, //recordFirst,
|
|
|
|
0, //recordNext,
|
|
|
|
stasis_page_not_supported, // is block supported
|
|
|
|
0, //pageGenericBlockFirst,
|
|
|
|
0, //pageGenericBlockNext,
|
|
|
|
0, //pageGenericBlockDone,
|
|
|
|
0, //freespace,
|
|
|
|
0, //compact,
|
|
|
|
0, //preRalloc,
|
|
|
|
0, //postRalloc,
|
|
|
|
0, //Free,
|
|
|
|
0, //XXX page_impl_dereference_identity,
|
|
|
|
stasis_page_blob_loaded,
|
|
|
|
stasis_page_blob_flushed,
|
|
|
|
stasis_page_blob_cleanup
|
|
|
|
};
|
2007-07-18 20:09:14 +00:00
|
|
|
return pi;
|
2004-06-26 02:05:24 +00:00
|
|
|
}
|
2009-05-08 06:53:30 +00:00
|
|
|
void stasis_page_blob_initialize(Page * p) {
|
2008-09-28 03:11:24 +00:00
|
|
|
assertlocked(p->rwlatch);
|
|
|
|
DEBUG("lsn: %lld\n",(long long)p->LSN);
|
|
|
|
stasis_page_cleanup(p);
|
|
|
|
*stasis_page_type_ptr(p) = BLOB_PAGE;
|
|
|
|
}
|