SyncNode.c

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

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