]> git.ipfire.org Git - thirdparty/squid.git/blame - src/BodyPipe.h
Fixed and polished autoconsumption mode.
[thirdparty/squid.git] / src / BodyPipe.h
CommitLineData
1b39caaa 1
2#ifndef SQUID_BODY_PIPE_H
3#define SQUID_BODY_PIPE_H
4
5#include "MemBuf.h"
6#include "AsyncCall.h"
e7352f30 7#include "ICAP/AsyncJob.h"
1b39caaa 8
9class BodyPipe;
10
11// Interface for those who want to produce body content for others.
12// BodyProducer is expected to create the BodyPipe.
13// One pipe cannot have more than one producer.
e7352f30 14class BodyProducer: virtual public AsyncJob {
1b39caaa 15 public:
e7352f30 16 BodyProducer():AsyncJob("BodyProducer"){}
1b39caaa 17 virtual ~BodyProducer() {}
18
e7352f30 19 virtual void noteMoreBodySpaceAvailable(RefCount<BodyPipe> bp) = 0;
20 virtual void noteBodyConsumerAborted(RefCount<BodyPipe> bp) = 0;
1b39caaa 21
22 protected:
23 void stopProducingFor(RefCount<BodyPipe> &pipe, bool atEof);
24};
25
26// Interface for those who want to consume body content from others.
27// BodyConsumer is expected to register with an existing BodyPipe
28// by calling BodyPipe::setConsumer().
29// One pipe cannot have more than one consumer.
e7352f30 30class BodyConsumer: virtual public AsyncJob {
1b39caaa 31 public:
e7352f30 32 BodyConsumer():AsyncJob("BodyConsumer"){}
1b39caaa 33 virtual ~BodyConsumer() {}
34
e7352f30 35 virtual void noteMoreBodyDataAvailable(RefCount<BodyPipe> bp) = 0;
36 virtual void noteBodyProductionEnded(RefCount<BodyPipe> bp) = 0;
37 virtual void noteBodyProducerAborted(RefCount<BodyPipe> bp) = 0;
1b39caaa 38
39 protected:
40 void stopConsumingFrom(RefCount<BodyPipe> &pipe);
41};
42
43// Makes raw buffer checkin/checkout interface efficient and exception-safe.
44// Either append or consume operations can be performed on a checkedout buffer.
45class BodyPipeCheckout {
46 public:
47 friend class BodyPipe;
48
49 public:
50 BodyPipeCheckout(BodyPipe &pipe); // checks out
51 ~BodyPipeCheckout(); // aborts checkout unless checkedIn
52
53 void checkIn();
54
55 public:
56 BodyPipe &pipe;
57 MemBuf &buf;
47f6e231 58 const uint64_t offset; // of current content, relative to the body start
1b39caaa 59
60 protected:
61 const size_t checkedOutSize;
62 bool checkedIn;
63
64 private:
65 BodyPipeCheckout(const BodyPipeCheckout &); // prevent copying
66 BodyPipeCheckout &operator =(const BodyPipeCheckout &); // prevent assignment
67};
68
69// Connects those who produces message body content with those who
70// consume it. For example, connects ConnStateData with FtpStateData OR
71// ICAPModXact with HttpStateData.
72class BodyPipe: public RefCountable {
73 public:
74 typedef RefCount<BodyPipe> Pointer;
75 typedef BodyProducer Producer;
76 typedef BodyConsumer Consumer;
77 typedef BodyPipeCheckout Checkout;
78
79 enum { MaxCapacity = SQUID_TCP_SO_RCVBUF };
80
81 friend class BodyPipeCheckout;
82
83 public:
84 BodyPipe(Producer *aProducer);
85 ~BodyPipe(); // asserts that producer and consumer are cleared
86
47f6e231 87 void setBodySize(uint64_t aSize); // set body size
1b39caaa 88 bool bodySizeKnown() const { return theBodySize >= 0; }
47f6e231 89 uint64_t bodySize() const;
90 uint64_t consumedSize() const { return theGetSize; }
1b39caaa 91 bool productionEnded() const { return !theProducer; }
92
93 // called by producers
94 void clearProducer(bool atEof); // aborts or sends eof
95 size_t putMoreData(const char *buf, size_t size);
96 bool mayNeedMoreData() const { return !bodySizeKnown() || needsMoreData(); }
97 bool needsMoreData() const { return bodySizeKnown() && unproducedSize() > 0; }
610d8f3b 98 uint64_t unproducedSize() const; // size of still unproduced data
e7352f30 99 bool stillProducing(Producer *producer) const { return theProducer == producer; }
1b39caaa 100
101 // called by consumers
102 bool setConsumerIfNotLate(Consumer *aConsumer);
103 void clearConsumer(); // aborts if still piping
104 size_t getMoreData(MemBuf &buf);
105 void consume(size_t size);
47f6e231 106 bool expectMoreAfter(uint64_t offset) const;
1b39caaa 107 bool exhausted() const; // saw eof/abort and all data consumed
e7352f30 108 bool stillConsuming(Consumer *consumer) const { return theConsumer == consumer; }
1b39caaa 109
110 // start or continue consuming when there is no consumer
111 void enableAutoConsumption();
112
113 const MemBuf &buf() const { return theBuf; }
114
115 const char *status() const; // for debugging only
116
117 protected:
118 // lower-level interface used by Checkout
119 MemBuf &checkOut(); // obtain raw buffer
120 void checkIn(Checkout &checkout); // return updated raw buffer
121 void undoCheckOut(Checkout &checkout); // undo checkout efffect
122
6c56baf6 123 void scheduleBodyDataNotification();
1b39caaa 124 void scheduleBodyEndNotification();
125
126 // keep counters in sync and notify producer or consumer
127 void postConsume(size_t size);
128 void postAppend(size_t size);
129
5121d48e
AR
130 void startAutoConsumption(); // delayed start of enabled consumption
131
1b39caaa 132 private:
47f6e231 133 int64_t theBodySize; // expected total content length, if known
1b39caaa 134 Producer *theProducer; // content producer, if any
135 Consumer *theConsumer; // content consumer, if any
136
47f6e231 137 uint64_t thePutSize; // ever-increasing total
138 uint64_t theGetSize; // ever-increasing total
1b39caaa 139
140 MemBuf theBuf; // produced but not yet consumed content, if any
141
142 bool mustAutoConsume; // consume when there is no consumer
143 bool isCheckedOut; // to keep track of checkout violations
144
145 CBDATA_CLASS2(BodyPipe);
146};
147
148#endif /* SQUID_BODY_PIPE_H */