diff options
Diffstat (limited to 'libibex/disktail.c')
-rw-r--r-- | libibex/disktail.c | 819 |
1 files changed, 0 insertions, 819 deletions
diff --git a/libibex/disktail.c b/libibex/disktail.c deleted file mode 100644 index 7d3abd10d8..0000000000 --- a/libibex/disktail.c +++ /dev/null @@ -1,819 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Copyright (C) 2000 Ximian, Inc. - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* a disk based array storage class that stores the tails of data lists - in common blocks */ - - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include <string.h> -#include <stdio.h> - -#include <glib.h> - -#include "block.h" -#include "index.h" - -#define d(x) -/*#define DEBUG*/ - -/* marker to define which root keys indicate a single length key */ -#define BLOCK_ONE (1<<BLOCK_BITS) - -/* tail blocks only contain tail data ... */ -/* and we pack it in, similar to the key data, only more compact */ -struct _tailblock { - unsigned int next:32-BLOCK_BITS; /* only needs to point to block numbers */ - unsigned int used:BLOCK_BITS; /* how many entries are used */ - union { - unsigned char offset[BLOCK_SIZE-4]; /* works upto blocksize of 1024 bytes */ - nameid_t data[(BLOCK_SIZE-4)/4]; - } tailblock_u; -}; -#define tb_offset tailblock_u.offset -#define tb_data tailblock_u.data - -/* map a tail index to a block index */ -#define TAIL_INDEX(b) ((b) & (BLOCK_SIZE-1)) -/* map a tail index to a block number */ -#define TAIL_BLOCK(b) ((b) & ~(BLOCK_SIZE-1)) -/* map a block + index to a tailid */ -#define TAIL_KEY(b, i) (((b) & ~(BLOCK_SIZE-1)) | ((i) & (BLOCK_SIZE-1))) - -#define TAIL_THRESHOLD ((BLOCK_SIZE-8)/6) - -static struct _IBEXStore *disk_create(struct _memcache *bc); -static int disk_sync(struct _IBEXStore *store); -static int disk_close(struct _IBEXStore *store); - -static blockid_t disk_add(struct _IBEXStore *store, blockid_t *head, blockid_t *tail, nameid_t data); -static blockid_t disk_add_list(struct _IBEXStore *store, blockid_t *head, blockid_t *tail, GArray *data); -static blockid_t disk_remove(struct _IBEXStore *store, blockid_t *head, blockid_t *tail, nameid_t data); -static void disk_free(struct _IBEXStore *store, blockid_t head, blockid_t tail); - -static gboolean disk_find(struct _IBEXStore *store, blockid_t head, blockid_t tail, nameid_t data); -static GArray *disk_get(struct _IBEXStore *store, blockid_t head, blockid_t tail); - -struct _IBEXStoreClass ibex_diskarray_class = { - disk_create, disk_sync, disk_close, - disk_add, disk_add_list, - disk_remove, disk_free, - disk_find, disk_get -}; - - -static int -tail_info(struct _memcache *blocks, struct _tailblock *bucket, nameid_t tailid, blockid_t **startptr) -{ - blockid_t *start, *end; - int index; - - /* get start/end of area to zap */ - index = TAIL_INDEX(tailid); - start = &bucket->tb_data[bucket->tb_offset[index]]; - if (index == 0) { - end = &bucket->tb_data[sizeof(bucket->tb_data)/sizeof(bucket->tb_data[0])]; - } else { - end = &bucket->tb_data[bucket->tb_offset[index-1]]; - } - if (startptr) - *startptr = start; - - ibex_block_cache_assert(blocks, end >= start); - - return end-start; -} - -/* compresses (or expand) the bucket entry, to the new size */ -static void -tail_compress(struct _memcache *blocks, struct _tailblock *bucket, int index, int newsize) -{ - int i; - blockid_t *start, *end, *newstart; - - /* get start/end of area to zap */ - start = &bucket->tb_data[bucket->tb_offset[index]]; - if (index == 0) { - end = &bucket->tb_data[sizeof(bucket->tb_data)/sizeof(bucket->tb_data[0])]; - } else { - end = &bucket->tb_data[bucket->tb_offset[index-1]]; - } - - if (end-start == newsize) - return; - - /* - XXXXXXXXXXXXXXXXXXXXXXXXXXXXXyyyyy - 0 20 25 - - newsize = 0 - end = 25 - newstart = 0 - start = 20 - - newstart+(end-start)-newsize = 5 - i = start-newstart - - XXXXXXXXXXXXXXXXXXXXXXXXXXXXXyyyyy - 0 20 25 - - newsize = 2 - end = 25 - newstart = 0 - start = 20 - - newstart+(end-start)-newsize = 3 - i = start-newstart + MIN(end-start, newsize)) = 22 - - XXXXXXXXXXXXXXXXXXXXXXXXXXXXX - 5 25 - newsize = 5 - end = 25 - start = 25 - newstart = 5 - - newstart+(end-start)-newsize = 0 - i = start-newstart = 20 - - XXXXXXXXXXXXXXXXXXXXXXXXXXXXXyy - 3 23 25 - newsize = 5 - end = 25 - start = 23 - newstart = 3 - - newstart+(end-start)-newsize = 0 - i = start-newstart + MIN(end-start, newsize) = 22 - - */ - - - /* fixup data */ - newstart = &bucket->tb_data[bucket->tb_offset[bucket->used-1]]; - - ibex_block_cache_assert(blocks, newstart+(end-start)-newsize <= &bucket->tb_data[sizeof(bucket->tb_data)/sizeof(bucket->tb_data[0])]); - ibex_block_cache_assert(blocks, newstart + (start-newstart) + MIN(end-start, newsize) <= &bucket->tb_data[sizeof(bucket->tb_data)/sizeof(bucket->tb_data[0])]); - ibex_block_cache_assert(blocks, newstart+(end-start)-newsize >= (blockid_t *) &bucket->tb_offset[bucket->used]); - ibex_block_cache_assert(blocks, newstart + (start-newstart) + MIN(end-start, newsize) >= (blockid_t *) &bucket->tb_offset[bucket->used]); - - memmove(newstart+(end-start)-newsize, newstart, ((start-newstart)+MIN(end-start, newsize)) * sizeof(blockid_t)); - - /* fixup key pointers */ - for (i=index;i<bucket->used;i++) { - bucket->tb_offset[i] += (end-start)-newsize; - } - ibex_block_dirty((struct _block *)bucket); -} - -/* - returns the number of blockid's free -*/ -static int -tail_space(struct _tailblock *tail) -{ - if (tail->used == 0) - return sizeof(tail->tb_data)/sizeof(tail->tb_data[0])-1; - - return &tail->tb_data[tail->tb_offset[tail->used-1]] - - (blockid_t *)&tail->tb_offset[tail->used] - 1; -} - -#if 0 -static void -tail_dump(struct _memcache *blocks, blockid_t tailid) -{ - int i; - struct _tailblock *tail = (struct _tailblock *)ibex_block_read(blocks, TAIL_BLOCK(tailid)); - - printf("Block %d, used %d\n", tailid, tail->used); - for (i=0;i<sizeof(struct _tailblock)/sizeof(unsigned int);i++) { - printf(" %08x", ((unsigned int *)tail)[i]); - } - printf("\n"); -} -#endif - -static blockid_t -tail_get(struct _memcache *blocks, int size) -{ - blockid_t tailid; - struct _tailblock *tail; - int freeindex; - blockid_t *end; - int i, count = 0; - - d(printf("looking for a tail node with %d items in it\n", size)); - - /* look for a node with enough space, if we dont find it fairly - quickly, just quit. needs a better free algorithm i think ... */ - tailid = blocks->root.tail; - while (tailid && count<5) { - int space; - - d(printf(" checking tail node %d\n", tailid)); - - tail = (struct _tailblock *)ibex_block_read(blocks, tailid); - - if (tail->used == 0) { - /* assume its big enough ... */ - tail->used = 1; - tail->tb_offset[0] = sizeof(tail->tb_data)/sizeof(tail->tb_data[0]) - size; - d(printf("allocated %d (%d), used %d\n", tailid, tailid, tail->used)); - ibex_block_dirty((struct _block *)tail); - - ibex_block_cache_assert(blocks, &tail->tb_offset[tail->used-1] - < (unsigned char *) &tail->tb_data[tail->tb_offset[tail->used-1]]); - - return tailid; - } - - ibex_block_cache_assert(blocks, &tail->tb_offset[tail->used-1] - < (unsigned char *) &tail->tb_data[tail->tb_offset[tail->used-1]]); - - /* see if we have a free slot first */ - freeindex = -1; - end = &tail->tb_data[sizeof(tail->tb_data)/sizeof(tail->tb_data[0])]; - for (i=0;i<tail->used;i++) { - if (end == &tail->tb_data[tail->tb_offset[i]]) { - freeindex = i; - break; - } - end = &tail->tb_data[tail->tb_offset[i]]; - } - - /* determine how much space we have available - incl any extra header we might need */ - space = ((char *)&tail->tb_data[tail->tb_offset[tail->used-1]]) - - ((char *)&tail->tb_offset[tail->used]) - /* FIXMEL work out why this is out a little bit */ - - 8; - if (freeindex == -1) - space -= sizeof(tail->tb_offset[0]); - - /* if we have enough, set it up, creating a new entry if necessary */ - /* for some really odd reason the compiler promotes this expression to unsigned, hence - the requirement for the space>0 check ... */ - if (space>0 && space > size*sizeof(blockid_t)) { - d(printf("space = %d, size = %d size*sizeof() = %d truth = %d\n", space, size, size*sizeof(blockid_t), space>size*sizeof(blockid_t))); - if (freeindex == -1) { - freeindex = tail->used; - tail->tb_offset[tail->used] = tail->tb_offset[tail->used-1]; - tail->used++; - } - tail_compress(blocks, tail, freeindex, size); - ibex_block_dirty((struct _block *)tail); - d(printf("allocated %d (%d), used %d\n", tailid, TAIL_KEY(tailid, freeindex), tail->used)); - return TAIL_KEY(tailid, freeindex); - } - count++; - tailid = block_location(tail->next); - } - - d(printf("allocating new data node for tail data\n")); - tailid = ibex_block_get(blocks); - tail = (struct _tailblock *)ibex_block_read(blocks, tailid); - tail->next = block_number(blocks->root.tail); - blocks->root.tail = tailid; - tail->used = 1; - tail->tb_offset[0] = sizeof(tail->tb_data)/sizeof(tail->tb_data[0]) - size; - ibex_block_dirty((struct _block *)tail); - d(printf("allocated %d (%d), used %d\n", tailid, TAIL_KEY(tailid, 0), tail->used)); - - g_assert(&tail->tb_offset[tail->used-1] - < (unsigned char *) &tail->tb_data[tail->tb_offset[tail->used-1]]); - - return TAIL_KEY(tailid, 0); -} - -static void -tail_free(struct _memcache *blocks, blockid_t tailid) -{ - struct _tailblock *tail; - - d(printf("freeing tail id %d\n", tailid)); - - if (tailid == 0) - return; - - tail = (struct _tailblock *)ibex_block_read(blocks, TAIL_BLOCK(tailid)); - d(printf(" tail %d used %d\n", tailid, tail->used)); - ibex_block_cache_assert(blocks, tail->used); - if (TAIL_INDEX(tailid) == tail->used - 1) { - tail->used --; - } else { - tail_compress(blocks, tail, TAIL_INDEX(tailid), 0); - } - ibex_block_dirty((struct _block *)tail); -} - -static struct _IBEXStore *disk_create(struct _memcache *bc) -{ - struct _IBEXStore *store; - - store = g_malloc0(sizeof(*store)); - store->klass = &ibex_diskarray_class; - store->blocks = bc; - - return store; -} - -static int disk_sync(struct _IBEXStore *store) -{ - /* no cache, nop */ - return 0; -} - -static int disk_close(struct _IBEXStore *store) -{ - g_free(store); - return 0; -} - -static blockid_t -disk_add(struct _IBEXStore *store, blockid_t *headptr, blockid_t *tailptr, nameid_t data) -{ - struct _block *block; - struct _block *newblock; - blockid_t new, head = *headptr /*, tail = *tailptr*/; - - g_error("Inbimplemented"); - - if (head == 0) { - head = ibex_block_get(store->blocks); - } - block = ibex_block_read(store->blocks, head); - - d(printf("adding record %d to block %d (next = %d)\n", data, head, block->next)); - - if (block->used < sizeof(block->bl_data)/sizeof(block->bl_data[0])) { - (printf("adding record into block %d %d\n", head, data)); - block->bl_data[block->used] = data; - block->used++; - ibex_block_dirty(block); - return head; - } else { - new = ibex_block_get(store->blocks); - newblock = ibex_block_read(store->blocks, new); - newblock->next = block_number(head); - newblock->bl_data[0] = data; - newblock->used = 1; - d(printf("adding record into new %d %d, next =%d\n", new, data, newblock->next)); - ibex_block_dirty(newblock); - return new; - } -} - -static blockid_t -disk_add_blocks_internal(struct _IBEXStore *store, blockid_t *headptr, blockid_t *tailptr, GArray *data) -{ - blockid_t head = *headptr, tail = *tailptr, new; - int tocopy; - struct _tailblock *tailblock; - struct _block *block, *newblock; - int space, copied = 0, left; - - /* assumes this funciton is in control of any tail creation */ - ibex_block_cache_assert(store->blocks, tail == 0); - - d(printf("Adding %d items to block list\n", data->len)); - - if (head == 0) { - head = ibex_block_get(store->blocks); - d(printf("allocating new head %d\n", head)); - } - block = ibex_block_read(store->blocks, head); - - /* ensure the first block is full before proceeding */ - space = sizeof(block->bl_data)/sizeof(block->bl_data[0]) - block->used; - if (space) { - tocopy = MIN(data->len, space); - memcpy(block->bl_data+block->used, &g_array_index(data, blockid_t, copied), tocopy*sizeof(blockid_t)); - block->used += tocopy; - ibex_block_dirty(block); - copied = tocopy; - d(printf("copied %d items to left over last node\n", tocopy)); - } - - while (copied < data->len) { - left = data->len - copied; - /* do we drop the rest in a tail? */ - if (left < TAIL_THRESHOLD) { - d(printf("Storing remaining %d items in tail\n", left)); - tocopy = left; - new = tail_get(store->blocks, tocopy); - tailblock = (struct _tailblock *)ibex_block_read(store->blocks, TAIL_BLOCK(new)); - memcpy(&tailblock->tb_data[tailblock->tb_offset[TAIL_INDEX(new)]], - &g_array_index(data, blockid_t, copied), tocopy*sizeof(blockid_t)); - *tailptr = new; - } else { - new = ibex_block_get(store->blocks); - newblock = (struct _block *)ibex_block_read(store->blocks, new); - newblock->next = block_number(head); - tocopy = MIN(left, sizeof(block->bl_data)/sizeof(block->bl_data[0])); - d(printf("storing %d items in own block\n", tocopy)); - memcpy(newblock->bl_data, &g_array_index(data, blockid_t, copied), tocopy*sizeof(blockid_t)); - newblock->used = tocopy; - block = newblock; - head = new; - ibex_block_dirty(newblock); - } - copied += tocopy; - } - - *headptr = head; - return head; -} -/* - case 1: - no head, no tail, adding a lot of data - add blocks until the last, which goes in a tail node - case 2: - no head, no tail, adding a little data - just add a tail node - case 3: - no head, tail, total exceeds a block - merge as much as possible into new full blocks, then the remainder in the tail - case 4: - no head, tail, room in existing tail for data - add new data to tail node - case 5: - no head, tail, no room in existing tail for data - add a new tail node, copy data across, free old tail node -*/ - -static blockid_t -disk_add_list(struct _IBEXStore *store, blockid_t *headptr, blockid_t *tailptr, GArray *data) -{ - blockid_t new, head = *headptr, tail = *tailptr, *start; - struct _tailblock *tailblock, *tailnew; - int len; - GArray *tmpdata = NULL; - - d(printf("adding %d items head=%d tail=%d\n", data->len, head, tail)); - if (data->len == 0) - return head; - - /* store length=1 data in the tail pointer */ - if (head == 0 && tail == 0 && data->len == 1) { - *headptr = BLOCK_ONE; - *tailptr = g_array_index(data, blockid_t, 0); - return BLOCK_ONE; - } - /* if we got length=1 data to append to, upgrade it to a real block list */ - if (head == BLOCK_ONE) { - tmpdata = g_array_new(0, 0, sizeof(blockid_t)); - g_array_append_vals(tmpdata, data->data, data->len); - g_array_append_val(tmpdata, tail); - head = *headptr = 0; - tail = *tailptr = 0; - } - - /* if we have no head, then check the tail */ - if (head == 0) { - if (tail == 0) { - if (data->len >= TAIL_THRESHOLD) { - /* add normally */ - head = disk_add_blocks_internal(store, headptr, tailptr, data); - } else { - /* else add to a tail block */ - new = tail_get(store->blocks, data->len); - d(printf("adding %d items to a tail block %d\n", data->len, new)); - tailnew = (struct _tailblock *)ibex_block_read(store->blocks, TAIL_BLOCK(new)); - memcpy(&tailnew->tb_data[tailnew->tb_offset[TAIL_INDEX(new)]], - data->data, data->len*sizeof(blockid_t)); - *tailptr = new; - ibex_block_dirty((struct _block *)tailnew); - } - } else { - tailblock = (struct _tailblock *)ibex_block_read(store->blocks, TAIL_BLOCK(tail)); - len = tail_info(store->blocks, tailblock, tail, &start); - /* case 3 */ - if (len + data->len >= TAIL_THRESHOLD) { - /* this is suboptimal, but should work - merge the tail data with - our new data, and write it out */ - if (tmpdata == NULL) { - tmpdata = g_array_new(0, 0, sizeof(blockid_t)); - g_array_append_vals(tmpdata, data->data, data->len); - } - g_array_append_vals(tmpdata, start, len); - *tailptr = 0; - tail_free(store->blocks, tail); - head = disk_add_blocks_internal(store, headptr, tailptr, tmpdata); - } else if (tail_space(tailblock) >= data->len) { - /* can we just expand this in our node, or do we need a new one? */ - tail_compress(store->blocks, tailblock, TAIL_INDEX(tail), data->len + len); - memcpy(&tailblock->tb_data[tailblock->tb_offset[TAIL_INDEX(tail)] + len], - data->data, data->len * sizeof(blockid_t)); - ibex_block_dirty((struct _block *)tailblock); - } else { - /* we need to allocate a new tail node */ - new = tail_get(store->blocks, data->len + len); - /* and copy the data across */ - tailnew = (struct _tailblock *)ibex_block_read(store->blocks, TAIL_BLOCK(new)); - memcpy(&tailnew->tb_data[tailnew->tb_offset[TAIL_INDEX(new)]], - start, len*sizeof(blockid_t)); - memcpy(&tailnew->tb_data[tailnew->tb_offset[TAIL_INDEX(new)]+len], - data->data, data->len*sizeof(blockid_t)); - tail_free(store->blocks, tail); - ibex_block_dirty((struct _block *)tailnew); - *tailptr = new; - } - } - } else { - if (tail) { - /* read/merge the tail with the new data, rewrite out. - suboptimal, but it should be 'ok' ? */ - tailblock = (struct _tailblock *)ibex_block_read(store->blocks, TAIL_BLOCK(tail)); - len = tail_info(store->blocks, tailblock, tail, &start); - tmpdata = g_array_new(0, 0, sizeof(blockid_t)); - g_array_append_vals(tmpdata, start, len); - g_array_append_vals(tmpdata, data->data, data->len); - *tailptr = 0; - tail_free(store->blocks, tail); - head = disk_add_blocks_internal(store, headptr, tailptr, tmpdata); - } else { - head = disk_add_blocks_internal(store, headptr, tailptr, data); - } - } - if (tmpdata) - g_array_free(tmpdata, TRUE); - - return head; -} - -static blockid_t -disk_remove(struct _IBEXStore *store, blockid_t *headptr, blockid_t *tailptr, nameid_t data) -{ - blockid_t head = *headptr, node = *headptr, tail = *tailptr; - int i; - - /* special case for 1-item nodes */ - if (head == BLOCK_ONE) { - if (tail == data) { - *tailptr = 0; - *headptr = 0; - head = 0; - } - return head; - } - - d(printf("removing %d from %d\n", data, head)); - while (node) { - struct _block *block = ibex_block_read(store->blocks, node); - - for (i=0;i<block->used;i++) { - if (block->bl_data[i] == data) { - struct _block *start = ibex_block_read(store->blocks, head); - - d(printf("removing data from block %d\n ", head)); - - start->used--; - block->bl_data[i] = start->bl_data[start->used]; - if (start->used == 0) { - blockid_t new; - - d(printf("dropping block %d, new head = %d\n", head, start->next)); - new = block_location(start->next); - start->next = block_number(store->blocks->root.free); - store->blocks->root.free = head; - head = new; - } - ibex_block_dirty(block); - ibex_block_dirty(start); - *headptr = head; - return head; - } - } - node = block_location(block->next); - } - - if (tail) { - struct _tailblock *tailblock = (struct _tailblock *)ibex_block_read(store->blocks, TAIL_BLOCK(tail)); - int len; - blockid_t *start; - - len = tail_info(store->blocks, tailblock, tail, &start); - for (i=0;i<len;i++) { - if (start[i] == data) { - for (;i<len-1;i++) - start[i] = start[i+1]; - if (len == 1) - *tailptr = 0; - if (len == 1 && (tailblock->used-1) == TAIL_INDEX(tail)) { - d(printf("dropping/unlinking tailblock %d (%d) used = %d\n", - TAIL_BLOCK(tail), tail, tailblock->used)); - tailblock->used--; - /* drop/unlink block? */ - ibex_block_dirty((struct _block *)tailblock); - *tailptr = 0; - } else { - tail_compress(store->blocks, tailblock, TAIL_INDEX(tail), len-1); - ibex_block_dirty((struct _block *)tailblock); - } - } - } - - } - - return head; -} - -static void disk_free(struct _IBEXStore *store, blockid_t head, blockid_t tail) -{ - blockid_t next; - struct _block *block; - - if (head == BLOCK_ONE) - return; - - while (head) { - d(printf("freeing block %d\n", head)); - block = ibex_block_read(store->blocks, head); - next = block_location(block->next); - ibex_block_free(store->blocks, head); - head = next; - } - if (tail) { - struct _tailblock *tailblock = (struct _tailblock *)ibex_block_read(store->blocks, TAIL_BLOCK(tail)); - d(printf("freeing tail block %d (%d)\n", TAIL_BLOCK(tail), tail)); - tail_compress(store->blocks, tailblock, TAIL_INDEX(tail), 0); - ibex_block_dirty((struct _block *)tailblock); - } -} - -static gboolean -disk_find(struct _IBEXStore *store, blockid_t head, blockid_t tail, nameid_t data) -{ - blockid_t node = head; - int i; - - d(printf("finding %d from %d\n", data, head)); - - if (head == BLOCK_ONE) - return data == tail; - - /* first check full blocks */ - while (node) { - struct _block *block = ibex_block_read(store->blocks, node); - - for (i=0;i<block->used;i++) { - if (block->bl_data[i] == data) { - return TRUE; - } - } - node = block_location(block->next); - } - - /* then check tail */ - if (tail) { - struct _tailblock *tailblock = (struct _tailblock *)ibex_block_read(store->blocks, TAIL_BLOCK(tail)); - int len; - blockid_t *start; - - len = tail_info(store->blocks, tailblock, tail, &start); - for (i=0;i<len;i++) { - if (start[i] == data) - return TRUE; - } - } - - return FALSE; -} - -static GArray * -disk_get(struct _IBEXStore *store, blockid_t head, blockid_t tail) -{ - GArray *result = g_array_new(0, 0, sizeof(nameid_t)); - - if (head == BLOCK_ONE) { - g_array_append_val(result, tail); - return result; - } - - while (head) { - struct _block *block = ibex_block_read(store->blocks, head); - - d(printf("getting data from block %d\n", head)); - - g_array_append_vals(result, block->bl_data, block->used); - head = block_location(block->next); - d(printf("next = %d\n", head)); - } - - /* chuck on any tail data as well */ - if (tail) { - struct _tailblock *tailblock; - int len; - blockid_t *start; - - tailblock = (struct _tailblock *)ibex_block_read(store->blocks, TAIL_BLOCK(tail)); - len = tail_info(store->blocks, tailblock, tail, &start); - g_array_append_vals(result, start, len); - } - return result; -} - -void ibex_diskarray_dump(struct _memcache *blocks, blockid_t head, blockid_t tail); - -void -ibex_diskarray_dump(struct _memcache *blocks, blockid_t head, blockid_t tail) -{ - blockid_t node = head; - - printf("dumping list %d tail %d\n", node, tail); - if (head == BLOCK_ONE) { - printf(" 1 length index: %d\n", tail); - return; - } - - while (node) { - struct _block *block = ibex_block_read(blocks, node); - int i; - - printf(" block %d used %d\n ", node, block->used); - for (i=0;i<block->used;i++) { - printf(" %d", block->bl_data[i]); - } - printf("\n"); - node = block_location(block->next); - } - - printf("tail: "); - if (tail) { - struct _tailblock *tailblock; - int len; - blockid_t *start; - int i; - - tailblock = (struct _tailblock *)ibex_block_read(blocks, TAIL_BLOCK(tail)); - len = tail_info(blocks, tailblock, tail, &start); - for (i=0;i<len;i++) - printf(" %d", start[i]); - } - printf("\n"); -} - -#if 0 -int main(int argc, char **argv) -{ - struct _memcache *bc; - struct _IBEXStore *disk; - int i; - blockid_t data[100]; - GArray adata; - blockid_t head=0, tail=0; - - for (i=0;i<100;i++) { - data[i] = i; - } - - bc = ibex_block_cache_open("index.db", O_CREAT|O_RDWR, 0600); - disk = ibex_diskarray_class.create(bc); - - head = 0; - tail = 0; - adata.data = data; - adata.len = 70; - for (i=0;i<100;i++) { - printf("Loop %d\n", i); - ibex_diskarray_class.add_list(disk, &head, &tail, &adata); - ibex_diskarray_dump(bc, head, tail); - } - -#if 0 - for (i=1;i<100;i++) { - printf("inserting %d items\n", i); - adata.data = data; - adata.len = i; - head=0; - tail=0; - ibex_diskarray_class.add_list(disk, &head, &tail, &adata); - ibex_diskarray_dump(bc, head, tail); - } -#endif - ibex_diskarray_class.close(disk); - ibex_block_cache_close(bc); - return 0; -} - -#endif |