int ccnl_nfn_thunk_already_computing(struct ccnl_relay_s *ccnl, struct ccnl_prefix_s *prefix) { int i = 0; struct ccnl_prefix_s *copy; DEBUGMSG(TRACE, "ccnl_nfn_thunk_already_computing()\n"); copy = ccnl_prefix_dup(prefix); // ccnl_nfn_remove_thunk_from_prefix(copy); ccnl_nfnprefix_set(copy, CCNL_PREFIX_NFN | CCNL_PREFIX_THUNK); for (i = 0; i < -ccnl->km->configid; ++i) { struct configuration_s *config; config = ccnl_nfn_findConfig(ccnl->km->configuration_list, -i); if (!config) continue; if (!ccnl_prefix_cmp(config->prefix, NULL, copy, CMP_EXACT)) { free_prefix(copy); return 1; } } free_prefix(copy); return 0; }
struct ccnl_interest_s* ccnl_nfn_RX_request(struct ccnl_relay_s *ccnl, struct ccnl_face_s *from, struct ccnl_pkt_s **pkt) { struct ccnl_interest_s *i; if (!ccnl_nfnprefix_isNFN((*pkt)->pfx) || ccnl->km->numOfRunningComputations >= NFN_MAX_RUNNING_COMPUTATIONS) return NULL; i = ccnl_interest_new(ccnl, from, pkt); if (!i) return NULL; i->flags &= ~CCNL_PIT_COREPROPAGATES; // do not forward interests for running computations ccnl_interest_append_pending(i, from); // if (!(i->flags & CCNL_PIT_COREPROPAGATES)) ccnl_nfn(ccnl, ccnl_prefix_dup(i->pkt->pfx), from, NULL, i, i->pkt->suite, 0); TRACEOUT(); return i; }
struct ccnl_interest_s* ccnl_nfn_RX_request(struct ccnl_relay_s *ccnl, struct ccnl_face_s *from, int suite, struct ccnl_buf_s **buf, struct ccnl_prefix_s **p, int minsfx, int maxsfx) { struct ccnl_interest_s *i; struct ccnl_prefix_s *p2; if (ccnl->km->numOfRunningComputations >= NFN_MAX_RUNNING_COMPUTATIONS) return 0; p2 = ccnl_prefix_dup(*p); i = ccnl_interest_new(ccnl, from, (*p)->suite, buf, p, minsfx, maxsfx); i->flags &= ~CCNL_PIT_COREPROPAGATES; // do not forward interests for running computations ccnl_interest_append_pending(i, from); if (!(i->flags & CCNL_PIT_COREPROPAGATES)) ccnl_nfn(ccnl, p2, from, NULL, i, suite, 0); else { free_prefix(p2); } return i; }
char* op_builtin_find(struct ccnl_relay_s *ccnl, struct configuration_s *config, int *restart, int *halt, char *prog, char *pending, struct stack_s **stack) { int local_search = 0; struct stack_s *h; char *cp = NULL; struct ccnl_prefix_s *prefix; struct ccnl_content_s *c = NULL; if (*restart) { DEBUGMSG(DEBUG, "---to do: OP_FIND restart\n"); *restart = 0; local_search = 1; } else { DEBUGMSG(DEBUG, "---to do: OP_FIND <%s> <%s>\n", prog+7, pending); h = pop_from_stack(&config->result_stack); // if (h->type != STACK_TYPE_PREFIX) ... config->fox_state->num_of_params = 1; config->fox_state->params = ccnl_malloc(sizeof(struct ccnl_stack_s *)); config->fox_state->params[0] = h; config->fox_state->it_routable_param = 0; } prefix = config->fox_state->params[0]->content; //check if result is now available //loop by reentering (with local_search) after timeout of the interest... DEBUGMSG(DEBUG, "FIND: Checking if result was received\n"); c = ccnl_nfn_local_content_search(ccnl, config, prefix); if (!c) { struct ccnl_prefix_s *copy; struct ccnl_interest_s *interest; if (local_search) { DEBUGMSG(INFO, "FIND: no content\n"); return NULL; } //Result not in cache, search over the network // struct ccnl_interest_s *interest = mkInterestObject(ccnl, config, prefix); copy = ccnl_prefix_dup(prefix); interest = ccnl_nfn_query2interest(ccnl, ©, config); DEBUGMSG(DEBUG, "FIND: sending new interest from Face ID: %d\n", interest->from->faceid); if (interest) ccnl_interest_propagate(ccnl, interest); //wait for content, return current program to continue later *halt = -1; //set halt to -1 for async computations return ccnl_strdup(prog); } DEBUGMSG(INFO, "FIND: result was found ---> handle it (%s), prog=%s, pending=%s\n", ccnl_prefix_to_path(prefix), prog, pending); #ifdef USE_NACK /* if (!strncmp((char*)c->content, ":NACK", 5)) { DEBUGMSG(DEBUG, "NACK RECEIVED, going to next parameter\n"); ++config->fox_state->it_routable_param; return prog ? ccnl_strdup(prog) : NULL; } */ #endif prefix = ccnl_prefix_dup(prefix); push_to_stack(&config->result_stack, prefix, STACK_TYPE_PREFIX); if (pending) { DEBUGMSG(DEBUG, "Pending: %s\n", pending); cp = ccnl_strdup(pending); } return cp; }
int ccnl_nfn(struct ccnl_relay_s *ccnl, // struct ccnl_buf_s *orig, struct ccnl_prefix_s *prefix, struct ccnl_face_s *from, struct configuration_s *config, struct ccnl_interest_s *interest, int suite, int start_locally) { int num_of_required_thunks = 0; int thunk_request = 0; struct ccnl_buf_s *res = NULL; char str[CCNL_MAX_PACKET_SIZE]; int i, len = 0; DEBUGMSG(TRACE, "ccnl_nfn(%p, %s, %p, config=%p)\n", (void*)ccnl, ccnl_prefix_to_path(prefix), (void*)from, (void*)config); // prefix = ccnl_prefix_dup(prefix); DEBUGMSG(DEBUG, "Namecomps: %s \n", ccnl_prefix_to_path(prefix)); if (config){ suite = config->suite; thunk_request = config->fox_state->thunk_request; goto restart; //do not do parsing thunks again } from->flags = CCNL_FACE_FLAGS_STATIC; if (ccnl_nfn_thunk_already_computing(ccnl, prefix)) { DEBUGMSG(DEBUG, "Computation for this interest is already running\n"); return -1; } if (ccnl_nfnprefix_isTHUNK(prefix)) thunk_request = 1; // Checks first if the interest has a routing hint and then searches for it locally. // If it exisits, the computation is started locally, otherwise it is directly forwarded without entering the AM. // Without this mechanism, there will be situations where several nodes "overtake" a computation // applying the same strategy and, potentially, all executing it locally (after trying all arguments). // TODO: this is not an elegant solution and should be improved on, because the clients cannot send a // computation with a routing hint on which the network applies a strategy if the routable name // does not exist (because each node will just forward it without ever taking it into an abstract machine). // encoding the routing hint more explicitely as well as additonal information (e.g. already tried names) // could solve the problem. More generally speaking, additional state describing the exact situation will be required. if (interest && interest->prefix->compcnt > 1) { // forward interests with outsourced components struct ccnl_prefix_s *copy = ccnl_prefix_dup(prefix); copy->compcnt -= (1 + thunk_request); DEBUGMSG(DEBUG, " checking local available of %s\n", ccnl_prefix_to_path(copy)); ccnl_nfnprefix_clear(copy, CCNL_PREFIX_NFN | CCNL_PREFIX_THUNK); if (!ccnl_nfn_local_content_search(ccnl, NULL, copy)) { free_prefix(copy); ccnl_interest_propagate(ccnl, interest); return 0; } free_prefix(copy); start_locally = 1; } //put packet together #ifdef USE_SUITE_CCNTLV if (prefix->suite == CCNL_SUITE_CCNTLV) { len = prefix->complen[prefix->compcnt-1] - 4; memcpy(str, prefix->comp[prefix->compcnt-1] + 4, len); str[len] = '\0'; } else #endif { len = prefix->complen[prefix->compcnt-1]; memcpy(str, prefix->comp[prefix->compcnt-1], len); str[len] = '\0'; } if (prefix->compcnt > 1) len += sprintf(str + len, " "); for (i = 0; i < prefix->compcnt-1; i++) { #ifdef USE_SUITE_CCNTLV if (prefix->suite == CCNL_SUITE_CCNTLV) len += sprintf(str+len,"/%.*s",prefix->complen[i]-4,prefix->comp[i]+4); else #endif len += sprintf(str+len,"/%.*s",prefix->complen[i],prefix->comp[i]); } DEBUGMSG(DEBUG, "expr is <%s>\n", str); //search for result here... if found return... if (thunk_request) num_of_required_thunks = ccnl_nfn_count_required_thunks(str); ++ccnl->km->numOfRunningComputations; restart: res = Krivine_reduction(ccnl, str, thunk_request, start_locally, num_of_required_thunks, &config, prefix, suite); //stores result if computed if (res) { struct ccnl_prefix_s *copy; struct ccnl_content_s *c; DEBUGMSG(INFO,"Computation finished: res: %.*s size: %d bytes. Running computations: %d\n", res->datalen, res->data, res->datalen, ccnl->km->numOfRunningComputations); if (config && config->fox_state->thunk_request) { // ccnl_nfn_remove_thunk_from_prefix(config->prefix); ccnl_nfnprefix_clear(config->prefix, CCNL_PREFIX_THUNK); } copy = ccnl_prefix_dup(config->prefix); c = ccnl_nfn_result2content(ccnl, ©, res->data, res->datalen); c->flags = CCNL_CONTENT_FLAGS_STATIC; set_propagate_of_interests_to_1(ccnl, c->name); ccnl_content_serve_pending(ccnl,c); ccnl_content_add2cache(ccnl, c); --ccnl->km->numOfRunningComputations; DBL_LINKED_LIST_REMOVE(ccnl->km->configuration_list, config); ccnl_nfn_freeConfiguration(config); ccnl_free(res); } #ifdef USE_NACK else if(config->local_done){ struct ccnl_content_s *nack; nack = ccnl_nfn_result2content(ccnl, &config->prefix, (unsigned char*)":NACK", 5); ccnl_content_serve_pending(ccnl, nack); } #endif return 0; }
char* ZAM_fox(struct ccnl_relay_s *ccnl, struct configuration_s *config, int *restart, int *halt, char *prog, char *arg, char *contd) { int local_search = 0, i; int parameter_number = 0; struct ccnl_content_s *c = NULL; struct ccnl_prefix_s *pref; struct ccnl_interest_s *interest; DEBUGMSG(DEBUG, "---to do: FOX <%s>\n", arg); ccnl_free(arg); if (*restart) { *restart = 0; local_search = 1; goto recontinue; } { struct stack_s *h; h = pop_or_resolve_from_result_stack(ccnl, config); assert(h); //TODO CHECK IF INT config->fox_state->num_of_params = *(int*)h->content; h->next = NULL; ccnl_nfn_freeStack(h); } DEBUGMSG(DEBUG, "NUM OF PARAMS: %d\n", config->fox_state->num_of_params); config->fox_state->params = ccnl_malloc(sizeof(struct ccnl_stack_s *) * config->fox_state->num_of_params); for (i = 0; i < config->fox_state->num_of_params; ++i) { //pop parameter from stack config->fox_state->params[i] = pop_from_stack(&config->result_stack); switch (config->fox_state->params[i]->type) { case STACK_TYPE_INT: DEBUGMSG(DEBUG, " info: Parameter %d %d\n", i, *(int *)config->fox_state->params[i]->content); break; case STACK_TYPE_PREFIX: DEBUGMSG(DEBUG, " info: Parameter %d %s\n", i, ccnl_prefix_to_path((struct ccnl_prefix_s*) config->fox_state->params[i]->content)); break; default: break; } } //as long as there is a routable parameter: try to find a result config->fox_state->it_routable_param = 0; //check if last result is now available recontinue: //loop by reentering after timeout of the interest... if (local_search) { DEBUGMSG(DEBUG, "Checking if result was received\n"); parameter_number = choose_parameter(config); pref = create_namecomps(ccnl, config, parameter_number, config->fox_state->params[parameter_number]->content); // search for a result c = ccnl_nfn_local_content_search(ccnl, config, pref); set_propagate_of_interests_to_1(ccnl, pref); free_prefix(pref); //TODO Check? //TODO remove interest here? if (c) { DEBUGMSG(DEBUG, "Result was found\n"); DEBUGMSG_CFWD(INFO, "data after result was found %.*s\n", c->pkt->contlen, c->pkt->content); goto handlecontent; } } //result was not delivered --> choose next parameter ++config->fox_state->it_routable_param; parameter_number = choose_parameter(config); if (parameter_number < 0) //no more parameter --> no result found, can try a local computation goto local_compute; // create new prefix with name components!!!! pref = create_namecomps(ccnl, config, parameter_number, config->fox_state->params[parameter_number]->content); c = ccnl_nfn_local_content_search(ccnl, config, pref); if (c) { free_prefix(pref); goto handlecontent; } // Result not in cache, search over the network // pref2 = ccnl_prefix_dup(pref); interest = ccnl_nfn_query2interest(ccnl, &pref, config); if (pref) free_prefix(pref); if (interest) { ccnl_interest_propagate(ccnl, interest); DEBUGMSG(DEBUG, " new interest's face is %d\n", interest->from->faceid); } // wait for content, return current program to continue later *halt = -1; //set halt to -1 for async computations return ccnl_strdup(prog); local_compute: if (config->local_done) return NULL; config->local_done = 1; pref = ccnl_nfnprefix_mkComputePrefix(config, config->suite); DEBUGMSG(DEBUG, "Prefix local computation: %s\n", ccnl_prefix_to_path(pref)); interest = ccnl_nfn_query2interest(ccnl, &pref, config); if (pref) free_prefix(pref); if (interest) ccnl_interest_propagate(ccnl, interest); handlecontent: //if result was found ---> handle it if (c) { #ifdef USE_NACK if (!strncmp((char*)c->pkt->content, ":NACK", 5)) { DEBUGMSG(DEBUG, "NACK RECEIVED, going to next parameter\n"); ++config->fox_state->it_routable_param; return prog ? ccnl_strdup(prog) : NULL; } #endif int isANumber = 1, i = 0; for(i = 0; i < c->pkt->contlen; ++i){ if(!isdigit(c->pkt->content[i])){ isANumber = 0; break; } } if (isANumber){ int *integer = ccnl_malloc(sizeof(int)); *integer = strtol((char*)c->pkt->content, 0, 0); push_to_stack(&config->result_stack, integer, STACK_TYPE_INT); } else { struct prefix_mapping_s *mapping; struct ccnl_prefix_s *name = create_prefix_for_content_on_result_stack(ccnl, config); push_to_stack(&config->result_stack, name, STACK_TYPE_PREFIX); mapping = ccnl_malloc(sizeof(struct prefix_mapping_s)); mapping->key = ccnl_prefix_dup(name); //TODO COPY mapping->value = ccnl_prefix_dup(c->pkt->pfx); DBL_LINKED_LIST_ADD(config->fox_state->prefix_mapping, mapping); DEBUGMSG(DEBUG, "Created a mapping %s - %s\n", ccnl_prefix_to_path(mapping->key), ccnl_prefix_to_path(mapping->value)); } } DEBUGMSG(DEBUG, " FOX continuation: %s\n", contd); return ccnl_strdup(contd); }
int ccnl_extractDataAndChunkInfo(unsigned char **data, int *datalen, int suite, struct ccnl_prefix_s **prefix, unsigned int *lastchunknum, unsigned char **content, int *contentlen) { struct ccnl_pkt_s *pkt = NULL; switch (suite) { #ifdef USE_SUITE_CCNTLV case CCNL_SUITE_CCNTLV: { int hdrlen; unsigned char *start = *data; if (ccntlv_isData(*data, *datalen) < 0) { DEBUGMSG(WARNING, "Received non-content-object\n"); return -1; } hdrlen = ccnl_ccntlv_getHdrLen(*data, *datalen); if (hdrlen < 0) return -1; *data += hdrlen; *datalen -= hdrlen; pkt = ccnl_ccntlv_bytes2pkt(start, data, datalen); break; } #endif #ifdef USE_SUITE_CISTLV case CCNL_SUITE_CISTLV: { int hdrlen; unsigned char *start = *data; if (cistlv_isData(*data, *datalen) < 0) { DEBUGMSG(WARNING, "Received non-content-object\n"); return -1; } hdrlen = ccnl_cistlv_getHdrLen(*data, *datalen); if (hdrlen < 0) return -1; *data += hdrlen; *datalen -= hdrlen; pkt = ccnl_cistlv_bytes2pkt(start, data, datalen); break; } #endif #ifdef USE_SUITE_NDNTLV case CCNL_SUITE_NDNTLV: { unsigned int typ, len; unsigned char *start = *data; if (ccnl_ndntlv_dehead(data, datalen, &typ, &len)) { DEBUGMSG(WARNING, "could not dehead\n"); return -1; } if (typ != NDN_TLV_Data) { DEBUGMSG(WARNING, "received non-content-object packet with type %d\n", typ); return -1; } pkt = ccnl_ndntlv_bytes2pkt(typ, start, data, datalen); break; } #endif default: DEBUGMSG(WARNING, "extractDataAndChunkInfo: suite %d not implemented\n", suite); return -1; } if (!pkt) { DEBUGMSG(WARNING, "extract(%s): parsing error or no prefix\n", ccnl_suite2str(suite)); return -1; } *prefix = ccnl_prefix_dup(pkt->pfx); *lastchunknum = pkt->val.final_block_id; *content = pkt->content; *contentlen = pkt->contlen; free_packet(pkt); return 0; }