Пример #1
0
/* Precreate an objhead and object for later use */
static void
hsh_prealloc(struct worker *wrk)
{
	struct waitinglist *wl;

	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);

	if (wrk->nobjcore == NULL)
		wrk->nobjcore = HSH_NewObjCore(wrk);
	CHECK_OBJ_NOTNULL(wrk->nobjcore, OBJCORE_MAGIC);

	if (wrk->nobjhead == NULL) {
		wrk->nobjhead = hsh_newobjhead();
		wrk->stats.n_objecthead++;
	}
	CHECK_OBJ_NOTNULL(wrk->nobjhead, OBJHEAD_MAGIC);

	if (wrk->nwaitinglist == NULL) {
		ALLOC_OBJ(wl, WAITINGLIST_MAGIC);
		XXXAN(wl);
		VTAILQ_INIT(&wl->list);
		wrk->nwaitinglist = wl;
		wrk->stats.n_waitinglist++;
	}
	CHECK_OBJ_NOTNULL(wrk->nwaitinglist, WAITINGLIST_MAGIC);

	if (hash->prep != NULL)
		hash->prep(wrk);
}
Пример #2
0
/* Precreate an objhead and object for later use */
static void
hsh_prealloc(struct worker *wrk)
{
	struct objhead *oh;
	struct waitinglist *wl;

	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);

	if (wrk->nobjcore == NULL)
		wrk->nobjcore = HSH_NewObjCore(wrk);
	CHECK_OBJ_NOTNULL(wrk->nobjcore, OBJCORE_MAGIC);

	if (wrk->nobjhead == NULL) {
		ALLOC_OBJ(oh, OBJHEAD_MAGIC);
		XXXAN(oh);
		oh->refcnt = 1;
		VTAILQ_INIT(&oh->objcs);
		Lck_New(&oh->mtx, lck_objhdr);
		wrk->nobjhead = oh;
		wrk->stats.n_objecthead++;
	}
	CHECK_OBJ_NOTNULL(wrk->nobjhead, OBJHEAD_MAGIC);

	if (wrk->nwaitinglist == NULL) {
		ALLOC_OBJ(wl, WAITINGLIST_MAGIC);
		XXXAN(wl);
		VTAILQ_INIT(&wl->list);
		wrk->nwaitinglist = wl;
		wrk->stats.n_waitinglist++;
	}
	CHECK_OBJ_NOTNULL(wrk->nwaitinglist, WAITINGLIST_MAGIC);

	if (hash->prep != NULL)
		hash->prep(wrk);
}
Пример #3
0
static int
cnt_pass(struct worker *wrk, struct req *req)
{
	struct busyobj *bo;

	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
	CHECK_OBJ_NOTNULL(req->vcl, VCL_CONF_MAGIC);
	AZ(req->objcore);
	AZ(req->obj);
	AZ(req->busyobj);

	req->busyobj = VBO_GetBusyObj(wrk, req);
	bo = req->busyobj;
	bo->refcount = 2;
	HTTP_Setup(bo->bereq, bo->ws, bo->vsl, HTTP_Bereq);
	http_FilterReq(req, HTTPH_R_PASS);

	VCL_pass_method(req);

	if (req->handling == VCL_RET_ERROR) {
		http_Teardown(bo->bereq);
		VBO_DerefBusyObj(wrk, &req->busyobj);
		req->req_step = R_STP_ERROR;
		return (0);
	}
	assert(req->handling == VCL_RET_PASS);
	req->acct_req.pass++;
	req->req_step = R_STP_FETCH;

	req->objcore = HSH_NewObjCore(wrk);
	req->objcore->busyobj = bo;
	return (0);
}
Пример #4
0
struct objcore *
HSH_Private(struct worker *wrk)
{
	struct objcore *oc;

	CHECK_OBJ_NOTNULL(private_oh, OBJHEAD_MAGIC);

	oc = HSH_NewObjCore(wrk);
	AN(oc);
	oc->refcnt = 1;
	oc->objhead = private_oh;
	oc->flags |= OC_F_PRIVATE;
	Lck_Lock(&private_oh->mtx);
	VTAILQ_INSERT_TAIL(&private_oh->objcs, oc, list);
	private_oh->refcnt++;
	Lck_Unlock(&private_oh->mtx);
	return (oc);
}
Пример #5
0
static int
cnt_error(struct worker *wrk, struct req *req)
{
	struct http *h;
	struct busyobj *bo;
	char date[40];

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

	bo = VBO_GetBusyObj(wrk, req);
	req->busyobj = bo;
	AZ(bo->stats);
	bo->stats = &wrk->stats;
	req->objcore = HSH_NewObjCore(wrk);
	req->obj = STV_NewObject(bo, &req->objcore,
	    TRANSIENT_STORAGE, cache_param->http_resp_size,
	    (uint16_t)cache_param->http_max_hdr);
	bo->stats = NULL;
	if (req->obj == NULL) {
		req->doclose = SC_OVERLOAD;
		req->director = NULL;
		http_Teardown(bo->beresp);
		http_Teardown(bo->bereq);
		return(1);
	}
	CHECK_OBJ_NOTNULL(req->obj, OBJECT_MAGIC);
	req->obj->vxid = bo->vsl->wid;
	req->obj->exp.entered = req->t_req;

	h = req->obj->http;

	if (req->err_code < 100 || req->err_code > 999)
		req->err_code = 501;

	http_PutProtocol(h, "HTTP/1.1");
	http_PutStatus(h, req->err_code);
	VTIM_format(W_TIM_real(wrk), date);
	http_PrintfHeader(h, "Date: %s", date);
	http_SetHeader(h, "Server: Varnish");

	if (req->err_reason != NULL)
		http_PutResponse(h, req->err_reason);
	else
		http_PutResponse(h, http_StatusMessage(req->err_code));
	VCL_error_method(req);

	if (req->handling == VCL_RET_RESTART &&
	    req->restarts <  cache_param->max_restarts) {
		HSH_Drop(wrk, &req->obj);
		VBO_DerefBusyObj(wrk, &req->busyobj);
		req->req_step = R_STP_RESTART;
		return (0);
	} else if (req->handling == VCL_RET_RESTART)
		req->handling = VCL_RET_DELIVER;


	/* We always close when we take this path */
	req->doclose = SC_TX_ERROR;
	req->wantbody = 1;

	assert(req->handling == VCL_RET_DELIVER);
	req->err_code = 0;
	req->err_reason = NULL;
	http_Teardown(bo->bereq);
	VBO_DerefBusyObj(wrk, &req->busyobj);
	req->req_step = R_STP_PREPRESP;
	return (0);
}
ssize_t
VRB_Cache(struct req *req, ssize_t maxsize)
{
	ssize_t l, yet;
	struct vfp_ctx *vfc;
	uint8_t *ptr;
	enum vfp_status vfps = VFP_ERROR;

	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);

	assert (req->req_step == R_STP_RECV);
	switch(req->req_body_status) {
	case REQ_BODY_CACHED:
		return (req->req_bodybytes);
	case REQ_BODY_FAIL:
		return (-1);
	case REQ_BODY_NONE:
		return (0);
	case REQ_BODY_WITHOUT_LEN:
	case REQ_BODY_WITH_LEN:
		break;
	default:
		WRONG("Wrong req_body_status in VRB_Cache()");
	}

	CHECK_OBJ_NOTNULL(req->htc, HTTP_CONN_MAGIC);
	vfc = req->htc->vfc;
	VFP_Setup(vfc);
	vfc->wrk = req->wrk;

	if (req->htc->content_length > maxsize) {
		req->req_body_status = REQ_BODY_FAIL;
		(void)VFP_Error(vfc, "Request body too big to cache");
		return (-1);
	}

	req->body_oc = HSH_NewObjCore(req->wrk);
	AN(req->body_oc);
	XXXAN(STV_NewObject(req->body_oc, req->wrk, TRANSIENT_STORAGE, 8));

	vfc->http = req->http;
	vfc->oc = req->body_oc;
	V1F_Setup_Fetch(vfc, req->htc);

	if (VFP_Open(vfc) < 0) {
		req->req_body_status = REQ_BODY_FAIL;
		return (-1);
	}

	AZ(req->req_bodybytes);
	AN(req->htc);
	yet = req->htc->content_length;
	if (yet < 0)
		yet = 0;
	do {
		AZ(vfc->failed);
		if (req->req_bodybytes > maxsize) {
			req->req_body_status = REQ_BODY_FAIL;
			(void)VFP_Error(vfc, "Request body too big to cache");
			VFP_Close(vfc);
			return(-1);
		}
		l = yet;
		if (VFP_GetStorage(vfc, &l, &ptr) != VFP_OK)
			break;
		AZ(vfc->failed);
		AN(ptr);
		AN(l);
		vfps = VFP_Suck(vfc, ptr, &l);
		if (l > 0 && vfps != VFP_ERROR) {
			req->req_bodybytes += l;
			req->acct.req_bodybytes += l;
			if (yet >= l)
				yet -= l;
			ObjExtend(req->wrk, req->body_oc, l);
		}

	} while (vfps == VFP_OK);
	VFP_Close(vfc);

	if (vfps == VFP_END) {
		assert(req->req_bodybytes >= 0);
		if (req->req_bodybytes != req->htc->content_length) {
			/* We must update also the "pristine" req.* copy */
			http_Unset(req->http0, H_Content_Length);
			http_Unset(req->http0, H_Transfer_Encoding);
			http_PrintfHeader(req->http0, "Content-Length: %ju",
			    (uintmax_t)req->req_bodybytes);

			http_Unset(req->http, H_Content_Length);
			http_Unset(req->http, H_Transfer_Encoding);
			http_PrintfHeader(req->http, "Content-Length: %ju",
			    (uintmax_t)req->req_bodybytes);
		}

		req->req_body_status = REQ_BODY_CACHED;
	} else {
		req->req_body_status = REQ_BODY_FAIL;
	}
	VSLb_ts_req(req, "ReqBody", VTIM_real());
	return (vfps == VFP_END ? req->req_bodybytes : -1);
}