/** * btree_sync(T, callback, cookie): * Serialize and write dirty nodes from the B+Tree ${T}; mark said nodes as * clean; free the shadow tree; and invoke the provided callback. */ int btree_sync(struct btree * T, int (* callback)(void *), void * cookie) { struct write_cookie * WC; size_t npages; const uint8_t ** bufv; uint64_t pn = 0; /* Bake a cookie. */ if ((WC = malloc(sizeof(struct write_cookie))) == NULL) goto err0; WC->T = T; WC->callback = callback; WC->cookie = cookie; /* Figure out how many pages we need to write. */ npages = ndirty(T->root_dirty); /* Allocate a vector to hold pointers to pages. */ if (IMALLOC(bufv, npages, const uint8_t *)) goto err1; /* Serialize pages and record pointers into the vector. */ if (serializetree(T, T->root_dirty, T->pagelen, T->nextblk, bufv, &pn)) goto err2; /* Sanity check the number of pages serialized. */ assert(pn == npages); /* Write pages out. */ if (proto_lbs_request_append_blks(T->LBS, npages, T->nextblk, T->pagelen, bufv, callback_append, WC)) { warnp("Error writing pages"); goto err2; } /* Free the page pointers vector. */ free(bufv); /* Success! */ return (0); err2: free(bufv); err1: free(WC); err0: /* Failure! */ return (-1); }
/* Compile a compressed dictionary file from the words in the given * files. */ int makedictfile(int filecount, char *files[]) { if (!filecount) { filecount = 1; files = &defwordlist; } nodecount = 1; if (!readwordlists(filecount, files, grabnewtreearc(0, nodecount))) return EXIT_FAILURE; computefrequencies(); serializetree(); writetreetofile(partitiontree()); report("Dictionary saved to %s\n", dictfilename); return EXIT_SUCCESS; }
/* Serialize the dirty nodes in a (sub)tree. */ static int serializetree(struct btree * T, struct node * N, size_t pagelen, uint64_t nextblk, const uint8_t ** bufv, uint64_t * pn) { size_t i; /* If this node is not dirty, return immediately. */ if (N->state != NODE_STATE_DIRTY) return (0); /* If this node has children, serialize them first. */ if (N->type == NODE_TYPE_PARENT) { for (i = 0; i <= N->nkeys; i++) if (serializetree(T, N->v.children[i], pagelen, nextblk, bufv, pn)) goto err0; } /* Record this node's page number. */ N->pagenum = nextblk + *pn; /* * Figure out what the oldest leaf number under this node is. The * oldest not-being-cleaned leaf is computed in makeclean. */ N->oldestleaf = N->pagenum; if (N->type == NODE_TYPE_PARENT) { for (i = 0; i <= N->nkeys; i++) { if (N->v.children[i]->oldestleaf < N->oldestleaf) N->oldestleaf = N->v.children[i]->oldestleaf; } } /* Serialize the page and record the page pointer. */ if (serialize(T, N, pagelen)) goto err0; bufv[(*pn)++] = N->pagebuf; /* Success! */ return (0); err0: /* Failure! */ return (-1); }