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 "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         // no entry?  this is not so good
00098         return NULL;
00099     struct SyncTreeWorkerEntry *stack = head->stack;
00100     int level = head->level;
00101     int oLim = head->lim;
00102     if (level > oLim) {
00103         // something bad has happened
00104         return NULL;
00105     }
00106     if (level == oLim) {
00107         // first, expand the stack to get enough room
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     // now we can push the node
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             // probably a real bug!
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             // report desired node as missing
00180             return SCR_missing;
00181         }
00182         int lim = nc->refLen;
00183         if (ent->pos >= lim) {
00184             // done with the current level, go back to the previous level
00185             ent = SyncTreeWorkerPop(head);
00186             if (ent == NULL) break;
00187             ent->pos++;
00188         } else {
00189             
00190             if (ent->pos == 0) {
00191                 // need to check the min and max of the current node
00192                 enum SyncCompareResult cr = SyncNodeCompareMinMax(nc, name);
00193                 if (cr == SCR_after) {
00194                     // not in this node at all, so pop out
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                     // a leaf, so the element name is inline
00202                     cr = SyncNodeCompareLeaf(nc, ep, name);
00203                     if (cr != SCR_after) return cr;
00204                     ent->pos++;
00205                 } else {
00206                     // a node, so try this recursively
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             // probably a real bug!
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             // TBD: fetch node if not present
00234             return SCR_missing;
00235         }
00236         int lim = nc->refLen;
00237         if (ent->pos >= lim) {
00238             // done with the current level, go back to the previous level
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                 // a leaf, so the element name is inline
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                     // that did not work well
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             // done with the current level, go back to the previous level
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                 // a leaf, so skip it
00294                 ent->pos++;
00295             } else {
00296                 // a node, so push into it
00297                 ent = SyncTreeWorkerPush(head);
00298                 if (ent == NULL) break;
00299             }
00300         }
00301     }
00302     return count;
00303 }
00304 
00305 
Generated on Tue Aug 21 14:54:19 2012 for Content-Centric Networking in C by  doxygen 1.6.3