Commit e44815ad authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Turn delivery-side gunzip into a VDP

parent 2f0c9c3c
......@@ -696,7 +696,8 @@ struct req {
#define RES_GUNZIP (1<<6)
/* Deliver pipeline */
vdp_bytes *vdps[5];
#define N_VDPS 5
vdp_bytes *vdps[N_VDPS];
int vdp_nxt;
/* Range */
......@@ -704,6 +705,9 @@ struct req {
ssize_t range_high;
ssize_t range_off;
/* Gunzip */
struct vgz *vgz;
/* Transaction VSL buffer */
struct vsl_log vsl[1];
......@@ -833,17 +837,44 @@ int HTTP1_IterateReqBody(struct req *req, req_body_iter_f *func, void *priv);
void V1D_Deliver(struct req *);
static inline int
VDP(struct req *req, int flush, void *ptr, ssize_t len)
VDP_bytes(struct req *req, int flush, void *ptr, ssize_t len)
{
int i, retval;
CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
/* Call the present layer, while pointing to the next layer down */
i = req->vdp_nxt--;
assert(i >= 0 && i < N_VDPS);
retval = req->vdps[i](req, flush, ptr, len);
req->vdp_nxt++;
return (retval);
}
static inline void
VDP_push(struct req *req, vdp_bytes *func)
{
CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
AN(func);
/* Push another layer */
assert(req->vdp_nxt >= 0);
assert(req->vdp_nxt + 1 < N_VDPS);
req->vdps[++req->vdp_nxt] = func;
}
static inline void
VDP_pop(struct req *req, vdp_bytes *func)
{
CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
/* Pop top layer */
assert(req->vdp_nxt >= 1);
assert(req->vdp_nxt < N_VDPS);
assert(req->vdps[req->vdp_nxt] == func);
req->vdp_nxt--;
}
/* cache_req_fsm.c [CNT] */
enum req_fsm_nxt CNT_Request(struct worker *, struct req *);
......@@ -911,6 +942,7 @@ enum vgzret_e VGZ_Gzip(struct vgz *, const void **, size_t *len, enum vgz_flag);
enum vgzret_e VGZ_Gunzip(struct vgz *, const void **, size_t *len);
enum vgzret_e VGZ_Destroy(struct vgz **);
void VGZ_UpdateObj(const struct vgz*, struct object *);
vdp_bytes VDP_gunzip;
int VGZ_WrwInit(struct vgz *vg);
enum vgzret_e VGZ_WrwGunzip(struct req *, struct vgz *, const void *ibuf,
......
......@@ -310,6 +310,53 @@ VGZ_WrwInit(struct vgz *vg)
return (0);
}
/*--------------------------------------------------------------------
* VDP for gunzip'ing
*/
int __match_proto__(vdp_bytes)
VDP_gunzip(struct req *req, int flush, void *ptr, ssize_t len)
{
enum vgzret_e vr;
size_t dl;
const void *dp;
struct worker *wrk;
struct vgz *vg;
CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
wrk = req->wrk;
CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
vg = req->vgz;
CHECK_OBJ_NOTNULL(vg, VGZ_MAGIC);
AN(vg->m_buf);
if (len == 0) {
AN(flush);
return (VDP_bytes(req, 1, vg->m_buf, vg->m_len));
}
VGZ_Ibuf(vg, ptr, len);
do {
if (vg->m_len == vg->m_sz)
vr = VGZ_STUCK;
else {
vr = VGZ_Gunzip(vg, &dp, &dl);
vg->m_len += dl;
}
if (vr < VGZ_OK)
return (-1);
if (vg->m_len == vg->m_sz || vr == VGZ_STUCK) {
if (VDP_bytes(req, 1, vg->m_buf, vg->m_len))
return (-1);
vg->m_len = 0;
VGZ_Obuf(vg, vg->m_buf, vg->m_sz);
}
} while (!VGZ_IbufEmpty(vg));
assert(vr == VGZ_STUCK || vr == VGZ_OK || vr == VGZ_END);
return (0);
}
/*--------------------------------------------------------------------
* Gunzip ibuf into outb, if it runs full, emit it with WRW.
* Leave flushing to caller, more data may be coming.
......@@ -342,7 +389,7 @@ VGZ_WrwGunzip(struct req *req, struct vgz *vg, const void *ibuf,
if (vr < VGZ_OK)
return (vr);
if (vg->m_len == vg->m_sz || vr == VGZ_STUCK) {
(void)VDP(req, 1, vg->m_buf, vg->m_len);
(void)VDP_bytes(req, 1, vg->m_buf, vg->m_len);
vg->m_len = 0;
VGZ_Obuf(vg, vg->m_buf, vg->m_sz);
}
......@@ -367,7 +414,7 @@ VGZ_WrwFlush(struct req *req, struct vgz *vg)
if (vg->m_len == 0)
return;
(void)VDP(req, 1, vg->m_buf, vg->m_len);
(void)VDP_bytes(req, 1, vg->m_buf, vg->m_len);
vg->m_len = 0;
VGZ_Obuf(vg, vg->m_buf, vg->m_sz);
}
......
......@@ -77,7 +77,7 @@ v1d_range_bytes(struct req *req, int flush, void *ptr, ssize_t len)
if (l > len)
l = len;
if (flush || l > 0)
retval = VDP(req, flush, p, l);
retval = VDP_bytes(req, flush, p, l);
req->range_off += len;
return (retval);
}
......@@ -147,45 +147,7 @@ v1d_dorange(struct req *req, const char *r)
req->range_off = 0;
req->range_low = low;
req->range_high = high + 1;
req->vdps[++req->vdp_nxt] = v1d_range_bytes;
}
/*--------------------------------------------------------------------
* We have a gzip'ed object and need to ungzip it for a client which
* does not understand gzip.
* XXX: handle invalid gzip data better (how ?)
*/
static void
v1d_WriteGunzipObj(struct req *req)
{
unsigned u = 0;
struct vgz *vg;
struct objiter *oi;
void *ptr;
ssize_t len;
int i;
CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
vg = VGZ_NewUngzip(req->vsl, "U D -");
AZ(VGZ_WrwInit(vg));
oi = ObjIterBegin(req->obj);
XXXAN(oi);
while (ObjIter(oi, &ptr, &len)) {
CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
u += len;
i = VGZ_WrwGunzip(req, vg, ptr, len);
/* XXX: error check */
(void)i;
}
VGZ_WrwFlush(req, vg);
(void)VGZ_Destroy(&vg);
assert(u == req->obj->len);
ObjIterEnd(&oi);
VDP_push(req, v1d_range_bytes);
}
/*--------------------------------------------------------------------*/
......@@ -203,9 +165,10 @@ v1d_WriteDirObj(struct req *req)
XXXAN(oi);
while (ObjIter(oi, &ptr, &len)) {
if (VDP(req, 0, ptr, len))
if (VDP_bytes(req, 0, ptr, len))
break;
}
(void)VDP_bytes(req, 1, NULL, 0);
ObjIterEnd(&oi);
}
......@@ -329,9 +292,19 @@ V1D_Deliver(struct req *req)
ESI_DeliverChild(req);
} else if (req->res_mode & RES_ESI_CHILD &&
!req->gzip_resp && req->obj->gziped) {
v1d_WriteGunzipObj(req);
VDP_push(req, VDP_gunzip);
req->vgz = VGZ_NewUngzip(req->vsl, "U D -");
AZ(VGZ_WrwInit(req->vgz));
v1d_WriteDirObj(req);
(void)VGZ_Destroy(&req->vgz);
VDP_pop(req, VDP_gunzip);
} else if (req->res_mode & RES_GUNZIP) {
v1d_WriteGunzipObj(req);
VDP_push(req, VDP_gunzip);
req->vgz = VGZ_NewUngzip(req->vsl, "U D -");
AZ(VGZ_WrwInit(req->vgz));
v1d_WriteDirObj(req);
(void)VGZ_Destroy(&req->vgz);
VDP_pop(req, VDP_gunzip);
} else {
v1d_WriteDirObj(req);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment