SyncNode.c

Go to the documentation of this file.
00001 /**
00002  * @file sync/SyncNode.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 
00022 #include "SyncNode.h"
00023 #include "SyncUtil.h"
00024 
00025 #include <stdlib.h>
00026 #include <string.h>
00027 #include <strings.h>
00028 
00029 extern int
00030 SyncSetCompErr(struct SyncNodeComposite *nc, int val) {
00031     SyncNoteErr("setErr");
00032     if (nc->err >= 0) nc->err = val;
00033     return val;
00034 }
00035 
00036 extern int
00037 SyncCheckCompErr(struct SyncNodeComposite *nc) {
00038     return nc->err < 0;
00039 }
00040 
00041 extern struct ccn_buf_decoder *
00042 SyncInitDecoderFromOffset(struct ccn_buf_decoder *d,
00043                           struct SyncNodeComposite *nc,
00044                           ssize_t start, ssize_t stop) {
00045     d = SyncInitDecoderFromCharbufRange(d, nc->cb, start, stop);
00046     return d;
00047 }
00048 
00049 /**
00050  * Makes a decoder from an element.
00051  */
00052 extern struct ccn_buf_decoder *
00053 SyncInitDecoderFromElem(struct ccn_buf_decoder *d,
00054                         struct SyncNodeComposite *nc,
00055                         struct SyncNodeElem *ep) {
00056     d = SyncInitDecoderFromCharbufRange(d, nc->cb, ep->start, ep->stop);
00057     return d;
00058 }
00059 
00060 
00061 extern void
00062 SyncNodeIncRC(struct SyncNodeComposite *nc) {
00063     int rc = nc->rc+1;
00064     if (rc > 0) nc->rc = rc;
00065 }
00066 
00067 extern struct SyncNodeComposite *
00068 SyncNodeDecRC(struct SyncNodeComposite *nc) {
00069     int rc = nc->rc;
00070     if (rc > 1) {
00071         nc->rc = rc-1;
00072         return nc;
00073     }
00074     nc->rc = 0;
00075     SyncFreeComposite(nc);
00076     return NULL;
00077 }
00078 
00079 ////////////////////////////////////////
00080 // Routines for comparison support
00081 ////////////////////////////////////////
00082 
00083 extern enum SyncCompareResult
00084 SyncNodeCompareMinMax(struct SyncNodeComposite *nc, struct ccn_charbuf *name) {
00085     ssize_t cmp = 0;
00086     
00087     cmp = SyncCmpNames(name, nc->minName);
00088     if (cmp < 0) return SCR_before;
00089     if (cmp == 0) return SCR_min;
00090     
00091     cmp = SyncCmpNames(name, nc->maxName);
00092     if (cmp < 0) return SCR_inside;
00093     if (cmp == 0) return SCR_max;
00094     return SCR_after;
00095 }
00096 
00097 
00098 extern enum SyncCompareResult
00099 SyncNodeCompareLeaf(struct SyncNodeComposite *nc,
00100                     struct SyncNodeElem *ep,
00101                     struct ccn_charbuf *name) {
00102     struct ccn_buf_decoder cmpDec;
00103     struct ccn_buf_decoder *cmpD = NULL;
00104     struct ccn_buf_decoder nameDec;
00105     struct ccn_buf_decoder *nameD = NULL;
00106     if (ep->kind & SyncElemKind_leaf) {
00107         // a leaf, as it should be
00108         cmpD = SyncInitDecoderFromOffset(&cmpDec, nc, ep->start, ep->stop);
00109         nameD = SyncInitDecoderFromCharbuf(&nameDec, name, 0);
00110         int cmp = SyncCmpNamesInner(nameD, cmpD);
00111         if (cmp == 0) return SCR_min;
00112         if (cmp == SYNC_BAD_CMP) return SCR_error;
00113         if (cmp < 0) return SCR_before;
00114         return SCR_after;
00115     } else {
00116         return SCR_inside;
00117     }
00118 }
00119 
00120 ////////////////////////////////////////
00121 // Routines for building CompositeNodes
00122 ////////////////////////////////////////
00123 
00124 // resetComposite resets a composite node to its initial state
00125 // except that it retains any allocated storage
00126 extern void
00127 SyncResetComposite(struct SyncNodeComposite *nc) {
00128     struct ccn_charbuf *cb = nc->cb;
00129     if (nc->minName != NULL) ccn_charbuf_destroy(&nc->minName);
00130     nc->minName = NULL;
00131     if (nc->maxName != NULL) ccn_charbuf_destroy(&nc->maxName);
00132     nc->maxName = NULL;
00133     if (nc->content != NULL) ccn_charbuf_destroy(&nc->content);
00134     nc->content = NULL;
00135     if (nc->hash != NULL) ccn_charbuf_destroy(&nc->hash);
00136     nc->hash = NULL;
00137     if (cb == NULL) {
00138         cb = ccn_charbuf_create();
00139         nc->cb = cb;
00140     }
00141     cb->length = 0;
00142     ccnb_element_begin(cb, CCN_DTAG_SyncNode);
00143     SyncAppendTaggedNumber(cb, CCN_DTAG_SyncVersion, SYNC_VERSION);
00144     ccnb_element_begin(cb, CCN_DTAG_SyncNodeElements);
00145     nc->longHash.pos = MAX_HASH_BYTES;
00146     nc->rc = 0;
00147     nc->refLen = 0;
00148     nc->err = 0;
00149     nc->leafCount = 0;
00150     nc->treeDepth = 1;
00151     nc->byteCount = 0;
00152 }
00153 
00154 // SyncAllocComposite allocates a new, empty, composite object
00155 extern struct SyncNodeComposite *
00156 SyncAllocComposite(struct SyncBaseStruct *base) {
00157     struct SyncNodeComposite *nc = NEW_STRUCT(1, SyncNodeComposite);
00158     nc->base = base;
00159     SyncResetComposite(nc);
00160     return nc;
00161 }
00162 
00163 // SyncExtendComposite extends the references section of a composite object
00164 // with a new offset
00165 // extending the encoding and obtaining the offset is handled separately
00166 extern void
00167 SyncExtendComposite(struct SyncNodeComposite *nc,
00168                     SyncElemKind kind,
00169                     ssize_t start, ssize_t stop) {
00170     int oldLen = nc->refLen;
00171     int newLen = oldLen+1;
00172     struct SyncNodeElem *refs = nc->refs;
00173     if (newLen >= nc->refLim) {
00174         // need to extend
00175         int newLim = newLen + newLen / 2 + 4;
00176         struct SyncNodeElem *lag = refs;
00177         refs = NEW_STRUCT(newLim, SyncNodeElem);
00178         if (lag != NULL) {
00179             if (oldLen > 0)
00180                 memmove(refs, lag, oldLen*sizeof(struct SyncNodeElem));
00181             free(lag);
00182         }
00183         nc->refLim = newLim;
00184         nc->refs = refs;
00185     }
00186     refs[oldLen].kind = kind;
00187     refs[oldLen].start = start;
00188     refs[oldLen].stop = stop;
00189     nc->refLen = newLen;
00190 }
00191 
00192 extern void
00193 SyncNodeMaintainMinMax(struct SyncNodeComposite *nc,
00194                        const struct ccn_charbuf *name) {
00195     struct ccn_charbuf *x = nc->minName;
00196     if (x == NULL) {
00197         x = ccn_charbuf_create();
00198         ccn_charbuf_append_charbuf(x, name);
00199     } else if (SyncCmpNames(name, x) < 0) {
00200         ccn_charbuf_reset(x);
00201         ccn_charbuf_append_charbuf(x, name);
00202     }
00203     nc->minName = x;
00204     x = nc->maxName;
00205     if (x == NULL) {
00206         x = ccn_charbuf_create();
00207         ccn_charbuf_append_charbuf(x, name);
00208     } else if (SyncCmpNames(name, x) > 0) {
00209         ccn_charbuf_reset(x);
00210         ccn_charbuf_append_charbuf(x, name);
00211     }
00212     nc->maxName = x;
00213 }
00214 
00215 extern void
00216 SyncNodeAddName(struct SyncNodeComposite *nc,
00217                 const struct ccn_charbuf *name) {
00218     struct ccn_charbuf *cb = nc->cb;
00219     ssize_t start = cb->length;
00220     SyncAppendElement(cb, name);
00221     ssize_t stop = cb->length;
00222     nc->leafCount++;
00223     SyncNodeMaintainMinMax(nc, name);
00224     SyncExtendComposite(nc, SyncElemKind_leaf, start, stop);
00225     SyncAccumHash(&nc->longHash, name);
00226 }
00227 
00228 extern void
00229 SyncNodeAddNode(struct SyncNodeComposite *nc,
00230                 struct SyncNodeComposite *node) {
00231     struct ccn_charbuf *cb = nc->cb;
00232     ssize_t start = cb->length;
00233     SyncNodeAppendLongHash(cb, node);
00234     ssize_t stop = cb->length;
00235     struct ccn_buf_decoder xds;
00236     struct ccn_buf_decoder *xd = SyncInitDecoderFromCharbufRange(&xds, cb, start, stop);
00237     SyncAccumHashInner(&nc->longHash, xd);
00238     SyncExtendComposite(nc, SyncElemKind_node, start, stop);
00239     unsigned nDepth = node->treeDepth+1;
00240     if (nDepth > nc->treeDepth) nc->treeDepth = nDepth;
00241     nc->byteCount = nc->byteCount + node->byteCount + node->cb->length;
00242     nc->leafCount = nc->leafCount + node->leafCount;
00243     SyncNodeMaintainMinMax(nc, node->minName);
00244     SyncNodeMaintainMinMax(nc, node->maxName);
00245 }
00246 
00247 extern int
00248 SyncNodeAppendLongHash(struct ccn_charbuf *cb, struct SyncNodeComposite *nc) {
00249     int pos = nc->longHash.pos;
00250     int len = MAX_HASH_BYTES-pos;
00251     int res = -1;
00252     if (len > 0) res = ccnb_append_tagged_blob(cb, CCN_DTAG_SyncContentHash,
00253                                                nc->longHash.bytes+pos,
00254                                                len);
00255     return res;
00256 }
00257 
00258 // SyncEndComposite finishes up the encoding
00259 // we can get into parsing problems for names and hashes
00260 extern void
00261 SyncEndComposite(struct SyncNodeComposite *nc) {
00262     if (!SyncCheckCompErr(nc) && nc->hash == NULL) {
00263         int res = 0;
00264         struct ccn_charbuf *cb = nc->cb;
00265         
00266         // terminate the references
00267         res |= ccnb_element_end(cb);
00268         
00269         // output the hash
00270         struct SyncLongHashStruct *hp = &nc->longHash;
00271         SyncNodeAppendLongHash(cb, nc);
00272         nc->hash = SyncLongHashToBuf(hp);
00273         
00274         // output the minName and maxName
00275         
00276         SyncAppendElement(cb, nc->minName);
00277         SyncAppendElement(cb, nc->maxName);
00278         
00279         res |= SyncAppendTaggedNumber(cb, CCN_DTAG_SyncNodeKind, nc->kind);
00280         res |= SyncAppendTaggedNumber(cb, CCN_DTAG_SyncLeafCount, nc->leafCount);
00281         res |= SyncAppendTaggedNumber(cb, CCN_DTAG_SyncTreeDepth, nc->treeDepth);
00282         res |= SyncAppendTaggedNumber(cb, CCN_DTAG_SyncByteCount, nc->byteCount);
00283         res |= ccnb_element_end(cb);
00284         if (res != 0) SyncSetCompErr(nc, -__LINE__);
00285     }
00286 }
00287 
00288 // freeComposite returns the storage for the composite object
00289 extern void
00290 SyncFreeComposite(struct SyncNodeComposite *nc) {
00291     if (nc == NULL) return;
00292     SyncResetComposite(nc);
00293     if (nc->cb != NULL)
00294         ccn_charbuf_destroy(&nc->cb);
00295     if (nc->refs != NULL) {
00296         free(nc->refs);
00297         nc->refs = NULL;
00298     }
00299     free(nc);
00300 }
00301 
00302 extern void
00303 SyncWriteComposite(struct SyncNodeComposite *nc, FILE *f) {
00304     fwrite(nc->cb->buf, sizeof(unsigned char), nc->cb->length, f);
00305     fflush(f);
00306 }
00307 
00308 extern int
00309 SyncParseComposite(struct SyncNodeComposite *nc, struct ccn_buf_decoder *d) {
00310     ssize_t startOff = d->decoder.token_index;
00311     unsigned char *base = ((unsigned char *) d->buf)+startOff;
00312     SyncResetComposite(nc);
00313     while (ccn_buf_match_dtag(d, CCN_DTAG_SyncNode)) {
00314         // the while loop is only present to let us break out early on error
00315         ccn_buf_advance(d);
00316         // first, get the version stamp
00317         uintmax_t vers = SyncParseUnsigned(d, CCN_DTAG_SyncVersion);
00318         if (SyncCheckDecodeErr(d) || vers != SYNC_VERSION) {
00319             SyncSetCompErr(nc, -__LINE__);
00320             break;
00321         }
00322         
00323         if (SyncCheckCompErr(nc) == 0 && ccn_buf_match_dtag(d, CCN_DTAG_SyncNodeElements)) {
00324             // we have a refs section
00325             ccn_buf_advance(d);
00326             
00327             for(;;) {
00328                 SyncElemKind kind = SyncElemKind_node;
00329                 ssize_t start = 0;
00330                 if (ccn_buf_match_dtag(d, CCN_DTAG_Name)) {
00331                     // a name, so it's a leaf
00332                     start = SyncParseName(d);
00333                     kind = SyncElemKind_leaf;
00334                 } else if (ccn_buf_match_dtag(d, CCN_DTAG_SyncContentHash)) {
00335                     // a hash, so it's a composite
00336                     start = SyncParseHash(d);
00337                 } else  {
00338                     ccn_buf_check_close(d);
00339                     break;
00340                 }
00341                 if (SyncCheckDecodeErr(d))  {
00342                     SyncSetCompErr(nc, -__LINE__);
00343                     break;
00344                 }
00345                 ssize_t stop = d->decoder.token_index;
00346                 SyncExtendComposite(nc, kind, start, stop);
00347             }
00348             
00349         }
00350         if (SyncCheckCompErr(nc)) break;
00351         
00352         if (ccn_buf_match_dtag(d, CCN_DTAG_SyncContentHash)) {
00353             const unsigned char * xp = NULL;
00354             size_t xs = 0;
00355             ccn_buf_advance(d);
00356             if (ccn_buf_match_blob(d, &xp, &xs)) {
00357                 ccn_buf_advance(d);
00358                 ccn_buf_check_close(d);
00359             } else {
00360                 nc->longHash.pos = 0;
00361                 SyncSetCompErr(nc, -__LINE__);
00362            }
00363             if (xp != NULL && xs > 0 && xs <= (ssize_t) MAX_HASH_BYTES) {
00364                 // fill the long hash from the raw hash bytes
00365                 // also fill the hash charbuf
00366                 int pos = MAX_HASH_BYTES-xs;
00367                 memcpy(&nc->longHash.bytes[pos], xp, xs);
00368                 nc->longHash.pos = pos;
00369                 nc->hash = SyncLongHashToBuf(&nc->longHash);
00370             } else {
00371                 // not so good
00372                 nc->longHash.pos = 0;
00373                 SyncSetCompErr(nc, -__LINE__);
00374             }
00375         } else {
00376             // we are supposed to have the hash code here
00377             SyncSetCompErr(nc, -__LINE__);
00378             break;
00379         }
00380         
00381         nc->minName = SyncExtractName(d);
00382         if (SyncCheckDecodeErr(d)) {
00383             SyncSetCompErr(nc, -__LINE__);
00384             break;
00385         }
00386         nc->maxName = SyncExtractName(d);
00387         if (SyncCheckDecodeErr(d)) {
00388             SyncSetCompErr(nc, -__LINE__);
00389             break;
00390         }
00391         
00392         nc->kind = (SyncNodeKind) SyncParseUnsigned(d, CCN_DTAG_SyncNodeKind);
00393         if (SyncCheckDecodeErr(d)) {
00394             SyncSetCompErr(nc, -__LINE__);
00395             break;
00396         }
00397         nc->leafCount = SyncParseUnsigned(d, CCN_DTAG_SyncLeafCount);
00398         if (SyncCheckDecodeErr(d)) {
00399             SyncSetCompErr(nc, -__LINE__);
00400             break;
00401         }
00402         nc->treeDepth = SyncParseUnsigned(d, CCN_DTAG_SyncTreeDepth);
00403         if (SyncCheckDecodeErr(d)) {
00404             SyncSetCompErr(nc, -__LINE__);
00405             break;
00406         }
00407         nc->byteCount = SyncParseUnsigned(d, CCN_DTAG_SyncByteCount);
00408         if (SyncCheckDecodeErr(d)) {
00409             SyncSetCompErr(nc, -__LINE__);
00410             break;
00411         }
00412         ccn_buf_check_close(d);
00413         if (SyncCheckDecodeErr(d)) {
00414             SyncSetCompErr(nc, -__LINE__);
00415         }
00416         break;
00417     }
00418     if (!SyncCheckCompErr(nc)) {
00419         // copy the needed bytes of the encoding
00420         // (note: clobbers anything in nc->cb)
00421         // use d->decoder.index instead of token_index here (no token at end)
00422         int len = d->decoder.index - startOff;
00423         if (len <= 0) {
00424             // should NOT happen!
00425             SyncSetCompErr(nc, -__LINE__);
00426         } else {
00427             struct ccn_charbuf *cb = nc->cb;
00428             cb->length = 0;
00429             ccn_charbuf_reserve(cb, len);
00430             unsigned char *dst = cb->buf;
00431             memcpy(dst, base, len);
00432             cb->length = len;
00433         }
00434     }
00435     return nc->err;
00436 }
00437 
Generated on Tue Aug 21 14:54:19 2012 for Content-Centric Networking in C by  doxygen 1.6.3