Revision: 14431
Author: adrian.chadd
Date: Mon Feb 22 05:10:34 2010
Log: Merge r14413:14430 from /branches/LUSCA_HEAD/ .


http://code.google.com/p/lusca-cache/source/detail?r=14431

Added:
 /playpen/LUSCA_HEAD_zerocopy_storeread/src/client_side_ims.c
 /playpen/LUSCA_HEAD_zerocopy_storeread/src/client_side_ims.h
Modified:
 /playpen/LUSCA_HEAD_zerocopy_storeread
 /playpen/LUSCA_HEAD_zerocopy_storeread/configure.in
 /playpen/LUSCA_HEAD_zerocopy_storeread/libiapp/comm.c
 /playpen/LUSCA_HEAD_zerocopy_storeread/libiapp/comm.h
 /playpen/LUSCA_HEAD_zerocopy_storeread/src/Makefile.am
 /playpen/LUSCA_HEAD_zerocopy_storeread/src/acl.c
 /playpen/LUSCA_HEAD_zerocopy_storeread/src/cf.data.pre
 /playpen/LUSCA_HEAD_zerocopy_storeread/src/client_db.c
 /playpen/LUSCA_HEAD_zerocopy_storeread/src/client_side.c
 /playpen/LUSCA_HEAD_zerocopy_storeread/src/client_side.h
 /playpen/LUSCA_HEAD_zerocopy_storeread/src/client_side_location_rewrite.c
 /playpen/LUSCA_HEAD_zerocopy_storeread/src/client_side_ranges.c
 /playpen/LUSCA_HEAD_zerocopy_storeread/src/client_side_ranges.h
 /playpen/LUSCA_HEAD_zerocopy_storeread/src/client_side_refresh.c
 /playpen/LUSCA_HEAD_zerocopy_storeread/src/enums.h
 /playpen/LUSCA_HEAD_zerocopy_storeread/src/structs.h
 /playpen/LUSCA_HEAD_zerocopy_storeread/src/tools.c

=======================================
--- /dev/null
+++ /playpen/LUSCA_HEAD_zerocopy_storeread/src/client_side_ims.c Mon Feb 22 05:10:34 2010
@@ -0,0 +1,297 @@
+#include "squid.h"
+
+#include "client_side.h"
+#include "client_side_ims.h"
+
+
+static void clientHandleIMSReply(void *data, HttpReply * rep);
+
+int
+modifiedSince(StoreEntry * entry, request_t * request)
+{
+    squid_off_t object_length;
+    MemObject *mem = entry->mem_obj;
+    time_t mod_time = entry->lastmod;
+    debug(33, 3) ("modifiedSince: '%s'\n", storeLookupUrl(entry));
+    debug(33, 3) ("modifiedSince: mod_time = %ld\n", (long int) mod_time);
+    if (mod_time < 0)
+        return 1;
+    /* Find size of the object */
+    object_length = mem->reply->content_length;
+    if (object_length < 0)
+        object_length = contentLen(entry);
+    if (mod_time > request->ims) {
+        debug(33, 3) ("--> YES: entry newer than client\n");
+        return 1;
+    } else if (mod_time < request->ims) {
+        debug(33, 3) ("-->  NO: entry older than client\n");
+        return 0;
+    } else if (request->imslen < 0) {
+        debug(33, 3) ("-->  NO: same LMT, no client length\n");
+        return 0;
+    } else if (request->imslen == object_length) {
+        debug(33, 3) ("-->  NO: same LMT, same length\n");
+        return 0;
+    } else {
+        debug(33, 3) ("--> YES: same LMT, different length\n");
+        return 1;
+    }
+}
+
+void
+clientProcessExpired(clientHttpRequest * http)
+{
+    char *url = http->uri;
+    StoreEntry *entry = NULL;
+    int hit = 0;
+    const char *etag;
+ const int can_revalidate = http->entry->mem_obj->reply->sline.status == HTTP_OK;
+    debug(33, 3) ("clientProcessExpired: '%s'\n", http->uri);
+    /*
+     * check if we are allowed to contact other servers
+     * @?@: Instead of a 504 (Gateway Timeout) reply, we may want to return
+     *      a stale entry *if* it matches client requirements
+     */
+    if (clientOnlyIfCached(http)) {
+       clientProcessOnlyIfCachedMiss(http);
+       return;
+    }
+    http->request->flags.refresh = 1;
+    http->old_entry = http->entry;
+    http->old_sc = http->sc;
+    if (http->entry->mem_obj && http->entry->mem_obj->ims_entry) {
+       entry = http->entry->mem_obj->ims_entry;
+       debug(33, 5) ("clientProcessExpired: collapsed request\n");
+       if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
+           debug(33, 1) ("clientProcessExpired: collapsed request ABORTED!\n");
+           entry = NULL;
+ } else if (http->entry->mem_obj->refresh_timestamp + Config.collapsed_forwarding_timeout < squid_curtime) {
+           debug(33, 1) ("clientProcessExpired: collapsed request STALE!\n");
+           entry = NULL;
+       }
+       if (entry) {
+           http->request->flags.collapsed = 1;           /* Don't trust the 
store entry */
+           storeLockObject(entry);
+           hit = 1;
+       } else {
+           storeUnlockObject(http->entry->mem_obj->ims_entry);
+           http->entry->mem_obj->ims_entry = NULL;
+       }
+    }
+    if (!entry) {
+ entry = storeCreateEntry(url, http->request->flags, http->request->method);
+       if (http->request->store_url)
+           storeEntrySetStoreUrl(entry, http->request->store_url);
+       if (http->entry->mem_obj) {
+           http->entry->mem_obj->refresh_timestamp = squid_curtime;
+           if (Config.onoff.collapsed_forwarding) {
+               http->entry->mem_obj->ims_entry = entry;
+               storeLockObject(http->entry->mem_obj->ims_entry);
+           }
+       }
+    }
+    if (entry->mem_obj->old_entry) {
+       storeUnlockObject(entry->mem_obj->old_entry);
+       entry->mem_obj->old_entry = NULL;
+    }
+    entry->mem_obj->old_entry = http->old_entry;
+    storeLockObject(entry->mem_obj->old_entry);
+    http->sc = storeClientRegister(entry, http);
+#if DELAY_POOLS
+    /* delay_id is already set on original store client */
+    delaySetStoreClient(http->sc, delayClient(http));
+#endif
+    if (can_revalidate && http->old_entry->lastmod > 0) {
+       http->request->lastmod = http->old_entry->lastmod;
+       http->request->flags.cache_validation = 1;
+    } else
+       http->request->lastmod = -1;
+ debug(33, 5) ("clientProcessExpired: lastmod %ld\n", (long int) entry->lastmod);
+    /* NOTE, don't call storeLockObject(), storeCreateEntry() does it */
+    http->entry = entry;
+    http->out.offset = 0;
+    if (can_revalidate) {
+ etag = httpHeaderGetStr(&http->old_entry->mem_obj->reply->header, HDR_ETAG);
+       if (etag) {
+           http->request->etag = xstrdup(etag);
+           http->request->flags.cache_validation = 1;
+       }
+    }
+    if (!hit)
+       fwdStart(http->conn->fd, http->entry, http->request);
+ /* Register with storage manager to receive updates when data comes in. */
+    if (EBIT_TEST(entry->flags, ENTRY_ABORTED))
+       debug(33, 0) ("clientProcessExpired: found ENTRY_ABORTED object\n");
+    storeClientCopyHeaders(http->sc, entry,
+       clientHandleIMSReply,
+       http);
+}
+
+static int
+clientGetsOldEntry(StoreEntry * new_entry, StoreEntry * old_entry, request_t * request)
+{
+    const http_status status = new_entry->mem_obj->reply->sline.status;
+    if (0 == status) {
+       debug(33, 5) ("clientGetsOldEntry: YES, broken HTTP reply\n");
+       return 1;
+    }
+    /* If the reply is a failure then send the old object as a last
+     * resort */
+    if (status >= 500 && status < 600) {
+       if (EBIT_TEST(new_entry->flags, ENTRY_NEGCACHED)) {
+ debug(33, 3) ("clientGetsOldEntry: NO, negatively cached failure reply=%d\n", status);
+           return 0;
+       }
+       if (refreshCheckStaleOK(old_entry, request)) {
+ debug(33, 3) ("clientGetsOldEntry: YES, failure reply=%d and old acceptable to send\n", status);
+           return 1;
+       }
+ debug(33, 3) ("clientGetsOldEntry: NO, failure reply=%d and old NOT acceptable to send\n", status);
+       return 0;
+    }
+    /* If the reply is not to a cache validation conditional then
+     * we should forward it to the client */
+    if (!request->flags.cache_validation) {
+       debug(33, 5) ("clientGetsOldEntry: NO, not a cache validation\n");
+       return 0;
+    }
+    /* If the reply is anything but "Not Modified" then
+     * we must forward it to the client */
+    if (HTTP_NOT_MODIFIED != status) {
+       debug(33, 5) ("clientGetsOldEntry: NO, reply=%d\n", status);
+       return 0;
+    }
+    /* If the ETag matches the clients If-None-Match, then return
+     * the servers 304 reply
+     */
+    if (httpHeaderHas(&new_entry->mem_obj->reply->header, HDR_ETAG) &&
+       httpHeaderHas(&request->header, HDR_IF_NONE_MATCH)) {
+ const char *etag = httpHeaderGetStr(&new_entry->mem_obj->reply->header, HDR_ETAG);
+       String etags = httpHeaderGetList(&request->header, HDR_IF_NONE_MATCH);
+       int etag_match = strListIsMember(&etags, etag, ',');
+       stringClean(&etags);
+       if (etag_match) {
+           debug(33, 5) ("clientGetsOldEntry: NO, client If-None-Match\n");
+           return 0;
+       }
+    }
+    /* If the client did not send IMS in the request, then it
+     * must get the old object, not this "Not Modified" reply */
+    if (!request->flags.ims) {
+       debug(33, 5) ("clientGetsOldEntry: YES, no client IMS\n");
+       return 1;
+    }
+    /* If the client IMS time is prior to the entry LASTMOD time we
+     * need to send the old object */
+    if (modifiedSince(old_entry, request)) {
+       debug(33, 5) ("clientGetsOldEntry: YES, modified since %ld\n",
+           (long int) request->ims);
+       return 1;
+    }
+    debug(33, 5) ("clientGetsOldEntry: NO, new one is fine\n");
+    return 0;
+}
+
+static void
+clientHandleIMSReply(void *data, HttpReply * rep)
+{
+    clientHttpRequest *http = data;
+    StoreEntry *entry = http->entry;
+    MemObject *mem;
+    const char *url = storeUrl(entry);
+    int unlink_request = 0;
+    StoreEntry *oldentry;
+    int recopy = 1;
+    debug(33, 3) ("clientHandleIMSReply: %s\n", url);
+ if (http->old_entry && http->old_entry->mem_obj && http->old_entry->mem_obj->ims_entry) {
+       storeUnlockObject(http->old_entry->mem_obj->ims_entry);
+       http->old_entry->mem_obj->ims_entry = NULL;
+    }
+    if (entry == NULL) {
+       return;
+    }
+    if (entry->mem_obj->old_entry) {
+       storeUnlockObject(entry->mem_obj->old_entry);
+       entry->mem_obj->old_entry = NULL;
+    }
+    mem = entry->mem_obj;
+    if (!rep) {
+       debug(33, 3) ("clientHandleIMSReply: ABORTED '%s'\n", url);
+       /* We have an existing entry, but failed to validate it */
+       /* Its okay to send the old one anyway */
+       http->log_type = LOG_TCP_REFRESH_FAIL_HIT;
+       storeClientUnregister(http->sc, entry, http);
+       storeUnlockObject(entry);
+       entry = http->entry = http->old_entry;
+       http->sc = http->old_sc;
+    } else if (clientGetsOldEntry(entry, http->old_entry, http->request)) {
+       /* We initiated the IMS request, the client is not expecting
+        * 304, so put the good one back.  First, make sure the old entry
+        * headers have been loaded from disk. */
+       oldentry = http->old_entry;
+       if (oldentry->mem_obj->request == NULL) {
+           oldentry->mem_obj->request = requestLink(mem->request);
+           unlink_request = 1;
+       }
+       if (rep->sline.status == HTTP_NOT_MODIFIED) {
+           /* Don't memcpy() the whole reply structure here.  For example,
+            * www.thegist.com (Netscape/1.13) returns a content-length for
+            * 304's which seems to be the length of the 304 HEADERS!!! and
+            * not the body they refer to.  */
+           httpReplyUpdateOnNotModified(oldentry->mem_obj->reply, rep);
+           storeTimestampsSet(oldentry);
+           storeUpdate(oldentry, http->request);
+           http->log_type = LOG_TCP_REFRESH_HIT;
+       } else {
+           http->log_type = LOG_TCP_REFRESH_FAIL_HIT;
+       }
+       storeClientUnregister(http->sc, entry, http);
+       http->sc = http->old_sc;
+       storeUnlockObject(entry);
+       entry = http->entry = oldentry;
+       if (unlink_request) {
+           requestUnlink(entry->mem_obj->request);
+           entry->mem_obj->request = NULL;
+       }
+    } else {
+       /* the client can handle this reply, whatever it is */
+       http->flags.hit = 0;
+       http->log_type = LOG_TCP_REFRESH_MISS;
+ if (HTTP_NOT_MODIFIED == rep->sline.status && http->request->flags.cache_validation) {
+           httpReplyUpdateOnNotModified(http->old_entry->mem_obj->reply,
+               rep);
+           storeTimestampsSet(http->old_entry);
+           storeUpdate(http->old_entry, http->request);
+           if (!EBIT_TEST(http->old_entry->flags, REFRESH_FAILURE))
+               http->log_type = LOG_TCP_REFRESH_HIT;
+           else
+               http->log_type = LOG_TCP_REFRESH_FAIL_HIT;
+       }
+       /* Get rid of the old entry if not a cache validation */
+       if (!http->request->flags.cache_validation)
+           storeRelease(http->old_entry);
+       storeClientUnregister(http->old_sc, http->old_entry, http);
+       storeUnlockObject(http->old_entry);
+       recopy = 0;
+    }
+    http->old_entry = NULL; /* done with old_entry */
+    http->old_sc = NULL;
+ if (http->request->flags.collapsed && !http->flags.hit && EBIT_TEST(entry->flags, RELEASE_REQUEST)) {
+       /* Collapsed request, but the entry is not good to be sent */
+       clientProcessMiss(http);
+       return;
+    }
+    if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
+       /* Old object got aborted, not good */
+       clientProcessMiss(http);
+        return;
+    }
+    if (recopy) {
+       storeClientCopyHeaders(http->sc, entry,
+           clientSendHeaders,
+           http);
+    } else {
+       clientSendHeaders(data, rep);
+    }
+}
+
=======================================
--- /dev/null
+++ /playpen/LUSCA_HEAD_zerocopy_storeread/src/client_side_ims.h Mon Feb 22 05:10:34 2010
@@ -0,0 +1,8 @@
+#ifndef        __CLIENT_SIDE_IMS_H__
+#define        __CLIENT_SIDE_IMS_H__
+
+extern void clientProcessExpired(clientHttpRequest *);
+/* XXX this is likely not meant to be here */
+extern int modifiedSince(StoreEntry * entry, request_t * request);
+
+#endif
=======================================
--- /playpen/LUSCA_HEAD_zerocopy_storeread/configure.in Thu Dec 24 07:26:45 2009 +++ /playpen/LUSCA_HEAD_zerocopy_storeread/configure.in Mon Feb 22 05:10:34 2010
@@ -1687,7 +1687,6 @@
        db.h \
        db_185.h \
        aio.h \
-       sys/capability.h \
 ,,,[
 #if HAVE_SYS_TYPES_H
 #include <sys/types.h>
@@ -1721,6 +1720,13 @@
 #endif
 ])

+dnl Check for libcap header
+AC_ARG_ENABLE(caps,
+[ --disable-caps disable usage of Linux capabilities library to control privileges])
+if test "x$enable_caps" != xno; then
+       AC_CHECK_HEADERS( sys/capability.h )
+fi
+
 dnl Check for IP-Filter headers. These are a bit nasty..
 AC_CHECK_HEADERS( \
        ip_compat.h \
=======================================
--- /playpen/LUSCA_HEAD_zerocopy_storeread/libiapp/comm.c Sat Feb 20 04:40:02 2010 +++ /playpen/LUSCA_HEAD_zerocopy_storeread/libiapp/comm.c Mon Feb 22 05:10:34 2010
@@ -267,6 +267,7 @@
     F = &fd_table[new_socket];

     sqinet_init(&(F->local_address));
+    sqinet_init(&(F->remote_address));
     sqinet_copy(&(F->local_address), a);

     F->tos = tos;
@@ -560,6 +561,7 @@
     else
        return COMM_ERROR;
     sqinet_ntoa(addr, F->ipaddrstr, MAX_IPSTRLEN, 0);
+    sqinet_copy(&F->remote_address, addr);
     F->remote_port = sqinet_get_port(addr);
     if (status == COMM_OK) {
        debug(5, 10) ("comm_connect_addr: FD %d connected to %s:%d\n",
@@ -614,6 +616,7 @@
     fd_note_static(sock, "HTTP Request");
     F = &fd_table[sock];
     sqinet_ntoa(&rem, F->ipaddrstr, MAX_IPSTRLEN, 0);
+    sqinet_copy(&F->remote_address, &rem);
     F->remote_port = sqinet_get_port(&rem);
     F->local_port = sqinet_get_port(&loc);
     commSetNonBlocking(sock);
@@ -730,6 +733,7 @@
 comm_close_finish(int fd)
 {
     sqinet_done(&fd_table[fd].local_address);
+    sqinet_done(&fd_table[fd].remote_address);
     fd_close(fd);              /* update fdstat */
     close(fd);
     CommStats.syscalls.sock.closes++;
@@ -1589,6 +1593,10 @@
         sqinet_init(&fd_table[*cwfd].local_address);
         sqinet_init(&fd_table[*crfd].local_address);
         sqinet_init(&fd_table[*pwfd].local_address);
+        sqinet_init(&fd_table[*prfd].remote_address);
+        sqinet_init(&fd_table[*cwfd].remote_address);
+        sqinet_init(&fd_table[*crfd].remote_address);
+        sqinet_init(&fd_table[*pwfd].remote_address);

        return 1;
 }
@@ -1610,6 +1618,8 @@
         fd_open(*crfd = *cwfd = fds[1], FD_PIPE, "IPC UNIX STREAM Parent");
         sqinet_init(&fd_table[*prfd].local_address);
         sqinet_init(&fd_table[*crfd].local_address);
+        sqinet_init(&fd_table[*prfd].remote_address);
+        sqinet_init(&fd_table[*crfd].remote_address);

        return 1;
 }
@@ -1626,6 +1636,8 @@
        fd_open(*crfd = *cwfd = fds[1], FD_PIPE, "IPC UNIX DGRAM Parent");
         sqinet_init(&fd_table[*prfd].local_address);
         sqinet_init(&fd_table[*crfd].local_address);
+        sqinet_init(&fd_table[*prfd].remote_address);
+        sqinet_init(&fd_table[*crfd].remote_address);

        return 1;
 }
=======================================
--- /playpen/LUSCA_HEAD_zerocopy_storeread/libiapp/comm.h Wed Sep 30 00:25:34 2009 +++ /playpen/LUSCA_HEAD_zerocopy_storeread/libiapp/comm.h Mon Feb 22 05:10:34 2010
@@ -64,6 +64,7 @@
     u_short local_port;
     u_short remote_port;
     sqaddr_t local_address;
+    sqaddr_t remote_address;
     unsigned char tos;
char ipaddrstr[MAX_IPSTRLEN]; /* dotted decimal address of peer - XXX should be MAX_IPSTRLEN */
     const char *desc;
=======================================
--- /playpen/LUSCA_HEAD_zerocopy_storeread/src/Makefile.am Sat Feb 20 04:40:02 2010 +++ /playpen/LUSCA_HEAD_zerocopy_storeread/src/Makefile.am Mon Feb 22 05:10:34 2010
@@ -116,6 +116,7 @@
        client_side_rewrite.c \
        client_side_ranges.c \
        client_side_refresh.c \
+       client_side_ims.c \
        client_side_async_refresh.c \
        client_side_storeurl_rewrite.c \
        client_side_location_rewrite.c \
=======================================
--- /playpen/LUSCA_HEAD_zerocopy_storeread/src/acl.c Mon Oct 26 23:58:33 2009 +++ /playpen/LUSCA_HEAD_zerocopy_storeread/src/acl.c Mon Feb 22 05:10:34 2010
@@ -241,6 +241,8 @@
        return ACL_EXTUSER_REGEX;
     if (!strcmp(s, "hier_code"))
        return ACL_HIER_CODE;
+    if (! strcmp(s, "dstfwdip"))
+       return ACL_DSTFWD_IP;
     return ACL_NONE;
 }

@@ -339,6 +341,8 @@
        return "ext_user_regex";
     if (type == ACL_HIER_CODE)
        return "hier_code";
+    if (type == ACL_DSTFWD_IP)
+        return "dstfwdip";
     return "ERROR";
 }

@@ -1019,6 +1023,7 @@
     case ACL_SRC_IP:
     case ACL_DST_IP:
     case ACL_MY_IP:
+    case ACL_DSTFWD_IP:
        aclParseIpList(&A->data);
        break;
     case ACL_SRC_DOMAIN:
@@ -2091,6 +2096,13 @@
     case ACL_HIER_CODE:
return aclMatchWordList(ae->data, hier_strings[checklist->request->hier.code]);
        /* NOTREACHED */
+    case ACL_DSTFWD_IP:
+ /* make sure this checks that the dstfwdip is SET to something non-blank and
+        * error out in case. */
+       if (IsAnyAddr(&checklist->fwdip_addr))
+           return -1;
+       return aclMatchIp(&ae->data, checklist->fwdip_addr);
+       /* NOTREACHED */
     case ACL_NONE:
     case ACL_ENUM_MAX:
        break;
@@ -2559,6 +2571,7 @@
        case ACL_SRC_IP:
        case ACL_DST_IP:
        case ACL_MY_IP:
+       case ACL_DSTFWD_IP:
            splay_destroy(a->data, aclFreeIpData);
            break;
 #if USE_ARP_ACL
@@ -3005,6 +3018,7 @@
     case ACL_SRC_IP:
     case ACL_DST_IP:
     case ACL_MY_IP:
+    case ACL_DSTFWD_IP:
        return aclDumpIpList(a->data);
     case ACL_SRC_DOMAIN:
     case ACL_DST_DOMAIN:
=======================================
--- /playpen/LUSCA_HEAD_zerocopy_storeread/src/cf.data.pre Sat Feb 20 04:40:02 2010 +++ /playpen/LUSCA_HEAD_zerocopy_storeread/src/cf.data.pre Mon Feb 22 05:10:34 2010
@@ -516,6 +516,16 @@
        acl aclname dst      ip-address/netmask ... (URL host's IP address)
        acl aclname myip     ip-address/netmask ... (local socket IP address)

+       acl aclname dstfwdip ip-address/netmask
+         # This ACL matches on the IP address of the host being forwarded to.
+         # This will be the IP of either the upstream origin server or the
+         # parent/sibling peer.
+         #
+         # Since the IP address of the forwarding host may change depending
+         # upon the current state of the forwarding process, this ACL is only
+         # really useful for one specific directive (which will be coded up
+         # shortly) and will always fail when used elsewhere.
+
        acl aclname arp      mac-address ... (xx:xx:xx:xx:xx:xx notation)
          # The arp ACL requires the special configure option --enable-arp-acl.
# Furthermore, the arp ACL code is not portable to all operating systems.
=======================================
--- /playpen/LUSCA_HEAD_zerocopy_storeread/src/client_db.c Fri Nov 13 00:29:46 2009 +++ /playpen/LUSCA_HEAD_zerocopy_storeread/src/client_db.c Mon Feb 22 05:10:34 2010
@@ -61,7 +61,7 @@

 typedef struct _ClientInfo ClientInfo;

-static radix_tree_t *client_tree = NULL;
+static radix_tree_t *client_v4_tree = NULL;
 dlink_list client_list;

 static ClientInfo *clientdbAdd(struct in_addr addr);
@@ -85,7 +85,7 @@
     Init_Prefix(&p, AF_INET, &addr, 32);
     c = memPoolAlloc(pool_client_info);
     c->addr = addr;
-    rn = radix_lookup(client_tree, &p);
+    rn = radix_lookup(client_v4_tree, &p);
     rn->data = c;
     dlinkAddTail(c, &c->node, &client_list);
     statCounter.client_http.clients++;
@@ -106,9 +106,9 @@
 void
 clientdbInit(void)
 {
-    if (client_tree)
+    if (client_v4_tree)
         return;
-    client_tree = New_Radix();
+    client_v4_tree = New_Radix();
cachemgrRegister("client_list", "Cache Client List", clientdbDump, 0, 1);
 }

@@ -123,7 +123,7 @@
        return;

     Init_Prefix(&pr, AF_INET, &addr, 32);
-    rn = radix_search_exact(client_tree, &pr);
+    rn = radix_search_exact(client_v4_tree, &pr);

     if (rn)
         c = rn->data;
@@ -164,7 +164,7 @@
     if (!Config.onoff.client_db)
        return 0;
     Init_Prefix(&p, AF_INET, &addr, 32);
-    rn = radix_search_exact(client_tree, &p);
+    rn = radix_search_exact(client_v4_tree, &p);
     if (rn)
         c = rn->data;
     if (c == NULL)
@@ -190,7 +190,7 @@
        return 0;

     Init_Prefix(&pr, AF_INET, &addr, 32);
-    rn = radix_search_exact(client_tree, &pr);
+    rn = radix_search_exact(client_v4_tree, &pr);
     if (rn)
         c = rn->data;

@@ -280,7 +280,7 @@
     bzero(&ci, sizeof(ci));
     storeAppendPrintf(sentry, "Cache Clients:\n");

-    RADIX_WALK(client_tree->head, rn) {
+    RADIX_WALK(client_v4_tree->head, rn) {
       c = rn->data;
       clientdbDumpEntry(sentry, c, &ci);
     } RADIX_WALK_END;
@@ -311,8 +311,8 @@
 void
 clientdbFreeMemory(void)
 {
-    Destroy_Radix(client_tree, clientdbFreeItemRadix, NULL);
-    client_tree = NULL;
+    Destroy_Radix(client_v4_tree, clientdbFreeItemRadix, NULL);
+    client_v4_tree = NULL;
 }

 static void
@@ -345,9 +345,9 @@
           continue;

       Init_Prefix(&p, AF_INET, &c->addr, 32);
-      rn = radix_search_exact(client_tree, &p);
+      rn = radix_search_exact(client_v4_tree, &p);
       rn->data = NULL;
-      radix_remove(client_tree, rn);
+      radix_remove(client_v4_tree, rn);
       clientdbFreeItem(c);

       cleanup_removed++;
=======================================
--- /playpen/LUSCA_HEAD_zerocopy_storeread/src/client_side.c Sat Feb 20 04:40:02 2010 +++ /playpen/LUSCA_HEAD_zerocopy_storeread/src/client_side.c Mon Feb 22 05:10:34 2010
@@ -42,6 +42,7 @@
 #include "client_side_async_refresh.h"
 #include "client_side_refresh.h"
 #include "client_side_etag.h"
+#include "client_side_ims.h"

 #include "client_side.h"

@@ -70,13 +71,10 @@
static clientHttpRequest *parseHttpRequestAbort(ConnStateData * conn, method_t ** method_p, const char *uri); static clientHttpRequest *parseHttpRequest(ConnStateData *, HttpMsgBuf *, method_t **, int *);

-static STHCB clientHandleIMSReply;
-static int clientGetsOldEntry(StoreEntry * new, StoreEntry * old, request_t * request);
 #if USE_IDENT
 static IDCB clientIdentDone;
 #endif

-static int clientOnlyIfCached(clientHttpRequest * http);
 static STNCB clientSendMoreData;
 static STHCB clientCacheHit;
 static void clientSetKeepaliveFlag(clientHttpRequest *);
@@ -91,7 +89,6 @@
static void httpsAcceptSSL(ConnStateData * connState, SSL_CTX * sslContext);
 #endif
 static int varyEvaluateMatch(StoreEntry * entry, request_t * request);
-static int modifiedSince(StoreEntry *, request_t *);
 static int clientCheckBeginForwarding(clientHttpRequest * http);

 #if USE_IDENT
@@ -128,7 +125,7 @@
* returns true if client specified that the object must come from the cache
  * without contacting origin server
  */
-static int
+int
 clientOnlyIfCached(clientHttpRequest * http)
 {
     const request_t *r = http->request;
@@ -158,296 +155,6 @@
     storeClientCopyHeaders(h->sc, e, clientSendHeaders, h);
     return e;
 }
-
-void
-clientProcessExpired(clientHttpRequest * http)
-{
-    char *url = http->uri;
-    StoreEntry *entry = NULL;
-    int hit = 0;
-    const char *etag;
- const int can_revalidate = http->entry->mem_obj->reply->sline.status == HTTP_OK;
-    debug(33, 3) ("clientProcessExpired: '%s'\n", http->uri);
-    /*
-     * check if we are allowed to contact other servers
-     * @?@: Instead of a 504 (Gateway Timeout) reply, we may want to return
-     *      a stale entry *if* it matches client requirements
-     */
-    if (clientOnlyIfCached(http)) {
-       clientProcessOnlyIfCachedMiss(http);
-       return;
-    }
-    http->request->flags.refresh = 1;
-    http->old_entry = http->entry;
-    http->old_sc = http->sc;
-    if (http->entry->mem_obj && http->entry->mem_obj->ims_entry) {
-       entry = http->entry->mem_obj->ims_entry;
-       debug(33, 5) ("clientProcessExpired: collapsed request\n");
-       if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
-           debug(33, 1) ("clientProcessExpired: collapsed request ABORTED!\n");
-           entry = NULL;
- } else if (http->entry->mem_obj->refresh_timestamp + Config.collapsed_forwarding_timeout < squid_curtime) {
-           debug(33, 1) ("clientProcessExpired: collapsed request STALE!\n");
-           entry = NULL;
-       }
-       if (entry) {
-           http->request->flags.collapsed = 1;           /* Don't trust the 
store entry */
-           storeLockObject(entry);
-           hit = 1;
-       } else {
-           storeUnlockObject(http->entry->mem_obj->ims_entry);
-           http->entry->mem_obj->ims_entry = NULL;
-       }
-    }
-    if (!entry) {
- entry = storeCreateEntry(url, http->request->flags, http->request->method);
-       if (http->request->store_url)
-           storeEntrySetStoreUrl(entry, http->request->store_url);
-       if (http->entry->mem_obj) {
-           http->entry->mem_obj->refresh_timestamp = squid_curtime;
-           if (Config.onoff.collapsed_forwarding) {
-               http->entry->mem_obj->ims_entry = entry;
-               storeLockObject(http->entry->mem_obj->ims_entry);
-           }
-       }
-    }
-    if (entry->mem_obj->old_entry) {
-       storeUnlockObject(entry->mem_obj->old_entry);
-       entry->mem_obj->old_entry = NULL;
-    }
-    entry->mem_obj->old_entry = http->old_entry;
-    storeLockObject(entry->mem_obj->old_entry);
-    http->sc = storeClientRegister(entry, http);
-#if DELAY_POOLS
-    /* delay_id is already set on original store client */
-    delaySetStoreClient(http->sc, delayClient(http));
-#endif
-    if (can_revalidate && http->old_entry->lastmod > 0) {
-       http->request->lastmod = http->old_entry->lastmod;
-       http->request->flags.cache_validation = 1;
-    } else
-       http->request->lastmod = -1;
- debug(33, 5) ("clientProcessExpired: lastmod %ld\n", (long int) entry->lastmod);
-    /* NOTE, don't call storeLockObject(), storeCreateEntry() does it */
-    http->entry = entry;
-    http->out.offset = 0;
-    if (can_revalidate) {
- etag = httpHeaderGetStr(&http->old_entry->mem_obj->reply->header, HDR_ETAG);
-       if (etag) {
-           http->request->etag = xstrdup(etag);
-           http->request->flags.cache_validation = 1;
-       }
-    }
-    if (!hit)
-       fwdStart(http->conn->fd, http->entry, http->request);
- /* Register with storage manager to receive updates when data comes in. */
-    if (EBIT_TEST(entry->flags, ENTRY_ABORTED))
-       debug(33, 0) ("clientProcessExpired: found ENTRY_ABORTED object\n");
-    storeClientCopyHeaders(http->sc, entry,
-       clientHandleIMSReply,
-       http);
-}
-
-static int
-clientGetsOldEntry(StoreEntry * new_entry, StoreEntry * old_entry, request_t * request)
-{
-    const http_status status = new_entry->mem_obj->reply->sline.status;
-    if (0 == status) {
-       debug(33, 5) ("clientGetsOldEntry: YES, broken HTTP reply\n");
-       return 1;
-    }
-    /* If the reply is a failure then send the old object as a last
-     * resort */
-    if (status >= 500 && status < 600) {
-       if (EBIT_TEST(new_entry->flags, ENTRY_NEGCACHED)) {
- debug(33, 3) ("clientGetsOldEntry: NO, negatively cached failure reply=%d\n", status);
-           return 0;
-       }
-       if (refreshCheckStaleOK(old_entry, request)) {
- debug(33, 3) ("clientGetsOldEntry: YES, failure reply=%d and old acceptable to send\n", status);
-           return 1;
-       }
- debug(33, 3) ("clientGetsOldEntry: NO, failure reply=%d and old NOT acceptable to send\n", status);
-       return 0;
-    }
-    /* If the reply is not to a cache validation conditional then
-     * we should forward it to the client */
-    if (!request->flags.cache_validation) {
-       debug(33, 5) ("clientGetsOldEntry: NO, not a cache validation\n");
-       return 0;
-    }
-    /* If the reply is anything but "Not Modified" then
-     * we must forward it to the client */
-    if (HTTP_NOT_MODIFIED != status) {
-       debug(33, 5) ("clientGetsOldEntry: NO, reply=%d\n", status);
-       return 0;
-    }
-    /* If the ETag matches the clients If-None-Match, then return
-     * the servers 304 reply
-     */
-    if (httpHeaderHas(&new_entry->mem_obj->reply->header, HDR_ETAG) &&
-       httpHeaderHas(&request->header, HDR_IF_NONE_MATCH)) {
- const char *etag = httpHeaderGetStr(&new_entry->mem_obj->reply->header, HDR_ETAG);
-       String etags = httpHeaderGetList(&request->header, HDR_IF_NONE_MATCH);
-       int etag_match = strListIsMember(&etags, etag, ',');
-       stringClean(&etags);
-       if (etag_match) {
-           debug(33, 5) ("clientGetsOldEntry: NO, client If-None-Match\n");
-           return 0;
-       }
-    }
-    /* If the client did not send IMS in the request, then it
-     * must get the old object, not this "Not Modified" reply */
-    if (!request->flags.ims) {
-       debug(33, 5) ("clientGetsOldEntry: YES, no client IMS\n");
-       return 1;
-    }
-    /* If the client IMS time is prior to the entry LASTMOD time we
-     * need to send the old object */
-    if (modifiedSince(old_entry, request)) {
-       debug(33, 5) ("clientGetsOldEntry: YES, modified since %ld\n",
-           (long int) request->ims);
-       return 1;
-    }
-    debug(33, 5) ("clientGetsOldEntry: NO, new one is fine\n");
-    return 0;
-}
-
-
-static void
-clientHandleIMSReply(void *data, HttpReply * rep)
-{
-    clientHttpRequest *http = data;
-    StoreEntry *entry = http->entry;
-    MemObject *mem;
-    const char *url = storeUrl(entry);
-    int unlink_request = 0;
-    StoreEntry *oldentry;
-    int recopy = 1;
-    debug(33, 3) ("clientHandleIMSReply: %s\n", url);
- if (http->old_entry && http->old_entry->mem_obj && http->old_entry->mem_obj->ims_entry) {
-       storeUnlockObject(http->old_entry->mem_obj->ims_entry);
-       http->old_entry->mem_obj->ims_entry = NULL;
-    }
-    if (entry == NULL) {
-       return;
-    }
-    if (entry->mem_obj->old_entry) {
-       storeUnlockObject(entry->mem_obj->old_entry);
-       entry->mem_obj->old_entry = NULL;
-    }
-    mem = entry->mem_obj;
-    if (!rep) {
-       debug(33, 3) ("clientHandleIMSReply: ABORTED '%s'\n", url);
-       /* We have an existing entry, but failed to validate it */
-       /* Its okay to send the old one anyway */
-       http->log_type = LOG_TCP_REFRESH_FAIL_HIT;
-       storeClientUnregister(http->sc, entry, http);
-       storeUnlockObject(entry);
-       entry = http->entry = http->old_entry;
-       http->sc = http->old_sc;
-    } else if (clientGetsOldEntry(entry, http->old_entry, http->request)) {
-       /* We initiated the IMS request, the client is not expecting
-        * 304, so put the good one back.  First, make sure the old entry
-        * headers have been loaded from disk. */
-       oldentry = http->old_entry;
-       if (oldentry->mem_obj->request == NULL) {
-           oldentry->mem_obj->request = requestLink(mem->request);
-           unlink_request = 1;
-       }
-       if (rep->sline.status == HTTP_NOT_MODIFIED) {
-           /* Don't memcpy() the whole reply structure here.  For example,
-            * www.thegist.com (Netscape/1.13) returns a content-length for
-            * 304's which seems to be the length of the 304 HEADERS!!! and
-            * not the body they refer to.  */
-           httpReplyUpdateOnNotModified(oldentry->mem_obj->reply, rep);
-           storeTimestampsSet(oldentry);
-           storeUpdate(oldentry, http->request);
-           http->log_type = LOG_TCP_REFRESH_HIT;
-       } else {
-           http->log_type = LOG_TCP_REFRESH_FAIL_HIT;
-       }
-       storeClientUnregister(http->sc, entry, http);
-       http->sc = http->old_sc;
-       storeUnlockObject(entry);
-       entry = http->entry = oldentry;
-       if (unlink_request) {
-           requestUnlink(entry->mem_obj->request);
-           entry->mem_obj->request = NULL;
-       }
-    } else {
-       /* the client can handle this reply, whatever it is */
-       http->flags.hit = 0;
-       http->log_type = LOG_TCP_REFRESH_MISS;
- if (HTTP_NOT_MODIFIED == rep->sline.status && http->request->flags.cache_validation) {
-           httpReplyUpdateOnNotModified(http->old_entry->mem_obj->reply,
-               rep);
-           storeTimestampsSet(http->old_entry);
-           storeUpdate(http->old_entry, http->request);
-           if (!EBIT_TEST(http->old_entry->flags, REFRESH_FAILURE))
-               http->log_type = LOG_TCP_REFRESH_HIT;
-           else
-               http->log_type = LOG_TCP_REFRESH_FAIL_HIT;
-       }
-       /* Get rid of the old entry if not a cache validation */
-       if (!http->request->flags.cache_validation)
-           storeRelease(http->old_entry);
-       storeClientUnregister(http->old_sc, http->old_entry, http);
-       storeUnlockObject(http->old_entry);
-       recopy = 0;
-    }
-    http->old_entry = NULL; /* done with old_entry */
-    http->old_sc = NULL;
- if (http->request->flags.collapsed && !http->flags.hit && EBIT_TEST(entry->flags, RELEASE_REQUEST)) {
-       /* Collapsed request, but the entry is not good to be sent */
-       clientProcessMiss(http);
-       return;
-    }
-    if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
-       /* Old object got aborted, not good */
-       clientProcessMiss(http);
-        return;
-    }
-    if (recopy) {
-       storeClientCopyHeaders(http->sc, entry,
-           clientSendHeaders,
-           http);
-    } else {
-       clientSendHeaders(data, rep);
-    }
-}
-
-static int
-modifiedSince(StoreEntry * entry, request_t * request)
-{
-    squid_off_t object_length;
-    MemObject *mem = entry->mem_obj;
-    time_t mod_time = entry->lastmod;
-    debug(33, 3) ("modifiedSince: '%s'\n", storeLookupUrl(entry));
-    debug(33, 3) ("modifiedSince: mod_time = %ld\n", (long int) mod_time);
-    if (mod_time < 0)
-       return 1;
-    /* Find size of the object */
-    object_length = mem->reply->content_length;
-    if (object_length < 0)
-       object_length = contentLen(entry);
-    if (mod_time > request->ims) {
-       debug(33, 3) ("--> YES: entry newer than client\n");
-       return 1;
-    } else if (mod_time < request->ims) {
-       debug(33, 3) ("-->  NO: entry older than client\n");
-       return 0;
-    } else if (request->imslen < 0) {
-       debug(33, 3) ("-->  NO: same LMT, no client length\n");
-       return 0;
-    } else if (request->imslen == object_length) {
-       debug(33, 3) ("-->  NO: same LMT, same length\n");
-       return 0;
-    } else {
-       debug(33, 3) ("--> YES: same LMT, different length\n");
-       return 1;
-    }
-}

 static void
 clientPurgeRequest(clientHttpRequest * http)
@@ -1329,6 +1036,54 @@
     http->request->vary = vary;
     clientProcessRequest(http);
 }
+
+/*
+ * This particular logic is a bit hairy.
+ *
+ * + If we have a store URL then we need to make sure the mem store url OR the mem url
+ *   match the request store url.
+ * + If we have no store URL then we need to make sure the mem url match the request url + * regardless of the store url (so objects which have store urls that match their urls
+ *   can still be HIT fine.)
+*/
+static int
+clientCheckUrlIsValid(clientHttpRequest *http)
+{
+       StoreEntry *e = http->entry;
+       MemObject *mem = e->mem_obj;
+       request_t *r = http->request;
+
+       if (r->store_url) {
+               if (mem->store_url == NULL && mem->url == NULL) {
+ debug(33, 1) ("clientCacheHit: request has store_url '%s'; mem has no url or store_url!\n",
+                           r->store_url);
+                       return 0;
+               }
+               if (mem->store_url && strcmp(r->store_url, mem->store_url) != 
0) {
+ debug(33, 1) ("clientCacheHit: request has store_url '%s'; mem object in hit has mis-matched store_url '%s'!\n",
+                           r->store_url, mem->store_url);
+                   return 0;
+               }
+ if (mem->store_url == NULL && mem->url && strcmp(r->store_url, mem->url) != 0) { + debug(33, 1) ("clientCacheHit: request has store_url '%s'; mem object in hit has mis-matched url '%s'!\n",
+                           r->store_url, mem->url);
+                   return 0;
+               }
+       } else {                        /* no store URL in request */
+               if (mem->store_url == NULL && mem->url == NULL) {
+ debug(33, 1) ("clientCacheHit: request has url '%s'; mem has no url or store_url!\n",
+                           urlCanonical(r));
+                       return 0;
+               }
+ /* We currently don't enforce that memObjects with storeurl's -require- a request with a storeurl */
+               if (strcmp(mem->url, urlCanonical(r)) != 0) {
+ debug(33, 1) ("clientCacheHit: (store url '%s'); URL mismatch '%s' != '%s'?\n",
+                           r->store_url, e->mem_obj->url, urlCanonical(r));
+                       return 0;
+               }
+       }
+       return 1;
+}

 /*
  * clientCacheHit should only be called until the HTTP reply headers
@@ -1366,43 +1121,11 @@
     mem = e->mem_obj;
debug(33, 3) ("clientCacheHit: %s = %d\n", http->uri, rep->sline.status);

-    /*
-     * This particular logic is a bit hairy.
-     *
- * + If we have a store URL then we need to make sure the mem store url OR the mem url
-     *   match the request store url.
- * + If we have no store URL then we need to make sure the mem url match the request url - * regardless of the store url (so objects which have store urls that match their urls
-     *   can still be HIT fine.)
-     */
-    if (r->store_url) {
-       if (mem->store_url == NULL && mem->url == NULL) {
- debug(33, 1) ("clientCacheHit: request has store_url '%s'; mem has no url or store_url!\n", r->store_url);
-           clientProcessMiss(http);
-           return;
-       }
-       if (mem->store_url && strcmp(r->store_url, mem->store_url) != 0) {
- debug(33, 1) ("clientCacheHit: request has store_url '%s'; mem object in hit has mis-matched store_url '%s'!\n", r->store_url, mem->store_url);
-           clientProcessMiss(http);
-           return;
-       }
- if (mem->store_url == NULL && mem->url && strcmp(r->store_url, mem->url) != 0) { - debug(33, 1) ("clientCacheHit: request has store_url '%s'; mem object in hit has mis-matched url '%s'!\n", r->store_url, mem->url);
-           clientProcessMiss(http);
-           return;
-       }
-    } else {                   /* no store URL in request */
-       if (mem->store_url == NULL && mem->url == NULL) {
- debug(33, 1) ("clientCacheHit: request has url '%s'; mem has no url or store_url!\n", urlCanonical(r));
-           clientProcessMiss(http);
-           return;
-       }
- /* We currently don't enforce that memObjects with storeurl's -require- a request with a storeurl */
-       if (strcmp(mem->url, urlCanonical(r)) != 0) {
- debug(33, 1) ("clientCacheHit: (store url '%s'); URL mismatch '%s' != '%s'?\n", r->store_url, e->mem_obj->url, urlCanonical(r));
-           clientProcessMiss(http);
-           return;
-       }
+    /* Make sure the request URL matches the object URL. */
+    /* Take the store URL into account! */
+    if (! clientCheckUrlIsValid(http)) {
+        clientProcessMiss(http);
+        return;
     }
     if (r->flags.collapsed && EBIT_TEST(e->flags, RELEASE_REQUEST)) {
        /* collapsed_forwarding, but the joined request is not good
@@ -2397,42 +2120,25 @@
     errorAppendEntry(http->entry, err);
 }

-/*
- * Return true if we should force a cache miss on this range request.
- * entry must be non-NULL.
+/*
+ * clientProcessRequest2() encapsulates some of the final request caching
+ * logic.
+ *
+ * This is all very dirty and not at all documented; it's quite suprising
+ * it all holds together.
+ *
+ * + If the request is deemed to be cachable, it does a storeEntry lookup
+ * + If the request has no-cache set, it invalidates ipcache entries
+ * + If the object doesn't exist, it checks some etag processing logic
+ *   and then finishes processing
+ * + There's a "too complex ranges!" check there which forces a miss
+ *
+ * + If LOG_TCP_HIT is returned, it sets http->e to be the cache StoreEntry.
+ * + If LOG_TCP_MISS is returned, http->e is forcibly set to NULL.
+ *
+ * I am guessing that http->e is already NULL at this point as StoreEntry
+ * references may be refcounted.
  */
-static int
-clientCheckRangeForceMiss(StoreEntry * entry, HttpHdrRange * range)
-{
-    /*
-     * If the range_offset_limit is NOT in effect, there
-     * is no reason to force a miss.
-     */
-    if (0 == httpHdrRangeOffsetLimit(range))
-       return 0;
-    /*
-     * Here, we know it's possibly a hit.  If we already have the
-     * whole object cached, we won't force a miss.
-     */
-    if (STORE_OK == entry->store_status)
-       return 0;               /* we have the whole object */
-    /*
-     * Now we have a hit on a PENDING object.  We need to see
-     * if the part we want is already cached.  If so, we don't
-     * force a miss.
-     */
-    assert(NULL != entry->mem_obj);
-    if (httpHdrRangeFirstOffset(range) <= entry->mem_obj->inmem_hi)
-       return 0;
-    /*
-     * Even though we have a PENDING copy of the object, we
-     * don't want to wait to reach the first range offset,
-     * so we force a miss for a new range request to the
-     * origin.
-     */
-    return 1;
-}
-
 static log_type
 clientProcessRequest2(clientHttpRequest * http)
 {
=======================================
--- /playpen/LUSCA_HEAD_zerocopy_storeread/src/client_side.h Sat Feb 20 04:40:02 2010 +++ /playpen/LUSCA_HEAD_zerocopy_storeread/src/client_side.h Mon Feb 22 05:10:34 2010
@@ -11,10 +11,10 @@
 extern void clientProcessHit(clientHttpRequest * http);
 extern void clientProcessMiss(clientHttpRequest * http);
 extern void clientProcessRequest(clientHttpRequest *);
-extern void clientProcessExpired(clientHttpRequest *);
 extern void clientProcessOnlyIfCachedMiss(clientHttpRequest * http);
 extern void httpRequestFree(void *data);
 extern void clientKeepaliveNextRequest(clientHttpRequest * http);
 extern STHCB clientSendHeaders;
+extern int clientOnlyIfCached(clientHttpRequest * http);

 #endif
=======================================
--- /playpen/LUSCA_HEAD_zerocopy_storeread/src/client_side_ranges.c Sat Feb 20 04:40:02 2010 +++ /playpen/LUSCA_HEAD_zerocopy_storeread/src/client_side_ranges.c Mon Feb 22 05:10:34 2010
@@ -315,3 +315,39 @@
     }
 }

+/*
+ * Return true if we should force a cache miss on this range request.
+ * entry must be non-NULL.
+ */
+int
+clientCheckRangeForceMiss(StoreEntry * entry, HttpHdrRange * range)
+{
+    /*
+     * If the range_offset_limit is NOT in effect, there
+     * is no reason to force a miss.
+     */
+    if (0 == httpHdrRangeOffsetLimit(range))
+        return 0;
+    /*
+     * Here, we know it's possibly a hit.  If we already have the
+     * whole object cached, we won't force a miss.
+     */
+    if (STORE_OK == entry->store_status)
+        return 0;               /* we have the whole object */
+    /*
+     * Now we have a hit on a PENDING object.  We need to see
+     * if the part we want is already cached.  If so, we don't
+     * force a miss.
+     */
+    assert(NULL != entry->mem_obj);
+    if (httpHdrRangeFirstOffset(range) <= entry->mem_obj->inmem_hi)
+        return 0;
+    /*
+     * Even though we have a PENDING copy of the object, we
+     * don't want to wait to reach the first range offset,
+     * so we force a miss for a new range request to the
+     * origin.
+     */
+    return 1;
+}
+
=======================================
--- /playpen/LUSCA_HEAD_zerocopy_storeread/src/client_side_ranges.h Sat Feb 20 04:40:02 2010 +++ /playpen/LUSCA_HEAD_zerocopy_storeread/src/client_side_ranges.h Mon Feb 22 05:10:34 2010
@@ -8,5 +8,6 @@
extern int clientCanPackMoreRanges(const clientHttpRequest * http, HttpHdrRangeIter * i, size_t size); extern int clientPackMoreRanges(clientHttpRequest * http, const char *buf, size_t size, MemBuf * mb); extern void clientBuildRangeHeader(clientHttpRequest * http, HttpReply * rep); +extern int clientCheckRangeForceMiss(StoreEntry * entry, HttpHdrRange * range);

 #endif
=======================================
--- /playpen/LUSCA_HEAD_zerocopy_storeread/src/client_side_refresh.c Sat Feb 20 04:40:02 2010 +++ /playpen/LUSCA_HEAD_zerocopy_storeread/src/client_side_refresh.c Mon Feb 22 05:10:34 2010
@@ -1,6 +1,7 @@
 #include "squid.h"

 #include "client_side_refresh.h"
+#include "client_side_ims.h"
 #include "client_side.h"

 static void
=======================================
--- /playpen/LUSCA_HEAD_zerocopy_storeread/src/enums.h Tue Apr 21 02:11:04 2009 +++ /playpen/LUSCA_HEAD_zerocopy_storeread/src/enums.h Mon Feb 22 05:10:34 2010
@@ -153,6 +153,7 @@
     ACL_EXTUSER,
     ACL_EXTUSER_REGEX,
     ACL_HIER_CODE,
+    ACL_DSTFWD_IP,
     ACL_ENUM_MAX
 } squid_acl;

=======================================
--- /playpen/LUSCA_HEAD_zerocopy_storeread/src/structs.h Sat Feb 20 05:55:18 2010 +++ /playpen/LUSCA_HEAD_zerocopy_storeread/src/structs.h Mon Feb 22 05:10:34 2010
@@ -288,6 +288,7 @@
     struct in_addr src_addr;
     struct in_addr dst_addr;
     struct in_addr my_addr;
+    struct in_addr fwdip_addr;
     unsigned short my_port;
     request_t *request;
     /* for acls that look at reply data */
=======================================
--- /playpen/LUSCA_HEAD_zerocopy_storeread/src/tools.c Wed Jul 8 15:28:20 2009 +++ /playpen/LUSCA_HEAD_zerocopy_storeread/src/tools.c Mon Feb 22 05:10:34 2010
@@ -42,11 +42,6 @@

 #ifdef _SQUID_LINUX_
 #if HAVE_SYS_CAPABILITY_H
-#undef _POSIX_SOURCE
-/* Ugly glue to get around linux header madness colliding with glibc */
-#define _LINUX_TYPES_H
-#define _LINUX_FS_H
-typedef uint32_t __u32;
 #include <sys/capability.h>
 #endif
 #endif

--
You received this message because you are subscribed to the Google Groups 
"lusca-commit" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/lusca-commit?hl=en.

Reply via email to