int VUT_g_Arg(const char *arg) { VUT.g_arg = VSLQ_Name2Grouping(arg, -1); if (VUT.g_arg == -2) VUT_Error(1, "Ambiguous grouping type: %s", arg); else if (VUT.g_arg < 0) VUT_Error(1, "Unknown grouping type: %s", arg); return (1); }
static void openout(int append) { AN(LOG.w_arg); if (LOG.B_opt) LOG.fo = VSL_WriteOpen(VUT.vsl, LOG.w_arg, append, 0); else LOG.fo = fopen(LOG.w_arg, append ? "a" : "w"); if (LOG.fo == NULL) VUT_Error(1, "Can't open output file (%s)", LOG.B_opt ? VSL_Error(VUT.vsl) : strerror(errno)); VUT.dispatch_priv = LOG.fo; }
int main(int argc, char **argv) { int i; const char *colon, *ptag; const char *profile = "responsetime"; pthread_t thr; int fnum = -1; struct profile cli_p = {0}; cli_p.name = 0; VUT_Init(progname, argc, argv, &vopt_spec); AZ(pthread_cond_init(&timebend_cv, NULL)); while ((i = getopt(argc, argv, vopt_spec.vopt_optstring)) != -1) { switch (i) { case 'h': /* Usage help */ usage(0); case 'p': delay = strtod(optarg, NULL); if (delay <= 0) VUT_Error(1, "-p: invalid '%s'", optarg); break; case 'P': colon = strchr(optarg, ':'); /* no colon, take the profile as a name */ if (colon == NULL) { profile = optarg; break; } /* else it's a definition, we hope */ if (colon == optarg + 1 && (*optarg == 'b' || *optarg == 'c')) { cli_p.VSL_arg = *optarg; ptag = colon + 1; colon = strchr(colon + 1, ':'); if (colon == NULL) profile_error(optarg); } else { ptag = optarg; cli_p.VSL_arg = 'c'; } assert(colon); if (sscanf(colon + 1, "%d:%d:%d", &cli_p.field, &cli_p.hist_low, &cli_p.hist_high) != 3) profile_error(optarg); match_tag = VSL_Name2Tag(ptag, colon - ptag); if (match_tag < 0) VUT_Error(1, "-P: '%s' is not a valid tag name", optarg); cli_p.name = "custom"; cli_p.tag = match_tag; profile = NULL; active_profile = &cli_p; break; case 'B': timebend = strtod(optarg, NULL); if (timebend == 0) VUT_Error(1, "-B: being able to bend time does not" " mean we can stop it" " (invalid factor '%s')", optarg); if (timebend < 0) VUT_Error(1, "-B: being able to bend time does not" " mean we can make it go backwards" " (invalid factor '%s')", optarg); break; default: if (!VUT_Arg(i, optarg)) usage(1); } } if (optind != argc) usage(1); /* Check for valid grouping mode */ assert(VUT.g_arg < VSL_g__MAX); if (VUT.g_arg != VSL_g_vxid && VUT.g_arg != VSL_g_request) VUT_Error(1, "Invalid grouping mode: %s" " (only vxid and request are supported)", VSLQ_grouping[VUT.g_arg]); if (profile) { for (active_profile = profiles; active_profile->name; active_profile++) { if (strcmp(active_profile->name, profile) == 0) break; } } AN(active_profile); if (!active_profile->name) VUT_Error(1, "-P: No such profile '%s'", profile); assert(VUT_Arg(active_profile->VSL_arg, NULL)); match_tag = active_profile->tag; fnum = active_profile->field; hist_low = active_profile->hist_low; hist_high = active_profile->hist_high; hist_range = hist_high - hist_low; hist_buckets = hist_range * HIST_RES; bucket_hit = calloc(sizeof *bucket_hit, hist_buckets); bucket_miss = calloc(sizeof *bucket_miss, hist_buckets); if (timebend > 0) t0 = VTIM_mono(); format = malloc(4L * fnum); AN(format); for (i = 0; i < fnum - 1; i++) strcpy(format + 4 * i, "%*s "); strcpy(format + 4 * (fnum - 1), "%lf"); log_ten = log(10.0); VUT_Setup(); if (pthread_create(&thr, NULL, do_curses, NULL) != 0) VUT_Error(1, "pthread_create(): %s", strerror(errno)); VUT.dispatch_f = accumulate; VUT.dispatch_priv = NULL; VUT.sighup_f = sighup; VUT_Main(); end_of_file = 1; AZ(pthread_join(thr, NULL)); VUT_Fini(); exit(0); }
int VUT_Main(void) { struct VSL_cursor *c; int i = -1; AN(VUT.vslq); while (!VUT.sigint) { if (VUT.sighup && VUT.sighup_f) { /* sighup callback */ VUT.sighup = 0; i = (VUT.sighup_f)(); if (i) break; } if (VUT.sigusr1) { /* Flush and report any incomplete records */ VUT.sigusr1 = 0; VSLQ_Flush(VUT.vslq, vut_dispatch, NULL); } if (VUT.vsm != NULL && !VSM_IsOpen(VUT.vsm)) { /* Reconnect VSM */ AZ(VUT.r_arg); VTIM_sleep(0.1); if (VSM_Open(VUT.vsm)) { VSM_ResetError(VUT.vsm); continue; } c = VSL_CursorVSM(VUT.vsl, VUT.vsm, VSL_COPT_TAIL | VSL_COPT_BATCH); if (c == NULL) { VSL_ResetError(VUT.vsl); VSM_Close(VUT.vsm); continue; } VSLQ_SetCursor(VUT.vslq, &c); AZ(c); VUT_Error(0, "Log reacquired"); } i = VSLQ_Dispatch(VUT.vslq, vut_dispatch, NULL); if (i == 1) /* Call again */ continue; else if (i == 0) { /* Nothing to do but wait */ if (VUT.idle_f) { i = (VUT.idle_f)(); if (i) break; } VTIM_sleep(0.01); continue; } else if (i == -1) { /* EOF */ break; } if (VUT.vsm == NULL) break; /* XXX: Make continuation optional */ VSLQ_Flush(VUT.vslq, vut_dispatch, NULL); if (i == -2) /* Abandoned */ VUT_Error(0, "Log abandoned"); else if (i < -2) /* Overrun */ VUT_Error(0, "Log overrun"); VSM_Close(VUT.vsm); } return (i); }
void VUT_Setup(void) { struct VSL_cursor *c; double t_start; int i; AN(VUT.vsl); AZ(VUT.vsm); AZ(VUT.vslq); /* Check input arguments */ if ((VUT.n_arg == NULL ? 0 : 1) + (VUT.N_arg == NULL ? 0 : 1) + (VUT.r_arg == NULL ? 0 : 1) > 1) VUT_Error(1, "Only one of -n, -N and -r options may be used"); /* Create and validate the query expression */ VUT.vslq = VSLQ_New(VUT.vsl, NULL, VUT.g_arg, VUT.q_arg); if (VUT.vslq == NULL) VUT_Error(1, "Query expression error:\n%s", VSL_Error(VUT.vsl)); /* Setup input */ if (VUT.r_arg) { REPLACE(VUT.name, VUT.r_arg); c = VSL_CursorFile(VUT.vsl, VUT.r_arg, 0); if (c == NULL) VUT_Error(1, "Can't open log file (%s)", VSL_Error(VUT.vsl)); } else { VUT.vsm = VSM_New(); AN(VUT.vsm); if (VUT.n_arg && VSM_n_Arg(VUT.vsm, VUT.n_arg) <= 0) VUT_Error(1, "%s", VSM_Error(VUT.vsm)); if (VUT.N_arg && VSM_N_Arg(VUT.vsm, VUT.N_arg) <= 0) VUT_Error(1, "%s", VSM_Error(VUT.vsm)); REPLACE(VUT.name, VSM_Name(VUT.vsm)); t_start = NAN; c = NULL; while (1) { i = VSM_Open(VUT.vsm); if (!i) c = VSL_CursorVSM(VUT.vsl, VUT.vsm, (VUT.d_opt ? VSL_COPT_TAILSTOP : VSL_COPT_TAIL) | VSL_COPT_BATCH); if (c) break; if (isnan(t_start) && VUT.t_arg > 0.) { VUT_Error(0, "Can't open log -" " retrying for %.0f seconds", VUT.t_arg); t_start = VTIM_real(); } VSM_Close(VUT.vsm); if (VUT.t_arg <= 0.) break; if (VTIM_real() - t_start > VUT.t_arg) break; VSM_ResetError(VUT.vsm); VSL_ResetError(VUT.vsl); VTIM_sleep(0.5); } if (VUT.t_arg >= 0. && (i || !c)) { if (i) VUT_Error(1, "Can't open VSM file (%s)", VSM_Error(VUT.vsm)); else VUT_Error(1, "Can't open log (%s)", VSL_Error(VUT.vsl)); } else if (!isnan(t_start)) VUT_Error(0, "Log opened"); } if (c) VSLQ_SetCursor(VUT.vslq, &c); AZ(c); /* Signal handlers */ (void)signal(SIGHUP, vut_sighup); (void)signal(SIGINT, vut_sigint); (void)signal(SIGTERM, vut_sigint); (void)signal(SIGUSR1, vut_sigusr1); /* Open PID file */ if (VUT.P_arg) { AZ(VUT.pfh); VUT.pfh = VPF_Open(VUT.P_arg, 0644, NULL); if (VUT.pfh == NULL) VUT_Error(1, "%s: %s", VUT.P_arg, strerror(errno)); } /* Daemon mode */ if (VUT.D_opt && varnish_daemon(0, 0) == -1) VUT_Error(1, "Daemon mode: %s", strerror(errno)); /* Write PID and setup exit handler */ if (VUT.pfh != NULL) { VPF_Write(VUT.pfh); AZ(atexit(vut_vpf_remove)); } }
int VUT_Arg(int opt, const char *arg) { int i; char *p; switch (opt) { case 'd': /* Head */ VUT.d_opt = 1; return (1); case 'D': /* Daemon mode */ VUT.D_opt = 1; return (1); case 'g': /* Grouping */ return (VUT_g_Arg(arg)); case 'k': /* Log transaction limit */ VUT.k_arg = (int)strtol(arg, &p, 10); if (*p != '\0' || VUT.k_arg <= 0) VUT_Error(1, "-k: Invalid number '%s'", arg); return (1); case 'n': /* Varnish instance name */ REPLACE(VUT.n_arg, arg); return (1); case 'N': /* Varnish stale VSM file */ REPLACE(VUT.N_arg, arg); return (1); case 'P': /* PID file */ REPLACE(VUT.P_arg, arg); return (1); case 'q': /* Query to use */ REPLACE(VUT.q_arg, arg); return (1); case 'r': /* Binary file input */ REPLACE(VUT.r_arg, arg); return (1); case 't': /* VSM connect timeout */ if (!strcasecmp("off", arg)) VUT.t_arg = -1.; else { VUT.t_arg = VNUM(arg); if (isnan(VUT.t_arg)) VUT_Error(1, "-t: Syntax error"); if (VUT.t_arg < 0.) VUT_Error(1, "-t: Range error"); } return (1); case 'V': /* Print version number and exit */ VCS_Message(VUT.progname); exit(0); default: AN(VUT.vsl); i = VSL_Arg(VUT.vsl, opt, arg); if (i < 0) VUT_Error(1, "%s", VSL_Error(VUT.vsl)); return (i); } }
int main(int argc, char * const *argv) { int opt; VUT_Init(progname, argc, argv, &vopt_spec); memset(&LOG, 0, sizeof LOG); while ((opt = getopt(argc, argv, vopt_spec.vopt_optstring)) != -1) { switch (opt) { case 'a': /* Append to file */ LOG.a_opt = 1; break; case 'A': /* Text output */ LOG.A_opt = 1; break; case 'h': /* Usage help */ usage(0); break; case 'w': /* Write to file */ REPLACE(LOG.w_arg, optarg); break; default: if (!VUT_Arg(opt, optarg)) usage(1); } } if (optind != argc) usage(1); if (VUT.D_opt && !LOG.w_arg) VUT_Error(1, "Missing -w option"); /* Setup output */ if (LOG.A_opt || !LOG.w_arg) VUT.dispatch_f = VSL_PrintTransactions; else VUT.dispatch_f = VSL_WriteTransactions; VUT.sighup_f = sighup; if (LOG.w_arg) { openout(LOG.a_opt); AN(LOG.fo); if (VUT.D_opt) VUT.sighup_f = rotateout; } else LOG.fo = stdout; VUT.idle_f = flushout; VUT_Setup(); VUT_Main(); VUT_Fini(); (void)flushout(); exit(0); }
int main(int argc, char * const *argv) { struct VSM_data *vd; double t_arg = 5.0, t_start = NAN; int once = 0, xml = 0, json = 0, f_list = 0, curses = 0; signed char opt; int i; VUT_Init(progname, argc, argv, &vopt_spec); vd = VSM_New(); AN(vd); while ((opt = getopt(argc, argv, vopt_spec.vopt_optstring)) != -1) { switch (opt) { case '1': once = 1; break; case 'h': /* Usage help */ usage(0); case 'l': f_list = 1; break; case 't': if (!strcasecmp(optarg, "off")) t_arg = -1.; else { t_arg = VNUM(optarg); if (isnan(t_arg)) VUT_Error(1, "-t: Syntax error"); if (t_arg < 0.) VUT_Error(1, "-t: Range error"); } break; case 'V': VCS_Message("varnishstat"); exit(0); case 'x': xml = 1; break; case 'j': json = 1; break; default: i = VSC_Arg(vd, opt, optarg); if (i < 0) VUT_Error(1, "%s", VSM_Error(vd)); if (!i) usage(1); } } if (optind != argc) usage(1); if (!(xml || json || once || f_list)) curses = 1; while (1) { i = VSM_Open(vd); if (!i) break; if (isnan(t_start) && t_arg > 0.) { fprintf(stderr, "Can't open log -" " retrying for %.0f seconds\n", t_arg); t_start = VTIM_real(); } if (t_arg <= 0.) break; if (VTIM_real() - t_start > t_arg) break; VSM_ResetError(vd); VTIM_sleep(0.5); } if (curses) { if (i && t_arg >= 0.) VUT_Error(1, "%s", VSM_Error(vd)); do_curses(vd, 1.0); exit(0); } if (i) VUT_Error(1, "%s", VSM_Error(vd)); if (xml) do_xml(vd); else if (json) do_json(vd); else if (once) do_once(vd); else if (f_list) list_fields(vd); else assert(0); exit(0); }