SyncRoot.c

Go to the documentation of this file.
00001 /**
00002  * @file sync/SyncRoot.c
00003  *  
00004  * Part of CCNx Sync.
00005  */
00006 /*
00007  * Copyright (C) 2011-2012 Palo Alto Research Center, Inc.
00008  *
00009  * This library is free software; you can redistribute it and/or modify it
00010  * under the terms of the GNU Lesser General Public License version 2.1
00011  * as published by the Free Software Foundation.
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00015  * Lesser General Public License for more details. You should have received
00016  * a copy of the GNU Lesser General Public License along with this library;
00017  * if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
00018  * Fifth Floor, Boston, MA 02110-1301 USA.
00019  */
00020 
00021 #include <stdlib.h>
00022 #include <string.h>
00023 #include <strings.h>
00024 
00025 #include <ccn/ccn.h>
00026 #include <ccn/charbuf.h>
00027 #include <ccn/coding.h>
00028 #include <ccn/digest.h>
00029 #include <ccn/indexbuf.h>
00030 #include <ccn/schedule.h>
00031 #include <ccn/uri.h>
00032 #include <ccnr/ccnr_msg.h>
00033 
00034 #include "SyncMacros.h"
00035 #include "SyncPrivate.h"
00036 #include "SyncActions.h"
00037 #include "SyncHashCache.h"
00038 #include "SyncUtil.h"
00039 #include "SyncRoot.h"
00040 
00041 ///////////////////////////////////////////////////////
00042 // Routines for root management
00043 ///////////////////////////////////////////////////////
00044 
00045 /**
00046  * copies the filter, including copies of the names
00047  */
00048 static struct SyncNameAccum *
00049 copyFilter(struct SyncNameAccum *filter) {
00050     int i = 0;
00051     int len = filter->len;
00052     struct SyncNameAccum *canon = SyncAllocNameAccum(len);
00053     for (i = 0; i < len; i++) {
00054         struct ccn_charbuf *name = filter->ents[i].name;
00055         struct ccn_charbuf *copy = ccn_charbuf_create();
00056         ccn_charbuf_append_charbuf(copy, name);
00057         canon->ents[i].name = copy;
00058         canon->ents[i].data = filter->ents[i].data;
00059         
00060     }
00061     canon->len = len;
00062     return canon;
00063 }
00064 
00065 /**
00066  * canonicalizes the filter
00067  * returns an existing equivalent filter if one is found
00068  * otherwise copies the input filter, links it in, and returns the copy
00069  */
00070 static struct SyncNameAccum *
00071 canonFilter(struct SyncBaseStruct *base, struct SyncNameAccum *filter) {
00072     struct SyncPrivate *priv = base->priv;
00073     struct SyncNameAccumList *filters = priv->filters;
00074     while (filters != NULL) {
00075         struct SyncNameAccum *accum = filters->accum;
00076         if (accum != NULL) {
00077             if (accum->len == filter->len) {
00078                 int i = 0;
00079                 int equal = 1;
00080                 while (i < filter->len) {
00081                     struct ccn_charbuf *x = filter->ents[i].name;
00082                     struct ccn_charbuf *y = accum->ents[i].name;
00083                     if (SyncCmpNames(x, y) != 0) {
00084                         equal = 0;
00085                         break;
00086                     }
00087                     i++;
00088                 }
00089                 if (equal)
00090                     // found an existing filter
00091                     return accum;
00092             }
00093         }
00094         filters = filters->next;
00095     }
00096     // copy the filter, then link it in to the private data
00097     struct SyncNameAccum *canon = copyFilter(filter);
00098     filters = NEW_STRUCT(1, SyncNameAccumList);
00099     filters->next = priv->filters;
00100     priv->filters = filters;
00101     filters->accum = canon;
00102     return canon;
00103 }
00104 
00105 extern struct SyncRootStruct *
00106 SyncAddRoot(struct SyncBaseStruct *base,
00107             int syncScope,
00108             const struct ccn_charbuf *topoPrefix,
00109             const struct ccn_charbuf *namingPrefix,
00110             struct SyncNameAccum *filter) {
00111     struct SyncRootStruct *root = NEW_STRUCT(1, SyncRootStruct);
00112     struct SyncPrivate *priv = base->priv;
00113     int newTopo = 0;
00114     root->base = base;
00115     root->priv = NEW_STRUCT(1, SyncRootPrivate);
00116     root->priv->stats = NEW_STRUCT(1, SyncRootStats);
00117     int64_t now = SyncCurrentTime();
00118     root->priv->lastAdvise = now;
00119     root->priv->lastUpdate = now;
00120     root->priv->stablePoint = CCNR_NULL_HWM;
00121     root->priv->lastUpdate = CCNR_NULL_HWM;
00122     if (syncScope < 1 || syncScope > 2)
00123         // invalid scopes treated as unscoped
00124         syncScope = -1;
00125     root->priv->syncScope = syncScope;
00126     root->priv->sliceBusy = -1;
00127     base->lastRootId++;
00128     root->rootId = base->lastRootId;
00129     if (topoPrefix != NULL) {
00130         int oldLen = priv->topoAccum->len;
00131         root->topoPrefix = SyncNameAccumCanon(priv->topoAccum, topoPrefix);
00132         if (oldLen < priv->topoAccum->len) newTopo++;
00133     }
00134     if (namingPrefix != NULL) {
00135         root->namingPrefix = SyncNameAccumCanon(priv->prefixAccum, namingPrefix);
00136     }
00137     if (filter != NULL) {
00138         root->filter = canonFilter(base, filter);
00139     }
00140     struct SyncRootStruct *lag = priv->rootHead;
00141     while (lag != NULL) {
00142         struct SyncRootStruct *next = lag->next;
00143         if (next == NULL) break;
00144         lag = next;
00145     }
00146     if (lag != NULL) lag->next = root;
00147     else priv->rootHead = root;
00148     priv->nRoots++;
00149     struct SyncHashCacheHead *ch = SyncHashCacheCreate(root, 64);
00150     root->ch = ch;
00151     root->currentHash = ccn_charbuf_create(); // initially empty!
00152     
00153     // init the state for name processing
00154     root->namesToAdd = SyncAllocNameAccum(0);
00155     root->namesToFetch = SyncAllocNameAccum(0);
00156     
00157     root->sliceCoding = ccn_charbuf_create();
00158     root->sliceHash = ccn_charbuf_create();
00159     if (SyncRootAppendSlice(root->sliceCoding, root) >= 0) {
00160         // make a hash code from the encoding
00161         struct ccn_digest *cow = ccn_digest_create(CCN_DIGEST_DEFAULT);
00162         size_t sz = ccn_digest_size(cow);
00163         unsigned char *dst = ccn_charbuf_reserve(root->sliceHash, sz);
00164         ccn_digest_init(cow);
00165         ccn_digest_update(cow, root->sliceCoding->buf, root->sliceCoding->length);
00166         ccn_digest_final(cow, dst, sz);
00167         root->sliceHash->length = sz;
00168         ccn_digest_destroy(&cow);
00169     }
00170     
00171     SyncRegisterInterests(root);
00172     return root;
00173 }
00174 
00175 extern struct SyncRootStruct *
00176 SyncRemRoot(struct SyncRootStruct *root) {
00177     if (root == NULL || root->base == NULL || root->compare != NULL)
00178         // NOTE: caller must ensure that there are no comparisons active!
00179         return root;
00180     struct SyncActionData *actions = root->actions;
00181     root->actions = NULL;
00182     while (actions != NULL) {
00183         // mark each interest as inactive, let the timeout free the data
00184         struct SyncActionData *next = actions->next;
00185         actions->root = NULL;
00186         actions->next = NULL;
00187         actions = next;
00188     }
00189     struct SyncBaseStruct *base = root->base;
00190     struct SyncPrivate *priv = base->priv;
00191     struct SyncRootStruct *lag = NULL;
00192     struct SyncRootStruct *this = priv->rootHead;
00193     while (this != NULL) {
00194         struct SyncRootStruct *next = this->next;
00195         if (this == root) {
00196             struct SyncRootPrivate *rp = root->priv;
00197             if (lag != NULL) lag->next = next;
00198             else priv->rootHead = next;
00199             if (root->ch != NULL)
00200                 root->ch = SyncHashCacheFree(root->ch);
00201             if (root->currentHash != NULL)
00202                 ccn_charbuf_destroy(&root->currentHash);
00203             if (root->namesToAdd != NULL)
00204                 SyncFreeNameAccumAndNames(root->namesToAdd);
00205             if (root->namesToFetch != NULL)
00206                 SyncFreeNameAccumAndNames(root->namesToFetch);
00207             if (root->sliceCoding != NULL)
00208                 ccn_charbuf_destroy(&root->sliceCoding);
00209             if (root->sliceHash != NULL)
00210                 ccn_charbuf_destroy(&root->sliceHash);
00211             if (rp != NULL) {
00212                 if (rp->stats != NULL) free(rp->stats);
00213                 struct SyncHashInfoList *list = rp->remoteSeen;
00214                 while (list != NULL) {
00215                     struct SyncHashInfoList *lag = list;
00216                     list = list->next;
00217                     free(lag);
00218                 }
00219                 list = rp->localMade;
00220                 while (list != NULL) {
00221                     struct SyncHashInfoList *lag = list;
00222                     list = list->next;
00223                     free(lag);
00224                 }
00225                 
00226                 struct SyncRootDeltas *deltas = rp->deltasHead;
00227                 while (deltas != NULL) {
00228                     struct SyncRootDeltas *next = deltas->next;
00229                     ccn_charbuf_destroy(&deltas->coding);
00230                     ccn_charbuf_destroy(&deltas->name);
00231                     ccn_charbuf_destroy(&deltas->cob);
00232                     free(deltas);
00233                     deltas = next;
00234                 }
00235                 if (rp->remoteDeltas != NULL) {
00236                     SyncFreeNameAccumAndNames(rp->remoteDeltas);
00237                 }
00238                 free(rp);
00239             }
00240             free(root);
00241             priv->nRoots--;
00242             break;
00243         }
00244         lag = this;
00245         this = next;
00246     }
00247     return NULL;
00248 }
00249 
00250 extern struct SyncRootStruct *
00251 SyncRootDecodeAndAdd(struct SyncBaseStruct *base,
00252                      struct ccn_buf_decoder *d) {
00253     struct SyncRootStruct *root = NULL;
00254     if (ccn_buf_match_dtag(d, CCN_DTAG_SyncConfigSlice)) {
00255         int oops = 0;
00256         ccn_buf_advance(d);
00257         uintmax_t vers = SyncParseUnsigned(d, CCN_DTAG_SyncVersion);
00258         if (vers == SLICE_VERSION) {
00259             struct ccn_charbuf *topo = SyncExtractName(d);
00260             struct ccn_charbuf *prefix = SyncExtractName(d);
00261             struct SyncNameAccum *filter = SyncAllocNameAccum(4);
00262             if (ccn_buf_match_dtag(d, CCN_DTAG_SyncConfigSliceList)) {
00263                 ccn_buf_advance(d);
00264                 while (ccn_buf_match_dtag(d, CCN_DTAG_SyncConfigSliceOp)) {
00265                     uintmax_t op = SyncParseUnsigned(d, CCN_DTAG_SyncConfigSliceOp);
00266                     struct ccn_charbuf *clause = SyncExtractName(d);
00267                     if (op != 0 || clause == NULL) {
00268                         oops++;
00269                         break;
00270                     }
00271                     SyncNameAccumAppend(filter, clause, op);
00272                 }
00273                 ccn_buf_check_close(d);
00274                 if (SyncCheckDecodeErr(d)) oops++;
00275             }
00276             ccn_buf_check_close(d);
00277             if (SyncCheckDecodeErr(d)) oops++;
00278             if (oops == 0) {
00279                 // TBD: extract the scope from the slice
00280                 root = SyncAddRoot(base, base->priv->syncScope, topo, prefix, filter);
00281             }
00282             // regardless of success, the temporary storage must be returned
00283             if (topo != NULL) ccn_charbuf_destroy(&topo);
00284             if (prefix != NULL) ccn_charbuf_destroy(&prefix);
00285             if (filter != NULL) SyncFreeNameAccumAndNames(filter);
00286         }
00287     }
00288     return root;
00289 }
00290 
00291 static int
00292 appendName(struct ccn_charbuf *cb, struct ccn_charbuf *name) {
00293     // we use this to append a name when the name might be NULL
00294     // the slice encoding depends on position
00295     int res = 0;
00296     if (name == NULL) {
00297         name = ccn_charbuf_create();
00298         ccn_name_init(name);
00299         res |= ccn_charbuf_append_charbuf(cb, name);
00300         ccn_charbuf_destroy(&name);
00301     } else
00302         res |= ccn_charbuf_append_charbuf(cb, name);
00303     return res;
00304 }
00305 
00306 extern int
00307 SyncRootAppendSlice(struct ccn_charbuf *cb, struct SyncRootStruct *root) {
00308     int res = 0;
00309     res |= ccnb_element_begin(cb, CCN_DTAG_SyncConfigSlice);
00310     res |= SyncAppendTaggedNumber(cb, CCN_DTAG_SyncVersion, SLICE_VERSION);
00311     // TBD: encode the scope
00312     res |= appendName(cb, root->topoPrefix);
00313     res |= appendName(cb, root->namingPrefix);
00314     res |= ccnb_element_begin(cb, CCN_DTAG_SyncConfigSliceList);
00315     struct SyncNameAccum *filter = root->filter;
00316     if (res >= 0 && filter != NULL) {
00317         int i = 0;
00318         for (i = 0; i < filter->len; i++) {
00319             struct ccn_charbuf *clause = filter->ents[i].name;
00320             res |= SyncAppendTaggedNumber(cb, CCN_DTAG_SyncConfigSliceOp, 0);
00321             res |= ccn_charbuf_append_charbuf(cb, clause);
00322             if (res < 0) break;
00323         }
00324     }
00325     res |= ccnb_element_end(cb);
00326     res |= ccnb_element_end(cb);
00327     return res;
00328 }
00329 
00330 extern struct SyncHashCacheEntry *
00331 SyncRootTopEntry(struct SyncRootStruct *root) {
00332     if (root->currentHash->length > 0) {
00333         struct ccn_charbuf *hash = root->currentHash;
00334         struct SyncHashCacheEntry *ent = SyncHashLookup(root->ch,
00335                                                         hash->buf,
00336                                                         hash->length);
00337         return ent;
00338     }
00339     return NULL;
00340 }
00341 
00342 extern enum SyncRootLookupCode
00343 SyncRootLookupName(struct SyncRootStruct *root,
00344                    const struct ccn_charbuf *name) {
00345     int skip = 0;
00346     if (name == NULL)
00347         // and why were we called?
00348         return SyncRootLookupCode_error;
00349     if (root->namingPrefix != NULL) {
00350         skip = SyncPrefixMatch(root->namingPrefix, name, 0);
00351         if (skip < 0) return SyncRootLookupCode_error;
00352         if (skip == 0) return SyncRootLookupCode_none;
00353     }
00354     skip = SyncComponentCount(root->namingPrefix);
00355     enum SyncRootLookupCode res = SyncRootLookupCode_covered;
00356     struct SyncNameAccum *filter = root->filter;
00357     if (filter != NULL && filter->len > 0) {
00358         // if present, there are restrictions, relative to the prefix
00359         int i = 0;
00360         res = SyncRootLookupCode_none;
00361         for (i = 0; i < filter->len; i++) {
00362             struct ccn_charbuf *pat = filter->ents[i].name;
00363             int match = SyncPatternMatch(pat, name, skip);
00364             if (match < 0) {
00365                 res = SyncRootLookupCode_error;
00366                 break;
00367             }
00368             if (match > 0) {
00369                 res = SyncRootLookupCode_covered;
00370                 break;
00371             }
00372         }
00373         if (res == SyncRootLookupCode_none && root->base->debug > 16) {
00374             struct ccn_charbuf *uri = ccn_charbuf_create();
00375             ccn_uri_append(uri, name->buf, name->length, 0);
00376             char *str = ccn_charbuf_as_string(uri);
00377             ccnr_msg(root->base->client_handle, "SyncRootLookupName, rejected %s", str);
00378             ccn_charbuf_destroy(&uri);
00379         }
00380     }
00381     return res;
00382 }
00383 
00384 
Generated on Tue Aug 21 14:54:19 2012 for Content-Centric Networking in C by  doxygen 1.6.3