--------------------- PatchSet 4703 Date: 2002/08/16 01:12:32 Author: rbcollins Branch: esi Tag: (none) Log: henrik's vary bugfix, plus request status refactoring Members: src/ESI.c:1.1.2.8->1.1.2.9 src/client_side.c:1.65.2.14->1.65.2.15 src/client_side_reply.c:1.1.2.12->1.1.2.13 src/enums.h:1.37.2.2->1.37.2.3 src/protos.h:1.59.2.8->1.59.2.9 Index: squid/src/ESI.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/Attic/ESI.c,v retrieving revision 1.1.2.8 retrieving revision 1.1.2.9 diff -u -r1.1.2.8 -r1.1.2.9 --- squid/src/ESI.c 15 Aug 2002 09:17:15 -0000 1.1.2.8 +++ squid/src/ESI.c 16 Aug 2002 01:12:32 -0000 1.1.2.9 @@ -1,6 +1,6 @@ /* - * $Id: ESI.c,v 1.1.2.8 2002/08/15 09:17:15 rbcollins Exp $ + * $Id: ESI.c,v 1.1.2.9 2002/08/16 01:12:32 rbcollins Exp $ * * DEBUG: section 86 ESI processing * AUTHOR: Robert Collins @@ -642,24 +642,31 @@ /* after the write to the user occurs, (ie here, or in a callback) * we call */ - switch (clientDetermineActionAfterWrite(-1, http, http->entry, body_size)){ - case 0: /* fallthru ok */ - case 1: /* ok */ + if (clientHttpRequestStatus(-1, http)) { + esiStreamContext *temp = esiStream; + /* ESI TODO: Tell the initiator we've failed */ + cbdataReferenceDone (esiStream); + cbdataFree (temp); /* free the request */ + return; + }; + switch (clientStreamStatus (node, http)) { + case STREAM_UNPLANNED_COMPLETE: /* fallthru ok */ + case STREAM_COMPLETE: /* ok */ // usertell request finished debug (86,0)("ESI subrequest finished OK\n"); cbdataReferenceDone (esiStream); httpRequestFree (http); return; - case 2: + case STREAM_FAILED: // usertell request failed debug (86,0)("ESI subrequest failed transfer\n"); cbdataReferenceDone (esiStream); httpRequestFree (http); return; - case 3: + case STREAM_NONE: /* More data will be coming from primary server; register with * storage manager. */ - clientStreamRead (node->node.prev->data, + clientStreamRead (node, http, http->out.offset, HTTP_REQBUF_SZ, esiStream->localbuf.buf); Index: squid/src/client_side.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/client_side.c,v retrieving revision 1.65.2.14 retrieving revision 1.65.2.15 diff -u -r1.65.2.14 -r1.65.2.15 --- squid/src/client_side.c 15 Aug 2002 14:12:02 -0000 1.65.2.14 +++ squid/src/client_side.c 16 Aug 2002 01:12:32 -0000 1.65.2.15 @@ -1,6 +1,6 @@ /* - * $Id: client_side.c,v 1.65.2.14 2002/08/15 14:12:02 rbcollins Exp $ + * $Id: client_side.c,v 1.65.2.15 2002/08/16 01:12:32 rbcollins Exp $ * * DEBUG: section 33 Client-side Routines * AUTHOR: Duane Wessels @@ -292,6 +292,7 @@ conn = http->conn; request = http->request; debug(33, 3) ("httpRequestFree: %s\n", http->uri); + /* FIXME: This needs to use the stream */ if (!clientCheckTransferDone(http)) { if (request && request->body_connection) clientAbortBody(request); /* abort body transter */ @@ -585,7 +586,7 @@ } else { debug(33, 2) ("clientKeepaliveNextRequest: FD %d Sending next\n", conn->fd); - /* If the client stream is waiting on a socket write to occured, thenm */ + /* If the client stream is waiting on a socket write to occur, then */ if (context->flags.deferred) { /* NO data is allowed to have been sent */ assert (http->out.size == 0); @@ -610,6 +611,8 @@ clientSocketContext *context = data; clientHttpRequest *http = context->http; StoreEntry *entry = http->entry; + /* cheating: we are always the tail */ + clientStreamNode *node = http->client_stream.tail->data; http->out.size += size; debug(33, 5) ("clientWriteComplete: FD %d, sz %ld, err %d, off %ld, len %d\n", fd, (long int) size, errflag, (long int) http->out.size, entry ? objectLen(entry) : 0); @@ -627,24 +630,30 @@ comm_close(fd); return; } - switch (clientDetermineActionAfterWrite(fd, http, entry, size)){ - case 0: - debug(33, 5) ("clientWriteComplete: FD %d Keeping Alive\n", fd); - clientKeepaliveNextRequest(context); - return; - case 1: /* fallthru */ - case 2: - if (fd != -1) - comm_close (fd); - return; - case 3: - /* More data will be coming from the stream. */ - clientStreamRead (http->client_stream.tail->data, http, http->out.offset, - HTTP_REQBUF_SZ, - context->reqbuf); - - break; - default:fatal ("Hit unreachable code in clientWriteComplete\n"); + if (clientHttpRequestStatus(fd, http)) { + if (fd != -1) + comm_close (fd); + /* Do we leak here ?*/ + return; + } + switch (clientStreamStatus (node, http)) { + case STREAM_NONE: + /* More data will be coming from the stream. */ + clientStreamRead (http->client_stream.tail->data, http, http->out.offset, + HTTP_REQBUF_SZ, + context->reqbuf); + break; + case STREAM_COMPLETE: + debug(33, 5) ("clientWriteComplete: FD %d Keeping Alive\n", fd); + clientKeepaliveNextRequest(context); + return; + case STREAM_UNPLANNED_COMPLETE: + /* fallthrough */ + case STREAM_FAILED: + if (fd != -1) + comm_close (fd); + return; + default:fatal ("Hit unreachable code in clientWriteComplete\n"); } } @@ -1799,17 +1808,21 @@ /* virtual "vary" object found. Calculate the vary key and * continue the search */ - vary = request->vary_headers = xstrdup(httpMakeVaryMark(request, entry->mem_obj->reply)); - if (vary) + vary = httpMakeVaryMark(request, entry->mem_obj->reply); + if (vary) { + request->vary_headers = xstrdup(vary); return VARY_OTHER; - else { + } else { /* Ouch.. we cannot handle this kind of variance */ /* XXX This cannot really happen, but just to be complete */ return VARY_CANCEL; } } else { - if (!vary) - vary = request->vary_headers = xstrdup(httpMakeVaryMark(request, entry->mem_obj->reply)); + if (!vary) { + vary = httpMakeVaryMark(request, entry->mem_obj->reply); + if (vary) + request->vary_headers = xstrdup(vary); + } if (!vary) { /* Ouch.. we cannot handle this kind of variance */ /* XXX This cannot really happen, but just to be complete */ Index: squid/src/client_side_reply.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/Attic/client_side_reply.c,v retrieving revision 1.1.2.12 retrieving revision 1.1.2.13 diff -u -r1.1.2.12 -r1.1.2.13 --- squid/src/client_side_reply.c 15 Aug 2002 09:17:15 -0000 1.1.2.12 +++ squid/src/client_side_reply.c 16 Aug 2002 01:12:32 -0000 1.1.2.13 @@ -1,6 +1,6 @@ /* - * $Id: client_side_reply.c,v 1.1.2.12 2002/08/15 09:17:15 rbcollins Exp $ + * $Id: client_side_reply.c,v 1.1.2.13 2002/08/16 01:12:32 rbcollins Exp $ * * DEBUG: section 88 Client-side Reply Routines * AUTHOR: Robert Collins (Originally Duane Wessels in client_side.c) @@ -50,6 +50,7 @@ #endif struct { int storelogiccomplete:1; + int complete:1; /* we have read all we can from upstream */ } flags; clientStreamNode *ourNode; /* This will go away if/when this file gets refactored some more */ } clientReplyContext; @@ -74,6 +75,7 @@ static StoreEntry *clientCreateStoreEntry(clientReplyContext *, method_t, request_flags); static STCB clientSendMoreData; static void clientRemoveStoreReference (clientReplyContext *, store_client **, StoreEntry **); +extern CSS clientReplyStatus; extern ErrorState *clientBuildError (err_type, http_status, char const *, struct in_addr *, request_t *); /* The clientReply clean interface */ @@ -895,75 +897,80 @@ } -/* A write has completed, what is the next status: - * 0 transfer complete ok, persistent connections allowed - * 1 transfer complete ok, persistent connections not allowed - * 2 transfer failed - * 3 transfer incomplete +/* A write has completed, what is the next status based on the + * canonical request data? + * 1 something is wrong + * 0 nothing is wrong. * - * Preconditions: - * *http is a valid structure. - * fd is either -1, or an open fd. - * - * TODO: enumify this - * - * This function is used by any http request sink, to determine the status - * of the object. */ int -clientDetermineActionAfterWrite(int fd, clientHttpRequest const *http, StoreEntry *entry, size_t size) +clientHttpRequestStatus (int fd, clientHttpRequest const *http) { - int done; #if SIZEOF_SIZE_T == 4 if (http->out.size > 0x7FFF0000) { - debug(88, 1) ("WARNING: closing FD %d to prevent counter overflow\n", fd); - debug(88, 1) ("\tclient %s\n", inet_ntoa(http->conn ? http->conn->peer.sin_addr : no_addr)); - debug(88, 1) ("\treceived %d bytes\n", (int) http->out.size); - debug(88, 1) ("\tURI %s\n", http->log_uri); - return 2; + debug(88, 1) ("WARNING: closing FD %d to prevent counter overflow\n", fd); + debug(88, 1) ("\tclient %s\n", inet_ntoa(http->conn ? http->conn->peer.sin_addr : no_addr)); + debug(88, 1) ("\treceived %d bytes\n", (int) http->out.size); + debug(88, 1) ("\tURI %s\n", http->log_uri); + return 1; } #endif #if SIZEOF_OFF_T == 4 if (http->out.offset > 0x7FFF0000) { - debug(88, 1) ("WARNING: closing FD %d to prevent counter overflow\n", fd); - debug(88, 1) ("\tclient %s\n", inet_ntoa(http->conn ? http->conn->peer.sin_addr : no_addr)); - debug(88, 1) ("\treceived %d bytes (offset %d)\n", (int) http->out.size, (int) http->out.offset); - debug(88, 1) ("\tURI %s\n", http->log_uri); - return 2; + debug(88, 1) ("WARNING: closing FD %d to prevent counter overflow\n", fd); + debug(88, 1) ("\tclient %s\n", inet_ntoa(http->conn ? http->conn->peer.sin_addr : no_addr)); + debug(88, 1) ("\treceived %d bytes (offset %d)\n", (int) http->out.size, (int) http->out.offset); + debug(88, 1) ("\tURI %s\n", http->log_uri); + return 1; } #endif - if (entry == NULL) - return 2; /* yuk */ - if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) - /* TODO: Could upstream read errors (retsize < 0) be - * lost, and result in undersize requests being considered - * complete. Should we tcp reset such connections ? - */ - return 2; - if ((done = clientCheckTransferDone(http)) != 0 || size == 0) { - debug(88, 5) ("clientWriteComplete: FD %d transfer is DONE\n", fd); - /* Ok we're finished, but how? */ - if (httpReplyBodySize(http->request->method, entry->mem_obj->reply) < 0) { - debug(88, 5) ("clientWriteComplete: closing, content_length < 0\n"); - return 2; - } else if (!done) { - debug(88, 5) ("clientWriteComplete: closing, !done, but read 0 bytes\n"); - return 2; - } else if (clientGotNotEnough(http)) { - debug(88, 5) ("clientWriteComplete: client didn't get all it expected\n"); - return 2; - } else if (http->request->flags.proxy_keepalive) { - return 0; /* allow keepalive */ - } - return 1; /* don't allow keepalive */ + return 0; +} + +/* Preconditions: + * *http is a valid structure. + * fd is either -1, or an open fd. + * + * TODO: enumify this + * + * This function is used by any http request sink, to determine the status + * of the object. + */ +clientStream_status_t +clientReplyStatus (clientStreamNode *this, clientHttpRequest *http) +{ + clientReplyContext *context = this->data; + int done; + /* Here because lower nodes don't need it */ + if (http->entry == NULL) + return STREAM_FAILED; /* yuck, but what can we do? */ + if (EBIT_TEST(http->entry->flags, ENTRY_ABORTED)) + /* TODO: Could upstream read errors (retsize < 0) be + * lost, and result in undersize requests being considered + * complete. Should we tcp reset such connections ? + */ + return STREAM_FAILED; + if ((done = clientCheckTransferDone(http)) != 0 || context->flags.complete) { + debug(88, 5) ("clientReplyStatus: transfer is DONE\n"); + /* Ok we're finished, but how? */ + if (httpReplyBodySize(http->request->method, http->entry->mem_obj->reply) < 0) { + debug(88, 5) ("clientWriteComplete: closing, content_length < 0\n"); + return STREAM_FAILED; + } else if (!done) { + debug(88, 5) ("clientWriteComplete: closing, !done, but read 0 bytes\n"); + return STREAM_FAILED; + } else if (clientGotNotEnough(http)) { + debug(88, 5) ("clientWriteComplete: client didn't get all it expected\n"); + return STREAM_UNPLANNED_COMPLETE; + } else if (http->request->flags.proxy_keepalive) { + return STREAM_COMPLETE; + } + return STREAM_UNPLANNED_COMPLETE; + } - if (clientReplyBodyTooLarge(entry->mem_obj->reply, http->out.offset)) - return 2; - /* More data will be coming from primary server; register with - * storage manager. */ - if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) - fatal ("entry aborted DURING clientWriteComplete \n"); - return 3; + if (clientReplyBodyTooLarge(http->entry->mem_obj->reply, http->out.offset)) + return STREAM_FAILED; + return STREAM_NONE; } /* Responses with no body will not have a content-type header, @@ -1185,13 +1192,6 @@ return LOG_TCP_HIT; } -extern CSS clientReplyStatus; - -clientStream_status_t -clientReplyStatus (clientStreamNode *this, clientHttpRequest *http) { - return STREAM_FAILED; -} - /* Request more data from the store for the client Stream * This is *the* entry point to this module. * @@ -1314,6 +1314,7 @@ /* We call into the stream, because we don't know that there is a * client socket! */ + context->flags.complete = 1; clientStreamCallback (http->client_stream.head->data, http, NULL, NULL, 0); /* clientWriteComplete(fd, NULL, 0, COMM_OK, http); */ return; @@ -1322,6 +1323,8 @@ * HEAD and may not be true for pipelining. * */ if (http->out.offset != 0) { + if (retsize == 0) + context->flags.complete = 1; clientStreamCallback (http->client_stream.head->data, http, NULL, buf, size); return; } @@ -1415,6 +1418,7 @@ /* ESI TODO: Can ESI affect headers on the master document */ body_size = 0; http->flags.done_copying = 1; + context->flags.complete = 1; } else { /* * If we are here, then store_status == STORE_OK and it @@ -1425,6 +1429,7 @@ * continue... */ http->flags.done_copying = 1; + context->flags.complete = 1; } } assert(rep || (body_buf && body_size)); Index: squid/src/enums.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/enums.h,v retrieving revision 1.37.2.2 retrieving revision 1.37.2.3 diff -u -r1.37.2.2 -r1.37.2.3 --- squid/src/enums.h 15 Aug 2002 09:17:15 -0000 1.37.2.2 +++ squid/src/enums.h 16 Aug 2002 01:12:32 -0000 1.37.2.3 @@ -1,6 +1,6 @@ /* - * $Id: enums.h,v 1.37.2.2 2002/08/15 09:17:15 rbcollins Exp $ + * $Id: enums.h,v 1.37.2.3 2002/08/16 01:12:32 rbcollins Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -522,6 +522,10 @@ typedef enum { STREAM_NONE, /* No particular status */ STREAM_COMPLETE, /* All data has been flushed, no more reads allowed */ + STREAM_UNPLANNED_COMPLETE, /* an unpredicted end has occured, no more + reads occured, but no need to tell + downstream that an error occured + */ STREAM_FAILED /* An error has occured in this node or an above one, * and the node is not generating an error body / it's * midstream Index: squid/src/protos.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/protos.h,v retrieving revision 1.59.2.8 retrieving revision 1.59.2.9 diff -u -r1.59.2.8 -r1.59.2.9 --- squid/src/protos.h 15 Aug 2002 09:17:15 -0000 1.59.2.8 +++ squid/src/protos.h 16 Aug 2002 01:12:32 -0000 1.59.2.9 @@ -1,6 +1,6 @@ /* - * $Id: protos.h,v 1.59.2.8 2002/08/15 09:17:15 rbcollins Exp $ + * $Id: protos.h,v 1.59.2.9 2002/08/16 01:12:32 rbcollins Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -149,7 +149,7 @@ /* client_side_reply.c - client side reply related routines (pure logic, no comms) */ extern int clientCheckTransferDone(clientHttpRequest const *); extern void *clientReplyNewContext (clientHttpRequest *); -extern int clientDetermineActionAfterWrite(int fd, clientHttpRequest const *http, StoreEntry *entry, size_t size); +extern int clientHttpRequestStatus (int fd, clientHttpRequest const *http); extern void clientSetReplyToError (void *,err_type,http_status,method_t,char const *,struct in_addr *, request_t *, char *,auth_user_request_t *auth_user_request); /* clientStream.c */