by ensuring the read buffer has space [unless it is really full].
Trunk r13995 (Parser-NG: Convert the ICAP read buffer to an SBuf)
broke ICAP transactions that read a lot of data because the new
SBuf::consume() method often does not free buffer space, unlike the
old MemBuf::consume(). Affected transactions failed with mayReadMore()
exceptions because their readBuf.spaceSize() was zero while they
needed to read more data.
Any append,parse,consume;append,parse,consume;... user of SBuf cannot
rely on SBuf::spaceSize() to be meaningful because even consuming the
entire SBuf contents may leave spaceSize() at zero! Instead such code
has to use SBuf::length() to keep buffer from growing too big and
SBuf::rawSpace(1) to ensure some space is available for reading when
the buffer is not too big.
return;
}
- if (readBuf.spaceSize())
+ if (readBuf.length() < SQUID_TCP_SO_RCVBUF)
scheduleRead();
else
- debugs(93,3,HERE << "nothing to do because !readBuf.spaceSize()");
+ debugs(93,3,HERE << "cannot read with a full buffer");
}
// comm module read a portion of the ICAP response for us
// TODO: tune this better to expected message sizes
readBuf.reserveCapacity(SQUID_TCP_SO_RCVBUF);
+ // we are not asked to grow beyond the allowed maximum
+ Must(readBuf.length() < SQUID_TCP_SO_RCVBUF);
+ // now we can ensure that there is space to read new data,
+ // even if readBuf.spaceSize() currently returns zero.
+ readBuf.rawSpace(1);
CommIoCbParams rd(this); // will be expanded with ReadNow results
rd.conn = io.conn;
bool Adaptation::Icap::Xaction::mayReadMore() const
{
return !doneReading() && // will read more data
- readBuf.spaceSize(); // have space for more data
+ readBuf.length() < SQUID_TCP_SO_RCVBUF; // have space for more data
}
bool Adaptation::Icap::Xaction::doneReading() const