while(ptr && ptr->pagenumber != pagenumber)
ptr = ptr->link;
- return ptr;;
+ return ptr;
}
static void
TBTPointer *ptr= (TBTPointer*)(page->data+db->pointersize*i);
for(j=0;j<follow+2;j++)
putchar(' ');
- printf("i:%d(%d) kl:%d ko:%d ",
- i, (int)ptr,
+ printf("i:%d(%p) kl:%d ko:%d ",
+ i, (void*)ptr,
(db->keylen) ? db->keylen : ptr->key.varlen.length,
(db->keylen) ? 0 : ptr->key.varlen.offset
);
if ( db->keylen ) {
if ( key->value )
memcpy( ptr->key.fixed.key, key->value, db->keylen );
- else
- memset( ptr->key.fixed.key, 0, db->keylen );
} else {
page->freespace -= PTRALIGN(key->length);
ptr->key.varlen.length = key->length;
ptr->pointer.internal.link = pagenumber;
}
-
static void
deleteKV(TBTree *db, TBTPage *page, TBTPointer **ptrs, u_int32_t num) {
- static char buf[TBTREEPAGESIZE];
- char *bufptr = buf;
TBTPointer *ptr = (TBTPointer*)page->data, *tmp, **ptrptr = ptrs;
- u_int32_t i, start;
+ u_int32_t i;
+
/* suppose ptrs are ordered! */
tmp = ptr;
while( ptrptr - ptrs < num && (char*)ptr - page->data < db->pointersize*page->npointer ) {
page->npointer-=num;
- tmp = (TBTPointer*)page->data;
- start = page->npointer * db->pointersize + page->freespace;
- for(i=0;i<page->npointer;i++) {
- if ( page->isleaf ) {
- memcpy( bufptr, page->data + tmp->pointer.leaf.offset, tmp->pointer.leaf.length );
- tmp->pointer.leaf.offset = start + (bufptr-buf);
- bufptr+=PTRALIGN(tmp->pointer.leaf.length);
+ if ( page->isleaf || db->keylen == 0 ) {
+ static char buf[TBTREEPAGESIZE];
+ char *bufptr = buf;
+ u_int32_t start = page->npointer * db->pointersize + page->freespace;
+
+ tmp = (TBTPointer*)page->data;
+ for(i=0;i<page->npointer;i++) {
+ if ( page->isleaf ) {
+ memcpy( bufptr, page->data + tmp->pointer.leaf.offset, tmp->pointer.leaf.length );
+ tmp->pointer.leaf.offset = start + (bufptr-buf);
+ bufptr+=PTRALIGN(tmp->pointer.leaf.length);
+ }
+
+ if ( db->keylen == 0 ) {
+ if ( tmp->key.varlen.length )
+ memcpy( bufptr, page->data + tmp->key.varlen.offset, tmp->key.varlen.length );
+ tmp->key.varlen.offset = start + (bufptr-buf);
+ bufptr+=PTRALIGN(tmp->key.varlen.length);
+ }
+ tmp = (TBTPointer*)( (char*)tmp + db->pointersize );
}
- if ( db->keylen == 0 ) {
- if ( tmp->key.varlen.length )
- memcpy( bufptr, page->data + tmp->key.varlen.offset, tmp->key.varlen.length );
- tmp->key.varlen.offset = start + (bufptr-buf);
- bufptr+=PTRALIGN(tmp->key.varlen.length);
- }
- tmp = (TBTPointer*)( (char*)tmp + db->pointersize );
+ memcpy( page->data + start, buf, bufptr-buf );
}
-
- memcpy( page->data + start, buf, bufptr-buf );
}
static u_int32_t
return TBT_OK;
}
+int
+TBTGetFirst(TBTree *db, TBTValue *key, TBTValue *value) {
+ TBTIterator iterator;
+ int rc;
+
+ if ( (rc=TBTInitIterator(db, &iterator))!=TBT_OK )
+ return rc;
+
+ rc=TBTIterate(db, &iterator, key, value);
+
+ if ( key->value ) {
+ char * ptr;
+
+ ptr = tmalloc( key->length );
+ memcpy( ptr, key->value, key->length );
+ key->value = ptr;
+
+ ptr = tmalloc( value->length );
+ memcpy( ptr, value->value, value->length );
+ value->value = ptr;
+ }
+
+ TBTFreeIterator(db, &iterator);
+
+ return rc;
+}
+
+static int
+findLast(TBTree *db, TBTValue *key, TBTValue *value, u_int32_t pagenumber) {
+ TBTMemPage *page;
+ TBTPointer *ptr;
+ int rc=TBT_OK,i;
+
+ if ( (rc=TBTReadPage(db, pagenumber, &page)) != TBT_OK )
+ return rc;
+
+ if ( page->page.npointer==0 ) {
+ if ( !page->iscached )
+ tfree(page);
+ return TBT_OK;
+ }
+
+ page->islocked=1;
+ if ( page->page.isleaf ) {
+ ptr = (TBTPointer*)(page->page.data + db->pointersize * (page->page.npointer-1));
+
+ key->length = ( db->keylen ) ? db->keylen : ptr->key.varlen.length;
+ key->value = tmalloc( key->length );
+ memcpy( key->value, ( db->keylen ) ? ptr->key.fixed.key : page->page.data + ptr->key.varlen.offset, key->length );
+
+ value->length = ptr->pointer.leaf.length;
+ value->value = tmalloc( value->length );
+ memcpy( value->value, page->page.data + ptr->pointer.leaf.offset, value->length );
+ } else {
+ for(i=page->page.npointer-1; i>=0; i--) {
+ ptr = (TBTPointer*)( page->page.data + db->pointersize * i );
+ rc = findLast(db, key, value, ptr->pointer.internal.link);
+ if ( rc!=TBT_OK || key->value )
+ break;
+ }
+ }
+
+ page->islocked=0;
+ if ( !page->iscached )
+ tfree(page);
+
+ return rc;
+}
+
+int
+TBTGetLast(TBTree *db, TBTValue *key, TBTValue *value) {
+ memset(key, 0, sizeof(TBTValue));
+ memset(value, 0, sizeof(TBTValue));
+ return findLast(db, key, value, TBTPAGEROOT);
+}