00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <stdlib.h>
00019 #include <stdio.h>
00020 #include <string.h>
00021 #include <strings.h>
00022 #include <sys/resource.h>
00023 #include <sys/time.h>
00024
00025 #include <ccn/ccn.h>
00026 #include <ccn/charbuf.h>
00027 #include <ccn/coding.h>
00028 #include <ccn/indexbuf.h>
00029 #include <ccn/schedule.h>
00030
00031 #include <ccnr/ccnr_msg.h>
00032 #include <ccnr/ccnr_sync.h>
00033 #include <ccnr/ccnr_private.h>
00034
00035 #include "SyncActions.h"
00036 #include "SyncNode.h"
00037 #include "SyncPrivate.h"
00038 #include "SyncRoot.h"
00039 #include "SyncTreeWorker.h"
00040 #include "SyncUtil.h"
00041
00042 #define M 1000000
00043
00044
00045 static int useCompExcl = 1;
00046 static int showHighLevel = 1;
00047 static int nDeltasLimit = 4;
00048 static int cachePurgeTrigger = 60;
00049 static int cacheCleanBatch = 16;
00050 static int cacheCleanDelta = 8;
00051 static int adviseNeedReset = 1;
00052 static int updateStallDelta = 15;
00053 static int updateNeedDelta = 6;
00054 static int shortDelayMicros = 1000;
00055 static int compareAssumeBad = 20;
00056 static int nodeSplitTrigger = 4000;
00057 static int exclusionLimit = 600;
00058 static int exclusionTrig = 5;
00059 static int stableTimeTrig = 10;
00060 static int hashSplitTrigger = 17;
00061 static int namesYieldInc = 100;
00062 static int namesYieldMicros = 20*1000;
00063 static char *syncStableSuffix = "SyncStable";
00064
00065 #define SYNC_UPDATE_VERSION (20120307)
00066
00067 enum SyncCompareState {
00068 SyncCompare_init,
00069 SyncCompare_preload,
00070 SyncCompare_busy,
00071 SyncCompare_waiting,
00072 SyncCompare_done
00073 };
00074
00075 struct SyncCompareData {
00076 struct SyncRootStruct *root;
00077 struct SyncTreeWorkerHead *twL;
00078 struct SyncTreeWorkerHead *twR;
00079 struct ccn_charbuf *hashL;
00080 struct ccn_charbuf *hashR;
00081 struct ccn_charbuf *cbL;
00082 struct ccn_charbuf *cbR;
00083 struct ccn_charbuf *lagL;
00084 int *lagMatch;
00085 struct SyncActionData *errList;
00086 int errsQueued;
00087 int namesAdded;
00088 int nodeFetchBusy;
00089 int nodeFetchFailed;
00090 int contentPos;
00091 int contentFetchBusy;
00092 int contentFetchFailed;
00093 struct ccn_scheduled_event *ev;
00094 enum SyncCompareState state;
00095 int64_t lastFetchOK;
00096 int64_t startTime;
00097 int64_t lastEnter;
00098 int64_t lastMark;
00099 int64_t maxHold;
00100 };
00101
00102 enum SyncUpdateState {
00103 SyncUpdate_init,
00104 SyncUpdate_inserted,
00105 SyncUpdate_busy,
00106 SyncUpdate_error,
00107 SyncUpdate_done
00108 };
00109
00110 struct SyncUpdateData {
00111 struct SyncRootStruct *root;
00112 enum SyncUpdateState state;
00113 struct SyncNameAccum *sort;
00114 struct SyncNodeAccum *nodes;
00115 struct SyncTreeWorkerHead *tw;
00116 struct ccn_charbuf *cb;
00117 IndexSorter_Base ixBase;
00118 IndexSorter_Index ixPos;
00119 int nameLenAccum;
00120 int namesAdded;
00121 int initLen;
00122 struct SyncHashCacheEntry *ceStart;
00123 struct SyncHashCacheEntry *ceStop;
00124 int64_t startTime;
00125 int64_t entryTime;
00126 int64_t maxHold;
00127 int preSortCount;
00128 int postSortCount;
00129 struct SyncRootDeltas *deltas;
00130 };
00131
00132
00133
00134
00135
00136 static int
00137 HeartbeatAction(struct ccn_schedule *sched,
00138 void *clienth,
00139 struct ccn_scheduled_event *ev,
00140 int flags);
00141
00142 static int
00143 UpdateAction(struct ccn_schedule *sched,
00144 void *clienth,
00145 struct ccn_scheduled_event *ev,
00146 int flags);
00147
00148 static int
00149 CompareAction(struct ccn_schedule *sched,
00150 void *clienth,
00151 struct ccn_scheduled_event *ev,
00152 int flags);
00153
00154
00155
00156
00157
00158
00159 static int
00160 showCacheEntry(struct SyncRootStruct *root, char *dst, int lim,
00161 char *prefix, struct SyncHashCacheEntry *ce) {
00162 int n = 0;
00163 if (ce == NULL) n = snprintf(dst, lim, "%shash#null", prefix);
00164 else n = snprintf(dst, lim, "%shash#%08x", prefix, (uint32_t) ce->small);
00165 return n;
00166 }
00167
00168 static void
00169 showCacheEntry1(struct SyncRootStruct *root, char *here, char *msg,
00170 struct SyncHashCacheEntry *ce) {
00171 char temp[1024];
00172 showCacheEntry(root, temp, sizeof(temp), "", ce);
00173 SyncNoteSimple2(root, here, msg, temp);
00174 }
00175
00176 static void
00177 showCacheEntry2(struct SyncRootStruct *root, char *here, char *msg,
00178 struct SyncHashCacheEntry *ce1, struct SyncHashCacheEntry *ce2) {
00179 char temp[1024];
00180 int n = showCacheEntry(root, temp, sizeof(temp), "", ce1);
00181 showCacheEntry(root, temp+n, sizeof(temp)-n, ", ", ce2);
00182 SyncNoteSimple2(root, here, msg, temp);
00183 }
00184
00185 static struct SyncActionData *
00186 newActionData(enum SyncRegisterActionKind kind) {
00187 struct SyncActionData *data = NEW_STRUCT(1, SyncActionData);
00188 data->startTime = SyncCurrentTime();
00189 data->kind = kind;
00190 data->state = SyncActionState_init;
00191 return data;
00192 }
00193
00194 static void
00195 linkActionData(struct SyncRootStruct *root, struct SyncActionData *data) {
00196 data->root = root;
00197 data->ce = root->priv->ceCurrent;
00198 data->next = root->actions;
00199 data->client_handle = root->base->client_handle;
00200 data->state = SyncActionState_sent;
00201 root->actions = data;
00202 }
00203
00204 static void
00205 delinkActionData(struct SyncActionData *data) {
00206 if (data == NULL) return;
00207 if (data->state == SyncActionState_sent) {
00208
00209 struct SyncRootStruct *root = data->root;
00210 if (root == NULL) return;
00211 struct SyncActionData *each = root->actions;
00212 struct SyncActionData *lag = NULL;
00213 data->state = SyncActionState_loose;
00214 while (each != NULL) {
00215 struct SyncActionData *next = each->next;
00216 if (data == each) {
00217 data->next = NULL;
00218 if (lag == NULL) root->actions = next;
00219 else lag->next = next;
00220 break;
00221 }
00222 lag = each;
00223 each = next;
00224 }
00225 } else {
00226 if (data->state == SyncActionState_error) {
00227
00228 struct SyncCompareData *comp = data->comp;
00229 if (comp == NULL) return;
00230 struct SyncActionData *each = comp->errList;
00231 struct SyncActionData *lag = NULL;
00232 data->state = SyncActionState_loose;
00233 while (each != NULL) {
00234 struct SyncActionData *next = each->next;
00235 if (data == each) {
00236 data->next = NULL;
00237 if (comp->errsQueued > 0) comp->errsQueued--;
00238 if (lag == NULL) comp->errList = next;
00239 else lag->next = next;
00240 break;
00241 }
00242 lag = each;
00243 each = next;
00244 }
00245 }
00246 }
00247 }
00248
00249 static int
00250 moveActionData(struct SyncActionData *data, enum SyncActionState dstState) {
00251
00252
00253
00254 if (data == NULL) return 0;
00255 if (dstState == SyncActionState_error && data->state != SyncActionState_sent)
00256 return 0;
00257 if (dstState == SyncActionState_sent && data->state != SyncActionState_error)
00258 return 0;
00259 struct SyncRootStruct *root = data->root;
00260 struct SyncCompareData *comp = data->comp;
00261 if (root == NULL || comp == NULL) return 0;
00262 delinkActionData(data);
00263 if (dstState == SyncActionState_sent) {
00264 data->next = root->actions;
00265 root->actions = data;
00266 } else {
00267 data->next = comp->errList;
00268 comp->errList = data;
00269 comp->errsQueued++;
00270 }
00271 data->state = dstState;
00272 return 1;
00273 }
00274
00275 static struct SyncActionData *
00276 destroyActionData(struct SyncActionData *data) {
00277 if (data != NULL) {
00278 delinkActionData(data);
00279
00280 if (data->prefix != NULL)
00281 ccn_charbuf_destroy(&data->prefix);
00282 if (data->hash != NULL)
00283 ccn_charbuf_destroy(&data->hash);
00284 data->next = NULL;
00285 data->root = NULL;
00286 data->comp = NULL;
00287 free(data);
00288 }
00289 return NULL;
00290 }
00291
00292 static char *
00293 getCmdStr(enum SyncRegisterActionKind kind) {
00294 switch (kind) {
00295 case SRI_Kind_AdviseInt:
00296 case SRI_Kind_RootAdvise:
00297 return "\xC1.S.ra";
00298 case SRI_Kind_FetchInt:
00299 case SRI_Kind_NodeFetch:
00300 return "\xC1.S.nf";
00301 case SRI_Kind_RootStats:
00302 return "\xC1.S.rs";
00303 default:
00304 return NULL;
00305 }
00306 }
00307
00308 static char *
00309 getKindStr(enum SyncRegisterActionKind kind) {
00310 switch (kind) {
00311 case SRI_Kind_None:
00312 return "None";
00313 case SRI_Kind_AdviseInt:
00314 case SRI_Kind_RootAdvise:
00315 return "RootAdvise";
00316 case SRI_Kind_FetchInt:
00317 case SRI_Kind_NodeFetch:
00318 return "NodeFetch";
00319 case SRI_Kind_RootStats:
00320 return "RootStats";
00321 case SRI_Kind_Content:
00322 return "Content";
00323 default:
00324 return NULL;
00325 }
00326 }
00327
00328 static void
00329 setCovered(struct SyncHashCacheEntry *ce) {
00330 char *here = "Sync.setCovered";
00331 if (ce->state & SyncHashState_covered) {
00332
00333 } else if (ce->state & SyncHashState_remote) {
00334
00335 struct SyncRootStruct *root = ce->head->root;
00336 if (root->base->debug >= CCNL_FINER) {
00337 char *hex = SyncHexStr(ce->hash->buf, ce->hash->length);
00338 SyncNoteSimple(root, here, hex);
00339 free(hex);
00340 }
00341 ce->state |= SyncHashState_covered;
00342 }
00343 }
00344
00345 static int
00346 isCovered(struct SyncHashCacheEntry *ce) {
00347 if (ce == NULL) return 1;
00348 if (ce->state & SyncHashState_covered) return 1;
00349 if (ce->state & SyncHashState_local) {
00350 setCovered(ce);
00351 return 1;
00352 }
00353 return 0;
00354 }
00355
00356 static int
00357 compareHash(struct ccn_charbuf *hashX, struct ccn_charbuf *hashY) {
00358 if (hashX == hashY) return 0;
00359 if (hashX == NULL) return -1;
00360 if (hashY == NULL) return 1;
00361 size_t lenX = hashX->length;
00362 size_t lenY = hashY->length;
00363 if (lenX < lenY) return -1;
00364 if (lenX > lenY) return 1;
00365 return memcmp(hashX->buf, hashY->buf, lenX);
00366 }
00367
00368
00369
00370 static struct SyncNameAccum *
00371 sortNames(struct SyncRootStruct *root, struct SyncNameAccum *src) {
00372 char *here = "Sync.sortNames";
00373 IndexSorter_Index ixLim = src->len;
00374 IndexSorter_Base ixBase = IndexSorter_New(ixLim, -1);
00375 ixBase->sorter = SyncNameAccumSorter;
00376 ixBase->client = src;
00377 IndexSorter_Index ix = 0;
00378 for (ix = 0; ix < ixLim; ix++) IndexSorter_Add(ixBase, ix);
00379 struct SyncNameAccum *dst = SyncAllocNameAccum(ixLim);
00380 struct ccn_charbuf *lag = NULL;
00381 for (ix = 0; ix < ixLim; ix++) {
00382 IndexSorter_Index j = IndexSorter_Rem(ixBase);
00383 if (j >= ixLim) {
00384 SyncNoteFailed(root, here, "rem failed", __LINE__);
00385 break;
00386 }
00387 struct ccn_charbuf *name = src->ents[j].name;
00388 src->ents[j].name = NULL;
00389 if (name == NULL) {
00390 SyncNoteFailed(root, here, "name == NULL", __LINE__);
00391 break;
00392 }
00393 if (lag == NULL || SyncCmpNames(lag, name) != 0) {
00394
00395 SyncNameAccumAppend(dst, name, src->ents[j].data);
00396 lag = name;
00397 } else {
00398
00399 ccn_charbuf_destroy(&name);
00400 }
00401 }
00402 src->len = 0;
00403 IndexSorter_Free(&ixBase);
00404 return dst;
00405 }
00406
00407 static int
00408 reportExclude(struct SyncRootStruct *root, struct ccn_buf_decoder *d) {
00409 char *here = "Sync.reportExclude";
00410 int res = -1;
00411 if (ccn_buf_match_dtag(d, CCN_DTAG_Exclude)) {
00412 res = d->decoder.element_index;
00413 ccn_buf_advance(d);
00414
00415 while (ccn_buf_match_dtag(d, CCN_DTAG_Component)) {
00416 size_t cs = 0;
00417 const unsigned char *cp = NULL;
00418 ccn_buf_advance(d);
00419 if (ccn_buf_match_blob(d, &cp, &cs)) {
00420 ccn_buf_advance(d);
00421 char *hex = SyncHexStr(cp, cs);
00422 SyncNoteSimple(root, here, hex);
00423 free(hex);
00424 ccn_buf_check_close(d);
00425 }
00426 }
00427 ccn_buf_check_close(d);
00428 }
00429 if (d->decoder.state < 0)
00430 res = d->decoder.state;
00431 if (res < 0)
00432 SyncNoteSimple(root, here, "parse failed");
00433 return res;
00434 }
00435
00436 #define StatsLine(XXX) \
00437 if (stats->XXX) \
00438 pos += snprintf(s+pos, lim-pos, ", %s %ju", #XXX, (uintmax_t) stats->XXX);
00439
00440 static struct ccn_charbuf *
00441 formatStats(struct SyncRootStruct *root, struct ccn_charbuf *cb) {
00442 struct SyncRootStats *stats = root->priv->stats;
00443 struct SyncNodeComposite *ncL = NULL;
00444 char s[2000];
00445 int lim = sizeof(s);
00446 int pos = 0;
00447 int64_t now = SyncCurrentTime();
00448 int ru_ok = -1;
00449 #ifdef RUSAGE_SELF
00450 struct rusage ru;
00451 ru_ok = getrusage(RUSAGE_SELF, &ru);
00452 #endif
00453 struct ccn_charbuf *hash = root->currentHash;
00454 struct SyncCompareData *comp = root->compare;
00455 struct SyncUpdateData *update = root->update;
00456 struct SyncHashCacheEntry *ceL = root->priv->ceCurrent;
00457 if (ceL != NULL) {
00458 SyncCacheEntryFetch(ceL);
00459 ncL = ceL->ncL;
00460 }
00461
00462 pos += snprintf(s+pos, lim-pos, "stats for root#%u", root->rootId);
00463 if (hash->length > 0) {
00464
00465 char *hex = SyncHexStr(hash->buf, hash->length);
00466 pos += snprintf(s+pos, lim-pos, ", currentHash %s", hex);
00467 free(hex);
00468 }
00469 if (comp != NULL) {
00470 struct ccn_charbuf *hashR = comp->hashR;
00471 if (hashR != NULL && hashR->length > 0) {
00472 char *hex = SyncHexStr(hashR->buf, hashR->length);
00473 pos += snprintf(s+pos, lim-pos, ", remoteHash %s", hex);
00474 free(hex);
00475 }
00476 intmax_t dt = SyncDeltaTime(comp->startTime, now);
00477 pos += snprintf(s+pos, lim-pos, ", compareBusy %jd", dt);
00478 }
00479 if (update != NULL) {
00480 intmax_t dt = SyncDeltaTime(update->startTime, now);
00481 pos += snprintf(s+pos, lim-pos, ", updateBusy %jd", dt);
00482 }
00483
00484 if (root->priv->lastHashChange != 0) {
00485 uintmax_t x = root->priv->lastHashChange;
00486 pos += snprintf(s+pos, lim-pos, ", lastHashChange %ju.%06u",
00487 x / M, (unsigned) (x % M));
00488 }
00489
00490 if (root->namesToAdd != NULL) {
00491 intmax_t rem = root->namesToAdd->len;
00492 if (rem > 0)
00493 pos += snprintf(s+pos, lim-pos, ", namesToAdd %jd", rem);
00494 }
00495 if (root->namesToFetch != NULL) {
00496 intmax_t rem = root->namesToFetch->len;
00497 if (comp != NULL) rem = rem - comp->contentPos;
00498 if (rem > 0)
00499 pos += snprintf(s+pos, lim-pos, ", namesToFetch %jd", rem);
00500 }
00501 if (ncL != NULL) {
00502 pos += snprintf(s+pos, lim-pos, ", treeDepth %ju", (uintmax_t)
00503 ncL->treeDepth);
00504 pos += snprintf(s+pos, lim-pos, ", treeNames %ju", (uintmax_t)
00505 ncL->leafCount);
00506 pos += snprintf(s+pos, lim-pos, ", treeBytes %ju", (uintmax_t)
00507 ncL->byteCount + ncL->cb->length);
00508 }
00509
00510 StatsLine(comparesDone);
00511 StatsLine(lastCompareMicros);
00512 StatsLine(updatesDone);
00513 StatsLine(lastUpdateMicros);
00514 StatsLine(nodesCreated);
00515 StatsLine(nodesShared);
00516 StatsLine(rootAdviseSent);
00517 StatsLine(rootAdviseSeen);
00518 StatsLine(rootAdviseReceived);
00519 StatsLine(rootAdviseTimeout);
00520 StatsLine(rootAdviseFailed);
00521 StatsLine(nodeFetchSent);
00522 StatsLine(nodeFetchSeen);
00523 StatsLine(nodeFetchReceived);
00524 StatsLine(nodeFetchTimeout);
00525 StatsLine(nodeFetchFailed);
00526 StatsLine(nodeFetchBytes);
00527 StatsLine(contentFetchSent);
00528 StatsLine(contentFetchReceived);
00529 StatsLine(contentFetchTimeout);
00530 StatsLine(contentFetchFailed);
00531 StatsLine(contentFetchBytes);
00532
00533 #ifdef RUSAGE_SELF
00534 if (ru_ok >= 0) {
00535 pos += snprintf(s+pos, lim-pos, ", maxrss %ju",
00536 (uintmax_t) ru.ru_maxrss);
00537 pos += snprintf(s+pos, lim-pos, ", utime %ju.%06u",
00538 (uintmax_t) ru.ru_utime.tv_sec,
00539 (unsigned) ru.ru_utime.tv_usec);
00540 pos += snprintf(s+pos, lim-pos, ", stime %ju.%06u",
00541 (uintmax_t) ru.ru_stime.tv_sec,
00542 (unsigned) ru.ru_stime.tv_usec);
00543 }
00544 #endif
00545 ccn_charbuf_append(cb, s, pos);
00546 return cb;
00547 }
00548
00549 #undef StatsLine
00550
00551 static struct SyncNameAccum *
00552 exclusionsFromHashList(struct SyncRootStruct *root,
00553 struct SyncNameAccum *acc,
00554 struct SyncHashInfoList *list) {
00555 int count = 0;
00556 int limit = exclusionLimit;
00557 int64_t now = SyncCurrentTime();
00558 int64_t limitMicros = exclusionTrig*M;
00559
00560 while (list != NULL) {
00561 struct SyncHashCacheEntry *ce = list->ce;
00562 if (ce != NULL && isCovered(ce)
00563 && SyncDeltaTime(ce->lastUsed, now) < limitMicros) {
00564
00565 struct ccn_charbuf *hash = ce->hash;
00566 count = count + hash->length + 8;
00567 if (count > limit)
00568
00569 break;
00570 struct ccn_charbuf *name = ccn_charbuf_create();
00571 ccn_name_init(name);
00572 ccn_name_append(name, hash->buf, hash->length);
00573 if (acc == NULL) acc = SyncAllocNameAccum(0);
00574 SyncNameAccumAppend(acc, name, 0);
00575 }
00576 list = list->next;
00577 }
00578 if (acc != NULL && acc->len > 1) {
00579
00580 struct SyncNameAccum *lag = acc;
00581 acc = sortNames(root, acc);
00582 SyncFreeNameAccum(lag);
00583 }
00584 return acc;
00585 }
00586
00587 static struct ccn_charbuf *
00588 constructCommandPrefix(struct SyncRootStruct *root,
00589 enum SyncRegisterActionKind kind) {
00590 struct ccn_charbuf *prefix = ccn_charbuf_create();
00591 int res = 0;
00592 ccn_name_init(prefix);
00593 if (root->topoPrefix != NULL && root->topoPrefix->length > 0) {
00594
00595 res |= SyncAppendAllComponents(prefix, root->topoPrefix);
00596 }
00597
00598 ccn_name_append_str(prefix, getCmdStr(kind));
00599 res |= ccn_name_append(prefix, root->sliceHash->buf, root->sliceHash->length);
00600
00601 if (res < 0) {
00602 ccn_charbuf_destroy(&prefix);
00603 }
00604 return prefix;
00605 }
00606
00607
00608
00609
00610 static int
00611 extractDeltas(struct SyncRootStruct *root, struct ccn_upcall_info *info) {
00612
00613 char *here = "Sync.extractDeltas";
00614 const unsigned char *cp = NULL;
00615 int count = 0;
00616 size_t cs = 0;
00617 size_t ccnb_size = info->pco->offset[CCN_PCO_E];
00618 const unsigned char *ccnb = info->content_ccnb;
00619 int res = ccn_content_get_value(ccnb, ccnb_size, info->pco,
00620 &cp, &cs);
00621 if (res < 0 || cs < 2) {
00622 SyncNoteFailed(root, here, "ccn_content_get_value", __LINE__);
00623 return -1;
00624 }
00625
00626
00627 struct ccn_buf_decoder ds;
00628 struct ccn_buf_decoder *d = ccn_buf_decoder_start(&ds, cp, cs);
00629
00630 if (ccn_buf_match_dtag(d, CCN_DTAG_SyncNodeDeltas)) {
00631 ccn_buf_advance(d);
00632 uintmax_t vers = SyncParseUnsigned(d, CCN_DTAG_SyncVersion);
00633 if (SyncCheckDecodeErr(d) || vers != SYNC_UPDATE_VERSION) {
00634 SyncNoteFailed(root, here, "bad version", __LINE__);
00635 return -1;
00636 }
00637 struct SyncNameAccum *na = root->priv->remoteDeltas;
00638 if (na != NULL) SyncFreeNameAccumAndNames(na);
00639 na = SyncAllocNameAccum(4);
00640 root->priv->remoteDeltas = na;
00641 while (ccn_buf_match_dtag(d, CCN_DTAG_Name)) {
00642 struct ccn_charbuf *name = SyncExtractName(d);
00643 if (name == NULL) {
00644 SyncNoteFailed(root, here, "bad name", __LINE__);
00645 break;
00646 }
00647 SyncNameAccumAppend(na, name, 0);
00648 count++;
00649 }
00650 ccn_buf_check_close(d);
00651 }
00652 return count;
00653 }
00654
00655
00656
00657 static struct SyncNodeComposite *
00658 extractNode(struct SyncRootStruct *root, struct ccn_upcall_info *info) {
00659
00660 char *here = "Sync.extractNode";
00661 const unsigned char *cp = NULL;
00662 size_t cs = 0;
00663 size_t ccnb_size = info->pco->offset[CCN_PCO_E];
00664 const unsigned char *ccnb = info->content_ccnb;
00665 int res = ccn_content_get_value(ccnb, ccnb_size, info->pco,
00666 &cp, &cs);
00667 if (res < 0 || cs < DEFAULT_HASH_BYTES) {
00668 SyncNoteFailed(root, here, "ccn_content_get_value", __LINE__);
00669 return NULL;
00670 }
00671
00672
00673 struct SyncNodeComposite *nc = SyncAllocComposite(root->base);
00674 struct ccn_buf_decoder ds;
00675 struct ccn_buf_decoder *d = ccn_buf_decoder_start(&ds, cp, cs);
00676 res |= SyncParseComposite(nc, d);
00677 if (res < 0) {
00678
00679 SyncNoteFailed(root, here, "bad parse", -res);
00680 SyncFreeComposite(nc);
00681 nc = NULL;
00682 }
00683 return nc;
00684 }
00685
00686
00687
00688
00689
00690 static int
00691 noteHash(struct SyncRootStruct *root, struct SyncHashCacheEntry *ce,
00692 int add, int remote) {
00693 char *here = "Sync.noteRemoteHash";
00694 int debug = root->base->debug;
00695 struct ccnr_handle *ccnr = root->base->client_handle;
00696 struct ccn_charbuf *hash = NULL;
00697 int hl = 0;
00698 struct SyncHashInfoList *head = root->priv->remoteSeen;
00699 struct SyncHashInfoList *each = head;
00700 struct SyncHashInfoList *lag = NULL;
00701 int64_t mark = SyncCurrentTime();
00702 int res = 0;
00703 if (remote == 0) {
00704 head = root->priv->localMade;
00705 here = "Sync.noteLocalHash";
00706 }
00707 if (ce != NULL) {
00708 ce->lastUsed = mark;
00709 if (ce->state & SyncHashState_local)
00710 setCovered(ce);
00711 hash = ce->hash;
00712 hl = hash->length;
00713 }
00714 while (each != NULL) {
00715 if (ce == each->ce) {
00716 if (lag != NULL) {
00717
00718 lag->next = each->next;
00719 each->next = head;
00720 head = each;
00721 res = 1;
00722 }
00723 break;
00724 }
00725 lag = each;
00726 each = each->next;
00727 }
00728 if (each == NULL && add) {
00729
00730 each = NEW_STRUCT(1, SyncHashInfoList);
00731 each->next = head;
00732 head = each;
00733 }
00734 if (each != NULL) {
00735 each->ce = ce;
00736 if (ce != NULL) ce->busy++;
00737 each->lastSeen = mark;
00738 each->lastReplied = 0;
00739 }
00740 if (remote == 0) root->priv->localMade = head;
00741 else root->priv->remoteSeen = head;
00742
00743 if (debug >= CCNL_FINE) {
00744 char *hex = "empty";
00745 if (hl > 0) hex = SyncHexStr(hash->buf, hl);
00746 char *extra = ((isCovered(ce)) ? "covered, " : "");
00747 ccnr_msg(ccnr, "%s, root#%u, %s%s", here, root->rootId, extra, hex);
00748 if (hl > 0) free(hex);
00749 }
00750 return res;
00751 }
00752
00753
00754
00755
00756
00757
00758 static struct SyncHashInfoList *
00759 chooseRemoteHash(struct SyncRootStruct *root) {
00760 struct SyncHashInfoList *each = root->priv->remoteSeen;
00761 int64_t now = SyncCurrentTime();
00762 int64_t limit = ((int64_t)root->base->priv->rootAdviseLifetime)*2*M;
00763 struct SyncHashInfoList *lag = NULL;
00764 while (each != NULL) {
00765 struct SyncHashCacheEntry *ce = each->ce;
00766 struct SyncHashInfoList *next = each->next;
00767 int64_t dt = SyncDeltaTime(each->lastSeen, now);
00768 if (dt < limit) {
00769
00770 if (ce != NULL
00771 && (ce->state & SyncHashState_remote)
00772 && ((ce->state & SyncHashState_covered) == 0))
00773 return each;
00774 } else {
00775
00776 if (lag == NULL) root->priv->remoteSeen = next;
00777 else lag->next = next;
00778 free(each);
00779 }
00780 each = next;
00781 }
00782 return NULL;
00783 }
00784
00785 static int
00786 fauxError(struct SyncBaseStruct *base) {
00787
00788 if (base != NULL && base->priv->fauxErrorTrigger > 0) {
00789 int fet = base->priv->fauxErrorTrigger;
00790 if (fet > 0) {
00791 int r = random() % 100;
00792 if (r < fet) return 1;
00793 }
00794 }
00795 return 0;
00796 }
00797
00798
00799
00800
00801
00802 static void
00803 destroyCompareData(struct SyncCompareData *data) {
00804 if (data == NULL) return;
00805 struct SyncRootStruct *root = data->root;
00806 struct SyncPrivate *priv = root->base->priv;
00807 if (root != NULL) {
00808 while (data->errList != NULL) {
00809 struct SyncActionData *sad = data->errList;
00810 destroyActionData(sad);
00811 }
00812 root->namesToFetch = SyncFreeNameAccumAndNames(root->namesToFetch);
00813 root->compare = NULL;
00814 struct SyncActionData *each = root->actions;
00815
00816 while (each != NULL) {
00817 if (each->comp == data) each->comp = NULL;
00818 each = each->next;
00819 }
00820 }
00821 if (priv->comparesBusy > 0) priv->comparesBusy--;
00822 ccn_charbuf_destroy(&data->hashL);
00823 ccn_charbuf_destroy(&data->hashR);
00824 ccn_charbuf_destroy(&data->cbL);
00825 ccn_charbuf_destroy(&data->cbR);
00826 data->twL = SyncTreeWorkerFree(data->twL);
00827 data->twR = SyncTreeWorkerFree(data->twR);
00828 if (data->ev != NULL && root != NULL) {
00829 data->ev->evdata = NULL;
00830 ccn_schedule_cancel(root->base->sched, data->ev);
00831 }
00832 free(data);
00833 }
00834
00835 static void
00836 abortCompare(struct SyncCompareData *data, char *why) {
00837
00838
00839
00840 if (data == NULL) return;
00841 struct SyncRootStruct *root = data->root;
00842 if (root != NULL) {
00843 char *here = "Sync.abortCompare";
00844 struct SyncBaseStruct *base = root->base;
00845 struct SyncRootPrivate *priv = root->priv;
00846 struct SyncHashInfoList *list = priv->remoteSeen;
00847 struct SyncHashInfoList *lag = NULL;
00848 struct ccn_charbuf *hash = data->hashR;
00849 while (list != NULL) {
00850 struct SyncHashInfoList *next = list->next;
00851 struct SyncHashCacheEntry *ce = list->ce;
00852 if (ce != NULL && compareHash(ce->hash, hash) == 0) {
00853
00854
00855 if (base->debug >= CCNL_INFO) {
00856
00857 char *hex = SyncHexStr(hash->buf, hash->length);
00858 ccnr_msg(root->base->client_handle,
00859 "%s, root#%u, remove remote hash %s",
00860 here, root->rootId, hex);
00861 free(hex);
00862 }
00863 list->next = NULL;
00864 list->ce = NULL;
00865 if (ce->busy > 0) ce->busy--;
00866 if (lag == NULL) priv->remoteSeen = next;
00867 else lag->next = next;
00868 free(list);
00869 break;
00870 }
00871 lag = list;
00872 list = next;
00873 }
00874 if (root->base->debug >= CCNL_WARNING)
00875 SyncNoteSimple(root, here, why);
00876 }
00877 destroyCompareData(data);
00878 }
00879
00880 static int
00881 extractBuf(struct ccn_charbuf *cb, struct SyncNodeComposite *nc, struct SyncNodeElem *ne) {
00882 struct ccn_buf_decoder ds;
00883 struct ccn_buf_decoder *d = SyncInitDecoderFromElem(&ds, nc, ne);
00884 ccn_charbuf_reset(cb);
00885 int res = SyncAppendElementInner(cb, d);
00886 return res;
00887 }
00888
00889 static struct SyncHashCacheEntry *
00890 ensureRemoteEntry(struct SyncCompareData *data,
00891 const unsigned char * xp,
00892 ssize_t xs) {
00893 char *here = "Sync.ensureRemoteEntry";
00894 struct SyncRootStruct *root = data->root;
00895 struct SyncHashCacheEntry *ce = SyncHashEnter(root->ch, xp, xs, SyncHashState_remote);
00896 if (ce == NULL) {
00897
00898 SyncNoteFailed(root, here, "bad enter", __LINE__);
00899 return ce;
00900 }
00901 if (ce->state & SyncHashState_local) setCovered(ce);
00902 return ce;
00903 }
00904
00905 static struct SyncHashCacheEntry *
00906 cacheEntryForElem(struct SyncCompareData *data,
00907 struct SyncNodeComposite *nc,
00908 struct SyncNodeElem *ne,
00909 int remote) {
00910 char *here = "Sync.cacheEntryForElem";
00911 struct SyncRootStruct *root = data->root;
00912 struct ccn_buf_decoder ds;
00913 struct ccn_buf_decoder *d = SyncInitDecoderFromOffset(&ds, nc,
00914 ne->start,
00915 ne->stop);
00916 const unsigned char * xp = NULL;
00917 ssize_t xs = 0;
00918 SyncGetHashPtr(d, &xp, &xs);
00919 if (xs == 0 || xp == NULL) {
00920
00921 SyncNoteFailed(root, here, "no hash", __LINE__);
00922 return NULL;
00923 }
00924 struct SyncHashCacheEntry *ce = NULL;
00925 if (remote > 0) {
00926
00927 ce = ensureRemoteEntry(data, xp, xs);
00928 } else {
00929
00930 ce = SyncHashLookup(root->ch, xp, xs);
00931 if (SyncCacheEntryFetch(ce) < 0) {
00932 SyncNoteFailed(root, here, "bad fetch", __LINE__);
00933 return NULL;
00934 }
00935 }
00936 if (ce == NULL) {
00937
00938 SyncNoteFailed(root, here, "bad lookup", __LINE__);
00939 return ce;
00940 }
00941 ce->lastUsed = data->lastEnter;
00942 return ce;
00943 }
00944
00945 static int
00946 comparisonFailed(struct SyncCompareData *data, char *why, int line) {
00947 SyncNoteFailed(data->root, "Sync.CompareAction", why, line);
00948 data->state = SyncCompare_waiting;
00949 return -1;
00950 }
00951
00952 static int
00953 addNameFromCompare(struct SyncCompareData *data) {
00954 char *here = "Sync.addNameFromCompare";
00955 struct SyncRootStruct *root = data->root;
00956 int debug = root->base->debug;
00957 struct ccn_charbuf *name = data->cbR;
00958 if (root->namesToFetch == NULL)
00959 root->namesToFetch = SyncAllocNameAccum(0);
00960 SyncNameAccumAppend(root->namesToFetch, SyncCopyName(name), 0);
00961 struct SyncTreeWorkerEntry *tweR = SyncTreeWorkerTop(data->twR);
00962 tweR->pos++;
00963 tweR->count++;
00964 data->namesAdded++;
00965 if (debug >= CCNL_FINE) {
00966 SyncNoteUri(root, here, "added", name);
00967 }
00968 return 0;
00969 }
00970
00971
00972
00973
00974
00975
00976
00977 static int
00978 doPreload(struct SyncCompareData *data) {
00979 struct SyncRootStruct *root = data->root;
00980 struct SyncTreeWorkerHead *twR = data->twR;
00981 int busyLim = root->base->priv->maxFetchBusy;
00982 for (;;) {
00983 if (data->nodeFetchBusy > busyLim) return 0;
00984 if (twR->level <= 0) break;
00985 struct SyncTreeWorkerEntry *ent = SyncTreeWorkerTop(twR);
00986 struct SyncHashCacheEntry *ceR = ent->cacheEntry;
00987 if (ceR == NULL)
00988 return -1;
00989 if (ceR->state & SyncHashState_fetching
00990 || isCovered(ceR)) {
00991
00992 } else if (ceR->ncR != NULL) {
00993
00994 struct SyncNodeComposite *ncR = ceR->ncR;
00995 int lim = ncR->refLen;
00996 while (ent->pos < lim) {
00997 struct SyncNodeElem *ep = &ncR->refs[ent->pos];
00998 if ((ep->kind & SyncElemKind_leaf) == 0)
00999 break;
01000 ent->pos++;
01001 }
01002 if (ent->pos < lim) {
01003 struct SyncNodeElem *ep = &ncR->refs[ent->pos];
01004 struct SyncHashCacheEntry *sub = cacheEntryForElem(data, ncR, ep, 1);
01005 if (sub == NULL)
01006 return -1;
01007 ent = SyncTreeWorkerPush(twR);
01008 if (ent == NULL)
01009 return -1;
01010 continue;
01011 }
01012 } else {
01013
01014 SyncStartNodeFetch(root, ceR, data);
01015 }
01016
01017 ent = SyncTreeWorkerPop(twR);
01018 if (ent != NULL) ent->pos++;
01019 }
01020 while (data->nodeFetchBusy < busyLim) {
01021
01022 struct SyncActionData *sad = data->errList;
01023 if (sad == NULL) break;
01024 struct SyncHashCacheEntry *ceR = SyncHashLookup(root->ch,
01025 sad->hash->buf,
01026 sad->hash->length);
01027 SyncStartNodeFetch(root, ceR, data);
01028 destroyActionData(sad);
01029 }
01030
01031 if (data->nodeFetchBusy > 0) return 0;
01032 if (data->errList != NULL) return 0;
01033 if (twR->level > 0) return 0;
01034 return 1;
01035 }
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048 static int
01049 doComparison(struct SyncCompareData *data) {
01050 struct SyncRootStruct *root = data->root;
01051 struct SyncTreeWorkerHead *twL = data->twL;
01052 struct SyncTreeWorkerHead *twR = data->twR;
01053
01054 for (;;) {
01055 struct SyncTreeWorkerEntry *tweR = SyncTreeWorkerTop(twR);
01056 if (tweR == NULL) {
01057
01058 return 1;
01059 }
01060 struct SyncHashCacheEntry *ceR = tweR->cacheEntry;
01061 if (ceR == NULL)
01062 return comparisonFailed(data, "bad cache entry for R", __LINE__);
01063 ceR->lastUsed = data->lastEnter;
01064 if (tweR->pos == 0 && isCovered(ceR)) {
01065
01066 size_t c = tweR->count;
01067 tweR = SyncTreeWorkerPop(twR);
01068 if (tweR != NULL) {
01069 tweR->pos++;
01070 tweR->count += c;
01071 }
01072 continue;
01073 }
01074 struct SyncNodeComposite *ncR = ceR->ncR;
01075 if (ncR == NULL) {
01076
01077 int nf = SyncStartNodeFetch(root, ceR, data);
01078 if (nf == 0) {
01079
01080
01081 return comparisonFailed(data, "node fetch duplicate?", __LINE__);
01082 } else if (nf > 0) {
01083
01084 } else {
01085
01086 return comparisonFailed(data, "bad node fetch for R", __LINE__);
01087 }
01088 return 0;
01089 }
01090 if (tweR->pos >= ncR->refLen) {
01091
01092
01093 size_t c = tweR->count;
01094 if (c == 0) {
01095
01096 setCovered(ceR);
01097 }
01098 tweR = SyncTreeWorkerPop(twR);
01099 if (tweR != NULL) {
01100 tweR->pos++;
01101 tweR->count += c;
01102 }
01103 continue;
01104 }
01105 struct SyncNodeElem *neR = SyncTreeWorkerGetElem(twR);
01106 if (neR == NULL)
01107 return comparisonFailed(data, "bad element for R", __LINE__);
01108
01109 if (extractBuf(data->cbR, ncR, neR) < 0)
01110
01111 return comparisonFailed(data, "bad extract for R", __LINE__);
01112
01113 struct SyncTreeWorkerEntry *tweL = SyncTreeWorkerTop(twL);
01114 if (tweL == NULL) {
01115
01116 if (neR->kind == SyncElemKind_node) {
01117
01118 struct SyncHashCacheEntry *subR = cacheEntryForElem(data, ncR, neR, 1);
01119 if (subR == NULL || SyncTreeWorkerPush(twR) == NULL)
01120 return comparisonFailed(data, "bad cache entry for R", __LINE__);
01121 } else {
01122
01123 addNameFromCompare(data);
01124 }
01125 } else {
01126 struct SyncHashCacheEntry *ceL = tweL->cacheEntry;
01127 if (SyncCacheEntryFetch(ceL) < 0)
01128 return comparisonFailed(data, "bad cache entry for L", __LINE__);
01129 struct SyncNodeComposite *ncL = ceL->ncL;
01130 ceL->lastUsed = data->lastEnter;
01131 if (tweL->pos >= ncL->refLen) {
01132
01133 tweL = SyncTreeWorkerPop(twL);
01134 if (tweL != NULL) tweL->pos++;
01135 continue;
01136 }
01137 struct SyncNodeElem *neL = SyncTreeWorkerGetElem(twL);
01138 if (neL == NULL || extractBuf(data->cbL, ncL, neL) < 0) {
01139
01140 return comparisonFailed(data, "bad extract for L", __LINE__);
01141 }
01142 if (neR->kind == SyncElemKind_node) {
01143
01144 struct SyncHashCacheEntry *subR = cacheEntryForElem(data, ncR, neR, 1);
01145 if (subR == NULL)
01146 return comparisonFailed(data, "bad element for R", __LINE__);
01147 if (isCovered(subR)) {
01148
01149
01150 tweR->pos++;
01151 continue;
01152 }
01153 if (subR->ncR == NULL) {
01154
01155
01156 if (SyncTreeWorkerPush(twR) == NULL)
01157 return comparisonFailed(data, "bad push for R", __LINE__);
01158 continue;
01159 }
01160
01161 if (neL->kind == SyncElemKind_leaf) {
01162
01163 enum SyncCompareResult scr = SyncNodeCompareMinMax(subR->ncR, data->cbL);
01164 switch (scr) {
01165 case SCR_before:
01166
01167 tweL->pos++;
01168 break;
01169 case SCR_max:
01170
01171 tweL->pos++;
01172 tweR->pos++;
01173 break;
01174 default:
01175
01176 if (SyncTreeWorkerPush(twR) == NULL)
01177 return comparisonFailed(data, "bad push for R", __LINE__);
01178 break;
01179 }
01180
01181 } else {
01182
01183 struct SyncHashCacheEntry *subL = cacheEntryForElem(data, ncL, neL, 0);
01184 if (subL == NULL || subL->ncL == NULL)
01185 return comparisonFailed(data, "bad cache entry for L", __LINE__);
01186
01187 struct SyncNodeComposite *ncL = subL->ncL;
01188 struct SyncNodeComposite *ncR = subR->ncR;
01189 int cmp = SyncCmpNames(ncR->minName, ncL->maxName);
01190 if (cmp > 0) {
01191
01192 tweL->pos++;
01193 } else {
01194
01195 if (SyncTreeWorkerPush(twL) == NULL)
01196 return comparisonFailed(data, "bad push for L", __LINE__);
01197 if (SyncTreeWorkerPush(twR) == NULL)
01198 return comparisonFailed(data, "bad push for R", __LINE__);
01199 }
01200 }
01201 } else {
01202
01203 if (neL->kind == SyncElemKind_leaf) {
01204
01205 int cmp = SyncCmpNames(data->cbL, data->cbR);
01206 if (cmp == 0) {
01207
01208 tweL->pos++;
01209 tweR->pos++;
01210 } else if (cmp < 0) {
01211
01212 tweL->pos++;
01213 } else {
01214
01215 addNameFromCompare(data);
01216 }
01217 } else {
01218
01219 struct SyncHashCacheEntry *subL = cacheEntryForElem(data, ncL, neL, 0);
01220 if (subL == NULL || subL->ncL == NULL)
01221 return comparisonFailed(data, "bad cache entry for L", __LINE__);
01222 enum SyncCompareResult scr = SyncNodeCompareMinMax(subL->ncL, data->cbR);
01223 switch (scr) {
01224 case SCR_before:
01225
01226 addNameFromCompare(data);
01227 break;
01228 case SCR_max:
01229
01230 tweL->pos++;
01231 tweR->pos++;
01232 break;
01233 case SCR_min:
01234
01235 tweR->pos++;
01236 break;
01237 case SCR_after:
01238
01239 tweL->pos++;
01240 break;
01241 case SCR_inside:
01242
01243 if (SyncTreeWorkerPush(twL) == NULL)
01244 return comparisonFailed(data, "bad push for L", __LINE__);
01245 break;
01246 default:
01247
01248 return comparisonFailed(data, "bad min/max compare", __LINE__);
01249 }
01250
01251 }
01252 }
01253 }
01254 }
01255 }
01256
01257 static int
01258 fetchStablePoint(struct SyncBaseStruct *base, ccnr_hwm *ptr) {
01259 int res = 0;
01260 struct ccn_charbuf *cb = ccn_charbuf_create();
01261 struct ccn_charbuf *name = SyncCopyName(base->priv->localHostPrefix);
01262 res |= ccn_name_append_str(name, syncStableSuffix);
01263 struct ccn_charbuf *interest = SyncGenInterest(name, 1, 0, -1, 1, NULL);
01264 if (interest == NULL) return -__LINE__;
01265
01266 res |= r_sync_lookup(base->client_handle, interest, cb);
01267 if (res >= 0) {
01268
01269 const unsigned char *xp = NULL;
01270 size_t xs = 0;
01271 res |= SyncPointerToContent(cb, NULL, &xp, &xs);
01272 if (res >= 0) {
01273
01274 uintmax_t val = 0;
01275 static char *key = "stable ";
01276 struct ccn_buf_decoder ds;
01277 struct ccn_buf_decoder *d = ccn_buf_decoder_start(&ds, xp, xs);
01278 res = -__LINE__;
01279 if (ccn_buf_match_dtag(d, CCN_DTAG_StringValue)) {
01280 ccn_buf_advance(d);
01281 res = -__LINE__;
01282 if (ccn_buf_match_blob(d, &xp, &xs)) {
01283 int ks = strlen(key);
01284 ccn_buf_advance(d);
01285 res = -__LINE__;
01286 if (xs > ks && strncmp(key, (char *) xp, ks) == 0) {
01287 xp = xp + ks;
01288 for (;;) {
01289 unsigned char c = *xp;
01290 if (c < '0' || c > '9') break;
01291 val = val * 10 + (c - '0');
01292 xp++;
01293 res = 0;
01294 }
01295 if (ptr != NULL && res == 0)
01296 *ptr = ccnr_hwm_decode(base->client_handle, val);
01297 }
01298 }
01299 }
01300 }
01301 }
01302
01303 ccn_charbuf_destroy(&cb);
01304 ccn_charbuf_destroy(&name);
01305 ccn_charbuf_destroy(&interest);
01306 return res;
01307 }
01308
01309 static int
01310 storeStablePoint(struct SyncBaseStruct *base, ccnr_hwm point) {
01311 struct ccn_charbuf *x = ccn_charbuf_create();
01312 struct ccn_charbuf *name = SyncCopyName(base->priv->localHostPrefix);
01313 int res = 0;
01314 char temp[32];
01315 int nc = snprintf(temp, sizeof(temp), "stable %ju",
01316 ccnr_hwm_encode(base->client_handle, point));
01317
01318 res |= ccnb_append_tagged_blob(x, CCN_DTAG_StringValue, temp, nc);
01319 res |= ccn_name_append_str(name, syncStableSuffix);
01320 res |= ccn_create_version(base->ccn, name, CCN_V_NOW, 0, 0);
01321 res |= ccn_name_append_numeric(name, CCN_MARKER_SEQNUM, 0);
01322 if (res >= 0) {
01323
01324
01325 struct ccn_charbuf *cob = SyncSignBuf(base, x, name,
01326 1, CCN_SP_FINAL_BLOCK);
01327 if (cob != NULL) {
01328 res |= r_sync_local_store(base->client_handle, cob);
01329 ccn_charbuf_destroy(&cob);
01330 }
01331 }
01332 ccn_charbuf_destroy(&name);
01333 ccn_charbuf_destroy(&x);
01334 return res;
01335 }
01336
01337 static int
01338 isRootStableEnough(struct SyncRootStruct *root, ccnr_hwm target) {
01339 if (root->namesToAdd->len == 0) return 1;
01340 return 0;
01341 }
01342
01343
01344
01345
01346 static void
01347 purgeOldEntries(struct SyncRootStruct *root) {
01348 char *here = "Sync.purgeOldEntries";
01349 struct SyncHashCacheHead *ch = root->ch;
01350 struct SyncHashCacheEntry *ceL = root->priv->ceCurrent;
01351 if (ceL == NULL) return;
01352 struct SyncTreeWorkerHead *twL = SyncTreeWorkerCreate(ch, ceL, 0);
01353 int64_t now = SyncCurrentTime();
01354 int64_t trigger = cachePurgeTrigger*M;
01355 SyncHashClearMarks(ch);
01356 SyncTreeMarkReachable(twL, 0);
01357 int hx = 0;
01358 for (hx = 0; hx < ch->mod; hx++) {
01359 struct SyncHashCacheEntry *ce = ch->ents[hx];
01360 while (ce != NULL) {
01361 if ((ce->state & SyncHashState_marked) == 0
01362 && ce->state & SyncHashState_stored) {
01363
01364 struct SyncNodeComposite *ncL = ce->ncL;
01365 if (ncL != NULL) {
01366 int64_t dt = SyncDeltaTime(ce->lastUsed, now);
01367 if (dt > trigger) {
01368
01369 ce->ncL = NULL;
01370 ncL = SyncNodeDecRC(ncL);
01371 if (root->base->debug >= CCNL_FINE) {
01372 char *hex = SyncHexStr(ce->hash->buf, ce->hash->length);
01373 SyncNoteSimple(root, here, hex);
01374 free(hex);
01375 }
01376 }
01377 }
01378 }
01379 ce = ce->next;
01380 }
01381 }
01382 SyncTreeWorkerFree(twL);
01383 }
01384
01385 static int
01386 CompareAction(struct ccn_schedule *sched,
01387 void *clienth,
01388 struct ccn_scheduled_event *ev,
01389 int flags) {
01390 char *here = "Sync.CompareAction";
01391 struct SyncCompareData *data = (struct SyncCompareData *) ev->evdata;
01392 if (data == NULL || data->root == NULL) {
01393
01394 return -1;
01395 }
01396 data->lastEnter = SyncCurrentTime();
01397 struct SyncRootStruct *root = data->root;
01398 struct ccnr_handle *ccnr = root->base->client_handle;
01399 int debug = root->base->debug;
01400 if (data->ev != ev || flags & CCN_SCHEDULE_CANCEL) {
01401
01402 if (debug >= CCNL_FINE)
01403 SyncNoteSimple(root, here, "orphan?");
01404 data->ev = NULL;
01405 return -1;
01406 }
01407
01408 int delay = shortDelayMicros;
01409 switch (data->state) {
01410 case SyncCompare_init:
01411
01412 if (debug >= CCNL_FINE)
01413 SyncNoteSimple(root, here, "init");
01414 data->state = SyncCompare_preload;
01415 case SyncCompare_preload: {
01416
01417 if (debug >= CCNL_FINE)
01418 SyncNoteSimple(root, here, "preload");
01419 struct SyncHashCacheEntry *ceR = SyncHashLookup(root->ch,
01420 data->hashR->buf,
01421 data->hashR->length);
01422 SyncTreeWorkerInit(data->twR, ceR, 1);
01423 int res = doPreload(data);
01424 if (res < 0) {
01425 abortCompare(data, "doPreload failed");
01426 return -1;
01427 }
01428 if (res == 0) {
01429
01430 if (data->nodeFetchBusy > 0) {
01431
01432 data->ev = NULL;
01433 delay = -1;
01434 }
01435 break;
01436 }
01437
01438 SyncTreeWorkerInit(data->twR, ceR, 1);
01439 data->state = SyncCompare_busy;
01440 }
01441 case SyncCompare_busy: {
01442
01443 if (debug >= CCNL_FINE)
01444 SyncNoteSimple(root, here, "busy");
01445 int res = doComparison(data);
01446 if (res < 0) {
01447 abortCompare(data, "doComparison failed");
01448 return -1;
01449 }
01450 if (data->errList != NULL) {
01451
01452 data->state = SyncCompare_preload;
01453 if (debug >= CCNL_WARNING)
01454 SyncNoteSimple(root, here, "retreat one state");
01455 break;
01456 }
01457 if (res == 0)
01458
01459 break;
01460
01461 data->state = SyncCompare_waiting;
01462 }
01463 case SyncCompare_waiting: {
01464 if (debug >= CCNL_FINE)
01465 SyncNoteSimple(root, here, "waiting");
01466 struct SyncNameAccum *namesToFetch = root->namesToFetch;
01467 int busyLim = root->base->priv->maxFetchBusy;
01468 int len = ((namesToFetch != NULL) ? namesToFetch->len : 0);
01469 if (debug >= CCNL_FINE) {
01470 int pos = data->contentPos;
01471 ccnr_msg(ccnr, "%s, root#%u, pos %d, names %d",
01472 here, root->rootId, pos, len);
01473 }
01474 while (data->contentFetchBusy < busyLim
01475 && data->contentPos < len) {
01476
01477 int pos = data->contentPos;
01478 struct ccn_charbuf *name = namesToFetch->ents[pos].name;
01479 SyncStartContentFetch(root, name, data);
01480 data->contentPos = pos + 1;
01481 }
01482 while (data->contentFetchBusy < busyLim) {
01483
01484 struct SyncActionData *sad = data->errList;
01485 if (sad == NULL) break;
01486 SyncStartContentFetch(root, sad->prefix, data);
01487 destroyActionData(sad);
01488 }
01489 if (data->contentFetchBusy > 0) {
01490
01491 data->ev = NULL;
01492 delay = -1;
01493 break;
01494 }
01495 data->state = SyncCompare_done;
01496 }
01497 case SyncCompare_done: {
01498
01499 int64_t now = SyncCurrentTime();
01500 int64_t mh = SyncDeltaTime(data->lastEnter, now);
01501 int64_t dt = SyncDeltaTime(data->startTime, now);
01502 root->priv->stats->comparesDone++;
01503 root->priv->stats->lastCompareMicros = dt;
01504 if (mh > data->maxHold) data->maxHold = mh;
01505 mh = (mh + 500) / 1000;
01506 dt = (dt + 500) / 1000;
01507
01508 if (debug >= CCNL_INFO) {
01509 int reportStats = root->base->priv->syncActionsPrivate & 4;
01510 char temp[64];
01511 snprintf(temp, sizeof(temp)-2,
01512 "%d.%03d secs [%d.%03d], %d names added",
01513 (int) (dt / 1000), (int) (dt % 1000),
01514 (int) (mh / 1000), (int) (mh % 1000),
01515 (int) data->namesAdded);
01516 SyncNoteSimple2(root, here, "done", temp);
01517 if (reportStats) {
01518 struct ccn_charbuf *cb = ccn_charbuf_create();
01519 formatStats(root, cb);
01520 char *str = ccn_charbuf_as_string(cb);
01521 ccnr_msg(root->base->client_handle, "%s, %s", here, str);
01522 ccn_charbuf_destroy(&cb);
01523 }
01524 }
01525 destroyCompareData(data);
01526 return -1;
01527 }
01528 default: break;
01529 }
01530 int64_t mh = SyncDeltaTime(data->lastEnter, SyncCurrentTime());
01531 if (mh > data->maxHold) data->maxHold = mh;
01532 return delay;
01533 }
01534
01535 static void
01536 kickCompare(struct SyncCompareData *scd, struct SyncActionData *action) {
01537
01538
01539 if (scd != NULL && scd->ev == NULL) {
01540 struct ccn_scheduled_event *ev = ccn_schedule_event(scd->root->base->sched,
01541 shortDelayMicros,
01542 CompareAction,
01543 scd,
01544 0);
01545 scd->ev = ev;
01546 }
01547 }
01548
01549 static void
01550 kickHeartBeat(struct SyncRootStruct *root, int micros) {
01551 if (root != NULL)
01552 ccn_schedule_event(root->base->sched,
01553 micros,
01554 HeartbeatAction,
01555 root->base,
01556 0);
01557 }
01558
01559
01560
01561
01562
01563 static struct SyncHashCacheEntry *
01564 newNodeCommon(struct SyncRootStruct *root,
01565 struct SyncNodeAccum *nodes,
01566 struct SyncNodeComposite *nc) {
01567
01568 char *here = "Sync.newNodeCommon";
01569 int debug = root->base->debug;
01570 struct ccnr_handle *ccnr = root->base->client_handle;
01571 if (nc == NULL || nc->hash == NULL) {
01572 SyncNoteFailed(root, here, "bad node", __LINE__);
01573 return NULL;
01574 }
01575 struct SyncHashCacheHead *ch = root->ch;
01576 struct ccn_charbuf *hash = nc->hash;
01577 struct SyncHashCacheEntry *ce = SyncHashLookup(ch, hash->buf, hash->length);
01578 SyncCacheEntryFetch(ce);
01579 if (ce != NULL && ce->ncL != NULL) {
01580
01581
01582 if (debug >= CCNL_FINE) {
01583 char *hex = SyncHexStr(hash->buf, hash->length);
01584 SyncNoteSimple2(root, here, "suppressed duplicate", hex);
01585 free(hex);
01586 }
01587 SyncFreeComposite(nc);
01588 nc = ce->ncL;
01589 root->priv->stats->nodesShared++;
01590 } else {
01591
01592 struct SyncPrivate *priv = root->base->priv;
01593 ce = SyncHashEnter(ch, hash->buf, hash->length, SyncHashState_local);
01594 if (ce == NULL) {
01595
01596 SyncNoteFailed(root, here, "bad enter", __LINE__);
01597 SyncNodeDecRC(nc);
01598 return NULL;
01599 }
01600 ce->ncL = nc;
01601 if (ce->state & SyncHashState_remote)
01602 setCovered(ce);
01603
01604 ce->state |= SyncHashState_storing;
01605 if (priv->storingTail == NULL) {
01606
01607 priv->storingHead = ce;
01608 } else {
01609
01610 priv->storingTail->storing = ce;
01611 }
01612 priv->storingTail = ce;
01613 priv->nStoring++;
01614 root->priv->stats->nodesCreated++;
01615 if (nc->cb->length >= nodeSplitTrigger) {
01616
01617 if (debug >= CCNL_INFO)
01618 ccnr_msg(ccnr,
01619 "%s, root#%u, cb->length (%d) >= nodeSplitTrigger (%d)",
01620 here, root->rootId,
01621 (int) nc->cb->length, (int) nodeSplitTrigger);
01622 }
01623 }
01624 SyncNodeIncRC(nc);
01625 SyncAccumNode(nodes, nc);
01626 return ce;
01627 }
01628
01629 static struct SyncHashCacheEntry *
01630 nodeFromNodes(struct SyncRootStruct *root, struct SyncNodeAccum *na) {
01631 char *here = "Sync.nodeFromNodes";
01632 struct SyncHashCacheHead *ch = root->ch;
01633 struct SyncBaseStruct *base = root->base;
01634 struct ccnr_handle *ccnr = base->client_handle;
01635 int debug = base->debug;
01636 int lim = na->len;
01637 if (lim == 0) {
01638 SyncNoteFailed(root, here, "empty", __LINE__);
01639 return NULL;
01640 }
01641 if (lim == 1) {
01642
01643 struct SyncNodeComposite *nc = na->ents[0];
01644 if (nc == NULL || nc->hash == NULL) {
01645 SyncNoteFailed(root, here, "bad node", __LINE__);
01646 return NULL;
01647 }
01648 struct SyncHashCacheEntry *ce = SyncHashLookup(ch,
01649 nc->hash->buf,
01650 nc->hash->length);
01651 if (ce == NULL)
01652 SyncNoteFailed(root, here, "bad lookup", __LINE__);
01653 return ce;
01654 }
01655
01656 int accLim = nodeSplitTrigger - nodeSplitTrigger/8;
01657 struct SyncNodeAccum *nodes = SyncAllocNodeAccum(0);
01658 struct SyncHashCacheEntry *ce = NULL;
01659 int j = 0;
01660 while (j < lim) {
01661 int maxLen = 0;
01662 int i = j;
01663 struct SyncNodeComposite *nc = SyncAllocComposite(base);
01664 int accLen = nc->cb->length;
01665
01666 while (i < lim && accLen < accLim) {
01667 struct SyncNodeComposite *elem = na->ents[i];
01668 i++;
01669 int nodeLen = elem->hash->length + 8;
01670 if (nodeLen > maxLen) maxLen = nodeLen;
01671 accLen = accLen + nodeLen + (maxLen - nodeLen) * 2;
01672 }
01673
01674
01675 while (j < i) {
01676 struct SyncNodeComposite *elem = na->ents[j];
01677 j++;
01678 SyncNodeAddNode(nc, elem);
01679 }
01680 SyncEndComposite(nc);
01681 ce = newNodeCommon(root, nodes, nc);
01682 }
01683
01684 ce = nodeFromNodes(root, nodes);
01685 nodes = SyncFreeNodeAccum(nodes);
01686 if (debug >= CCNL_FINE) {
01687 ccnr_msg(ccnr, "%s, root#%u, %d refs", here, root->rootId, lim);
01688 }
01689 return ce;
01690 }
01691
01692 extern int
01693 SyncStartSliceEnum(struct SyncRootStruct *root) {
01694 char *here = "Sync.SyncStartSliceEnum";
01695 struct SyncBaseStruct *base = root->base;
01696 if (base->priv->sliceBusy == 0) {
01697 int debug = root->base->debug;
01698 struct ccn_charbuf *name = root->namingPrefix;
01699 struct ccn_charbuf *nin = SyncGenInterest(name,
01700 -1, -1, -1, -1,
01701 NULL);
01702 int res = r_sync_enumerate(base->client_handle, nin);
01703
01704 ccn_charbuf_destroy(&nin);
01705 if (res > 0) {
01706 if (debug >= CCNL_INFO)
01707 SyncNoteUri(root, here, "slice enum start", name);
01708 base->priv->sliceBusy = res;
01709 root->priv->sliceBusy = res;
01710 return 1;
01711 } else if (debug >= CCNL_SEVERE) {
01712 SyncNoteUri(root, here, "slice enum failed", name);
01713 return -1;
01714 }
01715 }
01716 return 0;
01717 }
01718
01719
01720
01721
01722
01723 static int
01724 HeartbeatAction(struct ccn_schedule *sched,
01725 void *clienth,
01726 struct ccn_scheduled_event *ev,
01727 int flags) {
01728 char *here = "Sync.HeartbeatAction";
01729 struct SyncBaseStruct *base = (struct SyncBaseStruct *) ev->evdata;
01730 if (base == NULL || base->priv == NULL || (flags & CCN_SCHEDULE_CANCEL)) {
01731
01732 return -1;
01733 }
01734
01735 struct SyncPrivate *priv = base->priv;
01736 if (priv->sliceEnum > 0) {
01737
01738 return shortDelayMicros;
01739 }
01740
01741
01742 struct SyncRootStruct *root = priv->rootHead;
01743 while (root != NULL) {
01744 if (root->priv->sliceBusy < 0 && priv->sliceBusy == 0) {
01745
01746 if (SyncStartSliceEnum(root) < 0)
01747 return priv->heartbeatMicros;
01748 return shortDelayMicros;
01749 }
01750 root = root->next;
01751 }
01752 int64_t now = SyncCurrentTime();
01753 root = priv->rootHead;
01754 int64_t lifeMicros = ((int64_t) priv->rootAdviseLifetime)*M;
01755 int64_t needMicros = ((int64_t) updateNeedDelta)*M;
01756
01757 while (root != NULL) {
01758 struct SyncRootPrivate *rp = root->priv;
01759 struct SyncCompareData *comp = root->compare;
01760 if (rp->sliceBusy < 0 && priv->sliceBusy == 0) {
01761
01762 if (SyncStartSliceEnum(root) < 0)
01763 return priv->heartbeatMicros;
01764 } else if (priv->sliceBusy > 0) {
01765
01766 } else if (root->update != NULL) {
01767
01768 } else if (comp == NULL) {
01769
01770 size_t addLen = root->namesToAdd->len;
01771 int64_t deltaAdvise = SyncDeltaTime(rp->lastAdvise, now);
01772 int64_t deltaUpdate = SyncDeltaTime(rp->lastUpdate, now);
01773 int64_t needUpdate = needMicros;
01774 if (addLen == rp->prevAddLen)
01775
01776 needUpdate = rp->stats->lastUpdateMicros * 2;
01777 if (rp->adviseNeed <= 0 && deltaAdvise > lifeMicros)
01778
01779 rp->adviseNeed = adviseNeedReset;
01780 if (deltaUpdate >= needUpdate) {
01781
01782 if (addLen > 0) {
01783
01784 SyncUpdateRoot(root);
01785 }
01786 struct SyncHashCacheEntry *ceL = rp->ceCurrent;
01787 if (ceL != NULL && (ceL->state & SyncHashState_local)) {
01788 if (rp->adviseNeed > 0 || ceL != rp->lastLocalSent) {
01789 SyncSendRootAdviseInterest(root);
01790 }
01791 } else
01792
01793 SyncSendRootAdviseInterest(root);
01794 if (root->update == NULL) {
01795 if (rp->remoteDeltas != NULL)
01796
01797 SyncStartCompareAction(root, NULL);
01798 else {
01799
01800 struct SyncHashInfoList *x = chooseRemoteHash(root);
01801 if (x != NULL) {
01802 SyncStartCompareAction(root, x->ce->hash);
01803 }
01804 }
01805 }
01806 }
01807 rp->prevAddLen = root->namesToAdd->len;
01808 } else {
01809
01810 int64_t dt = SyncDeltaTime(comp->lastMark, now);
01811 if (dt > updateStallDelta*M) {
01812
01813 if (base->debug >= CCNL_WARNING)
01814 SyncNoteSimple(root, here, "compare stalled?");
01815 comp->lastMark = now;
01816 }
01817
01818 dt = SyncDeltaTime(comp->lastFetchOK, now);
01819 if (dt > compareAssumeBad*M) {
01820 abortCompare(comp, "no progress");
01821 }
01822 }
01823
01824
01825 root = root->next;
01826 }
01827 int64_t deltaClean = SyncDeltaTime(priv->lastCacheClean, now);
01828 if (priv->useRepoStore && deltaClean >= cacheCleanDelta*M) {
01829
01830
01831 int cleanRem = cacheCleanBatch;
01832 while (cleanRem > 0) {
01833 struct SyncHashCacheEntry *ce = priv->storingHead;
01834 if (ce == NULL) break;
01835 struct SyncHashCacheEntry *ceN = ce->storing;
01836 SyncCacheEntryStore(ce);
01837 priv->storingHead = ceN;
01838 if (ceN == NULL) priv->storingTail = ceN;
01839 if (priv->nStoring > 0) priv->nStoring--;
01840 root = ce->head->root;
01841 ccnr_hwm chw = ce->stablePoint;
01842 if (ccnr_hwm_compare(base->client_handle, chw, root->priv->stablePoint) > 0) {
01843
01844 root->priv->stablePoint = chw;
01845 root->priv->lastStable = now;
01846 if (ccnr_hwm_compare(base->client_handle, chw, priv->stableTarget) > 0)
01847 priv->stableTarget = chw;
01848 if (base->debug >= CCNL_INFO) {
01849 char temp[64];
01850 snprintf(temp, sizeof(temp),
01851 "newly stable at %ju",
01852 ccnr_hwm_encode(base->client_handle, chw));
01853 SyncNoteSimple(root, here, temp);
01854 }
01855 }
01856 cleanRem--;
01857 }
01858 priv->lastCacheClean = now;
01859 }
01860 if (priv->stableEnabled && priv->useRepoStore
01861 && priv->nStoring == 0
01862 && ccnr_hwm_compare(base->client_handle, priv->stableTarget, priv->stableStored) > 0) {
01863
01864 int unstable = 1;
01865 int64_t dt = SyncDeltaTime(priv->lastStable, now);
01866 if (dt > stableTimeTrig*M) {
01867
01868 unstable = 0;
01869 root = priv->rootHead;
01870 while (root != NULL) {
01871 if (!isRootStableEnough(root, priv->stableTarget)) {
01872 unstable++;
01873 break;
01874 }
01875 root = root->next;
01876 }
01877 }
01878 if (unstable == 0) {
01879
01880 if (base->debug >= CCNL_INFO) {
01881 char temp[64];
01882 snprintf(temp, sizeof(temp),
01883 "stable target reached at %ju",
01884 ccnr_hwm_encode(base->client_handle, priv->stableTarget));
01885 ccnr_msg(base->client_handle, "%s, %s", here, temp);
01886 }
01887 int spRes = storeStablePoint(base, priv->stableTarget);
01888 if (spRes < 0 && base->debug >= CCNL_WARNING) {
01889 ccnr_msg(base->client_handle, "%s, warning: stable target not stored", here);
01890 }
01891 priv->lastStable = now;
01892 priv->stableStored = priv->stableTarget;
01893 }
01894 }
01895 return priv->heartbeatMicros;
01896 }
01897
01898
01899
01900
01901
01902
01903 extern int
01904 SyncStartHeartbeat(struct SyncBaseStruct *base) {
01905 static char *here = "Sync.SyncStartHeartbeat";
01906 int res = -1;
01907 if (base != NULL && base->sched != NULL) {
01908 int debug = base->debug;
01909 struct ccnr_handle *ccnr = base->client_handle;
01910 struct SyncPrivate *priv = base->priv;
01911 struct ccn_charbuf *nin = SyncGenInterest(priv->sliceCmdPrefix,
01912 -1, -1, -1, -1,
01913 NULL);
01914
01915
01916
01917 ccnr_hwm commitPoint = CCNR_NULL_HWM;
01918 if (priv->stableEnabled && priv->useRepoStore) {
01919 res = fetchStablePoint(base, &commitPoint);
01920 if (res < 0 && base->debug >= CCNL_WARNING)
01921 ccnr_msg(base->client_handle, "%s, no stable recovery point", here);
01922 }
01923 r_sync_notify_after(base->client_handle, commitPoint);
01924
01925
01926 res = r_sync_enumerate(ccnr, nin);
01927 ccn_charbuf_destroy(&nin);
01928 if (res > 0) {
01929 priv->sliceEnum = res;
01930 if (debug >= CCNL_INFO)
01931 ccnr_msg(ccnr, "%s, slice enumerate started, %d", here, res);
01932 res = 0;
01933 } else if (debug >= CCNL_WARNING) {
01934
01935 ccnr_msg(ccnr, "%s, no slices found", here);
01936 }
01937
01938
01939 struct ccn_scheduled_event *ev = ccn_schedule_event(base->sched,
01940 priv->heartbeatMicros,
01941 HeartbeatAction,
01942 base,
01943 0);
01944
01945 res = 0;
01946 if (ev == NULL) {
01947 if (debug >= CCNL_SEVERE)
01948 ccnr_msg(ccnr, "%s, initial schedule failed!", here);
01949 res = -1;
01950 }
01951 }
01952 return res;
01953 }
01954
01955
01956
01957
01958 extern enum ccn_upcall_res
01959 SyncRemoteFetchResponse(struct ccn_closure *selfp,
01960 enum ccn_upcall_kind kind,
01961 struct ccn_upcall_info *info) {
01962 static char *here = "Sync.SyncRemoteFetchResponse";
01963 struct SyncActionData *data = selfp->data;
01964 enum ccn_upcall_res ret = CCN_UPCALL_RESULT_OK;
01965 switch (kind) {
01966 case CCN_UPCALL_FINAL:
01967 selfp->data = destroyActionData(data);
01968 free(selfp);
01969 break;
01970 case CCN_UPCALL_CONTENT_UNVERIFIED:
01971
01972
01973 case CCN_UPCALL_CONTENT_RAW:
01974 case CCN_UPCALL_CONTENT_KEYMISSING:
01975 case CCN_UPCALL_INTEREST_TIMED_OUT:
01976 case CCN_UPCALL_CONTENT: {
01977 if (data == NULL) break;
01978 struct ccnr_handle *ccnr = data->client_handle;
01979 struct SyncRootStruct *root = data->root;
01980 struct SyncCompareData *comp = data->comp;
01981 if (root == NULL) break;
01982 int debug = root->base->debug;
01983 struct SyncRootStats *stats = root->priv->stats;
01984 size_t bytes = 0;
01985 int faux = fauxError(root->base);
01986 int64_t now = SyncCurrentTime();
01987 if (ccnr != NULL && info != NULL && info->pco != NULL && faux == 0
01988 && kind != CCN_UPCALL_INTEREST_TIMED_OUT)
01989 bytes = info->pco->offset[CCN_PCO_E];
01990 if (debug >= CCNL_INFO) {
01991 char temp[64];
01992 char *ns = "node";
01993 char *ks = "ok";
01994 if (faux) ks = "faux error";
01995 if (data->kind == SRI_Kind_Content) ns = "content";
01996 if (kind == CCN_UPCALL_INTEREST_TIMED_OUT) ks = "timeout!";
01997 int64_t dt = SyncDeltaTime(data->startTime, now);
01998 dt = (dt + 500) / 1000;
01999 if (bytes > 0)
02000 snprintf(temp, sizeof(temp),
02001 "%s, %s, %d.%03d secs, %u bytes",
02002 ns, ks, (int) (dt / 1000), (int) (dt % 1000),
02003 (unsigned) bytes);
02004 else
02005 snprintf(temp, sizeof(temp),
02006 "%s, %s, %d.%03d secs",
02007 ns, ks, (int) (dt / 1000), (int) (dt % 1000));
02008 SyncNoteUri(root, here, temp, data->prefix);
02009 }
02010
02011 switch (data->kind) {
02012 case SRI_Kind_Content: {
02013 if (bytes > 0) {
02014
02015 ret = r_sync_upcall_store(ccnr, CCN_UPCALL_CONTENT, info);
02016 if (ret < 0) {
02017
02018 bytes = 0;
02019 if (debug >= CCNL_SEVERE)
02020 SyncNoteFailed(root, here, "content store", __LINE__);
02021 } else {
02022
02023 if (debug >= CCNL_FINE)
02024 SyncNoteSimple(root, here, "content stored");
02025 }
02026 }
02027 if (comp != NULL && comp->contentFetchBusy > 0)
02028 comp->contentFetchBusy--;
02029 if (bytes > 0) {
02030
02031 stats->contentFetchReceived++;
02032 stats->contentFetchBytes += bytes;
02033 if (comp != NULL)
02034 comp->lastFetchOK = now;
02035 } else {
02036
02037 if (kind == CCN_UPCALL_INTEREST_TIMED_OUT)
02038 stats->contentFetchTimeout++;
02039 stats->contentFetchFailed++;
02040 if (comp != NULL) {
02041
02042 comp->contentFetchFailed++;
02043 if (!moveActionData(data, SyncActionState_error))
02044 SyncNoteFailed(root, here, "moveActionData", __LINE__);
02045 selfp->data = NULL;
02046 }
02047 }
02048
02049 kickCompare(comp, data);
02050 break;
02051 }
02052 case SRI_Kind_NodeFetch: {
02053
02054 const unsigned char *xp = data->hash->buf;
02055 ssize_t xs = data->hash->length;
02056 char *highWhy = "??";
02057 char *hex = SyncHexStr(xp, xs);
02058 struct SyncHashCacheEntry *ce = SyncHashLookup(root->ch, xp, xs);
02059 if (bytes <= 0) {
02060
02061 highWhy = "no fetch";
02062 } else if (ce != NULL && (isCovered(ce) || ce->ncR != NULL)) {
02063
02064
02065 if (debug >= CCNL_FINE) {
02066 SyncNoteSimple2(root, here, "remote node covered", hex);
02067 }
02068 highWhy = "covered";
02069 } else {
02070
02071 struct SyncNodeComposite *ncR = extractNode(root, info);
02072 if (ncR == NULL) {
02073
02074 if (debug >= CCNL_SEVERE)
02075 SyncNoteSimple2(root, here, "extractNode failed", hex);
02076 bytes = 0;
02077 highWhy = "extract failed";
02078 } else {
02079
02080 ce = SyncHashEnter(root->ch, xp, xs, SyncHashState_remote);
02081 ce->ncR = ncR;
02082 SyncNodeIncRC(ncR);
02083 if (debug >= CCNL_INFO) {
02084 SyncNoteSimple2(root, here, "remote node entered", hex);
02085 }
02086 if (comp == NULL) {
02087 if (debug >= CCNL_ERROR)
02088 SyncNoteSimple(root, here, "remote node comp == NULL");
02089 }
02090 highWhy = "entered";
02091 }
02092
02093 }
02094 if (debug >= CCNL_INFO && showHighLevel) {
02095 char temp[64];
02096 snprintf(temp, sizeof(temp),
02097 "reply received, %s",
02098 highWhy);
02099 showCacheEntry1(root, "Sync.$NodeFetch", temp, ce);
02100 }
02101
02102 if (comp != NULL && comp->nodeFetchBusy > 0)
02103 comp->nodeFetchBusy--;
02104 if (bytes > 0) {
02105
02106 stats->nodeFetchReceived++;
02107 stats->nodeFetchBytes += bytes;
02108 if (comp != NULL)
02109 comp->lastFetchOK = now;
02110 } else {
02111
02112 if (kind == CCN_UPCALL_INTEREST_TIMED_OUT)
02113 stats->nodeFetchTimeout++;
02114 else stats->nodeFetchFailed++;
02115 if (comp != NULL) {
02116
02117 if (!moveActionData(data, SyncActionState_error))
02118 SyncNoteFailed(root, here, "moveActionData", __LINE__);
02119 comp->nodeFetchFailed++;
02120 selfp->data = NULL;
02121 }
02122 }
02123 if (ce != NULL && (ce->state & SyncHashState_fetching))
02124
02125 ce->state -= SyncHashState_fetching;
02126 kickCompare(comp, data);
02127 free(hex);
02128 break;
02129 }
02130 default:
02131
02132 ret = CCN_UPCALL_RESULT_ERR;
02133 break;
02134 }
02135 break;
02136 }
02137 default:
02138
02139 ret = CCN_UPCALL_RESULT_ERR;
02140 break;
02141 }
02142 return ret;
02143 }
02144
02145 extern int
02146 SyncStartNodeFetch(struct SyncRootStruct *root,
02147 struct SyncHashCacheEntry *ce,
02148 struct SyncCompareData *comp) {
02149 static char *here = "Sync.SyncStartNodeFetch";
02150 enum SyncRegisterActionKind kind = SRI_Kind_NodeFetch;
02151 struct SyncBaseStruct *base = root->base;
02152 int debug = base->debug;
02153 struct ccn *ccn = base->ccn;
02154 if (ccn == NULL)
02155 return SyncNoteFailed(root, here, "bad ccn handle", __LINE__);
02156
02157 struct ccn_charbuf *hash = ce->hash;
02158 struct SyncActionData *data = root->actions;
02159 if (ce->state & SyncHashState_fetching)
02160
02161 return 0;
02162 while (data != NULL) {
02163 if (data->kind == kind && compareHash(data->hash, hash) == 0)
02164 return 0;
02165 data = data->next;
02166 }
02167
02168 struct ccn_closure *action = NEW_STRUCT(1, ccn_closure);
02169 data = newActionData(kind);
02170 struct ccn_charbuf *name = constructCommandPrefix(root, kind);
02171 int res = -1;
02172 char *why = "constructCommandPrefix";
02173 if (name != NULL) {
02174 data->skipToHash = SyncComponentCount(name);
02175 ccn_name_append(name, hash->buf, hash->length);
02176 data->prefix = name;
02177 data->hash = ccn_charbuf_create();
02178 ccn_charbuf_append_charbuf(data->hash, hash);
02179 data->comp = comp;
02180 action->data = data;
02181 action->p = &SyncRemoteFetchResponse;
02182
02183 struct ccn_charbuf *template = SyncGenInterest(NULL,
02184 root->priv->syncScope,
02185 base->priv->fetchLifetime,
02186 -1, 1, NULL);
02187 res = ccn_express_interest(ccn, name, action, template);
02188 if (res < 0) {
02189 why = "ccn_express_interest";
02190 if (debug >= CCNL_SEVERE) {
02191 char *hex = SyncHexStr(hash->buf, hash->length);
02192 SyncNoteSimple2(root, here, "failed to express interest", hex);
02193 free(hex);
02194 }
02195 } else {
02196 root->priv->stats->nodeFetchSent++;
02197 if (debug >= CCNL_INFO) {
02198 char *hex = SyncHexStr(hash->buf, hash->length);
02199 SyncNoteSimple2(root, here, "fetching", hex);
02200 free(hex);
02201 if (showHighLevel)
02202 showCacheEntry1(root, "Sync.$NodeFetch", "interest sent", ce);
02203 }
02204 }
02205 ccn_charbuf_destroy(&template);
02206 }
02207 if (res >= 0) {
02208
02209 linkActionData(root, data);
02210 comp->nodeFetchBusy++;
02211 ce->state |= SyncHashState_fetching;
02212 res = 1;
02213 } else {
02214
02215 comp->nodeFetchFailed++;
02216 data = destroyActionData(data);
02217 free(action);
02218 if (debug >= CCNL_SEVERE)
02219 SyncNoteFailed(root, here, why, __LINE__);
02220 }
02221 return res;
02222 }
02223
02224 extern int
02225 SyncStartContentFetch(struct SyncRootStruct *root,
02226 struct ccn_charbuf *name,
02227 struct SyncCompareData *comp) {
02228 static char *here = "Sync.SyncStartContentFetch";
02229 struct SyncBaseStruct *base = root->base;
02230 int debug = base->debug;
02231 struct ccn *ccn = base->ccn;
02232 if (ccn == NULL || name == NULL)
02233 return SyncNoteFailed(root, here, "bad ccnr handle", __LINE__);
02234
02235
02236 struct ccn_charbuf *interest = SyncGenInterest(name, 1, 0, 0, -1, NULL);
02237 int res = r_sync_lookup(base->client_handle, interest, NULL);
02238 ccn_charbuf_destroy(&interest);
02239
02240 if (res >= 0) {
02241
02242
02243 if (debug >= CCNL_INFO)
02244 SyncNoteUri(root, here, "ignored, already present", name);
02245 SyncAddName(root->base, name, 0);
02246 res = 0;
02247 } else {
02248 struct ccn_closure *action = NEW_STRUCT(1, ccn_closure);
02249 struct SyncActionData *data = newActionData(SRI_Kind_Content);
02250 data->prefix = ccn_charbuf_create();
02251 ccn_charbuf_append_charbuf(data->prefix, name);
02252 data->comp = comp;
02253 action->data = data;
02254 action->p = &SyncRemoteFetchResponse;
02255 data->skipToHash = -1;
02256 struct ccn_charbuf *template = SyncGenInterest(NULL,
02257 root->priv->syncScope,
02258 base->priv->fetchLifetime,
02259 0, -1, NULL);
02260 res = ccn_express_interest(ccn, name, action, template);
02261 ccn_charbuf_destroy(&template);
02262 if (res >= 0) {
02263
02264 root->priv->stats->contentFetchSent++;
02265 linkActionData(root, data);
02266 res = 1;
02267 if (debug >= CCNL_INFO)
02268 SyncNoteUri(root, here, "fetching", name);
02269 comp->contentFetchBusy++;
02270 } else {
02271
02272 if (debug >= CCNL_SEVERE)
02273 SyncNoteUri(root, here, "failed", name);
02274 data = destroyActionData(data);
02275 free(action);
02276 comp->contentFetchFailed++;
02277 }
02278 }
02279 return res;
02280 }
02281
02282 static struct SyncActionData *
02283 SyncFindAction(struct SyncRootStruct *root, enum SyncRegisterActionKind kind) {
02284 struct SyncActionData *each = root->actions;
02285 while (each != NULL) {
02286 if (each->kind == kind) return each;
02287 each = each->next;
02288 }
02289 return NULL;
02290 }
02291
02292 extern int
02293 SyncAddName(struct SyncBaseStruct *base,
02294 struct ccn_charbuf *name,
02295 ccnr_accession item) {
02296 static char *here = "Sync.SyncAddName";
02297 struct SyncPrivate *priv = base->priv;
02298 int debug = base->debug;
02299 struct SyncRootStruct *root = priv->rootHead;
02300 int count = 0;
02301 while (root != NULL) {
02302 if (SyncRootLookupName(root, name) == SyncRootLookupCode_covered) {
02303
02304
02305 struct ccn_charbuf *prev = NULL;
02306 int pos = root->namesToAdd->len;
02307 if (pos > 0) prev = root->namesToAdd->ents[pos-1].name;
02308 if (prev != NULL && SyncCmpNames(name, prev) == 0) {
02309
02310 if (debug >= CCNL_FINE) {
02311 SyncNoteUri(root, here, "ignore dup", name);
02312 }
02313 } else {
02314
02315 uintmax_t itemNum = ccnr_accession_encode(base->client_handle, item);
02316 SyncNameAccumAppend(root->namesToAdd, SyncCopyName(name), itemNum);
02317 if (item != CCNR_NULL_ACCESSION)
02318 root->priv->highWater = ccnr_hwm_update(base->client_handle,
02319 root->priv->highWater,
02320 item);
02321 count++;
02322 if (debug >= CCNL_FINE) {
02323 char temp[64];
02324
02325 if (item >= CCNR_MIN_ACCESSION && item <= CCNR_MAX_ACCESSION) {
02326 snprintf(temp, sizeof(temp), "added, %ju", itemNum);
02327 } else {
02328 snprintf(temp, sizeof(temp), "no accession");
02329 }
02330 SyncNoteUri(root, here, temp, name);
02331 }
02332 }
02333 }
02334 root = root->next;
02335 }
02336 if (item != CCNR_NULL_ACCESSION)
02337 base->highWater = ccnr_hwm_update(base->client_handle, base->highWater, item);
02338 return count;
02339 }
02340
02341 static int
02342 findAndDeleteRoot(struct SyncBaseStruct *base, char *here,
02343 const unsigned char *hp, ssize_t hs) {
02344 struct SyncRootStruct *root = base->priv->rootHead;
02345 int debug = base->debug;
02346 while (root != NULL) {
02347 struct ccn_charbuf *sh = root->sliceHash;
02348 if (sh->length == hs && memcmp(sh->buf, hp, hs) == 0) {
02349
02350 if (debug >= CCNL_INFO) {
02351 char *hex = SyncHexStr(hp, hs);
02352 ccnr_msg(base->client_handle,
02353 "%s, root#%u, deleted, %s",
02354 here, root->rootId, hex);
02355 free(hex);
02356 }
02357
02358 struct SyncPrivate *priv = base->priv;
02359 struct SyncHashCacheEntry *ce = priv->storingHead;
02360 struct SyncHashCacheEntry *lag = NULL;
02361 while (ce != NULL) {
02362 struct SyncHashCacheEntry *ceN = ce->storing;
02363 if (ce->head->root == root) {
02364
02365 if (lag == NULL) priv->storingHead = ceN;
02366 else lag->storing = ceN;
02367 if (priv->nStoring > 0) priv->nStoring--;
02368 } else lag = ce;
02369 if (ceN == NULL) priv->storingTail = lag;
02370 ce = ceN;
02371 }
02372 SyncRemRoot(root);
02373 return 1;
02374 }
02375 root = root->next;
02376 }
02377 if (debug >= CCNL_FINE) {
02378 char *hex = SyncHexStr(hp, hs);
02379 ccnr_msg(base->client_handle,
02380 "%s, root not found, %s",
02381 here, hex);
02382 free(hex);
02383 }
02384 return 0;
02385 }
02386
02387 extern int
02388 SyncHandleSlice(struct SyncBaseStruct *base, struct ccn_charbuf *name) {
02389 char *here = "Sync.SyncHandleSlice";
02390 char *why = NULL;
02391 struct ccnr_handle *ccnr = base->client_handle;
02392 int debug = base->debug;
02393 const unsigned char *hp = NULL;
02394 ssize_t hs = 0;
02395 int match = SyncPrefixMatch(base->priv->sliceCmdPrefix, name, 0);
02396 if (match < 0) return match;
02397
02398 SyncGetComponentPtr(name, match, &hp, &hs);
02399 why = "invalid hash";
02400 if (hs > 0 && hs < MAX_HASH_BYTES) {
02401
02402 struct ccn_charbuf *content = ccn_charbuf_create();
02403 struct ccn_charbuf *interest = SyncGenInterest(name, 1, 0, -1, 1, NULL);
02404 int lookupRes = -__LINE__;
02405 if (interest != NULL) {
02406 lookupRes = r_sync_lookup(ccnr, interest, content);
02407 ccn_charbuf_destroy(&interest);
02408 }
02409 why = "bad fetch";
02410 if (lookupRes >= 0 && content->length > 0) {
02411
02412 struct ccn_parsed_ContentObject pcos;
02413 struct ccn_parsed_ContentObject *pco = &pcos;
02414 int parseRes = ccn_parse_ContentObject(content->buf,
02415 content->length,
02416 pco, NULL);
02417 const unsigned char *xp = NULL;
02418 size_t xs = 0;
02419 why = "bad content object";
02420 if (parseRes >= 0) {
02421 if (pco->type == CCN_CONTENT_GONE) {
02422 findAndDeleteRoot(base, here, hp, hs);
02423 ccn_charbuf_destroy(&content);
02424 return 0;
02425 } else {
02426 why = "bad content start";
02427 parseRes = SyncPointerToContent(content, pco, &xp, &xs);
02428 if (debug >= CCNL_SEVERE && (xs <= 0 || parseRes < 0)) {
02429
02430 ssize_t start = pco->offset[CCN_PCO_B_Content];
02431 ssize_t stop = pco->offset[CCN_PCO_E_Content];
02432 int len = stop-start;
02433 char *hex = SyncHexStr(content->buf+start, len);
02434 ccnr_msg(ccnr,
02435 "%s, invalid content start, line %d, len %d, %s",
02436 here, -parseRes, len, hex);
02437 free(hex);
02438 }
02439 }
02440 }
02441 if (parseRes >= 0) {
02442 struct SyncRootStruct *root = base->priv->rootHead;
02443 while (root != NULL) {
02444 struct ccn_charbuf *sh = root->sliceHash;
02445 if (sh->length == hs && memcmp(sh->buf, hp, hs) == 0) {
02446
02447
02448 if (debug >= CCNL_FINE) {
02449 char *hex = SyncHexStr(hp, hs);
02450 ccnr_msg(ccnr,
02451 "%s, new root ignored for slice %s",
02452 here, hex);
02453 free(hex);
02454 }
02455 ccn_charbuf_destroy(&content);
02456 return 0;
02457 }
02458 root = root->next;
02459 }
02460 why = "no content tag";
02461 struct ccn_buf_decoder rds;
02462 struct ccn_buf_decoder *rd = NULL;
02463 rd = ccn_buf_decoder_start(&rds, xp, xs);
02464 root = SyncRootDecodeAndAdd(base, rd);
02465 why = "slice decode";
02466 if (root != NULL) {
02467 struct ccn_charbuf *sh = root->sliceHash;
02468 if (sh->length == hs && memcmp(sh->buf, hp, hs) == 0) {
02469
02470 if (debug >= CCNL_INFO) {
02471 char *hex = SyncHexStr(hp, hs);
02472 SyncNoteSimple2(root, here, "new root for slice", hex);
02473 free(hex);
02474 }
02475 ccn_charbuf_destroy(&content);
02476 return 1;
02477 } else {
02478
02479
02480
02481 if (debug >= CCNL_WARNING) {
02482 char *hexL = SyncHexStr(sh->buf, sh->length);
02483 char *hexR = SyncHexStr(hp, hs);
02484 ccnr_msg(ccnr, "%s, failed, hashes not equal, L %s, R %s",
02485 here, hexL, hexR);
02486 free(hexL);
02487 free(hexR);
02488 }
02489 root = SyncRemRoot(root);
02490 if (root != NULL) {
02491
02492 SyncNoteFailed(root, here, "root not removed", __LINE__);
02493 }
02494 }
02495 }
02496
02497 }
02498 }
02499 if (debug >= CCNL_SEVERE)
02500 ccnr_msg(ccnr, "%s, failed! (%s)", here, why);
02501 ccn_charbuf_destroy(&content);
02502 }
02503 return -1;
02504 }
02505
02506
02507
02508 static struct SyncRootDeltas *
02509 NewDeltas(struct SyncRootStruct *root) {
02510 struct SyncRootDeltas *deltas = NEW_STRUCT(1, SyncRootDeltas);
02511 deltas->ceStart = root->priv->ceCurrent;
02512 deltas->coding = ccn_charbuf_create();
02513 deltas->whenMade = SyncCurrentTime();
02514 ccnb_element_begin(deltas->coding, CCN_DTAG_SyncNodeDeltas);
02515 SyncAppendTaggedNumber(deltas->coding, CCN_DTAG_SyncVersion, SYNC_UPDATE_VERSION);
02516 return deltas;
02517 }
02518
02519
02520
02521
02522 static struct SyncRootDeltas *
02523 FreeDeltas(struct SyncRootDeltas *deltas) {
02524 if (deltas != NULL) {
02525 ccn_charbuf_destroy(&deltas->coding);
02526 ccn_charbuf_destroy(&deltas->name);
02527 ccn_charbuf_destroy(&deltas->cob);
02528 free(deltas);
02529 }
02530 return NULL;
02531 }
02532
02533
02534
02535
02536 static int
02537 RemRootDeltas(struct SyncRootStruct *root, struct SyncRootDeltas *deltas) {
02538 struct SyncRootPrivate *rp = root->priv;
02539 if (deltas != NULL) {
02540 struct SyncRootDeltas *lag = NULL;
02541 struct SyncRootDeltas *each = rp->deltasHead;
02542 while (each != NULL) {
02543 struct SyncRootDeltas *next = each->next;
02544 if (each == deltas) {
02545
02546 if (lag == NULL) rp->deltasHead = next;
02547 else lag->next = next;
02548 if (deltas == rp->deltasTail)
02549 rp->deltasTail = lag;
02550 rp->nDeltas--;
02551
02552 FreeDeltas(deltas);
02553 return 1;
02554 }
02555 lag = each;
02556 each = next;
02557 }
02558 }
02559 return 0;
02560 }
02561
02562
02563
02564 static int
02565 SendDeltasReply(struct SyncRootStruct *root, struct SyncRootDeltas *deltas) {
02566 static char *here = "Sync.SendDeltasReply";
02567 struct SyncBaseStruct *base = root->base;
02568 struct SyncRootPrivate *rp = root->priv;
02569 struct ccn_charbuf *name = deltas->name;
02570 struct ccn_charbuf *cob = deltas->cob;
02571 int res = 0;
02572 int debug = root->base->debug;
02573 char *newCobMsg = "";
02574 if (name == NULL) {
02575
02576 struct ccn_charbuf *hash = NULL;
02577 name = constructCommandPrefix(root, SRI_Kind_RootAdvise);
02578 if (deltas->ceStart != NULL) hash = deltas->ceStart->hash;
02579 if (hash == NULL)
02580
02581 ccn_name_append_str(name, "");
02582 else
02583
02584 ccn_name_append(name, hash->buf, hash->length);
02585
02586 hash = deltas->ceStop->hash;
02587 ccn_name_append(name, hash->buf, hash->length);
02588 ccn_create_version(base->ccn, name, CCN_V_NOW, 0, 0);
02589 ccn_name_append_numeric(name, CCN_MARKER_SEQNUM, 0);
02590 deltas->name = name;
02591 }
02592 if (cob == NULL) {
02593
02594 cob = SyncSignBuf(base, deltas->coding, name,
02595 base->priv->rootAdviseFresh,
02596 CCN_SP_FINAL_BLOCK);
02597 deltas->cob = cob;
02598 newCobMsg = "+";
02599 }
02600 res = ccn_put(base->ccn, cob->buf, cob->length);
02601 if (res >= 0) {
02602
02603 deltas->whenSent = SyncCurrentTime();
02604 if (debug >= CCNL_INFO) {
02605 char temp[64];
02606 snprintf(temp, sizeof(temp),
02607 "reply sent%s (%u)",
02608 newCobMsg,
02609 deltas->deltasCount);
02610 SyncNoteUri(root, here, temp, name);
02611 if (showHighLevel)
02612 showCacheEntry2(root, "Sync.$RootAdvise", temp,
02613 deltas->ceStart, deltas->ceStop);
02614 }
02615 } else {
02616 if (debug >= CCNL_SEVERE)
02617 SyncNoteUri(root, here, "reply failed", name);
02618 }
02619
02620
02621 while (rp->nDeltas > nDeltasLimit) {
02622 deltas = rp->deltasHead;
02623 if (deltas == rp->deltasTail) break;
02624 if (RemRootDeltas(root, deltas) != 1) break;
02625 }
02626 return res;
02627 }
02628
02629
02630
02631 static struct SyncHashInfoList *
02632 scanRemoteSeen(struct SyncRootStruct *root, struct SyncHashCacheEntry *ceR) {
02633 struct SyncHashInfoList *remoteSeen = root->priv->remoteSeen;
02634 while (remoteSeen != NULL) {
02635 if (remoteSeen->ce == ceR) return remoteSeen;
02636 remoteSeen = remoteSeen->next;
02637 }
02638 return NULL;
02639 }
02640
02641
02642
02643
02644 static struct SyncRootDeltas *
02645 CloseUpdateCoding(struct SyncUpdateData *ud) {
02646 struct SyncRootStruct *root = ud->root;
02647 struct SyncRootDeltas *deltas = ud->deltas;
02648 if (deltas != NULL) {
02649 struct SyncHashCacheEntry *ceStop = root->priv->ceCurrent;
02650 ud->deltas = NULL;
02651 deltas->next = NULL;
02652 if (deltas->deltasCount <= 0 || deltas->coding == NULL || ud->ceStart == ceStop) {
02653
02654 FreeDeltas(deltas);
02655 deltas = NULL;
02656 } else {
02657
02658 ccnb_element_end(deltas->coding);
02659 struct SyncRootPrivate *rp = root->priv;
02660 struct SyncRootDeltas *tail = rp->deltasTail;
02661 if (tail != NULL) {
02662 tail->next = deltas;
02663 } else {
02664 rp->deltasHead = deltas;
02665 }
02666 tail = deltas;
02667 deltas->ceStop = ceStop;
02668 rp->nDeltas++;
02669 }
02670 }
02671 return deltas;
02672 }
02673
02674
02675
02676 static struct SyncRootDeltas *
02677 scanDeltas(struct SyncRootStruct *root, struct SyncHashCacheEntry *ceR) {
02678 struct SyncRootDeltas *deltas = root->priv->deltasHead;
02679 while (deltas != NULL) {
02680 if (deltas->ceStart == ceR) break;
02681 deltas = deltas->next;
02682 }
02683 return deltas;
02684 }
02685
02686 extern enum ccn_upcall_res
02687 SyncInterestArrived(struct ccn_closure *selfp,
02688 enum ccn_upcall_kind kind,
02689 struct ccn_upcall_info *info) {
02690 static char *here = "Sync.SyncInterestArrived";
02691 struct SyncActionData *data = selfp->data;
02692 enum ccn_upcall_res ret = CCN_UPCALL_RESULT_OK;
02693 char temp[200];
02694 switch (kind) {
02695 case CCN_UPCALL_FINAL:
02696 data = destroyActionData(data);
02697 free(selfp);
02698 break;
02699 case CCN_UPCALL_INTEREST: {
02700 struct SyncRootStruct *root = data->root;
02701 if (root == NULL) break;
02702 struct SyncRootPrivate *rp = root->priv;
02703 struct SyncBaseStruct *base = root->base;
02704 int debug = base->debug;
02705 int skipToHash = data->skipToHash;
02706 const unsigned char *buf = info->interest_ccnb;
02707 struct ccn_indexbuf *comps = info->interest_comps;
02708 char *hexL = NULL;
02709 char *hexR = NULL;
02710 if ((info->pi->answerfrom & CCN_AOK_NEW) == 0) {
02711
02712 if (debug >= CCNL_INFO)
02713 SyncNoteUri(root, here, "CCN_AOK_NEW = 0", data->prefix);
02714 break;
02715 }
02716 switch (data->kind) {
02717 case SRI_Kind_None:
02718
02719 break;
02720 case SRI_Kind_RootStats: {
02721 char *who = getKindStr(data->kind);
02722 struct ccn_charbuf *name = SyncCopyName(data->prefix);
02723 ccn_create_version(info->h, name, CCN_V_NOW, 0, 0);
02724 ccn_name_append_numeric(name, CCN_MARKER_SEQNUM, 0);
02725 if (debug >= CCNL_FINE)
02726 SyncNoteUri(root, here, who, name);
02727 struct ccn_charbuf *cb = ccn_charbuf_create();
02728 struct timeval tv = {0};
02729 gettimeofday(&tv, 0);
02730 int pos = snprintf(temp, sizeof(temp),
02731 "%ju.%06u: ",
02732 (uintmax_t) tv.tv_sec,
02733 (unsigned) tv.tv_usec);
02734 ccn_charbuf_append(cb, temp, pos);
02735 formatStats(root, cb);
02736 struct ccn_charbuf *cob = SyncSignBuf(base, cb, name,
02737 1, CCN_SP_FINAL_BLOCK);
02738 int res = ccn_put(info->h, cob->buf, cob->length);
02739 if (res >= 0) {
02740
02741 if (debug >= CCNL_INFO)
02742 SyncNoteUri(root, here, "reply sent", name);
02743 } else {
02744 if (debug >= CCNL_SEVERE)
02745 SyncNoteUri(root, here, "reply failed", name);
02746 }
02747 ccn_charbuf_destroy(&name);
02748 ccn_charbuf_destroy(&cb);
02749 ccn_charbuf_destroy(&cob);
02750 ret = CCN_UPCALL_RESULT_INTEREST_CONSUMED;
02751 break;
02752 }
02753 case SRI_Kind_AdviseInt:
02754 case SRI_Kind_FetchInt: {
02755 const unsigned char *bufR = NULL;
02756 size_t lenR = 0;
02757 struct SyncHashCacheEntry *ceL = NULL;
02758 struct SyncHashCacheEntry *ceR = NULL;
02759 const unsigned char *bufL = root->currentHash->buf;
02760 char *who = getKindStr(data->kind);
02761 size_t lenL = root->currentHash->length;
02762 char *highHere = "??";
02763 ccn_name_comp_get(buf, comps, skipToHash, &bufR, &lenR);
02764 if (bufR == NULL || lenR == 0) {
02765 if (data->kind == SRI_Kind_FetchInt) {
02766 }
02767 } else {
02768 hexR = SyncHexStr(bufR, lenR);
02769 ceR = SyncHashEnter(root->ch, bufR, lenR, SyncHashState_remote);
02770 }
02771 hexL = SyncHexStr(bufL, lenL);
02772 ceL = root->priv->ceCurrent;
02773
02774 if (debug >= CCNL_INFO) {
02775 if (hexR == NULL)
02776 SyncNoteSimple2(root, here, who, "empty remote hash");
02777 else SyncNoteSimple3(root, here, who, "remote hash", hexR);
02778 if (hexL == NULL)
02779 SyncNoteSimple2(root, here, who, "empty local hash");
02780 else SyncNoteSimple3(root, here, who, "local hash", hexL);
02781 }
02782 if (data->kind == SRI_Kind_AdviseInt) {
02783
02784
02785 int seen = noteHash(root, ceR, 1, 1);
02786 if (debug >= CCNL_INFO) {
02787
02788 rp->stats->rootAdviseSeen++;
02789 highHere = "Sync.$RootAdvise";
02790 if (debug >= CCNL_INFO && showHighLevel)
02791 showCacheEntry1(root, highHere, "interest arrived", ceR);
02792 }
02793 if (ceL == ceR) {
02794
02795 if (debug >= CCNL_INFO)
02796 SyncNoteSimple2(root, here, who, "ignored (same hash)");
02797
02798 rp->adviseNeed = 0;
02799 purgeOldEntries(root);
02800 break;
02801 }
02802 ssize_t excl_start = info->pi->offset[CCN_PI_B_Exclude];
02803 ssize_t excl_stop = info->pi->offset[CCN_PI_E_Exclude];
02804 ssize_t excl_len = excl_stop - excl_start;
02805 if (excl_len > 0) {
02806
02807 if (debug >= CCNL_FINER) {
02808 struct ccn_buf_decoder ds;
02809 struct ccn_buf_decoder *d = &ds;
02810 ccn_buf_decoder_start(d,
02811 buf+excl_start,
02812 excl_len);
02813 reportExclude(root, d);
02814 }
02815 if (useCompExcl && lenL > 0
02816 && ccn_excluded(buf+excl_start,
02817 excl_len,
02818 bufL,
02819 lenL)) {
02820
02821 if (debug >= CCNL_INFO)
02822 SyncNoteSimple2(root, here, who, "excluded");
02823 break;
02824 }
02825 }
02826 if (seen == 0 && !isCovered(ceR)) {
02827
02828
02829 rp->adviseNeed = adviseNeedReset;
02830
02831 }
02832 } else {
02833
02834 rp->stats->nodeFetchSeen++;
02835 if (ceR == NULL) {
02836
02837 if (debug >= CCNL_SEVERE)
02838 SyncNoteSimple2(root, here, who, "failed, no remote hash");
02839 return CCN_UPCALL_RESULT_ERR;
02840 }
02841 highHere = "Sync.$NodeFetch";
02842 if (debug >= CCNL_INFO && showHighLevel)
02843 showCacheEntry1(root, highHere, "interest arrived", ceR);
02844
02845 ceL = ceR;
02846 }
02847 if (lenL == 0) {
02848 if (debug >= CCNL_INFO)
02849 SyncNoteSimple2(root, here, who, "ignored (empty local root)");
02850 if (lenR == 0) {
02851
02852 rp->adviseNeed = 0;
02853 }
02854 if (root->namesToAdd->len > 0) {
02855 if (debug >= CCNL_FINE)
02856 SyncNoteSimple2(root, here, who, "new tree needed");
02857 }
02858 break;
02859 }
02860
02861 long fresh = base->priv->rootAdviseFresh;
02862
02863
02864
02865
02866
02867 rp->adviseNeed = adviseNeedReset;
02868
02869
02870
02871
02872 if (SyncCacheEntryFetch(ceL) < 0) {
02873
02874 if (debug >= CCNL_FINE) {
02875 SyncNoteSimple3(root, here, who, "no local node", hexL);
02876 }
02877 break;
02878 }
02879 struct SyncNodeComposite *ncL = ceL->ncL;
02880
02881
02882
02883
02884 struct SyncRootDeltas *deltas = NULL;
02885 struct ccn_charbuf *cbL = ncL->cb;
02886 struct ccn_charbuf *name = SyncCopyName(data->prefix);
02887 ccn_name_append(name, bufR, lenR);
02888 if (data->kind == SRI_Kind_AdviseInt) {
02889
02890 ccn_name_append(name, bufL, lenL);
02891 deltas = scanDeltas(root, ceR);
02892 if (deltas != NULL && deltas->whenSent == 0) {
02893
02894 SendDeltasReply(root, deltas);
02895 ccn_charbuf_destroy(&name);
02896 ret = CCN_UPCALL_RESULT_INTEREST_CONSUMED;
02897 break;
02898 }
02899 }
02900
02901
02902 struct ccn_charbuf *cob = NULL;
02903 if (data->kind == SRI_Kind_FetchInt) {
02904
02905 cob = ncL->content;
02906 }
02907 if (cob == NULL && cbL != NULL) {
02908
02909 cob = SyncSignBuf(base, cbL, name,
02910 fresh, CCN_SP_FINAL_BLOCK);
02911 }
02912
02913 if (cob != NULL) {
02914
02915 if (ccn_content_matches_interest(cob->buf, cob->length,
02916 1, NULL,
02917 info->interest_ccnb,
02918 info->pi->offset[CCN_PI_E],
02919 info->pi)) {
02920
02921 int res = ccn_put(info->h, cob->buf, cob->length);
02922 if (res >= 0) {
02923
02924 if (debug >= CCNL_INFO) {
02925 char *why = "reply sent";
02926 SyncNoteUri(root, here, why, name);
02927 if (showHighLevel) {
02928 if (data->kind == SRI_Kind_AdviseInt)
02929 showCacheEntry2(root, highHere, why, ceR, ceL);
02930 else showCacheEntry1(root, highHere, why, ceL);
02931 }
02932 }
02933 } else {
02934 if (debug >= CCNL_SEVERE)
02935 SyncNoteUri(root, here, "reply failed", name);
02936 }
02937 ret = CCN_UPCALL_RESULT_INTEREST_CONSUMED;
02938 } else {
02939
02940 if (debug >= CCNL_FINE)
02941 SyncNoteUri(root, here, "no match", name);
02942 }
02943 if (data->kind == SRI_Kind_FetchInt) {
02944
02945 ncL->content = cob;
02946 } else {
02947
02948
02949 ccn_charbuf_destroy(&cob);
02950 }
02951 }
02952 ccn_charbuf_destroy(&name);
02953 break;
02954 }
02955 default:
02956
02957 ret = CCN_UPCALL_RESULT_ERR;
02958 break;
02959 }
02960 if (hexL != NULL) free(hexL);
02961 if (hexR != NULL) free(hexR);
02962 break;
02963 }
02964 default:
02965
02966 ret = CCN_UPCALL_RESULT_ERR;
02967 break;
02968 }
02969 return ret;
02970
02971 }
02972
02973 static int
02974 SyncRegisterInterest(struct SyncRootStruct *root,
02975 enum SyncRegisterActionKind kind) {
02976 static char *here = "Sync.SyncRegisterInterest";
02977 int res = 0;
02978 struct SyncBaseStruct *base = root->base;
02979 int debug = base->debug;
02980 if (base->ccn == NULL)
02981 return -__LINE__;
02982 struct ccn_charbuf *prefix = constructCommandPrefix(root, kind);
02983 if (prefix != NULL) {
02984
02985 struct ccn_closure *action = NEW_STRUCT(1, ccn_closure);
02986 struct SyncActionData *data = newActionData(kind);
02987 data->prefix = prefix;
02988 data->skipToHash = SyncComponentCount(prefix);
02989 action->data = data;
02990 action->p = &SyncInterestArrived;
02991
02992
02993 res |= ccn_set_interest_filter(root->base->ccn, prefix, action);
02994 if (res < 0) {
02995 if (debug >= CCNL_SEVERE)
02996 SyncNoteUri(root, here, "ccn_set_interest_filter failed", prefix);
02997 data = destroyActionData(data);
02998 } else {
02999 linkActionData(root, data);
03000 if (debug >= CCNL_INFO)
03001 SyncNoteUri(root, here, getKindStr(kind), prefix);
03002 }
03003 } else {
03004
03005 res = SyncNoteFailed(root, here, "bad prefix", __LINE__);
03006 }
03007 return res;
03008 }
03009
03010 extern int
03011 SyncRegisterInterests(struct SyncRootStruct *root) {
03012 char *here = "Sync.SyncRegisterInterests";
03013 struct SyncBaseStruct *base = root->base;
03014 struct ccn *ccn = base->ccn;
03015 if (ccn == NULL) return -1;
03016 int res = 0;
03017 if (base->debug >= CCNL_INFO) {
03018
03019 char *hex = SyncHexStr(root->sliceHash->buf, root->sliceHash->length);
03020 struct ccn_charbuf *uriTopo = NULL;
03021 char *msgTopo = "??";
03022 struct ccn_charbuf *topoPrefix = root->topoPrefix;
03023 if (topoPrefix != NULL && topoPrefix->length > 0) {
03024 uriTopo = SyncUriForName(topoPrefix);
03025 msgTopo = ccn_charbuf_as_string(uriTopo);
03026 }
03027 struct ccn_charbuf *uriPrefix = NULL;
03028 char *msgPrefix = "??";
03029 struct ccn_charbuf *namingPrefix = root->namingPrefix;
03030 if (namingPrefix != NULL && namingPrefix->length > 0) {
03031 uriPrefix = SyncUriForName(namingPrefix);
03032 msgPrefix = ccn_charbuf_as_string(uriPrefix);
03033 }
03034
03035 ccnr_msg(root->base->client_handle,
03036 "%s, root#%u, topo %s, prefix %s, hash %s",
03037 here, root->rootId, msgTopo, msgPrefix, hex);
03038
03039 struct SyncNameAccum *filter = root->filter;
03040 if (filter != NULL) {
03041 int i = 0;
03042 for (i = 0; i < filter->len; i++) {
03043 struct ccn_charbuf *uri = SyncUriForName(filter->ents[i].name);
03044 ccnr_msg(root->base->client_handle,
03045 "%s, root#%u, op %d, pattern %s",
03046 here, root->rootId,
03047 (int) filter->ents[i].data,
03048 ccn_charbuf_as_string(uri));
03049 ccn_charbuf_destroy(&uri);
03050 }
03051 }
03052 if (uriTopo != NULL) ccn_charbuf_destroy(&uriTopo);
03053 if (uriPrefix != NULL) ccn_charbuf_destroy(&uriPrefix);
03054 free(hex);
03055 }
03056 res |= SyncRegisterInterest(root, SRI_Kind_AdviseInt);
03057 res |= SyncRegisterInterest(root, SRI_Kind_FetchInt);
03058 res |= SyncRegisterInterest(root, SRI_Kind_RootStats);
03059 root->priv->adviseNeed = adviseNeedReset;
03060 return res;
03061 }
03062
03063
03064 extern enum ccn_upcall_res
03065 SyncRootAdviseResponse(struct ccn_closure *selfp,
03066 enum ccn_upcall_kind kind,
03067 struct ccn_upcall_info *info) {
03068 static char *here = "Sync.SyncRootAdviseResponse";
03069 struct SyncActionData *data = selfp->data;
03070 enum ccn_upcall_res ret = CCN_UPCALL_RESULT_OK;
03071 switch (kind) {
03072 case CCN_UPCALL_FINAL:
03073 data = destroyActionData(data);
03074 free(selfp);
03075 break;
03076 case CCN_UPCALL_CONTENT_UNVERIFIED:
03077 ret = CCN_UPCALL_RESULT_VERIFY;
03078 break;
03079 case CCN_UPCALL_CONTENT_KEYMISSING:
03080 ret = CCN_UPCALL_RESULT_FETCHKEY;
03081 break;
03082 case CCN_UPCALL_INTEREST_TIMED_OUT: {
03083 if (data == NULL || info == NULL ||
03084 data->root == NULL || data->kind != SRI_Kind_RootAdvise) {
03085
03086 } else {
03087 int64_t now = SyncCurrentTime();
03088 struct SyncRootStruct *root = data->root;
03089 int debug = root->base->debug;
03090 root->priv->stats->rootAdviseTimeout++;
03091 if (debug >= CCNL_INFO) {
03092 char temp[64];
03093 int64_t dt = SyncDeltaTime(data->startTime, now);
03094 dt = (dt + 500) / 1000;
03095 snprintf(temp, sizeof(temp),
03096 "timeout, %d.%03d secs",
03097 (int) (dt / 1000), (int) (dt % 1000));
03098 SyncNoteUri(root, here, temp, data->prefix);
03099 }
03100 data->startTime = now;
03101
03102 ret = CCN_UPCALL_RESULT_REEXPRESS;
03103 }
03104 break;
03105 }
03106 case CCN_UPCALL_CONTENT_RAW:
03107 case CCN_UPCALL_CONTENT: {
03108 if (data == NULL || info == NULL ||
03109 data->root == NULL || data->kind != SRI_Kind_RootAdvise) {
03110
03111 break;
03112 }
03113 struct SyncRootStruct *root = data->root;
03114 int debug = root->base->debug;
03115 if (debug >= CCNL_INFO) {
03116 struct ccn_charbuf *nm = SyncNameForIndexbuf(info->content_ccnb,
03117 info->content_comps);
03118 size_t bytes = info->pco->offset[CCN_PCO_E];
03119 char temp[64];
03120 int64_t dt = SyncDeltaTime(data->startTime, SyncCurrentTime());
03121 dt = (dt + 500) / 1000;
03122 snprintf(temp, sizeof(temp),
03123 "content, %d.%03d secs, %u bytes",
03124 (int) (dt / 1000), (int) (dt % 1000),
03125 (unsigned) bytes);
03126 SyncNoteUri(root, here, temp, nm);
03127 ccn_charbuf_destroy(&nm);
03128 }
03129
03130 const unsigned char *hp = NULL;
03131 size_t hs = 0;
03132 size_t bytes = 0;
03133 int failed = 0;
03134 int cres = ccn_name_comp_get(info->content_ccnb,
03135 info->content_comps,
03136 data->skipToHash, &hp, &hs);
03137 if (cres < 0 || hp == NULL || hs == 0) {
03138
03139 failed++;
03140 SyncNoteFailed(root, here, "bad hash", __LINE__);
03141 } else if (fauxError(root->base)) {
03142 failed++;
03143 if (debug >= CCNL_WARNING)
03144 SyncNoteSimple(root, here, "faux error");
03145 } else {
03146 char *highWhy = "covered";
03147 char highWhyTemp[32];
03148 struct SyncHashCacheEntry *ce = SyncHashEnter(root->ch, hp, hs,
03149 SyncHashState_remote);
03150 noteHash(root, ce, 1, 1);
03151 if (!isCovered(ce)) {
03152
03153 struct SyncNodeComposite *nc = NULL;
03154 char *hex = SyncHexStr(hp, hs);
03155 if (ce != NULL && ce->ncR != NULL) {
03156 nc = ce->ncR;
03157 highWhy = "not covered";
03158 if (debug >= CCNL_INFO)
03159 SyncNoteSimple2(root, here, highWhy, hex);
03160 } else {
03161 int nd = extractDeltas(root, info);
03162 if (nd > 0) {
03163
03164 snprintf(highWhyTemp, sizeof(highWhyTemp),
03165 "deltas (%u)", nd);
03166 highWhy = highWhyTemp;
03167 if (debug >= CCNL_INFO) {
03168 SyncNoteSimple2(root, here, highWhy, hex);
03169 }
03170 SyncStartCompareAction(root, NULL);
03171 } else {
03172 nc = extractNode(root, info);
03173 if (nc == NULL) {
03174
03175 failed++;
03176 if (debug >= CCNL_SEVERE)
03177 SyncNoteSimple2(root, here, "extractNode failed", hex);
03178 } else {
03179
03180 ce->ncR = nc;
03181 SyncNodeIncRC(nc);
03182 bytes = info->pco->offset[CCN_PCO_E];
03183 if (debug >= CCNL_INFO)
03184 SyncNoteSimple2(root, here, "remote entered", hex);
03185 SyncStartCompareAction(root, ce->hash);
03186 }
03187 }
03188 }
03189 free(hex);
03190 }
03191 if (debug >= CCNL_INFO && showHighLevel) {
03192 char temp[64];
03193 snprintf(temp, sizeof(temp),
03194 "reply received, %s",
03195 highWhy);
03196 showCacheEntry2(root, "Sync.$RootAdvise", temp,
03197 root->priv->ceCurrent,
03198 ce);
03199 }
03200 }
03201 if (failed) {
03202 root->priv->stats->rootAdviseFailed++;
03203 } else {
03204 root->priv->stats->rootAdviseReceived++;
03205 root->priv->stats->rootAdviseBytes += bytes;
03206 }
03207 break;
03208 }
03209 default:
03210
03211 ret = CCN_UPCALL_RESULT_ERR;
03212 break;
03213 }
03214 return ret;
03215 }
03216
03217 extern int
03218 SyncSendRootAdviseInterest(struct SyncRootStruct *root) {
03219 static char *here = "Sync.SyncSendRootAdviseInterest";
03220 enum SyncRegisterActionKind kind = SRI_Kind_RootAdvise;
03221 int debug = root->base->debug;
03222 struct SyncActionData *data = SyncFindAction(root, kind);
03223 struct SyncHashCacheEntry *ce = root->priv->ceCurrent;
03224 if (root->base->ccn == NULL)
03225
03226 return 0;
03227 if (data != NULL) {
03228
03229 if (ce == NULL || ce == root->priv->lastLocalSent)
03230 return 0;
03231
03232 data->kind = SRI_Kind_None;
03233 if (debug >= CCNL_FINE)
03234 SyncNoteSimple(root, here, "marked old interest as inactive");
03235 }
03236 struct ccn_closure *action = NEW_STRUCT(1, ccn_closure);
03237 struct ccn_charbuf *prefix = constructCommandPrefix(root, kind);
03238 struct ccn_charbuf *hash = ccn_charbuf_create();
03239
03240 ccn_charbuf_append_charbuf(hash, root->currentHash);
03241 ccn_name_append(prefix, hash->buf, hash->length);
03242
03243 data = newActionData(kind);
03244 data->skipToHash = SyncComponentCount(prefix);
03245 data->hash = hash;
03246 data->prefix = prefix;
03247 action->data = data;
03248 action->p = &SyncRootAdviseResponse;
03249
03250 struct SyncNameAccum *excl = exclusionsFromHashList(root, NULL, root->priv->remoteSeen);
03251 excl = exclusionsFromHashList(root, excl, root->priv->localMade);
03252 int exclCount = ((excl == NULL) ? 0 : excl->len);
03253 struct ccn_charbuf *template = SyncGenInterest(NULL,
03254 root->priv->syncScope,
03255 root->base->priv->rootAdviseLifetime,
03256 -1, -1,
03257 excl);
03258 int res = ccn_express_interest(root->base->ccn,
03259 prefix,
03260 action,
03261 template);
03262 SyncFreeNameAccumAndNames(excl);
03263 ccn_charbuf_destroy(&template);
03264 if (res >= 0) {
03265
03266 if (root->priv->adviseNeed > 0) root->priv->adviseNeed--;
03267 linkActionData(root, data);
03268 root->priv->lastAdvise = SyncCurrentTime();
03269 root->priv->lastLocalSent = ce;
03270 root->priv->stats->rootAdviseSent++;
03271 if (debug >= CCNL_INFO) {
03272 SyncNoteUri(root, here, "sent", prefix);
03273 if (showHighLevel) {
03274 char temp[32];
03275 snprintf(temp, sizeof(temp),
03276 "interest sent (excl %d)", exclCount);
03277 showCacheEntry1(root, "Sync.$RootAdvise", temp, ce);
03278 }
03279 }
03280 return 1;
03281 } else {
03282
03283 data = destroyActionData(data);
03284 free(action);
03285 if (debug >= CCNL_ERROR)
03286 SyncNoteSimple(root, here, "ccn_express_interest failed");
03287 return -1;
03288 }
03289 }
03290
03291 static int
03292 MakeNodeFromNames(struct SyncUpdateData *ud, int split) {
03293 char *here = "Sync.MakeNodeFromNames";
03294 struct SyncRootStruct *root = ud->root;
03295 int debug = root->base->debug;
03296 struct SyncNameAccum *na = ud->sort;
03297 int lim = na->len;
03298 if (lim == 0)
03299
03300 return 0;
03301 int i = 0;
03302 if (split == 0) split = lim;
03303 if (debug >= CCNL_FINE) {
03304 char tmp[64];
03305 snprintf(tmp, sizeof(tmp),
03306 "split %d, lim %d",
03307 split, lim);
03308 SyncNoteSimple(root, here, tmp);
03309 }
03310
03311
03312 struct SyncLongHashStruct longHash;
03313 memset(&longHash, 0, sizeof(struct SyncLongHashStruct));
03314 longHash.pos = MAX_HASH_BYTES;
03315 for (i = 0; i < split; i++) {
03316 struct ccn_charbuf *name = na->ents[i].name;
03317 SyncAccumHash(&longHash, name);
03318 }
03319 ssize_t hs = MAX_HASH_BYTES-longHash.pos;
03320 unsigned char *hp = longHash.bytes+longHash.pos;
03321 struct SyncHashCacheEntry *ce = SyncHashLookup(root->ch, hp, hs);
03322 if (ce != NULL && ce->ncL != NULL) {
03323
03324 struct SyncNodeComposite *nc = ce->ncL;
03325 SyncNodeIncRC(nc);
03326 SyncAccumNode(ud->nodes, nc);
03327 root->priv->stats->nodesShared++;
03328 if (debug >= CCNL_FINE) {
03329 char *hex = SyncHexStr(hp, hs);
03330 SyncNoteSimple2(root, here, "existing local node", hex);
03331 free(hex);
03332 }
03333 } else {
03334
03335 if (debug >= CCNL_FINE) {
03336 char *hex = SyncHexStr(hp, hs);
03337 SyncNoteSimple2(root, here, "need new local node", hex);
03338 free(hex);
03339 }
03340 struct SyncNodeComposite *nc = SyncAllocComposite(root->base);
03341 for (i = 0; i < split; i++) {
03342 struct ccn_charbuf *name = na->ents[i].name;
03343 SyncNodeAddName(nc, name);
03344 ccn_charbuf_destroy(&name);
03345 na->ents[i].name = NULL;
03346 }
03347 SyncEndComposite(nc);
03348 newNodeCommon(root, ud->nodes, nc);
03349 }
03350
03351 ud->nameLenAccum = 0;
03352 i = 0;
03353 while (split < lim) {
03354 struct ccn_charbuf *name = na->ents[split].name;
03355 ud->nameLenAccum += name->length;
03356 na->ents[i] = na->ents[split];
03357 na->ents[split].name = NULL;
03358 i++;
03359 split++;
03360 }
03361 na->len = i;
03362 return i;
03363 }
03364
03365 static int
03366 TryNodeSplit(struct SyncUpdateData *ud) {
03367 char *here = "Sync.TryNodeSplit";
03368 struct SyncNameAccum *na = ud->sort;
03369 int lim = na->len;
03370 if (lim == 0)
03371
03372 return 0;
03373 struct SyncRootStruct *root = ud->root;
03374 int debug = root->base->debug;
03375 struct ccn_charbuf *prev = NULL;
03376 int accLim = nodeSplitTrigger - nodeSplitTrigger/8;
03377 int accMin = nodeSplitTrigger/2;
03378 int res = 0;
03379 int splitMethod = 3;
03380 int maxLen = 0;
03381 int accLen = 0;
03382 int prevMatch = 0;
03383 int split = 0;
03384 if (debug >= CCNL_FINE) {
03385 char tmp[64];
03386 snprintf(tmp, sizeof(tmp),
03387 "entered, %d names",
03388 lim);
03389 SyncNoteSimple(root, here, tmp);
03390 }
03391 for (split = 0; split < lim; split++) {
03392 struct ccn_charbuf *name = na->ents[split].name;
03393 int nameLen = name->length + 8;
03394 if (nameLen > maxLen) maxLen = nameLen;
03395 accLen = accLen + nameLen + (maxLen - nameLen) * 2;
03396 prev = name;
03397 if (split+1 < lim) {
03398 if (splitMethod & 1) {
03399
03400 struct ccn_charbuf *next = na->ents[split+1].name;
03401 int match = SyncComponentMatch(name, next);
03402 if (accLen >= accMin
03403 && (match < prevMatch || (match > prevMatch+1))) {
03404
03405 if (debug >= CCNL_FINE) {
03406 char tmp[64];
03407 snprintf(tmp, sizeof(tmp),
03408 "split %d, lim %d, match %d, prev %d, accLen %d",
03409 split, lim, match, prevMatch, accLen);
03410 SyncNoteSimple2(root, here, "level split found", tmp);
03411 }
03412 break;
03413 }
03414 prevMatch = match;
03415 }
03416 if (splitMethod & 2) {
03417
03418 int pos = name->length - 9;
03419 if (pos > 0 && accLen >= accMin) {
03420 unsigned c = name->buf[pos] & 255;
03421 if (c < hashSplitTrigger) {
03422 if (debug >= CCNL_FINE) {
03423 char tmp[64];
03424 snprintf(tmp, sizeof(tmp),
03425 "split %d, lim %d, x %u, accLen %d",
03426 split, lim, c, accLen);
03427 SyncNoteSimple2(root, here, "hash split found", tmp);
03428 }
03429 break;
03430 }
03431 }
03432 }
03433 }
03434 if (accLen >= accLim) {
03435 break;
03436 }
03437 }
03438
03439 res = MakeNodeFromNames(ud, split);
03440 return res;
03441 }
03442
03443
03444
03445 static int
03446 AddUpdateName(struct SyncUpdateData *ud, struct ccn_charbuf *name, int isNew) {
03447 static char *here = "Sync.AddUpdateName";
03448 struct SyncRootStruct *root = ud->root;
03449 int debug = root->base->debug;
03450 struct SyncNameAccum *dst = ud->sort;
03451 int nameLen = name->length;
03452 int accLim = nodeSplitTrigger - nodeSplitTrigger/8;
03453 int res = 0;
03454 name = SyncCopyName(name);
03455 SyncNameAccumAppend(dst, name, 0);
03456 if (debug >= CCNL_FINE) {
03457 char *msg = ((isNew) ? "added+" : "added");
03458 SyncNoteUri(root, here, msg, name);
03459 }
03460 if (isNew) {
03461 struct SyncRootDeltas *deltas = ud->deltas;
03462 int deltasLimit = root->base->priv->deltasLimit;
03463 if (deltasLimit > 0 && deltas != NULL && deltas->coding != NULL) {
03464
03465 ccn_charbuf_append_charbuf(deltas->coding, name);
03466 if (deltas->coding->length > deltasLimit) {
03467
03468 ccn_charbuf_destroy(&deltas->coding);
03469 }
03470 deltas->deltasCount++;
03471 }
03472 }
03473
03474 ud->nameLenAccum += nameLen;
03475 ud->namesAdded++;
03476 if (ud->nameLenAccum >= accLim) {
03477
03478 res = TryNodeSplit(ud);
03479 }
03480 return res;
03481 }
03482
03483
03484
03485 static int
03486 SyncTreeMergeNames(struct SyncTreeWorkerHead *head,
03487 struct SyncUpdateData *ud) {
03488 char *here = "Sync.SyncTreeMergeNames";
03489 struct SyncRootStruct *root = ud->root;
03490 int debug = root->base->debug;
03491 IndexSorter_Base ixBase = ud->ixBase;
03492 struct SyncNameAccum *src = (struct SyncNameAccum *) ixBase->client;
03493 IndexSorter_Index srcPos = 0;
03494 struct ccn_charbuf *cb = ud->cb;
03495 int res = 0;
03496 int namesLim = ud->namesAdded+namesYieldInc;
03497 if (head != NULL) {
03498 while (res == 0) {
03499 struct SyncTreeWorkerEntry *ent = SyncTreeWorkerTop(head);
03500 if (ent == NULL) break;
03501 if (ent->cacheEntry == NULL) {
03502
03503 res = -__LINE__;
03504 break;
03505 }
03506 struct SyncHashCacheEntry *ce = ent->cacheEntry;
03507 if (head->remote <= 0) SyncCacheEntryFetch(ce);
03508 struct SyncNodeComposite *nc = ((head->remote > 0) ? ce->ncR : ce->ncL);
03509 if (nc == NULL) {
03510
03511 res = -__LINE__;
03512 break;
03513 }
03514 int lim = nc->refLen;
03515 if (ent->pos >= lim) {
03516
03517 ent = SyncTreeWorkerPop(head);
03518 if (ent == NULL) break;
03519 ent->pos++;
03520 } else {
03521 struct SyncNodeElem *ep = &nc->refs[ent->pos];
03522 if (ep->kind & SyncElemKind_leaf) {
03523
03524 enum SyncCompareResult cmp = SCR_after;
03525 struct ccn_charbuf *name = NULL;
03526
03527 if (ud->ixBase->len > 0) {
03528 srcPos = IndexSorter_Best(ud->ixBase);
03529 name = src->ents[srcPos].name;
03530 if (name != NULL)
03531 cmp = SyncNodeCompareLeaf(nc, ep, name);
03532 }
03533 switch (cmp) {
03534 case SCR_before:
03535
03536 AddUpdateName(ud, name, 1);
03537 case SCR_min:
03538
03539 if (cmp == SCR_min) {
03540 if (debug >= CCNL_FINE) {
03541 SyncNoteUri(root, here, "skip", name);
03542 }
03543 }
03544 for (;;) {
03545 IndexSorter_Rem(ud->ixBase);
03546 if (ud->ixBase->len <= 0) break;
03547 srcPos = IndexSorter_Best(ud->ixBase);
03548 struct ccn_charbuf *next = src->ents[srcPos].name;
03549 if (SyncCmpNames(name, next) != 0) break;
03550 if (debug >= CCNL_FINE) {
03551 SyncNoteUri(root, here, "skip dup", next);
03552 }
03553 }
03554 break;
03555 case SCR_after:
03556
03557 extractBuf(cb, nc, ep);
03558 AddUpdateName(ud, cb, 0);
03559 ent->pos++;
03560 break;
03561 default:
03562
03563 res = -__LINE__;
03564 break;
03565 }
03566 if (ud->namesAdded >= namesLim) {
03567 int64_t dt = SyncDeltaTime(ud->entryTime, SyncCurrentTime());
03568 if (dt >= namesYieldMicros) {
03569
03570 if (debug >= CCNL_FINE)
03571 SyncNoteSimple(root, here, "yield");
03572 return 0;
03573 }
03574 namesLim += namesYieldInc;
03575 }
03576 } else {
03577
03578 ent = SyncTreeWorkerPush(head);
03579 if (ent == NULL) {
03580 res = -__LINE__;
03581 break;
03582 }
03583 }
03584 }
03585 }
03586 }
03587 if (res == 0) {
03588
03589 while (ud->ixBase->len > 0) {
03590 srcPos = IndexSorter_Best(ud->ixBase);
03591 struct ccn_charbuf *name = src->ents[srcPos].name;
03592 AddUpdateName(ud, name, 1);
03593 for (;;) {
03594 IndexSorter_Rem(ud->ixBase);
03595 if (ud->ixBase->len <= 0) break;
03596 srcPos = IndexSorter_Best(ud->ixBase);
03597 struct ccn_charbuf *next = src->ents[srcPos].name;
03598 if (SyncCmpNames(name, next) != 0) break;
03599 }
03600 if (ud->namesAdded >= namesLim) {
03601 int64_t dt = SyncDeltaTime(ud->entryTime, SyncCurrentTime());
03602 if (dt >= namesYieldMicros) {
03603
03604 if (debug >= CCNL_FINE)
03605 SyncNoteSimple(root, here, "yield");
03606 return 0;
03607 }
03608 namesLim += namesYieldInc;
03609 }
03610 }
03611 res = 1;
03612 }
03613 return res;
03614 }
03615
03616 static struct SyncUpdateData *
03617 FreeUpdateData(struct SyncUpdateData *ud) {
03618 if (ud != NULL) {
03619 ud->sort = SyncFreeNameAccumAndNames(ud->sort);
03620 ud->nodes = SyncFreeNodeAccum(ud->nodes);
03621 ud->deltas = FreeDeltas(ud->deltas);
03622 free(ud);
03623 }
03624 return NULL;
03625 }
03626
03627 static int
03628 UpdateAction(struct ccn_schedule *sched,
03629 void *clienth,
03630 struct ccn_scheduled_event *ev,
03631 int flags) {
03632 char *here = "Sync.UpdateAction";
03633 int64_t now = SyncCurrentTime();
03634 struct SyncUpdateData *ud = (struct SyncUpdateData *) ev->evdata;
03635 struct SyncRootStruct *root = ud->root;
03636 struct SyncBaseStruct *base = root->base;
03637 int debug = base->debug;
03638 struct ccnr_handle *ccnr = base->client_handle;
03639 int showEntry = base->priv->syncActionsPrivate & 8;
03640
03641 ud->entryTime = now;
03642
03643 switch (ud->state) {
03644 case SyncUpdate_init: {
03645
03646
03647 if (showEntry && debug >= CCNL_INFO) {
03648 SyncNoteSimple(root, here, "SyncUpdate_init");
03649 }
03650 struct SyncNameAccum *src = (struct SyncNameAccum *) ud->ixBase->client;
03651 IndexSorter_Index srcLen = src->len;
03652 IndexSorter_Index ix = ud->ixPos;
03653 IndexSorter_Index ixLim = ix+namesYieldInc;
03654 if (srcLen < ixLim) ixLim = srcLen;
03655
03656 while (ix < srcLen) {
03657 if (ix > ixLim) {
03658 int64_t dt = SyncDeltaTime(ud->entryTime, SyncCurrentTime());
03659 if (dt >= namesYieldMicros) {
03660
03661 if (debug >= CCNL_FINE)
03662 SyncNoteSimple(root, here, "yield");
03663 break;
03664 }
03665 ixLim += namesYieldInc;
03666 }
03667 if (debug >= CCNL_FINE) {
03668 struct ccn_charbuf *name = src->ents[ix].name;
03669 SyncNoteUri(root, here, "insert", name);
03670 }
03671 IndexSorter_Add(ud->ixBase, ix);
03672 ix++;
03673 }
03674 ud->ixPos = ix;
03675 if (ix < srcLen)
03676
03677 return shortDelayMicros;
03678
03679 struct SyncHashCacheEntry *ent = SyncRootTopEntry(root);
03680 if (ent != NULL && ud->tw == NULL) {
03681 SyncCacheEntryFetch(ent);
03682 ud->tw = SyncTreeWorkerCreate(root->ch, ent, 0);
03683 }
03684 ud->sort = SyncAllocNameAccum(0);
03685 ud->cb = ccn_charbuf_create();
03686 ud->nodes = SyncAllocNodeAccum(0);
03687 ud->state = SyncUpdate_inserted;
03688 }
03689 case SyncUpdate_inserted: {
03690
03691
03692 if (showEntry && debug >= CCNL_INFO) {
03693 SyncNoteSimple(root, here, "SyncUpdate_inserted");
03694 }
03695
03696 int res = SyncTreeMergeNames(ud->tw, ud);
03697 if (res == 0) break;
03698
03699 res = MakeNodeFromNames(ud, 0);
03700
03701
03702 struct SyncNameAccum *src = (struct SyncNameAccum *) ud->ixBase->client;
03703 ud->tw = SyncTreeWorkerFree(ud->tw);
03704 src = SyncFreeNameAccumAndNames(src);
03705 IndexSorter_Free(&ud->ixBase);
03706 ccn_charbuf_destroy(&ud->cb);
03707 if (res < 0) {
03708
03709 ud->deltas = FreeDeltas(ud->deltas);
03710 ud->sort = SyncFreeNameAccumAndNames(ud->sort);
03711 SyncNoteFailed(root, here, "merge names", __LINE__);
03712 return res;
03713 }
03714 ud->state = SyncUpdate_busy;
03715 }
03716 case SyncUpdate_busy: {
03717
03718
03719 if (showEntry && debug >= CCNL_INFO) {
03720 SyncNoteSimple(root, here, "SyncUpdate_busy");
03721 }
03722 int initCount = root->priv->currentSize;
03723 struct SyncHashCacheEntry *ce = nodeFromNodes(root, ud->nodes);
03724 int count = ud->namesAdded;
03725 if (ce == NULL) {
03726 count = SyncNoteFailed(root, here, "bad nodeFromNames()", __LINE__);
03727 } else {
03728 SyncCacheEntryFetch(ce);
03729 struct SyncNodeComposite *nc = ce->ncL;
03730 if (nc != NULL) {
03731 struct ccn_charbuf *old = root->currentHash;
03732 struct ccn_charbuf *hash = SyncLongHashToBuf(&nc->longHash);
03733 char *hex = SyncHexStr(hash->buf, hash->length);
03734 struct SyncHashCacheEntry *cePrev = root->priv->ceCurrent;
03735 struct SyncHashCacheEntry *ce = SyncHashEnter(root->ch,
03736 hash->buf, hash->length,
03737 SyncHashState_local);
03738 root->currentHash = hash;
03739 root->priv->ceCurrent = ce;
03740 root->priv->currentSize = count;
03741 now = SyncCurrentTime();
03742 if (ce != cePrev) {
03743
03744 root->priv->lastHashChange = now;
03745 noteHash(root, ce, 1, 0);
03746 }
03747 ud->ceStop = ce;
03748
03749 struct SyncRootDeltas *deltas = CloseUpdateCoding(ud);
03750 int64_t dt = SyncDeltaTime(ud->startTime, now);
03751 root->priv->stats->updatesDone++;
03752 root->priv->stats->lastUpdateMicros = dt;
03753 dt = (dt + 500) / 1000;
03754 int64_t mh = SyncDeltaTime(ud->entryTime, now);
03755 if (mh < ud->maxHold) mh = ud->maxHold;
03756 mh = (mh + 500) / 1000;
03757 if (debug >= CCNL_INFO) {
03758 int reportStats = base->priv->syncActionsPrivate & 4;
03759 char temp[256];
03760 snprintf(temp, sizeof(temp)-2,
03761 "%d.%03d secs [%d.%03d], %d names, depth %d, hash %s",
03762 (int) (dt / 1000), (int) (dt % 1000),
03763 (int) (mh / 1000), (int) (mh % 1000),
03764 (int) count, (int) nc->treeDepth, hex);
03765 SyncNoteSimple2(root, here, "done", temp);
03766 if (reportStats) {
03767 struct ccn_charbuf *cb = ccn_charbuf_create();
03768 formatStats(root, cb);
03769 char *str = ccn_charbuf_as_string(cb);
03770 ccnr_msg(root->base->client_handle, "%s, %s", here, str);
03771 ccn_charbuf_destroy(&cb);
03772 }
03773 }
03774 struct SyncHashCacheEntry *chk = SyncRootTopEntry(root);
03775 if (chk != ce)
03776 count = SyncNoteFailed(root, here, "bad top entry", __LINE__);
03777 else if (ud->ceStart != ud->ceStop) {
03778
03779
03780 struct SyncHashInfoList *remoteSeen = scanRemoteSeen(root, ud->ceStart);
03781 ccnr_hwm hwm = root->priv->highWater;
03782 ce->stablePoint = hwm;
03783 if (debug >= CCNL_INFO) {
03784 char temp[1024];
03785 if (hwm != CCNR_NULL_HWM) {
03786 snprintf(temp, sizeof(temp),
03787 "new stable point at %ju",
03788 ccnr_hwm_encode(root->base->client_handle, hwm));
03789 } else {
03790 snprintf(temp, sizeof(temp), "high water?");
03791 }
03792 SyncNoteSimple(root, here, temp);
03793 if (showHighLevel) {
03794 int tlim = sizeof(temp)-16;
03795 int pos = snprintf(temp, sizeof(temp),
03796 "done (%d)",
03797 count);
03798 if (deltas != NULL) {
03799 pos += snprintf(temp+pos, tlim-pos,
03800 ", deltas (%d)",
03801 deltas->deltasCount);
03802 }
03803
03804 if (remoteSeen != NULL)
03805 pos += snprintf(temp+pos, tlim-pos, ", seen");
03806
03807 showCacheEntry2(root, "Sync.$Update", temp,
03808 ud->ceStart, ud->ceStop);
03809 }
03810 }
03811 if (deltas != NULL && deltas->whenSent == 0
03812 && remoteSeen != NULL) {
03813
03814
03815
03816
03817 SendDeltasReply(root, deltas);
03818 remoteSeen->lastReplied = now;
03819 } else
03820
03821 SyncSendRootAdviseInterest(root);
03822 }
03823 if (old != NULL) ccn_charbuf_destroy(&old);
03824 free(hex);
03825
03826 ccnr_hwm hwm = root->priv->highWater;
03827 ce->stablePoint = hwm;
03828 if (debug >= CCNL_INFO) {
03829 char temp[64];
03830 if (hwm != CCNR_NULL_HWM) {
03831 snprintf(temp, sizeof(temp),
03832 "new stable point at %ju",
03833 ccnr_hwm_encode(root->base->client_handle, hwm));
03834 } else {
03835 snprintf(temp, sizeof(temp), "high water?");
03836 }
03837 SyncNoteSimple(root, here, temp);
03838 }
03839 } else {
03840 count = SyncNoteFailed(root, here, "bad node", __LINE__);
03841 }
03842 }
03843 root->priv->adviseNeed = adviseNeedReset;
03844 if (count <= initCount) {
03845
03846 if (debug >= CCNL_INFO) {
03847 struct ccn_charbuf *hash = root->currentHash;
03848 char *hex = SyncHexStr(hash->buf, hash->length);
03849 ccnr_msg(ccnr,
03850 "%s, root#%u, note, count %d, initCount %d, hash %s",
03851 here, root->rootId, count, initCount, hex);
03852 free(hex);
03853 }
03854 }
03855 root->update = FreeUpdateData(ud);
03856 ev->evdata = NULL;
03857 kickHeartBeat(root, 0);
03858 return -1;
03859 }
03860 default: {
03861
03862 return -1;
03863 }
03864 }
03865 int64_t edt = SyncDeltaTime(ud->entryTime, SyncCurrentTime());
03866 if (edt > ud->maxHold) ud->maxHold = edt;
03867 return shortDelayMicros;
03868 }
03869
03870
03871
03872 extern int
03873 SyncUpdateRoot(struct SyncRootStruct *root) {
03874 char *here = "Sync.UpdateAction";
03875 struct SyncNameAccum *acc = root->namesToAdd;
03876 if (acc->len == 0) return 0;
03877 int64_t now = SyncCurrentTime();
03878 struct SyncBaseStruct *base = root->base;
03879 struct ccn_charbuf *hash = root->currentHash;
03880 struct ccnr_handle *ccnr = base->client_handle;
03881 struct SyncUpdateData *ud = NEW_STRUCT(1, SyncUpdateData);
03882 ud->root = root;
03883 ud->state = SyncUpdate_init;
03884 ud->startTime = now;
03885 ud->entryTime = now;
03886 ud->ixBase = IndexSorter_New(acc->len, -1);
03887 ud->ixBase->sorter = SyncNameAccumSorter;
03888 ud->ixBase->client = acc;
03889 ud->ixPos = 0;
03890 ud->initLen = root->priv->currentSize;
03891 ud->ceStart = root->priv->ceCurrent;
03892 if (root->base->priv->deltasLimit > 0)
03893
03894 ud->deltas = NewDeltas(root);
03895 struct ccn_scheduled_event *ev = ccn_schedule_event(base->sched,
03896 0,
03897 UpdateAction,
03898 ud,
03899 0);
03900 if (ev == NULL) {
03901 if (base->debug >= CCNL_SEVERE)
03902 ccnr_msg(ccnr, "%s, initial schedule failed!", here);
03903 FreeUpdateData(ud);
03904 return -1;
03905 }
03906 root->priv->lastUpdate = now;
03907 root->update = ud;
03908 root->namesToAdd = SyncAllocNameAccum(0);
03909 if (base->debug >= CCNL_INFO) {
03910 char *hex = SyncHexStr(hash->buf, hash->length);
03911 ccnr_msg(ccnr,
03912 "%s, root#%u, start, toAdd %d, current %d, hash %s",
03913 here, root->rootId,
03914 (int) acc->len, (int) ud->initLen, hex);
03915 free(hex);
03916 }
03917 return 1;
03918 }
03919
03920 extern int
03921 SyncStartCompareAction(struct SyncRootStruct *root, struct ccn_charbuf *hashR) {
03922 char *here = "Sync.SyncStartCompareAction";
03923 struct SyncPrivate *priv = root->base->priv;
03924 if (root->compare != NULL || root->update != NULL
03925 || priv->comparesBusy >= priv->maxComparesBusy)
03926
03927 return 0;
03928
03929 struct ccn_charbuf *hashL = root->currentHash;
03930 struct SyncHashCacheEntry *ceL = root->priv->ceCurrent;
03931 struct SyncNameAccum *remoteDeltas = root->priv->remoteDeltas;
03932 if (remoteDeltas == NULL && hashR == NULL)
03933
03934 return 0;
03935
03936 struct SyncHashCacheEntry *ceR = NULL;
03937 if (hashR != NULL) {
03938 ceR = SyncHashEnter(root->ch,
03939 hashR->buf,
03940 hashR->length,
03941 SyncHashState_remote);
03942 if (ceR == NULL)
03943 return SyncNoteFailed(root, here, "bad lookup for R", __LINE__);
03944 }
03945
03946 int debug = root->base->debug;
03947 struct ccnr_handle *ccnr = root->base->client_handle;
03948 struct SyncCompareData *data = NEW_STRUCT(1, SyncCompareData);
03949 int64_t mark = SyncCurrentTime();
03950 data->startTime = mark;
03951 data->lastEnter = mark;
03952 data->lastMark = mark;
03953 data->lastFetchOK = mark;
03954 data->root = root;
03955 root->compare = data;
03956 root->namesToFetch = SyncFreeNameAccumAndNames(root->namesToFetch);
03957 data->twL = SyncTreeWorkerCreate(root->ch, ceL, 0);
03958 if (ceL != NULL) ceL->lastUsed = mark;
03959 data->twR = SyncTreeWorkerCreate(root->ch, ceR, 1);
03960 if (ceR != NULL) ceR->lastUsed = mark;
03961 data->hashL = ccn_charbuf_create();
03962 ccn_charbuf_append_charbuf(data->hashL, hashL);
03963 if (remoteDeltas == NULL) {
03964
03965 data->state = SyncCompare_init;
03966 data->hashR = ccn_charbuf_create();
03967 ccn_charbuf_append_charbuf(data->hashR, hashR);
03968 } else {
03969
03970 root->namesToFetch = remoteDeltas;
03971 root->priv->remoteDeltas = NULL;
03972 data->state = SyncCompare_waiting;
03973 }
03974
03975 data->cbL = ccn_charbuf_create();
03976 data->cbR = ccn_charbuf_create();
03977
03978 priv->comparesBusy++;
03979
03980 kickCompare(data, NULL);
03981
03982 if (debug >= CCNL_INFO) {
03983 char *hexL = SyncHexStr(hashL->buf, hashL->length);
03984 char *msgL = ((hashL->length > 0) ? hexL : "empty");
03985 if (hashR != NULL && hashR->length > 0) {
03986 char *hexR = SyncHexStr(hashR->buf, hashR->length);
03987 ccnr_msg(ccnr, "%s, root#%u, L %s, R %s",
03988 here, root->rootId, msgL, hexR);
03989 free(hexR);
03990 } else {
03991 ccnr_msg(ccnr, "%s, root#%u, L %s, R empty",
03992 here, root->rootId, msgL);
03993 }
03994 free(hexL);
03995 }
03996
03997 return 1;
03998 }
03999
04000 #undef M