Without this check, a DelayId::operator bool() caller could incorrectly
limit reading from a cache_peer that has been configured to ignore delay
pools. Luckily, all existing code paths that use this operator checked
the markedAsNoDelay flag, avoiding this problem:
* DelayId::bytesWanted() and DelayId::bytesIn() checked markedAsNoDelay.
* While MemObject::delayRead() itself did not check markedAsNoDelay, the
method is not called when markedAsNoDelay is true. The analysis of the
corresponding code paths is complex, especially for HttpStateData! We
also call expensive mostBytesAllowed() several times on these paths.
Refactoring this code is outside this API safety improvement scope.
This change helps avoid accidental/unwanted read delays during future
code changes.
DelayId::operator bool() const
{
- return pool_ || compositeId.getRaw();
+ return (pool_ || compositeId.getRaw()) && !markedAsNoDelay;
}
/* create a delay Id for a given request */
{
/* unlimited */
- if (! (*this) || markedAsNoDelay)
+ if (! (*this))
return max(minimum, maximum);
/* limited */
if (! (*this))
return;
- if (markedAsNoDelay)
- return;
-
assert ((unsigned short)(pool() - 1) != 0xFFFF);
if (compositeId != nullptr)
DelayIdComposite::Pointer const compositePosition() const;
void compositePosition(const DelayIdComposite::Pointer &);
bool operator == (DelayId const &rhs) const;
+
+ /// Whether we may delay reading. This operator is meant to be used as an
+ /// optimization that helps avoid more expensive bytesWanted() computations.
+ /// \retval false if bytesWanted() called with a positive maximum limit
+ /// parameter will never return zero
operator bool() const;
+
int bytesWanted(int min, int max) const;
void bytesIn (int qty);
void setNoDelay(bool const);