Cleaned out old cruft, such as commented out code, dead data structures, and dead files. sloccount went from $75,000 to $50,000 on src/lladd. ;)

This commit is contained in:
Sears Russell 2004-06-28 22:48:02 +00:00
parent fab0e6cbbd
commit c4fac084b8
22 changed files with 141 additions and 2202 deletions

View file

@ -47,6 +47,20 @@ terms specified in this license.
* It would be nice if the logger API could be simplified by having * It would be nice if the logger API could be simplified by having
* more of its functionality handled this way. * more of its functionality handled this way.
* *
Implementation notes:
- Just a Tupdate, with a log flush as its operationsTable[]
function.
- After recovery, all of the xacts pages will have been 'stolen',
(if recovery flushes dirty pages)
- Recovery function needs to distinguish between actions before and
after the last Tprepare log entry. This is handle by a guard on
the logHandle's iterator, but could be generalized in the future
(to support savepoints, for example) Right now, recovery uses a
guarded iterator, transUndo() does not.
* *
* @ingroup OPERATIONS * @ingroup OPERATIONS
* *
@ -61,11 +75,23 @@ terms specified in this license.
#include <lladd/operations.h> #include <lladd/operations.h>
extern recordid prepare_bogus_rec; extern recordid prepare_bogus_rec;
/**
Prepare transaction for commit. Currently, a transaction may be
prepared multiple times. Once Tprepare() returns, the caller is
guaranteed that the current transaction will resume exactly where
it was when Tprepare() was called.
@param xid Transaction id.
@param rec @todo undocumented.
@param dat @todo Ignored for now?
*/
#define Tprepare(xid, rec, dat) Tupdate(xid, rec, 0, OPERATION_PREPARE) #define Tprepare(xid, rec, dat) Tupdate(xid, rec, 0, OPERATION_PREPARE)
Operation getPrepare(); Operation getPrepare();
/**
Recovery's undo phase uses this logHandle iterator guard to implement Tprepare().
*/
int prepareGuard(LogEntry * e, void * state); int prepareGuard(LogEntry * e, void * state);
void * getPrepareGuardState(); void * getPrepareGuardState();
#endif #endif

View file

@ -83,17 +83,6 @@ typedef struct Page_s {
int queue; int queue;
} Page; } Page;
/**
* tracks changes to blobs
*/
typedef struct {
int xid;
recordid *records;
size_t len;
} touchedBlob_t;
#define DEFAULT_TOUCHED 2
/** /**
* initializes all the important variables needed in all the * initializes all the important variables needed in all the
* functions dealing with pages. * functions dealing with pages.
@ -143,7 +132,6 @@ Page* pageAlloc(int id);
recordid pageSlotRalloc(Page page, recordid rid); recordid pageSlotRalloc(Page page, recordid rid);
int pageTest(); int pageTest();
recordid pageBalloc(Page page, int size, int offset);
int getSlotType(Page p, int slot, int type); int getSlotType(Page p, int slot, int type);
void setSlotType(Page p, int slot, int type); void setSlotType(Page p, int slot, int type);

View file

@ -2,8 +2,6 @@
#include <assert.h> #include <assert.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdlib.h> #include <stdlib.h>
/* stdio */
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -36,13 +34,12 @@ static void readRawRecord(int xid, recordid rid, void * buf, int size) {
static void writeRawRecord(int xid, lsn_t lsn, recordid rid, const void * buf, int size) { static void writeRawRecord(int xid, lsn_t lsn, recordid rid, const void * buf, int size) {
recordid blob_rec_rid = rid; recordid blob_rec_rid = rid;
blob_rec_rid.size = size; blob_rec_rid.size = size;
/* writeRecord(xid, lsn, blob_rec_rid, buf); */
Tset(xid, blob_rec_rid, buf); Tset(xid, blob_rec_rid, buf);
} }
/* moved verbatim from bufferManger.c */ /* moved verbatim from bufferManger.c, then hacked up to use FILE * instead of ints. */
void openBlobStore() { void openBlobStore() {
int blobfd0, blobfd1; int blobfd0, blobfd1;
if( ! (blobf0 = fopen(BLOB0_FILE, "w+"))) { /* file may not exist */ if( ! (blobf0 = fopen(BLOB0_FILE, "w+"))) { /* file may not exist */
@ -114,7 +111,6 @@ recordid allocBlob(int xid, lsn_t lsn, size_t blobSize) {
assert(blobSize > 0); /* Don't support zero length blobs right now... */ assert(blobSize > 0); /* Don't support zero length blobs right now... */
/* First in buffer manager. */ /* First in buffer manager. */
/* recordid rid = ralloc(xid, lsn, sizeof(blob_record_t)); */
recordid rid = Talloc(xid, sizeof(blob_record_t)); recordid rid = Talloc(xid, sizeof(blob_record_t));
@ -143,9 +139,10 @@ recordid allocBlob(int xid, lsn_t lsn, size_t blobSize) {
setSlotType(p, rid.slot, BLOB_SLOT); setSlotType(p, rid.slot, BLOB_SLOT);
rid.size = BLOB_SLOT; rid.size = BLOB_SLOT;
/* writeRecord needs to know to 'do the right thing' here, since
we've changed the size it has recorded for this record. */ /* Tset() needs to know to 'do the right thing' here, since we've
/* @todo What should writeRawRecord do with the lsn? */ changed the size it has recorded for this record, and
writeRawRecord makes sure that that is the case. */
writeRawRecord (xid, lsn, rid, &blob_rec, sizeof(blob_record_t)); writeRawRecord (xid, lsn, rid, &blob_rec, sizeof(blob_record_t));
rid.size = blob_rec.size; rid.size = blob_rec.size;
@ -220,12 +217,11 @@ static void tripleHashRemove(int xid, recordid rid) {
}*/ }*/
void readBlob(int xid, recordid rid, void * buf) { void readBlob(int xid, recordid rid, void * buf) {
/* First, determine if the blob is dirty. */
/* lsn_t * dirty = tripleHashLookup(xid, rid); */
/* We don't care if the blob is dirty, since the record from the
buffer manager will reflect that if it is.. */
blob_record_t rec; blob_record_t rec;
/* int readcount; */
FILE * fd; FILE * fd;
long offset; long offset;
@ -233,14 +229,6 @@ void readBlob(int xid, recordid rid, void * buf) {
readRawRecord(xid, rid, &rec, sizeof(blob_record_t)); readRawRecord(xid, rid, &rec, sizeof(blob_record_t));
/* if(dirty) {
DEBUG("Reading dirty blob.\n");
fd = rec.fd ? blobf0 : blobf1; / * Read the updated version * /
} else {
DEBUG("Reading clean blob.\n");
fd = rec.fd ? blobf1 : blobf0; / * Read the clean version * /
} */
fd = rec.fd ? blobf1 : blobf0; fd = rec.fd ? blobf1 : blobf0;
offset = myFseek(fd, (long int) rec.offset, SEEK_SET); offset = myFseek(fd, (long int) rec.offset, SEEK_SET);
@ -261,9 +249,10 @@ void readBlob(int xid, recordid rid, void * buf) {
current version of the dirty blob, and the lsn field should be current version of the dirty blob, and the lsn field should be
checked to be sure that it increases monotonically. */ checked to be sure that it increases monotonically. */
void writeBlob(int xid, lsn_t lsn, recordid rid, const void * buf) { void writeBlob(int xid, lsn_t lsn, recordid rid, const void * buf) {
/* First, determine if the blob is dirty. */ /* First, determine if the blob is dirty. */
lsn_t * dirty = tripleHashLookup(xid, rid); lsn_t * dirty = tripleHashLookup(xid, rid);
blob_record_t rec; blob_record_t rec;
long offset; long offset;
FILE * fd; FILE * fd;
@ -274,7 +263,7 @@ void writeBlob(int xid, lsn_t lsn, recordid rid, const void * buf) {
if(dirty) { if(dirty) {
assert(lsn > *dirty); assert(lsn > *dirty);
*dirty = lsn; /* Updates value in dirty blobs (works because of pointer aliasing.) */ *dirty = lsn; /* Updates value in triple hash (works because of pointer aliasing.) */
DEBUG("Blob already dirty.\n"); DEBUG("Blob already dirty.\n");
@ -288,12 +277,6 @@ void writeBlob(int xid, lsn_t lsn, recordid rid, const void * buf) {
/* Tset() raw record */ /* Tset() raw record */
writeRawRecord(xid, lsn, rid, &rec, sizeof(blob_record_t)); writeRawRecord(xid, lsn, rid, &rec, sizeof(blob_record_t));
} }
/*
readRawRecord(xid, rid, &rec, sizeof(blob_record_t));
fd = rec.fd ? blobf0 : blobf1; / * Read the slot for the dirty (updated) version. * /
*/
fd = rec.fd ? blobf1 : blobf0; /* rec's fd is up-to-date, so use it directly */ fd = rec.fd ? blobf1 : blobf0; /* rec's fd is up-to-date, so use it directly */
@ -307,83 +290,41 @@ void writeBlob(int xid, lsn_t lsn, recordid rid, const void * buf) {
/* No need to update the raw blob record. */ /* No need to update the raw blob record. */
} }
/** @todo check return values */
/*
void commitBlobs(int xid, lsn_t lsn) {
/ * Because this is a commit, we must update each page atomically.
Therefore, we need to re-group the dirtied blobs by page id, and
then issue one write per page. Since we write flip the bits of each
dirty blob record on the page, we can't get away with incrementally
updating things. * /
pblHashTable_t * rid_buckets = pblHtLookup(dirtyBlobs, &xid, sizeof(int));
pblHashTable_t * this_bucket;
if(!rid_buckets) { return; } / * No blobs for this xid. * /
for(this_bucket = pblHtFirst(rid_buckets); this_bucket; this_bucket = pblHtNext(rid_buckets)) {
blob_record_t buf;
recordid * rid_ptr;
lsn_t * rid_lsn;
int first = 1;
int page_number;
/ * All right, this_bucket contains all of the rids for this page. * /
for(rid_lsn = pblHtFirst(this_bucket); rid_lsn; rid_lsn = pblHtNext(this_bucket)) {
/ ** @todo INTERFACE VIOLATION Can only use bufferManager's
read/write record since we're single threaded, and this calling
sequence cannot possibly call kick page. Really, we sould use
pageReadRecord / pageWriteRecord, and bufferManager should let
us write out the whole page atomically... * /
rid_ptr = pblHtCurrentKey(this_bucket);
if(first) {
page_number = rid_ptr->page;
first = 0;
} else {
assert(page_number == rid_ptr->page);
}
/ ** @todo For now, we assume that overlapping transactions (from
the Tbegin() to Tcommit() call) do not access the same
blob. * /
readRawRecord(xid, *rid_ptr, &buf, sizeof(blob_record_t));
/ * This rid is dirty, so swap the fd pointer. * /
buf.fd = (buf.fd ? 0 : 1);
writeRawRecord(xid, lsn, *rid_ptr, &buf, sizeof(blob_record_t));
pblHtRemove(this_bucket, rid_ptr, sizeof(recordid));
/ * free(rid_ptr); * /
free(rid_lsn);
}
if(!first) {
pblHtRemove(rid_buckets, &page_number, sizeof(int));
} else {
abort(); / * Bucket existed, but was empty?!? * /
}
pblHtDelete(this_bucket);
}
}
*/
void commitBlobs(int xid) { void commitBlobs(int xid) {
abortBlobs(xid); abortBlobs(xid);
} }
/** /**
Just clean up the dirty list for this xid. @todo Check return values. Just clean up the dirty list for this xid. @todo Check return values.
(Functionally equivalent to the old rmTouch() function. Just (Functionally equivalent to the old rmTouch() function. Just
deletes this xid's dirty list.) deletes this xid's dirty list.)
@todo doesn't take lsn_t, since it doesnt write any blobs. Change the api? @todo doesn't take lsn_t, since it doesnt write any blobs. Change
the api?
@todo The tripleHash data structure is overkill here. We only
need two layers of hash tables, but it works, and it would be a
pain to change it, unless we need to touch this file for some
other reason.
*/ */
void abortBlobs(int xid) { void abortBlobs(int xid) {
/*
At first glance, it may seem easier to keep track of which blobs
are dirty only in blobManager, and then propogate those updates to
bufferManager later. It turns out that it's much easier to
propogate the changes to bufferManger, since otherwise, recovery
and undo have to reason about lazy propogation of values to the
bufferManager, and also have to preserve *write* ordering, even
though the writes may be across many transactions, and could be
propogated in the wrong order. If we generate a Tset() (for the
blob record in bufferManager) for each write, things become much
easier.
*/
pblHashTable_t * rid_buckets = pblHtLookup(dirtyBlobs, &xid, sizeof(int)); pblHashTable_t * rid_buckets = pblHtLookup(dirtyBlobs, &xid, sizeof(int));
pblHashTable_t * this_bucket; pblHashTable_t * this_bucket;
if(!rid_buckets) { return; } /* No dirty blobs for this xid.. */ if(!rid_buckets) { return; } /* No dirty blobs for this xid.. */
@ -391,6 +332,7 @@ void abortBlobs(int xid) {
for(this_bucket = pblHtFirst(rid_buckets); this_bucket; this_bucket = pblHtNext(rid_buckets)) { for(this_bucket = pblHtFirst(rid_buckets); this_bucket; this_bucket = pblHtNext(rid_buckets)) {
lsn_t * rid_lsn; lsn_t * rid_lsn;
int page_number; int page_number;
/* All right, this_bucket contains all of the rids for this page. */ /* All right, this_bucket contains all of the rids for this page. */
for(rid_lsn = pblHtFirst(this_bucket); rid_lsn; rid_lsn = pblHtNext(this_bucket)) { for(rid_lsn = pblHtFirst(this_bucket); rid_lsn; rid_lsn = pblHtNext(this_bucket)) {

View file

@ -38,21 +38,19 @@ BEGIN_C_DECLS
/** /**
If blob is resident, return a pointer to it. Otherwise, check if Read the blob from the recordid rid into buf.
it's dirty (it could have been stolen), an retrieve it from the
appropriate blob file.
*/ */
void readBlob(int xid, recordid rid, void * buf); void readBlob(int xid, recordid rid, void * buf);
/** /**
If you write to a blob, call this function to mark it dirty. Write the contents of buf to the blob in recordid rid.
*/ */
void writeBlob(int xid, lsn_t lsn, recordid rid, const void * buf); void writeBlob(int xid, lsn_t lsn, recordid rid, const void * buf);
/** /**
Atomically (with respect to recovery) make the dirty version of the Atomicly (with respect to recovery) make the dirty version of the
blob the primary copy and mark it not-dirty. blob the primary copy and mark it not-dirty.
*/ */
@ -70,6 +68,12 @@ typedef struct {
unsigned fd : 1; unsigned fd : 1;
} blob_record_t; } blob_record_t;
/**
Allocate a blob of size blobSize.
@todo This function does not atomically allocate space in the blob
file.
*/
recordid allocBlob(int xid, lsn_t lsn, size_t blobSize); recordid allocBlob(int xid, lsn_t lsn, size_t blobSize);
void openBlobStore(); void openBlobStore();
void closeBlobStore(); void closeBlobStore();

View file

@ -68,8 +68,6 @@ static unsigned int bufferSize = 1; /* < MAX_BUFFER_SIZE */
static Page *repHead, *repMiddle, *repTail; /* replacement policy */ static Page *repHead, *repMiddle, *repTail; /* replacement policy */
static int stable = -1; static int stable = -1;
/*int blobfd0 = -1;
int blobfd1 = -1;*/
static void pageMap(Page *ret) { static void pageMap(Page *ret) {
@ -95,12 +93,8 @@ int bufInit() {
bufferSize = 1; bufferSize = 1;
stable = -1; stable = -1;
/* blobfd0 = -1;
blobfd1 = -1; */
/* Create STORE_FILE, if necessary, then open it read/write
/* Create STORE_FILE, BLOB0_FILE, BLOB1_FILE if necessary,
then open it read/write
If we're creating it, then put one all-zero record at the beginning of it. If we're creating it, then put one all-zero record at the beginning of it.
(Need to have at least one record in the PAGE file?) (Need to have at least one record in the PAGE file?)
@ -141,27 +135,6 @@ int bufInit() {
openBlobStore(); openBlobStore();
/* if( (blobfd0 = open(BLOB0_FILE, O_RDWR, 0)) == -1 ) { / * file may not exist * /
if( (blobfd0 = creat(BLOB0_FILE, 0666)) == -1 ) { / * cannot even create it * /
printf("ERROR: %i on %s line %d", errno, __FILE__, __LINE__);
exit(errno);
}
if( close(blobfd0) || ((blobfd0 = open(BLOB0_FILE, O_RDWR, 0)) == -1) ) { / * need to reopen with read perms * /
printf("ERROR: %i on %s line %d", errno, __FILE__, __LINE__);
exit(errno);
}
}
if( (blobfd1 = open(BLOB1_FILE, O_RDWR, 0)) == -1 ) { / * file may not exist * /
if( (blobfd1 = creat(BLOB1_FILE, 0666)) == -1 ) { / * cannot even create it * /
printf("ERROR: %i on %s line %d", errno, __FILE__, __LINE__);
exit(errno);
}
if( close(blobfd1) || ((blobfd1 = open(BLOB1_FILE, O_RDWR, 0)) == -1) ) { / * need to reopen with read perms * /
printf("ERROR: %i on %s line %d", errno, __FILE__, __LINE__);
exit(errno);
}
} */
return 0; return 0;
} }
@ -219,8 +192,14 @@ static void qRemove(Page *ret) {
assert(ret != repHead); assert(ret != repHead);
} }
/**
LRU-2S from Markatos "On Caching Searching Engine Results"
@todo Should this be its own file?
*/
static Page *kickPage(int pageid) { static Page *kickPage(int pageid) {
/* LRU-2S from Markatos "On Caching Searching Engine Results" */
Page *ret = repTail; Page *ret = repTail;
assert( bufferSize == MAX_BUFFER_SIZE ); assert( bufferSize == MAX_BUFFER_SIZE );
@ -328,38 +307,22 @@ Page loadPage (int pageid) {
return *loadPagePtr(pageid); return *loadPagePtr(pageid);
} }
/*int lastGoodPageKey = 0; */
Page * lastRallocPage = 0; Page * lastRallocPage = 0;
recordid ralloc(int xid, lsn_t lsn, size_t size) { recordid ralloc(int xid, lsn_t lsn, size_t size) {
static unsigned int lastFreepage = 0; static unsigned int lastFreepage = 0;
recordid ret; recordid ret;
Page p; Page p;
/* int blobSize = 0; */
if (size >= BLOB_THRESHOLD_SIZE) { /* TODO combine this with if below */ if (size >= BLOB_THRESHOLD_SIZE) { /* TODO combine this with if below */
ret = allocBlob(xid, lsn, size); ret = allocBlob(xid, lsn, size);
/* blobSize = size;
size = BLOB_REC_SIZE; */
} else { } else {
while(freespace(p = loadPage(lastFreepage)) < size ) { lastFreepage++; } while(freespace(p = loadPage(lastFreepage)) < size ) { lastFreepage++; }
/* if (blobSize >= BLOB_THRESHOLD_SIZE) {
int fileSize = (int) lseek(blobfd1, 0 , SEEK_END);
/ * fstat(blobfd1, &sb);
fileSize = (int) sb.st_size; * /
lseek(blobfd0, fileSize+blobSize-1, SEEK_SET);
write(blobfd0, "", 1);
lseek(blobfd1, fileSize+blobSize-1, SEEK_SET);
write(blobfd1, "", 1);
return pageBalloc(p, blobSize, fileSize);
} else { */
ret = pageRalloc(p, size); ret = pageRalloc(p, size);
/* } */
} }
DEBUG("alloced rid = {%d, %d, %d}\n", ret.page, ret.slot, ret.size); DEBUG("alloced rid = {%d, %d, %d}\n", ret.page, ret.slot, ret.size);
return ret; return ret;
@ -441,7 +404,6 @@ void bufDeinit() {
printf("ERROR: flushPage on %s line %d", __FILE__, __LINE__); printf("ERROR: flushPage on %s line %d", __FILE__, __LINE__);
exit(ret); exit(ret);
} }
/* free(p); */
} }
pblHtDelete(activePages); pblHtDelete(activePages);
@ -450,8 +412,6 @@ void bufDeinit() {
exit(errno); exit(errno);
} }
/* close(blobfd0);
close(blobfd1); */
closeBlobStore(); closeBlobStore();
return; return;
@ -462,12 +422,8 @@ void bufDeinit() {
*/ */
void simulateBufferManagerCrash() { void simulateBufferManagerCrash() {
closeBlobStore(); closeBlobStore();
/*close(blobfd0);
close(blobfd1);*/
close(stable); close(stable);
/* blobfd0 = -1;
blobfd1 = -1; */
stable = -1; stable = -1;
} }

View file

@ -68,7 +68,6 @@ const byte * getUpdateArgs(const LogEntry * ret) {
const byte * getUpdatePreImage(const LogEntry * ret) { const byte * getUpdatePreImage(const LogEntry * ret) {
assert(ret->type == UPDATELOG); assert(ret->type == UPDATELOG);
if(operationsTable[ret->contents.update.funcID].undo != NO_INVERSE) { if(operationsTable[ret->contents.update.funcID].undo != NO_INVERSE) {
/* if(ret->contents.update.invertible) { */
return NULL; return NULL;
} else { } else {
return ((byte*)ret) + sizeof(struct __raw_log_entry) + sizeof(UpdateLogEntry) + ret->contents.update.argSize; return ((byte*)ret) + sizeof(struct __raw_log_entry) + sizeof(UpdateLogEntry) + ret->contents.update.argSize;
@ -86,7 +85,6 @@ LogEntry * allocUpdateLogEntry(lsn_t prevLSN, int xid,
ret->xid = xid; ret->xid = xid;
ret->type = UPDATELOG; ret->type = UPDATELOG;
ret->contents.update.funcID = funcID; ret->contents.update.funcID = funcID;
/* ret->contents.update.invertible = invertible; */
ret->contents.update.rid = rid; ret->contents.update.rid = rid;
ret->contents.update.argSize = argSize; ret->contents.update.argSize = argSize;

View file

@ -188,16 +188,3 @@ LogEntry * readLSNEntry(lsn_t LSN) {
return ret; return ret;
} }
/*lsn_t nextLSN() {
lsn_t orig_pos = ftell(log);
lsn_t ret;
fseek(log, 0, SEEK_END);
ret = ftell(log);
fseek(log, orig_pos, SEEK_SET);
return ret;
}*/

View file

@ -1,142 +0,0 @@
/*---
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
* $Id$
*
* C implementation of logger.h
*
* @deprecated
* @see logger2.c
******************/
#include <stdlib.h>
#include <lladd/transactional.h>
#include <lladd/logger.h>
#include "logparser.h"
#include "logstreamer.h"
#include <lladd/bufferManager.h>
static long LogCommonWriterNoExtra(long prevLSN, int xid, int type); /*defined later*/
long LogTransBegin(Transaction t) {
return -1;
}
/* jason please review and delete comment when done
* to recover: pageRalloc(loadPage(rid.page), rid.size)
*/
long LogTransAlloc(long prevLSN, int xid, recordid rid) {
char *extra;
int sizeOfExtra = allocPartsToString(&extra, rid);
return writeNewLog(prevLSN, xid, XALLOC, extra, sizeOfExtra);
}
long LogTransCommit(long prevLSN, int xid) {
long newLSN = LogCommonWriterNoExtra(prevLSN, xid, XCOMMIT);
flushLog();
return newLSN;
}
long LogTransAbort(long prevLSN, int xid) {
return LogCommonWriterNoExtra(prevLSN, xid, XABORT);
}
long LogUpdate (long prevLSN, int xid, recordid rid, Operation op, const void *args) {
char *extra;
/* size_t sizeOfData, sizeOfExtra; */
int sizeOfData, sizeOfExtra;
void *preImage = 0;
int invertible;
if (op.sizeofData==SIZEOF_RECORD) {
/*then get the size of this record */
sizeOfData = rid.size;
}
else sizeOfData = op.sizeofData;
/*heck to see if op is invertible */
if (op.undo==NO_INVERSE) {
invertible = 0;
preImage = (void *)malloc(rid.size);
readRecord(xid, rid, preImage);
}
else invertible = 1;
/*will put all of the parts special to an update log record into extra */
sizeOfExtra = updatePartsToString(&extra, op.id, rid, args, sizeOfData, invertible, preImage);
/*extra has been malloced, but writeNewLog will free it*/
if(preImage) {
free(preImage);
}
return writeNewLog(prevLSN, xid, UPDATELOG, extra, sizeOfExtra);
}
long LogCLR (long prevLSN, int xid, long ulLSN, recordid ulRID, long ulPrevLSN) {
#define CLRSIZEOFEXTRA 20
char *extra;
CLRPartsToString(&extra, ulLSN, ulRID, ulPrevLSN);
/*extra has been malloced, but writeNewLog will free it*/
return writeNewLog(prevLSN, xid, CLRLOG, extra, CLRSIZEOFEXTRA);
}
long LogEnd (long prevLSN, int xid) {
return LogCommonWriterNoExtra(prevLSN, xid, XEND);
}
/*
LogCommonWriterNoExtra writes the log record in the log tail when there is no extra data
being put in the log record -- a special case, and therefore just calls the more generalized LogCommongWriter
*/
static long LogCommonWriterNoExtra(long prevLSN, int xid, int type) {
return writeNewLog(prevLSN, xid, type, 0, 0);
}
void logInit() {
startLogStream();
}
void logDeinit() {
closeLogStream();
/** FOR NOW, don't delete the log stream at the end, even if all transactions
* are committed because we want to debug
*/
/*deleteLogStream();*/
}

View file

@ -112,7 +112,7 @@ LogEntry * LogUpdate(TransactionLog * l, recordid rid, int operation, const byte
return e; return e;
} }
lsn_t LogCLR(/*TransactionLog * l,*/ LogEntry * undone) { lsn_t LogCLR(LogEntry * undone) {
lsn_t ret; lsn_t ret;
LogEntry * e = allocCLRLogEntry(-1, undone->xid, undone->LSN, undone->contents.update.rid, undone->prevLSN); LogEntry * e = allocCLRLogEntry(-1, undone->xid, undone->LSN, undone->contents.update.rid, undone->prevLSN);
writeLogEntry(e); writeLogEntry(e);

View file

@ -1,316 +0,0 @@
/*---
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
* $Id$
*
* corresponding C file of the log parser
*
* @deprecated
* @see logEntry.c
* *************/
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "logparser.h"
#include "logstreamer.h"
static CommonLog assembleLog (long prevLSN, int xid, int type, void *extra, int extraLength);
static void writeCommonLog (CommonLog comLog);
static UpdateLog assembleUpdateLog (int funcID, recordid rid, const void *args, int arglen, int invertible, const void *preimage);
static CLRLog assembleCLRLog (long thisUpdateLSN, recordid rid, long undoNextLSN);
static int updateLogToString (char **s, UpdateLog upLog);
static int CLRLogToString (char **s, CLRLog clrlog);
long writeNewLog (long prevLSN, int xid, int type, char *extra, int extraLength) {
long thisLSN = writeStreamPos();
CommonLog tmpLog;
/* printf("LogType:%d\n", type); */
tmpLog = assembleLog(prevLSN, xid, type, extra, extraLength);
writeCommonLog (tmpLog);
if (tmpLog.extraData !=0)
free(tmpLog.extraData ); /*free up any malloc'ed string if it is there*/
if (extra != 0)
free(extra); /*free up extra space that might have been malloced previously*/
return thisLSN;
}
int updatePartsToString (char **buf, int funcID, recordid rid, const char *args, int arglen, int invertible, const void *preImage) {
UpdateLog ul;
int sizeOfString;
ul = assembleUpdateLog(funcID, rid, args, arglen, invertible, preImage);
sizeOfString = updateLogToString(buf, ul);
/* if (ul.args!=0)
free(ul.args); //deallocate the update log's arg string that was malloc'ed in assembleUpdateLog (assembleupdate log no longer mallocs. )
if (!invertible)
free(ul.preImage); */
return sizeOfString;
}
int CLRPartsToString (char **txt, long thisUpdateLSN, recordid rid, long undoNextLSN) {
return CLRLogToString(txt, assembleCLRLog(thisUpdateLSN, rid, undoNextLSN));
}
CommonLog readNextCommonLog() {
return readCommonLogFromLSN(readPos());
}
CommonLog readCommonLogFromLSN(long LSN) {
byte * buf;/* char *buf;*/
long junk;
int bufPos, numObjs, extraSize;
CommonLog commonStuff;
commonStuff.LSN = LSN;
commonStuff.type = 0;
/*seekandreadlog will allocate space for buffer */
junk = seekAndReadLog(LSN, &buf);
if (junk==0) {
commonStuff.valid=0;
free(buf);
return commonStuff;
}
numObjs = sscanf ((char*)buf, "%ld %d %d", &(commonStuff.prevLSN), &(commonStuff.xid), &(commonStuff.type));
if (numObjs!=3) {
commonStuff.valid = 0;
free(buf);
return commonStuff; /*if we don't have the 3 basic ingredients, invalid log entry or at end of file, etc*/
}
commonStuff.valid = 1;
/*try to read extra data, if possible (will first have a size in bytes of the future data)
check if there is data beyond the 3 fields for optional data, and if so note where to put the data in buf*/
if (sscanf((char*)buf, "%ld %*d %*d %d %n", &junk, &extraSize, &bufPos)==2) { /*note: pos does not increase the object count of sscanf*/
/*then there is an extra string*/
commonStuff.extraData = (void*)malloc(extraSize);
commonStuff.extraDataSize = extraSize;
memcpy(commonStuff.extraData, buf+bufPos, extraSize);
/*printf ("reading extradata=%d %d; extrasize=%d, bufpos=%d\n", *(int *)commonStuff.extraData, *(int *)(commonStuff.extraData+4), extraSize, bufPos);*/
}
else {
commonStuff.extraData = NULL;
commonStuff.extraDataSize = 0;
}
free(buf);
return commonStuff;
}
UpdateLog updateStringToParts(byte *txt) {
UpdateLog thisUpdate;
int txtPos;
long int tmp_size;
/*read in the fixed size parts and get the position of where the data begins*/
sscanf ((char*)txt, "%d %d %d %ld %d %d%n", &(thisUpdate.funcID), &(thisUpdate.rid.page),
&(thisUpdate.rid.slot), &tmp_size,/*(thisUpdate.rid.size),*/ &(thisUpdate.invertible), &thisUpdate.argSize, &txtPos);
thisUpdate.rid.size = (size_t) tmp_size;
txtPos++; /*there is an additional space between the argSize and the arg data*/
thisUpdate.args = (void*)malloc(thisUpdate.argSize);
memcpy((byte*)thisUpdate.args, txt+txtPos, thisUpdate.argSize);
txtPos += 1+thisUpdate.argSize;
if (!thisUpdate.invertible) {
thisUpdate.preImage = (void*)malloc(thisUpdate.rid.size);
/* Remove the const qualifier from preImage so that we can initialize the malloced memory. */
memcpy((void*)thisUpdate.preImage, txt+txtPos, thisUpdate.rid.size);
}
return thisUpdate;
}
CLRLog CLRStringToParts (void *txt) {
CLRLog clrlog;
long int size_tmp;
sscanf(txt, "%ld %d %d %ld %ld", &(clrlog.thisUpdateLSN), &(clrlog.rid.page), &(clrlog.rid.slot), &(size_tmp), &(clrlog.undoNextLSN));
clrlog.rid.size = (size_t) size_tmp;
return clrlog;
}
/* TODO: Fix string buffer size!!! */
int allocPartsToString (char **txt, recordid rid) {
return asprintf(txt, "%d %d %ld", rid.page, rid.slot, (long int)rid.size);
/* *txt = malloc(2*sizeof(int)+sizeof(long)+200);
sprintf (*txt, "%d %d %ld", rid.page, rid.slot, rid.size); */
/*memcpy(txt, &rid, sizeof(recordid));
printf ("writing rid=%d,%d,%ld\n", rid.page, rid.slot, rid.size);*/
/*return sizeof(recordid);*/
}
recordid allocStringToRID (void *txt) {
recordid tmp;
long int tmp2;
sscanf(txt, "%d %d %ld", &tmp.page, &tmp.slot, &tmp2);
tmp.size = (size_t)tmp2;
/*memcpy(&tmp, txt, sizeof(recordid));
printf ("reading rid=%d,%d,%ld\n", tmp.page, tmp.slot, tmp.size);*/
return tmp;
}
/************ PRIVATE WRITING-RELATED FUNCTIONS ********************/
/*
put the pieces of a complete (common) log into the structure
*/
static CommonLog assembleLog (long prevLSN, int xid, int type, void *extra, int extraLength) {
CommonLog tmp;
tmp.prevLSN = prevLSN;
tmp.xid = xid;
tmp.type = type;
tmp.valid = 1;
tmp.extraDataSize = extraLength;
if (extraLength==0)
tmp.extraData = NULL;
else {
tmp.extraData = (void*)malloc(extraLength);
memcpy(tmp.extraData, extra, extraLength);
}
return tmp;
}
/*
marshal an common log into the log file
*/
static void writeCommonLog (CommonLog comLog) {
char *buf;
int bytesWritten;
if (comLog.extraDataSize==0) {
/*TODO: Fix buffer size! (Throughout file) */
/* buf = malloc(2*sizeof(int)+sizeof(long)+200); */
bytesWritten = asprintf (&buf, "%ld %d %d", comLog.prevLSN, comLog.xid, comLog.type);
}
else {
char * buf2;
/* buf = malloc(3*sizeof(int)+sizeof(long)+200+4+comLog.extraDataSize); */
/*first print all the ordinary components plus a space, then size of extra; note the last byte put into sprintf*/
bytesWritten = asprintf (&buf, "%ld %d %d %d ", comLog.prevLSN, comLog.xid, comLog.type, comLog.extraDataSize);
buf2 = malloc(bytesWritten + comLog.extraDataSize);
memcpy (buf2, buf, bytesWritten);
free(buf);
buf = buf2;
/*directly write the data into the buffer after the rest of the stuff*/
memcpy (buf+bytesWritten, comLog.extraData, comLog.extraDataSize);
/*printf("writing extra=%d %d\n", *(int *)comLog.extraData, *(int *)(comLog.extraData+4));*/
}
writeLog(buf, bytesWritten+comLog.extraDataSize);
free(buf);
}
/*
Given all the components of an update log, will produce an update log
Returns an UpdateLog
NOTE: mallocates the output log's args string, so must be freed after use (Not true any more.)
*/
static UpdateLog assembleUpdateLog (int funcID, recordid rid, const void *args, int arglen, int invertible, const void *preimage) {
UpdateLog tmpLog;
tmpLog.funcID = funcID;
tmpLog.rid = rid;
/* tmpLog.args = (void*)malloc(arglen); */
tmpLog.argSize = arglen;
tmpLog.invertible = invertible;
/* memcpy (tmpLog.args, args, arglen); */
tmpLog.args = args;
if (!invertible) {
/*Don't need this? Just set the pointer... */
/* tmpLog.preImage = (void*)malloc(rid.size);
memcpy(tmpLog.preImage, preimage, rid.size); */
tmpLog.preImage = preimage;
} else {
tmpLog.preImage = 0;
}
return tmpLog;
}
static CLRLog assembleCLRLog (long thisUpdateLSN, recordid rid, long undoNextLSN) {
CLRLog tmpLog;
tmpLog.thisUpdateLSN = thisUpdateLSN;
tmpLog.rid = rid;
tmpLog.undoNextLSN = undoNextLSN;
return tmpLog;
}
/*
marshal an update log into a string (assume the string space has been allocated)
returns number of bytes written to the string
*/
static int updateLogToString (char **s, UpdateLog upLog) {
int bytesWritten;
/* int maxDigitsForInt = 25; //32767 is 5 digits, plus a negative
int maxDigitsForLong = 25;
int estSize = 5*maxDigitsForInt+maxDigitsForLong+6+upLog.argSize;*/
char *tmp;
/* if (!upLog.invertible)
estSize+=1+upLog.rid.size; */
bytesWritten = asprintf (&tmp, "%d %d %d %ld %d %d ", upLog.funcID, upLog.rid.page, upLog.rid.slot, (long int)upLog.rid.size, upLog.invertible, upLog.argSize);
*s = malloc(bytesWritten + upLog.argSize);
memcpy(*s, tmp, bytesWritten);
free (tmp);
memcpy(*s+bytesWritten, upLog.args, upLog.argSize);
bytesWritten+=upLog.argSize;
if (!upLog.invertible) {
tmp = *s;
*s = malloc(bytesWritten+1 +upLog.rid.size);
memcpy(*s, tmp, bytesWritten);
free (tmp);
sprintf (*s+bytesWritten, " ");
memcpy(*s+bytesWritten+1, upLog.preImage, upLog.rid.size);
bytesWritten += 1 + upLog.rid.size;
}
return bytesWritten;
}
static int CLRLogToString (char **s, CLRLog clrlog) {
/* int estSize = 3*sizeof(long)+2*sizeof(int)+400; */
int bytesWritten;
/* *s = malloc(estSize); */
bytesWritten = asprintf (s, "%ld %d %d %ld %ld ", clrlog.thisUpdateLSN, clrlog.rid.page, clrlog.rid.slot, (long int)clrlog.rid.size, clrlog.undoNextLSN);
/* if (bytesWritten!=estSize) {
//error!
}*/
return bytesWritten;
}

View file

@ -1,206 +0,0 @@
/*---
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
*
* logparser implements the specific formats of the log entrys to be read and
* written in the log file.
*
* All log entries have some fields in common (always) - a previous LSN, a
* transaction id, a log type, and any extra text specific to the type of entry.
* The extra text may be NULL, in which case there is no extra text! If there is
* extra text, additional public functions are written to put together and take
* apart the string into its object.
*
* This has been entirely rewritten. Don't use it.
*
* @deprecated @see logEntry.h
*
* Proposed api:
All of these return a pointer to a single malloced region that should be freed.
allocCommonLogEntry(LSN, prevLSN, xid, type);
allocUpdateLogEntry(LSN, prevLSN, xid, type=UPDATE, funcID, rid, args, argSize, preImage);
allocCLRLogEntry (LSN, prevLSN, xid, type=CLR, thisUpdateLSN, rid, undoNextLSN);
struct {
thisUpdateLSN;
rid;
undoNextLSN;
} CLRLogEntry;
struct {
funcID;
rid;
argSize;
/ * Implicit members:
args; @ ((byte*)ule) + sizeof(UpdateLogEntry)
preImage; @ ((byte*)ule) + sizeof(UpdateLogEntry) + ule.argSize * /
} UpdateLogEntry;
struct {
LSN;
prevLSN;
xid;
type;
union {
UpdateLogEntry update;
CLRLogEntry clr;
} contents;
} LogEntry;
sizeofLogEntry(LogEntry *);
size_t getUpdateArgs(LogEntry *);
size_t getUpdatePreImage(LogEntry *);
*
* $Id$
**/
#ifndef __LOGPARSER_H__
#define __LOGPARSER_H__
#include <lladd/page.h>
#include <lladd/constants.h>
/* max the log line can be is 2 pages (set redo and undo data possibly) plus
* some more log stuff */
/*#define maxLogLineLength 2*PAGE_SIZE + 100 */
/*
fields common to all log entries
extra could be null, indicating no extra data needed
*/
typedef struct {
/**LSN field is ignored when writing to log, since it is determined
by the writer */
long LSN;
long prevLSN;
int xid;
int type;
void *extraData;
int extraDataSize;
int valid;
} CommonLog;
/**
Update Log components (that are normally stored in the 'extra' field of a common log
The preimage is used for undos of operations with no inverses, and
the args field is used for the redo process, and inverse functions.
*/
typedef struct {
/**what function it is*/
int funcID;
/**page and slot number*/
recordid rid;
/**binary data of the function arguments*/
const byte *args;
int argSize;
int invertible;
/**if funcID is not invertible will store a preImage with size=rid.size*/
const byte *preImage;
} UpdateLog;
typedef struct {
/* UpdateLog ul; //has everything in an update log */
long thisUpdateLSN;
recordid rid;
long undoNextLSN;
} CLRLog;
/********* PUBLIC WRITING-RELATED FUNCTIONS **************/
/**
Given all the necessary components of a log entry, assemble it and then write it to the log file
return the LSN of this new log entry
*/
long writeNewLog (long prevLSN, int xid, int type, char *extra, int extraLength);
/**
put all of the components of the extra part of an update log into a buffer
returns the length of the string written to buf
@ todo Logparser shouldn't write to char**
*/
int updatePartsToString (char **buf, int funcID, recordid rid, const char *args, int arglen, int invertible, const void *preImage);
/**
Takes in a buffer and a record id and copies the recordid into the buffer
*/
int allocPartsToString (char **txt, recordid rid);
/**
*/
int CLRPartsToString (char **txt, long thisUpdateLSN, recordid rid, long undoNextLSN);
/********* PUBLIC READING-RELATED FUNCTIONS **************/
/**
parse a log line that only parses entries common to all log records into its structure. Can specify an LSN
NOTE: the extra part of CommonLog might have a malloc'ed string in it; should be freed after use
*/
CommonLog readNextCommonLog();
CommonLog readCommonLogFromLSN(long LSN);
CLRLog readCLRLogFromLSN(long LSN);
/**
parse the extra part of an update log record into an UpdateLog structure
NOTE: the args part of the UpdateLog has a malloc'ed string in it; should be freed after use
*/
UpdateLog updateStringToParts(byte *txt);
CLRLog CLRStringToParts (void *txt);
/**
Read a buffer and parse it into a recordid
*/
recordid allocStringToRID (void *txt);
#endif

View file

@ -1,148 +0,0 @@
/*---
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$
the C implementation of logstreamer.h
******************/
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <unistd.h>
#include <lladd/constants.h>
#include "logstreamer.h"
static FILE *log;
int startLogStream() {
log = fopen(LOG_FILE, "a+");
if (log==NULL) {
/*there was an error opening this file */
return FILE_WRITE_OPEN_ERROR;
}
/*if file is empty, write a null at the 0th character */
if (streamPos()==0)
fputs("0", log);
/*start reading at the 1st character*/
fseek(log, 1, SEEK_SET);
return 0; /*otherwise return 0 for no errors*/
}
int writeLog(void *s, int length) {
/* int i; */
fprintf(log, "%d ", length); /*print out the size of this log entry (not including this item and the \n */
if(1 != fwrite(s, length, 1, log)) {
/* for( i = 0; i < length; i++ ) {
if(fputc(*(char*)(s+i), log) == EOF) { //write the string to the log tail*/
perror("logstreamer: fputc");
assert(0);
/* } */
}
fprintf (log, "\n"); /*then write a carriage return just for our viewing pleasure*/
return 0; /*otherwise, no errors*/
}
void flushLog() {
fflush(log);
/* fsync(fileno(log)); */
fdatasync(fileno(log));
}
void closeLogStream() {
fclose(log);
}
void deleteLogStream() {
remove(LOG_FILE);
}
long streamPos() {
return ftell(log);
}
/* Assumes we're already @ EOF. */
long writeStreamPos() {
/* long cur = ftell(log);
fseek(log, 0, SEEK_END);
assert(cur == ftell(log));*/
return ftell(log);
/* long curPos = streamPos();
long returnVal;
fseek(log, 0, SEEK_END);
returnVal = ftell(log);
fseek(log, curPos, SEEK_SET);
return returnVal;*/
}
int readLog(byte **buffer) {
int length, i;
*buffer = 0;
if (feof(log)) return 0;
fscanf(log, "%d ", &length);
if (feof(log)) return 0;
/*get length characters from the log at this point and put them
into the buffer */
*buffer = malloc(length+5); /*5 extra just to be safe*/
for (i=0; i<length; i++)
*(char*)(*buffer+i) = fgetc(log);
/*experiment: null terminate the buffer to avoid read leaks over the memory just in case */
*(char*)(*buffer+i) = '\0';
/*then read in the newline that was put in to be nice */
fgetc(log);
return length;
}
int seekAndReadLog(long pos, byte **buffer) {
fseek(log, pos, 0); /*seek to pos positions from the beginning of the file*/
return readLog(buffer);
}
void seekInLog(long pos) {
fseek(log, pos, 0);
}
long readPos () {
return ftell(log);
}

View file

@ -1,135 +0,0 @@
/*---
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
*
* $Id$
*
* logstreamer is the implementation of writing the log tail
* It must be bufferred -- in that when something is written to the log tail it
* is not immediately written to disk, but rather just ot memory. But
* logstreamer must be able to force flush to disk, which will be done when a
* commit log entry is written to the log tail
*
* Note: using the stdio FILEs for this, and by default it is "fully" buffered.
* The log tail may be flushed to disk without an explicit call to fflush (when
* the program terminates, the file closes), but this is acceptable because it
* never hurts to have more flushes to disk, as long as it doesn't hurt
* performance.
*
* @deprecated @see logWriter.h logHandle.h
*
* *************/
#ifndef __LOGSTREAMER_H__
#define __LOGSTREAMER_H__
#include <lladd/constants.h>
#include <lladd/common.h>
/*
start a new log stream by opening the log file for reading
returns 0 on success, or an error code define above
*/
int startLogStream();
/*
passed an address with data in it, writes it out to the log tail (not yet
flushed)
returns 0 on success, or an error code defined above
*/
int writeLog(void *s, int length);
/*
flush the entire log (tail) that is currently in memory to disk
*/
void flushLog();
/*
Close the log stream
*/
void closeLogStream();
/*
Get the current position of the stream (in terms of bytes)
*/
long getFilePos();
/*
Actually deletes the log file that may have been written to disk! Danger!!
Only use after calling closeLogStream AND you are sure there are no active (or
future active) transactions!
*/
void deleteLogStream();
/*
* Returns the current position of the stream no matter where it is
*/
long streamPos();
/*
* Returns the position of the stream if it were to read.
*/
long writeStreamPos();
/*
* readLog reads a line from the log puts it in a string
*
* returns the number of bytes read and put into buffer
* */
int readLog(byte **buffer);
/*
* seek to a position in the log file and read it into the buffer
*
* returns the number of bytes read and put into buffer
* */
int seekAndReadLog(long pos, byte **buffer);
/*
* tell the current position in the log file
* */
long readPos ();
void seekInLog(long pos);
#endif

View file

@ -14,7 +14,8 @@
@todo Currently, if the system crashes during an alloc, (before the @todo Currently, if the system crashes during an alloc, (before the
log is flushed, but after bufferManager returns a rid), then 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 space alloced during the crash is leaked. This doesn't seem to be
too big of a deal, but it should be fixed someday. too big of a deal, but it should be fixed someday. A more serious
problem results from crashes during blob allocation.
*/ */
@ -59,6 +60,10 @@ recordid Talloc(int xid, size_t size) {
problem involving blob allocation, which is more serious, as it may problem involving blob allocation, which is more serious, as it may
result in double allocation...) result in double allocation...)
@todo If this should be the only call to ralloc in lladd, we may consider
removing the lsn parameter someday. (Is there a good reason to
provide users with direct access to ralloc()?)
*/ */
rid = ralloc(xid, -1, size); rid = ralloc(xid, -1, size);

View file

@ -47,7 +47,6 @@ terms specified in this license.
**********************************************/ **********************************************/
#include <lladd/operations/prepare.h> #include <lladd/operations/prepare.h>
/*#include "../logger/logstreamer.h"*/
#include <lladd/logger/logWriter.h> #include <lladd/logger/logWriter.h>
#include <malloc.h> #include <malloc.h>
@ -57,37 +56,17 @@ static int operate(int xid, recordid rid, const void *dat) {
syncLog(); syncLog();
return 0; return 0;
} }
/*static int no_op(int xid, recordid rid, const void *dat) {
return 0;
}*/
/**
Tprepare notes:
- Just a Tupdate, with a log flush as its operationsTable[]
function. (done)
- After recovery, all of the xacts pages will have been 'stolen',
(if recovery flushes dirty pages) (done)
- Recovery function needs to distinguish between actions before and
after the last Tprepare log entry.
- The switch in recovUndo needs to treat Tprepares as follows:
- If we're really doing recovery, don't push the prevLSN onto
transRecLSN's. Instead, add it to the active transaction table
in transactional.c
- If not, do nothing, but push the prevLSN onto transRecLSN's
*/
Operation getPrepare() { Operation getPrepare() {
Operation o = { Operation o = {
OPERATION_PREPARE, /* id */ OPERATION_PREPARE, /* id */
0, /* No extra data. */ 0, /* No extra data. */
OPERATION_PREPARE, /*&no_op,*/ /* Otherwise, it will need to store a pre-image of something... */ 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. */
&operate /* Function */ &operate /* Function */
}; };
return o; return o;

View file

@ -135,10 +135,6 @@ void pageDeRalloc(Page page, recordid rid);
void pageCompact(Page page); void pageCompact(Page page);
touchedBlob_t *touched;
size_t touchedLen;
/** /**
* pageInit() initializes all the important variables needed in * pageInit() initializes all the important variables needed in
* all the functions dealing with pages. * all the functions dealing with pages.
@ -173,90 +169,8 @@ void pageInit() {
MASK_0000FFFF = (1 << (2*BITS_PER_BYTE)) - 1; MASK_0000FFFF = (1 << (2*BITS_PER_BYTE)) - 1;
MASK_FFFF0000 = ~MASK_0000FFFF; MASK_FFFF0000 = ~MASK_0000FFFF;
touchedLen = DEFAULT_TOUCHED;
touched = calloc(touchedLen, sizeof(touchedBlob_t));
/* if( (blob_0_fd = open(BLOB0_FILE, O_RDWR, 0)) == -1 ) {
perror("page.c:opening blob file 0");
exit(-1);
}
if( (blob_1_fd = open(BLOB1_FILE, O_RDWR, 0)) == -1 ) {
perror("page.c:opening blob file 1");
exit(-1);
} */
} }
static void rehashTouch() {
int i;
touchedBlob_t *touched_old = touched;
touchedLen *= 2;
touched = calloc(touchedLen, sizeof(touchedBlob_t));
assert(touched);
for( i = 0; i < touchedLen/2; i++ ) {
if( touched_old[i].records ) {
touched[touched_old[i].xid%touchedLen] = touched_old[i];
}
}
free(touched_old);
}
static int touchBlob(int xid, recordid rid) {
touchedBlob_t *t = &touched[xid%touchedLen];
if( t->records ) {
if( t->xid == xid ) {
recordid ret = t->records[(rid.page+rid.slot)%t->len];
if( ret.size ) {
if( ret.page == rid.page && ret.slot == rid.slot ) {
return 1;
} else { /* there's another entry for this space */
int i;
recordid *old = t->records;
t->len *= 2;
t->records = calloc(t->len, sizeof(recordid));
for( i = 0; i < t->len/2; i++ ) {
if( old[i].size ) {
t->records[ (old[i].page+old[i].slot) % t->len ] = old[i];
}
}
return touchBlob(xid, rid);
}
} else { /* space is free, mark it */
t->records[(rid.page+rid.slot)%t->len] = rid;
return 0;
}
} else { /* this is not our transaction */
do {
rehashTouch();
} while( touchBlob(xid, rid) );
return 0;
}
} else { /* we haven't allocated for this xid */
t->records = calloc(DEFAULT_TOUCHED, sizeof(recordid));
t->records[(rid.page+rid.slot)%DEFAULT_TOUCHED] = rid;
t->len = DEFAULT_TOUCHED;
t->xid = xid;
return 0;
}
assert(0);
return 0;
}
/*static void rmTouch(int xid) {
touchedBlob_t *t = &touched[xid%touchedLen];
if( t ) {
free( t->records );
t->records = NULL;
/ * touched[xid%touchedLen].xid = -1; TODO: necessary? * /
}
}*/
void pageCommit(int xid) { void pageCommit(int xid) {
/* rmTouch(xid); */ /* rmTouch(xid); */
} }
@ -265,8 +179,6 @@ void pageAbort(int xid) {
/* rmTouch(xid); */ /* rmTouch(xid); */
} }
/*#define getFirstHalfOfWord(memAddr) (((*(int*)memAddr) >> (2*BITS_PER_BYTE)) & MASK_0000FFFF) */
static int getFirstHalfOfWord(unsigned int *memAddr) { static int getFirstHalfOfWord(unsigned int *memAddr) {
unsigned int word = *memAddr; unsigned int word = *memAddr;
word = (word >> (2*BITS_PER_BYTE)); /* & MASK_0000FFFF; */ word = (word >> (2*BITS_PER_BYTE)); /* & MASK_0000FFFF; */
@ -384,6 +296,8 @@ static void writeNumSlots(byte *memAddr, int numSlots) {
* *
* NOTE: pageRalloc() assumes that the caller already made sure that sufficient * NOTE: pageRalloc() assumes that the caller already made sure that sufficient
* amount of freespace exists in this page. (@see freespace()) * amount of freespace exists in this page. (@see freespace())
*
* @todo Makes no attempt to reuse old recordid's.
*/ */
recordid pageRalloc(Page page, size_t size) { recordid pageRalloc(Page page, size_t size) {
int freeSpace = readFreeSpace(page.memAddr); int freeSpace = readFreeSpace(page.memAddr);
@ -393,12 +307,11 @@ recordid pageRalloc(Page page, size_t size) {
rid.page = page.id; rid.page = page.id;
rid.slot = numSlots; rid.slot = numSlots;
rid.size = size; rid.size = size;
/*int i; */
/* Make sure there's enough free space... */ /* Make sure there's enough free space... */
/* assert (freespace(page) >= (int)size); */ /* assert (freespace(page) >= (int)size); */ /*Expensive, so skipped not done. */
/* Reuse an old (invalid) slot entry */ /* Reuse an old (invalid) slot entry. Why was this here? */
/* for (i = 0; i < numSlots; i++) { /* for (i = 0; i < numSlots; i++) {
if (!isValidSlot(page.memAddr, i)) { if (!isValidSlot(page.memAddr, i)) {
rid.slot = i; rid.slot = i;
@ -468,12 +381,12 @@ void pageCompact(Page page) {
int i; int i;
byte buffer[PAGE_SIZE]; byte buffer[PAGE_SIZE];
/* char *buffer = (char *)malloc(PAGE_SIZE); */
int freeSpace = 0; int freeSpace = 0;
int numSlots = readNumSlots(page.memAddr); int numSlots = readNumSlots(page.memAddr);
int meta_size = LSN_SIZE + FREE_SPACE_SIZE + NUMSLOTS_SIZE + (SLOT_SIZE*numSlots); int meta_size = LSN_SIZE + FREE_SPACE_SIZE + NUMSLOTS_SIZE + (SLOT_SIZE*numSlots);
int slot_length; int slot_length;
int last_used_slot = 0; int last_used_slot = 0;
/* Can't compact in place, slot numbers can come in different orders than /* Can't compact in place, slot numbers can come in different orders than
the physical space allocated to them. */ the physical space allocated to them. */
memcpy(buffer + PAGE_SIZE - meta_size, page.memAddr + PAGE_SIZE - meta_size, meta_size); memcpy(buffer + PAGE_SIZE - meta_size, page.memAddr + PAGE_SIZE - meta_size, meta_size);
@ -537,163 +450,34 @@ int isBlobSlot(byte *pageMemAddr, int slot) {
return BLOB_SLOT == getSlotLength(pageMemAddr, slot); return BLOB_SLOT == getSlotLength(pageMemAddr, slot);
} }
/** /*
Blob format: @todo This needs should trust the rid (since the caller needs to
overrid the size in special circumstances, but if the size has been
If the slot entry's size is BLOB_SLOT, then the slot points to a blob record instead of data. The format of this record is: overridden, we should check for the circumstances where doing so is
allowed.
Int: Version number (0/1)
Int: Archive offset
Int: Blob size.
TODO: BufferManager should pass in file descriptors so that this function doesn't have to open and close the file on each call.
@todo This needs to trust the rid, which is fine, but it could do more to check if the page agrees with the rid...
*/ */
void pageReadRecord(int xid, Page page, recordid rid, byte *buff) { void pageReadRecord(int xid, Page page, recordid rid, byte *buff) {
byte *recAddress = page.memAddr + getSlotOffset(page.memAddr, rid.slot);
/*look at record, if slot offset == blob_slot, then its a blob, else its normal. */ byte *recAddress = page.memAddr + getSlotOffset(page.memAddr, rid.slot);
/* if(isBlobSlot(page.memAddr, rid.slot)) { memcpy(buff, recAddress, rid.size);
int fd = -1;
int version;
int offset;
int length;
version = *(int *)recAddress;
offset = *(int *)(recAddress + 4);
length = *(int *)(recAddress + 8);
fd = version == 0 ? blobfd0 : blobfd1;
/ * if( (fd = open(version == 0 ? BLOB0_FILE : BLOB1_FILE, O_RDWR, 0)) == -1 ) {
printf("page.c:pageReadRecord error and exiting\n");
exit(-1);
} * /
lseek(fd, offset, SEEK_SET);
read(fd, buff, length);
/ * close(fd); * /
} else { */
/* For now, we need page.c to trust the rid. */
/* int size = getSecondHalfOfWord((int*)slotMemAddr(page.memAddr, rid.slot)); */
memcpy(buff, recAddress, rid.size);
/*}*/
} }
void pageWriteRecord(int xid, Page page, recordid rid, const byte *data) { void pageWriteRecord(int xid, Page page, recordid rid, const byte *data) {
byte *rec;
/* int version = -1;
int fd = -1;
int blobRec[3];
if (isBlobSlot(page.memAddr, rid.slot)) { byte *rec;
/ * TODO: Rusty's wild guess as to what's supposed to happen. Touch blob appears to lookup the blob,
and allocate it if its not there. It returns 0 if it's a new blob, 1 otherwise, so I think we assert(rid.size < PAGE_SIZE);
just ignore its return value...* /
rec = page.memAddr + getSlotOffset(page.memAddr, rid.slot);
if(memcpy(rec, data, rid.size) == NULL ) {
printf("ERROR: MEM_WRITE_ERROR on %s line %d", __FILE__, __LINE__);
exit(MEM_WRITE_ERROR);
}
if( !touchBlob(xid, rid) ) {
/ * record hasn't been touched yet * /
rec = page.memAddr + getSlotOffset(page.memAddr, rid.slot);
version = *(int *)rec;
blobRec[0] = version == 0 ? 1 : 0;
blobRec[1] = *(int *)(rec + 4);
blobRec[2] = *(int *)(rec + 8);
memcpy(rec, blobRec, BLOB_REC_SIZE);
} else {
rec = page.memAddr + getSlotOffset(page.memAddr, rid.slot);
}
fd = version == 0 ? blobfd0 : blobfd1;
if(-1 == lseek(fd, *(int *)(rec +4), SEEK_SET)) {
perror("lseek");
}
if(-1 == write(fd, data, *(int *)(rec +8))) {
perror("write");
}
/ * Flush kernel buffers to hard drive. TODO: the
(standard) fdatasync() call only flushes the data
instead of the data + metadata. Need to have
makefile figure out if it's available, and do some
macro magic in order to use it, if possible...
This is no longer called here, since it is called at commit.
* /
/ * fsync(fd); * /
} else { / * write a record that is not a blob */
assert(rid.size < PAGE_SIZE);
rec = page.memAddr + getSlotOffset(page.memAddr, rid.slot);
if(memcpy(rec, data, rid.size) == NULL ) {
printf("ERROR: MEM_WRITE_ERROR on %s line %d", __FILE__, __LINE__);
exit(MEM_WRITE_ERROR);
}
/*}*/
} }
/* Currently not called any where, or tested. */
/*byte * pageMMapRecord(int xid, Page page, recordid rid) {
byte *rec;
int version = -1;
int fd = -1;
int blobRec[3];
byte * ret;
if (isBlobSlot(page.memAddr, rid.slot)) {
/ * TODO: Rusty's wild guess as to what's supposed to happen. Touch blob appears to lookup the blob,
and allocate it if its not there. It returns 0 if it's a new blob, 1 otherwise, so I think we
just ignore its return value...* /
if( !touchBlob(xid, rid) ) {
/ * record hasn't been touched yet * /
rec = page.memAddr + getSlotOffset(page.memAddr, rid.slot);
version = *(int *)rec;
blobRec[0] = version == 0 ? 1 : 0;
blobRec[1] = *(int *)(rec + 4);
blobRec[2] = *(int *)(rec + 8);
memcpy(rec, blobRec, BLOB_REC_SIZE);
} else {
rec = page.memAddr + getSlotOffset(page.memAddr, rid.slot);
}
fd = version == 0 ? blobfd0 : blobfd1;
if((ret = mmap((byte*) 0, *(int *)(rec +8), (PROT_READ | PROT_WRITE), MAP_SHARED, fd, *(int *)(rec +4))) == (byte*)-1) {
perror("pageMMapRecord");
}
/ * if(-1 == lseek(fd, *(int *)(rec +4), SEEK_SET)) {
perror("lseek");
}
if(-1 == write(fd, data, *(int *)(rec +8))) {
perror("write");
} * /
/ * Flush kernel buffers to hard drive. TODO: the
(standard) fdatasync() call only flushes the data
instead of the data + metadata. Need to have
makefile figure out if it's available, and do some
macro magic in order to use it, if possible...* /
/ * fsync(fd); * /
} else { / * write a record that is not a blob * /
rec = page.memAddr + getSlotOffset(page.memAddr, rid.slot);
ret = rec;
/ * if(memcpy(rec, data, rid.size) == NULL ) {
printf("ERROR: MEM_WRITE_ERROR on %s line %d", __FILE__, __LINE__);
exit(MEM_WRITE_ERROR);
}* /
}
return ret;
}
*/
void pageRealloc(Page *p, int id) { void pageRealloc(Page *p, int id) {
p->id = id; p->id = id;
p->LSN = 0; p->LSN = 0;
@ -706,17 +490,17 @@ Page pool[MAX_BUFFER_SIZE];
Allocate a new page. Allocate a new page.
@param id The id of the new page. @param id The id of the new page.
@return A pointer to the new page. This memory is part of a pool, @return A pointer to the new page. This memory is part of a pool,
and should not be freed by the application. and should never be freed by manually.
*/ */
Page *pageAlloc(int id) { Page *pageAlloc(int id) {
Page *p = &(pool[nextPage]); Page *p = &(pool[nextPage]);
nextPage++; nextPage++;
assert(nextPage <= MAX_BUFFER_SIZE); assert(nextPage <= MAX_BUFFER_SIZE);
/* pageRealloc(p, id);
Page *p = (Page*)malloc(sizeof(Page));*/ /* freed in bufDeinit */
/* assert(p); */ return p;
pageRealloc(p, id);
return p;
} }
void printPage(byte *memAddr) { void printPage(byte *memAddr) {
@ -777,58 +561,6 @@ int pageTest() {
return 0; return 0;
} }
/**
*
*/
recordid pageBalloc(Page page, int size, int fileOffset) {
int freeSpace = readFreeSpace(page.memAddr);
int numSlots = readNumSlots(page.memAddr);
recordid rid;
int i;
rid.page = page.id;
rid.slot = numSlots;
rid.size = size;
if (freespace(page) < BLOB_REC_SIZE) {
printf("Error in pageRalloc()\n");
exit(-1);
}
for (i = 0; i < numSlots; i++) {
if (!isValidSlot(page.memAddr, i)) {
rid.slot = i;
break;
}
}
if (rid.slot == numSlots) {
writeNumSlots(page.memAddr, numSlots+1);
}
setSlotOffset(page.memAddr, rid.slot, freeSpace);
setSlotLength(page.memAddr, rid.slot, BLOB_SLOT);
writeFreeSpace(page.memAddr, freeSpace + BLOB_REC_SIZE);
*(int *)(page.memAddr + freeSpace) = 0;
*(int *)(page.memAddr + freeSpace + 4) = fileOffset;
*(int *)(page.memAddr + freeSpace + 8) = size;
return rid;
}
/*
int getBlobOffset(int page, int slot) {
printf("Error: not yet implemented!!\n");
exit(-1);
}
int getBlobSize(int page, int slot) {
printf("Error: not yet implemented!!\n");
exit(-1);
}*/
void setSlotType(Page p, int slot, int type) { void setSlotType(Page p, int slot, int type) {
assert(type > PAGE_SIZE); assert(type > PAGE_SIZE);

View file

@ -1,460 +0,0 @@
/*---
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
* $Id$
*
* Implements recovery for a NO STEAL system -- we won't need any undo functions, CLRs, or to redo any aborted/uncommitted transactions
*
* @deprecated
* @see recovery2.c
* *************/
#include <stdlib.h>
#include "recovery.h"
#include <lladd/transactional.h>
#include <lladd/common.h>
#include "linkedlist.h"
#include <lladd/logger.h>
#include "logger/logparser.h"
#include "logger/logstreamer.h"
#include <pbl/pbl.h>
#include <lladd/page.h>
#include <lladd/bufferManager.h>
#include <stdio.h>
/* just set an arbitrary recovery xid */
#define RECOVERY_XID 69
/* moved from recovery.h, sice this is the only file that uses it. */
static void undoUpdateRec(CommonLog cl, UpdateLog ul);
/* map from page number to the recLSN that dirtied it */
static pblHashTable_t *dirtyPages;
/* sorted list of recLSNs of active transactiosn */
static LinkedListPtr transRecLSNs=NULL;
/* map from transID to status of the transaction: U (to be undone), or not in
* there, or committed but not ended (C)
* */
static pblHashTable_t *transTable;
/* the LSN of the dirty page with the smallest corresponding LSN */
static long minDirtyLSN;
void undoUpdateRec(CommonLog cl, UpdateLog ul) {
int undoIndex = operationsTable[ul.funcID].undo;
long CLRLSN;
CLRLSN = LogCLR(-1, cl.xid, cl.LSN, ul.rid, cl.prevLSN);
/*printf ("Undoing LSN=%ld (and writing new pageLSN=%ld\n", cl.LSN, CLRLSN); */
if (undoIndex==NO_INVERSE)
writeRecord(RECOVERY_XID, ul.rid, ul.preImage); /*if there's no inverse we directly write the preimage to the record*/
else operationsTable[undoIndex].run(RECOVERY_XID, ul.rid, ul.args);
writeLSN(CLRLSN, ul.rid.page);
}
/**
* Do this CLR action, and return the undoNextLSN listed in this clrlog
*/
/*static long DoCLRAction(CLRLog clrlog) {
UpdateLog ul;
CommonLog commonLog = readCommonLogFromLSN(clrlog.thisUpdateLSN);
if (commonLog.type!=UPDATELOG) {
printf ("Don't know how to undo a non-update log (LSN=%ld)! Aborting undo...\n", commonLog.LSN);
return -1;
}
ul = updateStringToParts(commonLog.extraData);
undoUpdate(commonLog, ul);
return clrlog.undoNextLSN;
}*/
/**
* Redo this clrlog, and it doesn't write out any CLR for the CLR. For now copy
* and pasted form undoUpdate, make it cleaner in the future.
*/
static void RedoCLRAction(CLRLog clrlog) {
int undoIndex;
UpdateLog ul;
CommonLog commonLog = readCommonLogFromLSN(clrlog.thisUpdateLSN);
if (commonLog.type!=UPDATELOG) {
printf ("Don't know how to undo a non-update log (LSN=%ld)! Aborting undo...\n", commonLog.LSN);
return;
}
ul = updateStringToParts(commonLog.extraData);
undoIndex = operationsTable[ul.funcID].undo;
printf ("ReUndoing LSN=%ld\n", commonLog.LSN);
if (undoIndex==NO_INVERSE)
writeRecord(RECOVERY_XID, ul.rid, ul.preImage); /*if there's no inverse we directly write the preimage to the record*/
else operationsTable[undoIndex].run(RECOVERY_XID, ul.rid, ul.args);
writeLSN(commonLog.LSN, clrlog.rid.page);
}
static void recovInit() {
/* startLogStream(); */ /* This is now called after Tinit() opens the log (to support Tprepare, and to fix the reused XID bug) */
dirtyPages = pblHtCreate();
transTable = pblHtCreate();
}
/*
loadCheckPoint scans the log from the end to find the most recent checkpoint
loads the dirty page table from the checkpoint
set the lsn to start to be one after the end_checkpoint log **check this-i think it should be one after begin_checkpoint
if there are no checkpoints, LSN starts is 0
*/
static void loadCheckPoint (long *endCheckptLSN) {
/*for now just assume no checkpoints
therefore committedtrans table and DPT are empty
start recovery at LSN 0 */
*endCheckptLSN = 1;
}
/*
At end of recovery, wrap up --
delete the committed transaction list
possibly in the future: delete the log file
*/
static void CleanUp() {
/* void *trans; */
destroyList(transRecLSNs);
transRecLSNs = 0;
/*any pages that were dirty should be flushed to disk and then the
corresponding transaction ended */
/*flushAllPages(); */
/*trans = pblHtFirst(transTable);
while (trans!=NULL) {
LogEnd(-1, *(int *)pblHtCurrentKey(transTable));
trans = pblHtNext(transTable);
}*/
pblHtDelete(dirtyPages);
pblHtDelete(transTable);
flushLog();
/* closeLogStream(); */
bufTransCommit(RECOVERY_XID); /*What is this? */
}
/*
Returns true ifa page must be redone
loads the page into loadedPage if it needs to be redone
*/
static int MustBeRedone(long entryLSN, int page, Page *loadedPage) {
/* if this log entry's page is dirty */
long tmp;
long *recLSN = pblHtLookup(dirtyPages, &page, sizeof(int));
if (recLSN!=NULL) {
/*unmalloc this entry in the table, don't need it anymore */
tmp = *recLSN;
/* if the log entry's LSN is less than the recLSN of the dirty page */
if (entryLSN <= tmp) {
/*load page into memory, if the log's LSN is greater than (more recent) the LSN of that actual page (as it was on disk) */
*loadedPage = loadPage(page);
if (entryLSN > readLSN(page))
return 1;
}
}
return 0;
}
/*
Given a page number and the log's LSN, analyze the page, aka
look it up in the dirty page table and add it if it's not there, and
have the table reflect the most recent LSN
also keeps track of the smallest dirty LSN
*/
static void analyzePage(int page, long curLSN) {
long *LSNCopy;
/*add page to the dirty page table if not there already with recLSN equal to this LSN */
long *oldLSN = pblHtLookup(dirtyPages, &page, sizeof(int));
if (oldLSN==NULL) {
/*make a new entry */
LSNCopy = (long *)malloc(sizeof(long));
*LSNCopy = curLSN;
pblHtInsert( dirtyPages, &page, sizeof(int), LSNCopy);
} else {
/*update the old entry to have the most recent LSN */
*oldLSN = curLSN;
}
/*if it's the smallest dirty LSN, make note of it */
if (minDirtyLSN==-1 || curLSN < minDirtyLSN)
minDirtyLSN = curLSN;
}
/**
* Analysis is the first phase:
* 1) determines the point in the log at which to start the Redo pass
* 2) determines (a conservative superset of the) pages in the buffer pool
* that were dirty at the time of the crash
*
* At the end of Analysis, transaction table contains accurate list of all
* transactions that were active at the time of the crash, and dirty page table
* includes all pages that were dirty ta time of crash (plus maybe some that
* were written to disk)
*/
static void RecovAnalysis () {
long curLSN, *thisTLSN;
int highestXid = -1;
CommonLog logEntry;
UpdateLog ul;
recordid thisRid;
CLRLog clrlog;
char *status;
pblHashTable_t *transMaxLSN = pblHtCreate();
minDirtyLSN = -1;
loadCheckPoint(&curLSN); /*sets DPT, AT and the current LSN to the last checkpoint if there is on */
/*scan through the log until the end*/
logEntry = readCommonLogFromLSN(curLSN);
while (logEntry.valid==1) {
if(highestXid < logEntry.xid) {
highestXid = logEntry.xid;
}
if ((status = (char *)pblHtLookup(transTable, &logEntry.xid, sizeof(int)))==NULL) {
status = malloc(sizeof(char));
*status = 'U'; /*default is to be undone */
pblHtInsert(transTable, &logEntry.xid, sizeof(int), status);
}
if ((thisTLSN = (long *)pblHtLookup(transMaxLSN, &logEntry.xid, sizeof(int))) != NULL) {
removeVal(&transRecLSNs, *thisTLSN); /*it's not the max anymore -- will add another val in later */
}
else {
thisTLSN = (long *)malloc(sizeof(long));
*thisTLSN = -1;
pblHtInsert(transMaxLSN, &logEntry.xid, sizeof(int), thisTLSN);
}
curLSN = logEntry.LSN;
switch(logEntry.type) {
case XCOMMIT:
*status = 'C';
break;
case XEND:
pblHtRemove(transTable, &logEntry.xid, sizeof(int)); /*not a transaction anymore, remove it from the transaction table */
pblHtRemove(transMaxLSN, &logEntry.xid, sizeof(int));
break;
case UPDATELOG:
/*determine what page it modified*/
ul = updateStringToParts(logEntry.extraData);
analyzePage(ul.rid.page, logEntry.LSN);
free(logEntry.extraData);
/*removeVal(&transRecLSNs, *thisTLSN);*/
addSortedVal(&transRecLSNs, logEntry.LSN);
*thisTLSN = logEntry.LSN;
break;
case XALLOC:
thisRid = allocStringToRID(logEntry.extraData);
analyzePage(thisRid.page, logEntry.LSN);
free(logEntry.extraData);
/*removeVal(&transRecLSNs, *thisTLSN); */
addSortedVal(&transRecLSNs, logEntry.LSN);
*thisTLSN = logEntry.LSN;
break;
case CLRLOG:
clrlog = CLRStringToParts(logEntry.extraData);
analyzePage(clrlog.rid.page, logEntry.LSN);
addSortedVal(&transRecLSNs, logEntry.LSN);
*thisTLSN = logEntry.LSN;
break;
}
/*printList(transRecLSNs); */
logEntry = readNextCommonLog();
}
TsetXIDCount(highestXid);
pblHtDelete(transMaxLSN);
}
/**
* Redo applies updates of all committed transactions if they haven't been flushed to disk yet
*
*/
static void RecovRedo () {
long curLSN = minDirtyLSN; /* start with smallest recLSN in dirty page table */
UpdateLog ul;
/* long *recLSN, */
long nextLSN;
Page loadedPage;
CLRLog clrlog;
recordid rec;
int i;
CommonLog logEntry;
/* starting from there, scan forward until end of log */
logEntry = readCommonLogFromLSN(curLSN);
while (logEntry.valid!=0) {
/*for each redoable log record, check whether logged action must be redone - redoable actions are update logs/alloc logs and must be a committed transaction*/
if (pblHtLookup(transTable, &logEntry.xid, sizeof(int))!=NULL) {
switch (logEntry.type) { /*only look at redoable log entries */
case UPDATELOG:
ul = updateStringToParts(logEntry.extraData);
if (MustBeRedone(logEntry.LSN, ul.rid.page, &loadedPage)==1) {
/*reapply logged action, AND set LSN on page to the LSN of the redone log record, flush to disk(?)
note that this is going around logging (which is done in transactional) so this will be unlogged*/
printf ("redoing op %d at LSN=%ld (>%ld), rid (page, slot, size)=%d,%d,%d. args (length %d)=", ul.funcID, logEntry.LSN, loadedPage.LSN, ul.rid.page, ul.rid.slot, ul.rid.size, ul.argSize);
for (i=0; i<ul.argSize; i++)
printf ("%c", *(char*)(ul.args+i));
printf ("\n");
operationsTable[ul.funcID].run(RECOVERY_XID, ul.rid, ul.args);
/*loadedPage.LSN = logEntry.LSN;*/
writeLSN(logEntry.LSN, ul.rid.page);
}
/** @todo KLUDGE: updateStringToParts mallocs ul.args, while assembleUpdateLog does not. Therefore, we remove the const qualifier from ul.args here,
and free it. Elsewhere, we do not have to do this. */
free((byte*)ul.args);
break;
case XALLOC:
rec = allocStringToRID(logEntry.extraData);
if (MustBeRedone(logEntry.LSN, rec.page, &loadedPage)==1) {
/*reallocate the record in the page just like how it was before*/
printf ("redoing record allocation at LSN=%ld: rid=%d,%d,%ld where pageid=%d.\n", logEntry.LSN, rec.page, rec.slot, (long int)rec.size, (int)loadedPage.id);
pageSlotRalloc(loadedPage, rec);
writeLSN(logEntry.LSN, rec.page);
}
break;
case CLRLOG:
clrlog = CLRStringToParts(logEntry.extraData);
if (MustBeRedone(logEntry.LSN, clrlog.rid.page, &loadedPage)==1) {
printf("redoing CLR at LSN=%ld (>%ld), rid=%d,%d,%ld...", logEntry.LSN, loadedPage.LSN, clrlog.rid.page, clrlog.rid.slot, (long int)clrlog.rid.size);
nextLSN = streamPos();
RedoCLRAction(clrlog);
seekInLog(nextLSN);
writeLSN(logEntry.LSN, clrlog.rid.page);
}
break;
} /* switch*/
} /* committed trans IF */
if (logEntry.extraData)
free(logEntry.extraData);
logEntry = readNextCommonLog();
} /* while */
}
/**
* Looking at the set of lastLSN values for all 'loser' (non ending)
* transactions, pick the most recent LSN, undo it (if it is an update log) and
* add in prevLSN to the set of to be looked at LSNs, or add undoNextLSN if it
* is a CLR log
*/
static void RecovUndo(int recovering) {
long LSNToLookAt;
CommonLog comLog;
UpdateLog ul;
CLRLog clrlog;
recordid rec;
Page loadedPage;
while (transRecLSNs!=NULL) {
LSNToLookAt = popMaxVal(&transRecLSNs);
comLog = readCommonLogFromLSN(LSNToLookAt);
switch (comLog.type) {
case UPDATELOG:
ul = updateStringToParts(comLog.extraData);
undoUpdateRec(comLog, ul);
if ((ul.funcID != OPERATION_PREPARE) ||
(!recovering)) {
if (comLog.prevLSN>0) /*0 or -1 are invalid LSNs*/
addSortedVal(&transRecLSNs, comLog.prevLSN);
/*else LogEnd(-1, comLog.xid);*/
} else if (ul.funcID == OPERATION_PREPARE) {
/* TODO: Ugly! */
printf("Reviving XID: %d\n", comLog.xid);
Trevive(comLog.xid, LSNToLookAt);
} else {
printf("EEK!\n");
}
/*else LogEnd(-1, comLog.xid);*/
break;
case CLRLOG:
clrlog = CLRStringToParts(comLog.extraData);
if (clrlog.undoNextLSN>0)
addSortedVal(&transRecLSNs, clrlog.undoNextLSN);
/*else LogEnd(-1, comLog.xid);*/
break;
case XALLOC:
rec = allocStringToRID(comLog.extraData);
loadedPage = loadPage(rec.page);
printf ("NOT undoing record allocation at LSN=%ld: rid=%d,%d,%ld where pageid=%d.\n", comLog.LSN, rec.page, rec.slot, (long int)rec.size, loadedPage.id);
/* If page is already in memory (likely), then this just gets a pointer to it. */
/* The next line is correct, but commented because it causes trouble with LLADD hash. */
/* pageDeRalloc(loadedPage, rec); */
if (comLog.prevLSN>0) /*0 or -1 are invalid LSNs*/
addSortedVal(&transRecLSNs, comLog.prevLSN);
break;
default: printf ("Unknown log type to undo (TYPE=%d, XID= %d, LSN=%ld), skipping...\n", comLog.type, comLog.xid, comLog.LSN);
if (comLog.prevLSN>0)
addSortedVal(&transRecLSNs, comLog.prevLSN);
/*else LogEnd(-1, comLog.xid);*/
break;
}
}
}
/**
* because this messes with transRecLSNs,
* should NOT be called by recovery. Call it from
* non-recovery code!
*/
void undoTrans(Transaction t) {
if (transRecLSNs) {
destroyList(transRecLSNs);
}
transRecLSNs = 0;
if(t.LSN > 0) {
addSortedVal(&transRecLSNs, t.LSN);
} else {
/* printf ("Nothing to undo for xid %d\n", t.xid); I think this is normal for the sequence Tbegin, Tread, Tabort -- Rusty */
}
RecovUndo(0);
}
void InitiateRecovery () {
recovInit();
printf ("Analysis\n");
RecovAnalysis();
printf ("Redo\n");
RecovRedo();
printf ("Undo\n");
RecovUndo(1);
CleanUp();
}

View file

@ -1,65 +0,0 @@
/*---
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
Used to implement recovery.
@deprecated
@see recovery2.h
*/
#ifndef __RECOVERY_H__
#define __RECOVERY_H__
#include "logger/logparser.h"
#include <lladd/transactional.h>
/*
Initiate the recovery method!
When finished, pages on disk fully reflect all committed transactions in the log
*/
void InitiateRecovery ();
void undoTrans(Transaction t);
#endif

View file

@ -21,19 +21,6 @@
/** @todo This include is an artifact of our lack of infrastructure to support log iterator guards. */ /** @todo This include is an artifact of our lack of infrastructure to support log iterator guards. */
#include <lladd/operations/prepare.h> #include <lladd/operations/prepare.h>
/** Maps from xid (int) to status:
NULL - Haven't seen XID
U - XID is scheduled for UNDO
C - XID committed, but not ended. (End records are written once
the XID is flushed to disk. They are only written during the
recovery process, and shutdown since LLADD follows a no force
policy.) @todo Implement end records.
@todo We don't ever read values out of this hash table... could it
be replaced entirely with transactionLSN?
*/
/*static pblHashTable_t * transactionStatus; */
static pblHashTable_t * transactionLSN; static pblHashTable_t * transactionLSN;
static LinkedListPtr rollbackLSNs = NULL; static LinkedListPtr rollbackLSNs = NULL;
/** /**
@ -116,9 +103,8 @@ static void Analysis () {
not overwrite this transaction's work with stale data.) not overwrite this transaction's work with stale data.)
The redo phase checks for a transaction's presence in The redo phase checks for a transaction's presence in
transactionLSN before redoing its actions. Therefore, if transactionLSN before redoing its actions. Therefore, if we
we remove this transaction from the transactionStatus hash, remove this transaction from the hash, it will not be redone.
it will not be redone.
*/ */
pblHtRemove(transactionLSN, &(e->xid), sizeof(int)); pblHtRemove(transactionLSN, &(e->xid), sizeof(int));
break; break;
@ -140,9 +126,6 @@ static void Analysis () {
/* Don't want this XID in the list of rolled back lsn's since /* Don't want this XID in the list of rolled back lsn's since
this XACT will be rolled back during redo. */ this XACT will be rolled back during redo. */
break; break;
/* case XALLOC: */ /* @todo Don't use XALLOC anymore, dont need it here. */
/* assert (0); */
default: default:
assert (0); assert (0);
} }
@ -156,13 +139,13 @@ static void Redo() {
LogEntry * e; LogEntry * e;
while((e = nextInLog(&lh))) { while((e = nextInLog(&lh))) {
/* int garbage; */
/* Check to see if this log entry is part of a transaction that needs to be redone. */ /* Check to see if this log entry is part of a transaction that needs to be redone. */
if(pblHtLookup(transactionLSN, &(e->xid), sizeof(int)) != NULL) { if(pblHtLookup(transactionLSN, &(e->xid), sizeof(int)) != NULL) {
/* Check to see if this log entry contains an action that needs to be redone. */ /* Check to see if this log entry contains an action that needs to be redone. */
if(e->type == UPDATELOG || if(e->type == UPDATELOG ||
e->type == CLRLOG) { e->type == CLRLOG) {
/* redoOperation checks the page that contains e->rid, so we /* redoUpdate checks the page that contains e->rid, so we
don't need to check to see if the page is newer than this don't need to check to see if the page is newer than this
log entry. */ log entry. */
redoUpdate(e); redoUpdate(e);
@ -213,36 +196,30 @@ static void Undo(int recovery) {
/* printf("1"); fflush(NULL); */ /* printf("1"); fflush(NULL); */
/* This check was incorrect. Since blobManager may lazily
update the pageManager, it is possible for this test to
fail. In that case, the undo is handled by blob manager
(it removes this page from it's dirty blob list), not
us. (Nope, it is now, again correct--fixed blobManager)*/
assert(e->LSN <= this_lsn); assert(e->LSN <= this_lsn);
/* printf("1a"); fflush(NULL); */ /* printf("1a"); fflush(NULL); */
/* Need to log a clr here. */ /* Need to log a clr here. */
clr_lsn = LogCLR(e); clr_lsn = LogCLR(e);
/* writeLSN(clr_lsn, e->contents.update.rid.page); */
/* Undo update is a no-op if the page does not reflect this /* Undo update is a no-op if the page does not reflect this
update, but it will write the new clr_lsn. */ update, but it will write the new clr_lsn if necessary. */
undoUpdate(e, clr_lsn); undoUpdate(e, clr_lsn);
/* printf("1b"); fflush(NULL); */ /* printf("1b"); fflush(NULL); */
break; break;
case CLRLOG: case CLRLOG:
/* Don't need to do anything special to handle CLR's. /* Don't need to do anything special to handle CLR's.
Iterator will correctly jump to clr's previous undo record. */ Iterator will correctly jump to clr's previous undo record. */
/* printf("2"); fflush(NULL); */ /* printf("2"); fflush(NULL); */
break; break;
/* case XALLOC: */
/* Don't use xalloc anymore. */
/*assert(0);*/
break;
case XABORT: case XABORT:
/* Since XABORT is a no-op, we can safely ignore it. (XABORT records may be passed in by undoTrans.)*/ /* Since XABORT is a no-op, we can silentlt ignore it. (XABORT
records may be passed in by undoTrans.)*/
break; break;
default: default:
printf ("Unknown log type to undo (TYPE=%d, XID= %d, LSN=%ld), skipping...\n", e->type, e->xid, e->LSN); printf ("Unknown log type to undo (TYPE=%d, XID= %d, LSN=%ld), skipping...\n", e->type, e->xid, e->LSN);
@ -264,6 +241,7 @@ void InitiateRecovery() {
DEBUG("Undo started\n"); DEBUG("Undo started\n");
Undo(1); Undo(1);
DEBUG("Recovery complete.\n"); DEBUG("Recovery complete.\n");
/** @todo Should we manually empty the hash table? */ /** @todo Should we manually empty the hash table? */
pblHtDelete(transactionLSN); pblHtDelete(transactionLSN);
@ -277,10 +255,10 @@ void undoTrans(TransactionLog transaction) {
} }
rollbackLSNs = 0; rollbackLSNs = 0;
if(transaction.prevLSN > 0) { if(transaction.prevLSN > 0) {
/* printf("scheduling lsn %ld for undo.\n", transaction.prevLSN); */ DEBUG("scheduling lsn %ld for undo.\n", transaction.prevLSN);
addSortedVal(&rollbackLSNs, transaction.prevLSN); addSortedVal(&rollbackLSNs, transaction.prevLSN);
} else { } else {
/* Nothing to undo. (Happens for read-only xacts. */ /* Nothing to undo. (Happens for read-only xacts.) */
} }
Undo(0); Undo(0);

View file

@ -1,182 +0,0 @@
/*---
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
* $Id$
*
* implements main interface to tranactional pages
*
* @deprecated
* @see transactional2.c
* ************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <lladd/transactional.h>
#include <lladd/constants.h>
#include <lladd/logger.h>
#include <lladd/bufferManager.h>
#include "recovery.h"
Transaction XactionTable[MAX_TRANSACTIONS];
int numActiveXactions = 0;
int xidCount = 0;
#define INVALID_XTABLE_XID -1
int Tinit() {
memset(XactionTable, INVALID_XTABLE_XID, sizeof(Transaction)*MAX_TRANSACTIONS);
operationsTable[OPERATION_SET] = getSet();
operationsTable[OPERATION_INCREMENT] = getIncrement();
operationsTable[OPERATION_DECREMENT] = getDecrement();
operationsTable[OPERATION_PREPARE] = getPrepare();
operationsTable[OPERATION_LHINSERT] = getLHInsert();
operationsTable[OPERATION_LHREMOVE] = getLHRemove();
pageInit();
bufInit();
logInit();
return 0;
}
int Tbegin() {
int i, index = 0;
if( numActiveXactions == MAX_TRANSACTIONS )
return EXCEED_MAX_TRANSACTIONS;
else
numActiveXactions++;
for( i = 0; i < MAX_TRANSACTIONS; i++ ) {
xidCount++;
if( XactionTable[xidCount%MAX_TRANSACTIONS].xid == INVALID_XTABLE_XID ) {
index = xidCount%MAX_TRANSACTIONS;
break;
}
}
assert( i < MAX_TRANSACTIONS );
XactionTable[index].xid = xidCount;
XactionTable[index].LSN = LogTransBegin(XactionTable[index]);
return XactionTable[index].xid;
}
void Tupdate(int xid, recordid rid, const void *dat, int op) {
assert(numActiveXactions <= MAX_TRANSACTIONS);
writeLSN(XactionTable[xid%MAX_TRANSACTIONS].LSN = LogUpdate(XactionTable[xid%MAX_TRANSACTIONS].LSN, xid, rid, operationsTable[op], dat), rid.page);
operationsTable[op].run(xid, rid, dat);
}
recordid Talloc(int xid, size_t size) {
recordid ret;
ret = ralloc(xid, size);
writeLSN(XactionTable[xid%MAX_TRANSACTIONS].LSN = LogTransAlloc(XactionTable[xid%MAX_TRANSACTIONS].LSN, xid, ret), ret.page);
return ret;
}
void Tread(int xid, recordid rid, void *dat) {
readRecord(xid, rid, dat);
}
int Tcommit(int xid) {
LogTransCommit(XactionTable[xid%MAX_TRANSACTIONS].LSN, xid);
bufTransCommit(xid); /* unlocks pages */
XactionTable[xid%MAX_TRANSACTIONS].xid = INVALID_XTABLE_XID;
numActiveXactions--;
assert( numActiveXactions >= 0 );
return 0;
}
int Tabort(int xid) {
/* should call undoTrans after log trans abort. undoTrans will cause pages to contain CLR values corresponding to */
undoTrans(XactionTable[xid%MAX_TRANSACTIONS]);
LogTransAbort(XactionTable[xid%MAX_TRANSACTIONS].LSN, xid);
bufTransAbort(xid);
XactionTable[xid%MAX_TRANSACTIONS].xid = INVALID_XTABLE_XID;
numActiveXactions--;
assert( numActiveXactions >= 0 );
return 0;
}
int Tdeinit() {
int i;
for( i = 0; i < MAX_TRANSACTIONS; i++ ) {
if( XactionTable[i].xid != INVALID_XTABLE_XID ) {
Tabort(XactionTable[i].xid);
}
}
assert( numActiveXactions == 0 );
bufDeinit();
logDeinit();
return 0;
}
void Trevive(int xid, long lsn) {
int index = xid % MAX_TRANSACTIONS;
if(XactionTable[index].xid != INVALID_XTABLE_XID) {
printf("Clashing Tprepare()'ed XID's encountered on recovery!!\n");
exit(-1);
}
XactionTable[index].xid = xid;
XactionTable[index].LSN = lsn;
numActiveXactions++;
}
void TsetXIDCount(xid) {
xidCount = xid;
}

View file

@ -2,7 +2,7 @@
#include <lladd/constants.h> #include <lladd/constants.h>
#include <lladd/logger/logger2.h> #include <lladd/logger/logger2.h>
#include <lladd/bufferManager.h> #include <lladd/bufferManager.h>
#include <lladd/recovery2.h> #include <lladd/recovery.h>
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
@ -29,7 +29,6 @@ int Tinit() {
openLogWriter(); openLogWriter();
InitiateRecovery(); InitiateRecovery();
/* logInit(); */
return 0; return 0;
} }
@ -66,9 +65,8 @@ void Tupdate(int xid, recordid rid, const void *dat, int op) {
assert(XactionTable[xid % MAX_TRANSACTIONS].prevLSN == e->LSN); assert(XactionTable[xid % MAX_TRANSACTIONS].prevLSN == e->LSN);
/* printf("e->LSN: %ld\n", e->LSN); */ DEBUG("Tupdate() e->LSN: %ld\n", e->LSN);
/* writeLSN(e->LSN, rid.page); <-- Handled by doUpdate now */
doUpdate(e); doUpdate(e);
} }
@ -91,13 +89,14 @@ int Tcommit(int xid) {
int Tabort(int xid) { int Tabort(int xid) {
lsn_t lsn; lsn_t lsn;
lsn = LogTransAbort(&XactionTable[xid%MAX_TRANSACTIONS]); lsn = LogTransAbort(&XactionTable[xid%MAX_TRANSACTIONS]);
/* should call undoTrans after log trans abort. undoTrans will cause pages to contain CLR values corresponding to */
/* @todo is the order of the next two calls important? */ /* @todo is the order of the next two calls important? */
undoTrans(XactionTable[xid%MAX_TRANSACTIONS]); undoTrans(XactionTable[xid%MAX_TRANSACTIONS]);
bufTransAbort(xid, lsn); bufTransAbort(xid, lsn);
XactionTable[xid%MAX_TRANSACTIONS].xid = INVALID_XTABLE_XID; XactionTable[xid%MAX_TRANSACTIONS].xid = INVALID_XTABLE_XID;
numActiveXactions--; numActiveXactions--;
assert( numActiveXactions >= 0 ); assert( numActiveXactions >= 0 );
return 0; return 0;
} }
@ -113,7 +112,6 @@ int Tdeinit() {
assert( numActiveXactions == 0 ); assert( numActiveXactions == 0 );
bufDeinit(); bufDeinit();
/* logDeinit(); */
closeLogWriter(); closeLogWriter();
return 0; return 0;