Added test cases for Tprepare(), implemented some redo-only operations, and started to clean up record allocation/deallocation.
Also, numerous bugfixes.
This commit is contained in:
parent
811bc5c710
commit
96e7af92a4
22 changed files with 558 additions and 48 deletions
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
Operation getAlloc();
|
||||
Operation getDealloc();
|
||||
Operation getRealloc();
|
||||
|
||||
/**
|
||||
Allocate a record.
|
||||
|
|
62
lladd/operations/instantSet.h
Normal file
62
lladd/operations/instantSet.h
Normal file
|
@ -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 <lladd/operations.h>
|
||||
|
||||
#define TinstantSet(xid,rid,dat) Tupdate(xid,rid,dat, OPERATION_INSTANT_SET)
|
||||
|
||||
Operation getInstantSet();
|
||||
|
||||
#endif
|
60
lladd/operations/noop.h
Normal file
60
lladd/operations/noop.h
Normal file
|
@ -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 <lladd/operations.h>
|
||||
|
||||
Operation getNoop();
|
||||
|
||||
#endif
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)* /)) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
60
src/lladd/operations/instantSet.c
Normal file
60
src/lladd/operations/instantSet.c
Normal file
|
@ -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 <lladd/operations/instantSet.h>
|
||||
#include <lladd/operations/set.h>
|
||||
#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;
|
||||
}
|
|
@ -63,6 +63,7 @@ int lHtValid(int xid, lladdHash_t *ht) {
|
|||
} else {
|
||||
ret = 1;
|
||||
}
|
||||
releasePage(p);
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
|
|
64
src/lladd/operations/noop.c
Normal file
64
src/lladd/operations/noop.c
Normal file
|
@ -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 <lladd/operations/noop.h>
|
||||
#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;
|
||||
}
|
|
@ -49,7 +49,7 @@ terms specified in this license.
|
|||
#include <lladd/operations/prepare.h>
|
||||
#include "../logger/logWriter.h"
|
||||
#include <malloc.h>
|
||||
|
||||
#include <assert.h>
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -43,6 +43,8 @@ terms specified in this license.
|
|||
#include <assert.h>
|
||||
|
||||
#include <lladd/transactional.h>
|
||||
#include "../../src/lladd/logger/logWriter.h"
|
||||
|
||||
#include <lladd/bufferManager.h>
|
||||
|
||||
#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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -177,7 +177,6 @@ START_TEST(pageOpCheckAllocDealloc) {
|
|||
|
||||
} END_TEST
|
||||
|
||||
|
||||
Suite * check_suite(void) {
|
||||
Suite *s = suite_create("pageOperations");
|
||||
/* Begin a new test */
|
||||
|
|
Loading…
Reference in a new issue