SyncTreeWorker.c
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "SyncMacros.h"
00021 #include "SyncNode.h"
00022 #include "SyncTreeWorker.h"
00023 #include "SyncHashCache.h"
00024 #include "SyncUtil.h"
00025 #include <stdlib.h>
00026 #include <string.h>
00027 #include <strings.h>
00028
00029 extern void
00030 SyncTreeWorkerInit(struct SyncTreeWorkerHead *head,
00031 struct SyncHashCacheEntry *ent,
00032 int remote) {
00033 SyncTreeWorkerReset(head, 0);
00034 head->remote = remote;
00035 if (ent != NULL) {
00036 struct SyncTreeWorkerEntry *sp = &head->stack[0];
00037 sp->pos = 0;
00038 sp->cacheEntry = ent;
00039 ent->busy++;
00040 head->level = 1;
00041 }
00042 }
00043
00044 extern struct SyncTreeWorkerHead *
00045 SyncTreeWorkerCreate(struct SyncHashCacheHead *cache,
00046 struct SyncHashCacheEntry *ent,
00047 int remote) {
00048 struct SyncTreeWorkerHead * head = NEW_STRUCT(1, SyncTreeWorkerHead);
00049 int lim = 4;
00050 struct SyncTreeWorkerEntry * stack = NEW_STRUCT(lim, SyncTreeWorkerEntry);
00051 head->stack = stack;
00052 head->lim = lim;
00053 head->cache = cache;
00054 SyncTreeWorkerInit(head, ent, remote);
00055 return head;
00056 }
00057
00058 extern struct SyncTreeWorkerEntry *
00059 SyncTreeWorkerTop(struct SyncTreeWorkerHead *head) {
00060 if (head->level <= 0) return NULL;
00061 struct SyncTreeWorkerEntry *stack = head->stack;
00062 struct SyncTreeWorkerEntry *ent = &stack[head->level - 1];
00063 return ent;
00064 }
00065
00066 extern struct SyncNodeElem *
00067 SyncTreeWorkerGetElem(struct SyncTreeWorkerHead *head) {
00068 struct SyncTreeWorkerEntry *ent = SyncTreeWorkerTop(head);
00069 if (ent == NULL) return NULL;
00070 struct SyncHashCacheEntry *ce = ent->cacheEntry;
00071 if (ce == NULL) return NULL;
00072 struct SyncNodeComposite *nc = ((head->remote > 0) ? ce->ncR : ce->ncL);
00073 if (nc == NULL) return NULL;
00074 int pos = ent->pos;
00075 if (pos < 0 || pos >= nc->refLen) return NULL;
00076 struct SyncNodeElem *ref = &nc->refs[pos];
00077 return ref;
00078 }
00079
00080 extern struct SyncTreeWorkerEntry *
00081 SyncTreeWorkerPush(struct SyncTreeWorkerHead *head) {
00082 struct SyncNodeElem *ref = SyncTreeWorkerGetElem(head);
00083 if (ref == NULL || (ref->kind & SyncElemKind_leaf))
00084 return NULL;
00085 struct SyncTreeWorkerEntry *ent = SyncTreeWorkerTop(head);
00086 struct SyncHashCacheEntry *ce = ent->cacheEntry;
00087 struct SyncNodeComposite *nc = ((head->remote > 0) ? ce->ncR : ce->ncL);
00088 struct ccn_buf_decoder cbd;
00089 struct ccn_buf_decoder *cb = SyncInitDecoderFromOffset(&cbd, nc,
00090 ref->start,
00091 ref->stop);
00092 const unsigned char *xp = NULL;
00093 ssize_t xs = 0;
00094 SyncGetHashPtr(cb, &xp, &xs);
00095 ce = SyncHashLookup(head->cache, xp, xs);
00096 if (ce == NULL)
00097
00098 return NULL;
00099 struct SyncTreeWorkerEntry *stack = head->stack;
00100 int level = head->level;
00101 int oLim = head->lim;
00102 if (level > oLim) {
00103
00104 return NULL;
00105 }
00106 if (level == oLim) {
00107
00108 int nLim = oLim + oLim / 2 + 4;
00109 struct SyncTreeWorkerEntry *nStack = NEW_STRUCT(nLim,
00110 SyncTreeWorkerEntry);
00111 memcpy(nStack, stack, level*sizeof(struct SyncTreeWorkerEntry));
00112 free(stack);
00113 stack = nStack;
00114 head->stack = nStack;
00115 head->lim = nLim;
00116 }
00117
00118 head->level = level+1;
00119 ent = &stack[level];
00120 ent->pos = 0;
00121 ent->count = 0;
00122 ent->cacheEntry = ce;
00123 ce->busy++;
00124 head->visits++;
00125 return ent;
00126 }
00127
00128 extern struct SyncTreeWorkerEntry *
00129 SyncTreeWorkerPop(struct SyncTreeWorkerHead *head) {
00130 int level = head->level;
00131 if (level <= 0) return NULL;
00132 level--;
00133 struct SyncTreeWorkerEntry *stack = head->stack;
00134 struct SyncTreeWorkerEntry *ep = &stack[level];
00135 struct SyncHashCacheEntry *ce = ep->cacheEntry;
00136 if (ce != NULL && ce->busy > 0) ce->busy--;
00137 head->level = level;
00138 if (level <= 0) return NULL;
00139 return &head->stack[level - 1];
00140 }
00141
00142 extern void
00143 SyncTreeWorkerReset(struct SyncTreeWorkerHead *head, int level) {
00144 if (head == NULL) return;
00145 while (head->level > level) {
00146 SyncTreeWorkerPop(head);
00147 }
00148 if (level > 0) {
00149 head->stack[head->level - 1].pos = 0;
00150 }
00151 head->state = SyncTreeWorkerState_init;
00152 }
00153
00154 extern struct SyncTreeWorkerHead *
00155 SyncTreeWorkerFree(struct SyncTreeWorkerHead *head) {
00156 if (head != NULL) {
00157 SyncTreeWorkerReset(head, 0);
00158 free(head->stack);
00159 free(head);
00160 }
00161 return NULL;
00162 }
00163
00164 extern enum SyncCompareResult
00165 SyncTreeLookupName(struct SyncTreeWorkerHead *head,
00166 struct ccn_charbuf *name,
00167 int minLevel) {
00168
00169 enum SyncCompareResult cr = SCR_inside;
00170 while (head->level > minLevel) {
00171 struct SyncTreeWorkerEntry *ent = SyncTreeWorkerTop(head);
00172 if (ent->cacheEntry == NULL) {
00173
00174 return SCR_error;
00175 }
00176 struct SyncHashCacheEntry *ce = ent->cacheEntry;
00177 struct SyncNodeComposite *nc = ((head->remote > 0) ? ce->ncR : ce->ncL);
00178 if (nc == NULL) {
00179
00180 return SCR_missing;
00181 }
00182 int lim = nc->refLen;
00183 if (ent->pos >= lim) {
00184
00185 ent = SyncTreeWorkerPop(head);
00186 if (ent == NULL) break;
00187 ent->pos++;
00188 } else {
00189
00190 if (ent->pos == 0) {
00191
00192 enum SyncCompareResult cr = SyncNodeCompareMinMax(nc, name);
00193 if (cr == SCR_after) {
00194
00195 ent->pos = lim;
00196 } else if (cr != SCR_inside) return cr;
00197 }
00198 if (ent->pos < lim) {
00199 struct SyncNodeElem *ep = &nc->refs[ent->pos];
00200 if (ep->kind & SyncElemKind_leaf) {
00201
00202 cr = SyncNodeCompareLeaf(nc, ep, name);
00203 if (cr != SCR_after) return cr;
00204 ent->pos++;
00205 } else {
00206
00207 ent = SyncTreeWorkerPush(head);
00208 if (ent == NULL) {
00209 return SCR_error;
00210 }
00211 }
00212 }
00213 }
00214
00215 }
00216 return SCR_after;
00217 }
00218
00219 extern enum SyncCompareResult
00220 SyncTreeGenerateNames(struct SyncTreeWorkerHead *head,
00221 struct SyncNameAccum *accum,
00222 int minLevel) {
00223
00224 while (head->level > minLevel) {
00225 struct SyncTreeWorkerEntry *ent = SyncTreeWorkerTop(head);
00226 if (ent->cacheEntry == NULL) {
00227
00228 return SCR_error;
00229 }
00230 struct SyncHashCacheEntry *ce = ent->cacheEntry;
00231 struct SyncNodeComposite *nc = ((head->remote > 0) ? ce->ncR : ce->ncL);
00232 if (nc == NULL) {
00233
00234 return SCR_missing;
00235 }
00236 int lim = nc->refLen;
00237 if (ent->pos >= lim) {
00238
00239 ent = SyncTreeWorkerPop(head);
00240 if (ent == NULL) break;
00241 ent->pos++;
00242 } else {
00243 struct SyncNodeElem *ep = &nc->refs[ent->pos];
00244 if (ep->kind & SyncElemKind_leaf) {
00245
00246 struct ccn_buf_decoder bd;
00247 struct ccn_buf_decoder *d = SyncInitDecoderFromOffset(&bd,
00248 nc,
00249 ep->start,
00250 ep->stop);
00251 struct ccn_charbuf *cb = ccn_charbuf_create();
00252 int res = SyncAppendElementInner(cb, d);
00253 if (res < 0) {
00254
00255 ccn_charbuf_destroy(&cb);
00256 return SCR_error;
00257 }
00258 SyncNameAccumAppend(accum, cb, 0);
00259 ent->pos++;
00260 } else {
00261 ent = SyncTreeWorkerPush(head);
00262 if (ent == NULL) {
00263 return SCR_error;
00264 }
00265 }
00266 }
00267
00268 }
00269 return SCR_after;
00270 }
00271
00272 extern int
00273 SyncTreeMarkReachable(struct SyncTreeWorkerHead *head, int minLevel) {
00274 int count = 0;
00275 while (head->level > minLevel) {
00276 struct SyncTreeWorkerEntry *ent = SyncTreeWorkerTop(head);
00277 if (ent == NULL) break;
00278 struct SyncHashCacheEntry *ce = ent->cacheEntry;
00279 if (ce == NULL) break;
00280 ce->state |= SyncHashState_marked;
00281 count++;
00282 struct SyncNodeComposite *nc = ((head->remote > 0) ? ce->ncR : ce->ncL);
00283 if (nc == NULL) break;
00284 int lim = nc->refLen;
00285 if (ent->pos >= lim) {
00286
00287 ent = SyncTreeWorkerPop(head);
00288 if (ent == NULL) break;
00289 ent->pos++;
00290 } else {
00291 struct SyncNodeElem *ep = &nc->refs[ent->pos];
00292 if (ep->kind & SyncElemKind_leaf) {
00293
00294 ent->pos++;
00295 } else {
00296
00297 ent = SyncTreeWorkerPush(head);
00298 if (ent == NULL) break;
00299 }
00300 }
00301 }
00302 return count;
00303 }
00304
00305