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); }