Implemented pageOrientedList, also did some bug fixing, and added some support functions to alloc.c

This commit is contained in:
Sears Russell 2005-01-28 03:32:17 +00:00
parent 05934d296a
commit 17f76264aa
20 changed files with 826 additions and 86 deletions

149
lladd.pws
View file

@ -11,24 +11,50 @@ filter.file.ignore.hidden=0
filter.dir.ignore.hidden=0 filter.dir.ignore.hidden=0
[filenumbers] [filenumbers]
0=22 0=170
1=1 1=70
2=12 2=21
3=2 3=50
4=50 4=1
5=3 5=1
6=25 6=89
7=24 7=22
8=30 8=1
9=1 9=1
10=67 10=153
11=1 11=102
12=17 12=4
13=1 13=6
14=104 14=1
15=387 15=69
16=58 16=148
17=8 17=1
18=1
19=1
20=13
21=43
22=87
23=2
24=1
25=106
26=106
27=124
28=151
29=158
30=324
31=145
32=46
33=5
34=38
35=49
36=11
37=47
38=76
39=29
40=1
41=324
42=66
43=167
[filemarkers] [filemarkers]
0= 0=
@ -49,16 +75,78 @@ filter.dir.ignore.hidden=0
15= 15=
16= 16=
17= 17=
18=
19=
20=
21=
22=
23=
24=
25=
26=
27=
28=
29=
30=
31=
32=
33=
34=
35=
36=
37=
38=
39=
40=
41=
42=
43=
[filelist] [filelist]
0=/home/sears/lladd/libdfa/messages.h 0=/home/sears/lladd/src/lladd/page/slotted.h
1=/home/sears/lladd/test/dfa/Makefile.am 1=/home/sears/lladd/lladd/operations/pageOrientedListNTA.h
2=/home/sears/lladd/test/lladd/Makefile.am 2=/home/sears/lladd/src/lladd/operations/pageOrientedListNTA.c
3=/home/sears/lladd/test/lladd/check_blobRecovery.c 3=/home/sears/lladd/lladd/operations/linkedListNTA.h
4=/home/sears/lladd/test/dfa/check_networksetup.c 4=/home/sears/lladd/src/lladd/operations/linkedListNTA.c
5=/home/sears/lladd/libdfa/networksetup.sample 5=/home/sears/lladd/lladd/operations/linearHashNTA.h
6=/home/sears/lladd/src/libdfa/networksetup.c 6=/home/sears/lladd/lladd/operations/prepare.h
7=/home/sears/lladd/libdfa/networksetup.h 7=/home/sears/lladd/lladd/operations/alloc.h
8=/home/sears/lladd/benchmarks/berkeleyDB/Makefile.am
9=/home/sears/lladd/benchmarks/berkeleyDB/bdbRaw.c
10=/home/sears/lladd/lladd/transactional.h
11=/home/sears/lladd/doc/index.html
12=/home/sears/lladd/test/cht/run
13=/home/sears/lladd/test/cht/Makefile.am
14=/home/sears/lladd/src/apps/cht/Makefile.am
15=/home/sears/lladd/configure.in
16=/home/sears/lladd/src/lladd/logger/logWriter.c
17=/home/sears/lladd/src/lladd/operations/alloc.c
18=/home/sears/lladd/lladd/constants.h
19=/home/sears/lladd/src/lladd/operations.c
20=/home/sears/lladd/test/cht/subordinate.c
21=/home/sears/lladd/src/libdfa/callbacks.c
22=/home/sears/lladd/src/2pc/2pc.h
23=/home/sears/lladd/test/2pc/Makefile.am
24=/home/sears/lladd/test/cht/cht_server.c
25=/home/sears/lladd/test/cht/simple.c
26=/home/sears/lladd/test/2pc/always_commit.c
27=/home/sears/lladd/test/dfa/star.c
28=/home/sears/lladd/src/apps/cht/cht.h
29=/home/sears/lladd/libdfa/libdfa.h
30=/home/sears/lladd/src/libdfa/libdfa.c
31=/home/sears/lladd/src/apps/cht/cht_client.c
32=/home/sears/lladd/src/lladd/operations/linearHashNTA.c
33=/home/sears/lladd/test/cht/client.conf
34=/home/sears/lladd/libdfa/networksetup.h
35=/home/sears/lladd/src/apps/cht/cht.c
36=/home/sears/lladd/test/cht/cluster.conf
37=/home/sears/lladd/test/cht/client.c
38=/home/sears/lladd/src/libdfa/networksetup.c
39=/home/sears/lladd/src/apps/cht/cht_server.c
40=/home/sears/lladd/src/apps/cht/cht_message.c
41=/home/sears/lladd/src/libdfa/messages.c
42=/home/sears/lladd/libdfa/messages.h
43=/home/sears/lladd/src/2pc/2pc.c
[Project Tree] [Project Tree]
0=0 0=0
@ -73,11 +161,12 @@ filter.dir.ignore.hidden=0
[File Tree] [File Tree]
0=0 0=0
1=0:5 1=0:6
2=0:6 2=0:6:2
3=0:9 3=0:10
4=0:10 4=0:10:4
5=0:11 5=0:10:4:4
6=0:12
[executer args] [executer args]
0=check_linearHash 0=check_linearHash

View file

@ -164,6 +164,7 @@ typedef struct {
#include "operations/nestedTopActions.h" #include "operations/nestedTopActions.h"
#include "operations/linkedListNTA.h" #include "operations/linkedListNTA.h"
#include "operations/linearHashNTA.h" #include "operations/linearHashNTA.h"
#include "operations/pageOrientedListNTA.h"
extern Operation operationsTable[]; /* [MAX_OPERATIONS]; memset somewhere */ extern Operation operationsTable[]; /* [MAX_OPERATIONS]; memset somewhere */

View file

@ -30,6 +30,8 @@ Operation getRealloc();
*/ */
recordid Talloc(int xid, long size); recordid Talloc(int xid, long size);
recordid TallocFromPage(int xid, long page, long size);
/** /**
Free a record. Free a record.
@todo Currently, we just leak store space on dealloc. @todo Currently, we just leak store space on dealloc.
@ -37,12 +39,33 @@ recordid Talloc(int xid, long size);
void Tdealloc(int xid, recordid rid); void Tdealloc(int xid, recordid rid);
/** /**
Return the type of a record, as returned by getRecordType. Obtain the type of a record, as returned by getRecordType.
@todo document TrecordType @param xid the transaction id.
@see getRecordType
@param rid the record of interest. The size field will be ignored,
allowing this function to be used to probe for records in pages.
@return UNINITIALIZED_RECORD, BLOB_RECORD, SLOTTED_RECORD, or FIXED_RECORD.
@see getRecordType
*/ */
int TrecordType(int xid, recordid rid); int TrecordType(int xid, recordid rid);
/**
Obtain the length of the data stored in a record.
@param xid the transaction id.
@param rid the record of interest. The size field will be ignored,
allowing this function to be used to probe for records in pages.
@return -1 if the record does not exist, the size of the record otherwise.
*/
int TrecordSize(int xid, recordid rid);
/** Return the number of records stored in page pageid */
int TrecordsInPage(int xid, int pageid);
#endif #endif

View file

@ -0,0 +1,89 @@
/*---
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
A linked list implementation designed to handle variable length entries, and
minimize the number of pages spanned by each list.
The data is stored using the slotted page implementation.
slot 0 is a long that points to the next page in the list.
The rest of the slots store data.
$Id $
*/
#ifndef __pageOrientedListNTA_H
#define __pageOrientedListNTA_H
typedef struct {
long page;
/* The slot of the next record to be returned. */
int slot;
} lladd_pagedList_iterator;
//recordid dereferencePagedListRID(int xid, recordid rid);
/** @return 1 if the key was already in the list. */
int TpagedListInsert(int xid, recordid list, const byte * key, int keySize, const byte * value, int valueSize);
int TpagedListFind(int xid, recordid list, const byte * key, int keySize, byte ** value);
int TpagedListRemove(int xid, recordid list, const byte * key, int keySize);
int TpagedListMove(int xid, recordid start_list, recordid end_list, const byte *key, int keySize);
/** The linked list iterator can tolerate the concurrent removal of values that
it has already returned. In the presence of such removals, the iterator
will return the keys and values present in the list as it existed when next()
was first called.
@return a new iterator initialized to the head of the list. */
lladd_pagedList_iterator * TpagedListIterator(int xid, recordid list);
/** @return 1 if there was another entry to be iterated over. 0 otherwise.
If this function returns 1, the caller must free() the malloced memory
returned via the key and value arguments.*/
int TpagedListNext(int xid, lladd_pagedList_iterator * it, byte ** key, int * keySize, byte ** value, int * valueSize);
recordid TpagedListAlloc(int xid);
void TpagedListDelete(int xid, recordid list);
Operation getPagedListInsert();
Operation getPagedListRemove();
#endif

View file

@ -46,7 +46,7 @@ terms specified in this license.
#include <stdlib.h> #include <stdlib.h>
#include "../../2pc/2pc.h" #include "../../2pc/2pc.h"
#include "../../libdfa/callbacks.h" #include "../../libdfa/callbacks.h"
#include <pbl/jbhash.h> //#include <pbl/jbhash.h>
#include "cht_message.h" #include "cht_message.h"

View file

@ -40,6 +40,9 @@ permission to use and distribute the software in accordance with the
terms specified in this license. terms specified in this license.
---*/ ---*/
/*#include <sys/types.h> */ /*#include <sys/types.h> */
#define _GNU_SOURCE
#include <lladd/common.h> #include <lladd/common.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/poll.h> #include <sys/poll.h>

View file

@ -10,6 +10,8 @@ liblladd_a_SOURCES=crc32.c common.c stats.c io.c bufferManager.c linkedlist.c op
operations/increment.c operations/prepare.c operations/set.c \ operations/increment.c operations/prepare.c operations/set.c \
operations/alloc.c operations/noop.c operations/instantSet.c \ operations/alloc.c operations/noop.c operations/instantSet.c \
page/slotted.c operations/lladdhash.c page/header.c page/fixed.c \ page/slotted.c operations/lladdhash.c page/header.c page/fixed.c \
operations/arrayList.c hash.c operations/linearHash.c operations/naiveLinearHash.c \ operations/arrayList.c hash.c operations/linearHash.c \
operations/nestedTopActions.c operations/linearHashNTA.c operations/linkedListNTA.c operations/naiveLinearHash.c operations/nestedTopActions.c \
operations/linearHashNTA.c operations/linkedListNTA.c \
operations/pageOrientedListNTA.c
AM_CFLAGS= -g -Wall -pedantic -std=gnu99 AM_CFLAGS= -g -Wall -pedantic -std=gnu99

View file

@ -213,6 +213,24 @@ recordid preAllocBlob(int xid, long blobSize) {
} }
recordid preAllocBlobFromPage(int xid, long page, long blobSize) {
/* Allocate space for the blob entry. */
DEBUG("Allocing blob (size %ld)\n", blobSize);
assert(blobSize > 0); /* Don't support zero length blobs right now... */
/* First in buffer manager. */
recordid rid = TallocFromPage(xid, page, sizeof(blob_record_t));
rid.size = blobSize;
return rid;
}
void allocBlob(int xid, Page * p, lsn_t lsn, recordid rid) { void allocBlob(int xid, Page * p, lsn_t lsn, recordid rid) {
long fileSize; long fileSize;

View file

@ -78,6 +78,7 @@ typedef struct {
recordid preAllocBlob(int xid, long blobsize); recordid preAllocBlob(int xid, long blobsize);
recordid preAllocBlobFromPage(int xid, long page, long blobsize);
/** /**
Allocate a blob of size blobSize. Allocate a blob of size blobSize.

View file

@ -109,6 +109,7 @@ recordid Talloc(int xid, long size) {
recordid rid; recordid rid;
Page * p = NULL; Page * p = NULL;
if(size >= BLOB_THRESHOLD_SIZE) { if(size >= BLOB_THRESHOLD_SIZE) {
/**@todo is it OK that Talloc doesn't pin the page when a blob is alloced?*/
rid = preAllocBlob(xid, size); rid = preAllocBlob(xid, size);
} else { } else {
pthread_mutex_lock(&talloc_mutex); pthread_mutex_lock(&talloc_mutex);
@ -133,6 +134,29 @@ recordid Talloc(int xid, long size) {
} }
recordid TallocFromPage(int xid, long page, long size) {
recordid rid;
Page * p = NULL;
if(size >= BLOB_THRESHOLD_SIZE) {
rid = preAllocBlobFromPage(xid, page, size);
} else {
pthread_mutex_lock(&talloc_mutex);
rid = slottedPreRallocFromPage(xid, page, size, &p);
assert(p != NULL);
}
Tupdate(xid,rid, NULL, OPERATION_ALLOC);
if(p != NULL) {
/* release the page that preRallocFromPage pinned for us. */
/* @todo alloc.c pins multiple pages -> Will deadlock with small buffer sizes.. */
releasePage(p);
pthread_mutex_unlock(&talloc_mutex);
}
return rid;
}
void Tdealloc(int xid, recordid rid) { void Tdealloc(int xid, recordid rid) {
void * preimage = malloc(rid.size); void * preimage = malloc(rid.size);
Page * p = loadPage(rid.page); Page * p = loadPage(rid.page);
@ -149,3 +173,20 @@ int TrecordType(int xid, recordid rid) {
releasePage(p); releasePage(p);
return ret; return ret;
} }
int TrecordSize(int xid, recordid rid) {
int ret;
Page * p = loadPage(rid.page);
ret = getRecordSize(xid, p, rid);
releasePage(p);
return ret;
}
int TrecordsInPage(int xid, int pageid) {
Page * p = loadPage(pageid);
readlock(p->rwlatch, 187);
int ret = *numslots_ptr(p);
unlock(p->rwlatch);
releasePage(p);
return ret;
}

View file

@ -0,0 +1,247 @@
#include <lladd/transactional.h>
#include "../blobManager.h"
#include "../page.h"
#include "../page/slotted.h"
#include <assert.h>
#include <string.h>
/**
Low level function that looks at the page structure, and finds the 'real' recordid
of a page oriented list rid */
/*recordid dereferencePagedListRID(int xid, recordid rid) {
Page * p = loadPage(rid.page);
while((*numslots_ptr(p)-POLL_NUM_RESERVED) <= rid.slot) {
int oldSlot = rid.slot;
oldSlot -= (*numslots_ptr(p) - POLL_NUM_RESERVED);
rid.slot = POLL_NEXT;
readRecord(xid, p , rid, &rid);
rid.slot = oldSlot;
releasePage(p);
p = loadPage(rid.page);
}
releasePage(p);
rid.slot+=POLL_NUM_RESERVED;
return rid;
}*/
recordid TpagedListAlloc(int xid) {
long page = TpageAlloc(xid);
recordid list = TallocFromPage(xid, page, sizeof(long));
long zero = 0;
Tset(xid, list, &zero);
assert(list.slot == 0);
assert(list.size == sizeof(long));
return list;
}
int TpagedListInsert(int xid, recordid list, const byte * key, int keySize, const byte * value, int valueSize) {
int ret = 0;
// if find in list, return 1
byte * val;
if(keySize == TpagedListFind(xid, list, key, keySize, &val)) {
free(val);
ret = 1;
int removed = TpagedListRemove(xid, list, key, keySize);
assert(removed);
// delete from list
}
Page * p = loadPage(list.page);
int recordSize = (sizeof(short)+keySize+valueSize);
int isBlob = recordSize >= BLOB_THRESHOLD_SIZE;
int realSize = recordSize;
if(isBlob) {
recordSize = sizeof(blob_record_t);
}
while(slottedFreespace(p) < recordSize) {
// load next page, update some rid somewhere
list.slot = 0;
list.size = sizeof(long);
long nextPage;
readRecord(xid, p, list, &nextPage);
// printf("+ page = %d nextpage=%ld freespace: %d recordsize: %d\n", list.page, nextPage, slottedFreespace(p), recordSize); fflush(stdout);
if(nextPage == 0) {
releasePage(p);
nextPage = TpageAlloc(xid);
Tset(xid, list, &nextPage);
p = loadPage(nextPage);
// slottedPageInitialize(p);
// ** @todo shouldn't a log entry be generated here?? */
list.page = nextPage;
assert(slottedFreespace(p) >= recordSize);
long zero = 0;
TallocFromPage(xid, list.page, sizeof(long));
Tset(xid, list, &zero);
} else {
releasePage(p);
list.page = nextPage;
p = loadPage(nextPage);
}
}
if(isBlob) {
recordSize = realSize;
}
releasePage(p);
recordid rid = TallocFromPage(xid, list.page, recordSize); // Allocates a record at a location given by the caller
short* record = malloc(recordSize);
*record = keySize;
memcpy((record+1), key, keySize);
memcpy(((char*)(record+1))+keySize, value, valueSize);
Tset(xid, rid, record);
return ret;
}
int TpagedListFind(int xid, recordid list, const byte * key, int keySize, byte ** value) {
long nextPage = 1;
while (nextPage) {
int i;
int pageCount = TrecordsInPage(xid, list.page);
// printf("%ld\n", nextPage);
fflush(stdout);
for(i = 1; i < pageCount; i++) {
recordid entry = list;
entry.slot = i;
int length = TrecordSize(xid, entry);
if(length != -1) { // then entry is defined.
short * dat = malloc(length);
entry.size = length;
Tread(xid, entry, dat);
if(*dat == keySize && !memcmp(dat+1, key, keySize)) {
int valueSize = length-keySize-sizeof(short);
*value = malloc(valueSize);
memcpy(*value, ((byte*)(dat+1))+keySize, valueSize);
free(dat);
return valueSize;
}
free(dat);
}
}
// recordid rid = list;
list.slot = 0;
list.size = sizeof(long);
Tread(xid, list, &nextPage);
list.page = nextPage;
}
return 0;
}
int TpagedListRemove(int xid, recordid list, const byte * key, int keySize) {
long nextPage = 1;
while (nextPage) {
int i;
int pageCount = TrecordsInPage(xid, list.page);
// printf("%ld\n", nextPage);
fflush(stdout);
for(i = 1; i < pageCount; i++) {
recordid entry = list;
entry.slot = i;
int length = TrecordSize(xid, entry);
if(length != -1) { // then entry is defined.
short * dat = malloc(length);
entry.size = length;
Tread(xid, entry, dat);
if(*dat == keySize && !memcmp(dat+1, key, keySize)) {
Tdealloc(xid, entry);
free(dat);
return 1;
}
free(dat);
}
}
list.slot = 0;
list.size = sizeof(long);
Tread(xid, list, &nextPage);
list.page = nextPage;
}
return 0;
}
int TpagedListMove(int xid, recordid start_list, recordid end_list, const byte *key, int keySize) {
byte * value;
int valueSize = TpagedListFind(xid, start_list, key, keySize, &value);
if(valueSize) {
int ret = TpagedListRemove(xid, start_list, key, keySize);
assert(ret);
ret = TpagedListInsert(xid, end_list, key, keySize, value, valueSize);
assert(!ret);
free(value);
return 1;
} else {
return 0;
}
}
lladd_pagedList_iterator * TpagedListIterator(int xid, recordid list) {
lladd_pagedList_iterator * ret = malloc(sizeof(lladd_pagedList_iterator));
ret->page = list.page;
ret->slot = 1;
return ret;
}
int TpagedListNext(int xid, lladd_pagedList_iterator * it,
byte ** key, int * keySize,
byte ** value, int * valueSize) {
// printf("next: page %d slot %d\n", it->page, it->slot);
recordid rid;
while(it->page) {
while(it->slot < TrecordsInPage(xid, it->page)) {
rid.page = it->page;
rid.slot = it->slot;
rid.size=TrecordSize(xid, rid);
if(rid.size != -1) {
// found entry!
byte * dat = malloc(rid.size);
Tread(xid, rid, dat);
// populate / alloc pointers passed in by caller.
*keySize = *(short*)dat;
*valueSize = rid.size - *keySize - sizeof(short);
*key = malloc(*keySize);
*value = malloc(*valueSize);
memcpy(*key, ((short*)dat)+1, *keySize);
memcpy(*value, ((byte*)(((short*)dat)+1)) + *keySize, *valueSize);
free(dat);
it->slot++;
return 1;
}
it->slot++;
}
rid.page = it->page;
rid.slot = 0;
rid.size = sizeof(long);
Tread(xid, rid, &(it->page));
it->slot = 1;
}
free(it);
return 0;
}

View file

@ -315,31 +315,27 @@ void readRecordUnlocked(int xid, Page * p, recordid rid, void *buf) {
*/ */
int getRecordTypeUnlocked(int xid, Page * p, recordid rid) { int getRecordTypeUnlocked(int xid, Page * p, recordid rid) {
assert(rid.page == p->id); assert(rid.page == p->id);
int page_type = *page_type_ptr(p); int page_type = *page_type_ptr(p);
if(page_type == UNINITIALIZED_PAGE) {
return UNINITIALIZED_RECORD;
if(page_type == UNINITIALIZED_PAGE) { } else if(page_type == SLOTTED_PAGE) {
return UNINITIALIZED_RECORD; if(*numslots_ptr(p) <= rid.slot || *slot_length_ptr(p, rid.slot) == INVALID_SLOT) {
return UNINITIALIZED_PAGE;
} else if(rid.size > BLOB_THRESHOLD_SIZE) { } else if(*slot_length_ptr(p, rid.slot) == BLOB_REC_SIZE) {
// printf("%d , %d\n", *numslots_ptr(p), *slot_length_ptr(p, rid.slot)); return BLOB_RECORD;
return(*numslots_ptr(p) > rid.slot && } else {
*slot_length_ptr(p, rid.slot) == BLOB_REC_SIZE) ? return SLOTTED_RECORD;
BLOB_RECORD : UNINITIALIZED_RECORD; }
} else if(page_type == FIXED_PAGE || page_type == ARRAY_LIST_PAGE) {
} else if(page_type == SLOTTED_PAGE) { return (fixedPageCount(p) > rid.slot) ?
return (*numslots_ptr(p) > rid.slot && FIXED_RECORD : UNINITIALIZED_RECORD;
*slot_length_ptr(p, rid.slot) != INVALID_SLOT) ? } else {
SLOTTED_RECORD : UNINITIALIZED_RECORD; abort();
return UNINITIALIZED_RECORD;
} else if(page_type == FIXED_PAGE || page_type == ARRAY_LIST_PAGE) { }
return (fixedPageCount(p) > rid.slot) ?
FIXED_RECORD : UNINITIALIZED_RECORD;
} else {
abort();
return UNINITIALIZED_RECORD;
}
} }
int getRecordType(int xid, Page * p, recordid rid) { int getRecordType(int xid, Page * p, recordid rid) {
@ -348,6 +344,20 @@ int getRecordType(int xid, Page * p, recordid rid) {
unlock(p->rwlatch); unlock(p->rwlatch);
return ret; return ret;
} }
/** @todo implemenet getRecordLength for blobs and fixed length pages. */
int getRecordSize(int xid, Page * p, recordid rid) {
readlock(p->rwlatch, 353);
int ret = getRecordTypeUnlocked(xid, p, rid);
if(ret == UNINITIALIZED_RECORD) {
ret = -1;
} else if(ret == SLOTTED_RECORD) {
ret = *slot_length_ptr(p, rid.slot);
} else {
abort(); // unimplemented for fixed length pages and blobs.
}
unlock(p->rwlatch);
return ret;
}
void writeRecordUnlocked(int xid, Page * p, lsn_t lsn, recordid rid, const void *dat) { void writeRecordUnlocked(int xid, Page * p, lsn_t lsn, recordid rid, const void *dat) {

View file

@ -298,12 +298,26 @@ void pageRealloc(Page * p, int id);
/*int pageAlloc() ;*/ /*int pageAlloc() ;*/
/** /**
obtains the type of the record pointed to by rid. obtains the type of the record pointed to by rid.
@return UNINITIALIZED_RECORD, BLOB_RECORD, SLOTTED_RECORD, or FIXED_RECORD.
*/ */
int getRecordType(int xid, Page * p, recordid rid); int getRecordType(int xid, Page * p, recordid rid);
int getRecordSize(int xid, Page * p, recordid rid);
/** /**
same as getRecordType(), but does not obtain a lock. same as getRecordType(), but does not obtain a lock.
*/ */
int getRecordTypeUnlocked(int xid, Page * p, recordid rid); int getRecordTypeUnlocked(int xid, Page * p, recordid rid);
/**
return the length of the record rid. (the rid parameter's size field will be ignored)
@todo implement getRecordLength for blobs and fixed length pages.
@return -1 if the field does not exist, the size of the field otherwise.
*/
int getRecordLength(int xid, Page * p, recordid rid);
END_C_DECLS END_C_DECLS

View file

@ -160,17 +160,12 @@ int slottedFreespace(Page * page) {
recordid slottedPreRalloc(int xid, long size, Page ** pp) { recordid slottedPreRalloc(int xid, long size, Page ** pp) {
recordid ret; recordid ret;
/* Page * p; */
/* DEBUG("Rallocing record of size %ld\n", (long int)size); */
assert(size < BLOB_THRESHOLD_SIZE); assert(size < BLOB_THRESHOLD_SIZE);
/* pthread_mutex_lock(&lastFreepage_mutex); */
/** @todo is ((unsigned int) foo) == -1 portable? Gotta love C.*/ /** @todo is ((unsigned int) foo) == -1 portable? Gotta love C.*/
/*printf("lastFreepage %d\n", lastFreepage); fflush(NULL); */
if(lastFreepage == -1) { if(lastFreepage == -1) {
lastFreepage = TpageAlloc(xid/*, SLOTTED_PAGE*/); lastFreepage = TpageAlloc(xid);
*pp = loadPage(lastFreepage); *pp = loadPage(lastFreepage);
assert(*page_type_ptr(*pp) == UNINITIALIZED_PAGE); assert(*page_type_ptr(*pp) == UNINITIALIZED_PAGE);
slottedPageInitialize(*pp); slottedPageInitialize(*pp);
@ -180,23 +175,33 @@ recordid slottedPreRalloc(int xid, long size, Page ** pp) {
if(slottedFreespace(*pp) < size ) { if(slottedFreespace(*pp) < size ) {
releasePage(*pp); releasePage(*pp);
lastFreepage = TpageAlloc(xid/*, SLOTTED_PAGE*/); lastFreepage = TpageAlloc(xid);
*pp = loadPage(lastFreepage); *pp = loadPage(lastFreepage);
slottedPageInitialize(*pp); slottedPageInitialize(*pp);
} }
ret = slottedRawRalloc(*pp, size); ret = slottedRawRalloc(*pp, size);
/* releasePage(p); */ /* This gets called in Talloc() now. That prevents the page from being prematurely stolen. */
/* pthread_mutex_unlock(&lastFreepage_mutex); */
DEBUG("alloced rid = {%d, %d, %ld}\n", ret.page, ret.slot, ret.size); DEBUG("alloced rid = {%d, %d, %ld}\n", ret.page, ret.slot, ret.size);
return ret; return ret;
} }
recordid slottedPreRallocFromPage(int xid, long page, long size, Page **pp) {
recordid ret;
*pp = loadPage(page);
assert(slottedFreespace(*pp) >= size);
if(*page_type_ptr(*pp) == UNINITIALIZED_PAGE) {
slottedPageInitialize(*pp);
}
assert(*page_type_ptr(*pp) == SLOTTED_PAGE);
ret = slottedRawRalloc(*pp, size);
return ret;
}
recordid slottedRawRalloc(Page * page, int size) { recordid slottedRawRalloc(Page * page, int size) {

View file

@ -92,6 +92,12 @@ void slottedPageInitialize(Page * p);
* *
*/ */
recordid slottedPreRalloc(int xid, long size, Page**p); recordid slottedPreRalloc(int xid, long size, Page**p);
/**
Identical to slottedPreRalloc, but allows the user to specify which page the
record should be allocated in.
*/
recordid slottedPreRallocFromPage(int xid, long page, long size, Page**p);
/** /**
* The second phase of slot allocation. Called after the log entry * The second phase of slot allocation. Called after the log entry
* has been produced, and during recovery. * has been produced, and during recovery.

View file

@ -39,10 +39,10 @@ authors grant the U.S. Government and others acting in its behalf
permission to use and distribute the software in accordance with the permission to use and distribute the software in accordance with the
terms specified in this license. terms specified in this license.
---*/ ---*/
#include <string.h>
#include "../../src/apps/cht/cht.h" #include "../../src/apps/cht/cht.h"
#include <assert.h> #include <assert.h>
#include <string.h>
/** Thanks, jbhtsimple.c!! */ /** Thanks, jbhtsimple.c!! */

View file

@ -1,11 +1,11 @@
INCLUDES = @CHECK_CFLAGS@ INCLUDES = @CHECK_CFLAGS@
if HAVE_CHECK if HAVE_CHECK
## Had to disable check_lht because lht needs to be rewritten. ## Had to disable check_lht because lht needs to be rewritten.
TESTS = check_logEntry check_logWriter check_page check_operations check_transactional2 check_recovery check_blobRecovery check_bufferManager check_indirect check_lladdhash check_pageOperations check_linearHash check_logicalLinearHash check_header check_linkedListNTA check_linearHashNTA TESTS = check_logEntry check_logWriter check_page check_operations check_transactional2 check_recovery check_blobRecovery check_bufferManager check_indirect check_lladdhash check_pageOperations check_linearHash check_logicalLinearHash check_header check_linkedListNTA check_linearHashNTA check_pageOrientedList
else else
TESTS = TESTS =
endif endif
noinst_PROGRAMS = $(TESTS) noinst_PROGRAMS = $(TESTS)
LDADD = @CHECK_LIBS@ $(top_builddir)/src/lladd/liblladd.a $(top_builddir)/src/pbl/libpbl.a $(top_builddir)/src/libdfa/librw.a # -lefence LDADD = @CHECK_LIBS@ $(top_builddir)/src/lladd/liblladd.a $(top_builddir)/src/pbl/libpbl.a $(top_builddir)/src/libdfa/librw.a # -lefence
CLEANFILES = check_lht.log check_logEntry.log storefile.txt logfile.txt blob0_file.txt blob1_file.txt check_blobRecovery.log check_logWriter.log check_operations.log check_recovery.log check_transactional2.log check_page.log check_bufferManager.log check_indirect.log check_bufferMananger.log check_lladdhash.log check_pageOperations.log check_linearhash.log check_linkedListNTA.log check_linearHashNTA.log CLEANFILES = check_lht.log check_logEntry.log storefile.txt logfile.txt blob0_file.txt blob1_file.txt check_blobRecovery.log check_logWriter.log check_operations.log check_recovery.log check_transactional2.log check_page.log check_bufferManager.log check_indirect.log check_bufferMananger.log check_lladdhash.log check_pageOperations.log check_linearhash.log check_linkedListNTA.log check_linearHashNTA.log check_pageOrientedListNTA.log
AM_CFLAGS= -g -Wall -pedantic -std=gnu99 AM_CFLAGS= -g -Wall -pedantic -std=gnu99

View file

@ -208,7 +208,7 @@ START_TEST(transactionalLinearHashTest)
int xid = Tbegin(); int xid = Tbegin();
recordid foo = Talloc(xid, 1); Talloc(xid, 1); // discard alloced rid...
// printf("%d %d %ld\n", foo.page, foo.slot, foo.size); // printf("%d %d %ld\n", foo.page, foo.slot, foo.size);

View file

@ -399,11 +399,9 @@ START_TEST(pageCheckSlotTypeTest) {
assert(getRecordType(xid, p, bad) == UNINITIALIZED_RECORD); assert(getRecordType(xid, p, bad) == UNINITIALIZED_RECORD);
bad.size = 100000; bad.size = 100000;
assert(getRecordType(xid, p, bad) == UNINITIALIZED_RECORD); assert(getRecordType(xid, p, bad) == UNINITIALIZED_RECORD);
/** @todo this test could be better... The behavior for getRecordType in this /** getRecordType now ignores the size field, so this (correctly) returns SLOTTED_RECORD */
case (valid slot, invalid size) is a bit ambiguous. Maybe an INVALID_RECORDID
would be an appropriate return value... */
bad.slot = slot.slot; bad.slot = slot.slot;
assert(getRecordType(xid, p, bad) == UNINITIALIZED_RECORD); assert(getRecordType(xid, p, bad) == SLOTTED_RECORD);
releasePage(p); releasePage(p);
@ -447,11 +445,9 @@ START_TEST(pageTrecordTypeTest) {
assert(TrecordType(xid, bad) == UNINITIALIZED_RECORD); assert(TrecordType(xid, bad) == UNINITIALIZED_RECORD);
bad.size = 100000; bad.size = 100000;
assert(TrecordType(xid, bad) == UNINITIALIZED_RECORD); assert(TrecordType(xid, bad) == UNINITIALIZED_RECORD);
/** @todo this test could be better... The behavior for getRecordType in this
case (valid slot, invalid size) is a bit ambiguous. Maybe an INVALID_RECORDID
would be an appropriate return value... */
bad.slot = slot.slot; bad.slot = slot.slot;
assert(TrecordType(xid, bad) == UNINITIALIZED_RECORD); assert(TrecordType(xid, bad) == SLOTTED_RECORD);
Tcommit(xid); Tcommit(xid);

View file

@ -0,0 +1,195 @@
/*---
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.
---*/
#include <config.h>
#include <check.h>
#include <lladd/transactional.h>
#include <assert.h>
#include "../check_includes.h"
#define LOG_NAME "check_pageOrientedListNTA.log"
/** @test */
#define NUM_ENTRIES 2000
START_TEST(pagedListCheck) {
Tinit();
int xid = Tbegin();
recordid list = TpagedListAlloc(xid);
int a;
recordid b;
int i;
printf("\n");
for(i = 0; i < NUM_ENTRIES; i++) {
if(!(i % (NUM_ENTRIES/10))) {
printf("."); fflush(stdout);
}
a = i;
b.page = i+1;
b.slot = i+2;
b.size = i+3;
int ret = TpagedListInsert(xid, list, (byte*)&a, sizeof(int), (byte*)&b, sizeof(recordid));
assert(!ret);
recordid * bb;
ret = TpagedListFind(xid, list, (byte*)&a, sizeof(int), (byte**)&bb);
assert(ret == sizeof(recordid));
assert(!memcmp(bb, &b, sizeof(recordid)));
}
Tcommit(xid);
printf("\n");
xid = Tbegin();
for(i = 0; i < NUM_ENTRIES; i++ ) {
if(!(i % (NUM_ENTRIES/10))) {
printf("."); fflush(stdout);
}
a = i;
b.page = i+1;
b.slot = i+2;
b.size = i+3;
recordid * bb;
int ret = TpagedListFind(xid, list, (byte*)&a, sizeof(int), (byte**)&bb);
assert(ret == sizeof(recordid));
assert(!memcmp(bb, &b, sizeof(recordid)));
if(!(i % 10)) {
ret = TpagedListRemove(xid, list, (byte*)&a, sizeof(int));
assert(ret);
free(bb);
bb = 0;
ret = TpagedListFind(xid, list, (byte*)&a, sizeof(int), (byte**)&bb);
assert(!ret);
assert(!bb);
}
}
Tabort(xid);
xid = Tbegin();
printf("\n");
for(i = 0; i < NUM_ENTRIES; i++) {
if(!(i % (NUM_ENTRIES/10))) {
printf("."); fflush(stdout);
}
a = i;
b.page = i+1;
b.slot = i+2;
b.size = i+3;
recordid * bb;
int ret = TpagedListFind(xid, list, (byte*)&a, sizeof(int), (byte**)&bb);
assert(ret == sizeof(recordid));
assert(!memcmp(bb, &b, sizeof(recordid)));
}
byte * seen = calloc(NUM_ENTRIES, sizeof(byte));
lladd_pagedList_iterator * it = TpagedListIterator(xid, list);
int keySize;
int valueSize;
int * key = 0;
recordid * value = 0;
while(TpagedListNext(xid, it, (byte**)&key, &keySize, (byte**)&value, &valueSize)) {
assert(!seen[*key]);
seen[*key] = 1;
assert(value->page == *key+1);
assert(value->slot == *key+2);
assert(value->size == *key+3);
free(key);
free(value);
key = 0;
value = 0;
}
for(i = 0; i < NUM_ENTRIES; i++) {
assert(seen[i] == 1);
}
Tcommit(xid);
Tdeinit();
} END_TEST
Suite * check_suite(void) {
Suite *s = suite_create("pageOrientedList");
/* Begin a new test */
TCase *tc = tcase_create("pageOrientedList");
/* Sub tests are added, one per line, here */
tcase_add_test(tc, pagedListCheck);
/* --------------------------------------------- */
tcase_add_checked_fixture(tc, setup, teardown);
suite_add_tcase(s, tc);
return s;
}
#include "../check_setup.h"