Ejemplo n.º 1
0
static enum req_fsm_nxt
cnt_fetch(struct worker *wrk, struct req *req)
{

	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
	CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
	AZ(req->obj);

	req->acct_req.fetch++;
	(void)HTTP1_DiscardReqBody(req);

	if (req->objcore->flags & OC_F_FAILED) {
		req->err_code = 503;
		req->req_step = R_STP_ERROR;
		(void)HSH_DerefObjCore(&wrk->stats, &req->objcore);
		req->objcore = NULL;
		return (REQ_FSM_MORE);
	}

	req->obj = oc_getobj(&wrk->stats, req->objcore);
	req->objcore = NULL;
	req->err_code = req->obj->response;
	req->req_step = R_STP_DELIVER;
	return (REQ_FSM_MORE);
}
Ejemplo n.º 2
0
static int
cnt_lookup(struct worker *wrk, struct req *req)
{
	struct objcore *oc;
	struct object *o;
	struct objhead *oh;
	struct busyobj *bo;

	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
	AZ(req->objcore);

	CHECK_OBJ_NOTNULL(req->vcl, VCL_CONF_MAGIC);
	AZ(req->busyobj);

	VRY_Prep(req);

	AZ(req->objcore);
	oc = HSH_Lookup(req);
	if (oc == NULL) {
		/*
		 * We lost the session to a busy object, disembark the
		 * worker thread.   We return to STP_LOOKUP when the busy
		 * object has been unbusied, and still have the objhead
		 * around to restart the lookup with.
		 */
		return (2);
	}
	AZ(req->objcore);

	CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
	oh = oc->objhead;
	CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);

	/* If we inserted a new object it's a miss */
	if (oc->flags & OC_F_BUSY) {
		AZ(req->busyobj);
		bo = VBO_GetBusyObj(wrk, req);
		req->busyobj = bo;
		/* One ref for req, one for FetchBody */
		bo->refcount = 2;
		VRY_Finish(req, bo);

		oc->busyobj = bo;
		wrk->stats.cache_miss++;

		req->objcore = oc;
		req->req_step = R_STP_MISS;
		return (0);
	}

	/* We are not prepared to do streaming yet */
	XXXAZ(req->busyobj);

	o = oc_getobj(&wrk->stats, oc);
	CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
	req->obj = o;

	VRY_Finish(req, NULL);

	if (oc->flags & OC_F_PASS) {
		wrk->stats.cache_hitpass++;
		VSLb(req->vsl, SLT_HitPass, "%u", req->obj->vxid);
		(void)HSH_Deref(&wrk->stats, NULL, &req->obj);
		AZ(req->objcore);
		req->req_step = R_STP_PASS;
		return (0);
	}

	wrk->stats.cache_hit++;
	VSLb(req->vsl, SLT_Hit, "%u", req->obj->vxid);
	req->req_step = R_STP_HIT;
	return (0);
}
Ejemplo n.º 3
0
static enum req_fsm_nxt
cnt_lookup(struct worker *wrk, struct req *req)
{
	struct objcore *oc, *boc;
	struct object *o;
	struct objhead *oh;
	enum lookup_e lr;

	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
	AZ(req->objcore);

	CHECK_OBJ_NOTNULL(req->vcl, VCL_CONF_MAGIC);

	VRY_Prep(req);

	AZ(req->objcore);
	lr = HSH_Lookup(req, &oc, &boc,
	    req->esi_level == 0 ? 1 : 0,
	    req->hash_always_miss ? 1 : 0
	);
	if (lr == HSH_BUSY) {
		/*
		 * We lost the session to a busy object, disembark the
		 * worker thread.   We return to STP_LOOKUP when the busy
		 * object has been unbusied, and still have the objhead
		 * around to restart the lookup with.
		 */
		return (REQ_FSM_DISEMBARK);
	}

	if (boc == NULL) {
		VRY_Finish(req, DISCARD);
	} else {
		AN(boc->flags & OC_F_BUSY);
		VRY_Finish(req, KEEP);
	}

	AZ(req->objcore);
	if (lr == HSH_MISS) {
		/* Found nothing */
		VSLb(req->vsl, SLT_Debug, "XXXX MISS");
		AZ(oc);
		AN(boc);
		AN(boc->flags & OC_F_BUSY);
		req->objcore = boc;
		req->req_step = R_STP_MISS;
		return (REQ_FSM_MORE);
	}

	CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
	AZ (oc->flags & OC_F_BUSY);
	AZ(req->objcore);

	if (oc->flags & OC_F_PASS) {
		/* Found a hit-for-pass */
		VSLb(req->vsl, SLT_Debug, "XXXX HIT-FOR-PASS");
		AZ(boc);
		(void)HSH_DerefObjCore(&wrk->stats, &oc);
		req->objcore = NULL;
		wrk->stats.cache_hitpass++;
		req->req_step = R_STP_PASS;
		return (REQ_FSM_MORE);
	}

	oh = oc->objhead;
	CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);

	o = oc_getobj(&wrk->stats, oc);
	CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
	req->obj = o;

	VSLb(req->vsl, SLT_Hit, "%u", req->obj->vxid);

	VCL_hit_method(req->vcl, wrk, req, NULL, req->http->ws);

	switch (wrk->handling) {
	case VCL_RET_DELIVER:
		if (boc != NULL) {
			VBF_Fetch(wrk, req, boc, o, VBF_BACKGROUND);
		} else {
			(void)HTTP1_DiscardReqBody(req);// XXX: handle err
		}
		wrk->stats.cache_hit++;
		req->req_step = R_STP_DELIVER;
		return (REQ_FSM_MORE);
	case VCL_RET_FETCH:
		(void)HSH_DerefObj(&wrk->stats, &req->obj);
		req->objcore = boc;
		if (req->objcore != NULL)
			req->req_step = R_STP_MISS;
		else {
			/*
			 * We don't have a busy object, so treat this
			 * lige a pass
			 */
			VSLb(req->vsl, SLT_VCL_Error,
			    "vcl_hit{} returns fetch without busy object."
			    "  Doing pass.");
			req->req_step = R_STP_PASS;
		}
		return (REQ_FSM_MORE);
	case VCL_RET_RESTART:
		req->req_step = R_STP_RESTART;
		break;
	case VCL_RET_ERROR:
		req->req_step = R_STP_ERROR;
		break;
	case VCL_RET_PASS:
		wrk->stats.cache_hit++;
		req->req_step = R_STP_PASS;
		break;
	default:
		INCOMPL();
	}

	/* Drop our object, we won't need it */
	(void)HSH_DerefObj(&wrk->stats, &req->obj);
	req->objcore = NULL;

	if (boc != NULL) {
		(void)HSH_DerefObjCore(&wrk->stats, &boc);
		free(req->vary_b);
		req->vary_b = NULL;
	}

	return (REQ_FSM_MORE);
}
Ejemplo n.º 4
0
static int
cnt_lookup(struct sess *sp)
{
    struct objcore *oc;
    struct object *o;
    struct objhead *oh;
    struct worker *wrk;

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

    CHECK_OBJ_NOTNULL(sp->vcl, VCL_CONF_MAGIC);
    AZ(wrk->busyobj);

    if (sp->hash_objhead == NULL) {
        /* Not a waiting list return */
        AZ(sp->vary_b);
        AZ(sp->vary_l);
        AZ(sp->vary_e);
        (void)WS_Reserve(sp->ws, 0);
    } else {
        AN(sp->ws->r);
    }
    sp->vary_b = (void*)sp->ws->f;
    sp->vary_e = (void*)sp->ws->r;
    sp->vary_b[2] = '\0';

    oc = HSH_Lookup(sp, &oh);

    if (oc == NULL) {
        /*
         * We lost the session to a busy object, disembark the
         * worker thread.   The hash code to restart the session,
         * still in STP_LOOKUP, later when the busy object isn't.
         * NB:  Do not access sp any more !
         */
        return (1);
    }


    CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
    CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);

    /* If we inserted a new object it's a miss */
    if (oc->flags & OC_F_BUSY) {
        wrk->stats.cache_miss++;

        if (sp->vary_l != NULL) {
            assert(oc->busyobj->vary == sp->vary_b);
            VRY_Validate(oc->busyobj->vary);
            WS_ReleaseP(sp->ws, (void*)sp->vary_l);
        } else {
            AZ(oc->busyobj->vary);
            WS_Release(sp->ws, 0);
        }
        sp->vary_b = NULL;
        sp->vary_l = NULL;
        sp->vary_e = NULL;

        wrk->objcore = oc;
        CHECK_OBJ_NOTNULL(wrk->busyobj, BUSYOBJ_MAGIC);
        sp->step = STP_MISS;
        return (0);
    }

    o = oc_getobj(wrk, oc);
    CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
    wrk->obj = o;

    WS_Release(sp->ws, 0);
    sp->vary_b = NULL;
    sp->vary_l = NULL;
    sp->vary_e = NULL;

    if (oc->flags & OC_F_PASS) {
        wrk->stats.cache_hitpass++;
        WSP(sp, SLT_HitPass, "%u", wrk->obj->xid);
        (void)HSH_Deref(wrk, NULL, &wrk->obj);
        wrk->objcore = NULL;
        sp->step = STP_PASS;
        return (0);
    }

    wrk->stats.cache_hit++;
    WSP(sp, SLT_Hit, "%u", wrk->obj->xid);
    sp->step = STP_HIT;
    return (0);
}