00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
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
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
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
00121
00122
00123
00124
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
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
00163
00164
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
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
00258
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
00266 res |= ccnb_element_end(cb);
00267
00268
00269 struct SyncLongHashStruct *hp = &nc->longHash;
00270 SyncNodeAppendLongHash(cb, nc);
00271 nc->hash = SyncLongHashToBuf(hp);
00272
00273
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
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
00314 ccn_buf_advance(d);
00315
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
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
00331 start = SyncParseName(d);
00332 kind = SyncElemKind_leaf;
00333 } else if (ccn_buf_match_dtag(d, CCN_DTAG_SyncContentHash)) {
00334
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
00364
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
00371 nc->longHash.pos = 0;
00372 SyncSetCompErr(nc, -__LINE__);
00373 }
00374 } else {
00375
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
00419
00420
00421 int len = d->decoder.index - startOff;
00422 if (len <= 0) {
00423
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