/* * Parse the -n argument and populate -T if necessary. * * Run on every connect, must do some cleanup. * * XXX: It writes to stdout in addition to the logger because the logger * may not be operational yet. Not sure if this makes sense... At any rate, * the required bit is to write to the logger. */ static int n_arg_sock(struct agent_core_t *core) { struct VSM_data *vsd; struct vadmin_config_t *vadmin; char *p; GET_PRIV(core, vadmin); vsd = VSM_New(); assert(VSL_Arg(vsd, 'n', core->config->n_arg)); if (VSM_Open(vsd, 1)) { logger(vadmin->logger,"Couldn't open VSM"); fprintf(stderr, "Couldn't open VSM\n"); VSM_Delete(vsd); vsd = NULL; } if (core->config->T_arg_orig) { if (core->config->T_arg) free(core->config->T_arg); core->config->T_arg = strdup(core->config->T_arg_orig); } else { if (vsd == NULL) { logger(vadmin->logger,"No -T arg and no shmlog readable."); return -1; } p = VSM_Find_Chunk(vsd, "Arg", "-T", "", NULL); if (p == NULL) { fprintf(stderr, "No -T arg in shared memory\n"); logger(vadmin->logger, "No -T arg in shared memory."); return (-1); } core->config->T_arg = strdup(p); } if (core->config->S_arg == NULL && !vsd) { logger(vadmin->logger, "No shmlog and no -S arg. Unknown if authentication will work."); } if (vsd && core->config->S_arg == NULL) { p = VSM_Find_Chunk(vsd, "Arg", "-S", "", NULL); if (p != NULL) core->config->S_arg = strdup(p); } p = strchr(core->config->T_arg, '\n'); if (p) { assert(p); *p = '\0'; } if (vsd) VSM_Delete(vsd); logger(vadmin->logger, "-T argument computed to: %s", core->config->T_arg ? core->config->T_arg : "(null)"); return (1); }
static int n_arg_sock(const char *n_arg) { char *T_arg = NULL, *T_start = NULL; char *S_arg = NULL; struct VSM_data *vsm; char *p; int sock; struct VSM_fantom vt; vsm = VSM_New(); AN(vsm); if (VSM_n_Arg(vsm, n_arg) < 0) { fprintf(stderr, "%s\n", VSM_Error(vsm)); VSM_Delete(vsm); return (-1); } if (VSM_Open(vsm)) { fprintf(stderr, "%s\n", VSM_Error(vsm)); VSM_Delete(vsm); return (-1); } if (!VSM_Get(vsm, &vt, "Arg", "-T", "")) { fprintf(stderr, "No -T arg in shared memory\n"); VSM_Delete(vsm); return (-1); } AN(vt.b); T_start = T_arg = strdup(vt.b); if (VSM_Get(vsm, &vt, "Arg", "-S", "")) { AN(vt.b); S_arg = strdup(vt.b); } VSM_Delete(vsm); sock = -1; while (*T_arg) { p = strchr(T_arg, '\n'); AN(p); *p = '\0'; sock = cli_sock(T_arg, S_arg); if (sock >= 0) break; T_arg = p + 1; } free(T_start); free(S_arg); return (sock); }
static void * varnishlog_thread(void *priv) { struct varnish *v; struct VSM_data *vsl; CAST_OBJ_NOTNULL(v, priv, VARNISH_MAGIC); vsl = VSM_New(); VSL_Setup(vsl); (void)VSL_Arg(vsl, 'n', v->workdir); VSL_NonBlocking(vsl, 1); while (v->pid && VSL_Open(vsl, 0) != 0) { assert(usleep(VSL_SLEEP_USEC) == 0 || errno == EINTR); } while (v->pid) { if (VSL_Dispatch(vsl, h_addlog, v) < 0) { assert(usleep(v->vsl_sleep) == 0 || errno == EINTR); v->vsl_sleep += v->vsl_sleep; if (v->vsl_sleep > VSL_SLEEP_USEC) v->vsl_sleep = VSL_SLEEP_USEC; } } VSM_Delete(vsl); return (NULL); }
static void * varnishlog_thread(void *priv) { struct varnish *v; struct VSM_data *vsl; CAST_OBJ_NOTNULL(v, priv, VARNISH_MAGIC); vsl = VSM_New(); (void)VSL_Arg(vsl, 'n', v->workdir); while (v->pid) { if (VSL_Dispatch(vsl, h_addlog, v) <= 0) usleep(100000); } VSM_Delete(vsl); return (NULL); }
static void varnish_delete(struct varnish *v) { CHECK_OBJ_NOTNULL(v, VARNISH_MAGIC); vtc_logclose(v->vl); free(v->name); free(v->workdir); if (v->vd != NULL) VSM_Delete(v->vd); /* * We do not delete the workdir, it may contain stuff people * want (coredumps, shmlog/stats etc), and trying to divine * "may want" is just too much trouble. Leave it around and * nuke it at the start of the next test-run. */ /* XXX: MEMLEAK (?) */ FREE_OBJ(v); }
void VUT_Fini(void) { free(VUT.n_arg); free(VUT.N_arg); free(VUT.r_arg); free(VUT.P_arg); free(VUT.name); vut_vpf_remove(); AZ(VUT.pfh); if (VUT.vslq) VSLQ_Delete(&VUT.vslq); if (VUT.vsl) VSL_Delete(VUT.vsl); if (VUT.vsm) VSM_Delete(VUT.vsm); memset(&VUT, 0, sizeof VUT); }
static int varnish_read (user_data_t *ud) /* {{{ */ { struct VSM_data *vd; const c_varnish_stats_t *stats; user_config_t *conf; if ((ud == NULL) || (ud->data == NULL)) return (EINVAL); conf = ud->data; vd = VSM_New(); #if HAVE_VARNISH_V3 VSC_Setup(vd); #endif if (conf->instance != NULL) { int status; status = VSM_n_Arg (vd, conf->instance); if (status < 0) { VSM_Delete (vd); ERROR ("varnish plugin: VSM_n_Arg (\"%s\") failed " "with status %i.", conf->instance, status); return (-1); } } #if HAVE_VARNISH_V3 if (VSC_Open (vd, /* diag = */ 1)) #else /* if HAVE_VARNISH_V4 */ if (VSM_Open (vd)) #endif { VSM_Delete (vd); ERROR ("varnish plugin: Unable to open connection."); return (-1); } #if HAVE_VARNISH_V3 stats = VSC_Main(vd); #else /* if HAVE_VARNISH_V4 */ stats = VSC_Main(vd, NULL); #endif if (!stats) { VSM_Delete (vd); ERROR ("varnish plugin: Unable to get statistics."); return (-1); } varnish_monitor (conf, stats); VSM_Delete (vd); return (0); } /* }}} */
static unsigned int vlog_reply(struct http_request *request, void *data) { struct vlog_req_priv vrp = { .limit = 10 }; int disp_status; char *p; char *tag = NULL; char *tag_re = NULL; struct VSL_data *vsl = NULL; struct VSLQ *vslq = NULL; struct VSL_cursor *c = NULL; enum VSL_grouping_e grouping = VSL_g_request; struct agent_core_t *core = data; p = next_slash(request->url + 1); if (p) { char *lim = strdup(p); assert(lim); char *tmp2 = strchr(lim, '/'); if (tmp2 && *tmp2) *tmp2 = '\0'; int j = sscanf(lim, "%u", &vrp.limit); if(j != 1) { free(lim); http_reply(request->connection, 500, "Not a number"); return 0; } free(lim); p = next_slash(p); } if (p) { tag = strdup(p); char *tmp2 = strchr(tag,'/'); if (tmp2 && *tmp2) *tmp2 = '\0'; p = next_slash(p); } if (p) { tag_re = strdup(p); char *tmp2 = strchr(tag_re, '/'); if (tmp2 && *tmp2) *tmp2 = '\0'; p = next_slash(p); } vrp.answer = VSB_new_auto(); assert(vrp.answer != NULL); vrp.vsm = VSM_New(); assert(vrp.vsm); if (!VSM_n_Arg(vrp.vsm, core->config->n_arg)) { VSB_printf(vrp.answer, "Error in creating shmlog: %s", VSM_Error(vrp.vsm)); VSB_finish(vrp.answer); http_reply(request->connection, 500, VSB_data(vrp.answer)); goto cleanup; } if (VSM_Open(vrp.vsm) != 0) { VSB_printf(vrp.answer, "Error in opening shmlog: %s", VSM_Error(vrp.vsm)); VSB_finish(vrp.answer); http_reply(request->connection, 500, VSB_data(vrp.answer)); goto cleanup; } vsl = VSL_New(); assert(vsl); if (tag) { grouping = VSL_g_raw; if (VSL_Arg(vsl, 'i', tag) < 0) { VSB_printf(vrp.answer, "Unable to specify tag '%s': %s", tag, VSL_Error(vsl)); VSB_finish(vrp.answer); http_reply(request->connection, 500, VSB_data(vrp.answer)); goto cleanup; } if (tag_re) { VSL_Arg(vsl,'I', tag_re); } } c = VSL_CursorVSM(vsl, vrp.vsm, VSL_COPT_BATCH | VSL_COPT_TAILSTOP); if (c == NULL) { VSB_printf(vrp.answer, "Can't open log (%s)", VSL_Error(vsl)); VSB_finish(vrp.answer); http_reply(request->connection, 500, VSB_data(vrp.answer)); goto cleanup; } vslq = VSLQ_New(vsl, &c, grouping, NULL); if (vslq == NULL) { VSB_clear(vrp.answer); VSB_printf(vrp.answer, "Error in creating query: %s", VSL_Error(vsl)); http_reply(request->connection, 500, VSB_data(vrp.answer)); goto cleanup; } VSB_printf(vrp.answer, "{ \"log\": ["); do { disp_status = VSLQ_Dispatch(vslq, vlog_cb_func, &vrp); } while (disp_status == 1 && vrp.entries < vrp.limit); VSB_printf(vrp.answer, "\n] }\n"); assert(VSB_finish(vrp.answer) == 0); if (VSB_len(vrp.answer) > 1) { struct http_response *resp = http_mkresp(request->connection, 200, NULL); resp->data = VSB_data(vrp.answer); resp->ndata = VSB_len(vrp.answer); http_add_header(resp,"Content-Type","application/json"); send_response(resp); http_free_resp(resp); } else { http_reply(request->connection, 500, "FAIL"); } cleanup: free(tag); free(tag_re); VSB_delete(vrp.answer); if (vslq) VSLQ_Delete(&vslq); if (vsl) VSL_Delete(vsl); if (vrp.vsm) VSM_Delete(vrp.vsm); vrp.answer = NULL; return 0; } void vlog_init(struct agent_core_t *core) { struct agent_plugin_t *plug; struct vlog_priv_t *priv; ALLOC_OBJ(priv); plug = plugin_find(core,"vlog"); plug->data = priv; http_register_url(core, "/log", M_GET, vlog_reply, core); }
static unsigned int vlog_reply(struct http_request *request, void *data) { struct vlog_priv_t *vlog; int ret; char *limit = NULL; char *p; char *tag = NULL; char *itag = NULL; struct agent_core_t *core = data; GET_PRIV(data,vlog); p = next_slash(request->url + 1); assert(vlog->tag==NULL); assert(vlog->answer == NULL); if (p) { limit = strdup(p); assert(limit); char *tmp2 = index(limit,'/'); if (tmp2 && *tmp2) *tmp2 = '\0'; if(!(atoi(limit) > 0)) { free(limit); send_response_fail(request->connection,"Not a number"); return 0; } p = next_slash(p); } if (p) { tag = strdup(p); char *tmp2 = index(tag,'/'); if (tmp2 && *tmp2) *tmp2 = '\0'; p = next_slash(p); } if (p) { itag = strdup(p); char *tmp2 = index(itag,'/'); if (tmp2 && *tmp2) *tmp2 = '\0'; p = next_slash(p); } vlog->answer = VSB_new_auto(); assert(vlog->answer != NULL); vlog->vd = VSM_New(); assert(VSL_Arg(vlog->vd, 'n', core->config->n_arg)); VSL_Setup(vlog->vd); VSL_Arg(vlog->vd, 'd', ""); if (tag) { VSL_Arg(vlog->vd, 'i', tag); if (itag) VSL_Arg(vlog->vd,'I',itag); } else { VSL_Arg(vlog->vd, 'k', limit ? limit : "10"); } if (limit) free(limit); VSB_printf(vlog->answer, "{ \"log\": ["); ret = VSL_Open(vlog->vd, 1); if (ret) { send_response_fail(request->connection, "Error in opening shmlog"); goto cleanup; } if (tag == NULL) { do_order(vlog); } else { do_unorder(vlog); } VSB_printf(vlog->answer, "\n] }\n"); assert(VSB_finish(vlog->answer) == 0); if (VSB_len(vlog->answer) > 1) { struct http_response *resp = http_mkresp(request->connection, 200, NULL); resp->data = VSB_data(vlog->answer); resp->ndata = VSB_len(vlog->answer); http_add_header(resp,"Content-Type","application/json"); send_response2(resp); http_free_resp(resp); } else { send_response_fail(request->connection, "FAIL"); } cleanup: free(tag); free(itag); VSB_clear(vlog->answer); VSB_delete(vlog->answer); VSM_Delete(vlog->vd); vlog->answer = NULL; vlog->entries = 0; return 0; }