void NetworkSmpiModel::gapAppend(double size, Link* link, NetworkAction *act) { const char *src = link->getName(); xbt_fifo_t fifo; NetworkCm02Action *action= static_cast<NetworkCm02Action*>(act); if (sg_sender_gap > 0.0) { if (!gap_lookup) { gap_lookup = xbt_dict_new_homogeneous(nullptr); } fifo = (xbt_fifo_t) xbt_dict_get_or_null(gap_lookup, src); action->senderGap_ = 0.0; if (fifo && xbt_fifo_size(fifo) > 0) { /* Compute gap from last send */ /*last_action = (surf_action_network_CM02_t) xbt_fifo_get_item_content(xbt_fifo_get_last_item(fifo));*/ // bw = net_get_link_bandwidth(link); action->senderGap_ = sg_sender_gap; /* max(sg_sender_gap,last_action->sender.size / bw);*/ action->latency_ += action->senderGap_; } /* Append action as last send */ /*action->sender.link_name = link->lmm_resource.generic_resource.name; fifo = (xbt_fifo_t) xbt_dict_get_or_null(gap_lookup, action->sender.link_name); if (!fifo) { fifo = xbt_fifo_new(); xbt_dict_set(gap_lookup, action->sender.link_name, fifo, nullptr); } action->sender.fifo_item = xbt_fifo_push(fifo, action);*/ action->senderSize_ = size; } }
void NetworkSmpiModel::gapRemove(Action *lmm_action) { xbt_fifo_t fifo; size_t size; NetworkCm02Action *action = static_cast<NetworkCm02Action*>(lmm_action); if (sg_sender_gap > 0.0 && action->senderLinkName_ && action->senderFifoItem_) { fifo = (xbt_fifo_t) xbt_dict_get_or_null(gap_lookup, action->senderLinkName_); xbt_fifo_remove_item(fifo, action->senderFifoItem_); size = xbt_fifo_size(fifo); if (size == 0) { xbt_fifo_free(fifo); xbt_dict_remove(gap_lookup, action->senderLinkName_); size = xbt_dict_length(gap_lookup); if (size == 0) { xbt_dict_free(&gap_lookup); } } } }
/* * Handle a given task */ static void handle_task(node_t node, msg_task_t task) { XBT_DEBUG("Handling task %p", task); char mailbox[MAILBOX_NAME_SIZE]; int i, j, min, max, d; msg_task_t task_sent; task_data_t req_data; task_data_t task_data = (task_data_t) MSG_task_get_data(task); e_task_type_t type = task_data->type; // If the node is not ready keep the task for later if (node->ready != 0 && !(type==TASK_JOIN_LAST_REPLY || type==TASK_JOIN_REPLY)) { XBT_DEBUG("Task pending %i", type); xbt_fifo_push(node->pending_tasks, task); return; } switch (type) { /* * Try to join the ring */ case TASK_JOIN: { int next = routing_next(node, task_data->answer_id); XBT_DEBUG("Join request from %08x forwarding to %08x", task_data->answer_id, next); type = TASK_JOIN_LAST_REPLY; req_data = xbt_new0(s_task_data_t,1); req_data->answer_id = task_data->sender_id; req_data->steps = task_data->steps + 1; // if next different from current node forward the join if (next!=node->id) { get_mailbox(next, mailbox); task_data->sender_id = node->id; task_data->steps++; task_sent = MSG_task_create(NULL, COMP_SIZE, COMM_SIZE, task_data); MSG_task_send_with_timeout(task_sent, mailbox, timeout); type = TASK_JOIN_REPLY; } // send back the current node state to the joining node req_data->type = type; req_data->sender_id = node->id; get_mailbox(node->id, req_data->answer_to); req_data->state = node_get_state(node); task_sent = MSG_task_create(NULL, COMP_SIZE, COMM_SIZE, req_data); MSG_task_send_with_timeout(task_sent, task_data->answer_to, timeout); break; } /* * Join reply from all the node touched by the join */ case TASK_JOIN_LAST_REPLY: // if last node touched reply, copy its namespace set // TODO: it's work only if the two nodes are side to side (is it really the case ?) j = (task_data->sender_id < node->id) ? -1 : 0; for (i=0; i<NAMESPACE_SIZE/2; i++) { node->namespace_set[i] = task_data->state->namespace_set[i-j]; node->namespace_set[NAMESPACE_SIZE-1-i] = task_data->state->namespace_set[NAMESPACE_SIZE-1-i-j-1]; } node->namespace_set[NAMESPACE_SIZE/2+j] = task_data->sender_id; node->ready += task_data->steps + 1; case TASK_JOIN_REPLY: XBT_DEBUG("Joining Reply"); // if first node touched reply, copy its neighborood set if (task_data->sender_id == node->known_id) { node->neighborhood_set[0] = task_data->sender_id; for (i=1; i<NEIGHBORHOOD_SIZE; i++) node->neighborhood_set[i] = task_data->state->neighborhood_set[i-1]; } // copy the corresponding routing table levels min = (node->id==task_data->answer_id) ? 0 : shl(node->id, task_data->answer_id); max = shl(node->id, task_data->sender_id)+1; for (i=min;i<max;i++) { d = domain(node->id, i); for (j=0; j<LEVEL_SIZE; j++) if (d!=j) node->routing_table[i][j] = task_data->state->routing_table[i][j]; } node->ready--; // if the node is ready, do all the pending tasks and send update to known nodes if (node->ready==0) { XBT_DEBUG("Node %i is ready!!!", node->id); while(xbt_fifo_size(node->pending_tasks)) handle_task(node, xbt_fifo_pop(node->pending_tasks)); for (i=0; i<NAMESPACE_SIZE; i++) { j = node->namespace_set[i]; if (j!=-1) { XBT_DEBUG("Send update to %i", j); get_mailbox(j, mailbox); req_data = xbt_new0(s_task_data_t,1); req_data->answer_id = node->id; req_data->steps = 0; req_data->type = TASK_UPDATE; req_data->sender_id = node->id; get_mailbox(node->id, req_data->answer_to); req_data->state = node_get_state(node); task_sent = MSG_task_create(NULL, COMP_SIZE, COMM_SIZE, req_data); MSG_task_send_with_timeout(task_sent, mailbox, timeout); } } } break; /* * Recieved an update of state */ case TASK_UPDATE: XBT_DEBUG("Task update %i !!!", node->id); /* Update namespace ses */ printf("Task update from %i !!!\n", task_data->sender_id); print_node_id(node); print_node_namespace_set(node); int curr_namespace_set[NAMESPACE_SIZE]; int task_namespace_set[NAMESPACE_SIZE+1]; // Copy the current namedspace // and the task state namespace with state->id in the middle i=0; for (; i<NAMESPACE_SIZE/2; i++){ curr_namespace_set[i] = node->namespace_set[i]; task_namespace_set[i] = task_data->state->namespace_set[i]; } task_namespace_set[i] = task_data->state->id; for (; i<NAMESPACE_SIZE; i++){ curr_namespace_set[i] = node->namespace_set[i]; task_namespace_set[i+1] = task_data->state->namespace_set[i]; } // get the index of values before and after node->id in task_namespace min = -1; max = -1; for (i=0; i<=NAMESPACE_SIZE; i++) { j = task_namespace_set[i]; if (i<NAMESPACE_SIZE) printf("%08x %08x | ", j, curr_namespace_set[i]); if (j != -1 && j < node->id) min = i; if (j != -1 && max == -1 && j > node->id) max = i; } printf("\n"); // add lower elements j = NAMESPACE_SIZE/2-1; for (i=NAMESPACE_SIZE/2-1; i>=0; i--) { printf("i:%i, j:%i, min:%i, currj:%08x, taskmin:%08x\n", i, j, min, curr_namespace_set[j], task_namespace_set[min]); if (min<0) { node->namespace_set[i] = curr_namespace_set[j]; j--; } else if (curr_namespace_set[j] == task_namespace_set[min]) { node->namespace_set[i] = curr_namespace_set[j]; j--; min--; } else if (curr_namespace_set[j] > task_namespace_set[min]) { node->namespace_set[i] = curr_namespace_set[j]; j--; } else { node->namespace_set[i] = task_namespace_set[min]; min--; } } // add greater elements j = NAMESPACE_SIZE/2; for (i=NAMESPACE_SIZE/2; i<NAMESPACE_SIZE; i++) { printf("i:%i, j:%i, max:%i, currj:%08x, taskmax:%08x\n", i, j, max, curr_namespace_set[j], task_namespace_set[max]); if (min<0 || max>=NAMESPACE_SIZE) { node->namespace_set[i] = curr_namespace_set[j]; j++; } else if (curr_namespace_set[j] == -1) { node->namespace_set[i] = task_namespace_set[max]; max++; } else if (curr_namespace_set[j] == task_namespace_set[max]) { node->namespace_set[i] = curr_namespace_set[j]; j++; max++; } else if (curr_namespace_set[j] < task_namespace_set[max]) { node->namespace_set[i] = curr_namespace_set[j]; j++; } else { node->namespace_set[i] = task_namespace_set[max]; max++; } } print_node_namespace_set(node); /* Update routing table */ for (i=shl(node->id, task_data->state->id); i<LEVELS_COUNT; i++) { for (j=0; j<LEVEL_SIZE; j++) { if (node->routing_table[i][j]==-1 && task_data->state->routing_table[i][j]==-1) node->routing_table[i][j] = task_data->state->routing_table[i][j]; } } } }