static PyObject *qd_python_send(PyObject *self, PyObject *args) { qd_error_clear(); IoAdapter *ioa = (IoAdapter*) self; qd_composed_field_t *field = 0; PyObject *message = 0; int no_echo = 1; int control = 0; if (!PyArg_ParseTuple(args, "O|ii", &message, &no_echo, &control)) return 0; if (compose_python_message(&field, message, ioa->qd) == QD_ERROR_NONE) { qd_message_t *msg = qd_message(); qd_message_compose_2(msg, field); qd_composed_field_t *ingress = qd_compose_subfield(0); qd_compose_insert_string(ingress, qd_router_id(ioa->qd)); qd_composed_field_t *trace = qd_compose_subfield(0); qd_compose_start_list(trace); qd_compose_insert_string(trace, qd_router_id(ioa->qd)); qd_compose_end_list(trace); qd_message_set_ingress_annotation(msg, ingress); qd_message_set_trace_annotation(msg, trace); PyObject *address = PyObject_GetAttrString(message, "address"); if (address) { qdr_send_to2(ioa->core, msg, PyString_AsString(address), (bool) no_echo, (bool) control); Py_DECREF(address); } qd_compose_free(field); qd_message_free(msg); Py_RETURN_NONE; } if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError, qd_error_message()); return 0; }
static qd_iterator_t *router_annotate_message(qd_router_t *router, qd_parsed_field_t *in_ma, qd_message_t *msg, qd_bitmask_t **link_exclusions, bool strip_inbound_annotations) { qd_iterator_t *ingress_iter = 0; qd_parsed_field_t *trace = 0; qd_parsed_field_t *ingress = 0; qd_parsed_field_t *to = 0; qd_parsed_field_t *phase = 0; *link_exclusions = 0; if (in_ma && !strip_inbound_annotations) { uint32_t count = qd_parse_sub_count(in_ma); bool done = false; for (uint32_t idx = 0; idx < count && !done; idx++) { qd_parsed_field_t *sub = qd_parse_sub_key(in_ma, idx); if (!sub) continue; qd_iterator_t *iter = qd_parse_raw(sub); if (!iter) continue; if (qd_iterator_equal(iter, (unsigned char*) QD_MA_TRACE)) { trace = qd_parse_sub_value(in_ma, idx); } else if (qd_iterator_equal(iter, (unsigned char*) QD_MA_INGRESS)) { ingress = qd_parse_sub_value(in_ma, idx); } else if (qd_iterator_equal(iter, (unsigned char*) QD_MA_TO)) { to = qd_parse_sub_value(in_ma, idx); } else if (qd_iterator_equal(iter, (unsigned char*) QD_MA_PHASE)) { phase = qd_parse_sub_value(in_ma, idx); } done = trace && ingress && to && phase; } } // // QD_MA_TRACE: // If there is a trace field, append this router's ID to the trace. // If the router ID is already in the trace the msg has looped. // qd_composed_field_t *trace_field = qd_compose_subfield(0); qd_compose_start_list(trace_field); if (trace) { if (qd_parse_is_list(trace)) { // // Create a link-exclusion map for the items in the trace. This map will // contain a one-bit for each link that leads to a neighbor router that // the message has already passed through. // *link_exclusions = qd_tracemask_create(router->tracemask, trace); // // Append this router's ID to the trace. // uint32_t idx = 0; qd_parsed_field_t *trace_item = qd_parse_sub_value(trace, idx); while (trace_item) { qd_iterator_t *iter = qd_parse_raw(trace_item); qd_iterator_reset_view(iter, ITER_VIEW_ALL); qd_compose_insert_string_iterator(trace_field, iter); idx++; trace_item = qd_parse_sub_value(trace, idx); } } } qd_compose_insert_string(trace_field, node_id); qd_compose_end_list(trace_field); qd_message_set_trace_annotation(msg, trace_field); // // QD_MA_TO: // Preserve the existing value. // if (to) { qd_composed_field_t *to_field = qd_compose_subfield(0); qd_compose_insert_string_iterator(to_field, qd_parse_raw(to)); qd_message_set_to_override_annotation(msg, to_field); } // // QD_MA_PHASE: // Preserve the existing value. // if (phase) { int phase_val = qd_parse_as_int(phase); qd_message_set_phase_annotation(msg, phase_val); } // // QD_MA_INGRESS: // If there is no ingress field, annotate the ingress as // this router else keep the original field. // qd_composed_field_t *ingress_field = qd_compose_subfield(0); if (ingress && qd_parse_is_scalar(ingress)) { ingress_iter = qd_parse_raw(ingress); qd_compose_insert_string_iterator(ingress_field, ingress_iter); } else qd_compose_insert_string(ingress_field, node_id); qd_message_set_ingress_annotation(msg, ingress_field); // // Return the iterator to the ingress field _if_ it was present. // If we added the ingress, return NULL. // return ingress_iter; }