SyncRoot.c

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

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