int cmd_session_list (int argc, const char *argv[]) { var *v = api_get ("/session"); if (OPTIONS.json) { var_dump (v, stdout); var_free (v); return 0; } printf ("---------------------------------------------" "-----------------------------------\n"); printf ("Session ID Sender" " Last Refresh\n"); var *v_session = var_get_array_forkey (v, "session"); var *crsr = v_session->value.arr.first; while (crsr) { printf ("%08x-%08x %-39s %s\n", (uint32_t) (var_get_int_forkey (crsr, "sessid")), (uint32_t) (var_get_int_forkey (crsr, "addr")), var_get_str_forkey (crsr, "remote"), var_get_str_forkey (crsr, "lastcycle")); crsr = crsr->next; } printf ("---------------------------------------------" "-----------------------------------\n"); var_free (v); return 0; }
/** The tenant-list command */ int cmd_tenant_list (int argc, const char *argv[]) { var *res = api_get ("/"); if (OPTIONS.json) { var_dump (res, stdout); } else { printf ("UUID Hosts Name\n"); printf ("---------------------------------------------" "-----------------------------------\n"); var *res_tenant = var_get_array_forkey (res, "tenant"); if (var_get_count (res_tenant)) { var *crsr = res_tenant->value.arr.first; while (crsr) { printf ("%s %5llu %s\n", var_get_str_forkey (crsr, "id"), var_get_int_forkey (crsr, "hostcount"), var_get_str_forkey (crsr, "name")); crsr = crsr->next; } } printf ("----------------------------------------------" "----------------------------------\n"); } var_free (res); return 0; }
/** The host-list command */ int cmd_host_list (int argc, const char *argv[]) { if (OPTIONS.tenant[0] == 0) { fprintf (stderr, "%% No tenantid provided\n"); return 1; } const char *unit; var *apires = api_get ("/%s/host", OPTIONS.tenant); if (OPTIONS.json) { var_dump (apires, stdout); var_free (apires); return 0; } var *v_hosts = var_get_array_forkey (apires, "host"); if (var_get_count (v_hosts)) { printf ("UUID Size " "First record Last record\n"); printf ("---------------------------------------------" "-----------------------------------\n"); var *crsr = v_hosts->value.arr.first; while (crsr) { uint64_t usage = var_get_int_forkey (crsr, "usage"); unit = "KB"; usage = usage / 1024; if (usage > 2048) { unit = "MB"; usage = usage / 1024; } char start[24]; char end[24]; strncpy (start, var_get_str_forkey (crsr, "start"), 23); strncpy (end, var_get_str_forkey (crsr, "end"), 23); start[16] = 0; end[16] = 0; start[10] = ' '; end[10] = ' '; printf ("%s %4llu %s %s %s\n", var_get_str_forkey (crsr, "id"), usage, unit, start, end); crsr = crsr->next; } printf ("---------------------------------------------" "-----------------------------------\n"); } var_free (apires); return 0; }
int main (int argc, const char *argv[]) { const char *tstr = NULL; var *env = var_alloc(); var *env_collector = var_get_dict_forkey (env, "collector"); var *env_colors = var_get_array_forkey (env, "colors"); var_set_int_forkey (env_collector, "listenport", 3333); var_set_str_forkey (env_collector, "address", "127.0.0.1"); var_set_str_forkey (env_collector, "key", "secret"); var_clear_array (env_colors); var_add_str (env_colors, "red"); var_add_str (env_colors, "green"); var_add_str (env_colors, "blue"); assert (var_get_int_forkey (env_collector, "listenport") == 3333); assert (tstr = var_get_str_forkey (env_collector, "address")); assert (strcmp (tstr, "127.0.0.1") == 0); assert (tstr = var_get_str_forkey (env_collector, "key")); assert (strcmp (tstr, "secret") == 0); assert (var_get_count (env_collector) == 3); assert (tstr = var_get_str_atindex (env_colors, 0)); assert (strcmp (tstr, "red") == 0); assert (tstr = var_get_str_atindex (env_colors, 1)); assert (strcmp (tstr, "green") == 0); assert (tstr = var_get_str_atindex (env_colors, 2)); assert (strcmp (tstr, "blue") == 0); time_t tnow = time (NULL); var_set_time_forkey (env, "nowtime", tnow); assert (var_get_time_forkey (env, "nowtime") == tnow); var_set_unixtime_forkey (env, "unixtime", tnow); assert (var_get_time_forkey (env, "unixtime") == tnow); uuid uuid_in = uuidgen(); var_set_uuid_forkey (env, "myuuid", uuid_in); uuid uuid_out = var_get_uuid_forkey (env, "myuuid"); assert (uuidcmp (uuid_in, uuid_out)); var_new_generation (env); var_set_int_forkey (env_collector, "listenport", 3333); var_set_str_forkey (env_collector, "address", "192.168.1.1"); var_clear_array (env_colors); var_add_str (env_colors, "red"); var_add_str (env_colors, "green"); var_add_str (env_colors, "blue"); var *lport, *addr, *key; lport = var_find_key (env_collector, "listenport"); addr = var_find_key (env_collector, "address"); key = var_find_key (env_collector, "key"); assert (lport); assert (addr); assert (key); /* collector.listenport should be unchanged from first generation */ assert (lport->generation == env->generation); assert (lport->lastmodified < env->generation); assert (lport->firstseen == lport->lastmodified); /* collector.addr should be changed this generation */ assert (addr->generation == env->generation); assert (addr->lastmodified == env->generation); assert (addr->firstseen == env->firstseen); /* colors should be changed this generation */ assert (env_colors->generation == env->generation); assert (env_colors->lastmodified == env->generation); assert (env_colors->firstseen == env->firstseen); /* collector.key should be stale */ assert (key->generation < env->generation); var_clean_generation (env); /* collector.key should now be deleted */ key = var_find_key (env_collector, "key"); assert (key == NULL); return 0; }
/** Internal state machine for parsing a JSON-like configuration * text. Recurses on itself for new levels of hierarchy. * \param v The var at this cursor level. * \param buf The cursor (inout) * \param st The state to start out with. */ static int var_parse_json_level (var *v, const char **buf, parse_state st, int depth) { if (depth > default_max_json_depth) { sprintf (LAST_PARSE_ERROR, "Nested to deep"); return 0; } const char *c = *buf; var *vv = NULL; char keybuf[4096]; int keybuf_pos = 0; char valuebuf[4096]; int valuebuf_pos = 0; int value_nondigits = 0; int value_dots = 0; parse_state stnext; while (*c) { switch (st) { case PSTATE_BEGINNING: if (*c == '{') { st = PSTATE_DICT_WAITKEY; break; } /* intentional fall-through */ case PSTATE_DICT_WAITKEY: if (*c == '#') { stnext = st; st = PSTATE_COMMENT; break; } if (isspace (*c)) break; if (*c == ',') break; if (*c == '}') { *buf = c; return 1; } if (*c == '\"') st = PSTATE_DICT_KEY_QUOTED; else { if (! strchr (VALIDUNQUOTED, *c)) { sprintf (LAST_PARSE_ERROR, "Invalid char for " "key: '%c'", *c); return 0; } --c; st = PSTATE_DICT_KEY; } keybuf_pos = 0; keybuf[0] = 0; valuebuf_pos = 0; valuebuf[0] = 0; break; case PSTATE_DICT_KEY: if (*c == '#') { stnext = PSTATE_DICT_WAITVALUE; st = PSTATE_COMMENT; break; } if (isspace (*c)) { st = PSTATE_DICT_WAITVALUE; break; } if (*c == '{') { *buf = c+1; vv = var_get_dict_forkey (v, keybuf); if (! vv) { sprintf (LAST_PARSE_ERROR, "Couldn't get dict " "for key '%s'", keybuf); return 0; } if (!var_parse_json_level (vv, buf, PSTATE_DICT_WAITKEY, depth+1)) { return 0; } c = *buf; st = PSTATE_DICT_WAITKEY; break; } if (*c == '[') { *buf = c+1; vv = var_get_array_forkey (v, keybuf); if (! vv) { sprintf (LAST_PARSE_ERROR, "Couldn't get array " "for key '%s'", keybuf); return 0; } var_clear_array (vv); if (!var_parse_json_level (vv, buf, PSTATE_ARRAY_WAITVALUE, depth+1)) { return 0; } c = *buf; st = PSTATE_DICT_WAITKEY; break; } if (*c == ':') { st = PSTATE_DICT_WAITVALUE; break; } if (! strchr (VALIDUNQUOTED, *c)) { sprintf (LAST_PARSE_ERROR, "Invalid character in " "value '%c'", *c); return 0; } if (keybuf_pos >= 4095) return 0; keybuf[keybuf_pos++] = *c; keybuf[keybuf_pos] = 0; break; case PSTATE_DICT_KEY_QUOTED: if (*c == '\"') { st = PSTATE_DICT_WAITVALUE; break; } if (*c == '\\') ++c; if (keybuf_pos >= 4095) return 0; keybuf[keybuf_pos++] = *c; keybuf[keybuf_pos] = 0; break; case PSTATE_DICT_WAITVALUE: if (*c == '#') { stnext = st; st = PSTATE_COMMENT; break; } if (isspace (*c)) break; if (*c == ':') break; if (*c == '=') break; if (*c == '{') { *buf = c+1; vv = var_get_dict_forkey (v, keybuf); if (! vv) { sprintf (LAST_PARSE_ERROR, "Couldn't get dict for " "key '%s'", keybuf); return 0; } if (!var_parse_json_level (vv, buf, PSTATE_DICT_WAITKEY, depth+1)) { return 0; } c = *buf; st = PSTATE_DICT_WAITKEY; break; } if (*c == '[') { *buf = c+1; vv = var_get_array_forkey (v, keybuf); if (! vv) { sprintf (LAST_PARSE_ERROR, "Couldn't get array " "for key '%s'", keybuf); return 0; } var_clear_array (vv); if (!var_parse_json_level (vv, buf, PSTATE_ARRAY_WAITVALUE, depth+1)) { return 0; } c = *buf; st = PSTATE_DICT_WAITKEY; break; } if (*c == '\"') { st = PSTATE_DICT_VALUE_QUOTED; } else { if (! strchr (VALIDUNQUOTEDV, *c)) { sprintf (LAST_PARSE_ERROR, "Invalid character for " "value: '%c'", *c); return 0; } --c; value_nondigits = 0; value_dots = 0; st = PSTATE_DICT_VALUE; } valuebuf_pos = 0; valuebuf[0] = 0; break; case PSTATE_DICT_VALUE: if (isspace (*c) || (*c == ',') || (*c == '}') || (*c == '#')) { if ((! value_nondigits) && (value_dots < 2)) { if (value_dots == 0) { var_set_int_forkey (v, keybuf, strtoull(valuebuf, NULL, 10)); } else { var_set_double_forkey (v, keybuf, atof(valuebuf)); } } else var_set_str_forkey (v, keybuf, valuebuf); if (*c == '#') { stnext = PSTATE_DICT_WAITKEY; st = PSTATE_COMMENT; break; } if (*c == '}') { *buf = c; return 1; } st = PSTATE_DICT_WAITKEY; break; } if (! strchr (VALIDUNQUOTEDV, *c)) { sprintf (LAST_PARSE_ERROR, "Invalid character in " "value for '%s': '%c'", keybuf, *c); return 0; } if (*c == '.') value_dots++; else if ((!value_nondigits) && (*c<'0' || *c>'9')) { value_nondigits = 1; } if (valuebuf_pos >= 4095) return 0; valuebuf[valuebuf_pos++] = *c; valuebuf[valuebuf_pos] = 0; break; case PSTATE_DICT_VALUE_QUOTED: if (*c == '\"') { var_set_str_forkey (v, keybuf, valuebuf); st = PSTATE_DICT_WAITKEY; break; } if (*c == '\\') ++c; if (valuebuf_pos >= 4095) return 0; valuebuf[valuebuf_pos++] = *c; valuebuf[valuebuf_pos] = 0; break; case PSTATE_ARRAY_WAITVALUE: if (*c == '#') { stnext = st; st = PSTATE_COMMENT; break; } if (isspace (*c)) break; if (*c == ',') break; if (*c == ']') { *buf = c; return 1; } if (*c == '{') { *buf = c+1; vv = var_add_dict (v); if (! vv) { sprintf (LAST_PARSE_ERROR, "Couldn't add dict"); return 0; } if (!var_parse_json_level (vv, buf, PSTATE_DICT_WAITKEY, depth+1)) { return 0; } c = *buf; st = PSTATE_ARRAY_WAITVALUE; break; } if (*c == '[') { *buf = c+1; vv = var_add_array (v); if (! vv) { sprintf (LAST_PARSE_ERROR, "Couldn't add array"); return 0; } var_clear_array (vv); if (!var_parse_json_level (vv, buf, PSTATE_ARRAY_WAITVALUE, depth+1)) { return 0; } c = *buf; st = PSTATE_ARRAY_WAITVALUE; break; } if (*c == '\"') { st = PSTATE_ARRAY_VALUE_QUOTED; } else { if (! strchr (VALIDUNQUOTED, *c)) return 0; --c; value_nondigits = 0; value_dots = 0; st = PSTATE_ARRAY_VALUE; } valuebuf_pos = 0; valuebuf[0] = 0; break; case PSTATE_ARRAY_VALUE: if (isspace (*c) || (*c == ']') || (*c == ',') || (*c == '#')) { if ((! value_nondigits) && (value_dots<2)) { if (value_dots == 0) { var_add_int (v, strtoull (valuebuf, NULL, 10)); } else { var_add_double (v, atof (valuebuf)); } } else var_add_str (v, valuebuf); if (*c == '#') { stnext = PSTATE_ARRAY_WAITVALUE; st = PSTATE_COMMENT; break; } if (*c == ']') { *buf = c; return 1; } st = PSTATE_ARRAY_WAITVALUE; break; } if (! strchr (VALIDUNQUOTEDV, *c)) return 0; if (*c == '.') value_dots++; else if ((!value_nondigits) && (*c<'0' || *c>'9')) { value_nondigits = 1; } if (valuebuf_pos >= 4095) return 0; valuebuf[valuebuf_pos++] = *c; valuebuf[valuebuf_pos] = 0; break; case PSTATE_ARRAY_VALUE_QUOTED: if (*c == '\"') { var_add_str (v, valuebuf); st = PSTATE_ARRAY_WAITVALUE; break; } if (*c == '\\') ++c; if (valuebuf_pos >= 4095) return 0; valuebuf[valuebuf_pos++] = *c; valuebuf[valuebuf_pos] = 0; break; case PSTATE_COMMENT: if (*c == '\n') { st = stnext; } break; } ++c; *buf = c; } return 1; }
/** The get-recrod command */ int cmd_get_record (int argc, const char *argv[]) { if (OPTIONS.tenant[0] == 0) { fprintf (stderr, "%% No tenantid provided\n"); return 1; } if (OPTIONS.host[0] == 0) { fprintf (stderr, "%% No hostid provided\n"); return 1; } var *apires = api_get ("/%s/host/%s", OPTIONS.tenant, OPTIONS.host); if (OPTIONS.json) { var_dump (apires, stdout); var_free (apires); return 0; } #define Arr(x) var_get_array_forkey(apires,x) #define Vint(x) var_get_int_forkey(apires,x) #define Vstr(x) var_get_str_forkey(apires,x) #define Vfrac(x) var_get_double_forkey(apires,x) #define VDint(x,y) var_get_int_forkey(var_get_dict_forkey(apires,x),y) #define VDstr(x,y) var_get_str_forkey(var_get_dict_forkey(apires,x),y) #define VDfrac(x,y) var_get_double_forkey(var_get_dict_forkey(apires,x),y) #define VAfrac(x,y) var_get_double_atindex(var_get_array_forkey(apires,x),y) #define Vdone(x) var_delete_key(apires,x) /* -------------------------------------------------------------*/ print_hdr ("HOST"); print_value ("UUID", "%s", OPTIONS.host); print_value ("Hostname", "%s", Vstr("hostname")); print_value ("Address", "%s", VDstr("agent","ip")); print_value ("Status", "\033[1m%s\033[0m", Vstr("status")); print_array ("Problems", Arr("problems")); Vdone("hostname"); Vdone("agent"); Vdone("status"); Vdone("problems"); char uptimestr[128]; uint64_t uptime = Vint("uptime"); Vdone("uptime"); uint64_t u_days = uptime / 86400ULL; uint64_t u_hours = (uptime - (86400 * u_days)) / 3600ULL; uint64_t u_mins = (uptime - (86400 * u_days) - (3600 * u_hours)) / 60ULL; uint64_t u_sec = uptime % 60; if (u_days) { sprintf (uptimestr, "%llu day%s, %llu:%02llu:%02llu", u_days, (u_days==1)?"":"s", u_hours, u_mins, u_sec); } else if (u_hours) { sprintf (uptimestr, "%llu:%02llu:%02llu", u_hours, u_mins, u_sec); } else { sprintf (uptimestr, "%llu minute%s, %llu second%s", u_mins, (u_mins==1)?"":"s", u_sec, (u_sec==1)?"":"s"); } print_value ("Uptime","%s",uptimestr); print_value ("OS/Hardware","%s %s (%s)", VDstr("os","kernel"), VDstr("os","version"), VDstr("os","arch")); const char *dist = VDstr("os","distro"); if (dist) print_value ("Distribution", "%s", dist); Vdone("os"); /* -------------------------------------------------------------*/ print_hdr ("RESOURCES"); print_value ("Processes","\033[1m%llu\033[0m " "(\033[1m%llu\033[0m running, " "\033[1m%llu\033[0m stuck)", VDint("proc","total"), VDint("proc","run"), VDint("proc","stuck")); Vdone("proc"); print_value ("Load Average", "\033[1m%6.2f\033[0m / " "\033[1m%6.2f\033[0m / " "\033[1m%6.2f\033[0m", VAfrac ("loadavg",0), VAfrac ("loadavg", 1), VAfrac ("loadavg",2)); Vdone ("loadavg"); char cpubuf[128]; sprintf (cpubuf, "\033[1m%6.2f \033[0m%%", Vfrac("pcpu")); char meter[32]; strcpy (meter, "-[ ]+"); double iowait = VDfrac("io","pwait"); double pcpu = Vfrac("pcpu"); Vdone("pcpu"); double level = 4.5; int pos = 2; while (level < 100.0 && pos < 22) { if (level < pcpu) meter[pos++] = '#'; else meter[pos++] = ' '; level += 4.5; } print_value ("CPU", "%-40s %s", cpubuf, meter); if (iowait>0.001) print_value ("CPU iowait", "\033[1m%6.2f %%\033[0m", iowait); print_value ("Available RAM", "\033[1m%.2f\033[0m MB", ((double)VDint("mem","total"))/1024.0); print_value ("Free RAM", "\033[1m%.2f\033[0m MB", ((double)VDint("mem","free"))/1024.0); print_value ("Network in/out", "\033[1m%i\033[0m Kb/s " "(\033[1m%i\033[0m pps) / " "\033[1m%i\033[0m Kb/s " "(\033[1m%i\033[0m pps)", VDint("net","in_kbs"), VDint("net","in_pps"), VDint("net","out_kbs"), VDint("net","out_pps")); print_value ("Disk i/o", "\033[1m%i\033[0m rdops / " "\033[1m%i\033[0m wrops", VDint("io","rdops"), VDint("io","wrops")); Vdone("mem"); Vdone("net"); Vdone("io"); Vdone("badness"); print_values (apires, NULL); /* -------------------------------------------------------------*/ print_hdr ("PROCESS LIST"); const char *top_hdr[] = {"USER","PID","CPU","MEM","NAME",NULL}; const char *top_fld[] = {"user","pid","pcpu","pmem","name",NULL}; columnalign top_align[] = {CA_L, CA_R, CA_R, CA_R, CA_L, CA_NULL}; vartype top_tp[] = {VAR_STR,VAR_INT,VAR_DOUBLE,VAR_DOUBLE,VAR_STR,VAR_NULL}; int top_wid[] = {15, 7, 9, 9, 0, 0}; int top_div[] = {0, 0, 0, 0, 0, 0}; const char *top_suf[] = {"",""," %", " %", "", NULL}; var *v_top = var_get_array_forkey (apires, "top"); print_table (v_top, top_hdr, top_fld, top_align, top_tp, top_wid, top_suf, top_div); Vdone("top"); /* -------------------------------------------------------------*/ print_hdr ("STORAGE"); const char *df_hdr[] = {"DEVICE","SIZE","FS","USED","MOUNTPOINT",NULL}; const char *df_fld[] = {"device","size","fs","pused","mount",NULL}; columnalign df_aln[] = {CA_L,CA_R,CA_L,CA_R,CA_L,CA_NULL}; vartype df_tp[] = {VAR_STR,VAR_INT,VAR_STR,VAR_DOUBLE,VAR_STR,VAR_NULL}; int df_wid[] = {12, 14, 6, 8, 0}; int df_div[] = {0, (1024), 0, 0, 0, 0}; const char *df_suf[] = {""," GB", "", " %", "", ""}; var *v_df = var_get_array_forkey (apires, "df"); /*print_generic_table (v_df);*/ print_table (v_df, df_hdr, df_fld, df_aln, df_tp, df_wid, df_suf, df_div); Vdone("df"); /** Print any remaining table data */ print_tables (apires); printf ("---------------------------------------------" "-----------------------------------\n"); var_free (apires); print_done(); return 0; }
/** Daemon main run loop. */ int daemon_main (int argc, const char *argv[]) { const char *buf; size_t sz; if (strcmp (APP.logpath, "@syslog") == 0) { log_open_syslog ("opticon-agent", APP.loglevel); } else { log_open_file (APP.logpath, APP.loglevel); } probelist_start (&APP.probes); APP.resender = authresender_create (APP.transport); time_t tlast = time (NULL); time_t nextslow = tlast + 5; time_t nextsend = tlast + 10; time_t lastkeyrotate = 0; int slowround = 0; log_info ("Daemonized"); while (1) { time_t tnow = tlast = time (NULL); slowround = 0; /* If a slow round is due at this time, use the excuse to send an authentication packet */ if (nextslow <= tnow) { slowround = 1; uint32_t sid = APP.auth.sessionid; if (! sid) sid = gen_sessionid(); log_debug ("Authenticating session <%08x>", sid); APP.auth.sessionid = sid; APP.auth.serial = 0; APP.auth.tenantid = APP.tenantid; APP.auth.hostid = APP.hostid; /* Only rotate the AES key every half hour */ if (tnow - lastkeyrotate > 1800) { APP.auth.sessionkey = aeskey_create(); lastkeyrotate = tnow; } APP.auth.tenantkey = APP.collectorkey; /* Dispatch */ ioport *io_authpkt = ioport_wrap_authdata (&APP.auth, gen_serial()); sz = ioport_read_available (io_authpkt); buf = ioport_get_buffer (io_authpkt); outtransport_send (APP.transport, (void*) buf, sz); authresender_schedule (APP.resender, buf, sz); ioport_close (io_authpkt); /* Schedule next slow round */ nextslow = nextslow + 300; } log_debug ("Poking probes"); probe *p = APP.probes.first; time_t wakenext = tnow + 300; /* Go over the probes to figure out whether we should kick them */ while (p) { time_t firewhen = p->lastpulse + p->interval; if (firewhen <= tnow) { conditional_signal (&p->pulse); p->lastpulse = tnow; } /* Figure out whether the next event for this probe is sooner than the next wake-up time we determined so far */ if (p->lastpulse + p->interval < wakenext) { wakenext = p->lastpulse + p->interval; } p = p->next; } int collected = 0; int ncollected = 0; host *h = host_alloc(); var *vnagios = var_alloc(); var *vchkwarn = var_get_array_forkey (vnagios, "chkwarn"); var *vchkalert = var_get_array_forkey (vnagios, "chkalert"); /* If we're in a slow round, we already know we're scheduled. Otherwise, see if the next scheduled moment for sending a (fast lane) packet has passed. */ if (slowround || (tnow >= nextsend)) { h->uuid = APP.hostid; host_begin_update (h, time (NULL)); if (! slowround) while (nextsend <= tnow) nextsend += 60; log_debug ("Collecting probes"); /* Go over the probes again, picking up the ones relevant to the current round being performed */ p = APP.probes.first; while (p) { pthread_mutex_lock (&p->vlock); volatile var *v = p->vcurrent; /* See if data for this probe has been collected since the last kick */ if (v && (p->lastdispatch <= p->lastreply)) { /* Filter probes for the current lane */ if ((slowround && p->interval>60) || ((!slowround) && p->interval<61)) { log_debug ("Collecting <%s>", p->call); if (p->type == PROBE_NAGIOS) { /* Check for alert/warning state and * summarize before adding to host struct */ int pstatus = var_get_int_forkey ((var*)v, "status"); if (pstatus) { var *arr; switch (pstatus) { case 1: var_add_str (vchkwarn, p->id); break; default: var_add_str (vchkalert, p->id); break; } collected++; } ncollected++; } else { host_import (h, (var *) v); collected++; } p->lastdispatch = tnow; } } else { if (tnow - p->lastreply > (2*(p->interval))) { log_warn ("Probe <%s> seems stuck after %i seconds", p->call, tnow - p->lastreply); } } pthread_mutex_unlock (&p->vlock); p = p->next; } } /* Add the chk tree with nagios self-checks to the data */ if (ncollected) host_import (h, vnagios); /* If any data was collected, encode it */ if (collected) { log_debug ("Encoding probes"); ioport *encoded = ioport_create_buffer (NULL, 4096); if (! encoded) { log_warn ("Error creating ioport"); ioport_close (encoded); host_delete (h); continue; } if (! codec_encode_host (APP.codec, encoded, h)) { log_warn ("Error encoding host"); ioport_close (encoded); host_delete (h); continue; } if (APP.dumppath) { FILE *pktf = fopen (APP.dumppath,"a"); fprintf (pktf, "\n--- %s ---\n\n", slowround?"Slow":"Fast"); ioport *dump = ioport_create_filewriter (pktf); log_debug ("dump %llx", dump); codec *jsonc = codec_create_json(); log_debug ("jsonc %llx", jsonc); codec_encode_host (jsonc, dump, h); codec_release (jsonc); ioport_close (dump); fclose (pktf); } log_debug ("Encoded %i bytes", ioport_read_available (encoded)); ioport *wrapped = ioport_wrap_meterdata (APP.auth.sessionid, gen_serial(), APP.auth.sessionkey, encoded); if (! wrapped) { log_error ("Error wrapping"); ioport_close (encoded); host_delete (h); continue; } sz = ioport_read_available (wrapped); buf = ioport_get_buffer (wrapped); /* Send it off into space */ outtransport_send (APP.transport, (void*) buf, sz); log_info ("%s lane packet sent: %i bytes", slowround ? "Slow":"Fast", sz); ioport_close (wrapped); ioport_close (encoded); } /* Done with the host object */ host_delete (h); /* Figure out what the next scheduled wake-up time is */ tnow = time (NULL); if (nextsend < wakenext) wakenext = nextsend; if (nextslow < wakenext) wakenext = nextslow; if (wakenext > tnow) { log_debug ("Sleeping for %i seconds", (wakenext-tnow)); sleep (wakenext-tnow); } } return 666; }