add(layout, elem);
}
-void tdb_layout_add_free(struct tdb_layout *layout, tdb_len_t len)
+void tdb_layout_add_free(struct tdb_layout *layout, tdb_len_t len,
+ unsigned flist)
{
union tdb_layout_elem elem;
elem.base.type = FREE;
elem.free.len = len;
+ elem.free.flist_num = flist;
add(layout, elem);
}
{
struct tdb_used_record *u = mem;
- set_header(tdb, u, used->key.dsize, used->data.dsize,
- used->key.dsize + used->data.dsize + used->extra,
- tdb_hash(tdb, used->key.dptr, used->key.dsize));
+ set_used_header(tdb, u, used->key.dsize, used->data.dsize,
+ used->key.dsize + used->data.dsize + used->extra,
+ tdb_hash(tdb, used->key.dptr, used->key.dsize));
memcpy(u + 1, used->key.dptr, used->key.dsize);
memcpy((char *)(u + 1) + used->key.dsize,
used->data.dptr, used->data.dsize);
struct tdb_used_record *u = mem;
tdb_len_t len = sizeof(tdb_off_t) << TDB_SUBLEVEL_HASH_BITS;
- set_header(tdb, u, 0, len, len + htable->extra, 0);
+ set_used_header(tdb, u, 0, len, len + htable->extra, 0);
memset(u + 1, 0, len);
}
static void set_freelist(void *mem, struct tdb_context *tdb,
- struct tle_freelist *freelist)
+ struct tle_freelist *freelist, struct tdb_header *hdr,
+ tdb_off_t last_flist)
{
struct tdb_freelist *flist = mem;
memset(flist, 0, sizeof(*flist));
- set_header(tdb, &flist->hdr, 0,
- sizeof(*flist) - sizeof(flist->hdr),
- sizeof(*flist) - sizeof(flist->hdr), 1);
+ set_used_header(tdb, &flist->hdr, 0,
+ sizeof(*flist) - sizeof(flist->hdr),
+ sizeof(*flist) - sizeof(flist->hdr), 1);
+
+ if (last_flist) {
+ flist = (struct tdb_freelist *)((char *)hdr + last_flist);
+ flist->next = freelist->base.off;
+ } else {
+ hdr->free_list = freelist->base.off;
+ }
}
static void add_to_freetable(struct tdb_context *tdb,
tdb_off_t eoff,
- tdb_off_t elen)
+ tdb_off_t elen,
+ unsigned flist,
+ struct tle_freelist *freelist)
{
+ tdb->flist_off = freelist->base.off;
+ tdb->flist = flist;
add_free_record(tdb, eoff, sizeof(struct tdb_used_record) + elen);
}
abort();
}
+static struct tle_freelist *find_flist(struct tdb_layout *layout, unsigned num)
+{
+ unsigned i;
+
+ for (i = 0; i < layout->num_elems; i++) {
+ if (layout->elem[i].base.type != FREELIST)
+ continue;
+ if (num == 0)
+ return &layout->elem[i].flist;
+ num--;
+ }
+ abort();
+}
+
/* FIXME: Support TDB_CONVERT */
struct tdb_context *tdb_layout_get(struct tdb_layout *layout)
{
unsigned int i;
- tdb_off_t off, len, flist_off = 0;
+ tdb_off_t off, len, last_flist;
char *mem;
struct tdb_context *tdb;
e->base.off = off;
switch (e->base.type) {
case FREELIST:
- assert(flist_off == 0);
- flist_off = off;
len = freelist_len(&e->flist);
break;
case FREE:
}
off += len;
}
- /* Must have a free list! */
- assert(flist_off);
mem = malloc(off);
/* Now populate our header, cribbing from a real TDB header. */
free(tdb->map_ptr);
tdb->map_ptr = mem;
tdb->map_size = off;
- tdb->flist_off = flist_off;
+ last_flist = 0;
for (i = 0; i < layout->num_elems; i++) {
union tdb_layout_elem *e = &layout->elem[i];
switch (e->base.type) {
case FREELIST:
- set_freelist(mem + e->base.off, tdb, &e->flist);
+ set_freelist(mem + e->base.off, tdb, &e->flist,
+ (struct tdb_header *)mem, last_flist);
+ last_flist = e->base.off;
break;
case FREE:
set_free_record(mem + e->base.off, e->free.len);
break;
}
}
+ /* Must have a free list! */
+ assert(last_flist);
/* Now fill the free and hash tables. */
for (i = 0; i < layout->num_elems; i++) {
union tdb_layout_elem *e = &layout->elem[i];
switch (e->base.type) {
case FREE:
- add_to_freetable(tdb, e->base.off, e->free.len);
+ add_to_freetable(tdb, e->base.off, e->free.len,
+ e->free.flist_num,
+ find_flist(layout, e->free.flist_num));
break;
case DATA:
add_to_hashtable(tdb, e->base.off, e->used.key);
}
}
+ tdb->flist_off = find_flist(layout, 0)->base.off;
+
/* Get physical if they asked for it. */
if (layout->filename) {
int fd = open(layout->filename, O_WRONLY|O_TRUNC|O_CREAT,