Implemented pageOrientedList, also did some bug fixing, and added some support functions to alloc.c
This commit is contained in:
parent
05934d296a
commit
17f76264aa
20 changed files with 826 additions and 86 deletions
149
lladd.pws
149
lladd.pws
|
@ -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
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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
|
||||||
|
|
89
lladd/operations/pageOrientedListNTA.h
Normal file
89
lladd/operations/pageOrientedListNTA.h
Normal 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
|
|
@ -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"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
247
src/lladd/operations/pageOrientedListNTA.c
Normal file
247
src/lladd/operations/pageOrientedListNTA.c
Normal 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;
|
||||||
|
|
||||||
|
}
|
|
@ -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) {
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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!! */
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
195
test/lladd/check_pageOrientedList.c
Normal file
195
test/lladd/check_pageOrientedList.c
Normal 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"
|
Loading…
Reference in a new issue