#include <stdio.h>
#include <stdlib.h>
+#include "tlog.h"
+#include "tmalloc.h"
#include "psort.h"
#define LENARR (1<<10)
int inserted=0;
EXMPL **aptr;
+ opentlog( TL_OPEN_STDERR, TL_DEBUG, NULL);
+
if ( PS_init( &sobj, LIMIT, exstr_cmp, exstr_free ) ) {
fprintf(stderr,"No memory\n");
return 1;
printf("Test insert:\n");
for(i=0;i<LENARR;i++) {
if ( ! ptr ) {
- ptr = (EXMPL*)malloc( sizeof(EXMPL) );
- if ( ! ptr ) {
- fprintf(stderr,"No memory\n");
- return 1;
- }
- ptr->value=(char*)malloc( 64 );
- if ( ! ptr->value ) {
- fprintf(stderr,"No memory\n");
- return 1;
- }
+ ptr = (EXMPL*)tmalloc( sizeof(EXMPL) );
+ ptr->value=(char*)tmalloc( 64 );
}
ptr->id = random() % LENARR;
sprintf( ptr->value, "Value: %d, startnum: %d", ptr->id, i );
srandom(1);
printf("Test bulk insert:\n");
- aptr = (EXMPL**)malloc( sizeof(EXMPL*) * LENARR );
- if ( ! aptr ) {
- fprintf(stderr,"No memory\n");
- return 1;
- }
+ aptr = (EXMPL**)tmalloc( sizeof(EXMPL*) * LENARR );
for(i=0;i<LENARR;i++) {
- aptr[i] = (EXMPL*)malloc( sizeof(EXMPL) );
- if ( ! aptr[i] ) {
- fprintf(stderr,"No memory\n");
- return 1;
- }
- aptr[i]->value = (char*)malloc( 64 );
- if ( ! aptr[i]->value ) {
- fprintf(stderr,"No memory\n");
- return 1;
- }
+ aptr[i] = (EXMPL*)tmalloc( sizeof(EXMPL) );
+ aptr[i]->value = (char*)tmalloc( 64 );
aptr[i]->id = random() % LENARR;
sprintf( aptr[i]->value, "Value: %d, startnum: %d", aptr[i]->id, i );
}
fprintf(stderr,"No memory\n");
return 1;
}
- ptr = (EXMPL*)malloc( sizeof(EXMPL) * LENARR );
- if ( ! ptr ) {
- fprintf(stderr,"No memory\n");
- return 1;
- }
+ ptr = (EXMPL*)tmalloc( sizeof(EXMPL) * LENARR );
for(i=0;i<LENARR;i++) {
- ptr[i].value = (char*)malloc( 64 );
- if ( ! ptr[i].value ) {
- fprintf(stderr,"No memory\n");
- return 1;
- }
+ ptr[i].value = (char*)tmalloc( 64 );
ptr[i].id = random() % LENARR;
sprintf( ptr[i].value, "Value: %d, startnum: %d", ptr[i].id, i );
}
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
-#include <sys/time.h>
#include "tmalloc.h"
#include "tlog.h"
#include "tbtree.h"
+#define NOTFOUND 0
+#define FOUND 1
+
static int TBTReadPage(TBTree *db, u_int32_t pagenumber, TBTMemPage **page) ;
static int TBTWritePage(TBTree *db, TBTMemPage *page) ;
static int TBTNewPage(TBTree *db, TBTMemPage **page) ;
+
+
int
TBTOpen(TBTree *db, char *file) {
off_t offset;
if ( db->npage ) {
db->Cache=(TBTMemPage**)t0malloc( sizeof(TBTMemPage*)*db->npage );
- db->TimeCache=(TBTMemPage**)t0malloc( sizeof(TBTMemPage*)*db->npage );
db->curpage=0;
}
tfree( db->Cache[i] );
tfree( db->Cache );
- tfree( db->TimeCache );
}
flock( db->fd, LOCK_UN );
return (rc) ? TBT_ERROR : TBT_OK;
}
+static int
+findInCache(TBTree *db, u_int32_t pagenumber, int *pos, TBTMemPage **StopLow, TBTMemPage **StopHigh) {
+ TBTMemPage **StopMiddle;
+
+ /* Loop invariant: StopLow <= StopMiddle < StopHigh */
+ while (StopLow < StopHigh) {
+ StopMiddle = StopLow + ( ( StopHigh - StopLow ) >> 1 );
+
+ if ( (*StopMiddle)->pagenumber == pagenumber ) {
+ *pos = StopMiddle - db->Cache;
+ return FOUND;
+ } else if ( (*StopMiddle)->pagenumber < pagenumber )
+ StopLow = StopMiddle + 1;
+ else
+ StopHigh = StopMiddle;
+ }
+
+ *pos = StopHigh - db->Cache;
+ return NOTFOUND;
+}
+
static TBTMemPage*
-PageAlloc(TBTree *db, int *pos) {
+PageAlloc(TBTree *db, int *posincache) {
TBTMemPage *page;
+ *posincache = -1;
if ( db->curpage < db->npage ) {
- page = db->Cache[db->curpage] = db->TimeCache[db->curpage] = (TBTMemPage*)t0malloc(sizeof(TBTMemPage));
- *pos = db->curpage;
+ page = db->Cache[db->curpage] = (TBTMemPage*)tmalloc(sizeof(TBTMemPage));
+ memset( page, 0, TBTMEMPAGEHDRSZ );
page->iscached=1;
+ if ( db->curpage == 0 ) {
+ db->TimeCache = db->TimeCacheLast = page;
+ } else {
+ db->TimeCacheLast->next = page;
+ page->prev = db->TimeCacheLast;
+ db->TimeCacheLast = page;
+ }
+ *posincache = db->curpage;
db->curpage++;
} else if ( db->npage == 0 ) {
- page = (TBTMemPage*)t0malloc(sizeof(TBTMemPage));
+ page = (TBTMemPage*)tmalloc(sizeof(TBTMemPage));
+ memset( page, 0, TBTMEMPAGEHDRSZ );
} else {
- u_int32_t i;
- for( i=0; i<db->curpage && db->TimeCache[i]->islocked; i++ );
- if ( i == db->curpage ) { /*all pages locked*/
+ page = db->TimeCache;
+ while( page->next && page->islocked )
+ page = page->next;
+ if ( page==db->TimeCacheLast && page->islocked ) { /*all pages locked*/
/*tlog(TL_WARN,"TBTReadPage: all pages in cache locked, increase number of cached pages");*/
- page = (TBTMemPage*)t0malloc(sizeof(TBTMemPage));
+ page = (TBTMemPage*)tmalloc(sizeof(TBTMemPage));
+ memset( page, 0, TBTMEMPAGEHDRSZ );
} else {
- page = db->TimeCache[i];
if ( !page->issynced )
if ( TBTWritePage(db, page) )
return NULL;
- memset(page,0,sizeof(TBTMemPage));
+ if( findInCache(db, page->pagenumber, posincache, db->Cache, db->Cache + db->curpage) != FOUND )
+ tlog(TL_CRIT,"PageAlloc: something wrong: no page with pagenumber %d in cache", page->pagenumber);
+ memset( page, 0, TBTMEMPAGEHDRSZ );
page->iscached=1;
- *pos=i;
+ if ( page != db->TimeCacheLast ) {
+ if ( page->prev )
+ page->prev->next = page->next;
+ if ( page->next )
+ page->next->prev = page->prev;
+ db->TimeCacheLast->next = page;
+ page->prev = db->TimeCacheLast;
+ db->TimeCacheLast = page;
+ page->next = NULL;
+ }
}
}
}
static void
-moveFirstTime(TBTree *db, int pos) {
- TBTMemPage *ptr;
-
- if ( pos < 0 )
- return;
- if (pos+1==db->curpage )
- return;
-
- ptr = db->TimeCache[pos];
- memmove( db->TimeCache + pos , db->TimeCache + pos + 1, sizeof(TBTMemPage*)*(db->curpage-pos-1) );
- db->TimeCache[db->curpage-1] = ptr;
-}
-
-static void
-findAndMoveFirstTime(TBTree *db, TBTMemPage *page) {
- int pos;
- for(pos=0;pos<db->curpage;pos++)
- if ( page==db->TimeCache[pos] ) {
- moveFirstTime(db,pos);
- break;
- }
- tassert( pos<db->curpage );
-}
-
-static void
-findAndMovePN(TBTree *db, TBTMemPage *page) {
- int pos;
+findAndMovePN(TBTree *db, TBTMemPage *page, int pos) {
+ int newpos;
if ( db->curpage < 2 )
return;
- for(pos=0;pos<db->curpage;pos++)
- if ( page==db->Cache[pos] )
- break;
- tassert( pos<db->curpage );
-
- while(1) {
- if ( pos+1 != db->curpage && db->Cache[pos+1]->pagenumber < page->pagenumber ) {
- db->Cache[pos] = db->Cache[pos+1];
- db->Cache[pos+1] = page;
- pos++;
- } else if ( pos!=0 && db->Cache[pos-1]->pagenumber > page->pagenumber ) {
- db->Cache[pos] = db->Cache[pos-1];
- db->Cache[pos-1] = page;
- pos--;
- } else
- break;
- }
-}
-
-static int
-cmpNPage(const void *a, const void *b) {
- if ( (*(TBTMemPage**)a)->pagenumber == (*(TBTMemPage**)b)->pagenumber )
- return 0;
- return ( (*(TBTMemPage**)a)->pagenumber > (*(TBTMemPage**)b)->pagenumber ) ? 1 : -1;
+ if ( pos < 0 )
+ pos = db->curpage-1;
+ tassert( pos < db->curpage && db->Cache[pos]==page );
+
+ if ( pos+1 != db->curpage && db->Cache[pos+1]->pagenumber < page->pagenumber ) {
+ if ( findInCache(db, page->pagenumber, &newpos, db->Cache + pos + 1, db->Cache + db->curpage )!=NOTFOUND)
+ tlog(TL_CRIT,"findAndMovePN: Something wrong, duplicate page with pagenumber %d", page->pagenumber);
+ memmove( db->Cache + pos, db->Cache + pos + 1, (newpos-pos-1)*sizeof(TBTMemPage**) );
+ db->Cache[newpos-1] = page;
+ } else if ( pos!=0 && db->Cache[pos-1]->pagenumber > page->pagenumber ) {
+ if( findInCache(db, page->pagenumber, &newpos, db->Cache, db->Cache + pos )!=NOTFOUND);
+ tlog(TL_CRIT,"findAndMovePN: Something wrong, duplicate page with pagenumber %d", page->pagenumber);
+ memmove( db->Cache + newpos + 1, db->Cache + newpos, (pos-newpos)*sizeof(TBTMemPage**));
+ db->Cache[newpos] = page;
+ }
}
static int
TBTReadPage(TBTree *db, u_int32_t pagenumber, TBTMemPage **page) {
- TBTMemPage *ptr, key, **res;
- int rc;
- int pos;
-
- ptr=&key;
- key.pagenumber = pagenumber;
+ int rc, pos=0;
- res = (TBTMemPage**)bsearch(&ptr, db->Cache, db->curpage, sizeof(TBTMemPage*), cmpNPage);
- if ( res ) {
+ if ( findInCache(db, pagenumber, &pos, db->Cache, db->Cache + db->curpage)==FOUND ) {
db->cachehits++;
- *page=*res;
- findAndMoveFirstTime(db, *page);
+ *page=db->Cache[pos];
+ if ( *page != db->TimeCacheLast ) {
+ if ( (*page)->prev )
+ (*page)->prev->next = (*page)->next;
+ if ( (*page)->next )
+ (*page)->next->prev = (*page)->prev;
+ db->TimeCacheLast->next = (*page);
+ (*page)->prev = db->TimeCacheLast;
+ db->TimeCacheLast = *page;
+ (*page)->next = NULL;
+ }
} else {
off_t offset = (off_t)pagenumber * (off_t)TBTREEPAGESIZE;
-
- if( (*page = PageAlloc(db,&pos))==NULL )
+
+ if( (*page = PageAlloc(db, &pos))==NULL )
return TBT_ERROR;
if ( lseek(db->fd, offset, SEEK_SET) != offset ) {
tlog(TL_CRIT,"TBTReadPage: read failed: %s %d %d",strerror(errno), pagenumber, offset);
return TBT_ERROR;
}
- if ( (*page)->iscached ) {
- moveFirstTime(db, pos);
- findAndMovePN(db, *page);
- }
+ if ( (*page)->iscached )
+ findAndMovePN(db, *page, pos);
}
db->pageread++;
- gettimeofday( &( (*page)->last ), NULL );
-
return TBT_OK;
}
static int
TBTNewPage(TBTree *db, TBTMemPage **page) {
int pos;
+
if ( db->lastpagenumber==0 ) {
off_t offset;
if ( (offset=lseek(db->fd, 0, SEEK_END)) < 0 ) {
db->lastpagenumber = offset/TBTREEPAGESIZE;
}
- if( (*page = PageAlloc(db,&pos))==NULL )
+ if( (*page = PageAlloc(db, &pos))==NULL )
return TBT_ERROR;
+
(*page)->pagenumber = db->lastpagenumber;
(*page)->issynced=0;
(*page)->islocked=1;
db->lastpagenumber++;
- memset( &((*page)->page), 0, sizeof(TBTPAGEHDRSZ));
+ memset( &((*page)->page), 0, TBTMEMPAGEHDRSZ);
(*page)->page.freespace = TBTREEPAGESIZE-TBTPAGEHDRSZ;
- gettimeofday( &( (*page)->last ), NULL );
- if ( (*page)->iscached ) {
- moveFirstTime(db, pos);
- findAndMovePN(db, *page);
- }
+ if ( (*page)->iscached )
+ findAndMovePN(db, *page, pos);
return TBT_OK;
}
-#define NOTFOUND 0
-#define FOUND 1
-
static void
printValue(u_int32_t len, char *ptr) {
putchar('\'');
TBTMemPage *page;
if ( TBTReadPage(db, pagenumber, &page) ) {
- fprintf(stderr,"BEDA %d\n", pagenumber);
+ tlog(TL_CRIT,"BEDA %d\n", pagenumber);
return;
}