--------------------- PatchSet 4888 Date: 2007/06/26 15:25:23 Author: adri Branch: squid3_adri Tag: (none) Log: Bring over the test implemenation of iovec+writev for client-side HTTP replies. It seems to work with casual browsing.. Members: src/HttpReply.cc:1.41.2.1->1.41.2.2 src/HttpReply.h:1.19.2.1->1.19.2.2 src/client_side.cc:1.128.2.1->1.128.2.2 Index: squid3/src/HttpReply.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/HttpReply.cc,v retrieving revision 1.41.2.1 retrieving revision 1.41.2.2 diff -u -r1.41.2.1 -r1.41.2.2 --- squid3/src/HttpReply.cc 29 May 2007 14:45:31 -0000 1.41.2.1 +++ squid3/src/HttpReply.cc 26 Jun 2007 15:25:23 -0000 1.41.2.2 @@ -1,6 +1,6 @@ /* - * $Id: HttpReply.cc,v 1.41.2.1 2007/05/29 14:45:31 adri Exp $ + * $Id: HttpReply.cc,v 1.41.2.2 2007/06/26 15:25:23 adri Exp $ * * DEBUG: section 58 HTTP Reply (Response) * AUTHOR: Alex Rousskov @@ -122,6 +122,7 @@ hdrCacheClean(); header.clean(); httpStatusLineClean(&sline); + xfree(status_line); } void @@ -132,6 +133,101 @@ packerAppend(p, "\r\n", 2); } +/* + * This is a heavily hacked up specific routine which breaks layering + * all over the place. + */ +struct iovec * +HttpReply::getIoVecList(int *iovcnt, int *size, int numreserve) +{ + struct iovec *iov; + HttpHeaderEntry * e; + int i = 0; + int n; + int slen; + + (*iovcnt) = 0; + (*size) = 0; + /* Calculate the iovcnt size up front */ + slen = asprintf(&status_line, "HTTP/%d.%d %3d %s\r\n", sline.version.major, sline.version.minor, sline.status, httpStatusLineReason(&sline)); + + /* Status line */ + /* XXX this requires some.. hackery; as the status line is generated during packing! */ + (*iovcnt) ++; + + /* Headers */ + /* This requires four iovec's per header: HEADER, ": ", VALUE, "\r\n" */ + /* + * Now, there might be "invalid" slots in the header entries array; + * we assume they're all full here and then "adjust" the final iovcnt + * value to reflect how many we actually consumed. + */ + (*iovcnt) += (header.entries.count) * 4; + + /* \r\n separator */ + (*iovcnt)++; + + /* Reply body, if any here */ + if (body.mb->contentSize()) + (*iovcnt)++; + + + /* --- Now, build the iov --- */ +#undef malloc + iov = (struct iovec *) std::malloc(((*iovcnt) + numreserve) * sizeof(struct iovec)); + assert(iov); + + /* Add status line */ + iov[i].iov_base = (void *) status_line; + iov[i].iov_len = slen; + *size += iov[i].iov_len; + i++; + + /* Add headers */ + for (n = 0; n < (ssize_t) header.entries.count; n++) { + if (header.entries.items[n]) { + e = header.entries.items[n]; + iov[i].iov_base = (void *) e->name.buf(); + iov[i].iov_len = e->name.size(); + *size += iov[i].iov_len; + i++; + + iov[i].iov_base = (void *) ": "; + iov[i].iov_len = 2; + *size += iov[i].iov_len; + i++; + + iov[i].iov_base = (void *) e->value.buf(); + iov[i].iov_len = e->value.size(); + *size += iov[i].iov_len; + i++; + + iov[i].iov_base = (void *) "\r\n"; + iov[i].iov_len = 2; + *size += iov[i].iov_len; + i++; + } + } + + /* Add \r\n seperator */ + iov[i].iov_base = (void *) "\r\n"; + iov[i].iov_len = 2; + *size += iov[i].iov_len; + i++; + + /* Add reply body, if any */ + if (body.mb->contentSize()) { + iov[i].iov_base = (void *) body.mb->content(); + iov[i].iov_len = body.mb->contentSize(); + *size += iov[i].iov_len; + i++; + } + /* reset iovcnt as the initial assumption might've been too large .. */ + assert(i > 0); + *iovcnt = i; + return iov; +} + void HttpReply::packInto(Packer * p) { Index: squid3/src/HttpReply.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/HttpReply.h,v retrieving revision 1.19.2.1 retrieving revision 1.19.2.2 diff -u -r1.19.2.1 -r1.19.2.2 --- squid3/src/HttpReply.h 29 May 2007 14:45:32 -0000 1.19.2.1 +++ squid3/src/HttpReply.h 26 Jun 2007 15:25:23 -0000 1.19.2.2 @@ -1,6 +1,6 @@ /* - * $Id: HttpReply.h,v 1.19.2.1 2007/05/29 14:45:32 adri Exp $ + * $Id: HttpReply.h,v 1.19.2.2 2007/06/26 15:25:23 adri Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -111,6 +111,9 @@ /* mem-pack: returns a ready to use mem buffer with a packed reply */ MemBuf *pack(); + /* Build and return an iovec list */ + struct iovec * getIoVecList(int *iovcnt, int *size, int numreserve); + /* construct a 304 reply and return it */ HttpReply *make304() const; @@ -138,6 +141,7 @@ /* header manipulation */ time_t hdrExpirationTime(); + char * status_line; protected: virtual void packFirstLineInto(Packer * p, bool) const; Index: squid3/src/client_side.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/client_side.cc,v retrieving revision 1.128.2.1 retrieving revision 1.128.2.2 diff -u -r1.128.2.1 -r1.128.2.2 --- squid3/src/client_side.cc 29 May 2007 14:45:33 -0000 1.128.2.1 +++ squid3/src/client_side.cc 26 Jun 2007 15:25:23 -0000 1.128.2.2 @@ -1,6 +1,6 @@ /* - * $Id: client_side.cc,v 1.128.2.1 2007/05/29 14:45:33 adri Exp $ + * $Id: client_side.cc,v 1.128.2.2 2007/06/26 15:25:23 adri Exp $ * * DEBUG: section 33 Client-side Routines * AUTHOR: Duane Wessels @@ -1185,16 +1185,21 @@ void ClientSocketContext::sendStartOfMessage(HttpReply * rep, StoreIOBuffer bodyData) { + struct iovec *iov; + int iovcnt; + int iovsize; prepareReply(rep); assert (rep); - MemBuf *mb = rep->pack(); + //MemBuf *mb = rep->pack(); + iov = rep->getIoVecList(&iovcnt, &iovsize, 4); /* Save length of headers for persistent conn checks */ - http->out.headers_sz = mb->contentSize(); + //http->out.headers_sz = mb->contentSize(); + http->out.headers_sz = iovsize; #if HEADERS_LOG - headersLog(0, 0, http->request->method, rep); #endif +#if 0 if (bodyData.data && bodyData.length) { if (!multipartRangeRequest()) { size_t length = lengthToSend(bodyData.range()); @@ -1208,8 +1213,16 @@ /* write */ comm_write_mbuf(fd(), mb, clientWriteComplete, this); - delete mb; +#endif + if (bodyData.data && bodyData.length && ! multipartRangeRequest()) { + iov[iovcnt].iov_base = (void *) bodyData.data; + iov[iovcnt].iov_len = bodyData.length; + iovcnt++; + iovsize += bodyData.length; + noteSentBodyBytes(bodyData.length); + } + comm_writev(fd(), iov, iovcnt, iovsize, clientWriteComplete, this); } /*