/*
- * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
+ * 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.
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)
#endif
}
-MemObject::MemObject() :
- inmem_lo(0),
- nclients(0),
- smpCollapsed(false),
- ping_reply_callback(nullptr),
- ircb_data(nullptr),
- id(0),
- object_sz(-1),
- swap_hdr_sz(0),
-#if URL_CHECKSUM_DEBUG
- chksum(0),
-#endif
- vary_headers(nullptr)
+MemObject::MemObject()
{
- debugs(20, 3, "new MemObject " << this);
+ debugs(20, 3, "MemObject constructed, this=" << this);
+ ping_reply_callback = nullptr;
memset(&start_ping, 0, sizeof(start_ping));
- memset(&abort, 0, sizeof(abort));
reply_ = new HttpReply;
}
MemObject::~MemObject()
{
- debugs(20, 3, "del MemObject " << this);
+ debugs(20, 3, "MemObject destructed, this=" << this);
const Ctx ctx = ctx_enter(hasUris() ? urlXXX() : "[unknown_ctx]");
#if URL_CHECKSUM_DEBUG
ctx_exit(ctx); /* must exit before we free mem->url */
}
+HttpReply &
+MemObject::adjustableBaseReply()
+{
+ assert(!updatedReply_);
+ return *reply_;
+}
+
+void
+MemObject::replaceBaseReply(const HttpReplyPointer &r)
+{
+ assert(r);
+ reply_ = r;
+ updatedReply_ = nullptr;
+}
+
void
MemObject::write(const StoreIOBuffer &writeBuffer)
{
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->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_);
mb->appendf("\tmem-cache index: %d state: %d offset: %" PRId64 "\n", memCache.index, memCache.io, memCache.offset);
if (object_sz >= 0)
mb->appendf("\tobject_sz: %" PRId64 "\n", object_sz);
- if (smpCollapsed)
- mb->appendf("\tsmp-collapsed\n");
StoreClientStats statsVisitor(mb);
int64_t
MemObject::expectedReplySize() const
{
- debugs(20, 7, "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, "clen: " << clen);
- if (clen >= 0 && reply_->hdr_sz > 0) // yuck: Http::Message 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
data_hdr.freeContent();
inmem_lo = 0;
/* Should we check for clients? */
- if (reply_)
- reply_->reset();
+ assert(reply_);
+ reply_->reset();
+ updatedReply_ = nullptr;
+ appliedUpdates = false;
}
int64_t
bool
MemObject::readAheadPolicyCanRead() const
{
- const bool canRead = endOffset() - getReply()->hdr_sz <
+ 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);
}
void
MemObject::delayRead(DeferredRead const &aRead)
{
+#if USE_DELAY_POOLS
+ if (readAheadPolicyCanRead()) {
+ if (DelayId mostAllowedId = mostBytesAllowed()) {
+ mostAllowedId.delayRead(aRead);
+ return;
+ }
+ }
+#endif
deferredReads.delayRead(aRead);
}