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 { ...@@ -696,7 +696,8 @@ struct req {
#define RES_GUNZIP (1<<6) #define RES_GUNZIP (1<<6)
/* Deliver pipeline */ /* Deliver pipeline */
vdp_bytes *vdps[5]; #define N_VDPS 5
vdp_bytes *vdps[N_VDPS];
int vdp_nxt; int vdp_nxt;
/* Range */ /* Range */
...@@ -704,6 +705,9 @@ struct req { ...@@ -704,6 +705,9 @@ struct req {
ssize_t range_high; ssize_t range_high;
ssize_t range_off; ssize_t range_off;
/* Gunzip */
struct vgz *vgz;
/* Transaction VSL buffer */ /* Transaction VSL buffer */
struct vsl_log vsl[1]; struct vsl_log vsl[1];
...@@ -833,17 +837,44 @@ int HTTP1_IterateReqBody(struct req *req, req_body_iter_f *func, void *priv); ...@@ -833,17 +837,44 @@ int HTTP1_IterateReqBody(struct req *req, req_body_iter_f *func, void *priv);
void V1D_Deliver(struct req *); void V1D_Deliver(struct req *);
static inline int 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; int i, retval;
CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
/* Call the present layer, while pointing to the next layer down */ /* Call the present layer, while pointing to the next layer down */
i = req->vdp_nxt--; i = req->vdp_nxt--;
assert(i >= 0 && i < N_VDPS);
retval = req->vdps[i](req, flush, ptr, len); retval = req->vdps[i](req, flush, ptr, len);
req->vdp_nxt++; req->vdp_nxt++;
return (retval); 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] */ /* cache_req_fsm.c [CNT] */
enum req_fsm_nxt CNT_Request(struct worker *, struct req *); 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); ...@@ -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_Gunzip(struct vgz *, const void **, size_t *len);
enum vgzret_e VGZ_Destroy(struct vgz **); enum vgzret_e VGZ_Destroy(struct vgz **);
void VGZ_UpdateObj(const struct vgz*, struct object *); void VGZ_UpdateObj(const struct vgz*, struct object *);
vdp_bytes VDP_gunzip;
int VGZ_WrwInit(struct vgz *vg); int VGZ_WrwInit(struct vgz *vg);
enum vgzret_e VGZ_WrwGunzip(struct req *, struct vgz *, const void *ibuf, enum vgzret_e VGZ_WrwGunzip(struct req *, struct vgz *, const void *ibuf,
......
...@@ -310,6 +310,53 @@ VGZ_WrwInit(struct vgz *vg) ...@@ -310,6 +310,53 @@ VGZ_WrwInit(struct vgz *vg)
return (0); 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. * Gunzip ibuf into outb, if it runs full, emit it with WRW.
* Leave flushing to caller, more data may be coming. * Leave flushing to caller, more data may be coming.
...@@ -342,7 +389,7 @@ VGZ_WrwGunzip(struct req *req, struct vgz *vg, const void *ibuf, ...@@ -342,7 +389,7 @@ VGZ_WrwGunzip(struct req *req, struct vgz *vg, const void *ibuf,
if (vr < VGZ_OK) if (vr < VGZ_OK)
return (vr); return (vr);
if (vg->m_len == vg->m_sz || vr == VGZ_STUCK) { 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; vg->m_len = 0;
VGZ_Obuf(vg, vg->m_buf, vg->m_sz); VGZ_Obuf(vg, vg->m_buf, vg->m_sz);
} }
...@@ -367,7 +414,7 @@ VGZ_WrwFlush(struct req *req, struct vgz *vg) ...@@ -367,7 +414,7 @@ VGZ_WrwFlush(struct req *req, struct vgz *vg)
if (vg->m_len == 0) if (vg->m_len == 0)
return; 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; vg->m_len = 0;
VGZ_Obuf(vg, vg->m_buf, vg->m_sz); 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) ...@@ -77,7 +77,7 @@ v1d_range_bytes(struct req *req, int flush, void *ptr, ssize_t len)
if (l > len) if (l > len)
l = len; l = len;
if (flush || l > 0) if (flush || l > 0)
retval = VDP(req, flush, p, l); retval = VDP_bytes(req, flush, p, l);
req->range_off += len; req->range_off += len;
return (retval); return (retval);
} }
...@@ -147,45 +147,7 @@ v1d_dorange(struct req *req, const char *r) ...@@ -147,45 +147,7 @@ v1d_dorange(struct req *req, const char *r)
req->range_off = 0; req->range_off = 0;
req->range_low = low; req->range_low = low;
req->range_high = high + 1; req->range_high = high + 1;
req->vdps[++req->vdp_nxt] = v1d_range_bytes; VDP_push(req, 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);
} }
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
...@@ -203,9 +165,10 @@ v1d_WriteDirObj(struct req *req) ...@@ -203,9 +165,10 @@ v1d_WriteDirObj(struct req *req)
XXXAN(oi); XXXAN(oi);
while (ObjIter(oi, &ptr, &len)) { while (ObjIter(oi, &ptr, &len)) {
if (VDP(req, 0, ptr, len)) if (VDP_bytes(req, 0, ptr, len))
break; break;
} }
(void)VDP_bytes(req, 1, NULL, 0);
ObjIterEnd(&oi); ObjIterEnd(&oi);
} }
...@@ -329,9 +292,19 @@ V1D_Deliver(struct req *req) ...@@ -329,9 +292,19 @@ V1D_Deliver(struct req *req)
ESI_DeliverChild(req); ESI_DeliverChild(req);
} else if (req->res_mode & RES_ESI_CHILD && } else if (req->res_mode & RES_ESI_CHILD &&
!req->gzip_resp && req->obj->gziped) { !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) { } 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 { } else {
v1d_WriteDirObj(req); 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