]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/MemObject.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / MemObject.cc
index 2966c1a10ad7449d4ff4935cba94db1d2ed4a911..61a7a26b7727f38ca58b13cb4646ec68bb2680c8 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: MemObject.cc,v 1.33 2008/01/20 08:54:28 amosjeffries Exp $
+ * $Id$
  *
  * DEBUG: section 19    Store Memory Primitives
  * AUTHOR: Robert Collins
  *  it under the terms of the GNU General Public License as published by
  *  the Free Software Foundation; either version 2 of the License, or
  *  (at your option) any later version.
- *  
+ *
  *  This program is distributed in the hope that it will be useful,
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
- *  
+ *
  *  You should have received a copy of the GNU General Public License
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
  */
 
 #include "squid.h"
-#include "MemObject.h"
-#include "HttpRequest.h"
+#include "comm/Connection.h"
+#include "Generic.h"
 #include "HttpReply.h"
+#include "HttpRequest.h"
+#include "MemBuf.h"
+#include "MemObject.h"
+#include "profiler/Profiler.h"
 #include "Store.h"
 #include "StoreClient.h"
-#include "Generic.h"
-#if DELAY_POOLS
+#include "protos.h"
+
+#if USE_DELAY_POOLS
 #include "DelayPools.h"
 #endif
-#include "MemBuf.h"
 
 /* TODO: make this global or private */
 #if URL_CHECKSUM_DEBUG
@@ -57,7 +61,7 @@ url_checksum(const char *url)
     SquidMD5Init(&M);
     SquidMD5Update(&M, (unsigned char *) url, strlen(url));
     SquidMD5Final(digest, &M);
-    xmemcpy(&ck, digest, sizeof(ck));
+    memcpy(&ck, digest, sizeof(ck));
     return ck;
 }
 
@@ -71,6 +75,15 @@ MemObject::inUseCount()
     return Pool().inUseCount();
 }
 
+void
+MemObject::resetUrls(char const *aUrl, char const *aLog_url)
+{
+    safe_free(url);
+    safe_free(log_url);    /* XXX account log_url */
+    log_url = xstrdup(aLog_url);
+    url = xstrdup(aUrl);
+}
+
 MemObject::MemObject(char const *aUrl, char const *aLog_url)
 {
     debugs(20, 3, HERE << "new MemObject " << this);
@@ -90,6 +103,8 @@ MemObject::MemObject(char const *aUrl, char const *aLog_url)
     object_sz = -1;
 
     /* XXX account log_url */
+
+    swapout.decision = SwapOut::swNeedsCheck;
 }
 
 MemObject::~MemObject()
@@ -144,7 +159,7 @@ MemObject::write ( StoreIOBuffer writeBuffer, STMCB *callback, void *callbackDat
     writeBuffer.offset += (_reply ? _reply->hdr_sz : 0);
 
     /* We don't separate out mime headers yet, so ensure that the first
-     * write is at offset 0 - where they start 
+     * write is at offset 0 - where they start
      */
     assert (data_hdr.endOffset() || writeBuffer.offset == 0);
 
@@ -159,16 +174,16 @@ MemObject::dump() const
     data_hdr.dump();
 #if 0
     /* do we want this one? */
-    debugs(20, 1, "MemObject->data.origin_offset: " << (data_hdr.head ? data_hdr.head->nodeBuffer.offset : 0));
+    debugs(20, DBG_IMPORTANT, "MemObject->data.origin_offset: " << (data_hdr.head ? data_hdr.head->nodeBuffer.offset : 0));
 #endif
 
-    debugs(20, 1, "MemObject->start_ping: " << start_ping.tv_sec  << "."<< std::setfill('0') << std::setw(6) << start_ping.tv_usec);
-    debugs(20, 1, "MemObject->inmem_hi: " << data_hdr.endOffset());
-    debugs(20, 1, "MemObject->inmem_lo: " << inmem_lo);
-    debugs(20, 1, "MemObject->nclients: " << nclients);
-    debugs(20, 1, "MemObject->reply: " << _reply);
-    debugs(20, 1, "MemObject->request: " << request);
-    debugs(20, 1, "MemObject->log_url: " << log_url << " " << checkNullString(log_url));
+    debugs(20, DBG_IMPORTANT, "MemObject->start_ping: " << start_ping.tv_sec  << "."<< std::setfill('0') << std::setw(6) << start_ping.tv_usec);
+    debugs(20, DBG_IMPORTANT, "MemObject->inmem_hi: " << data_hdr.endOffset());
+    debugs(20, DBG_IMPORTANT, "MemObject->inmem_lo: " << inmem_lo);
+    debugs(20, DBG_IMPORTANT, "MemObject->nclients: " << nclients);
+    debugs(20, DBG_IMPORTANT, "MemObject->reply: " << _reply);
+    debugs(20, DBG_IMPORTANT, "MemObject->request: " << request);
+    debugs(20, DBG_IMPORTANT, "MemObject->log_url: " << log_url << " " << checkNullString(log_url));
 }
 
 HttpReply const *
@@ -184,12 +199,10 @@ MemObject::replaceHttpReply(HttpReply *newrep)
     _reply = HTTPMSGLOCK(newrep);
 }
 
-struct LowestMemReader : public unary_function<store_client, void>
-{
-    LowestMemReader(int64_t seed):current(seed){}
+struct LowestMemReader : public unary_function<store_client, void> {
+    LowestMemReader(int64_t seed):current(seed) {}
 
-    void operator() (store_client const &x)
-    {
+    void operator() (store_client const &x) {
         if (x.memReaderHasLowerOffset(current))
             current = x.copyInto.offset;
     }
@@ -197,13 +210,12 @@ struct LowestMemReader : public unary_function<store_client, void>
     int64_t current;
 };
 
-struct StoreClientStats : public unary_function<store_client, void>
-{
-    StoreClientStats(MemBuf *anEntry):where(anEntry),index(0){}
+struct StoreClientStats : public unary_function<store_client, void> {
+    StoreClientStats(MemBuf *anEntry):where(anEntry),index(0) {}
 
-    void operator()(store_client const &x)
-    {
-        x.dumpStats(where, index++);
+    void operator()(store_client const &x) {
+        x.dumpStats(where, index);
+        ++index;
     }
 
     MemBuf *where;
@@ -211,17 +223,19 @@ struct StoreClientStats : public unary_function<store_client, void>
 };
 
 void
-MemObject::stat (MemBuf * mb) const
+MemObject::stat(MemBuf * mb) const
 {
     mb->Printf("\t%s %s\n",
                RequestMethodStr(method), log_url);
-    mb->Printf("\tinmem_lo: %"PRId64"\n", inmem_lo);
-    mb->Printf("\tinmem_hi: %"PRId64"\n", data_hdr.endOffset());
-    mb->Printf("\tswapout: %"PRId64" bytes queued\n",
+    if (vary_headers)
+        mb->Printf("\tvary_headers: %s\n", vary_headers);
+    mb->Printf("\tinmem_lo: %" PRId64 "\n", inmem_lo);
+    mb->Printf("\tinmem_hi: %" PRId64 "\n", data_hdr.endOffset());
+    mb->Printf("\tswapout: %" PRId64 " bytes queued\n",
                swapout.queue_offset);
 
     if (swapout.sio.getRaw())
-        mb->Printf("\tswapout: %"PRId64" bytes written\n",
+        mb->Printf("\tswapout: %" PRId64 " bytes written\n",
                    (int64_t) swapout.sio->offset());
 
     StoreClientStats statsVisitor(mb);
@@ -235,6 +249,15 @@ MemObject::endOffset () const
     return data_hdr.endOffset();
 }
 
+void
+MemObject::markEndOfReplyHeaders()
+{
+    const int hdr_sz = endOffset();
+    assert(hdr_sz >= 0);
+    assert(_reply);
+    _reply->hdr_sz = hdr_sz;
+}
+
 int64_t
 MemObject::size() const
 {
@@ -244,6 +267,23 @@ MemObject::size() const
     return object_sz;
 }
 
+int64_t
+MemObject::expectedReplySize() const
+{
+    debugs(20, 7, HERE << "object_sz: " << object_sz);
+    if (object_sz >= 0) // complete() has been called; we know the exact answer
+        return object_sz;
+
+    if (_reply) {
+        const int64_t clen = _reply->bodySize(method);
+        debugs(20, 7, HERE << "clen: " << clen);
+        if (clen >= 0 && _reply->hdr_sz > 0) // yuck: HttpMsg sets hdr_sz to 0
+            return clen + _reply->hdr_sz;
+    }
+
+    return -1; // not enough information to predict
+}
+
 void
 MemObject::reset()
 {
@@ -253,7 +293,6 @@ MemObject::reset()
     /* Should we check for clients? */
 }
 
-
 int64_t
 MemObject::lowestMemReaderOffset() const
 {
@@ -296,7 +335,7 @@ MemObject::objectBytesOnDisk() const
     /*
      * NOTE: storeOffset() represents the disk file size,
      * not the amount of object data on disk.
-     * 
+     *
      * If we don't have at least 'swap_hdr_sz' bytes
      * then none of the object data is on disk.
      *
@@ -317,7 +356,7 @@ MemObject::objectBytesOnDisk() const
 }
 
 int64_t
-MemObject::policyLowestOffsetToKeep() const
+MemObject::policyLowestOffsetToKeep(bool swap) const
 {
     /*
      * Careful.  lowest_offset can be greater than endOffset(), such
@@ -326,7 +365,8 @@ MemObject::policyLowestOffsetToKeep() const
     int64_t lowest_offset = lowestMemReaderOffset();
 
     if (endOffset() < lowest_offset ||
-            endOffset() - inmem_lo > (int64_t)Config.Store.maxInMemObjSize)
+            endOffset() - inmem_lo > (int64_t)Config.Store.maxInMemObjSize ||
+            (swap && !Config.onoff.memory_cache_first))
         return lowest_offset;
 
     return inmem_lo;
@@ -335,14 +375,14 @@ MemObject::policyLowestOffsetToKeep() const
 void
 MemObject::trimSwappable()
 {
-    int64_t new_mem_lo = policyLowestOffsetToKeep();
+    int64_t new_mem_lo = policyLowestOffsetToKeep(1);
     /*
      * We should only free up to what we know has been written
      * to disk, not what has been queued for writing.  Otherwise
      * there will be a chunk of the data which is not in memory
      * and is not yet on disk.
      * The -1 makes sure the page isn't freed until storeSwapOut has
-     * walked to the next page. (mem->swapout.memnode)
+     * walked to the next page.
      */
     int64_t on_disk;
 
@@ -360,14 +400,13 @@ MemObject::trimSwappable()
 void
 MemObject::trimUnSwappable()
 {
-    int64_t new_mem_lo = policyLowestOffsetToKeep();
+    int64_t new_mem_lo = policyLowestOffsetToKeep(0);
     assert (new_mem_lo > 0);
 
     data_hdr.freeDataUpto(new_mem_lo);
     inmem_lo = new_mem_lo;
 }
 
-
 bool
 MemObject::isContiguous() const
 {
@@ -378,22 +417,23 @@ MemObject::isContiguous() const
 }
 
 int
-MemObject::mostBytesWanted(int max) const
+MemObject::mostBytesWanted(int max, bool ignoreDelayPools) const
 {
-#if DELAY_POOLS
-    /* identify delay id with largest allowance */
-    DelayId largestAllowance = mostBytesAllowed ();
-    return largestAllowance.bytesWanted(0, max);
-#else
+#if USE_DELAY_POOLS
+    if (!ignoreDelayPools) {
+        /* identify delay id with largest allowance */
+        DelayId largestAllowance = mostBytesAllowed ();
+        return largestAllowance.bytesWanted(0, max);
+    }
+#endif
 
     return max;
-#endif
 }
 
 void
 MemObject::setNoDelay(bool const newValue)
 {
-#if DELAY_POOLS
+#if USE_DELAY_POOLS
 
     for (dlink_node *node = clients.head; node; node = node->next) {
         store_client *sc = (store_client *) node->data;
@@ -415,7 +455,7 @@ MemObject::kickReads()
     deferredReads.kickReads(-1);
 }
 
-#if DELAY_POOLS
+#if USE_DELAY_POOLS
 DelayId
 MemObject::mostBytesAllowed() const
 {
@@ -439,10 +479,6 @@ MemObject::mostBytesAllowed() const
 
 #endif
 
-        if (sc->getType() != STORE_MEM_CLIENT)
-            /* reading off disk */
-            continue;
-
         j = sc->delayId.bytesWanted(0, sc->copyInto.length);
 
         if (j > jmax) {
@@ -455,3 +491,9 @@ MemObject::mostBytesAllowed() const
 }
 
 #endif
+
+int64_t
+MemObject::availableForSwapOut() const
+{
+    return endOffset() - swapout.queue_offset;
+}