SyncTreeWorker.c

Go to the documentation of this file.
00001 /**
00002  * @file sync/SyncTreeWorker.c
00003  *  
00004  * Part of CCNx Sync.
00005  *
00006  * Copyright (C) 2011 Palo Alto Research Center, Inc.
00007  *
00008  * This library is free software; you can redistribute it and/or modify it
00009  * under the terms of the GNU Lesser General Public License version 2.1
00010  * as published by the Free Software Foundation.
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00014  * Lesser General Public License for more details. You should have received
00015  * a copy of the GNU Lesser General Public License along with this library;
00016  * if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
00017  * Fifth Floor, Boston, MA 02110-1301 USA.
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         // no entry?  this is not so good
00096         return NULL;
00097     struct SyncTreeWorkerEntry *stack = head->stack;
00098     int level = head->level;
00099     int oLim = head->lim;
00100     if (level > oLim) {
00101         // something bad has happened
00102         return NULL;
00103     }
00104     if (level == oLim) {
00105         // first, expand the stack to get enough room
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     // now we can push the node
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             // probably a real bug!
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             // report desired node as missing
00178             return SCR_missing;
00179         }
00180         int lim = nc->refLen;
00181         if (ent->pos >= lim) {
00182             // done with the current level, go back to the previous level
00183             ent = SyncTreeWorkerPop(head);
00184             if (ent == NULL) break;
00185             ent->pos++;
00186         } else {
00187             
00188             if (ent->pos == 0) {
00189                 // need to check the min and max of the current node
00190                 enum SyncCompareResult cr = SyncNodeCompareMinMax(nc, name);
00191                 if (cr == SCR_after) {
00192                     // not in this node at all, so pop out
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                     // a leaf, so the element name is inline
00200                     cr = SyncNodeCompareLeaf(nc, ep, name);
00201                     if (cr != SCR_after) return cr;
00202                     ent->pos++;
00203                 } else {
00204                     // a node, so try this recursively
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             // probably a real bug!
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             // TBD: fetch node if not present
00232             return SCR_missing;
00233         }
00234         int lim = nc->refLen;
00235         if (ent->pos >= lim) {
00236             // done with the current level, go back to the previous level
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                 // a leaf, so the element name is inline
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                     // that did not work well
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             // done with the current level, go back to the previous level
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                 // a leaf, so skip it
00292                 ent->pos++;
00293             } else {
00294                 // a node, so push into it
00295                 ent = SyncTreeWorkerPush(head);
00296                 if (ent == NULL) break;
00297             }
00298         }
00299     }
00300     return count;
00301 }
00302 
00303 

Generated on Thu Feb 16 00:44:01 2012 for Content-Centric Networking in C by  doxygen 1.5.6