]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/MemObject.cc
Source Format Enforcement (#532)
[thirdparty/squid.git] / src / MemObject.cc
index 8c8c310772b38a79ef7d39ab4235050fd56ebaa8..00fc25589bceffcd8a17bceea98669de59e51d39 100644 (file)
@@ -1,42 +1,18 @@
-
 /*
- * DEBUG: section 19    Store Memory Primitives
- * AUTHOR: Robert Collins
- *
- * SQUID Web Proxy Cache          http://www.squid-cache.org/
- * ----------------------------------------------------------
- *
- *  Squid is the result of efforts by numerous individuals from
- *  the Internet community; see the CONTRIBUTORS file for full
- *  details.   Many organizations have provided support for Squid's
- *  development; see the SPONSORS file for full details.  Squid is
- *  Copyrighted (C) 2001 by the Regents of the University of
- *  California; see the COPYRIGHT file for full details.  Squid
- *  incorporates software developed and/or copyrighted by other
- *  sources; see the CREDITS file for full details.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  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.
+ * Copyright (C) 1996-2020 The Squid Software Foundation and contributors
  *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
+/* DEBUG: section 19    Store Memory Primitives */
+
 #include "squid.h"
 #include "comm/Connection.h"
 #include "Generic.h"
 #include "globals.h"
 #include "HttpReply.h"
-#include "HttpRequest.h"
 #include "MemBuf.h"
 #include "MemObject.h"
 #include "profiler/Profiler.h"
@@ -75,8 +51,9 @@ MemObject::inUseCount()
 }
 
 const char *
-MemObject::storeId() const {
-    if (!storeId_.defined()) {
+MemObject::storeId() const
+{
+    if (!storeId_.size()) {
         debugs(20, DBG_IMPORTANT, "Bug: Missing MemObject::storeId value");
         dump();
         storeId_ = "[unknown_URI]";
@@ -85,22 +62,28 @@ MemObject::storeId() const {
 }
 
 const char *
-MemObject::logUri() const {
-    return logUri_.defined() ? logUri_.termedBuf() : storeId();
+MemObject::logUri() const
+{
+    return logUri_.size() ? logUri_.termedBuf() : storeId();
 }
 
 bool
-MemObject::hasUris() const {
-    return storeId_.defined();
+MemObject::hasUris() const
+{
+    return storeId_.size();
 }
 
 void
 MemObject::setUris(char const *aStoreId, char const *aLogUri, const HttpRequestMethod &aMethod)
 {
+    if (hasUris())
+        return;
+
     storeId_ = aStoreId;
+    debugs(88, 3, this << " storeId: " << storeId_);
 
     // fast pointer comparison for a common storeCreateEntry(url,url,...) case
-    if (!aLogUri || aLogUri == aStoreId) 
+    if (!aLogUri || aLogUri == aStoreId)
         logUri_.clean(); // use storeId_ by default to minimize copying
     else
         logUri_ = aLogUri;
@@ -112,23 +95,18 @@ MemObject::setUris(char const *aStoreId, char const *aLogUri, const HttpRequestM
 #endif
 }
 
-MemObject::MemObject(): smpCollapsed(false)
+MemObject::MemObject()
 {
-    debugs(20, 3, HERE << "new MemObject " << this);
-    _reply = new HttpReply;
-    HTTPMSGLOCK(_reply);
-
-    object_sz = -1;
-
-    /* XXX account log_url */
-
-    swapout.decision = SwapOut::swNeedsCheck;
+    debugs(20, 3, "MemObject constructed, this=" << this);
+    ping_reply_callback = nullptr;
+    memset(&start_ping, 0, sizeof(start_ping));
+    reply_ = new HttpReply;
 }
 
 MemObject::~MemObject()
 {
-    debugs(20, 3, HERE << "del MemObject " << this);
-    const Ctx ctx = ctx_enter(urlXXX());
+    debugs(20, 3, "MemObject destructed, this=" << this);
+    const Ctx ctx = ctx_enter(hasUris() ? urlXXX() : "[unknown_ctx]");
 
 #if URL_CHECKSUM_DEBUG
     checkUrlChecksum();
@@ -151,19 +129,22 @@ MemObject::~MemObject()
 
 #endif
 
-    HTTPMSGUNLOCK(_reply);
-
-    HTTPMSGUNLOCK(request);
-
     ctx_exit(ctx);              /* must exit before we free mem->url */
+}
 
-    safe_free(vary_headers);
+HttpReply &
+MemObject::adjustableBaseReply()
+{
+    assert(!updatedReply_);
+    return *reply_;
 }
 
 void
-MemObject::unlinkRequest()
+MemObject::replaceBaseReply(const HttpReplyPointer &r)
 {
-    HTTPMSGUNLOCK(request);
+    assert(r);
+    reply_ = r;
+    updatedReply_ = nullptr;
 }
 
 void
@@ -194,26 +175,14 @@ MemObject::dump() const
     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->reply: " << reply_);
+    debugs(20, DBG_IMPORTANT, "MemObject->updatedReply: " << updatedReply_);
+    debugs(20, DBG_IMPORTANT, "MemObject->appliedUpdates: " << appliedUpdates);
     debugs(20, DBG_IMPORTANT, "MemObject->request: " << request);
     debugs(20, DBG_IMPORTANT, "MemObject->logUri: " << logUri_);
     debugs(20, DBG_IMPORTANT, "MemObject->storeId: " << storeId_);
 }
 
-HttpReply const *
-MemObject::getReply() const
-{
-    return _reply;
-}
-
-void
-MemObject::replaceHttpReply(HttpReply *newrep)
-{
-    HTTPMSGUNLOCK(_reply);
-    _reply = newrep;
-    HTTPMSGLOCK(_reply);
-}
-
 struct LowestMemReader : public unary_function<store_client, void> {
     LowestMemReader(int64_t seed):current(seed) {}
 
@@ -240,29 +209,22 @@ struct StoreClientStats : public unary_function<store_client, void> {
 void
 MemObject::stat(MemBuf * mb) const
 {
-    mb->Printf("\t%s %s\n",
-               RequestMethodStr(method), logUri());
-    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);
+    mb->appendf("\t" SQUIDSBUFPH " %s\n", SQUIDSBUFPRINT(method.image()), logUri());
+    if (!vary_headers.isEmpty())
+        mb->appendf("\tvary_headers: " SQUIDSBUFPH "\n", SQUIDSBUFPRINT(vary_headers));
+    mb->appendf("\tinmem_lo: %" PRId64 "\n", inmem_lo);
+    mb->appendf("\tinmem_hi: %" PRId64 "\n", data_hdr.endOffset());
+    mb->appendf("\tswapout: %" PRId64 " bytes queued\n", swapout.queue_offset);
 
     if (swapout.sio.getRaw())
-        mb->Printf("\tswapout: %" PRId64 " bytes written\n",
-                   (int64_t) swapout.sio->offset());
+        mb->appendf("\tswapout: %" PRId64 " bytes written\n", (int64_t) swapout.sio->offset());
 
     if (xitTable.index >= 0)
-        mb->Printf("\ttransient index: %d state: %d\n",
-                   xitTable.index, xitTable.io);
+        mb->appendf("\ttransient index: %d state: %d\n", xitTable.index, xitTable.io);
     if (memCache.index >= 0)
-        mb->Printf("\tmem-cache index: %d state: %d offset: %" PRId64 "\n",
-                   memCache.index, memCache.io, memCache.offset);
+        mb->appendf("\tmem-cache index: %d state: %d offset: %" PRId64 "\n", memCache.index, memCache.io, memCache.offset);
     if (object_sz >= 0)
-        mb->Printf("\tobject_sz: %" PRId64 "\n", object_sz);
-    if (smpCollapsed)
-        mb->Printf("\tsmp-collapsed\n");
+        mb->appendf("\tobject_sz: %" PRId64 "\n", object_sz);
 
     StoreClientStats statsVisitor(mb);
 
@@ -280,8 +242,8 @@ MemObject::markEndOfReplyHeaders()
 {
     const int hdr_sz = endOffset();
     assert(hdr_sz >= 0);
-    assert(_reply);
-    _reply->hdr_sz = hdr_sz;
+    assert(reply_);
+    reply_->hdr_sz = hdr_sz;
 }
 
 int64_t
@@ -296,18 +258,27 @@ MemObject::size() const
 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
+    if (object_sz >= 0) {
+        debugs(20, 7, object_sz << " frozen by complete()");
         return object_sz;
+    }
+
+    const auto hdr_sz = baseReply().hdr_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;
+    // Cannot predict future length using an empty/unset or HTTP/0 reply.
+    // For any HTTP/1 reply, hdr_sz is positive  -- status-line cannot be empty.
+    if (hdr_sz <= 0)
+        return -1;
+
+    const auto clen = baseReply().bodySize(method);
+    if (clen < 0) {
+        debugs(20, 7, "unknown; hdr: " << hdr_sz);
+        return -1;
     }
 
-    return -1; // not enough information to predict
+    const auto messageSize = clen + hdr_sz;
+    debugs(20, 7, messageSize << " hdr: " << hdr_sz << " clen: " << clen);
+    return messageSize;
 }
 
 void
@@ -317,6 +288,10 @@ MemObject::reset()
     data_hdr.freeContent();
     inmem_lo = 0;
     /* Should we check for clients? */
+    assert(reply_);
+    reply_->reset();
+    updatedReply_ = nullptr;
+    appliedUpdates = false;
 }
 
 int64_t
@@ -333,11 +308,12 @@ MemObject::lowestMemReaderOffset() const
 bool
 MemObject::readAheadPolicyCanRead() const
 {
-    const bool canRead = endOffset() - getReply()->hdr_sz <
-        lowestMemReaderOffset() + Config.readAheadGap;
+    const auto savedHttpHeaders = baseReply().hdr_sz;
+    const bool canRead = endOffset() - savedHttpHeaders <
+                         lowestMemReaderOffset() + Config.readAheadGap;
 
     if (!canRead) {
-        debugs(19, 9, "no: " << endOffset() << '-' << getReply()->hdr_sz <<
+        debugs(19, 5, "no: " << endOffset() << '-' << savedHttpHeaders <<
                " < " << lowestMemReaderOffset() << '+' << Config.readAheadGap);
     }
 
@@ -424,7 +400,7 @@ MemObject::trimSwappable()
         new_mem_lo = on_disk - 1;
 
     if (new_mem_lo == -1)
-        new_mem_lo = 0;        /* the above might become -1 */
+        new_mem_lo = 0; /* the above might become -1 */
 
     data_hdr.freeDataUpto(new_mem_lo);
 
@@ -480,6 +456,14 @@ MemObject::setNoDelay(bool const newValue)
 void
 MemObject::delayRead(DeferredRead const &aRead)
 {
+#if USE_DELAY_POOLS
+    if (readAheadPolicyCanRead()) {
+        if (DelayId mostAllowedId = mostBytesAllowed()) {
+            mostAllowedId.delayRead(aRead);
+            return;
+        }
+    }
+#endif
     deferredReads.delayRead(aRead);
 }
 
@@ -531,3 +515,4 @@ MemObject::availableForSwapOut() const
 {
     return endOffset() - swapout.queue_offset;
 }
+