Exemplo n.º 1
0
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);
}
Exemplo n.º 2
0
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);
}
Exemplo n.º 4
0
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);
}
Exemplo n.º 5
0
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);
	}
}
Exemplo n.º 6
0
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);
}
Exemplo n.º 7
0
vmod_sleep(VRT_CTX, VCL_DURATION t)
{

    CHECK_OBJ_ORNULL(ctx, VRT_CTX_MAGIC);
    VTIM_sleep(t);
}
Exemplo n.º 8
0
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);
	}
}
Exemplo n.º 10
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);
}
Exemplo n.º 11
0
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));
	}
}
Exemplo n.º 12
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);
}