예제 #1
0
static void *
wrk_thread_real(void *priv, unsigned thread_workspace)
{
	struct worker *w, ww;
	unsigned char ws[thread_workspace];

	THR_SetName("cache-worker");
	w = &ww;
	memset(w, 0, sizeof *w);
	w->magic = WORKER_MAGIC;
	w->lastused = NAN;
	AZ(pthread_cond_init(&w->cond, NULL));

	WS_Init(w->aws, "wrk", ws, thread_workspace);

	VSL(SLT_WorkThread, 0, "%p start", w);

	Pool_Work_Thread(priv, w);
	AZ(w->pool);

	VSL(SLT_WorkThread, 0, "%p end", w);
	if (w->vcl != NULL)
		VCL_Rel(&w->vcl);
	AZ(pthread_cond_destroy(&w->cond));
	if (w->nvbo != NULL)
		VBO_Free(&w->nvbo);
	HSH_Cleanup(w);
	WRK_SumStat(w);
	return (NULL);
}
static void *
exp_timer(struct sess *sp, void *priv)
{
	struct objcore *oc;
	struct object *o;
	double t;
	struct objcore_head *lru;

	(void)priv;
	AZ(sleep(10));		/* XXX: Takes time for VCL to arrive */
	VCL_Get(&sp->vcl);
	t = TIM_real();
	while (1) {
		Lck_Lock(&exp_mtx);
		oc = binheap_root(exp_heap);
		CHECK_OBJ_ORNULL(oc, OBJCORE_MAGIC);
		if (oc == NULL || oc->timer_when > t) { /* XXX: > or >= ? */
			Lck_Unlock(&exp_mtx);
			WSL_Flush(sp->wrk, 0);
			WRK_SumStat(sp->wrk);
			AZ(sleep(1));
			VCL_Refresh(&sp->vcl);
			t = TIM_real();
			continue;
		}

		o = oc->obj;
		CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
		CHECK_OBJ_NOTNULL(o->objhead, OBJHEAD_MAGIC);
		assert(oc->flags & OC_F_ONLRU);
		assert(oc->timer_idx != BINHEAP_NOIDX);
		binheap_delete(exp_heap, oc->timer_idx);
		assert(oc->timer_idx == BINHEAP_NOIDX);
		lru = STV_lru(o->objstore);
		AN(lru);
		VTAILQ_REMOVE(lru, o->objcore, lru_list);
		oc->flags &= ~OC_F_ONLRU;

		{	/* Sanity checking */
			struct objcore *oc2 = binheap_root(exp_heap);
			if (oc2 != NULL) {
				assert(oc2->timer_idx != BINHEAP_NOIDX);
				assert(oc2->timer_when >= oc->timer_when);
			}
		}

		VSL_stats->n_expired++;
		Lck_Unlock(&exp_mtx);
		WSL(sp->wrk, SLT_ExpKill, 0, "%u %d",
		    o->xid, (int)(o->ttl - t));
		HSH_Deref(sp->wrk, &o);
	}
}
예제 #3
0
static void *
wrk_thread_real(void *priv, unsigned shm_workspace, unsigned sess_workspace,
    uint16_t nhttp, unsigned http_space, unsigned siov)
{
	struct worker *w, ww;
	uint32_t wlog[shm_workspace / 4];
	/* XXX: can we trust these to be properly aligned ? */
	unsigned char ws[sess_workspace];
	unsigned char http0[http_space];
	unsigned char http1[http_space];
	unsigned char http2[http_space];
	struct iovec iov[siov];
	struct SHA256Context sha256;

	THR_SetName("cache-worker");
	w = &ww;
	memset(w, 0, sizeof *w);
	w->magic = WORKER_MAGIC;
	w->lastused = NAN;
	w->wlb = w->wlp = wlog;
	w->wle = wlog + (sizeof wlog) / 4;
	w->sha256ctx = &sha256;
	w->bereq = HTTP_create(http0, nhttp);
	w->beresp = HTTP_create(http1, nhttp);
	w->resp = HTTP_create(http2, nhttp);
	w->wrw.iov = iov;
	w->wrw.siov = siov;
	w->wrw.ciov = siov;
	AZ(pthread_cond_init(&w->cond, NULL));

	WS_Init(w->ws, "wrk", ws, sess_workspace);

	VSL(SLT_WorkThread, 0, "%p start", w);

	Pool_Work_Thread(priv, w);
	AZ(w->pool);

	VSL(SLT_WorkThread, 0, "%p end", w);
	if (w->vcl != NULL)
		VCL_Rel(&w->vcl);
	AZ(pthread_cond_destroy(&w->cond));
	HSH_Cleanup(w);
	WRK_SumStat(w);
	return (NULL);
}
예제 #4
0
static int
cnt_done(struct sess *sp)
{
    double dh, dp, da;
    int i;
    struct worker *wrk;

    CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
    wrk = sp->wrk;
    CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
    CHECK_OBJ_ORNULL(sp->vcl, VCL_CONF_MAGIC);

    AZ(wrk->obj);
    AZ(wrk->busyobj);
    sp->director = NULL;
    sp->restarts = 0;

    wrk->busyobj = NULL;

    SES_Charge(sp);

    /* If we did an ESI include, don't mess up our state */
    if (sp->esi_level > 0)
        return (1);

    if (sp->vcl != NULL) {
        if (wrk->vcl != NULL)
            VCL_Rel(&wrk->vcl);
        wrk->vcl = sp->vcl;
        sp->vcl = NULL;
    }


    sp->t_end = W_TIM_real(wrk);
    WSP(sp, SLT_Debug, "PHK req %.9f resp %.9f end %.9f open %.9f",
        sp->t_req, sp->t_resp, sp->t_end,  sp->t_open);
    if (sp->xid == 0) {
        // sp->t_req = sp->t_end;
        sp->t_resp = sp->t_end;
    } else {
        dp = sp->t_resp - sp->t_req;
        da = sp->t_end - sp->t_resp;
        dh = sp->t_req - sp->t_open;
        /* XXX: Add StatReq == StatSess */
        /* XXX: Workaround for pipe */
        if (sp->fd >= 0) {
            WSP(sp, SLT_Length, "%ju",
                (uintmax_t)sp->req_bodybytes);
        }
        WSP(sp, SLT_ReqEnd, "%u %.9f %.9f %.9f %.9f %.9f",
            sp->xid, sp->t_req, sp->t_end, dh, dp, da);
    }
    sp->xid = 0;
    WSL_Flush(wrk, 0);

    sp->t_open = sp->t_end;
    sp->t_resp = NAN;

    sp->req_bodybytes = 0;

    sp->t_req = NAN;
    sp->hash_always_miss = 0;
    sp->hash_ignore_busy = 0;

    if (sp->fd >= 0 && sp->doclose != NULL) {
        /*
         * This is an orderly close of the connection; ditch nolinger
         * before we close, to get queued data transmitted.
         */
        // XXX: not yet (void)VTCP_linger(sp->fd, 0);
        SES_Close(sp, sp->doclose);
    }

    if (sp->fd < 0) {
        wrk->stats.sess_closed++;
        SES_Delete(sp, NULL);
        return (1);
    }

    if (wrk->stats.client_req >= cache_param->wthread_stats_rate)
        WRK_SumStat(wrk);
    /* Reset the workspace to the session-watermark */
    WS_Reset(sp->ws, sp->ws_ses);
    WS_Reset(wrk->ws, NULL);

    i = HTC_Reinit(sp->htc);
    if (i == 1) {
        wrk->stats.sess_pipeline++;
        sp->step = STP_START;
        return (0);
    }
    if (Tlen(sp->htc->rxbuf)) {
        wrk->stats.sess_readahead++;
        sp->step = STP_WAIT;
        return (0);
    }
    if (cache_param->session_linger > 0) {
        wrk->stats.sess_linger++;
        sp->step = STP_WAIT;
        return (0);
    }
    wrk->stats.sess_herd++;
    Pool_Wait(sp);
    return (1);
}