--------------------- PatchSet 4939 Date: 2007/06/26 07:08:40 Author: adri Branch: squid3_adri Tag: (none) Log: Begin fleshing out some test writev() code to replace the packer+write() combination used to write HTTP requests and replies. Members: src/comm.cc:1.74.6.1->1.74.6.2 src/comm.h:1.23.14.1->1.23.14.2 Index: squid3/src/comm.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/comm.cc,v retrieving revision 1.74.6.1 retrieving revision 1.74.6.2 diff -u -r1.74.6.1 -r1.74.6.2 --- squid3/src/comm.cc 29 May 2007 14:45:33 -0000 1.74.6.1 +++ squid3/src/comm.cc 26 Jun 2007 07:08:40 -0000 1.74.6.2 @@ -1,6 +1,6 @@ /* - * $Id: comm.cc,v 1.74.6.1 2007/05/29 14:45:33 adri Exp $ + * $Id: comm.cc,v 1.74.6.2 2007/06/26 07:08:40 adri Exp $ * * DEBUG: section 5 Socket Functions * AUTHOR: Harvest Derived @@ -54,6 +54,9 @@ #include #endif +#include + + /* * New C-like simple comm code. This stuff is a mess and doesn't really buy us anything. */ @@ -77,6 +80,10 @@ bool completed; comm_err_t errcode; int xerrno; + struct { + struct iovec *iov; /* iovec being written */ + int iovcnt; /* how many items in the list, can change over the course of the write */ + } wv; dlink_node node; }; typedef struct _comm_io_callback comm_io_callback_t; @@ -259,6 +266,7 @@ static void commSetTcpRcvbuf(int, int); static PF commConnectFree; static PF commHandleWrite; +static PF commHandleWriteV; static IPH commConnectDnsHandle; static void requireOpenAndActive(int const fd); @@ -1835,6 +1843,70 @@ conn_close_pool = memPoolCreate("close_handler", sizeof(close_handler)); } +static void +commHandleWriteV(int fd, void *data) +{ + comm_io_callback_t *state = (comm_io_callback_t *) data; + int len = 0; + int nleft; + + assert (state == COMMIO_FD_WRITECB(fd)); + + debugs(5, 5, "commHandleWriteV: FD " << fd << ": off " << + (long int) state->offset << ", sz " << (long int) state->size << "."); + + nleft = state->size - state->offset; + len = writev(fd, state->wv.iov, state->wv.iovcnt); + debugs(5, 5, "commHandleWrite: write() returns " << len); + fd_bytes(fd, len, FD_WRITE); + statCounter.syscalls.sock.writes++; + + if (len == 0) { + /* EOF? */ + if (nleft != 0) + debugs(5, 1, "commHandleWriteV: FD " << fd << ": write failure: connection closed with " << nleft << " bytes remaining."); + commio_complete_callback(fd, COMMIO_FD_WRITECB(fd), nleft ? COMM_ERROR : COMM_OK, errno); + xfree(state->wv.iov); + return; + } + + if (len < 0) { + /* error */ + if (fd_table[fd].flags.socket_eof) { + debugs(50, 2, "commHandleWriteV: FD " << fd << ": write failure: " << xstrerror() << "."); + commio_complete_callback(fd, COMMIO_FD_WRITECB(fd), nleft ? COMM_ERROR : COMM_OK, errno); + xfree(state->wv.iov); + } else if (ignoreErrno(errno)) { + debugs(50, 10, "commHandleWrite: FD " << fd << ": write failure: " << xstrerror() << "."); + commSetSelect(fd, COMM_SELECT_WRITE, commHandleWrite, state, 0); + } else { + debugs(50, 2, "commHandleWrite: FD " << fd << ": write failure: " << xstrerror() << "."); + commio_complete_callback(fd, COMMIO_FD_WRITECB(fd), nleft ? COMM_ERROR : COMM_OK, errno); + xfree(state->wv.iov); + } + return; + } + + /* len > 0, we've written some data */ + + /* First shortcut; have we written all the data thats left in the iovec? If so, finish */ + state->offset += len; + assert(state->offset <= state->size); + if (state->offset >= state->size) { + debugs(50, 2, "commHandleWriteV: FD " << fd << ": write complete in one hit!"); + commio_complete_callback(fd, COMMIO_FD_WRITECB(fd), COMM_OK, 0); + xfree(state->wv.iov); + return; + } + + /* + * A partial write, we need to find where in the iovec list we got to. + * We can't assume that only entire iovec's were written, so we have + * to find which iovecs were fully written, then possibly tweak the + * head iovec to point part-way into the buffer. + */ +} + /* Write to FD. */ static void commHandleWrite(int fd, void *data) { @@ -1928,6 +2000,31 @@ comm_write(fd, mb->buf, mb->size, handler, handler_data, mb->freeFunc()); } +/* + * This should be viewed as a temporary routine. + * + * Buffers pointed to by *iov must stay about for the lifetime of this write. + * the iov buffer will be xfree()'ed after use. + */ +void +comm_writev(int fd, struct iovec *iov, int iovcnt, int size, IOCB * handler, void *handler_data) +{ + assert(! fd_table[fd].flags.closing); + debugs(5, 5, "comm_writev: FD " << fd << ": iovcnt " << iovcnt << ": hndl " << handler << ": data " << handler_data << "."); + + if (commio_has_callback(fd, IOCB_WRITE, COMMIO_FD_WRITECB(fd))) { + /* This means that the write has been scheduled, but has not + * triggered yet + */ + fatalf ("comm_write: fd %d: pending callback!\n", fd); + } + /* XXX ugly */ + commio_set_callback(fd, IOCB_WRITE, COMMIO_FD_WRITECB(fd), handler, handler_data, NULL, NULL, size); + COMMIO_FD_WRITECB(fd)->wv.iov = iov; + COMMIO_FD_WRITECB(fd)->wv.iovcnt = iovcnt; + commSetSelect(fd, COMM_SELECT_WRITE, commHandleWriteV, COMMIO_FD_WRITECB(fd), 0); +} + /* * hm, this might be too general-purpose for all the places we'd Index: squid3/src/comm.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/comm.h,v retrieving revision 1.23.14.1 retrieving revision 1.23.14.2 diff -u -r1.23.14.1 -r1.23.14.2 --- squid3/src/comm.h 29 May 2007 14:45:33 -0000 1.23.14.1 +++ squid3/src/comm.h 26 Jun 2007 07:08:40 -0000 1.23.14.2 @@ -60,6 +60,7 @@ SQUIDCEXTERN int comm_udp_sendto(int, const struct sockaddr_in *, int, const void *, int); extern void comm_write(int fd, const char *buf, int len, IOCB *callback, void *callback_data, FREE *func); SQUIDCEXTERN void comm_write_mbuf(int fd, MemBuf *mb, IOCB * handler, void *handler_data); +SQUIDCEXTERN void comm_writev(int fd, struct iovec *iov, int iovcnt, int size, IOCB * handler, void *handler_data); SQUIDCEXTERN void commCallCloseHandlers(int fd); SQUIDCEXTERN int commSetTimeout(int fd, int, PF *, void *); SQUIDCEXTERN int ignoreErrno(int);