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