--------------------- PatchSet 10041 Date: 2007/09/27 15:09:16 Author: adri Branch: store_copy Tag: (none) Log: * Rename stmemNodeDeref to stmemNodeUnref * Implement disk paging of referenced pages via an ugly hack; which creates a temporary mem_node, copies into that, and passes that reference along. This at least doesn't increase the number of copies in the disk path. Members: src/client_side.c:1.202.2.4->1.202.2.5 src/protos.h:1.146.2.2->1.146.2.3 src/stmem.c:1.10.2.3->1.10.2.4 src/store_client.c:1.25.10.3->1.25.10.4 Index: squid/src/client_side.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/client_side.c,v retrieving revision 1.202.2.4 retrieving revision 1.202.2.5 diff -u -r1.202.2.4 -r1.202.2.5 --- squid/src/client_side.c 26 Sep 2007 07:33:49 -0000 1.202.2.4 +++ squid/src/client_side.c 27 Sep 2007 15:09:16 -0000 1.202.2.5 @@ -1,6 +1,6 @@ /* - * $Id: client_side.c,v 1.202.2.4 2007/09/26 07:33:49 adri Exp $ + * $Id: client_side.c,v 1.202.2.5 2007/09/27 15:09:16 adri Exp $ * * DEBUG: section 33 Client-side Routines * AUTHOR: Duane Wessels @@ -700,11 +700,11 @@ debug(33, 3) ("clientHandleETagReply: %s, %d bytes\n", url, (int) size); if (entry == NULL) { /* client aborted */ - storeClientDeref(&ref); + stmemNodeUnref(&ref); return; } if (size < 0 && !EBIT_TEST(entry->flags, ENTRY_ABORTED)) { - storeClientDeref(&ref); + stmemNodeUnref(&ref); clientHandleETagMiss(http); return; } @@ -712,7 +712,7 @@ status = mem->reply->sline.status; if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { debug(33, 3) ("clientHandleETagReply: ABORTED '%s'\n", url); - storeClientDeref(&ref); + stmemNodeUnref(&ref); clientHandleETagMiss(http); return; } @@ -721,10 +721,10 @@ if (size >= STORE_CLIENT_BUF_SZ) { /* will not get any bigger than that */ debug(33, 3) ("clientHandleETagReply: Reply is too large '%s'\n", url); - storeClientDeref(&ref); + stmemNodeUnref(&ref); clientHandleETagMiss(http); } else { - storeClientDeref(&ref); + stmemNodeUnref(&ref); storeClientRef(http->sc, entry, http->out.offset + size, http->out.offset, @@ -736,7 +736,7 @@ } if (HTTP_NOT_MODIFIED == mem->reply->sline.status) { /* Remember the ETag and restart */ - storeClientDeref(&ref); + stmemNodeUnref(&ref); if (mem->reply) { request_t *request = http->request; const char *etag = httpHeaderGetStr(&mem->reply->header, HDR_ETAG); @@ -945,11 +945,11 @@ http->old_entry->mem_obj->ims_entry = NULL; } if (entry == NULL) { - storeClientDeref(&ref); + stmemNodeUnref(&ref); return; } if (size < 0 && !EBIT_TEST(entry->flags, ENTRY_ABORTED)) { - storeClientDeref(&ref); + stmemNodeUnref(&ref); return; } mem = entry->mem_obj; @@ -976,7 +976,7 @@ http->sc = http->old_sc; /* continue */ } else { - storeClientDeref(&ref); + stmemNodeUnref(&ref); storeClientRef(http->sc, entry, http->out.offset + size, http->out.offset, @@ -1032,7 +1032,7 @@ http->old_sc = NULL; assert(!EBIT_TEST(entry->flags, ENTRY_ABORTED)); if (recopy) { - storeClientDeref(&ref); + stmemNodeUnref(&ref); storeClientRef(http->sc, entry, http->out.offset, http->out.offset, @@ -1040,8 +1040,8 @@ clientSendMoreHeaderData, http); } else { - /* XXX should be passing in a reference call, and dereferencing our copy! [ahc] */ - clientSendMoreHeaderData(data, ref, size); + clientSendMoreHeaderData(data, stmemNodeRef(&ref), size); + stmemNodeUnref(&ref); } } @@ -2126,12 +2126,12 @@ debug(33, 3) ("clientCacheHit: %s, %d bytes\n", http->uri, (int) size); http->flags.hit = 0; if (http->entry == NULL) { - storeClientDeref(&ref); + stmemNodeUnref(&ref); debug(33, 3) ("clientCacheHit: request aborted\n"); return; } else if (size <= 0) { /* swap in failure */ - storeClientDeref(&ref); + stmemNodeUnref(&ref); debug(33, 3) ("clientCacheHit: swapin failure for %s\n", http->uri); http->log_type = LOG_TCP_SWAPFAIL_MISS; clientProcessMiss(http); @@ -2142,13 +2142,13 @@ assert(!EBIT_TEST(e->flags, ENTRY_ABORTED)); if (!memHaveHeaders(mem)) { debug(33, 1) ("clientCacheHit: No reply headers in '%s'?\n", e->mem_obj->url); - storeClientDeref(&ref); + stmemNodeUnref(&ref); clientProcessMiss(http); return; } if (strcmp(mem->url, urlCanonical(r)) != 0) { debug(33, 1) ("clientCacheHit: URL mismatch '%s' != '%s'?\n", e->mem_obj->url, urlCanonical(r)); - storeClientDeref(&ref); + stmemNodeUnref(&ref); clientProcessMiss(http); return; } @@ -2184,7 +2184,7 @@ * so we only get here once. (it also takes care of cancelling loops) */ debug(33, 2) ("clientProcessHit: Vary detected!\n"); - storeClientDeref(&ref); + stmemNodeUnref(&ref); return; } case VARY_RESTART: @@ -2194,13 +2194,13 @@ safe_free(r->vary_hdr); safe_free(r->vary_headers); clientProcessRequest(http); - storeClientDeref(&ref); + stmemNodeUnref(&ref); return; case VARY_CANCEL: /* varyEvaluateMatch found a object loop. Process as miss */ debug(33, 1) ("clientProcessHit: Vary object loop!\n"); clientProcessMiss(http); - storeClientDeref(&ref); + stmemNodeUnref(&ref); return; } if (r->method == METHOD_PURGE) { @@ -2209,7 +2209,7 @@ http->sc = NULL; storeUnlockObject(e); clientPurgeRequest(http); - storeClientDeref(&ref); + stmemNodeUnref(&ref); return; } http->flags.hit = 1; @@ -2220,11 +2220,11 @@ #endif ) { http->log_type = LOG_TCP_NEGATIVE_HIT; - /* XXX should be passing in a reference call, and dereferncing our copy! [ahc] */ - clientSendMoreHeaderData(data, ref, size); + clientSendMoreHeaderData(data, stmemNodeRef(&ref), size); + stmemNodeUnref(&ref); } else { http->log_type = LOG_TCP_MISS; - storeClientDeref(&ref); + stmemNodeUnref(&ref); clientProcessMiss(http); } return; @@ -2242,7 +2242,7 @@ * Query the origin to see what should be done. */ http->log_type = LOG_TCP_MISS; - storeClientDeref(&ref); + stmemNodeUnref(&ref); clientProcessMiss(http); return; } @@ -2255,7 +2255,7 @@ debug(33, 4) ("clientCacheHit: Reply code %d != 200\n", mem->reply->sline.status); http->log_type = LOG_TCP_MISS; - storeClientDeref(&ref); + stmemNodeUnref(&ref); clientProcessMiss(http); return; } @@ -2321,7 +2321,7 @@ } else { clientProcessExpired(http); } - storeClientDeref(&ref); + stmemNodeUnref(&ref); return; } if (is_modified == 0) { @@ -2343,7 +2343,7 @@ storeAppend(e, mb.buf, mb.size); memBufClean(&mb); storeComplete(e); - storeClientDeref(&ref); + stmemNodeUnref(&ref); return; } /* @@ -2353,8 +2353,8 @@ http->log_type = LOG_TCP_MISS; else if (http->log_type == LOG_TCP_HIT && e->mem_status == IN_MEMORY) http->log_type = LOG_TCP_MEM_HIT; - /* XXX should be passing it in with a reference call, and dereferencing our copy! [ahc] */ - clientSendMoreHeaderData(data, ref, size); + clientSendMoreHeaderData(data, stmemNodeRef(&ref), size); + stmemNodeUnref(&ref); } /* put terminating boundary for multiparts */ @@ -2631,26 +2631,26 @@ if (DLINK_HEAD(conn->reqs) != http) { /* there is another object in progress, defer this one */ debug(33, 2) ("clientSendMoreHeaderData: Deferring %s\n", storeUrl(entry)); - storeClientDeref(&ref); + stmemNodeUnref(&ref); return; } else if (http->request->flags.reset_tcp) { comm_reset_close(fd); - storeClientDeref(&ref); + stmemNodeUnref(&ref); return; } else if (entry && EBIT_TEST(entry->flags, ENTRY_ABORTED)) { /* call clientWriteComplete so the client socket gets closed */ - storeClientDeref(&ref); + stmemNodeUnref(&ref); clientWriteComplete(fd, NULL, 0, COMM_OK, http); return; } else if (size < 0) { /* call clientWriteComplete so the client socket gets closed */ clientWriteComplete(fd, NULL, 0, COMM_OK, http); - storeClientDeref(&ref); + stmemNodeUnref(&ref); return; } else if (size == 0) { /* call clientWriteComplete so the client socket gets closed */ clientWriteComplete(fd, NULL, 0, COMM_OK, http); - storeClientDeref(&ref); + stmemNodeUnref(&ref); return; } assert(http->out.offset == 0); @@ -2663,7 +2663,7 @@ http->entry = clientCreateStoreEntry(http, http->request->method, null_request_flags); errorAppendEntry(http->entry, err); - storeClientDeref(&ref); + stmemNodeUnref(&ref); return; } clientMaxBodySize(http->request, http, rep); @@ -2676,7 +2676,7 @@ http->entry = clientCreateStoreEntry(http, http->request->method, null_request_flags); errorAppendEntry(http->entry, err); - storeClientDeref(&ref); + stmemNodeUnref(&ref); return; } /* @@ -2691,7 +2691,7 @@ */ http->range_iter.prefix_size = rep->hdr_sz; debug(33, 3) ("clientSendMoreHeaderData: %d bytes of headers\n", rep->hdr_sz); - storeClientDeref(&ref); + stmemNodeUnref(&ref); clientHttpLocationRewriteCheck(http); } @@ -2923,22 +2923,22 @@ if (DLINK_HEAD(conn->reqs) != http) { /* there is another object in progress, defer this one */ debug(33, 1) ("clientSendMoreData: Deferring %s\n", storeUrl(entry)); - storeClientDeref(&ref); + stmemNodeUnref(&ref); return; } else if (entry && EBIT_TEST(entry->flags, ENTRY_ABORTED)) { /* call clientWriteComplete so the client socket gets closed */ clientWriteComplete(fd, NULL, 0, COMM_OK, http); - storeClientDeref(&ref); + stmemNodeUnref(&ref); return; } else if (size < 0) { /* call clientWriteComplete so the client socket gets closed */ clientWriteComplete(fd, NULL, 0, COMM_OK, http); - storeClientDeref(&ref); + stmemNodeUnref(&ref); return; } else if (size == 0) { /* call clientWriteComplete so the client socket gets closed */ clientWriteComplete(fd, NULL, 0, COMM_OK, http); - storeClientDeref(&ref); + stmemNodeUnref(&ref); return; } /* XXX restore this optimisation later on! */ @@ -2982,7 +2982,7 @@ } /* write body */ comm_write_mbuf(fd, mb, clientWriteComplete, http); - storeClientDeref(&ref); + stmemNodeUnref(&ref); } /* @@ -2999,7 +2999,7 @@ * NOTE: clientWriteComplete doesn't currently use its "buf" * (second) argument, so we pass in NULL. */ - storeClientDeref(&http->nr); + stmemNodeUnref(&http->nr); clientWriteComplete(fd, NULL, size, errflag, data); } Index: squid/src/protos.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/protos.h,v retrieving revision 1.146.2.2 retrieving revision 1.146.2.3 diff -u -r1.146.2.2 -r1.146.2.3 --- squid/src/protos.h 25 Sep 2007 00:29:27 -0000 1.146.2.2 +++ squid/src/protos.h 27 Sep 2007 15:09:17 -0000 1.146.2.3 @@ -1,6 +1,6 @@ /* - * $Id: protos.h,v 1.146.2.2 2007/09/25 00:29:27 adri Exp $ + * $Id: protos.h,v 1.146.2.3 2007/09/27 15:09:17 adri Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -898,7 +898,11 @@ extern void stmemNodeFree(void *); extern char *stmemNodeGet(mem_node *); extern int stmemRef(const mem_hdr *mem, squid_off_t offset, mem_node_ref *r); -extern void stmemUnref(mem_node_ref *r); +extern void stmemNodeUnref(mem_node_ref *r); +extern mem_node_ref stmemNodeRef(mem_node_ref *r); +extern void stmemNodeRefCreate(mem_node_ref *r); + + /* ----------------------------------------------------------------- */ @@ -1087,7 +1091,6 @@ extern store_client *storeClientRegister(StoreEntry * e, void *data); extern void storeClientCopy(store_client *, StoreEntry *, squid_off_t, squid_off_t, size_t, char *, STCB *, void *); extern void storeClientRef(store_client *, StoreEntry *, squid_off_t, squid_off_t, size_t, STNCB *, void *); -extern void storeClientDeref(mem_node_ref *r); extern int storeClientCopyPending(store_client *, StoreEntry * e, void *data); extern int storeClientUnregister(store_client * sc, StoreEntry * e, void *data); extern squid_off_t storeLowestMemReaderOffset(const StoreEntry * entry); Index: squid/src/stmem.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/stmem.c,v retrieving revision 1.10.2.3 retrieving revision 1.10.2.4 diff -u -r1.10.2.3 -r1.10.2.4 --- squid/src/stmem.c 25 Sep 2007 00:29:27 -0000 1.10.2.3 +++ squid/src/stmem.c 27 Sep 2007 15:09:17 -0000 1.10.2.4 @@ -1,6 +1,6 @@ /* - * $Id: stmem.c,v 1.10.2.3 2007/09/25 00:29:27 adri Exp $ + * $Id: stmem.c,v 1.10.2.4 2007/09/27 15:09:17 adri Exp $ * * DEBUG: section 19 Store Memory Primitives * AUTHOR: Harvest Derived @@ -176,12 +176,32 @@ assert(r->offset >= 0); assert(r->offset >= 0); assert(p->len + t_off - offset > 0); - debug(19, 3) ("memRef: returning node %p, offset %d, %d bytes\n", p, (int) r->offset, (int) p->len + t_off - offset); + debug(19, 3) ("memRef: returning node %p, offset %d, %d bytes\n", p, (int) r->offset, (int) (p->len + t_off - offset)); return p->len + t_off - offset; } void -stmemUnref(mem_node_ref *r) +stmemNodeRefCreate(mem_node_ref *r) +{ + assert(r->node == NULL); + r->node = memAllocate(MEM_MEM_NODE); + r->node->uses = 0; + r->node->next = NULL; + r->node->len = 4096; + r->offset = 0; +} + +mem_node_ref +stmemNodeRef(mem_node_ref *r) +{ + mem_node_ref r2; + r2 = *r; + r2.node->uses++; + return r2; +} + +void +stmemNodeUnref(mem_node_ref *r) { if (! r->node) return; Index: squid/src/store_client.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/store_client.c,v retrieving revision 1.25.10.3 retrieving revision 1.25.10.4 diff -u -r1.25.10.3 -r1.25.10.4 --- squid/src/store_client.c 25 Sep 2007 00:29:27 -0000 1.25.10.3 +++ squid/src/store_client.c 27 Sep 2007 15:09:17 -0000 1.25.10.4 @@ -1,6 +1,6 @@ /* - * $Id: store_client.c,v 1.25.10.3 2007/09/25 00:29:27 adri Exp $ + * $Id: store_client.c,v 1.25.10.4 2007/09/27 15:09:17 adri Exp $ * * DEBUG: section 20 Storage Manager Client-Side Interface * AUTHOR: Duane Wessels @@ -146,7 +146,8 @@ sc->new_callback = NULL; sc->callback_data = NULL; sc->copy_buf = NULL; - nr = sc->node_ref; + nr = sc->node_ref; /* XXX this should be a reference; and we should dereference our copy! */ + /* This code "transfers" its ownership (and reference) of the node_ref to the caller. Ugly, but works. */ sc->node_ref.node = NULL; sc->node_ref.offset = -1; if (cbdataValid(cbdata)) { @@ -377,6 +378,7 @@ sz = stmemCopy(&mem->data_hdr, sc->copy_offset, sc->copy_buf, sc->copy_size); } else if (sc->new_callback && ! sc->callback) { + assert(sc->node_ref.node == NULL); /* We should never, ever have a node here; or we'd leak! */ sz = stmemRef(&mem->data_hdr, sc->copy_offset, &sc->node_ref); } else { fatal("storeClientCopy3: bad callback/new_callback combination!\n"); @@ -397,24 +399,26 @@ storeClientFileRead(store_client * sc) { MemObject *mem = sc->entry->mem_obj; - assert(sc->callback != NULL); + if ( (!sc->callback) && (!sc->new_callback)) { + fatal("storeClientFileRead: missing a callback!\n"); + } assert(!sc->flags.disk_io_pending); sc->flags.disk_io_pending = 1; - if (sc->new_callback) - fatal("For now: storeClientFileRead needs fixing to work in the storeClientRef() case!!\n"); + assert(sc->node_ref.node == NULL); /* We should never, ever have a node here; or we'd leak! */ + stmemNodeRefCreate(&sc->node_ref); /* Creates an entry with reference count == 1 */ if (mem->swap_hdr_sz == 0) { storeRead(sc->swapin_sio, - sc->copy_buf, - sc->copy_size, + sc->node_ref.node->data, + XMIN(SM_PAGE_SIZE, sc->copy_size), 0, storeClientReadHeader, sc); } else { if (sc->entry->swap_status == SWAPOUT_WRITING) - assert(storeSwapOutObjectBytesOnDisk(mem) > sc->copy_offset); + assert(storeSwapOutObjectBytesOnDisk(mem) > sc->copy_offset); /* XXX is this right? Shouldn't we incl. mem->swap_hdr_sz? */ storeRead(sc->swapin_sio, - sc->copy_buf, - sc->copy_size, + sc->node_ref.node->data, + XMIN(SM_PAGE_SIZE, sc->copy_size), sc->copy_offset + mem->swap_hdr_sz, storeClientReadBody, sc); @@ -422,21 +426,36 @@ } static void -storeClientReadBody(void *data, const char *buf, ssize_t len) +storeClientReadBody(void *data, const char *buf_unused, ssize_t len) { store_client *sc = data; MemObject *mem = sc->entry->mem_obj; assert(sc->flags.disk_io_pending); + char *cbuf = NULL; + sc->flags.disk_io_pending = 0; - assert(sc->callback != NULL); + if ( (!sc->callback) && (!sc->new_callback)) { + fatal("storeClientReadBody: missing a callback!\n"); + } + if (sc->new_callback) { + assert(sc->node_ref.node); + cbuf = sc->node_ref.node->data; + } else { + cbuf = sc->copy_buf; + } + /* XXX update how much data in that mem page is active; argh this should be done in a storage layer */ + if (sc->new_callback) { + assert(sc->node_ref.node); + sc->node_ref.node->len = len; + } debug(20, 3) ("storeClientReadBody: len %d\n", (int) len); if (sc->copy_offset == 0 && len > 0 && memHaveHeaders(mem) == 0) - httpReplyParse(mem->reply, sc->copy_buf, headersEnd(sc->copy_buf, len)); + httpReplyParse(mem->reply, cbuf, headersEnd(cbuf, len)); storeClientCallback(sc, len); } static void -storeClientReadHeader(void *data, const char *buf, ssize_t len) +storeClientReadHeader(void *data, const char *buf_unused, ssize_t len) { static int md5_mismatches = 0; store_client *sc = data; @@ -447,17 +466,32 @@ size_t copy_sz; tlv *tlv_list; tlv *t; + char *cbuf; int swap_object_ok = 1; assert(sc->flags.disk_io_pending); sc->flags.disk_io_pending = 0; - assert(sc->callback != NULL); + if ( (!sc->callback) && (!sc->new_callback)) { + fatal("storeClientReadHeader: missing a callback!\n"); + } + if (sc->new_callback) { + assert(sc->node_ref.node); + cbuf = sc->node_ref.node->data; + } else { + cbuf = sc->copy_buf; + } debug(20, 3) ("storeClientReadHeader: len %d\n", (int) len); + /* XXX update how much data in that mem page is active; argh this should be done in a storage layer */ + if (sc->new_callback) { + assert(sc->node_ref.node); + sc->node_ref.node->len = len; + } if (len < 0) { debug(20, 3) ("storeClientReadHeader: %s\n", xstrerror()); storeClientCallback(sc, len); return; } - tlv_list = storeSwapMetaUnpack(buf, &swap_hdr_sz); + assert(len <= SM_PAGE_SIZE); + tlv_list = storeSwapMetaUnpack(cbuf, &swap_hdr_sz); if (swap_hdr_sz > len) { /* oops, bad disk file? */ debug(20, 1) ("WARNING: swapfile header too small\n"); @@ -537,10 +571,12 @@ copy_sz = XMIN(sc->copy_size, body_sz); debug(20, 3) ("storeClientReadHeader: copying %d bytes of body\n", (int) copy_sz); - xmemmove(sc->copy_buf, sc->copy_buf + swap_hdr_sz, copy_sz); + debug(20, 8) ("sc %p; node_ref->node %p; data %p; copy size %d; data size %d\n", + sc, sc->node_ref.node, sc->node_ref.node->data, copy_sz, len); + xmemmove(cbuf, cbuf + swap_hdr_sz, copy_sz); if (sc->copy_offset == 0 && len > 0 && memHaveHeaders(mem) == 0) - httpReplyParse(mem->reply, sc->copy_buf, - headersEnd(sc->copy_buf, copy_sz)); + httpReplyParse(mem->reply, cbuf, + headersEnd(cbuf, copy_sz)); storeClientCallback(sc, copy_sz); return; } @@ -598,6 +634,7 @@ mem->url); storeClientCallback(sc, -1); } + stmemNodeUnref(&sc->node_ref); #if DELAY_POOLS delayUnregisterDelayIdPtr(&sc->delay_id); #endif @@ -734,8 +771,3 @@ storeAbort(entry); } -void -storeClientDeref(mem_node_ref *r) -{ - stmemUnref(r); -}