--------------------- PatchSet 2413 Date: 2001/05/30 23:17:30 Author: hno Branch: etag Tag: (none) Log: If-None-Match queries to locate the correct entity variant for this request Members: src/client_side.c:1.29.2.5->1.29.2.6 src/http.c:1.13.14.4->1.13.14.5 src/protos.h:1.29.2.2->1.29.2.3 src/store.c:1.12.14.9->1.12.14.10 src/structs.h:1.33.4.3->1.33.4.4 Index: squid/src/client_side.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/client_side.c,v retrieving revision 1.29.2.5 retrieving revision 1.29.2.6 diff -u -r1.29.2.5 -r1.29.2.6 --- squid/src/client_side.c 30 May 2001 21:37:28 -0000 1.29.2.5 +++ squid/src/client_side.c 30 May 2001 23:17:30 -0000 1.29.2.6 @@ -1,6 +1,6 @@ /* - * $Id: client_side.c,v 1.29.2.5 2001/05/30 21:37:28 hno Exp $ + * $Id: client_side.c,v 1.29.2.6 2001/05/30 23:17:30 hno Exp $ * * DEBUG: section 33 Client-side Routines * AUTHOR: Duane Wessels @@ -354,6 +354,37 @@ clientHandleETagMiss(clientHttpRequest *http) { StoreEntry *entry = http->entry; + MemObject *mem = entry->mem_obj; + request_t *request = http->request; + + if (mem->reply) { + const char *etag = httpHeaderGetStr(&mem->reply->header, HDR_ETAG); + if (etag) { + /* This has to match storeSetPublicKey, except for the key which is NULL */ + String vary = StringNull; + String varyhdr; + varyhdr = httpHeaderGetList(&mem->reply->header, HDR_VARY); + if (strBuf(varyhdr)) + strListAdd(&vary, strBuf(varyhdr), ','); + stringClean(&varyhdr); +#if X_ACCELERATOR_VARY + /* This needs to match the order in http.c:httpMakeVaryMark */ + varyhdr = httpHeaderGetList(&mem->reply->header, HDR_X_ACCELERATOR_VARY); + if (strBuf(varyhdr)) + strListAdd(&vary, strBuf(varyhdr), ','); + stringClean(&varyhdr); +#endif + storeAddVary(mem->url, mem->log_url, mem->method, NULL, httpHeaderGetStr(&mem->reply->header, HDR_ETAG), strBuf(vary), httpMakeVaryMark(request, mem->reply)); + } + } + request->done_etag = 1; + if (request->vary) { + storeLocateVaryDone(request->vary); + request->vary = NULL; + request->etags = NULL; /* pointed into request->vary */ + } + safe_free(request->etag); + safe_free(request->vary_headers); storeUnregister(http->sc, entry, http); storeUnlockObject(entry); clientProcessRequest(http); @@ -383,14 +414,14 @@ memFree(buf, MEM_CLIENT_SOCK_BUF); clientHandleETagMiss(http); return; - } else if (STORE_PENDING == entry->store_status && 0 == status) { + } + if (STORE_PENDING == entry->store_status && 0 == status) { debug(33, 3) ("clientHandleETagReply: Incomplete headers for '%s'\n", url); if (size >= CLIENT_SOCK_SZ) { /* will not get any bigger than that */ debug(33, 3) ("clientHandleETagReply: Reply is too large '%s'\n", url); memFree(buf, MEM_CLIENT_SOCK_BUF); clientHandleETagMiss(http); - return; } else { storeClientCopy(http->sc, entry, http->out.offset + size, @@ -399,12 +430,15 @@ buf, clientHandleETagReply, http); - return; } + return; + } + if (HTTP_NOT_MODIFIED == mem->reply->sline.status) { + /* Remember the ETag and restart */ + memFree(buf, MEM_CLIENT_SOCK_BUF); + clientHandleETagMiss(http); } else { - /* XXX Much more to do here. This only covers the - * case where the client SHOULD receive the object - */ + /* Send the new object to the client */ clientSendMoreData(data, buf, size); } } @@ -1593,20 +1627,28 @@ debug(33, 2) ("clientProcessHit: Vary MATCH!\n"); break; case VARY_OTHER: - /* This is not the correct entity for this request. We need - * to requery the cache. - */ - http->entry = NULL; - memFree(buf, MEM_CLIENT_SOCK_BUF); - storeUnregister(http->sc, e, http); - http->sc = NULL; - storeLocateVary(e, e->mem_obj->reply->hdr_sz, r->vary_headers, clientProcessVary, http); - storeUnlockObject(e); - /* Note: varyEvalyateMatch updates the request with vary information - * so we only get here once. (it also takes care of cancelling loops) - */ - debug(33, 2) ("clientProcessHit: Vary detected!\n"); - return; + { + /* This is not the correct entity for this request. We need + * to requery the cache. + */ + store_client *sc = http->sc; + http->entry = NULL; /* saved in e */ + memFree(buf, MEM_CLIENT_SOCK_BUF); + /* Warning: storeUnregister may abort the object so we must + * call storeLocateVary before unregistering, and + * storeLocateVary may complete immediately so we cannot + * rely on the http structure for this... + */ + http->sc = NULL; + storeLocateVary(e, e->mem_obj->reply->hdr_sz, r->vary_headers, clientProcessVary, http); + storeUnregister(sc, e, http); + storeUnlockObject(e); + /* Note: varyEvalyateMatch updates the request with vary information + * so we only get here once. (it also takes care of cancelling loops) + */ + debug(33, 2) ("clientProcessHit: Vary detected!\n"); + return; + } case VARY_CANCEL: /* varyEvaluateMatch found a object loop. Process as miss */ debug(33, 1) ("clientProcessHit: Vary object loop!\n"); @@ -2322,7 +2364,9 @@ /* this object isn't in the cache */ debug(33, 3) ("clientProcessRequest2: storeGet() MISS\n"); if (r->vary) { - if (r->etags) { + if (r->done_etag) { + debug(33, 0) ("clientProcessRequest2: ETag loop\n"); + } else if (r->etags) { debug(33, 0) ("clientProcessRequest2: ETag miss\n"); r->etags = NULL; } else if (r->vary->etags.count > 0) { Index: squid/src/http.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/http.c,v retrieving revision 1.13.14.4 retrieving revision 1.13.14.5 diff -u -r1.13.14.4 -r1.13.14.5 --- squid/src/http.c 30 May 2001 10:08:46 -0000 1.13.14.4 +++ squid/src/http.c 30 May 2001 23:17:30 -0000 1.13.14.5 @@ -1,6 +1,6 @@ /* - * $Id: http.c,v 1.13.14.4 2001/05/30 10:08:46 hno Exp $ + * $Id: http.c,v 1.13.14.5 2001/05/30 23:17:30 hno Exp $ * * DEBUG: section 11 Hypertext Transfer Protocol (HTTP) * AUTHOR: Harvest Derived @@ -324,7 +324,7 @@ * Returns false if the variance cannot be stored */ const char * -httpMakeVaryMark(request_t * request, HttpReply * reply) +httpMakeVaryMark(const request_t * request, HttpReply * reply) { String vary, hdr; const char *pos = NULL; Index: squid/src/protos.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/protos.h,v retrieving revision 1.29.2.2 retrieving revision 1.29.2.3 diff -u -r1.29.2.2 -r1.29.2.3 --- squid/src/protos.h 29 May 2001 15:04:39 -0000 1.29.2.2 +++ squid/src/protos.h 30 May 2001 23:17:30 -0000 1.29.2.3 @@ -1,6 +1,6 @@ /* - * $Id: protos.h,v 1.29.2.2 2001/05/29 15:04:39 hno Exp $ + * $Id: protos.h,v 1.29.2.3 2001/05/30 23:17:30 hno Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -305,7 +305,7 @@ extern int httpAnonHdrDenied(http_hdr_type hdr_id); extern void httpBuildRequestHeader(request_t *, request_t *, StoreEntry *, HttpHeader *, int, http_state_flags); extern void httpBuildVersion(http_version_t * version, unsigned int major, unsigned int minor); -extern const char *httpMakeVaryMark(request_t * request, HttpReply * reply); +extern const char *httpMakeVaryMark(const request_t * request, HttpReply * reply); /* Http Status Line */ /* init/clean */ @@ -1308,3 +1308,5 @@ void storeLocateVaryDone(VaryData *data); void storeLocateVary(StoreEntry * e, int offset, const char *vary_data, STLVCB *callback, void *cbdata); +void storeAddVary(const char *url, const char *log_url, const method_t method, const cache_key *key, const char *etag, const char *vary, const char *vary_headers); + Index: squid/src/store.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/store.c,v retrieving revision 1.12.14.9 retrieving revision 1.12.14.10 diff -u -r1.12.14.9 -r1.12.14.10 --- squid/src/store.c 30 May 2001 21:36:30 -0000 1.12.14.9 +++ squid/src/store.c 30 May 2001 23:17:30 -0000 1.12.14.10 @@ -1,6 +1,6 @@ /* - * $Id: store.c,v 1.12.14.9 2001/05/30 21:36:30 hno Exp $ + * $Id: store.c,v 1.12.14.10 2001/05/30 23:17:30 hno Exp $ * * DEBUG: section 20 Storage Manager * AUTHOR: Harvest Derived @@ -406,8 +406,7 @@ { AddVaryState *state = data; debug(11, 0) ("free_AddVaryState: %p\n", data); - if (!state->done) { - assert(state->key); + if (!state->done && state->key) { storeAppendPrintf(state->e, "Key: %s\n", state->key); if (state->etag) storeAppendPrintf(state->e, "ETag: %s\n", state->etag); @@ -440,7 +439,10 @@ if (state->current.ignore || state->current.key_used) { /* do nothing */ } else if (state->current.this_key) { - storeAppendPrintf(state->e, "Key: %s\n", state->key); + if (state->current.key) + storeAppendPrintf(state->e, "Key: %s\n", state->current.key); + else + storeAppendPrintf(state->e, "Key: %s\n", state->key); if (state->etag) storeAppendPrintf(state->e, "ETag: %s\n", state->etag); storeAppendPrintf(state->e, "VaryData: %s\n", state->vary_headers); @@ -482,12 +484,12 @@ int l = size; char *e; char *p = buf; - debug(11, 0) ("storeReadVary: %p offset=%d seen_offset=%d size=%d\n", data, state->offset, state->seen_offset, size); + debug(11, 3) ("storeReadVary: %p offset=%d seen_offset=%d size=%d\n", data, state->offset, state->seen_offset, size); if (size <= 0) { storeUnregister(state->sc, state->oe, state); state->sc = NULL; cbdataFree(state); - debug(11, 0) ("storeReadVary: DONE\n"); + debug(11, 2) ("storeReadVary: DONE\n"); return; } state->seen_offset += size; @@ -507,10 +509,12 @@ state->current.key = xmalloc(l2+1); memcpy(state->current.key, p2, l2); state->current.key[l2] = '\0'; - if (strcmp(state->current.key, state->key) == 0) { - state->current.this_key = 1; + if (state->key) { + if (strcmp(state->current.key, state->key) == 0) { + state->current.this_key = 1; + } } - debug(11, 0) ("storeReadVary: Key: %s%s\n", state->current.key, state->current.this_key ? " (THIS)" : ""); + debug(11, 3) ("storeReadVary: Key: %s%s\n", state->current.key, state->current.this_key ? " (THIS)" : ""); } else if (strmatchbeg(p, "ETag: ", l) == 0) { /* etag field */ p2 = p + 6; @@ -520,19 +524,23 @@ memcpy(state->current.etag, p2, l2); state->current.etag[l2] = '\0'; if (strcmp(state->current.etag, state->etag) == 0) { - const cache_key *oldkey = storeKeyScan(state->current.key); - if (strmatch(p2, state->key, l) != 0) { - StoreEntry *old_e = storeGet(oldkey); - if (old_e) - storeRelease(old_e); - safe_free(state->current.key); - state->current.key = xstrdup(state->key); + if (!state->key) { state->current.this_key = 1; + } else { + const cache_key *oldkey = storeKeyScan(state->current.key); + if (strmatch(p2, state->key, l) != 0) { + StoreEntry *old_e = storeGet(oldkey); + if (old_e) + storeRelease(old_e); + safe_free(state->current.key); + state->current.key = xstrdup(state->key); + state->current.this_key = 1; + } } } else if (state->current.this_key) { state->current.ignore = 1; } - debug(11, 0) ("storeReadVary: ETag: %s%s%s\n", state->current.etag, state->current.this_key ? " (THIS)" : "", state->current.ignore ? " (IGNORE)" : ""); + debug(11, 2) ("storeReadVary: ETag: %s%s%s\n", state->current.etag, state->current.this_key ? " (THIS)" : "", state->current.ignore ? " (IGNORE)" : ""); } else if (!state->current.ignore && strmatchbeg(p, "VaryData: ", l) == 0) { /* vary field */ p2 = p + 10; @@ -540,7 +548,7 @@ storeAddVaryFlush(state); if (strmatch(p2, state->vary_headers, l2) != 0) { storeAppend(state->e, p, e - p + 1); - debug(11, 0) ("storeReadVary: %s\n", p); + debug(11, 3) ("storeReadVary: %s\n", p); } } e += 1; @@ -548,7 +556,7 @@ p = e; } state->offset += p - buf; - debug(11, 0) ("storeReadVary: %p offset=%d seen_offset=%d\n", data, state->offset, state->seen_offset); + debug(11, 3) ("storeReadVary: %p offset=%d seen_offset=%d\n", data, state->offset, state->seen_offset); storeClientCopy(state->sc, state->oe, state->seen_offset, state->offset, @@ -563,7 +571,7 @@ * For updates only one of key or etag needs to be specified * At leas one of key or etag must be specified, preferably both. */ -static void +void storeAddVary(const char *url, const char *log_url, const method_t method, const cache_key *key, const char *etag, const char *vary, const char *vary_headers) { AddVaryState *state; @@ -572,11 +580,12 @@ CBDATA_INIT_TYPE_FREECB(AddVaryState, free_AddVaryState); state = cbdataAlloc(AddVaryState); state->url = xstrdup(url); - state->key = xstrdup(storeKeyText(key)); + if (key) + state->key = xstrdup(storeKeyText(key)); state->vary_headers = xstrdup(vary_headers); state->etag = xstrdup(etag); state->oe = storeGetPublic(url, method); - debug(11, 0) ("storeAddVary: %s (%s) %s %s\n", + debug(11, 1) ("storeAddVary: %s (%s) %s %s\n", state->url, state->key, state->vary_headers, state->etag); if (state->oe) storeLockObject(state->oe); @@ -609,7 +618,7 @@ } state->sc = storeClientListAdd(state->oe, state); state->buf = memAllocate(MEM_CLIENT_SOCK_BUF); - debug(11, 0) ("storeAddVary: %p\n", state); + debug(11, 3) ("storeAddVary: %p\n", state); storeClientCopy(state->sc, state->oe, 0, 0, CLIENT_SOCK_SZ, state->buf, @@ -668,7 +677,9 @@ storeLocateVaryDone(state->data); state->data = NULL; } + state->current.etag = NULL; /* shared by data->entries[x] */ safe_free(state->vary_data); + safe_free(state->current.key); if (state->sc) { storeUnregister(state->sc, state->e, state); state->sc = NULL; @@ -676,7 +687,7 @@ if (state->buf) memFree(state->buf, MEM_4K_BUF); cbdataFree(state); - debug(11, 0) ("storeLocateVary: DONE\n"); + debug(11, 2) ("storeLocateVary: DONE\n"); } static void @@ -686,7 +697,7 @@ char *e; char *p = buf; int l = size; - debug(11, 0) ("storeLocateVaryRead: %p offset=%d seen_offset=%d size=%d\n", data, state->offset, state->seen_offset, size); + debug(11, 3) ("storeLocateVaryRead: %p offset=%d seen_offset=%d size=%d\n", data, state->offset, state->seen_offset, size); if (size <= 0) { storeLocateVaryCallback(state); return; @@ -706,7 +717,7 @@ state->current.key = xmalloc(l2+1); memcpy(state->current.key, p2, l2); state->current.key[l2] = '\0'; - debug(11, 0) ("storeLocateVaryRead: Key: %s\n", state->current.key); + debug(11, 3) ("storeLocateVaryRead: Key: %s\n", state->current.key); } else if (strmatchbeg(p, "ETag: ", l) == 0) { /* etag field */ char *etag; @@ -717,7 +728,7 @@ etag[l2] = '\0'; state->current.etag = etag; arrayAppend(&state->data->etags, etag); - debug(11, 0) ("storeLocateVaryRead: ETag: %s\n", etag); + debug(11, 3) ("storeLocateVaryRead: ETag: %s\n", etag); } else if (strmatchbeg(p, "VaryData: ", l) == 0) { /* vary field */ p2 = p + 10; @@ -727,7 +738,7 @@ safe_free(state->data->key); state->data->key = xstrdup(state->current.key); state->data->etag = state->current.etag; - debug(11, 0) ("storeLocateVaryRead: MATCH! %s %s\n", state->current.key, state->current.etag); + debug(11, 1) ("storeLocateVaryRead: MATCH! %s %s\n", state->current.key, state->current.etag); } } e += 1; @@ -735,7 +746,7 @@ p = e; } state->offset += p - buf; - debug(11, 0) ("storeReadVary: %p offset=%d seen_offset=%d\n", data, state->offset, state->seen_offset); + debug(11, 3) ("storeReadVary: %p offset=%d seen_offset=%d\n", data, state->offset, state->seen_offset); storeClientCopy(state->sc, state->e, state->offset, state->seen_offset, 4096, state->buf, storeLocateVaryRead, state); } Index: squid/src/structs.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/structs.h,v retrieving revision 1.33.4.3 retrieving revision 1.33.4.4 diff -u -r1.33.4.3 -r1.33.4.4 --- squid/src/structs.h 30 May 2001 10:08:46 -0000 1.33.4.3 +++ squid/src/structs.h 30 May 2001 23:17:30 -0000 1.33.4.4 @@ -1,6 +1,6 @@ /* - * $Id: structs.h,v 1.33.4.3 2001/05/30 10:08:46 hno Exp $ + * $Id: structs.h,v 1.33.4.4 2001/05/30 23:17:30 hno Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -1612,6 +1612,7 @@ VaryData *vary; Array *etags; /* possible known entity tags (Vary MISS) */ char *etag; /* current entity tag, cache validation */ + unsigned int done_etag:1; /* We have done clientProcessETag on this, don't attempt it again */ }; struct _cachemgr_passwd {