]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/store.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / store.cc
index c4ffa93b5c4daf94fc78e7451695df0bd0a63e63..b4a9939f6a54eb75b62f219cd18e28d342744a8f 100644 (file)
@@ -1,7 +1,5 @@
 
 /*
- * $Id$
- *
  * DEBUG: section 20    Storage Manager
  * AUTHOR: Harvest Derived
  *
  */
 
 #include "squid.h"
+#include "CacheDigest.h"
+#include "CacheManager.h"
+#include "comm/Connection.h"
+#include "ETag.h"
 #include "event.h"
 #include "fde.h"
-#include "Store.h"
-#include "mgr/Registration.h"
-#include "StoreClient.h"
-#include "stmem.h"
+#include "globals.h"
+#include "http.h"
 #include "HttpReply.h"
 #include "HttpRequest.h"
-#include "MemObject.h"
 #include "mem_node.h"
+#include "MemObject.h"
+#include "mgr/Registration.h"
+#include "mgr/StoreIoAction.h"
+#include "profiler/Profiler.h"
+#include "repl_modules.h"
+#include "RequestFlags.h"
+#include "SquidConfig.h"
+#include "SquidTime.h"
+#include "Stack.h"
+#include "StatCounters.h"
+#include "stmem.h"
+#include "Store.h"
+#include "store_digest.h"
+#include "store_key_md5.h"
+#include "store_key_md5.h"
+#include "store_log.h"
+#include "store_rebuild.h"
+#include "StoreClient.h"
+#include "StoreIOState.h"
 #include "StoreMeta.h"
+#include "StrList.h"
+#include "swap_log_op.h"
 #include "SwapDir.h"
-#include "StoreIOState.h"
+#include "tools.h"
 #if USE_DELAY_POOLS
 #include "DelayPools.h"
 #endif
-#include "Stack.h"
-#include "SquidTime.h"
-#include "swap_log_op.h"
-#include "mgr/StoreIoAction.h"
+#if HAVE_LIMITS_H
+#include <limits.h>
+#endif
 
 static STMCB storeWriteComplete;
 
@@ -61,7 +80,6 @@ static STMCB storeWriteComplete;
 
 #define STORE_IN_MEM_BUCKETS            (229)
 
-
 /** \todo Convert these string constants to enum string-arrays generated */
 
 const char *memStatusStr[] = {
@@ -86,7 +104,6 @@ const char *swapStatusStr[] = {
     "SWAPOUT_DONE"
 };
 
-
 /*
  * This defines an repl type
  */
@@ -100,7 +117,6 @@ struct _storerepl_entry {
 
 static storerepl_entry_t *storerepl_list = NULL;
 
-
 /*
  * local function prototypes
  */
@@ -220,14 +236,14 @@ void
 StoreEntry::DeferReader(void *theContext, CommRead const &aRead)
 {
     StoreEntry *anEntry = (StoreEntry *)theContext;
-    anEntry->delayAwareRead(aRead.fd,
+    anEntry->delayAwareRead(aRead.conn,
                             aRead.buf,
                             aRead.len,
                             aRead.callback);
 }
 
 void
-StoreEntry::delayAwareRead(int fd, char *buf, int len, AsyncCall::Pointer callback)
+StoreEntry::delayAwareRead(const Comm::ConnectionPointer &conn, char *buf, int len, AsyncCall::Pointer callback)
 {
     size_t amountToRead = bytesWanted(Range<size_t>(0, len));
     /* sketch: readdeferer* = getdeferer.
@@ -241,40 +257,37 @@ StoreEntry::delayAwareRead(int fd, char *buf, int len, AsyncCall::Pointer callba
 #if USE_DELAY_POOLS
         if (!mem_obj->readAheadPolicyCanRead()) {
 #endif
-            mem_obj->delayRead(DeferredRead(DeferReader, this, CommRead(fd, buf, len, callback)));
+            mem_obj->delayRead(DeferredRead(DeferReader, this, CommRead(conn, buf, len, callback)));
             return;
 #if USE_DELAY_POOLS
         }
 
         /* delay id limit */
-        mem_obj->mostBytesAllowed().delayRead(DeferredRead(DeferReader, this, CommRead(fd, buf, len, callback)));
-
+        mem_obj->mostBytesAllowed().delayRead(DeferredRead(DeferReader, this, CommRead(conn, buf, len, callback)));
         return;
 
 #endif
 
     }
 
-    if (fd_table[fd].closing()) {
+    if (fd_table[conn->fd].closing()) {
         // Readers must have closing callbacks if they want to be notified. No
         // readers appeared to care around 2009/12/14 as they skipped reading
         // for other reasons. Closing may already be true at the delyaAwareRead
         // call time or may happen while we wait after delayRead() above.
-        debugs(20, 3, HERE << "wont read from closing FD " << fd << " for " <<
+        debugs(20, 3, HERE << "wont read from closing " << conn << " for " <<
                callback);
         return; // the read callback will never be called
     }
 
-    comm_read(fd, buf, amountToRead, callback);
+    comm_read(conn, buf, amountToRead, callback);
 }
 
 size_t
-StoreEntry::bytesWanted (Range<size_t> const aRange) const
+StoreEntry::bytesWanted (Range<size_t> const aRange, bool ignoreDelayPools) const
 {
-    assert (aRange.size());
-
     if (mem_obj == NULL)
-        return aRange.end - 1;
+        return aRange.end;
 
 #if URL_CHECKSUM_DEBUG
 
@@ -282,14 +295,10 @@ StoreEntry::bytesWanted (Range<size_t> const aRange) const
 
 #endif
 
-    /* Always read *something* here - we haven't got the header yet */
-    if (EBIT_TEST(flags, ENTRY_FWD_HDR_WAIT))
-        return aRange.end - 1;
-
     if (!mem_obj->readAheadPolicyCanRead())
         return 0;
 
-    return mem_obj->mostBytesWanted(aRange.end - 1);
+    return mem_obj->mostBytesWanted(aRange.end, ignoreDelayPools);
 }
 
 bool
@@ -314,7 +323,7 @@ StoreEntry::storeClientType() const
      * offset 0 in the memory object is the HTTP headers.
      */
 
-    if (mem_status == IN_MEMORY && UsingSmp()) {
+    if (mem_status == IN_MEMORY && Config.memShared && IamWorkerProcess()) {
         // clients of an object cached in shared memory are memory clients
         return STORE_MEM_CLIENT;
     }
@@ -326,7 +335,7 @@ StoreEntry::storeClientType() const
 
     if (EBIT_TEST(flags, ENTRY_ABORTED)) {
         /* I don't think we should be adding clients to aborted entries */
-        debugs(20, 1, "storeClientType: adding to ENTRY_ABORTED entry");
+        debugs(20, DBG_IMPORTANT, "storeClientType: adding to ENTRY_ABORTED entry");
         return STORE_MEM_CLIENT;
     }
 
@@ -371,32 +380,47 @@ StoreEntry::storeClientType() const
     return STORE_DISK_CLIENT;
 }
 
-StoreEntry::StoreEntry():
+StoreEntry::StoreEntry() :
+        mem_obj(NULL),
         hidden_mem_obj(NULL),
-        swap_file_sz(0)
+        timestamp(-1),
+        lastref(-1),
+        expires(-1),
+        lastmod(-1),
+        swap_file_sz(0),
+        refcount(0),
+        flags(0),
+        swap_filen(-1),
+        swap_dirn(-1),
+        lock_count(0),
+        mem_status(NOT_IN_MEMORY),
+        ping_status(PING_NONE),
+        store_status(STORE_PENDING),
+        swap_status(SWAPOUT_NONE)
 {
     debugs(20, 3, HERE << "new StoreEntry " << this);
-    mem_obj = NULL;
-
-    expires = lastmod = lastref = timestamp = -1;
-
-    swap_status = SWAPOUT_NONE;
-    swap_filen = -1;
-    swap_dirn = -1;
 }
 
-StoreEntry::StoreEntry(const char *aUrl, const char *aLogUrl):
+StoreEntry::StoreEntry(const char *aUrl, const char *aLogUrl) :
+        mem_obj(NULL),
         hidden_mem_obj(NULL),
-        swap_file_sz(0)
+        timestamp(-1),
+        lastref(-1),
+        expires(-1),
+        lastmod(-1),
+        swap_file_sz(0),
+        refcount(0),
+        flags(0),
+        swap_filen(-1),
+        swap_dirn(-1),
+        lock_count(0),
+        mem_status(NOT_IN_MEMORY),
+        ping_status(PING_NONE),
+        store_status(STORE_PENDING),
+        swap_status(SWAPOUT_NONE)
 {
     debugs(20, 3, HERE << "new StoreEntry " << this);
     mem_obj = new MemObject(aUrl, aLogUrl);
-
-    expires = lastmod = lastref = timestamp = -1;
-
-    swap_status = SWAPOUT_NONE;
-    swap_filen = -1;
-    swap_dirn = -1;
 }
 
 StoreEntry::~StoreEntry()
@@ -408,6 +432,27 @@ StoreEntry::~StoreEntry()
     delete hidden_mem_obj;
 }
 
+#if USE_ADAPTATION
+void
+StoreEntry::deferProducer(const AsyncCall::Pointer &producer)
+{
+    if (!deferredProducer)
+        deferredProducer = producer;
+    else
+        debugs(20, 5, HERE << "Deferred producer call is allready set to: " <<
+               *deferredProducer << ", requested call: " << *producer);
+}
+
+void
+StoreEntry::kickProducer()
+{
+    if (deferredProducer != NULL) {
+        ScheduleCallHere(deferredProducer);
+        deferredProducer = NULL;
+    }
+}
+#endif
+
 void
 StoreEntry::destroyMemObject()
 {
@@ -469,7 +514,6 @@ StoreEntry::hashDelete()
 
 /* -------------------------------------------------------------------------- */
 
-
 /* get rid of memory copy of the object */
 void
 StoreEntry::purgeMem()
@@ -496,7 +540,7 @@ void
 
 StoreEntry::lock()
 {
-    lock_count++;
+    ++lock_count;
     debugs(20, 3, "StoreEntry::lock: key '" << getMD5Text() <<"' count=" <<
            lock_count  );
     lastref = squid_curtime;
@@ -537,7 +581,7 @@ StoreEntry::releaseRequest()
 int
 StoreEntry::unlock()
 {
-    lock_count--;
+    --lock_count;
     debugs(20, 3, "StoreEntry::unlock: key '" << getMD5Text() << "' count=" << lock_count);
 
     if (lock_count)
@@ -548,14 +592,13 @@ StoreEntry::unlock()
 
     assert(storePendingNClients(this) == 0);
 
-    if (EBIT_TEST(flags, RELEASE_REQUEST))
-    {
+    if (EBIT_TEST(flags, RELEASE_REQUEST)) {
         this->release();
         return 0;
     }
 
     if (EBIT_TEST(flags, KEY_PRIVATE))
-        debugs(20, 1, "WARNING: " << __FILE__ << ":" << __LINE__ << ": found KEY_PRIVATE");
+        debugs(20, DBG_IMPORTANT, "WARNING: " << __FILE__ << ":" << __LINE__ << ": found KEY_PRIVATE");
 
     Store::Root().handleIdleEntry(*this); // may delete us
     return 0;
@@ -614,9 +657,9 @@ storeGetPublicByRequest(HttpRequest * req)
 {
     StoreEntry *e = storeGetPublicByRequestMethod(req, req->method);
 
-    if (e == NULL && req->method == METHOD_HEAD)
+    if (e == NULL && req->method == Http::METHOD_HEAD)
         /* We can generate a HEAD reply from a cached GET object */
-        e = storeGetPublicByRequestMethod(req, METHOD_GET);
+        e = storeGetPublicByRequestMethod(req, Http::METHOD_GET);
 
     return e;
 }
@@ -660,7 +703,7 @@ StoreEntry::setPrivateKey()
         mem_obj->id = getKeyCounter();
         newkey = storeKeyPrivate(mem_obj->url, mem_obj->method, mem_obj->id);
     } else {
-        newkey = storeKeyPrivate("JUNK", METHOD_NONE, getKeyCounter());
+        newkey = storeKeyPrivate("JUNK", Http::METHOD_NONE, getKeyCounter());
     }
 
     assert(hash_lookup(store_table, newkey) == NULL);
@@ -692,7 +735,7 @@ StoreEntry::setPublicKey()
 #if MORE_DEBUG_OUTPUT
 
     if (EBIT_TEST(flags, RELEASE_REQUEST))
-        debugs(20, 1, "assertion failed: RELEASE key " << key << ", url " << mem_obj->url);
+        debugs(20, DBG_IMPORTANT, "assertion failed: RELEASE key " << key << ", url " << mem_obj->url);
 
 #endif
 
@@ -733,7 +776,7 @@ StoreEntry::setPublicKey()
             StoreEntry *pe = storeCreateEntry(mem_obj->url, mem_obj->log_url, request->flags, request->method);
             /* We are allowed to do this typecast */
             HttpReply *rep = new HttpReply;
-            rep->setHeaders(HTTP_OK, "Internal marker object", "x-squid-internal/vary", -1, -1, squid_curtime + 100000);
+            rep->setHeaders(Http::scOkay, "Internal marker object", "x-squid-internal/vary", -1, -1, squid_curtime + 100000);
             vary = mem_obj->getReply()->header.getList(HDR_VARY);
 
             if (vary.size()) {
@@ -790,7 +833,7 @@ StoreEntry::setPublicKey()
 }
 
 StoreEntry *
-storeCreateEntry(const char *url, const char *log_url, request_flags flags, const HttpRequestMethod& method)
+storeCreateEntry(const char *url, const char *log_url, const RequestFlags &flags, const HttpRequestMethod& method)
 {
     StoreEntry *e = NULL;
     MemObject *mem = NULL;
@@ -855,20 +898,6 @@ StoreEntry::write (StoreIOBuffer writeBuffer)
     PROF_start(StoreEntry_write);
     assert(store_status == STORE_PENDING);
 
-    if (!writeBuffer.length) {
-        /* the headers are received already, but we have not received
-         * any body data. There are BROKEN abuses of HTTP which require
-         * the headers to be passed along before any body data - see
-         * http://developer.apple.com/documentation/QuickTime/QTSS/Concepts/chapter_2_section_14.html
-         * for an example of such bad behaviour. To accomodate this, if
-         * we have a empty write arrive, we flush to our clients.
-         * -RBC 20060903
-         */
-        PROF_stop(StoreEntry_write);
-        invokeHandlers();
-        return;
-    }
-
     debugs(20, 5, "storeWrite: writing " << writeBuffer.length << " bytes for '" << getMD5Text() << "'");
     PROF_stop(StoreEntry_write);
     storeGetMemSpace(writeBuffer.length);
@@ -894,7 +923,6 @@ StoreEntry::append(char const *buf, int len)
     write(tempBuffer);
 }
 
-
 void
 storeAppendPrintf(StoreEntry * e, const char *fmt,...)
 {
@@ -969,36 +997,32 @@ StoreEntry::checkCachable()
 {
 #if CACHE_ALL_METHODS
 
-    if (mem_obj->method != METHOD_GET) {
+    if (mem_obj->method != Http::METHOD_GET) {
         debugs(20, 2, "StoreEntry::checkCachable: NO: non-GET method");
-        store_check_cachable_hist.no.non_get++;
+        ++store_check_cachable_hist.no.non_get;
     } else
 #endif
         if (store_status == STORE_OK && EBIT_TEST(flags, ENTRY_BAD_LENGTH)) {
             debugs(20, 2, "StoreEntry::checkCachable: NO: wrong content-length");
-            store_check_cachable_hist.no.wrong_content_length++;
+            ++store_check_cachable_hist.no.wrong_content_length;
         } else if (!EBIT_TEST(flags, ENTRY_CACHABLE)) {
             debugs(20, 2, "StoreEntry::checkCachable: NO: not cachable");
-            store_check_cachable_hist.no.not_entry_cachable++;
+            ++store_check_cachable_hist.no.not_entry_cachable;
         } else if (EBIT_TEST(flags, ENTRY_NEGCACHED)) {
             debugs(20, 3, "StoreEntry::checkCachable: NO: negative cached");
-            store_check_cachable_hist.no.negative_cached++;
+            ++store_check_cachable_hist.no.negative_cached;
             return 0;           /* avoid release call below */
         } else if ((getReply()->content_length > 0 &&
-                    getReply()->content_length
-                    > Config.Store.maxObjectSize) ||
-                   mem_obj->endOffset() > Config.Store.maxObjectSize) {
-            debugs(20, 2, "StoreEntry::checkCachable: NO: too big");
-            store_check_cachable_hist.no.too_big++;
-        } else if (getReply()->content_length > Config.Store.maxObjectSize) {
+                    getReply()->content_length > store_maxobjsize) ||
+                   mem_obj->endOffset() > store_maxobjsize) {
             debugs(20, 2, "StoreEntry::checkCachable: NO: too big");
-            store_check_cachable_hist.no.too_big++;
+            ++store_check_cachable_hist.no.too_big;
         } else if (checkTooSmall()) {
             debugs(20, 2, "StoreEntry::checkCachable: NO: too small");
-            store_check_cachable_hist.no.too_small++;
+            ++store_check_cachable_hist.no.too_small;
         } else if (EBIT_TEST(flags, KEY_PRIVATE)) {
             debugs(20, 3, "StoreEntry::checkCachable: NO: private key");
-            store_check_cachable_hist.no.private_key++;
+            ++store_check_cachable_hist.no.private_key;
         } else if (swap_status != SWAPOUT_NONE) {
             /*
              * here we checked the swap_status because the remaining
@@ -1008,12 +1032,12 @@ StoreEntry::checkCachable()
             return 1;
         } else if (storeTooManyDiskFilesOpen()) {
             debugs(20, 2, "StoreEntry::checkCachable: NO: too many disk files open");
-            store_check_cachable_hist.no.too_many_open_files++;
+            ++store_check_cachable_hist.no.too_many_open_files;
         } else if (fdNFree() < RESERVED_FD) {
             debugs(20, 2, "StoreEntry::checkCachable: NO: too many FD's open");
-            store_check_cachable_hist.no.too_many_open_fds++;
+            ++store_check_cachable_hist.no.too_many_open_fds;
         } else {
-            store_check_cachable_hist.yes.Default++;
+            ++store_check_cachable_hist.yes.Default;
             return 1;
         }
 
@@ -1104,7 +1128,7 @@ StoreEntry::complete()
 void
 StoreEntry::abort()
 {
-    statCounter.aborted_requests++;
+    ++statCounter.aborted_requests;
     assert(store_status == STORE_PENDING);
     assert(mem_obj != NULL);
     debugs(20, 6, "storeAbort: " << getMD5Text());
@@ -1128,7 +1152,7 @@ StoreEntry::abort()
      */
     if (mem_obj->abort.callback) {
         if (!cbdataReferenceValid(mem_obj->abort.data))
-            debugs(20,1,HERE << "queueing event when abort.data is not valid");
+            debugs(20, DBG_IMPORTANT,HERE << "queueing event when abort.data is not valid");
         eventAdd("mem_obj->abort.callback",
                  mem_obj->abort.callback,
                  mem_obj->abort.data,
@@ -1169,7 +1193,7 @@ storeGetMemSpace(int size)
 
     last_check = squid_curtime;
 
-    pages_needed = (size / SM_PAGE_SIZE) + 1;
+    pages_needed = (size + SM_PAGE_SIZE-1) / SM_PAGE_SIZE;
 
     if (mem_node::InUseCount() + pages_needed < store_pages_max) {
         PROF_stop(storeGetMemSpace);
@@ -1184,7 +1208,7 @@ storeGetMemSpace(int size)
 
     while ((e = walker->Next(walker))) {
         e->purgeMem();
-        released++;
+        ++released;
 
         if (mem_node::InUseCount() + pages_needed < store_pages_max)
             break;
@@ -1197,7 +1221,6 @@ storeGetMemSpace(int size)
     PROF_stop(storeGetMemSpace);
 }
 
-
 /* thunk through to Store::Root().maintain(). Note that this would be better still
  * if registered against the root store itself, but that requires more complex
  * update logic - bigger fish to fry first. Long term each store when
@@ -1235,7 +1258,7 @@ StoreController::maintain()
 
     if (Store::Root().currentSize() > Store::Root().maxSize()) {
         if (squid_curtime - last_warn_time > 10) {
-            debugs(20, 0, "WARNING: Disk space over limit: "
+            debugs(20, DBG_CRITICAL, "WARNING: Disk space over limit: "
                    << Store::Root().currentSize() / 1024.0 << " KB > "
                    << (Store::Root().maxSize() >> 10) << " KB");
             last_warn_time = squid_curtime;
@@ -1273,7 +1296,7 @@ StoreEntry::release()
              * Fake a call to StoreEntry->lock()  When rebuilding is done,
              * we'll just call StoreEntry->unlock() on these.
              */
-            lock_count++;
+            ++lock_count;
             setReleaseFlag();
             LateReleaseStack.push_back(this);
         } else {
@@ -1312,17 +1335,17 @@ storeLateRelease(void *unused)
         return;
     }
 
-    for (i = 0; i < 10; i++) {
+    for (i = 0; i < 10; ++i) {
         e = LateReleaseStack.count ? LateReleaseStack.pop() : NULL;
 
         if (e == NULL) {
             /* done! */
-            debugs(20, 1, "storeLateRelease: released " << n << " objects");
+            debugs(20, DBG_IMPORTANT, "storeLateRelease: released " << n << " objects");
             return;
         }
 
         e->unlock();
-        n++;
+        ++n;
     }
 
     eventAdd("storeLateRelease", storeLateRelease, NULL, 0.0, 1);
@@ -1374,15 +1397,15 @@ StoreEntry::validLength() const
         return 1;
     }
 
-    if (mem_obj->method == METHOD_HEAD) {
+    if (mem_obj->method == Http::METHOD_HEAD) {
         debugs(20, 5, "storeEntryValidLength: HEAD request: " << getMD5Text());
         return 1;
     }
 
-    if (reply->sline.status == HTTP_NOT_MODIFIED)
+    if (reply->sline.status() == Http::scNotModified)
         return 1;
 
-    if (reply->sline.status == HTTP_NO_CONTENT)
+    if (reply->sline.status() == Http::scNoContent)
         return 1;
 
     diff = reply->hdr_sz + reply->content_length - objectLen();
@@ -1443,14 +1466,6 @@ StoreEntry::memoryCachable() const
     if (!Config.onoff.memory_cache_first && swap_status == SWAPOUT_DONE && refcount == 1)
         return 0;
 
-    if (UsingSmp()) {
-        const int64_t expectedSize = mem_obj->expectedReplySize();
-        // objects of unknown size are not allowed into memory cache, for now
-        if (expectedSize < 0 ||
-            expectedSize > static_cast<int64_t>(Config.Store.maxInMemObjSize))
-            return 0;
-    }
-
     return 1;
 }
 
@@ -1478,7 +1493,9 @@ StoreEntry::checkNegativeHit() const
 void
 StoreEntry::negativeCache()
 {
-    if (expires == 0)
+    // XXX: should make the default for expires 0 instead of -1
+    //      so we can distinguish "Expires: -1" from nothing.
+    if (expires <= 0)
 #if USE_HTTP_VIOLATIONS
         expires = squid_curtime + Config.negativeTtl;
 #else
@@ -1538,6 +1555,14 @@ StoreEntry::timestampsSet()
     if (served_date < 0 || served_date > squid_curtime)
         served_date = squid_curtime;
 
+    /* Bug 1791:
+     * If the returned Date: is more than 24 hours older than
+     * the squid_curtime, then one of us needs to use NTP to set our
+     * clock.  We'll pretend that our clock is right.
+     */
+    else if (served_date < (squid_curtime - 24 * 60 * 60) )
+        served_date = squid_curtime;
+
     /*
      * Compensate with Age header if origin server clock is ahead
      * of us and there is a cache in between us and the origin
@@ -1616,8 +1641,10 @@ StoreEntry::setMemStatus(mem_status_t new_status)
     if (new_status == mem_status)
         return;
 
-    if (UsingSmp()) {
-        assert(new_status != IN_MEMORY); // we do not call this otherwise
+    // are we using a shared memory cache?
+    if (Config.memShared && IamWorkerProcess()) {
+        // enumerate calling cases if shared memory is enabled
+        assert(new_status != IN_MEMORY || EBIT_TEST(flags, ENTRY_SPECIAL));
         // This method was designed to update replacement policy, not to
         // actually purge something from the memory cache (TODO: rename?).
         // Shared memory cache does not have a policy that needs updates.
@@ -1637,7 +1664,7 @@ StoreEntry::setMemStatus(mem_status_t new_status)
             debugs(20, 4, "StoreEntry::setMemStatus: inserted mem node " << mem_obj->url << " key: " << getMD5Text());
         }
 
-        hot_obj_count++; // TODO: maintain for the shared hot cache as well
+        ++hot_obj_count; // TODO: maintain for the shared hot cache as well
     } else {
         if (EBIT_TEST(flags, ENTRY_SPECIAL)) {
             debugs(20, 4, "StoreEntry::setMemStatus: special entry " << mem_obj->url);
@@ -1646,7 +1673,7 @@ StoreEntry::setMemStatus(mem_status_t new_status)
             debugs(20, 4, "StoreEntry::setMemStatus: removed mem node " << mem_obj->url);
         }
 
-        hot_obj_count--;
+        --hot_obj_count;
     }
 
     mem_status = new_status;
@@ -1666,6 +1693,8 @@ StoreEntry::url() const
 void
 StoreEntry::createMemObject(const char *aUrl, const char *aLogUrl)
 {
+    debugs(20, 3, "A mem_obj create attempted using : " << aUrl);
+
     if (mem_obj)
         return;
 
@@ -1754,9 +1783,9 @@ storeReplAdd(const char *type, REMOVALPOLICYCREATE * create)
     int i;
 
     /* find the number of currently known repl types */
-    for (i = 0; storerepl_list && storerepl_list[i].typestr; i++) {
+    for (i = 0; storerepl_list && storerepl_list[i].typestr; ++i) {
         if (strcmp(storerepl_list[i].typestr, type) == 0) {
-            debugs(20, 1, "WARNING: Trying to load store replacement policy " << type << " twice.");
+            debugs(20, DBG_IMPORTANT, "WARNING: Trying to load store replacement policy " << type << " twice.");
             return;
         }
     }
@@ -1779,14 +1808,14 @@ createRemovalPolicy(RemovalPolicySettings * settings)
 {
     storerepl_entry_t *r;
 
-    for (r = storerepl_list; r && r->typestr; r++) {
+    for (r = storerepl_list; r && r->typestr; ++r) {
         if (strcmp(r->typestr, settings->type) == 0)
             return r->create(settings->args);
     }
 
-    debugs(20, 1, "ERROR: Unknown policy " << settings->type);
-    debugs(20, 1, "ERROR: Be sure to have set cache_replacement_policy");
-    debugs(20, 1, "ERROR:   and memory_replacement_policy in squid.conf!");
+    debugs(20, DBG_IMPORTANT, "ERROR: Unknown policy " << settings->type);
+    debugs(20, DBG_IMPORTANT, "ERROR: Be sure to have set cache_replacement_policy");
+    debugs(20, DBG_IMPORTANT, "ERROR:   and memory_replacement_policy in squid.conf!");
     fatalf("ERROR: Unknown policy %s\n", settings->type);
     return NULL;                /* NOTREACHED */
 }
@@ -1812,7 +1841,6 @@ storeSwapFileNumberSet(StoreEntry * e, sfileno filn)
 
 #endif
 
-
 /*
  * Replace a store entry with
  * a new reply. This eats the reply.
@@ -1823,7 +1851,7 @@ StoreEntry::replaceHttpReply(HttpReply *rep, bool andStartWriting)
     debugs(20, 3, "StoreEntry::replaceHttpReply: " << url());
 
     if (!mem_obj) {
-        debugs(20, 0, "Attempt to replace object with no in-memory representation");
+        debugs(20, DBG_CRITICAL, "Attempt to replace object with no in-memory representation");
         return;
     }
 
@@ -1833,7 +1861,6 @@ StoreEntry::replaceHttpReply(HttpReply *rep, bool andStartWriting)
         startWriting();
 }
 
-
 void
 StoreEntry::startWriting()
 {
@@ -1846,19 +1873,18 @@ StoreEntry::startWriting()
 
     assert (isEmpty());
     assert(mem_obj);
-    
+
     const HttpReply *rep = getReply();
     assert(rep);
 
     rep->packHeadersInto(&p);
     mem_obj->markEndOfReplyHeaders();
 
-    httpBodyPackInto(&rep->body, &p);
+    rep->body.packInto(&p);
 
     packerClean(&p);
 }
 
-
 char const *
 StoreEntry::getSerialisedMetaData()
 {
@@ -1871,93 +1897,8 @@ StoreEntry::getSerialisedMetaData()
     return result;
 }
 
-bool
-StoreEntry::swapoutPossible()
-{
-    if (!Config.cacheSwap.n_configured)
-        return false;
-
-    /* should we swap something out to disk? */
-    debugs(20, 7, "storeSwapOut: " << url());
-    debugs(20, 7, "storeSwapOut: store_status = " << storeStatusStr[store_status]);
-
-    assert(mem_obj);
-    MemObject::SwapOut::Decision &decision = mem_obj->swapout.decision;
-
-    // if we decided that swapout is not possible, do not repeat same checks
-    if (decision == MemObject::SwapOut::swImpossible) {
-        debugs(20, 3, "storeSwapOut: already rejected");
-        return false;
-    }
-
-    // this flag may change so we must check it even if we already said "yes"
-    if (EBIT_TEST(flags, ENTRY_ABORTED)) {
-        assert(EBIT_TEST(flags, RELEASE_REQUEST));
-        // StoreEntry::abort() already closed the swap out file, if any
-        decision = MemObject::SwapOut::swImpossible;
-        return false;
-    }
-
-    // if we decided that swapout is possible, do not repeat same checks
-    if (decision == MemObject::SwapOut::swPossible) {
-        debugs(20, 3, "storeSwapOut: already allowed");
-        return true;
-    }
-
-    // if we are swapping out already, do not repeat same checks
-    if (swap_status != SWAPOUT_NONE) {
-        debugs(20, 3, "storeSwapOut: already started");
-        decision = MemObject::SwapOut::swPossible;
-        return true;
-    }
-
-    if (!checkCachable()) {
-        debugs(20, 3, "storeSwapOut: not cachable");
-        decision = MemObject::SwapOut::swImpossible;
-        return false;
-    }
-
-    if (EBIT_TEST(flags, ENTRY_SPECIAL)) {
-        debugs(20, 3, "storeSwapOut: " << url() << " SPECIAL");
-        decision = MemObject::SwapOut::swImpossible;
-        return false;
-    }
-
-    // check cache_dir max-size limit if all cache_dirs have it
-    if (store_maxobjsize >= 0) {
-        // TODO: add estimated store metadata size to be conservative
-
-        // use guaranteed maximum if it is known
-        const int64_t expectedEnd = mem_obj->expectedReplySize();
-        debugs(20, 7, "storeSwapOut: expectedEnd = " << expectedEnd);
-        if (expectedEnd > store_maxobjsize) {
-            debugs(20, 3, "storeSwapOut: will not fit: " << expectedEnd <<
-                " > " << store_maxobjsize);
-            decision = MemObject::SwapOut::swImpossible;
-            return false; // known to outgrow the limit eventually
-        }
-        if (expectedEnd < 0) {
-            debugs(20, 3, "storeSwapOut: wait for more info: " <<
-                store_maxobjsize);
-            return false; // may fit later, but will be rejected now
-        }
-
-        // use current minimum (always known)
-        const int64_t currentEnd = mem_obj->endOffset();
-        if (currentEnd > store_maxobjsize) {
-            debugs(20, 3, "storeSwapOut: does not fit: " << currentEnd <<
-                " > " << store_maxobjsize);
-            decision = MemObject::SwapOut::swImpossible;
-            return false; // already does not fit and may only get bigger
-        }
-    }
-
-    decision = MemObject::SwapOut::swPossible;
-    return true;
-}
-
 void
-StoreEntry::trimMemory()
+StoreEntry::trimMemory(const bool preserveSwappable)
 {
     /*
      * DPW 2007-05-09
@@ -1967,7 +1908,10 @@ StoreEntry::trimMemory()
     if (mem_status == IN_MEMORY)
         return;
 
-    if (!swapOutAble()) {
+    if (EBIT_TEST(flags, ENTRY_SPECIAL))
+        return; // cannot trim because we do not load them again
+
+    if (!preserveSwappable) {
         if (mem_obj->policyLowestOffsetToKeep(0) == 0) {
             /* Nothing to do */
             return;
@@ -2024,6 +1968,17 @@ StoreEntry::modifiedSince(HttpRequest * request) const
     }
 }
 
+bool
+StoreEntry::hasEtag(ETag &etag) const
+{
+    if (const HttpReply *reply = getReply()) {
+        etag = reply->header.getETag(HDR_ETAG);
+        if (etag.str)
+            return true;
+    }
+    return false;
+}
+
 bool
 StoreEntry::hasIfMatchEtag(const HttpRequest &request) const
 {
@@ -2036,8 +1991,8 @@ StoreEntry::hasIfNoneMatchEtag(const HttpRequest &request) const
 {
     const String reqETags = request.header.getList(HDR_IF_NONE_MATCH);
     // weak comparison is allowed only for HEAD or full-body GET requests
-    const bool allowWeakMatch = !request.flags.range &&
-                                (request.method == METHOD_GET || request.method == METHOD_HEAD);
+    const bool allowWeakMatch = !request.flags.isRanged &&
+                                (request.method == Http::METHOD_GET || request.method == Http::METHOD_HEAD);
     return hasOneOfEtags(reqETags, allowWeakMatch);
 }
 
@@ -2104,8 +2059,8 @@ StoreEntry::isAccepting() const
 std::ostream &operator <<(std::ostream &os, const StoreEntry &e)
 {
     return os << e.swap_filen << '@' << e.swap_dirn << '=' <<
-        e.mem_status << '/' << e.ping_status << '/' << e.store_status << '/' <<
-        e.swap_status;
+           e.mem_status << '/' << e.ping_status << '/' << e.store_status << '/' <<
+           e.swap_status;
 }
 
 /* NullStoreEntry */