From 96e7af92a403c2fc22cc4d0cfd6fa0182135c5ae Mon Sep 17 00:00:00 2001 From: Sears Russell Date: Sat, 2 Oct 2004 07:29:34 +0000 Subject: [PATCH] Added test cases for Tprepare(), implemented some redo-only operations, and started to clean up record allocation/deallocation. Also, numerous bugfixes. --- lladd/constants.h | 8 +- lladd/operations.h | 3 +- lladd/operations/alloc.h | 1 + lladd/operations/instantSet.h | 62 ++++++++++ lladd/operations/noop.h | 60 ++++++++++ lladd/operations/prepare.h | 6 +- src/lladd/Makefile.am | 8 +- src/lladd/bufferManager.c | 2 +- src/lladd/logger/logger2.c | 4 + src/lladd/operations/alloc.c | 61 +++++++--- src/lladd/operations/instantSet.c | 60 ++++++++++ src/lladd/operations/lladdhash.c | 1 + src/lladd/operations/noop.c | 64 +++++++++++ src/lladd/operations/prepare.c | 41 +++++-- src/lladd/page.c | 6 +- src/lladd/page/slotted.c | 17 ++- src/lladd/page/slotted.h | 2 +- src/lladd/recovery2.c | 6 +- src/lladd/transactional2.c | 7 +- test/lladd/check_operations.c | 182 +++++++++++++++++++++++++++++- test/lladd/check_page.c | 4 +- test/lladd/check_pageOperations.c | 1 - 22 files changed, 558 insertions(+), 48 deletions(-) create mode 100644 lladd/operations/instantSet.h create mode 100644 lladd/operations/noop.h create mode 100644 src/lladd/operations/instantSet.c create mode 100644 src/lladd/operations/noop.c diff --git a/lladd/constants.h b/lladd/constants.h index 5c71a7d..1bab788 100644 --- a/lladd/constants.h +++ b/lladd/constants.h @@ -96,7 +96,8 @@ terms specified in this license. #define OPERATION_LHINSERT 5 #define OPERATION_LHREMOVE 6 #define OPERATION_DEALLOC 7 -/*#define OPERATION_PAGE_ALLOC 8 +#define OPERATION_REALLOC 8 +/*#define OPERATION_PAGE_ALLOC ? #define OPERATION_PAGE_DEALLOC 9 */ #define OPERATION_PAGE_SET 10 #define OPERATION_UPDATE_FREESPACE 11 @@ -106,9 +107,10 @@ terms specified in this license. #define OPERATION_FREE_PAGE 15 #define OPERATION_ALLOC_FREED 16 #define OPERATION_UNALLOC_FREED 17 - +#define OPERATION_NOOP 18 +#define OPERATION_INSTANT_SET 19 /* number above should be less than number below */ -#define MAX_OPERATIONS 20 +#define MAX_OPERATIONS 40 /** This constant is used as a placeholder to mark slot locations that are invalid. @see slotted.c, indirect.c diff --git a/lladd/operations.h b/lladd/operations.h index e3f01e4..1c32a8a 100644 --- a/lladd/operations.h +++ b/lladd/operations.h @@ -137,7 +137,8 @@ typedef struct { #include "operations/lladdhash.h" #include "operations/alloc.h" #include "operations/pageOperations.h" - +#include "operations/noop.h" +#include "operations/instantSet.h" extern Operation operationsTable[]; /* [MAX_OPERATIONS]; memset somewhere */ diff --git a/lladd/operations/alloc.h b/lladd/operations/alloc.h index 10f20c9..2f61186 100644 --- a/lladd/operations/alloc.h +++ b/lladd/operations/alloc.h @@ -13,6 +13,7 @@ Operation getAlloc(); Operation getDealloc(); +Operation getRealloc(); /** Allocate a record. diff --git a/lladd/operations/instantSet.h b/lladd/operations/instantSet.h new file mode 100644 index 0000000..ed8ec60 --- /dev/null +++ b/lladd/operations/instantSet.h @@ -0,0 +1,62 @@ +/*--- +This software is copyrighted by the Regents of the University of +California, and other parties. The following terms apply to all files +associated with the software unless explicitly disclaimed in +individual files. + +The authors hereby grant permission to use, copy, modify, distribute, +and license this software and its documentation for any purpose, +provided that existing copyright notices are retained in all copies +and that this notice is included verbatim in any distributions. No +written agreement, license, or royalty fee is required for any of the +authorized uses. Modifications to this software may be copyrighted by +their authors and need not follow the licensing terms described here, +provided that the new terms are clearly indicated on the first page of +each file where they apply. + +IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY +FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY +DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND +NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND +THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +GOVERNMENT USE: If you are acquiring this software on behalf of the +U.S. government, the Government shall have only "Restricted Rights" in +the software and related documentation as defined in the Federal +Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are +acquiring the software on behalf of the Department of Defense, the +software shall be classified as "Commercial Computer Software" and the +Government shall have only "Restricted Rights" as defined in Clause +252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the +authors grant the U.S. Government and others acting in its behalf +permission to use and distribute the software in accordance with the +terms specified in this license. +---*/ +/** + * @file + * + * function definitions for set + * + * @ingroup OPERATIONS + * + * $Id$ + * + **********************************************/ + +#ifndef __INSTANT_SET_H__ +#define __INSTANT_SET_H__ + +#include + +#define TinstantSet(xid,rid,dat) Tupdate(xid,rid,dat, OPERATION_INSTANT_SET) + +Operation getInstantSet(); + +#endif diff --git a/lladd/operations/noop.h b/lladd/operations/noop.h new file mode 100644 index 0000000..fc71a2a --- /dev/null +++ b/lladd/operations/noop.h @@ -0,0 +1,60 @@ +/*--- +This software is copyrighted by the Regents of the University of +California, and other parties. The following terms apply to all files +associated with the software unless explicitly disclaimed in +individual files. + +The authors hereby grant permission to use, copy, modify, distribute, +and license this software and its documentation for any purpose, +provided that existing copyright notices are retained in all copies +and that this notice is included verbatim in any distributions. No +written agreement, license, or royalty fee is required for any of the +authorized uses. Modifications to this software may be copyrighted by +their authors and need not follow the licensing terms described here, +provided that the new terms are clearly indicated on the first page of +each file where they apply. + +IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY +FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY +DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND +NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND +THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +GOVERNMENT USE: If you are acquiring this software on behalf of the +U.S. government, the Government shall have only "Restricted Rights" in +the software and related documentation as defined in the Federal +Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are +acquiring the software on behalf of the Department of Defense, the +software shall be classified as "Commercial Computer Software" and the +Government shall have only "Restricted Rights" as defined in Clause +252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the +authors grant the U.S. Government and others acting in its behalf +permission to use and distribute the software in accordance with the +terms specified in this license. +---*/ +/** + * @file + * + * function definitions for set + * + * @ingroup OPERATIONS + * + * $Id$ + * + **********************************************/ + +#ifndef __NOOP_H__ +#define __NOOP_H__ + +#include + +Operation getNoop(); + +#endif diff --git a/lladd/operations/prepare.h b/lladd/operations/prepare.h index 3561312..edbc5aa 100644 --- a/lladd/operations/prepare.h +++ b/lladd/operations/prepare.h @@ -87,8 +87,10 @@ extern recordid prepare_bogus_rec; @todo Tprepare() shouldn't take a record or buffer as arguments... @param xid Transaction id. + @param rec must be a valid record id. any valid recordid will do. This parameter will be removed eventually. + @param dat unused. */ -#define Tprepare(xid, rec, dat) Tupdate(xid, rec, 0, OPERATION_PREPARE) +#define Tprepare(xid, rec) Tupdate(xid, rec, 0, OPERATION_PREPARE) Operation getPrepare(); @@ -97,4 +99,6 @@ Operation getPrepare(); */ int prepareGuard(LogEntry * e, void * state); void * getPrepareGuardState(); +int prepareAction(void * state); #endif + diff --git a/src/lladd/Makefile.am b/src/lladd/Makefile.am index 0777246..05de0d5 100644 --- a/src/lladd/Makefile.am +++ b/src/lladd/Makefile.am @@ -3,6 +3,12 @@ lib_LIBRARIES=liblladd.a #liblladd_a_LIBADD=logger/liblogger.a operations/liboperations.a # removed: recovery.c transactional.c logger.c logger/logparser.c logger/logstreamer.c -liblladd_a_SOURCES=common.c stats.c io.c bufferManager.c linkedlist.c operations.c pageFile.c pageCache.c page.c blobManager.c recovery2.c transactional2.c logger/logEntry.c logger/logWriter.c logger/logHandle.c logger/logger2.c operations/pageOperations.c page/indirect.c operations/decrement.c operations/increment.c operations/prepare.c operations/set.c operations/alloc.c page/slotted.c operations/lladdhash.c page/header.c +liblladd_a_SOURCES=common.c stats.c io.c bufferManager.c linkedlist.c operations.c \ + pageFile.c pageCache.c page.c blobManager.c recovery2.c transactional2.c \ + logger/logEntry.c logger/logWriter.c logger/logHandle.c logger/logger2.c \ + operations/pageOperations.c page/indirect.c operations/decrement.c \ + operations/increment.c operations/prepare.c operations/set.c \ + operations/alloc.c operations/noop.c operations/instantSet.c \ + page/slotted.c operations/lladdhash.c page/header.c AM_CFLAGS= -g -Wall -pedantic -std=gnu99 diff --git a/src/lladd/bufferManager.c b/src/lladd/bufferManager.c index 29f1b1b..7d26be0 100644 --- a/src/lladd/bufferManager.c +++ b/src/lladd/bufferManager.c @@ -101,7 +101,7 @@ void bufDeinit() { for( p = (Page*)pblHtFirst( activePages ); p; p = (Page*)pblHtNext(activePages)) { - pblHtRemove( activePages, 0, 0 ) + pblHtRemove( activePages, 0, 0 ); DEBUG("+"); /** @todo No one seems to set the dirty flag... */ /*if(p->dirty && (ret = pageWrite(p)/ *flushPage(*p)* /)) { diff --git a/src/lladd/logger/logger2.c b/src/lladd/logger/logger2.c index 5f30872..775a4f7 100644 --- a/src/lladd/logger/logger2.c +++ b/src/lladd/logger/logger2.c @@ -109,6 +109,10 @@ LogEntry * LogUpdate(TransactionLog * l, Page * p, recordid rid, int operation, } + + + + e = allocUpdateLogEntry(l->prevLSN, l->xid, operation, rid, args, argSize, preImage); writeLogEntry(e); diff --git a/src/lladd/operations/alloc.c b/src/lladd/operations/alloc.c index a351a32..8c005b0 100644 --- a/src/lladd/operations/alloc.c +++ b/src/lladd/operations/alloc.c @@ -54,7 +54,26 @@ static int operate(int xid, Page * p, lsn_t lsn, recordid rid, const void * dat) 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); + /* 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); + return 0; } @@ -69,6 +88,27 @@ Operation getAlloc() { } +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) { recordid rid; @@ -84,18 +124,11 @@ recordid Talloc(int xid, long size) { } - - -Operation getDealloc() { - Operation o = { - OPERATION_DEALLOC, - 0, - OPERATION_ALLOC, - &deoperate - }; - return o; -} - void Tdealloc(int xid, recordid rid) { - Tupdate(xid, rid, NULL, OPERATION_DEALLOC); + 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); } diff --git a/src/lladd/operations/instantSet.c b/src/lladd/operations/instantSet.c new file mode 100644 index 0000000..17ee983 --- /dev/null +++ b/src/lladd/operations/instantSet.c @@ -0,0 +1,60 @@ +/*--- +This software is copyrighted by the Regents of the University of +California, and other parties. The following terms apply to all files +associated with the software unless explicitly disclaimed in +individual files. + +The authors hereby grant permission to use, copy, modify, distribute, +and license this software and its documentation for any purpose, +provided that existing copyright notices are retained in all copies +and that this notice is included verbatim in any distributions. No +written agreement, license, or royalty fee is required for any of the +authorized uses. Modifications to this software may be copyrighted by +their authors and need not follow the licensing terms described here, +provided that the new terms are clearly indicated on the first page of +each file where they apply. + +IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY +FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY +DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND +NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND +THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +GOVERNMENT USE: If you are acquiring this software on behalf of the +U.S. government, the Government shall have only "Restricted Rights" in +the software and related documentation as defined in the Federal +Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are +acquiring the software on behalf of the Department of Defense, the +software shall be classified as "Commercial Computer Software" and the +Government shall have only "Restricted Rights" as defined in Clause +252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the +authors grant the U.S. Government and others acting in its behalf +permission to use and distribute the software in accordance with the +terms specified in this license. +---*/ +/********************************************** + * $Id$ + * + * sets the given reference to dat + **********************************************/ + +#include +#include +#include "../page.h" + +/** @todo The spirit of instantSet suggests that it should hold a + shorter write lock than set, but instant set was written before + the lock manager... */ +Operation getInstantSet() { + Operation o = getSet(); + o.id = OPERATION_INSTANT_SET; + o.undo = OPERATION_NOOP; + return o; +} diff --git a/src/lladd/operations/lladdhash.c b/src/lladd/operations/lladdhash.c index 8d1744c..7da5782 100644 --- a/src/lladd/operations/lladdhash.c +++ b/src/lladd/operations/lladdhash.c @@ -63,6 +63,7 @@ int lHtValid(int xid, lladdHash_t *ht) { } else { ret = 1; } + releasePage(p); return ret; } /** diff --git a/src/lladd/operations/noop.c b/src/lladd/operations/noop.c new file mode 100644 index 0000000..936851b --- /dev/null +++ b/src/lladd/operations/noop.c @@ -0,0 +1,64 @@ +/*--- +This software is copyrighted by the Regents of the University of +California, and other parties. The following terms apply to all files +associated with the software unless explicitly disclaimed in +individual files. + +The authors hereby grant permission to use, copy, modify, distribute, +and license this software and its documentation for any purpose, +provided that existing copyright notices are retained in all copies +and that this notice is included verbatim in any distributions. No +written agreement, license, or royalty fee is required for any of the +authorized uses. Modifications to this software may be copyrighted by +their authors and need not follow the licensing terms described here, +provided that the new terms are clearly indicated on the first page of +each file where they apply. + +IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY +FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY +DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND +NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND +THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +GOVERNMENT USE: If you are acquiring this software on behalf of the +U.S. government, the Government shall have only "Restricted Rights" in +the software and related documentation as defined in the Federal +Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are +acquiring the software on behalf of the Department of Defense, the +software shall be classified as "Commercial Computer Software" and the +Government shall have only "Restricted Rights" as defined in Clause +252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the +authors grant the U.S. Government and others acting in its behalf +permission to use and distribute the software in accordance with the +terms specified in this license. +---*/ +/********************************************** + * $Id$ + * + * sets the given reference to dat + **********************************************/ + +#include +#include "../page.h" + +static int operate(int xid, Page *p, lsn_t lsn, recordid rid, const void *dat) { + pageWriteLSN(p, lsn); + return 0; +} + +Operation getNoop() { + Operation o = { + OPERATION_NOOP, + 0, + OPERATION_NOOP, + &operate + }; + return o; +} diff --git a/src/lladd/operations/prepare.c b/src/lladd/operations/prepare.c index 9b94613..173b17b 100644 --- a/src/lladd/operations/prepare.c +++ b/src/lladd/operations/prepare.c @@ -49,7 +49,7 @@ terms specified in this license. #include #include "../logger/logWriter.h" #include - +#include recordid prepare_bogus_rec = { 0, 0, 0}; static int operate(int xid, Page * p, lsn_t lsn, recordid rid, const void *dat) { @@ -61,12 +61,7 @@ Operation getPrepare() { Operation o = { OPERATION_PREPARE, /* id */ 0, /* No extra data. */ - OPERATION_PREPARE, /* If we set this to NO_INVERSE, it - will needlessly store a - pre-image of something... since - OPERATION_PREPARE just performs - a log flush, calling it during - redo is harmless. */ + OPERATION_NOOP, &operate /* Function */ }; return o; @@ -74,22 +69,46 @@ Operation getPrepare() { /** PrepareGuardState is 1 if the iterator should continue on the next (previous) log entry, 0 otherwise. */ -typedef int PrepareGuardState; +typedef struct{ + int continueIterating; + int prevLSN; + int xid; +} PrepareGuardState; void * getPrepareGuardState() { PrepareGuardState * s = malloc (sizeof(PrepareGuardState)); - *s = 1; + s->continueIterating = 1; + s->prevLSN = -1; + s->xid = -1; return s; } int prepareGuard(LogEntry * e, void * state) { PrepareGuardState * pgs = state; - int ret = *pgs; + int ret = pgs->continueIterating; if(e->type == UPDATELOG) { if(e->contents.update.funcID == OPERATION_PREPARE) { - *pgs = 0; + pgs->continueIterating = 0; + pgs->prevLSN = e->prevLSN; } } + if(pgs->xid == -1) { + pgs->xid = e->xid; + } else { + assert(pgs->xid == e->xid); + } + return ret; } + +/** @todo When fleshing out the logHandle's prepareAction interface, figure out what the return value should mean... */ +int prepareAction( +void * state) { + PrepareGuardState * pgs = state; + if(!pgs->continueIterating) { + assert(pgs->prevLSN != -1); + Trevive(pgs->xid, pgs->prevLSN); + } + return 0; +} diff --git a/src/lladd/page.c b/src/lladd/page.c index 47e0cbb..c574a8f 100644 --- a/src/lladd/page.c +++ b/src/lladd/page.c @@ -169,7 +169,7 @@ void pageCommit(int xid) { void pageAbort(int xid) { } - +/* static int pageAllocUnlocked() { int ret = lastAllocedPage; Page * p; @@ -177,7 +177,7 @@ static int pageAllocUnlocked() { lastAllocedPage += 1; p = loadPage(lastAllocedPage); - /** TODO Incorrect, but this kludge tricks the tests (for now) */ + / ** TODO Incorrect, but this kludge tricks the tests (for now) * / while(*page_type_ptr(p) != UNINITIALIZED_PAGE) { releasePage(p); lastAllocedPage++; @@ -186,7 +186,7 @@ static int pageAllocUnlocked() { releasePage(p); return ret; -} +}*/ /** @todo DATA CORRUPTION BUG pageAllocMultiple needs to scan forward in the store file until diff --git a/src/lladd/page/slotted.c b/src/lladd/page/slotted.c index 43fbcf5..47dca75 100644 --- a/src/lladd/page/slotted.c +++ b/src/lladd/page/slotted.c @@ -283,12 +283,16 @@ recordid slottedPostRalloc(Page * page, lsn_t lsn, recordid rid) { slottedPageInitialize(page); } - if(*slot_length_ptr(page, rid.slot) == 0 /*|| *slot_length_ptr(page, rid.slot) == -1*/) { + if((*slot_length_ptr(page, rid.slot) == 0) || (*slot_ptr(page, rid.slot) == INVALID_SLOT)) { + /* if(*slot_ptr(page, rid.slot) == INVALID_SLOT) { */ __really_do_ralloc(page, rid); } else { + int ijk = rid.size; + int lmn = *slot_length_ptr(page, rid.slot); + assert((rid.size == *slot_length_ptr(page, rid.slot)) || (*slot_length_ptr(page, rid.slot) >= PAGE_SIZE)); @@ -302,14 +306,17 @@ recordid slottedPostRalloc(Page * page, lsn_t lsn, recordid rid) { } -void slottedDeRalloc(Page * page, recordid rid) { +void slottedDeRalloc(Page * page, lsn_t lsn, recordid rid) { readlock(page->rwlatch, 443); *slot_ptr(page, rid.slot) = INVALID_SLOT; - *slot_length_ptr(page, rid.slot) = *freelist_ptr(page); - *freelist_ptr(page) = rid.slot; - + *slot_length_ptr(page, rid.slot) = *freelist_ptr(page); + *freelist_ptr(page) = rid.slot; + /* *slot_length_ptr(page, rid.slot) = 0; */ + + pageWriteLSN(page, lsn); + unlock(page->rwlatch); } diff --git a/src/lladd/page/slotted.h b/src/lladd/page/slotted.h index ec12109..c621db3 100644 --- a/src/lladd/page/slotted.h +++ b/src/lladd/page/slotted.h @@ -111,7 +111,7 @@ recordid slottedPostRalloc(Page * page, lsn_t lsn, recordid rid); * * @param rid the recordid to be freed. */ -void slottedDeRalloc(Page * page, recordid rid); +void slottedDeRalloc(Page * page, lsn_t lsn, recordid rid); void slottedPageInit(); void slottedPageDeinit(); diff --git a/src/lladd/recovery2.c b/src/lladd/recovery2.c index 2839998..4fa5204 100644 --- a/src/lladd/recovery2.c +++ b/src/lladd/recovery2.c @@ -179,12 +179,13 @@ static void Undo(int recovery) { /* printf("!"); fflush(NULL); */ - prepare_guard_state = getPrepareGuardState(); while(rollbackLSNs != NULL) { LogEntry * e; lsn_t rollback = popMaxVal(&rollbackLSNs); + prepare_guard_state = getPrepareGuardState(); + DEBUG("Undoing LSN %ld\n", (long int)rollback); if(recovery) { /** @todo shouldn't be hardcoded here! */ @@ -250,10 +251,11 @@ static void Undo(int recovery) { } free(e); } + prepareAction(prepare_guard_state); + free(prepare_guard_state); /* printf("$"); fflush(NULL); */ } - free(prepare_guard_state); } void InitiateRecovery() { diff --git a/src/lladd/transactional2.c b/src/lladd/transactional2.c index f473be2..e38573d 100644 --- a/src/lladd/transactional2.c +++ b/src/lladd/transactional2.c @@ -41,6 +41,7 @@ void setupOperationsTable() { /* operationsTable[OPERATION_LHINSERT] = getLHInsert(); operationsTable[OPERATION_LHREMOVE] = getLHRemove(); */ operationsTable[OPERATION_DEALLOC] = getDealloc(); + operationsTable[OPERATION_REALLOC] = getRealloc(); /* operationsTable[OPERATION_PAGE_ALLOC] = getPageAlloc(); operationsTable[OPERATION_PAGE_DEALLOC] = getPageDealloc(); */ operationsTable[OPERATION_PAGE_SET] = getPageSet(); @@ -53,7 +54,8 @@ void setupOperationsTable() { operationsTable[OPERATION_FREE_PAGE] = getFreePageOperation(); operationsTable[OPERATION_ALLOC_FREED] = getAllocFreedPage(); operationsTable[OPERATION_UNALLOC_FREED] = getUnallocFreedPage(); - + operationsTable[OPERATION_NOOP] = getNoop(); + operationsTable[OPERATION_INSTANT_SET] = getInstantSet(); } @@ -219,6 +221,9 @@ int Tdeinit() { void Trevive(int xid, long lsn) { int index = xid % MAX_TRANSACTIONS; pthread_mutex_lock(&transactional_2_mutex); + + DEBUG("Reviving xid %d at lsn %ld\n", xid, lsn); + if(XactionTable[index].xid != INVALID_XTABLE_XID) { if(xid != XactionTable[index].xid) { printf("Clashing Tprepare()'ed XID's encountered on recovery!!\n"); diff --git a/test/lladd/check_operations.c b/test/lladd/check_operations.c index 201de8c..708abfb 100644 --- a/test/lladd/check_operations.c +++ b/test/lladd/check_operations.c @@ -43,6 +43,8 @@ terms specified in this license. #include #include +#include "../../src/lladd/logger/logWriter.h" + #include #include "../check_includes.h" @@ -51,7 +53,11 @@ terms specified in this license. #define LOG_NAME "check_operations.log" +void simulateBufferManagerCrash(); +extern int numActiveXactions; /** + @test + Assuming that the Tset() operation is implemented correctly, checks that doUpdate, redoUpdate and undoUpdate are working correctly, for operations that use physical logging. @@ -197,6 +203,179 @@ START_TEST(operation_physical_do_undo) { } END_TEST +/** + @test check the Tprepare() call by simulating crashes. +*/ +START_TEST(operation_prepare) { + + /* Check this sequence prepare, action, crash, recover, read, action, abort, read again. */ + + Tinit(); + + int loser = Tbegin(); + int prepared = Tbegin(); + int winner = Tbegin(); + + recordid a = Talloc(winner, sizeof(int)); + recordid b = Talloc(winner, sizeof(int)); + + int one =1; + int two =2; + int three=3; + + Tset(winner, a, &one); + Tset(winner, b, &one); + + Tset(loser, a, &three); + Tset(prepared, b, &three); + + Tprepare(prepared, a); + + Tset(prepared, b, &two); + + Tcommit(winner); + + simulateBufferManagerCrash(); + closeLogWriter(); + numActiveXactions = 0; + + + Tinit(); + + int in; + + Tread(prepared, b, &in); + + assert(in == three); + + Tset(prepared, b, &two); + + Tabort(prepared); + + int checker = Tbegin(); + + Tread(checker, b, &in); + + assert(in == one); + + Tread(checker, a, &in); + + assert(in == one); + + Tcommit(checker); + + Tdeinit(); + /* Check this sequence prepare, action, crash, recover, read, action, _COMMIT_, read again. */ + + Tinit(); + + loser = Tbegin(); + prepared = Tbegin(); + winner = Tbegin(); + + a = Talloc(winner, sizeof(int)); + b = Talloc(winner, sizeof(int)); + + one =1; + two =2; + three=3; + + Tset(winner, a, &one); + Tset(winner, b, &one); + + Tset(loser, a, &three); + Tset(prepared, b, &three); + + Tprepare(prepared, a); + + Tset(prepared, b, &two); + + Tcommit(winner); + + simulateBufferManagerCrash(); + closeLogWriter(); + numActiveXactions = 0; + + + Tinit(); + + Tread(prepared, b, &in); + + assert(in == three); + + Tset(prepared, b, &two); + + Tcommit(prepared); + + checker = Tbegin(); + + Tread(checker, b, &in); + + assert(in == two); + + Tread(checker, a, &in); + + assert(in == one); + + Tcommit(checker); + + Tdeinit(); + +} END_TEST +/** + @test make sure the TinstantSet() operation works as expected during normal operation. + @todo need to write test for TinstantSet() for the recovery case... +*/ + +START_TEST(operation_instant_set) { + + Tinit(); + + int xid = Tbegin(); + + recordid rid = Talloc(xid, sizeof(int)); /** @todo probably need an immediate version of TpageAlloc... */ + int one = 1; + int two = 2; + int three = 3; + Tset(xid, rid, &one); + + Tcommit(xid); + + xid = Tbegin(); + + TinstantSet(xid, rid, &two); + + Tset(xid, rid, &three); + + Tabort(xid); + + xid = Tbegin(); + + Tread(xid, rid, &three); + + assert(two == three); + + Tcommit(xid); + + Tdeinit(); + + Tinit(); + + xid = Tbegin(); + + Tread(xid, rid, &three); + + assert(two == three); + + Tcommit(xid); + + Tdeinit(); + + + +} END_TEST + + /** Add suite declarations here @@ -208,7 +387,8 @@ Suite * check_suite(void) { /* Sub tests are added, one per line, here */ tcase_add_test(tc, operation_physical_do_undo); - + tcase_add_test(tc, operation_instant_set); + tcase_add_test(tc, operation_prepare); /* --------------------------------------------- */ tcase_add_checked_fixture(tc, setup, teardown); suite_add_tcase(s, tc); diff --git a/test/lladd/check_page.c b/test/lladd/check_page.c index b17054f..e8f2f59 100644 --- a/test/lladd/check_page.c +++ b/test/lladd/check_page.c @@ -83,7 +83,7 @@ static void * multiple_simultaneous_pages ( void * arg_ptr) { readRecord(1, p, rid[k], (byte*)&j); assert((j + 1) == i + k); - slottedDeRalloc(p, rid[k]); + slottedDeRalloc(p, lsn, rid[k]); sched_yield(); } } @@ -123,7 +123,7 @@ static void* worker_thread(void * arg_ptr) { if(! first ) { readRecord(1, p, rid, (byte*)&j); assert((j + 1) == i); - slottedDeRalloc(p, rid); + slottedDeRalloc(p, lsn, rid); sched_yield(); } diff --git a/test/lladd/check_pageOperations.c b/test/lladd/check_pageOperations.c index baeb985..94663a5 100644 --- a/test/lladd/check_pageOperations.c +++ b/test/lladd/check_pageOperations.c @@ -177,7 +177,6 @@ START_TEST(pageOpCheckAllocDealloc) { } END_TEST - Suite * check_suite(void) { Suite *s = suite_create("pageOperations"); /* Begin a new test */