abortedConsumption = true;
// in case somebody enabled auto-consumption before regular one aborted
- if (mustAutoConsume)
- startAutoConsumption();
+ startAutoConsumptionIfNeeded();
}
}
postConsume(size);
}
-// In the AutoConsumption mode the consumer has gone but the producer continues
-// producing data. We are using a BodySink BodyConsumer which just discards the produced data.
void
BodyPipe::enableAutoConsumption()
{
mustAutoConsume = true;
debugs(91,5, HERE << "enabled auto consumption" << status());
- if (!theConsumer && theBuf.hasContent())
- startAutoConsumption();
+ startAutoConsumptionIfNeeded();
}
-// start auto consumption by creating body sink
+/// Check the current need and, if needed, start auto consumption. In auto
+/// consumption mode, the consumer is gone, but the producer continues to
+/// produce data. We use a BodySink BodyConsumer to discard that data.
void
-BodyPipe::startAutoConsumption()
+BodyPipe::startAutoConsumptionIfNeeded()
{
- Must(mustAutoConsume);
- Must(!theConsumer);
+ const auto startNow =
+ mustAutoConsume && // was enabled
+ !theConsumer && // has not started yet
+ theProducer.valid() && // still useful (and will eventually stop)
+ theBuf.hasContent(); // has something to consume right now
+ if (!startNow)
+ return;
+
theConsumer = new BodySink(this);
debugs(91,7, HERE << "starting auto consumption" << status());
scheduleBodyDataNotification();
thePutSize += size;
debugs(91,7, HERE << "added " << size << " bytes" << status());
- if (mustAutoConsume && !theConsumer && size > 0)
- startAutoConsumption();
+ if (!mayNeedMoreData())
+ clearProducer(true); // reached end-of-body
// We should not consume here even if mustAutoConsume because the
// caller may not be ready for the data to be consumed during this call.
scheduleBodyDataNotification();
- if (!mayNeedMoreData())
- clearProducer(true); // reached end-of-body
+ startAutoConsumptionIfNeeded();
}
void
bool exhausted() const; // saw eof/abort and all data consumed
bool stillConsuming(const Consumer::Pointer &consumer) const { return theConsumer == consumer; }
- // start or continue consuming when there is no consumer
+ /// start or continue consuming when producing without consumer
void enableAutoConsumption();
const MemBuf &buf() const { return theBuf; }
void postConsume(size_t size);
void postAppend(size_t size);
- void startAutoConsumption(); // delayed start of enabled consumption
+ void startAutoConsumptionIfNeeded();
private:
int64_t theBodySize; // expected total content length, if known
MemBuf theBuf; // produced but not yet consumed content, if any
- bool mustAutoConsume; // consume when there is no consumer
+ bool mustAutoConsume; ///< keep theBuf empty when producing without consumer
bool abortedConsumption; ///< called BodyProducer::noteBodyConsumerAborted
bool isCheckedOut; // to keep track of checkout violations
};