[master] 1ca4bfc Rewrite the esi_include delivery to use ObjIter()
Poul-Henning Kamp
phk at FreeBSD.org
Mon Aug 18 12:17:32 CEST 2014
commit 1ca4bfc7b37ead6a9f0a95ee3f93bbb350cdf852
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Mon Aug 18 10:17:13 2014 +0000
Rewrite the esi_include delivery to use ObjIter()
diff --git a/bin/varnishd/cache/cache_esi_deliver.c b/bin/varnishd/cache/cache_esi_deliver.c
index 71313e3..d74f27a 100644
--- a/bin/varnishd/cache/cache_esi_deliver.c
+++ b/bin/varnishd/cache/cache_esi_deliver.c
@@ -458,67 +458,34 @@ ESI_Deliver(struct req *req)
* Include an object in a gzip'ed ESI object delivery
*/
-static uint8_t
-ved_deliver_byterange(struct req *req, const struct object *obj, ssize_t low,
- ssize_t high)
-{
- struct storage *st;
- ssize_t l, lx;
- u_char *p;
-
- lx = 0;
- VTAILQ_FOREACH(st, &obj->body->list, list) {
- p = st->ptr;
- l = st->len;
- if (lx + l < low) {
- lx += l;
- continue;
- }
- if (lx == high)
- return (p[0]);
- assert(lx < high);
- if (lx < low) {
- p += (low - lx);
- l -= (low - lx);
- lx = low;
- }
- if (lx + l >= high)
- l = high - lx;
- assert(lx >= low && lx + l <= high);
- if (l != 0)
- req->resp_bodybytes += WRW_Write(req->wrk, p, l);
- if (p + l < st->ptr + st->len)
- return(p[l]);
- lx += l;
- }
- INCOMPL();
-}
-
void
ESI_DeliverChild(struct req *req)
{
- struct storage *st;
- struct object *obj;
ssize_t start, last, stop, lpad;
ssize_t l;
char *p;
- u_char cc;
uint32_t icrc;
uint32_t ilen;
uint64_t olen;
uint8_t *dbits;
- int i, j;
+ uint8_t *pp;
uint8_t tailbuf[8];
+ enum objiter_status ois;
+ struct objiter *oi;
+ void *sp;
+ ssize_t sl, ll, dl;
CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
- obj = ObjGetObj(req->objcore, &req->wrk->stats);
- CHECK_OBJ_NOTNULL(obj, OBJECT_MAGIC);
-
if (!ObjCheckFlag(req->objcore, &req->wrk->stats, OF_GZIPED)) {
- VTAILQ_FOREACH(st, &obj->body->list, list)
- ved_pretend_gzip(req, st->ptr, st->len);
+ oi = ObjIterBegin(req->wrk, req->objcore);
+ do {
+ ois = ObjIter(oi, &sp, &sl);
+ if (sl > 0)
+ ved_pretend_gzip(req, sp, sl);
+ } while (ois == OIS_DATA || ois == OIS_STREAM);
+ ObjIterEnd(&oi);
return;
}
/*
@@ -527,15 +494,13 @@ ESI_DeliverChild(struct req *req)
* padding it, as necessary, to a byte boundary.
*/
- dbits = (void*)WS_Alloc(req->ws, 8);
- AN(dbits);
- p = ObjGetattr(obj->objcore, &req->wrk->stats, OA_GZIPBITS, &l);
+ p = ObjGetattr(req->objcore, &req->wrk->stats, OA_GZIPBITS, &l);
AN(p);
assert(l == 24);
start = vbe64dec(p);
last = vbe64dec(p + 8);
stop = vbe64dec(p + 16);
- olen = ObjGetLen(obj->objcore, &req->wrk->stats);
+ olen = ObjGetLen(req->objcore, &req->wrk->stats);
assert(start > 0 && start < olen * 8);
assert(last > 0 && last < olen * 8);
assert(stop > 0 && stop < olen * 8);
@@ -549,64 +514,140 @@ ESI_DeliverChild(struct req *req)
* XXX: optimize for the case where the 'last'
* XXX: bit is in a empty copy block
*/
- *dbits = ved_deliver_byterange(req, obj, start/8, last/8);
- *dbits &= ~(1U << (last & 7));
- req->resp_bodybytes += WRW_Write(req->wrk, dbits, 1);
- cc = ved_deliver_byterange(req, obj, 1 + last/8, stop/8);
- switch((int)(stop & 7)) {
- case 0: /* xxxxxxxx */
- /* I think we have an off by one here, but that's OK */
- lpad = 0;
- break;
- case 1: /* x000.... 00000000 00000000 11111111 11111111 */
- case 3: /* xxx000.. 00000000 00000000 11111111 11111111 */
- case 5: /* xxxxx000 00000000 00000000 11111111 11111111 */
- dbits[1] = cc | 0x00;
- dbits[2] = 0x00; dbits[3] = 0x00;
- dbits[4] = 0xff; dbits[5] = 0xff;
- lpad = 5;
- break;
- case 2: /* xx010000 00000100 00000001 00000000 */
- dbits[1] = cc | 0x08;
- dbits[2] = 0x20;
- dbits[3] = 0x80;
- dbits[4] = 0x00;
- lpad = 4;
- break;
- case 4: /* xxxx0100 00000001 00000000 */
- dbits[1] = cc | 0x20;
- dbits[2] = 0x80;
- dbits[3] = 0x00;
- lpad = 3;
- break;
- case 6: /* xxxxxx01 00000000 */
- dbits[1] = cc | 0x80;
- dbits[2] = 0x00;
- lpad = 2;
- break;
- case 7: /* xxxxxxx0 00...... 00000000 00000000 11111111 11111111 */
- dbits[1] = cc | 0x00;
- dbits[2] = 0x00;
- dbits[3] = 0x00; dbits[4] = 0x00;
- dbits[5] = 0xff; dbits[6] = 0xff;
- lpad = 6;
- break;
- default:
- INCOMPL();
- }
- if (lpad > 0)
- req->resp_bodybytes += WRW_Write(req->wrk, dbits + 1, lpad);
-
- /* We need the entire tail, but it may not be in one storage segment */
- st = VTAILQ_LAST(&obj->body->list, storagehead);
- for (i = sizeof tailbuf; i > 0; i -= j) {
- j = st->len;
- if (j > i)
- j = i;
- memcpy(tailbuf + i - j, st->ptr + st->len - j, j);
- st = VTAILQ_PREV(st, storagehead, list);
- assert(i == j || st != NULL);
- }
+
+ memset(tailbuf, 0xdd, sizeof tailbuf);
+ dbits = (void*)WS_Alloc(req->ws, 8);
+ AN(dbits);
+ ll = 0;
+ oi = ObjIterBegin(req->wrk, req->objcore);
+ do {
+ ois = ObjIter(oi, &sp, &sl);
+ pp = sp;
+ if (sl > 0) {
+ /* Skip over the GZIP header */
+ dl = start / 8 - ll;
+ if (dl > 0) {
+ /* Before start, skip */
+ if (dl > sl)
+ dl = sl;
+ ll += dl;
+ sl -= dl;
+ pp += dl;
+ }
+ }
+ if (sl > 0) {
+ /* The main body of the object */
+ dl = last / 8 - ll;
+ if (dl > 0) {
+ if (dl > sl)
+ dl = sl;
+ req->resp_bodybytes +=
+ WRW_Write(req->wrk, pp, dl);
+ ll += dl;
+ sl -= dl;
+ pp += dl;
+ }
+ }
+ if (sl > 0 && ll == last / 8) {
+ /* Remove the "LAST" bit */
+ dbits[0] = *pp;
+ dbits[0] &= ~(1U << (last & 7));
+ req->resp_bodybytes += WRW_Write(req->wrk, dbits, 1);
+ ll++;
+ sl--;
+ pp++;
+ }
+ if (sl > 0) {
+ /* Last block */
+ dl = stop / 8 - ll;
+ if (dl > 0) {
+ if (dl > sl)
+ dl = sl;
+ req->resp_bodybytes +=
+ WRW_Write(req->wrk, pp, dl);
+ ll += dl;
+ sl -= dl;
+ pp += dl;
+ }
+ }
+ if (sl > 0 && (stop & 7) && ll == stop / 8) {
+ /* Add alignment to byte boundary */
+ dbits[1] = *pp;
+ ll++;
+ sl--;
+ pp++;
+ switch((int)(stop & 7)) {
+ case 1: /*
+ * x000....
+ * 00000000 00000000 11111111 11111111
+ */
+ case 3: /*
+ * xxx000..
+ * 00000000 00000000 11111111 11111111
+ */
+ case 5: /*
+ * xxxxx000
+ * 00000000 00000000 11111111 11111111
+ */
+ dbits[2] = 0x00; dbits[3] = 0x00;
+ dbits[4] = 0xff; dbits[5] = 0xff;
+ lpad = 5;
+ break;
+ case 2: /* xx010000 00000100 00000001 00000000 */
+ dbits[1] |= 0x08;
+ dbits[2] = 0x20;
+ dbits[3] = 0x80;
+ dbits[4] = 0x00;
+ lpad = 4;
+ break;
+ case 4: /* xxxx0100 00000001 00000000 */
+ dbits[1] |= 0x20;
+ dbits[2] = 0x80;
+ dbits[3] = 0x00;
+ lpad = 3;
+ break;
+ case 6: /* xxxxxx01 00000000 */
+ dbits[1] |= 0x80;
+ dbits[2] = 0x00;
+ lpad = 2;
+ break;
+ case 7: /*
+ * xxxxxxx0
+ * 00......
+ * 00000000 00000000 11111111 11111111
+ */
+ dbits[2] = 0x00;
+ dbits[3] = 0x00; dbits[4] = 0x00;
+ dbits[5] = 0xff; dbits[6] = 0xff;
+ lpad = 6;
+ break;
+ case 0: /* xxxxxxxx */
+ default:
+ WRONG("compiler must be broken");
+ }
+ req->resp_bodybytes +=
+ WRW_Write(req->wrk, dbits + 1, lpad);
+ }
+ if (sl > 0) {
+ /* Recover GZIP tail */
+ dl = olen - ll;
+ assert(dl >= 0);
+ if (dl > sl)
+ dl = sl;
+ if (dl > 0) {
+ assert(dl <= 8);
+ l = ll - (olen - 8);
+ assert(l >= 0);
+ assert(l <= 8);
+ assert(l + dl <= 8);
+ memcpy(tailbuf + l, pp, dl);
+ ll += dl;
+ sl -= dl;
+ pp += dl;
+ }
+ }
+ } while (ois == OIS_DATA || ois == OIS_STREAM);
+ ObjIterEnd(&oi);
icrc = vle32dec(tailbuf);
ilen = vle32dec(tailbuf + 4);
More information about the varnish-commit
mailing list