--------------------- PatchSet 11754 Date: 2007/11/21 13:44:29 Author: hno Branch: HEAD Tag: (none) Log: Bug #7: Update stored headers with headers from 304 responses This patch updates the stored headers after seeing a 304 response. Currently implemented by rewriting the whole object but may be optimized to rewrite only the header portion the day the store interface supports this. Members: src/Makefile.am:1.64->1.65 src/Makefile.in:1.293->1.294 src/client_side.c:1.745->1.746 src/protos.h:1.542->1.543 src/store_update.c:INITIAL->1.1 Index: squid/src/Makefile.am =================================================================== RCS file: /cvsroot/squid/squid/src/Makefile.am,v retrieving revision 1.64 retrieving revision 1.65 diff -u -r1.64 -r1.65 --- squid/src/Makefile.am 15 Nov 2007 04:43:54 -0000 1.64 +++ squid/src/Makefile.am 21 Nov 2007 13:44:29 -0000 1.65 @@ -1,7 +1,7 @@ # # Makefile for the Squid Object Cache server # -# $Id: Makefile.am,v 1.64 2007/11/15 04:43:54 adrian Exp $ +# $Id: Makefile.am,v 1.65 2007/11/21 13:44:29 hno Exp $ # # Uncomment and customize the following to suit your needs: # @@ -248,6 +248,7 @@ store_swapin.c \ store_swapmeta.c \ store_swapout.c \ + store_update.c \ structs.h \ tools.c \ typedefs.h \ Index: squid/src/Makefile.in =================================================================== RCS file: /cvsroot/squid/squid/src/Makefile.in,v retrieving revision 1.293 retrieving revision 1.294 diff -u -r1.293 -r1.294 --- squid/src/Makefile.in 16 Nov 2007 01:12:47 -0000 1.293 +++ squid/src/Makefile.in 21 Nov 2007 13:44:29 -0000 1.294 @@ -17,7 +17,7 @@ # # Makefile for the Squid Object Cache server # -# $Id: Makefile.in,v 1.293 2007/11/16 01:12:47 hno Exp $ +# $Id: Makefile.in,v 1.294 2007/11/21 13:44:29 hno Exp $ # # Uncomment and customize the following to suit your needs: # @@ -111,9 +111,9 @@ ssl.c ssl_support.c stat.c StatHist.c String.c stmem.c store.c \ store_io.c store_client.c store_digest.c store_dir.c \ store_key_md5.c store_log.c store_rebuild.c store_swapin.c \ - store_swapmeta.c store_swapout.c structs.h tools.c typedefs.h \ - unlinkd.c url.c urn.c useragent.c wccp.c wccp2.c whois.c \ - win32.c + store_swapmeta.c store_swapout.c store_update.c structs.h \ + tools.c typedefs.h unlinkd.c url.c urn.c useragent.c wccp.c \ + wccp2.c whois.c win32.c @USE_DEVPOLL_FALSE@@USE_EPOLL_FALSE@@USE_KQUEUE_FALSE@@USE_POLL_FALSE@@USE_SELECT_FALSE@@USE_SELECT_SIMPLE_FALSE@@USE_SELECT_WIN32_TRUE@am__objects_1 = comm_select_win32.$(OBJEXT) @USE_DEVPOLL_FALSE@@USE_EPOLL_FALSE@@USE_KQUEUE_FALSE@@USE_POLL_FALSE@@USE_SELECT_SIMPLE_FALSE@@USE_SELECT_TRUE@am__objects_1 = comm_select.$(OBJEXT) @USE_DEVPOLL_FALSE@@USE_EPOLL_FALSE@@USE_KQUEUE_FALSE@@USE_POLL_FALSE@@USE_SELECT_SIMPLE_TRUE@am__objects_1 = comm_select_simple.$(OBJEXT) @@ -171,9 +171,9 @@ store_key_md5.$(OBJEXT) store_log.$(OBJEXT) \ store_rebuild.$(OBJEXT) store_swapin.$(OBJEXT) \ store_swapmeta.$(OBJEXT) store_swapout.$(OBJEXT) \ - tools.$(OBJEXT) $(am__objects_9) url.$(OBJEXT) urn.$(OBJEXT) \ - useragent.$(OBJEXT) wccp.$(OBJEXT) wccp2.$(OBJEXT) \ - whois.$(OBJEXT) $(am__objects_10) + store_update.$(OBJEXT) tools.$(OBJEXT) $(am__objects_9) \ + url.$(OBJEXT) urn.$(OBJEXT) useragent.$(OBJEXT) wccp.$(OBJEXT) \ + wccp2.$(OBJEXT) whois.$(OBJEXT) $(am__objects_10) nodist_squid_OBJECTS = repl_modules.$(OBJEXT) auth_modules.$(OBJEXT) \ store_modules.$(OBJEXT) globals.$(OBJEXT) \ string_arrays.$(OBJEXT) @@ -564,6 +564,7 @@ store_swapin.c \ store_swapmeta.c \ store_swapout.c \ + store_update.c \ structs.h \ tools.c \ typedefs.h \ @@ -893,6 +894,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/store_swapin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/store_swapmeta.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/store_swapout.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/store_update.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/string_arrays.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tools.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unlinkd.Po@am__quote@ Index: squid/src/client_side.c =================================================================== RCS file: /cvsroot/squid/squid/src/client_side.c,v retrieving revision 1.745 retrieving revision 1.746 diff -u -r1.745 -r1.746 --- squid/src/client_side.c 16 Nov 2007 11:38:46 -0000 1.745 +++ squid/src/client_side.c 21 Nov 2007 13:44:29 -0000 1.746 @@ -1,6 +1,6 @@ /* - * $Id: client_side.c,v 1.745 2007/11/16 11:38:46 adrian Exp $ + * $Id: client_side.c,v 1.746 2007/11/21 13:44:29 hno Exp $ * * DEBUG: section 33 Client-side Routines * AUTHOR: Duane Wessels @@ -851,6 +851,7 @@ * not the body they refer to. */ httpReplyUpdateOnNotModified(oldentry->mem_obj->reply, rep); storeTimestampsSet(oldentry); + storeUpdate(oldentry, http->request); } storeClientUnregister(http->sc, entry, http); http->sc = http->old_sc; Index: squid/src/protos.h =================================================================== RCS file: /cvsroot/squid/squid/src/protos.h,v retrieving revision 1.542 retrieving revision 1.543 diff -u -r1.542 -r1.543 --- squid/src/protos.h 16 Nov 2007 11:38:46 -0000 1.542 +++ squid/src/protos.h 21 Nov 2007 13:44:29 -0000 1.543 @@ -1,6 +1,6 @@ /* - * $Id: protos.h,v 1.542 2007/11/16 11:38:46 adrian Exp $ + * $Id: protos.h,v 1.543 2007/11/21 13:44:29 hno Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -969,6 +969,7 @@ void storeResumeRead(StoreEntry *); void storeResetDefer(StoreEntry *); extern int memHaveHeaders(const MemObject * mem); +extern void storeUpdate(StoreEntry * e, request_t *); /* store_modules.c */ --- /dev/null Wed Nov 21 13:52:00 2007 +++ squid/src/store_update.c Wed Nov 21 13:52:00 2007 @@ -0,0 +1,184 @@ + +/* + * $Id: store_update.c,v 1.1 2007/11/21 13:44:29 hno Exp $ + * + * DEBUG: section 20 Storage Manager + * AUTHOR: Henrik Nordstrom + * + * Copyright (C) 2007 Henrik Nordstrom + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#include "squid.h" + +/* Update the on-disk representation of the object to match + * current in-memory representation. This requires rewriting + * the object headers (bot meta and http) which isn't supported + * by the store layer today, so we rewrite the full object. + */ + +/* Local state */ +typedef struct { + StoreEntry *oldentry; + StoreEntry *newentry; + store_client *sc; + squid_off_t offset; + char buf[4096]; +} StoreUpdateState; + +CBDATA_TYPE(StoreUpdateState); + +static void +free_StoreUpdateState(void *data) +{ + StoreUpdateState *state = data; + if (state->sc) + storeClientUnregister(state->sc, state->oldentry, state); + if (state->oldentry) + storeUnlockObject(state->oldentry); + if (state->newentry) { + /* Set to NULL on completion, so we only get here in abnormal situations */ + storeRelease(state->newentry); + storeUnlockObject(state->newentry); + } +} + +static void +storeUpdateDone(StoreUpdateState * state) +{ + if (state->sc) { + store_client *sc = state->sc; + state->sc = NULL; + storeClientUnregister(sc, state->oldentry, state); + } + cbdataFree(state); +} +static void +storeUpdateAbort(void *data) +{ + StoreUpdateState *state = data; + storeUpdateDone(state); +} + +static void +storeUpdateCopy(void *data, char *buf, ssize_t size) +{ + StoreUpdateState *state = data; + + if (EBIT_TEST(state->newentry->flags, ENTRY_ABORTED)) { + debug(20, 1) ("storeUpdateCopy: Aborted at %d (%d)\n", (int) state->offset, (int) size); + /* the abort callback deals with the needed cleanup */ + return; + } + if (EBIT_TEST(state->newentry->flags, KEY_PRIVATE) && state->newentry->mem_obj->nclients == 0) { + debug(20, 2) ("storeUpdateCopy: Gone stale with no clients, skip copying of the rest\n"); + storeUpdateDone(state); + return; + } + if (size < 0) { + debug(20, 1) ("storeUpdateCopy: Error at %d (%d)\n", (int) state->offset, (int) size); + storeUpdateDone(state); + return; + } + if (size > 0) { + storeAppend(state->newentry, buf, size); + if (EBIT_TEST(state->newentry->flags, ENTRY_ABORTED)) { + debug(20, 1) ("storeUpdateCopy: Aborted on write at %d (%d)\n", (int) state->offset, (int) size); + return; + } + state->offset += size; + storeClientCopy(state->sc, state->oldentry, state->offset, state->offset, sizeof(state->buf), state->buf, storeUpdateCopy, state); + return; + } else { + storeComplete(state->newentry); + storeUnlockObject(state->newentry); + state->newentry = NULL; + storeUpdateDone(state); + } +} + +void +storeUpdate(StoreEntry * entry, request_t * request) +{ + StoreUpdateState *state; + request_flags flags = null_request_flags; + const char *vary; + + if (!request) + request = entry->mem_obj->request; + + if (EBIT_TEST(entry->flags, KEY_PRIVATE)) + return; /* Nothing to do here... */ + + CBDATA_INIT_TYPE_FREECB(StoreUpdateState, free_StoreUpdateState); + + if (entry->mem_obj) + entry->mem_obj->refresh_timestamp = 0; + state = cbdataAlloc(StoreUpdateState); + state->oldentry = entry; + storeLockObject(state->oldentry); + flags.cachable = 1; + state->newentry = storeCreateEntry(storeUrl(entry), flags, entry->mem_obj->method); + storeRegisterAbort(state->newentry, storeUpdateAbort, state); + state->sc = storeClientRegister(state->oldentry, state); + state->offset = entry->mem_obj->reply->hdr_sz; + storeBuffer(state->newentry); + httpReplySwapOut(httpReplyClone(entry->mem_obj->reply), state->newentry); + state->newentry->timestamp = entry->timestamp; + state->newentry->lastref = entry->lastref; + state->newentry->expires = entry->expires; + state->newentry->lastmod = entry->lastmod; + state->newentry->refcount = entry->refcount; + if (request) { + state->newentry->mem_obj->request = requestLink(request); + vary = httpMakeVaryMark(request, state->newentry->mem_obj->reply); + if (vary) { + state->newentry->mem_obj->vary_headers = xstrdup(vary); + if (strBuf(request->vary_encoding)) + entry->mem_obj->vary_encoding = xstrdup(strBuf(request->vary_encoding)); + } + } else { + if (entry->mem_obj->vary_headers) + state->newentry->mem_obj->vary_headers = xstrdup(entry->mem_obj->vary_headers); + if (entry->mem_obj->vary_encoding) + state->newentry->mem_obj->vary_encoding = xstrdup(entry->mem_obj->vary_encoding); + } + storeSetPublicKey(state->newentry); + storeBufferFlush(state->newentry); + if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { + /* + * the above storeBufferFlush() call could ABORT this entry, + * in that case, there's nothing for us to do. + */ + debug(20, 1) ("storeUpdate: Aborted on write\n"); + return; + } + storeClientCopy(state->sc, state->oldentry, state->offset, state->offset, sizeof(state->buf), state->buf, storeUpdateCopy, state); + return; +}