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