diff --git a/src/stasis/operations/set.c b/src/stasis/operations/set.c index c9e359f..2a65f2b 100644 --- a/src/stasis/operations/set.c +++ b/src/stasis/operations/set.c @@ -90,16 +90,20 @@ typedef struct { slotid_t slot; } set_range_t; -int Tset(int xid, recordid rid, const void * dat) { - Page * p = loadPage(xid, rid.page); +Page * TsetWithPage(int xid, recordid rid, Page *p, const void * dat) { readlock(p->rwlatch,0); rid = stasis_record_dereference(xid,p,rid); + if(rid.page != p->id) { + unlock(p->rwlatch); + releasePage(p); + p = loadPage(xid, rid.page); + readlock(p->rwlatch,0); + } short type = stasis_record_type_read(xid,p,rid); if(type == BLOB_SLOT) { stasis_blob_write(xid,p,rid,dat); unlock(p->rwlatch); - releasePage(p); } else { rid.size = stasis_record_type_to_size(rid.size); if(rid.page == p->id) { @@ -107,7 +111,6 @@ int Tset(int xid, recordid rid, const void * dat) { assert(rid.size == stasis_record_length_read(xid, p, rid)); } unlock(p->rwlatch); - releasePage(p); size_t sz = sizeof(slotid_t) + sizeof(int64_t) + 2 * rid.size; byte * const buf = malloc(sz); @@ -117,11 +120,17 @@ int Tset(int xid, recordid rid, const void * dat) { *(int64_t*) b = rid.size; b += sizeof(int64_t); memcpy(b, dat, rid.size); b += rid.size; - Tread(xid, rid, b); + TreadWithPage(xid, rid, p, b); - Tupdate(xid,rid.page,buf,sz,OPERATION_SET); + TupdateWithPage(xid,rid.page,p,buf,sz,OPERATION_SET); free(buf); } + return p; +} + +int Tset(int xid, recordid rid, const void * dat) { + Page * p = loadPage(xid, rid.page); + releasePage( TsetWithPage(xid, rid, p, dat) ); return 0; } diff --git a/src/stasis/transactional2.c b/src/stasis/transactional2.c index dc42f06..46de7ac 100644 --- a/src/stasis/transactional2.c +++ b/src/stasis/transactional2.c @@ -138,14 +138,12 @@ int Tbegin() { } } -void Tupdate(int xid, pageid_t page, - const void * dat, size_t datlen, int op) { +void TupdateWithPage(int xid, pageid_t page, Page *p, const void * dat, size_t datlen, int op) { assert(stasis_initted); assert(page != INVALID_PAGE); LogEntry * e; stasis_transaction_table_entry_t * xact = stasis_transaction_table_get(stasis_transaction_table, xid); assert(xact); - Page * p = loadPageForOperation(xid, page, op, 0); if(globalLockManager.writeLockPage && p) { globalLockManager.writeLockPage(xid, page); @@ -178,6 +176,11 @@ void Tupdate(int xid, pageid_t page, } if(p) unlock(p->rwlatch); +} + +void Tupdate(int xid, pageid_t page, const void * dat, size_t datlen, int op) { + Page * p = loadPageForOperation(xid, page, op, 0); + TupdateWithPage(xid, page, p, dat, datlen, op); if(p) releasePage(p); } @@ -249,12 +252,7 @@ void TreadStr(int xid, recordid rid, char * dat) { Tread(xid, rid, dat); } -compensated_function void Tread(int xid, recordid rid, void * dat) { - Page * p; - try { - p = loadPage(xid, rid.page); - } end; - +Page * TreadWithPage(int xid, recordid rid, Page *p, void * dat) { readlock(p->rwlatch,0); rid = stasis_record_dereference(xid, p, rid); @@ -273,7 +271,16 @@ compensated_function void Tread(int xid, recordid rid, void * dat) { stasis_record_read(xid, p, rid, dat); } unlock(p->rwlatch); - releasePage(p); + return p; +} + +compensated_function void Tread(int xid, recordid rid, void * dat) { + Page * p; + try { + p = loadPage(xid, rid.page); + } end; + + releasePage( TreadWithPage(xid, rid, p, dat) ); } compensated_function void TreadRaw(int xid, recordid rid, void * dat) { diff --git a/stasis/operations/set.h b/stasis/operations/set.h index 9e0f8d2..9d1262f 100644 --- a/stasis/operations/set.h +++ b/stasis/operations/set.h @@ -61,6 +61,7 @@ terms specified in this license. @param dat the new value of the record. */ int Tset(int xid, recordid rid, const void * dat); +Page * TsetWithPage(int xid, recordid rid, Page *p, const void * dat); int TsetRaw(int xid, recordid rid, const void * dat); diff --git a/stasis/transactional.h b/stasis/transactional.h index 46c8e93..46ec01d 100644 --- a/stasis/transactional.h +++ b/stasis/transactional.h @@ -602,8 +602,8 @@ int Tbegin(void); * * @see operations.h For an overview of the operations API */ -void Tupdate(int xid, pageid_t page, - const void *dat, size_t datlen, int op); +void Tupdate(int xid, pageid_t page, const void *dat, size_t datlen, int op); +void TupdateWithPage(int xid, pageid_t page, Page *p, const void *dat, size_t datlen, int op); /** @deprecated Only exists to work around swig/python limitations. */ @@ -633,6 +633,7 @@ void TreorderableWritebackUpdate(int xid, void* h, * @param dat buffer into which data goes */ compensated_function void Tread(int xid, recordid rid, void *dat); +Page * TreadWithPage(int xid, recordid rid, Page *p, void *dat); /** * Read a value of a record without first dereferencing the record. * Use Tread() unless you're implementing code that provides