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