extern int SyncTreeMarkReachable(struct SyncTreeWorkerHead *head, int minLevel) { int count = 0; while (head->level > minLevel) { struct SyncTreeWorkerEntry *ent = SyncTreeWorkerTop(head); if (ent == NULL) break; struct SyncHashCacheEntry *ce = ent->cacheEntry; if (ce == NULL) break; ce->state |= SyncHashState_marked; count++; struct SyncNodeComposite *nc = ((head->remote > 0) ? ce->ncR : ce->ncL); if (nc == NULL) break; int lim = nc->refLen; if (ent->pos >= lim) { // done with the current level, go back to the previous level ent = SyncTreeWorkerPop(head); if (ent == NULL) break; ent->pos++; } else { struct SyncNodeElem *ep = &nc->refs[ent->pos]; if (ep->kind & SyncElemKind_leaf) { // a leaf, so skip it ent->pos++; } else { // a node, so push into it ent = SyncTreeWorkerPush(head); if (ent == NULL) break; } } } return count; }
extern enum SyncCompareResult SyncTreeLookupName(struct SyncTreeWorkerHead *head, struct ccn_charbuf *name, int minLevel) { enum SyncCompareResult cr = SCR_inside; while (head->level > minLevel) { struct SyncTreeWorkerEntry *ent = SyncTreeWorkerTop(head); if (ent->cacheEntry == NULL) { // probably a real bug! return SCR_error; } struct SyncHashCacheEntry *ce = ent->cacheEntry; struct SyncNodeComposite *nc = ((head->remote > 0) ? ce->ncR : ce->ncL); if (nc == NULL) { // report desired node as missing return SCR_missing; } int lim = nc->refLen; if (ent->pos >= lim) { // done with the current level, go back to the previous level ent = SyncTreeWorkerPop(head); if (ent == NULL) break; ent->pos++; } else { if (ent->pos == 0) { // need to check the min and max of the current node enum SyncCompareResult cr = SyncNodeCompareMinMax(nc, name); if (cr == SCR_after) { // not in this node at all, so pop out ent->pos = lim; } else if (cr != SCR_inside) return cr; } if (ent->pos < lim) { struct SyncNodeElem *ep = &nc->refs[ent->pos]; if (ep->kind & SyncElemKind_leaf) { // a leaf, so the element name is inline cr = SyncNodeCompareLeaf(nc, ep, name); if (cr != SCR_after) return cr; ent->pos++; } else { // a node, so try this recursively ent = SyncTreeWorkerPush(head); if (ent == NULL) { return SCR_error; } } } } } return SCR_after; }
extern enum SyncCompareResult SyncTreeGenerateNames(struct SyncTreeWorkerHead *head, struct SyncNameAccum *accum, int minLevel) { while (head->level > minLevel) { struct SyncTreeWorkerEntry *ent = SyncTreeWorkerTop(head); if (ent->cacheEntry == NULL) { // probably a real bug! return SCR_error; } struct SyncHashCacheEntry *ce = ent->cacheEntry; struct SyncNodeComposite *nc = ((head->remote > 0) ? ce->ncR : ce->ncL); if (nc == NULL) { // TBD: fetch node if not present return SCR_missing; } int lim = nc->refLen; if (ent->pos >= lim) { // done with the current level, go back to the previous level ent = SyncTreeWorkerPop(head); if (ent == NULL) break; ent->pos++; } else { struct SyncNodeElem *ep = &nc->refs[ent->pos]; if (ep->kind & SyncElemKind_leaf) { // a leaf, so the element name is inline struct ccn_buf_decoder bd; struct ccn_buf_decoder *d = SyncInitDecoderFromOffset(&bd, nc, ep->start, ep->stop); struct ccn_charbuf *cb = ccn_charbuf_create(); int res = SyncAppendElementInner(cb, d); if (res < 0) { // that did not work well ccn_charbuf_destroy(&cb); return SCR_error; } SyncNameAccumAppend(accum, cb, 0); ent->pos++; } else { ent = SyncTreeWorkerPush(head); if (ent == NULL) { return SCR_error; } } } } return SCR_after; }
int BuildTree(struct SyncUpdateData *ud, struct SyncTreeWorkerHead *tw, struct SyncNameAccum *src) { int res = 0; while (res == 0) { struct SyncTreeWorkerEntry *ent = SyncTreeWorkerTop(tw); if (ent == NULL) break; struct SyncHashCacheEntry *ce = ent->cacheEntry; if (ce == NULL) // no cache entry, so bad news return -__LINE__; struct SyncNodeComposite *nc = CacheEntryFetch(ud, ce); if (nc == NULL) { if (ce->state & SyncHashState_fetching) // can't process this node now, it's being fetched return 0; return -__LINE__; } struct ccn_charbuf *name = BestName(ud); enum SyncCompareResult scr = SyncNodeCompareMinMax(nc, name); switch (scr) { case SCR_before: // name < Min(L), so add name, advance names UpdateAddName(ud, name); AdvanceName(ud); break; case SCR_min: // name == Min(L), advance names AdvanceName(ud); break; case SCR_max: // R == Max(L), discard R, advance both ent->pos++; AdvanceName(ud); break; case SCR_after: // R > Max(L), advance L AcceptNode(ud); break; case SCR_inside: // Min(L) < R < Max(L), so dive into L if (SyncTreeWorkerPush(tw) == NULL) return - __LINE__; break; default: // this is really broken return -__LINE__; } } }