void print_node_list(struct dr_node *first_node) { struct dr_node *parent; struct dr_node *child; parent = first_node; say(DEBUG, "\nDR nodes list\n==============\n"); while (parent) { say(DEBUG, "%s: %s\n" "\tdrc index: 0x%x description: %s\n" "\tdrc name: %s\n\tloc code: %s\n", parent->ofdt_path, (parent->skip ? "(SKIP)" : ""), parent->drc_index, node_type(parent), parent->drc_name, parent->loc_code); child = parent->children; while (child) { say(DEBUG, "%s: %s\n" "\tdrc index: 0x%x description: %s\n" "\tdrc name: %s\n\tloc code: %s\n", child->ofdt_path, (child->skip ? "(SKIP)" : ""), child->drc_index, node_type(child), child->drc_name, child->loc_code); child = child->next; } parent = parent->next; } say(DEBUG, "\n"); }
/* daemon-specific node manipulation */ static void post_process_nodes(void) { uint i, x; ldebug("post processing %d masters, %d pollers, %d peers", num_masters, num_pollers, num_peers); for (i = 0; i < num_nodes; i++) { merlin_node *node = node_table[i]; if (!node) { lerr("node is null. i is %d. num_nodes is %d. wtf?", i, num_nodes); continue; } if (!node->sain.sin_port) node->sain.sin_port = htons(default_port); node->action = node_action_handler; node->ioc = iocache_create(MERLIN_IOC_BUFSIZE); if (node->ioc == NULL) { lerr("Failed to malloc(%i) for io cache for node %s. Aborting", MERLIN_IOC_BUFSIZE, node->name); } /* * this lets us support multiple merlin instances on * a single system, but all instances on the same * system will be marked at the same time, so we skip * them on the second pass here. */ if (node->flags & MERLIN_NODE_FIXED_SRCPORT) { continue; } if (node->sain.sin_addr.s_addr == htonl(INADDR_LOOPBACK)) { node->flags |= MERLIN_NODE_FIXED_SRCPORT; ldebug("Using fixed source-port for local %s node %s", node_type(node), node->name); continue; } for (x = i + 1; x < num_nodes; x++) { merlin_node *nx = node_table[x]; if (node->sain.sin_addr.s_addr == nx->sain.sin_addr.s_addr) { ldebug("Using fixed source-port for %s node %s", node_type(node), node->name); ldebug("Using fixed source-port for %s node %s", node_type(nx), nx->name); node->flags |= MERLIN_NODE_FIXED_SRCPORT; nx->flags |= MERLIN_NODE_FIXED_SRCPORT; if (node->sain.sin_port == nx->sain.sin_port) { lwarn("Nodes %s and %s have same ip *and* same port. Voodoo?", node->name, nx->name); } } } } }
/* * Accept an inbound connection from a remote host * Returns 0 on success and -1 on errors */ static int net_accept_one(int sd, int events, void *discard) { int sock, result; merlin_node *node; struct sockaddr_in sain; socklen_t slen = sizeof(struct sockaddr_in); sock = accept(sd, (struct sockaddr *)&sain, &slen); if (sock < 0) { lerr("accept() failed: %s", strerror(errno)); return -1; } node = find_node(&sain); linfo("NODESTATE: %s connected from %s:%d. Current state is %s", node ? node->name : "An unregistered node", inet_ntoa(sain.sin_addr), ntohs(sain.sin_port), node ? node_state_name(node->state) : "unknown"); if (!node) { close(sock); return 0; } switch (node->state) { case STATE_NEGOTIATING: case STATE_CONNECTED: case STATE_PENDING: /* if node->sock >= 0, we must negotiate which one to use */ if (node->sock >= 0) { int sel_sd = net_negotiate_socket(node, node->sock, sock); if (sel_sd != sock) { close(sock); } } break; case STATE_NONE: /* * we must close it unconditionally or we'll leak fd's * for reconnecting nodes that were previously connected */ node_disconnect(node, "fd leak prevention for connecting nodes"); node->sock = sock; break; default: lerr("%s %s has an unknown status", node_type(node), node->name); break; } node_set_state(node, STATE_NEGOTIATING, "Inbound connection accepted. Negotiating protocol version"); result = iobroker_register(nagios_iobs, node->sock, node, net_input); if (result < 0) { lerr("IOB: Failed to register %d for %s node %s for input events: %s", node->sock, node_type(node), node->name, iobroker_strerror(result)); } return sock; }
static eval_err_t do_splitsym(memory_state_t *ms, node_t **args, node_t **out, void *p) { char *start, *end; node_t *sym; (void) p; sym = args[0]; if(node_type(sym) != NODE_SYMBOL) { *out = sym; return eval_err(EVAL_ERR_EXPECTED_SYMBOL); } start = node_symbol_name(sym); end = start + strlen(start) - 1; // end points to last nonzero char /* construct value list backwards */ for(*out = NULL; end >= start; end--) { *out = node_cons_new(ms, node_value_new(ms, *end), *out); } return EVAL_OK; }
/* * Reads input from a particular node and ships it off to * the "handle_event()" */ int net_input(int sd, int io_evt, void *node_) { merlin_event *pkt; merlin_node *node = (merlin_node *)node_; int len, events = 0; errno = 0; ldebug("NETINPUT from %p (%s)", node, node ? node->name : "oops"); len = node_recv(node); if (len < 0) { return 0; } node->stats.bytes.read += len; node->last_recv = time(NULL); while ((pkt = node_get_event(node))) { events++; handle_event(node, pkt); free(pkt); } ldebug("Read %d events in %s from %s node %s", events, human_bytes(len), node_type(node), node->name); return events; }
static eval_err_t do_mathop(memory_state_t *ms, node_t **args, node_t **out, void *p) { mathop_t fn = (mathop_t) p; if(node_type(args[0]) != NODE_VALUE) { *out = args[0]; return eval_err(EVAL_ERR_EXPECTED_VALUE); } if(node_type(args[1]) != NODE_VALUE) { *out = args[1]; return eval_err(EVAL_ERR_EXPECTED_VALUE); } fn(ms, node_value(args[0]), node_value(args[1]), out); return EVAL_OK; }
/* * Accept an inbound connection from a remote host * Returns 0 on success and -1 on errors */ int net_accept_one(void) { int sock; merlin_node *node; struct sockaddr_in sain; socklen_t slen = sizeof(struct sockaddr_in); /* * we get called from polling_loop(). If so, check for readability * to see if anyone has connected and, if not, return early */ if (!io_read_ok(net_sock, 0)) return -1; sock = accept(net_sock, (struct sockaddr *)&sain, &slen); if (sock < 0) { lerr("accept() failed: %s", strerror(errno)); return -1; } node = find_node(&sain, NULL); linfo("%s connected from %s:%d. Current state is %s", node ? node->name : "An unregistered node", inet_ntoa(sain.sin_addr), ntohs(sain.sin_port), node ? node_state_name(node->state) : "unknown"); if (!node) { close(sock); return 0; } switch (node->state) { case STATE_NEGOTIATING: /* this should *NEVER EVER* happen */ lerr("Aieee! Negotiating connection with one attempting inbound. Bad Thing(tm)"); /* fallthrough */ case STATE_CONNECTED: case STATE_PENDING: /* if node->sock >= 0, we must negotiate which one to use */ node->sock = net_negotiate_socket(node, sock); break; case STATE_NONE: /* * we must close it unconditionally or we'll leak fd's * for reconnecting nodes that were previously connected */ node_disconnect(node, "fd leak prevention for connecting nodes"); node->sock = sock; break; default: lerr("%s %s has an unknown status", node_type(node), node->name); break; } node_set_state(node, STATE_CONNECTED, "Inbound connection accepted or negotiated"); return sock; }
// // print() functions // void Formula::print(FILE *output_file) { if(myChildren.empty()) { if(node_type()==Op_Relation || node_type()==Op_Or) fprintf(output_file, "FALSE"); else if(node_type()==Op_And) fprintf(output_file, "TRUE"); else { assert(0); } } for(List_Iterator<Formula*> c(myChildren); c;) { if (node_type() == Op_Exists || node_type() == Op_Forall || (*c)->priority() < priority()) fprintf(output_file, "( "); (*c)->print(output_file); if (node_type() == Op_Exists || node_type() == Op_Forall || (*c)->priority() < priority()) fprintf(output_file, " )"); c++; if(c.live()) print_separator(output_file); } }
/** * insert_print_node * * Insert the node into the list of nodes. The list is * sorted by location codes. * * @param node dlpar node to add */ void insert_print_node(struct dr_node *node) { struct print_node *pnode; pnode = zalloc(sizeof(*pnode)); if (pnode == NULL) { fprintf(stderr, "Could not allocate print node for drc %x\n", node->drc_index); return; } pnode->node = node; pnode->desc = node_type(node); pnode->next = NULL; max_sname = MAX(max_sname, strlen(node->drc_name)); max_desc = MAX(max_desc, strlen(pnode->desc)); /* Insert the new print_node into the sorted list of print nodes */ if (print_list == NULL) { print_list = pnode; return; } if (loc_code_cmp(print_list->node->drc_name, pnode->node->drc_name) > 0) { /* The location code for the new node is less than that * of the first node so insert the new node at the front. */ pnode->next = print_list; print_list = pnode; } else { /* Find the first node in the list where the new node's * location code is less than the existing node's location * code and insert the new node before that node. */ struct print_node *last; last = print_list; while (last->next != NULL) { if (loc_code_cmp(last->next->node->drc_name, pnode->node->drc_name) > 0) { pnode->next = last->next; last->next = pnode; break; } last = last->next; } /* Put the new node at the end of the list if itslocation * code is not less than any other node's location code. */ if (last->next == NULL) last->next = pnode; } }
constant_type_t local_type(node_t*node, int num, model_t*m) { node_t*setlocal = node_find_setlocal(node, num); if(!setlocal) { fprintf(stderr, "Couldn't find assignment of variable %d\n", num); return CONSTANT_MISSING; } return node_type(setlocal, m); }
/* * Read as much data as we possibly can from the node so * that whatever parsing code there is can handle it later. * All information the caller needs will reside in the * nodes own merlin_iocache function, and we return the * number of bytes read, or -1 on errors. * The io-cache buffer must be allocated before we get * to this point, and if the caller wants to poll the * socket for input, it'll have to do so itself. */ int node_recv(merlin_node *node) { int bytes_read; iocache *ioc = node->ioc; if (!node || node->sock < 0) { return -1; } bytes_read = iocache_read(ioc, node->sock); /* * If we read something, update the stat counter * and return. The caller will have to handle the * input as it sees fit */ if (bytes_read > 0) { node->last_action = node->last_recv = time(NULL); node->stats.bytes.read += bytes_read; return bytes_read; } /* no real error, but no new data, so return 0 */ if (errno == EAGAIN || errno == EWOULDBLOCK) { ldebug("No input available from %s node %s.", node_type(node), node->name); return 0; } /* * Remote endpoint shut down, or we ran into some random error * we can't handle any other way than disconnecting the node and * letting the write machinery attempt to reconnect later */ if (bytes_read < 0) { lerr("Failed to read from socket %d into %p for %s node %s: %s", node->sock, ioc, node_type(node), node->name, strerror(errno)); } /* zero-read. We've been disconnected for some reason */ ldebug("bytes_read: %d; errno: %d; strerror(%d): %s", bytes_read, errno, errno, strerror(errno)); node_disconnect(node, "recv() failed"); return -1; }
static eval_err_t do_symeq_p(memory_state_t *ms, node_t **args, node_t **out, void *p) { (void) p; if(node_type(args[0]) != NODE_SYMBOL) { *out = args[0]; return eval_err(EVAL_ERR_EXPECTED_SYMBOL); } if(node_type(args[1]) != NODE_SYMBOL) { *out = args[1]; return eval_err(EVAL_ERR_EXPECTED_SYMBOL); } *out = NULL; if(strcmp(node_symbol_name(args[0]), node_symbol_name(args[1]))) { *out = node_value_new(ms, 1); } return EVAL_OK; }
static void fill_locals(node_t*node, model_t*m, constant_type_t*types) { if(node->type == &node_setlocal) { types[node->value.i] = node_type(node->child[0], m); } int t; for(t=0;t<node->num_children;t++) { fill_locals(node->child[t], m, types); } }
static eval_err_t do_car(memory_state_t *ms, node_t **in, node_t **out, void *p) { (void) p; if(node_type(in[0]) != NODE_CONS) { *out = in[0]; return eval_err(EVAL_ERR_EXPECTED_CONS); } *out = node_cons_car(in[0]); return EVAL_OK; }
static eval_err_t cons_matchfn(memory_state_t *ms, node_t **in, node_t **out, void *p) { (void) p; if(node_type(in[0]) == NODE_SYMBOL) { *out = node_value_new(ms, 1); } else { *out = NULL; } return EVAL_OK; }
/* * creates the node-table, with fanout indices at the various * different types of nodes. This allows us to iterate over * all the nodes or a particular subset of them using the same * table, which is quite handy. */ static void create_node_tree(merlin_node *table, unsigned n) { uint i, xnoc, xpeer, xpoll; for (i = 0; i < n; i++) { merlin_node *node = &table[i]; switch (node->type) { case MODE_NOC: num_masters++; break; case MODE_POLLER: num_pollers++; break; case MODE_PEER: num_peers++; break; } } /* * Sort nodes by type. This way, we can keep them all linear * while each has its own table base pointer and still not waste * much memory. Pretty nifty, really. */ node_table = calloc(num_nodes, sizeof(merlin_node *)); noc_table = node_table; peer_table = &node_table[num_masters]; poller_table = &node_table[num_masters + num_peers]; xnoc = xpeer = xpoll = 0; for (i = 0; i < n; i++) { merlin_node *node = &table[i]; switch (node->type) { case MODE_NOC: node->id = xnoc; noc_table[xnoc++] = node; break; case MODE_PEER: node->id = num_masters + xpeer; peer_table[xpeer++] = node; break; case MODE_POLLER: node->id = num_masters + num_peers + xpoll; poller_table[xpoll++] = node; break; } if(is_module) asprintf(&node->source_name, "Merlin %s %s", node_type(node), node->name); } }
void c_write_header(model_t*model, state_t*s) { node_t*root = (node_t*)model->code; if(node_has_child(root, &node_arg_max)) { c_write_function_arg_min_or_max(s, "max", "", "double", ">"); } if(node_has_child(root, &node_arg_max_i)) { c_write_function_arg_min_or_max(s, "max", "_i", "int", ">"); } if(node_has_child(root, &node_arg_min)) { c_write_function_arg_min_or_max(s, "min", "", "double", "<"); } if(node_has_child(root, &node_arg_min_i)) { c_write_function_arg_min_or_max(s, "min", "_i", "int", "<"); } if(node_has_child(root, &node_array_arg_max_i)) { c_write_function_array_arg_max_i(s); } if(node_has_child(root, &node_sqr)) { c_write_function_sqr(s); } if(node_has_child(root, &node_sort_float_array_asc)) { c_write_function_compare_float_ptr(s); } constant_type_t type = node_type(root, model); strf(s, "%s predict(", c_type_name(type)); int t; for(t=0;t<model->sig->num_inputs;t++) { if(t) strf(s, ", "); if(s->model->sig->has_column_names) { strf(s, "%s %s", c_type_name(model_param_type(s->model,t)), s->model->sig->column_names[t]); } else { strf(s, "%s p%d", c_type_name(model_param_type(s->model,t)), t); } } strf(s, ")\n"); strf(s, "{\n"); indent(s); int num_locals = 0; constant_type_t*types = node_local_types(root, s->model, &num_locals); for(t=0;t<num_locals;t++) { if(types[t] != CONSTANT_MISSING) { strf(s, "%s v%d;\n", c_type_name(types[t]), t); } } c_enumerate_arrays(root, s); }
void c_write_node_equals(node_t*n, state_t*s) { constant_type_t type = node_type(n->child[0], s->model); if(type==CONSTANT_STRING) { strf(s, "!strcmp("); write_node(s, n->child[0]); strf(s, ","); write_node(s, n->child[1]); strf(s, ")"); } else { write_node(s, n->child[0]); strf(s, " == "); write_node(s, n->child[1]); } }
void print_node_list(struct dr_node *first_node) { struct dr_node *parent; struct dr_node *child; /* Short-circuit printing nodes if not requested. */ if (output_level < EXTRA_DEBUG) return; parent = first_node; say(EXTRA_DEBUG, "\nDR nodes list\n==============\n"); while (parent) { say(EXTRA_DEBUG, "%s: %s\n" "\tdrc index: 0x%x description: %s\n" "\tdrc name: %s\n\tloc code: %s\n", parent->ofdt_path, (parent->skip ? "(SKIP)" : ""), parent->drc_index, node_type(parent), parent->drc_name, parent->loc_code); child = parent->children; while (child) { say(EXTRA_DEBUG, "%s: %s\n" "\tdrc index: 0x%x description: %s\n" "\tdrc name: %s\n\tloc code: %s\n", child->ofdt_path, (child->skip ? "(SKIP)" : ""), child->drc_index, node_type(child), child->drc_name, child->loc_code); child = child->next; } parent = parent->next; } say(EXTRA_DEBUG, "\n"); }
static eval_err_t do_makesym(memory_state_t *ms, node_t **args, node_t **out, void *p) { char name[MAX_SYM_LEN], *cursor;; node_t *val, *val_iter; (void) p; val = args[0]; if(node_type(val) != NODE_CONS) { *out = val; return eval_err(EVAL_ERR_EXPECTED_CONS); } val_iter = val; cursor = name; for(val_iter = val; val_iter; val_iter = node_cons_cdr(val_iter)) { val = node_cons_car(val_iter); if(node_type(val) != NODE_VALUE) { *out = val; return eval_err(EVAL_ERR_EXPECTED_VALUE); } if(node_value(val) > 255 ) { *out = val; return eval_err(EVAL_ERR_VALUE_BOUNDS); } *cursor++ = node_value(val); if(cursor - &(name[0]) >= (ssize_t) sizeof(name)) { break; } val_iter = node_cons_cdr(val_iter); } *cursor = 0; *out = node_symbol_new(ms, name); return EVAL_OK; }
static eval_err_t func_matchfn(memory_state_t *ms, node_t **in, node_t **out, void *p) { nodetype_t type = node_type(in[0]); (void) p; if(type == NODE_LAMBDA || type == NODE_FOREIGN || type == NODE_CONTINUATION || type == NODE_SPECIAL_FUNC) { *out = node_value_new(ms, 1); } else { *out = NULL; } return EVAL_OK; }
EXPORT int reg_to_mach_diff_reconfigure( O_CURVE **newc, O_CURVE **oldc, NODE *oldn) { int i; debug_print("mach_diff","Entering reg_to_mach_diff_reconfigure()\n"); if (debugging("mach_diff")) { (void) printf("WARNING in diffraction_node_propagate(), " "bifurcation from regular diffraction " "to mach difraction.\n"); } if (newc[5]->orient == POSITIVE_ORIENTATION) { start_status(oldc[5]->curve) = INCIDENT; start_status(newc[5]->curve) = INCIDENT; } else { end_status(oldc[5]->curve) = INCIDENT; end_status(newc[5]->curve) = INCIDENT; } if (newc[0]->orient == POSITIVE_ORIENTATION) { start_status(oldc[0]->curve) = TRANSMITTED; start_status(newc[0]->curve) = TRANSMITTED; } else { end_status(oldc[0]->curve) = TRANSMITTED; end_status(newc[0]->curve) = TRANSMITTED; } /* untrack any reflected waves */ for (i = 1; i < 4; i++) if (newc[i]->curve != NULL) untracked_hyper_surf(newc[i]->curve) = YES; node_type(oldn) = TRANSMISSION_NODE; debug_print("mach_diff","Leaving reg_to_mach_diff_reconfigure()\n"); return REPEAT_TIME_STEP_NODE; } /*end reg_to_mach_diff_reconfigure*/
/* * Reads input from a particular node and ships it off to * the "handle_network_event()" routine up above */ static int net_input(merlin_node *node) { merlin_event *pkt; int len, events = 0; errno = 0; len = node_recv(node); if (len < 0) { return 0; } node->stats.bytes.read += len; node->last_recv = time(NULL); while ((pkt = node_get_event(node))) { events++; handle_network_event(node, pkt); } ldebug("Read %d events in %s from %s node %s", events, human_bytes(len), node_type(node), node->name); return events; }
/* * Initiate a connection attempt to a node and mark it as PENDING. * Note that since we're using sockets in non-blocking mode (in order * to be able to effectively multiplex), the connection attempt will * never be completed in this function */ int net_try_connect(merlin_node *node) { int sockopt = 1; struct sockaddr *sa = (struct sockaddr *)&node->sain; int connected = 0, should_log = 0; struct timeval connect_timeout = { MERLIN_CONNECT_TIMEOUT, 0 }; struct sockaddr_in sain; time_t interval = MERLIN_CONNECT_INTERVAL; /* don't log obsessively */ if (node->last_conn_attempt_logged + 30 <= time(NULL)) { should_log = 1; node->last_conn_attempt_logged = time(NULL); } if (!(node->flags & MERLIN_NODE_CONNECT)) { if (should_log) { linfo("Connect attempt blocked by config to %s node %s", node_type(node), node->name); } return 0; } /* if it's not yet time to connect, don't even try it */ if (node->last_conn_attempt + interval > time(NULL)) { ldebug("connect to %s blocked for %lu more seconds", node->name, node->last_conn_attempt + interval - time(NULL)); return 0; } /* mark the time so we can time it out ourselves if need be */ node->last_conn_attempt = time(NULL); /* create the socket if necessary */ if (node->sock < 0) { node_disconnect(node, "struct reset (no real disconnect)"); node->sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (node->sock < 0) { lerr("Failed to obtain socket for node %s: %s", node->name, strerror(errno)); lerr("Aborting connection attempt to %s", node->name); return -1; } } /* * don't try to connect to a node if an attempt is already pending, * but do check if the connection has completed successfully */ if (node->state == STATE_PENDING || node->state == STATE_CONNECTED) { if (net_is_connected(node)) node_set_state(node, STATE_CONNECTED, "Attempted connect completed"); return 0; } sa->sa_family = AF_INET; if (should_log) { linfo("Connecting to %s %s@%s:%d", node_type(node), node->name, inet_ntoa(node->sain.sin_addr), ntohs(node->sain.sin_port)); } (void)setsockopt(node->sock, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(int)); if (node->flags & MERLIN_NODE_FIXED_SRCPORT) { ldebug("Using fixed source port for %s node %s", node_type(node), node->name); /* * first we bind() to a local port calculated by our own * listening port + the target port. */ sain.sin_family = AF_INET; sain.sin_port = htons(net_source_port(node)); sain.sin_addr.s_addr = 0; if (bind(node->sock, (struct sockaddr *)&sain, sizeof(sain))) { lerr("Failed to bind() outgoing socket for node %s to port %d: %s", node->name, ntohs(sain.sin_port), strerror(errno)); } } if (fcntl(node->sock, F_SETFL, O_NONBLOCK) < 0) { lwarn("Failed to set socket for %s non-blocking: %s", node->name, strerror(errno)); } if (setsockopt(node->sock, SOL_SOCKET, SO_RCVTIMEO, &connect_timeout, sizeof(connect_timeout)) < 0) { ldebug("Failed to set receive timeout for node %s: %s", node->name, strerror(errno)); } if (setsockopt(node->sock, SOL_SOCKET, SO_SNDTIMEO, &connect_timeout, sizeof(connect_timeout)) < 0) { ldebug("Failed to set send timeout for node %s: %s", node->name, strerror(errno)); } if (connect(node->sock, sa, sizeof(struct sockaddr_in)) < 0) { if (errno == EINPROGRESS || errno == EALREADY) { node_set_state(node, STATE_PENDING, "connect() already in progress"); } else if (errno == EISCONN) { connected = 1; } else { if (should_log) { node_disconnect(node, "connect() failed to %s node '%s' (%s:%d): %s", node_type(node), node->name, inet_ntoa(node->sain.sin_addr), ntohs(node->sain.sin_port), strerror(errno)); } else { node_disconnect(node, NULL); } return -1; } } if (connected || net_is_connected(node)) { linfo("Successfully connected to %s %s@%s:%d", node_type(node), node->name, inet_ntoa(node->sain.sin_addr), ntohs(node->sain.sin_port)); node_set_state(node, STATE_CONNECTED, "connect() successful"); } else { if (should_log) { linfo("Connection pending to %s %s@%s:%d", node_type(node), node->name, inet_ntoa(node->sain.sin_addr), ntohs(node->sain.sin_port)); } node_set_state(node, STATE_PENDING, "connect() in progress"); } return 0; }
constant_type_t node_type(node_t*n, model_t*m) { switch(node_get_opcode(n)) { case opcode_node_arg_max: case opcode_node_arg_max_i: case opcode_node_array_arg_max_i: case opcode_node_inc_array_at_pos: case opcode_node_int: case opcode_node_inclocal: return CONSTANT_INT; case opcode_node_nop: case opcode_node_debug_print: case opcode_node_missing: case opcode_node_for_local_from_n_to_m: case opcode_node_sort_float_array_asc: return CONSTANT_MISSING; case opcode_node_in: case opcode_node_not: case opcode_node_lt: case opcode_node_lte: case opcode_node_gt: case opcode_node_gte: case opcode_node_bool: case opcode_node_equals: return CONSTANT_BOOL; case opcode_node_bool_to_float: case opcode_node_float: case opcode_node_term_frequency: return CONSTANT_FLOAT; case opcode_node_category: return CONSTANT_CATEGORY; case opcode_node_int_array: return CONSTANT_INT_ARRAY; case opcode_node_category_array: return CONSTANT_CATEGORY_ARRAY; case opcode_node_float_array: return CONSTANT_FLOAT_ARRAY; case opcode_node_string_array: return CONSTANT_STRING_ARRAY; case opcode_node_mixed_array: return CONSTANT_MIXED_ARRAY; case opcode_node_zero_int_array: return CONSTANT_INT_ARRAY; case opcode_node_zero_float_array: return CONSTANT_FLOAT_ARRAY; case opcode_node_string: return CONSTANT_STRING; case opcode_node_constant: return n->value.type; case opcode_node_return: /* strictly speaking, this node doesn't have a "type" at all (since it causes evaluation to terminate), but in order to make node_type(root) do the right thing, we treat it as if it would cascade its value up the tree */ return node_type(n->child[0],m); case opcode_node_brackets: case opcode_node_sqr: case opcode_node_abs: case opcode_node_neg: case opcode_node_exp: case opcode_node_add: case opcode_node_sub: case opcode_node_mul: case opcode_node_div: case opcode_node_setlocal: return node_type(n->child[0],m); case opcode_node_block: return node_type(n->child[n->num_children-1],m); case opcode_node_if: return node_type(n->child[1],m); case opcode_node_set_array_at_pos: return node_type(n->child[2],m); case opcode_node_array_at_pos: return node_array_element_type(n->child[0]); case opcode_node_param: return model_param_type(m, n->value.i); case opcode_node_getlocal: return local_type(node_find_root(n), n->value.i, m); default: fprintf(stderr, "Couldn't do type deduction for ast node %s\n", n->type->name); return CONSTANT_MISSING; } }
/* * Negotiate which socket to use for communication when the remote * host has accepted a connection attempt from us while we have * accepted one from the remote host. We must make sure both ends * agree on one socket to use. */ static int net_negotiate_socket(merlin_node *node, int con, int lis) { struct sockaddr_in lissain, consain; socklen_t slen = sizeof(struct sockaddr_in); linfo("negotiate: Choosing socket for %s %s (%d or %d)", node_type(node), node->name, con, lis); if (con < 0) return lis; if (lis < 0) return con; /* we prefer the socket with the lowest ip-address */ if (getsockname(lis, (struct sockaddr *)&lissain, &slen) < 0) { lerr("negotiate: getsockname(%d, ...) failed: %s", lis, strerror(errno)); return con; } if (getpeername(con, (struct sockaddr *)&consain, &slen) < 0) { lerr("negotiate: getpeername(%d, ...) failed: %s", con, strerror(errno)); return lis; } ldebug("negotiate: lis(%d): %s:%d", lis, inet_ntoa(lissain.sin_addr), ntohs(lissain.sin_port)); ldebug("negotiate: con(%d): %s:%d", con, inet_ntoa(consain.sin_addr), ntohs(consain.sin_port)); if (lissain.sin_addr.s_addr > consain.sin_addr.s_addr) { ldebug("negotiate: con has lowest ip. using that"); return con; } if (consain.sin_addr.s_addr > lissain.sin_addr.s_addr) { ldebug("negotiate: lis has lowest ip. using that"); return lis; } /* * this will happen if multiple merlin instances run * on the same server, such as when we're testing * things. In that case, let the portnumber decide * the tiebreak */ if (lissain.sin_port > consain.sin_port) { ldebug("negotiate: con has lowest port. using that"); return con; } if (consain.sin_port > lissain.sin_port) { ldebug("negotiate: lis has lowest port. using that"); return lis; } ldebug("negotiate: con and lis are equal. killing both"); node->last_conn_attempt_logged = 0; node_disconnect(node, "socket negotiation failed"); iobroker_close(nagios_iobs, lis); node->sock = -1; return -1; }
/* * Initiate a connection attempt to a node and mark it as PENDING. * Note that since we're using sockets in non-blocking mode (in order * to be able to effectively multiplex), the connection attempt will * never be completed in this function */ int net_try_connect(merlin_node *node) { int sockopt = 1; struct sockaddr *sa = (struct sockaddr *)&node->sain; int should_log = 0; struct timeval connect_timeout = { MERLIN_CONNECT_TIMEOUT, 0 }; struct sockaddr_in sain; time_t interval = MERLIN_CONNECT_INTERVAL; int result; /* don't log obsessively */ if (node->last_conn_attempt_logged + 30 <= time(NULL)) { should_log = 1; node->last_conn_attempt_logged = time(NULL); } if (!(node->flags & MERLIN_NODE_CONNECT)) { if (should_log) { linfo("CONN: Connect attempt blocked by config to %s node %s", node_type(node), node->name); } return 0; } /* don't bother trying to connect if it's pending or done */ switch (node->state) { case STATE_NEGOTIATING: if (node->conn_sock < 0) break; case STATE_CONNECTED: case STATE_PENDING: ldebug("CONN: node %s state is %s, so bailing", node->name, node_state_name(node->state)); return 0; } /* if it's not yet time to connect, don't even try it */ if (node->last_conn_attempt + interval > time(NULL)) { return 0; } /* mark the time so we can time it out ourselves if need be */ node->last_conn_attempt = time(NULL); /* create the socket if necessary */ if (node->conn_sock < 0) { node_disconnect(node, "struct reset (no real disconnect)"); node->conn_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (node->conn_sock < 0) { lerr("CONN: Failed to obtain connection socket for node %s: %s", node->name, strerror(errno)); lerr("CONN: Aborting connection attempt to %s", node->name); return -1; } } sa->sa_family = AF_INET; if (should_log) { linfo("CONN: Connecting to %s %s@%s:%d", node_type(node), node->name, inet_ntoa(node->sain.sin_addr), ntohs(node->sain.sin_port)); } if (setsockopt(node->conn_sock, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(int))) { ldebug("CONN: Failed to set sockopt SO_REUSEADDR for node %s connect socket %d: %s", node->name, node->conn_sock, strerror(errno)); } if (node->flags & MERLIN_NODE_FIXED_SRCPORT) { ldebug("CONN: Using fixed source port %d for %s node %s", net_source_port(node), node_type(node), node->name); /* * first we bind() to a local port calculated by our own * listening port + the target port. */ sain.sin_family = AF_INET; sain.sin_port = htons(net_source_port(node)); sain.sin_addr.s_addr = 0; if (bind(node->conn_sock, (struct sockaddr *)&sain, sizeof(sain))) { lerr("CONN: Failed to bind() outgoing socket %d for node %s to port %d: %s", node->conn_sock, node->name, ntohs(sain.sin_port), strerror(errno)); if (errno == EBADF || errno == EADDRINUSE) { close(node->conn_sock); node->conn_sock = -1; return -1; } } } if (fcntl(node->conn_sock, F_SETFL, O_NONBLOCK) < 0) { lwarn("CONN: Failed to set socket %d for %s non-blocking: %s", node->conn_sock, node->name, strerror(errno)); } if (setsockopt(node->conn_sock, SOL_SOCKET, SO_RCVTIMEO, &connect_timeout, sizeof(connect_timeout)) < 0) { ldebug("CONN: Failed to set receive timeout for %d, node %s: %s", node->conn_sock, node->name, strerror(errno)); } if (setsockopt(node->conn_sock, SOL_SOCKET, SO_SNDTIMEO, &connect_timeout, sizeof(connect_timeout)) < 0) { ldebug("CONN: Failed to set send timeout for %d, node %s: %s", node->conn_sock, node->name, strerror(errno)); } if (connect(node->conn_sock, sa, sizeof(struct sockaddr_in)) < 0) { if (errno == EINPROGRESS) { /* * non-blocking socket and connect() can't be completed * immediately (ie, the normal case) */ node_set_state(node, STATE_PENDING, "Connecting"); } else if (errno == EALREADY) { ldebug("CONN: Connect already in progress for socket %d to %s. This should never happen", node->conn_sock, node->name); node_set_state(node, STATE_PENDING, "connect() already in progress"); } else { /* a real connection error */ ldebug("CONN: connect() via %d to %s failed: %s", node->conn_sock, node->name, strerror(errno)); close(node->conn_sock); node->conn_sock = -1; if (should_log) { node_disconnect(node, "CONN: connect() failed to %s node '%s' (%s:%d): %s", node_type(node), node->name, inet_ntoa(node->sain.sin_addr), ntohs(node->sain.sin_port), strerror(errno)); } else { node_disconnect(node, NULL); } return -1; } } result = iobroker_register_out(nagios_iobs, node->conn_sock, node, conn_writable); if (result < 0) { node_disconnect(node, "IOB: Failed to register %s connect socket %d with iobroker: %s", node->name, node->conn_sock, iobroker_strerror(result)); close(node->conn_sock); node->conn_sock = -1; return -1; } return 0; }
/* * Check if a socket is connected by looking up * ip and port of the remote host. * Returns 0 if not, and 1 if it is. */ int net_is_connected(merlin_node *node) { struct sockaddr_in sain; socklen_t slen; int optval = 0, gsoerr = 0, gsores = 0, gpnres = 0, gpnerr = 0; if (!node || node->sock < 0) return 0; if (node->state == STATE_CONNECTED) return 1; if (node->state == STATE_NONE) return 0; /* * yes, getpeername() actually has to be here, or getsockopt() * won't return errors when we're not yet connected. It's * important that we read the socket error state though, or * some older kernels will maintain the link in SYN_SENT state * more or less indefinitely, so get all the syscalls taken * care of no matter if they actually work or not. */ errno = 0; slen = sizeof(struct sockaddr_in); gpnres = getpeername(node->sock, (struct sockaddr *)&sain, &slen); gpnerr = errno; slen = sizeof(optval); gsores = getsockopt(node->sock, SOL_SOCKET, SO_ERROR, &optval, &slen); gsoerr = errno; if (!gpnres && !gsores && !optval && !gpnerr && !gsoerr) { return 1; } if (optval) { node_disconnect(node, "connect() to %s node %s (%s:%d) failed: %s", node_type(node), node->name, inet_ntoa(node->sain.sin_addr), ntohs(node->sain.sin_port), strerror(optval)); return 0; } if (gsores < 0 && gsoerr != ENOTCONN) { node_disconnect(node, "getsockopt(%d) failed for %s node %s: %s", node->sock, node_type(node), node->name, strerror(gsoerr)); } if (gpnres < 0 && gpnerr != ENOTCONN) { lerr("getpeername(%d) failed for %s: %s", node->sock, node->name, strerror(gpnerr)); return 0; } /* * if a connection is in progress, we should be getting * ENOTCONN, but we need to give it time to complete * first. 30 seconds should be enough. */ if (node->last_conn_attempt + MERLIN_CONNECT_TIMEOUT < time(NULL)) { node_disconnect(node, "connect() timed out after %d seconds", MERLIN_CONNECT_TIMEOUT); } return 0; }
EXPORT NODE *adv_node_loop_after_good_prop( NODE *oldn, NODE *newn, RPROBLEM **rp) { NODE *n; NODE *next_oldn; RPROBLEM *rp1; RP_NODE *rpn; if ((rp != NULL) && (*rp != NULL) && (newn != NULL) && (node_type(newn) != SUBDOMAIN_NODE) && (!is_virtual_fixed_node(newn))) { for (rp1 = *rp; rp1; rp1 = rp1->prev) { for (rpn = rp1->first_rp_node; rpn; rpn = rpn->next) { if ((rpn->node == newn)) break; } if (rpn == NULL) continue; /* Delete rp1 from rp list */ if (rp1->prev) rp1->prev->next = rp1->next; if (rp1->next) rp1->next->prev = rp1->prev; else *rp = rp1->prev; /* Push other nodes in rp1 to end of node list */ for (rpn = rp1->first_rp_node; rpn; rpn = rpn->next) { if ((rpn->node == newn)) continue; if (propagation_status(rpn->node) == PROPAGATED_NODE) continue; /* Check if node already follows newn */ for (n = next_node(newn); n != NULL; n = next_node(n)) { if (n == rpn->node) break; } if (n != NULL) continue; n = rpn->node; (void) reorder_node_loop(rpn->old_node,rpn->node); } free_rp(rp1); } } /* * Reset propagation status to UNPROPAGATED_NODE * after successful node propagation. */ next_oldn = next_node(oldn); for (oldn = next_oldn; oldn != NULL; oldn = next_node(oldn)) { if ((newn = correspond_node(oldn)) == NULL) continue; if (propagation_status(newn) != PROPAGATED_NODE) propagation_status(newn) = UNPROPAGATED_NODE; } return next_oldn; } /*end adv_node_loop_after_good_prop*/
void c_write_node_debug_print(node_t*n, state_t*s) { strf(s, "printf(\"%s\n\", ", c_printf_type(node_type(n, s->model))); write_node(s, n->child[0]); strf(s, ");"); }