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; }
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__; } } }