00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <stddef.h>
00024 #include <stdint.h>
00025 #include <stdlib.h>
00026 #include <string.h>
00027 #include <time.h>
00028 #include <unistd.h>
00029 #include <sys/types.h>
00030
00031 #include <ccn/btree.h>
00032 #include <ccn/btree_content.h>
00033 #include <ccn/ccn.h>
00034 #include <ccn/charbuf.h>
00035 #include <ccn/indexbuf.h>
00036 #include <ccn/schedule.h>
00037
00038 #include <sync/SyncBase.h>
00039
00040 #include "ccnr_private.h"
00041
00042 #include "ccnr_dispatch.h"
00043 #include "ccnr_io.h"
00044 #include "ccnr_link.h"
00045 #include "ccnr_msg.h"
00046 #include "ccnr_proto.h"
00047 #include "ccnr_store.h"
00048 #include "ccnr_sync.h"
00049 #include "ccnr_util.h"
00050
00051 #ifndef CCNLINT
00052
00053
00054
00055 PUBLIC uintmax_t
00056 ccnr_accession_encode(struct ccnr_handle *ccnr, ccnr_accession a)
00057 {
00058 return(a);
00059 }
00060
00061 PUBLIC ccnr_accession
00062 ccnr_accession_decode(struct ccnr_handle *ccnr, uintmax_t encoded)
00063 {
00064 return(encoded);
00065 }
00066
00067 PUBLIC int
00068 ccnr_accession_compare(struct ccnr_handle *ccnr, ccnr_accession x, ccnr_accession y)
00069 {
00070 if (x > y) return 1;
00071 if (x == y) return 0;
00072 if (x < y) return -1;
00073 return CCNR_NOT_COMPARABLE;
00074 }
00075
00076 PUBLIC uintmax_t
00077 ccnr_hwm_encode(struct ccnr_handle *ccnr, ccnr_hwm hwm)
00078 {
00079 return(hwm);
00080 }
00081
00082 PUBLIC ccnr_hwm
00083 ccnr_hwm_decode(struct ccnr_handle *ccnr, uintmax_t encoded)
00084 {
00085 return(encoded);
00086 }
00087
00088 PUBLIC int
00089 ccnr_acc_in_hwm(struct ccnr_handle *ccnr, ccnr_accession a, ccnr_hwm hwm)
00090 {
00091 return(a <= hwm);
00092 }
00093
00094 PUBLIC ccnr_hwm
00095 ccnr_hwm_update(struct ccnr_handle *ccnr, ccnr_hwm hwm, ccnr_accession a)
00096 {
00097 return(a <= hwm ? hwm : a);
00098 }
00099
00100 PUBLIC ccnr_hwm
00101 ccnr_hwm_merge(struct ccnr_handle *ccnr, ccnr_hwm x, ccnr_hwm y)
00102 {
00103 return(x < y ? y : x);
00104 }
00105
00106 PUBLIC int
00107 ccnr_hwm_compare(struct ccnr_handle *ccnr, ccnr_hwm x, ccnr_hwm y)
00108 {
00109 if (x > y) return 1;
00110 if (x == y) return 0;
00111 if (x < y) return -1;
00112 return CCNR_NOT_COMPARABLE;
00113 }
00114 #endif
00115
00116 PUBLIC void
00117 r_sync_notify_after(struct ccnr_handle *ccnr, ccnr_hwm item)
00118 {
00119
00120
00121
00122 ccnr->notify_after = (ccnr_accession) item;
00123 }
00124
00125
00126
00127
00128 PUBLIC int
00129 r_sync_notify_content(struct ccnr_handle *ccnr, int e, struct content_entry *content)
00130 {
00131 int res;
00132 ccnr_accession acc = CCNR_NULL_ACCESSION;
00133
00134 if (content == NULL) {
00135 res = SyncNotifyContent(ccnr->sync_handle, e, CCNR_NULL_ACCESSION, NULL);
00136 if (res != -1)
00137 ccnr_msg(ccnr, "SyncNotifyContent returned %d, expected -1",
00138 e, res);
00139 }
00140 else {
00141 struct ccn_charbuf *cb = r_util_charbuf_obtain(ccnr);
00142
00143 acc = r_store_content_accession(ccnr, content);
00144 if (acc == CCNR_NULL_ACCESSION) {
00145 ccnr_debug_content(ccnr, __LINE__, "r_sync_notify_content - not yet stable", NULL, content);
00146 return(0);
00147 }
00148
00149 ccn_name_init(cb);
00150 res = r_store_name_append_components(cb, ccnr, content, 0, -1);
00151 if (res < 0) abort();
00152 if (CCNSHOULDLOG(ccnr, r_sync_notify_content, CCNL_FINEST))
00153 ccnr_debug_content(ccnr, __LINE__, "r_sync_notify_content", NULL, content);
00154 res = SyncNotifyContent(ccnr->sync_handle, e, acc, cb);
00155 r_util_charbuf_release(ccnr, cb);
00156 }
00157 if (CCNSHOULDLOG(ccnr, r_sync_notify_content, CCNL_FINEST))
00158 ccnr_msg(ccnr, "SyncNotifyContent(..., %d, 0x%jx, ...) returned %d",
00159 e, ccnr_accession_encode(ccnr, acc), res);
00160 if (e == 0 && res == -1)
00161 r_sync_notify_after(ccnr, CCNR_MAX_ACCESSION);
00162 return(res);
00163 }
00164
00165
00166
00167
00168 struct sync_enumeration_state {
00169 int magic;
00170 int index;
00171 ccnr_cookie cookie;
00172 struct ccn_parsed_interest parsed_interest;
00173 struct ccn_charbuf *interest;
00174 struct ccn_indexbuf *comps;
00175 };
00176 static const int se_cookie = __LINE__;
00177
00178 static struct sync_enumeration_state *
00179 cleanup_se(struct ccnr_handle *ccnr, struct sync_enumeration_state *md)
00180 {
00181 if (md != NULL && md->magic == se_cookie) {
00182 int i = md->index;
00183 if (CCNSHOULDLOG(ccnr, cleanup_se, CCNL_FINEST))
00184 ccnr_msg(ccnr, "sync_enum_cleanup %d", i);
00185 if (0 < i && i < CCNR_MAX_ENUM)
00186 ccnr->active_enum[i] = CCNR_NULL_ACCESSION;
00187 ccn_indexbuf_destroy(&md->comps);
00188 ccn_charbuf_destroy(&md->interest);
00189 free(md);
00190 }
00191 return(NULL);
00192 }
00193
00194 static int
00195 r_sync_enumerate_action(struct ccn_schedule *sched,
00196 void *clienth,
00197 struct ccn_scheduled_event *ev,
00198 int flags)
00199 {
00200 struct ccnr_handle *ccnr = clienth;
00201 struct sync_enumeration_state *md = NULL;
00202 struct content_entry *content = NULL;
00203 struct ccn_btree_node *leaf = NULL;
00204 struct ccn_charbuf *interest = NULL;
00205 struct ccn_indexbuf *comps = NULL;
00206 struct ccn_parsed_interest *pi = NULL;
00207 struct ccn_charbuf *scratch = NULL;
00208 struct ccn_charbuf *flat = NULL;
00209 int ndx;
00210 int res;
00211 int try;
00212 int matches;
00213
00214 md = ev->evdata;
00215 if (md->magic != se_cookie || md->index >= CCNR_MAX_ENUM) abort();
00216 if ((flags & CCN_SCHEDULE_CANCEL) != 0) {
00217 ev->evdata = cleanup_se(ccnr, md);
00218 return(0);
00219 }
00220 pi = &md->parsed_interest;
00221 interest = md->interest;
00222 comps = md->comps;
00223
00224
00225
00226
00227
00228
00229
00230 content = r_store_content_from_cookie(ccnr, md->cookie);
00231 if (content == NULL && md->cookie != 0)
00232 content = r_store_content_from_accession(ccnr, ccnr->active_enum[md->index]);
00233 for (try = 0, matches = 0; content != NULL; try++) {
00234 if (scratch == NULL)
00235 scratch = ccn_charbuf_create();
00236 flat = r_store_content_flatname(ccnr, content);
00237 res = ccn_btree_lookup(ccnr->btree, flat->buf, flat->length, &leaf);
00238 if (CCN_BT_SRCH_FOUND(res) == 0) {
00239 ccnr_debug_content(ccnr, __LINE__, "impossible", NULL, content);
00240 break;
00241 }
00242 ndx = CCN_BT_SRCH_INDEX(res);
00243 res = ccn_btree_match_interest(leaf, ndx, interest->buf, pi, scratch);
00244 if (res == -1) {
00245 ccnr_debug_content(ccnr, __LINE__, "impossible", NULL, content);
00246 break;
00247 }
00248 if (res == 1) {
00249 res = r_sync_notify_content(ccnr, md->index, content);
00250 matches++;
00251 if (res == -1) {
00252 if (CCNSHOULDLOG(ccnr, r_sync_enumerate_action, CCNL_FINEST))
00253 ccnr_debug_content(ccnr, __LINE__, "r_sync_enumerate_action", NULL,
00254 content);
00255 ev->evdata = cleanup_se(ccnr, md);
00256 ccn_charbuf_destroy(&scratch);
00257 return(0);
00258 }
00259 }
00260 content = r_store_content_next(ccnr, content);
00261 if (content != NULL &&
00262 !r_store_content_matches_interest_prefix(ccnr, content,
00263 interest->buf,
00264 interest->length))
00265 content = NULL;
00266 if (content != NULL) {
00267 md->cookie = r_store_content_cookie(ccnr, content);
00268 ccnr->active_enum[md->index] = r_store_content_accession(ccnr, content);
00269 if (ccnr->active_enum[md->index] != CCNR_NULL_ACCESSION &&
00270 (matches >= 8 || try >= 200)) {
00271 ccn_charbuf_destroy(&scratch);
00272 return(300);
00273 }
00274 }
00275 }
00276 r_sync_notify_content(ccnr, md->index, NULL);
00277 ev->evdata = cleanup_se(ccnr, md);
00278 ccn_charbuf_destroy(&scratch);
00279 return(0);
00280 }
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297 PUBLIC int
00298 r_sync_enumerate(struct ccnr_handle *ccnr,
00299 struct ccn_charbuf *interest)
00300 {
00301 int ans = -1;
00302 int i;
00303 int res;
00304 struct ccn_indexbuf *comps = NULL;
00305 struct ccn_parsed_interest parsed_interest = {0};
00306 struct ccn_parsed_interest *pi = &parsed_interest;
00307 struct content_entry *content = NULL;
00308 struct sync_enumeration_state *md = NULL;
00309
00310 if (CCNSHOULDLOG(ccnr, r_sync_enumerate, CCNL_FINEST))
00311 ccnr_debug_ccnb(ccnr, __LINE__, "sync_enum_start", NULL,
00312 interest->buf, interest->length);
00313 comps = ccn_indexbuf_create();
00314 res = ccn_parse_interest(interest->buf, interest->length, pi, comps);
00315 if (res < 0) {
00316 ccnr_debug_ccnb(ccnr, __LINE__, "bogus r_sync_enumerate request", NULL,
00317 interest->buf, interest->length);
00318 if (CCNSHOULDLOG(ccnr, r_sync_enumerate, CCNL_FINEST)) {
00319 struct ccn_charbuf *temp = ccn_charbuf_create();
00320 ccn_charbuf_putf(temp, "interest_dump ");
00321 for (i = 0; i < interest->length; i++)
00322 ccn_charbuf_putf(temp, "%02X", interest->buf[i]);
00323 ccnr_msg(ccnr, ccn_charbuf_as_string(temp));
00324 ccn_charbuf_destroy(&temp);
00325 }
00326 goto Bail;
00327 }
00328
00329 for (i = 1; i < CCNR_MAX_ENUM; i++) {
00330 if (ccnr->active_enum[i] == CCNR_NULL_ACCESSION) {
00331 ans = i;
00332 ccnr->active_enum[ans] = CCNR_MAX_ACCESSION;
00333 break;
00334 }
00335 }
00336 if (ans < 0) {
00337 if (CCNSHOULDLOG(ccnr, r_sync_enumerate, CCNL_WARNING))
00338 ccnr_msg(ccnr, "sync_enum - Too many active enumerations!", ans);
00339 goto Bail;
00340 }
00341 content = r_store_find_first_match_candidate(ccnr, interest->buf, pi);
00342 if (content == NULL) {
00343 if (CCNSHOULDLOG(ccnr, r_sync_enumerate, CCNL_FINE))
00344 ccnr_debug_ccnb(ccnr, __LINE__, "sync_enum_nomatch", NULL,
00345 interest->buf, interest->length);
00346 }
00347 else if (r_store_content_matches_interest_prefix(ccnr,
00348 content, interest->buf, interest->length)) {
00349 ccnr->active_enum[ans] = r_store_content_accession(ccnr, content);
00350 if (CCNSHOULDLOG(ccnr, r_sync_enumerate, CCNL_FINEST))
00351 ccnr_msg(ccnr, "sync_enum id=%d starting accession=0x%jx",
00352 ans, ccnr_accession_encode(ccnr, ccnr->active_enum[ans]));
00353 }
00354
00355
00356 md = calloc(1, sizeof(*md));
00357 if (md == NULL) { ccnr->active_enum[ans] = CCNR_NULL_ACCESSION; ans = -1; goto Bail; }
00358 md->magic = se_cookie;
00359 md->cookie = content == NULL ? 0 : r_store_content_cookie(ccnr, content);
00360 md->index = ans;
00361 md->interest = ccn_charbuf_create();
00362 if (md->interest == NULL) goto Bail;
00363 ccn_charbuf_append(md->interest, interest->buf, interest->length);
00364 md->parsed_interest = parsed_interest;
00365 md->comps = comps;
00366 comps = NULL;
00367
00368
00369
00370 if (NULL != ccn_schedule_event(ccnr->sched, 123, r_sync_enumerate_action, md, 0))
00371 md = NULL;
00372
00373 Bail:
00374 if (md != NULL) {
00375 ans = -1;
00376 md = cleanup_se(ccnr, md);
00377 }
00378 ccn_indexbuf_destroy(&comps);
00379 if (CCNSHOULDLOG(ccnr, r_sync_enumerate, CCNL_FINEST))
00380 ccnr_msg(ccnr, "sync_enum %d", ans);
00381 return(ans);
00382 }
00383
00384 PUBLIC int
00385 r_sync_lookup(struct ccnr_handle *ccnr,
00386 struct ccn_charbuf *interest,
00387 struct ccn_charbuf *content_ccnb)
00388 {
00389 int ans = -1;
00390 struct ccn_indexbuf *comps = r_util_indexbuf_obtain(ccnr);
00391 struct ccn_parsed_interest parsed_interest = {0};
00392 struct ccn_parsed_interest *pi = &parsed_interest;
00393 struct content_entry *content = NULL;
00394
00395 if (NULL == comps || (ccn_parse_interest(interest->buf, interest->length, pi, comps) < 0))
00396 abort();
00397 content = r_store_lookup(ccnr, interest->buf, pi, comps);
00398 if (content != NULL) {
00399 ans = 0;
00400 if (content_ccnb != NULL) {
00401 ccn_charbuf_append(content_ccnb,
00402 r_store_content_base(ccnr, content),
00403 r_store_content_size(ccnr, content));
00404 }
00405 }
00406 r_util_indexbuf_release(ccnr, comps);
00407
00408 return(ans);
00409 }
00410
00411
00412
00413
00414
00415 PUBLIC enum ccn_upcall_res
00416 r_sync_upcall_store(struct ccnr_handle *ccnr,
00417 enum ccn_upcall_kind kind,
00418 struct ccn_upcall_info *info)
00419 {
00420 enum ccn_upcall_res ans = CCN_UPCALL_RESULT_OK;
00421 const unsigned char *ccnb = NULL;
00422 size_t ccnb_size = 0;
00423 struct content_entry *content;
00424
00425 if (kind != CCN_UPCALL_CONTENT)
00426 return(CCN_UPCALL_RESULT_ERR);
00427
00428 ccnb = info->content_ccnb;
00429 ccnb_size = info->pco->offset[CCN_PCO_E];
00430
00431 content = process_incoming_content(ccnr, r_io_fdholder_from_fd(ccnr, ccn_get_connection_fd(info->h)),
00432 (void *)ccnb, ccnb_size);
00433 if (content == NULL) {
00434 ccnr_msg(ccnr, "r_sync_upcall_store: failed to process incoming content");
00435 return(CCN_UPCALL_RESULT_ERR);
00436 }
00437
00438 if ((r_store_content_flags(content) & CCN_CONTENT_ENTRY_STABLE) == 0) {
00439 r_store_commit_content(ccnr, content);
00440 if (CCNSHOULDLOG(ccnr, r_sync_upcall_store, CCNL_FINE))
00441 ccnr_debug_content(ccnr, __LINE__, "content_stored",
00442 r_io_fdholder_from_fd(ccnr, ccnr->active_out_fd),
00443 content);
00444 }
00445 r_proto_initiate_key_fetch(ccnr, ccnb, info->pco, 0,
00446 r_store_content_cookie(ccnr, content));
00447
00448 return(ans);
00449 }
00450
00451
00452
00453
00454
00455
00456
00457 PUBLIC int
00458 r_sync_local_store(struct ccnr_handle *ccnr,
00459 struct ccn_charbuf *content_cb)
00460 {
00461 struct content_entry *content = NULL;
00462
00463
00464 content = process_incoming_content(ccnr, ccnr->face0,
00465 (void *)content_cb->buf, content_cb->length);
00466 if (content == NULL) {
00467 ccnr_msg(ccnr, "r_sync_local_store: failed to process content");
00468 return(-1);
00469 }
00470
00471
00472 if ((r_store_content_flags(content) & CCN_CONTENT_ENTRY_STABLE) == 0) {
00473 r_store_commit_content(ccnr, content);
00474 if (CCNSHOULDLOG(ccnr, r_sync_local_store, CCNL_FINE))
00475 ccnr_debug_content(ccnr, __LINE__, "content_stored_local",
00476 r_io_fdholder_from_fd(ccnr, ccnr->active_out_fd),
00477 content);
00478 }
00479 return(0);
00480 }