void cmd_delay(CMD_ARGS) { double f; (void)priv; (void)cmd; if (av == NULL) return; AN(av[1]); AZ(av[2]); f = strtod(av[1], NULL); vtc_log(vl, 3, "delaying %g second(s)", f); VTIM_sleep(f); }
static void * vwe_timeout_idle_ticker(void *priv) { char ticker = 'R'; struct vwe *vwe; CAST_OBJ_NOTNULL(vwe, priv, VWE_MAGIC); THR_SetName("cache-epoll-timeout_idle_ticker"); while (1) { /* ticking */ assert(write(vwe->timer_pipes[1], &ticker, 1)); VTIM_sleep(100 * 1e-3); } return (NULL); }
static struct objcore * ban_lurker_getfirst(struct vsl_log *vsl, struct ban *bt) { struct objhead *oh; struct objcore *oc; while (1) { Lck_Lock(&ban_mtx); oc = VTAILQ_FIRST(&bt->objcore); CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC); if (oc == &oc_marker) { VTAILQ_REMOVE(&bt->objcore, oc, ban_list); Lck_Unlock(&ban_mtx); return (NULL); } oh = oc->objhead; CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC); if (!Lck_Trylock(&oh->mtx)) { if (oc->refcnt == 0) { Lck_Unlock(&oh->mtx); } else { /* * We got the lock, and the oc is not being * dismantled under our feet. * Take it off the ban and (optimistically) * put it on the * destination ban */ AZ(oc->flags & OC_F_BUSY); oc->refcnt += 1; VTAILQ_REMOVE(&bt->objcore, oc, ban_list); VTAILQ_INSERT_TAIL(&bt->objcore, oc, ban_list); Lck_Unlock(&oh->mtx); Lck_Unlock(&ban_mtx); break; } } /* Try again, later */ Lck_Unlock(&ban_mtx); VSC_C_main->bans_lurker_contention++; VSL_Flush(vsl, 0); VTIM_sleep(cache_param->ban_lurker_sleep); } return (oc); }
static void* cooldown_thread(void *priv) { struct vrt_ctx ctx; struct priv_vcl *priv_vcl; CAST_OBJ_NOTNULL(priv_vcl, priv, PRIV_VCL_MAGIC); AN(priv_vcl->vcl); AN(priv_vcl->vclref); INIT_OBJ(&ctx, VRT_CTX_MAGIC); ctx.vcl = priv_vcl->vcl; VTIM_sleep(vcl_release_delay); VRT_rel_vcl(&ctx, &priv_vcl->vclref); priv_vcl->vcl = NULL; return (NULL); }
static void tst_delta() { double m_begin, m_end; double r_begin, r_end; const double ref = 1; int err = 0; r_begin = VTIM_real(); m_begin = VTIM_mono(); VTIM_sleep(ref); r_end = VTIM_real(); m_end = VTIM_mono(); err += tst_delta_check("VTIM_mono", m_begin, m_end, ref); err += tst_delta_check("VTIM_real", r_begin, r_end, ref); if (err) { printf("%d time delta test errrors\n", err); exit(4); } }
static void * mpl_guard(void *priv) { struct mempool *mpl; struct memitem *mi = NULL; double mpl_slp __state_variable__(mpl_slp); double last = 0; CAST_OBJ_NOTNULL(mpl, priv, MEMPOOL_MAGIC); mpl_slp = 0.15; // random while (1) { VTIM_sleep(mpl_slp); mpl_slp = 0.814; // random mpl->t_now = VTIM_real(); if (mi != NULL && (mpl->n_pool > mpl->param->max_pool || mi->size < *mpl->cur_size)) { FREE_OBJ(mi); mi = NULL; } if (mi == NULL && mpl->n_pool < mpl->param->min_pool) mi = mpl_alloc(mpl); if (mpl->n_pool < mpl->param->min_pool && mi != NULL) { /* can do */ } else if (mpl->n_pool > mpl->param->max_pool && mi == NULL) { /* can do */ } else if (!VTAILQ_EMPTY(&mpl->surplus)) { /* can do */ } else if (last + .1 * mpl->param->max_age < mpl->t_now) { /* should do */ } else if (mpl->self_destruct) { /* can do */ } else { continue; /* nothing to do */ } mpl_slp = 0.314; // random if (Lck_Trylock(&mpl->mtx)) continue; if (mpl->self_destruct) { AZ(mpl->live); while (1) { if (mi == NULL) { mi = VTAILQ_FIRST(&mpl->list); if (mi != NULL) { mpl->vsc->pool = --mpl->n_pool; VTAILQ_REMOVE(&mpl->list, mi, list); } } if (mi == NULL) { mi = VTAILQ_FIRST(&mpl->surplus); if (mi != NULL) VTAILQ_REMOVE(&mpl->surplus, mi, list); } if (mi == NULL) break; FREE_OBJ(mi); mi = NULL; } VSM_Free(mpl->vsc); Lck_Unlock(&mpl->mtx); Lck_Delete(&mpl->mtx); FREE_OBJ(mpl); break; } if (mpl->n_pool < mpl->param->min_pool && mi != NULL && mi->size >= *mpl->cur_size) { CHECK_OBJ_NOTNULL(mi, MEMITEM_MAGIC); mpl->vsc->pool = ++mpl->n_pool; mi->touched = mpl->t_now; VTAILQ_INSERT_HEAD(&mpl->list, mi, list); mi = NULL; mpl_slp = .01; // random } if (mpl->n_pool > mpl->param->max_pool && mi == NULL) { mi = VTAILQ_FIRST(&mpl->list); CHECK_OBJ_NOTNULL(mi, MEMITEM_MAGIC); mpl->vsc->pool = --mpl->n_pool; mpl->vsc->surplus++; VTAILQ_REMOVE(&mpl->list, mi, list); mpl_slp = .01; // random } if (mi == NULL) { mi = VTAILQ_FIRST(&mpl->surplus); if (mi != NULL) { CHECK_OBJ_NOTNULL(mi, MEMITEM_MAGIC); VTAILQ_REMOVE(&mpl->surplus, mi, list); mpl_slp = .01; // random } } if (mi == NULL && mpl->n_pool > mpl->param->min_pool) { mi = VTAILQ_LAST(&mpl->list, memhead_s); CHECK_OBJ_NOTNULL(mi, MEMITEM_MAGIC); if (mi->touched + mpl->param->max_age < mpl->t_now) { mpl->vsc->pool = --mpl->n_pool; mpl->vsc->timeout++; VTAILQ_REMOVE(&mpl->list, mi, list); mpl_slp = .01; // random } else { mi = NULL; last = mpl->t_now; } } else if (mpl->n_pool <= mpl->param->min_pool) { last = mpl->t_now; } Lck_Unlock(&mpl->mtx); if (mi != NULL) { FREE_OBJ(mi); mi = NULL; } } return (NULL); }
vmod_sleep(VRT_CTX, VCL_DURATION t) { CHECK_OBJ_ORNULL(ctx, VRT_CTX_MAGIC); VTIM_sleep(t); }
static void* pool_herder(void *priv) { struct pool *pp; struct pool_task *pt; double t_idle; struct worker *wrk; CAST_OBJ_NOTNULL(pp, priv, POOL_MAGIC); while (1) { /* Make more threads if needed and allowed */ if (pp->nthr < cache_param->wthread_min || (pp->dry && pp->nthr < cache_param->wthread_max)) { pool_breed(pp); continue; } assert(pp->nthr >= cache_param->wthread_min); if (pp->nthr > cache_param->wthread_min) { t_idle = VTIM_real() - cache_param->wthread_timeout; Lck_Lock(&pp->mtx); /* XXX: unsafe counters */ VSC_C_main->sess_queued += pp->nqueued; VSC_C_main->sess_dropped += pp->ndropped; pp->nqueued = pp->ndropped = 0; wrk = NULL; pt = VTAILQ_LAST(&pp->idle_queue, taskhead); if (pt != NULL) { AZ(pt->func); CAST_OBJ_NOTNULL(wrk, pt->priv, WORKER_MAGIC); if (wrk->lastused < t_idle || pp->nthr > cache_param->wthread_max) { /* Give it a kiss on the cheek... */ VTAILQ_REMOVE(&pp->idle_queue, &wrk->task, list); wrk->task.func = pool_kiss_of_death; AZ(pthread_cond_signal(&wrk->cond)); } else wrk = NULL; } Lck_Unlock(&pp->mtx); if (wrk != NULL) { pp->nthr--; Lck_Lock(&pool_mtx); VSC_C_main->threads--; VSC_C_main->threads_destroyed++; Lck_Unlock(&pool_mtx); VTIM_sleep(cache_param->wthread_destroy_delay); continue; } } Lck_Lock(&pp->mtx); if (!pp->dry) { (void)Lck_CondWait(&pp->herder_cond, &pp->mtx, VTIM_real() + 5); } else { /* XXX: unsafe counters */ VSC_C_main->threads_limited++; pp->dry = 0; } Lck_Unlock(&pp->mtx); } NEEDLESS_RETURN(NULL); }
static void ban_lurker_test_ban(struct worker *wrk, struct vsl_log *vsl, struct ban *bt, struct banhead_s *obans, struct ban *bd) { struct ban *bl, *bln; struct objcore *oc; unsigned tests; int i; /* * First see if there is anything to do, and if so, insert marker */ Lck_Lock(&ban_mtx); oc = VTAILQ_FIRST(&bt->objcore); if (oc != NULL) VTAILQ_INSERT_TAIL(&bt->objcore, &oc_marker, ban_list); Lck_Unlock(&ban_mtx); if (oc == NULL) return; while (1) { if (++ban_batch > cache_param->ban_lurker_batch) { VTIM_sleep(cache_param->ban_lurker_sleep); ban_batch = 0; } oc = ban_lurker_getfirst(vsl, bt); if (oc == NULL) return; i = 0; VTAILQ_FOREACH_REVERSE_SAFE(bl, obans, banhead_s, l_list, bln) { if (bl->flags & BANS_FLAG_COMPLETED) { /* Ban was overtaken by new (dup) ban */ VTAILQ_REMOVE(obans, bl, l_list); continue; } tests = 0; i = ban_evaluate(wrk, bl->spec, oc, NULL, &tests); VSC_C_main->bans_lurker_tested++; VSC_C_main->bans_lurker_tests_tested += tests; if (i) break; } if (i) { VSLb(vsl, SLT_ExpBan, "%u banned by lurker", ObjGetXID(wrk, oc)); EXP_Rearm(oc, oc->exp.t_origin, 0, 0, 0); // XXX ^ fake now VSC_C_main->bans_lurker_obj_killed++; } else { if (oc->ban != bd) { Lck_Lock(&ban_mtx); oc->ban->refcount--; VTAILQ_REMOVE(&oc->ban->objcore, oc, ban_list); oc->ban = bd; bd->refcount++; VTAILQ_INSERT_TAIL(&bd->objcore, oc, ban_list); Lck_Unlock(&ban_mtx); ObjUpdateMeta(wrk, oc); } } (void)HSH_DerefObjCore(wrk, &oc); } }
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 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); }