]>
Commit | Line | Data |
---|---|---|
c8be6d7b | 1 | /* |
1f7b830e | 2 | * Copyright (C) 1996-2025 The Squid Software Foundation and contributors |
c8be6d7b | 3 | * |
bbc27441 AJ |
4 | * Squid software is distributed under GPLv2+ license and includes |
5 | * contributions from numerous individuals and organizations. | |
6 | * Please see the COPYING and CONTRIBUTORS files for details. | |
c8be6d7b | 7 | */ |
8 | ||
ff9d9458 FC |
9 | #ifndef SQUID_SRC_STORECLIENT_H |
10 | #define SQUID_SRC_STORECLIENT_H | |
c8be6d7b | 11 | |
e227da8d | 12 | #include "acl/ChecklistFiller.h" |
1fa761af | 13 | #include "base/AsyncCall.h" |
f925268a | 14 | #include "base/forward.h" |
582c2af2 | 15 | #include "dlink.h" |
122a6e3c | 16 | #include "store/ParsingBuffer.h" |
c8be6d7b | 17 | #include "StoreIOBuffer.h" |
e877aaac | 18 | #include "StoreIOState.h" |
c8be6d7b | 19 | |
122a6e3c AR |
20 | /// A storeClientCopy() callback function. |
21 | /// | |
22 | /// Upon storeClientCopy() success, StoreIOBuffer::flags.error is zero, and | |
23 | /// * HTTP response headers (if any) are available via MemObject::freshestReply(); | |
24 | /// * HTTP response body bytes (if any) are available via StoreIOBuffer. | |
25 | /// | |
26 | /// STCB callbacks may use response semantics to detect certain EOF conditions. | |
27 | /// Callbacks that expect HTTP headers may call store_client::atEof(). Similar | |
28 | /// to clientStreamCallback() callbacks, callbacks dedicated to receiving HTTP | |
29 | /// bodies may use zero StoreIOBuffer::length as an EOF condition. | |
30 | /// | |
31 | /// Errors are indicated by setting StoreIOBuffer flags.error. | |
32 | using STCB = void (void *, StoreIOBuffer); | |
c8be6d7b | 33 | |
3b13a8fd | 34 | class StoreEntry; |
819be284 | 35 | class ACLFilledChecklist; |
d2a6dcba | 36 | class LogTags; |
e6ccf245 | 37 | |
ee989932 | 38 | // TODO: Merge store_client into StoreClient. |
7976fed3 | 39 | /// a storeGetPublic*() caller |
e227da8d | 40 | class StoreClient: public Acl::ChecklistFiller |
62e76326 | 41 | { |
42 | ||
e6ccf245 | 43 | public: |
337b9aa4 | 44 | ~StoreClient () override {} |
62e76326 | 45 | |
d2a6dcba | 46 | /// \return LogTags (if the class logs transactions) or nil (otherwise) |
7976fed3 | 47 | virtual LogTags *loggingTags() const = 0; |
d2a6dcba | 48 | |
819be284 | 49 | protected: |
d2a6dcba EB |
50 | /// \returns whether the caller must collapse on the given entry |
51 | /// Before returning true, updates common collapsing-related stats. | |
52 | /// See also: StoreEntry::hittingRequiresCollapsing(). | |
7976fed3 | 53 | bool startCollapsingOn(const StoreEntry &, const bool doingRevalidation) const; |
d2a6dcba | 54 | |
819be284 EB |
55 | // These methods only interpret Squid configuration. Their allowances are |
56 | // provisional -- other factors may prevent collapsed forwarding. The first | |
57 | // two exist primarily to distinguish two major CF cases in callers code. | |
58 | /// whether Squid configuration allows us to become a CF initiator | |
59 | bool mayInitiateCollapsing() const { return onCollapsingPath(); } | |
819be284 EB |
60 | /// whether Squid configuration allows collapsing for this transaction |
61 | bool onCollapsingPath() const; | |
ee989932 AR |
62 | |
63 | /// whether startCollapsingOn() was called and returned true | |
64 | mutable bool didCollapse = false; | |
e6ccf245 | 65 | }; |
e6ccf245 | 66 | |
9a0a18de | 67 | #if USE_DELAY_POOLS |
b67e2c8c | 68 | #include "DelayId.h" |
69 | #endif | |
70 | ||
c8be6d7b | 71 | /* keep track each client receiving data from that particular StoreEntry */ |
62e76326 | 72 | |
73 | class store_client | |
74 | { | |
5c2f68b7 | 75 | CBDATA_CLASS(store_client); |
62e76326 | 76 | |
528b2c61 | 77 | public: |
836d3c0b | 78 | explicit store_client(StoreEntry *); |
2f44bd34 | 79 | ~store_client(); |
1fa761af | 80 | |
3a5c8b44 AR |
81 | /// the client will not use HTTP response bytes with lower offsets (if any) |
82 | auto discardableHttpEnd() const { return discardableHttpEnd_; } | |
1fa761af | 83 | |
528b2c61 | 84 | int getType() const; |
1fa761af EB |
85 | |
86 | /// React to the end of reading the response from disk. There will be no | |
87 | /// more readHeader() and readBody() callbacks for the current storeRead() | |
88 | /// swapin after this notification. | |
89 | void noteSwapInDone(bool error); | |
90 | ||
528b2c61 | 91 | void doCopy (StoreEntry *e); |
92 | void readHeader(const char *buf, ssize_t len); | |
beae59b0 | 93 | void readBody(const char *buf, ssize_t len); |
1fa761af EB |
94 | |
95 | /// Request StoreIOBuffer-described response data via an asynchronous STCB | |
96 | /// callback. At most one outstanding request is allowed per store_client. | |
528b2c61 | 97 | void copy(StoreEntry *, StoreIOBuffer, STCB *, void *); |
1fa761af | 98 | |
fcc35180 | 99 | void dumpStats(MemBuf * output, int clientNumber) const; |
528b2c61 | 100 | |
122a6e3c AR |
101 | // TODO: When STCB gets a dedicated Answer type, move this info there. |
102 | /// Whether the last successful storeClientCopy() answer was known to | |
103 | /// contain the last body bytes of the HTTP response | |
104 | /// \retval true requesting bytes at higher offsets is futile | |
105 | /// \sa STCB | |
106 | bool atEof() const { return atEof_; } | |
107 | ||
c8be6d7b | 108 | #if STORE_CLIENT_LIST_DEBUG |
62e76326 | 109 | |
c8be6d7b | 110 | void *owner; |
111 | #endif | |
62e76326 | 112 | |
f53969cc | 113 | StoreEntry *entry; /* ptr to the parent StoreEntry, argh! */ |
d3b3ab85 | 114 | StoreIOState::Pointer swapin_sio; |
62e76326 | 115 | |
26ac0430 | 116 | struct { |
1fa761af EB |
117 | /// whether we are expecting a response to be swapped in from disk |
118 | /// (i.e. whether async storeRead() is currently in progress) | |
119 | // TODO: a better name reflecting the 'in' scope of the flag | |
3dd52a0b | 120 | bool disk_io_pending; |
1fa761af EB |
121 | |
122 | /// whether the store_client::doCopy()-initiated STCB sequence is | |
123 | /// currently in progress | |
3dd52a0b | 124 | bool store_copying; |
3d0ac046 | 125 | } flags; |
62e76326 | 126 | |
9a0a18de | 127 | #if USE_DELAY_POOLS |
b67e2c8c | 128 | DelayId delayId; |
1fa761af EB |
129 | |
130 | /// The maximum number of bytes the Store client can read/copy next without | |
131 | /// overflowing its buffer and without violating delay pool limits. Store | |
132 | /// I/O is not rate-limited, but we assume that the same number of bytes may | |
133 | /// be read from the Squid-to-server connection that may be rate-limited. | |
134 | int bytesWanted() const; | |
135 | ||
b67e2c8c | 136 | void setDelayId(DelayId delay_id); |
c8be6d7b | 137 | #endif |
62e76326 | 138 | |
c8be6d7b | 139 | dlink_node node; |
62e76326 | 140 | |
528b2c61 | 141 | private: |
122a6e3c AR |
142 | bool moreToRead() const; |
143 | bool canReadFromMemory() const; | |
144 | bool answeredOnce() const { return answers >= 1; } | |
145 | bool sendingHttpHeaders() const; | |
146 | int64_t nextHttpReadOffset() const; | |
f25d697f | 147 | |
528b2c61 | 148 | void fileRead(); |
4e70dae3 | 149 | void scheduleDiskRead(); |
122a6e3c | 150 | void readFromMemory(); |
4e70dae3 | 151 | void scheduleRead(); |
0cdcf3d7 | 152 | bool startSwapin(); |
122a6e3c AR |
153 | void handleBodyFromDisk(); |
154 | void maybeWriteFromDiskToMemory(const StoreIOBuffer &); | |
155 | ||
156 | bool parseHttpHeadersFromDisk(); | |
157 | bool tryParsingHttpHeaders(); | |
158 | void skipHttpHeadersFromDisk(); | |
62e76326 | 159 | |
1fa761af EB |
160 | void fail(); |
161 | void callback(ssize_t); | |
162 | void noteCopiedBytes(size_t); | |
1fa761af EB |
163 | void noteNews(); |
164 | void finishCallback(); | |
165 | static void FinishCallback(store_client *); | |
166 | ||
528b2c61 | 167 | int type; |
168 | bool object_ok; | |
62e76326 | 169 | |
122a6e3c AR |
170 | /// \copydoc atEof() |
171 | bool atEof_; | |
172 | ||
1fa761af EB |
173 | /// Storage and metadata associated with the current copy() request. Ought |
174 | /// to be ignored when not answering a copy() request. | |
3a5c8b44 AR |
175 | /// * copyInto.offset is the requested HTTP response body offset; |
176 | /// * copyInto.data is the client-owned, client-provided result buffer; | |
177 | /// * copyInto.length is the size of the .data result buffer; | |
178 | /// * copyInto.flags are unused by this class. | |
1fa761af EB |
179 | StoreIOBuffer copyInto; |
180 | ||
3a5c8b44 AR |
181 | // TODO: Convert to uint64_t after fixing mem_hdr::endOffset() and friends. |
182 | /// \copydoc discardableHttpEnd() | |
183 | int64_t discardableHttpEnd_ = 0; | |
184 | ||
122a6e3c AR |
185 | /// the total number of finishCallback() calls |
186 | uint64_t answers; | |
187 | ||
188 | /// Accumulates raw bytes read from Store while answering the current copy() | |
189 | /// request. Buffer contents depends on the source and parsing stage; it may | |
190 | /// hold (parts of) swap metadata, HTTP response headers, and/or HTTP | |
191 | /// response body bytes. | |
192 | std::optional<Store::ParsingBuffer> parsingBuffer; | |
193 | ||
194 | StoreIOBuffer lastDiskRead; ///< buffer used for the last storeRead() call | |
1fa761af | 195 | |
90703668 | 196 | /* Until we finish stuffing code into store_client */ |
197 | ||
198 | public: | |
199 | ||
26ac0430 | 200 | struct Callback { |
6ec49cda | 201 | Callback() = default; |
62e76326 | 202 | |
203 | Callback (STCB *, void *); | |
1fa761af EB |
204 | |
205 | /// Whether the copy() answer is needed/expected (by the client) and has | |
206 | /// not been computed (by us). False during (asynchronous) answer | |
207 | /// delivery to the STCB callback_handler. | |
90703668 | 208 | bool pending() const; |
1fa761af | 209 | |
6ec49cda AR |
210 | STCB *callback_handler = nullptr; ///< where to deliver the answer |
211 | CallbackData cbData; ///< the first STCB callback parameter | |
f925268a | 212 | CodeContextPointer codeContext; ///< Store client context |
1fa761af EB |
213 | |
214 | /// a scheduled asynchronous finishCallback() call (or nil) | |
215 | AsyncCall::Pointer notifier; | |
2fadd50d | 216 | } _callback; |
c8be6d7b | 217 | }; |
218 | ||
122a6e3c AR |
219 | /// Asynchronously read HTTP response headers and/or body bytes from Store. |
220 | /// | |
221 | /// The requested zero-based HTTP body offset is specified via the | |
222 | /// StoreIOBuffer::offset field. The first call (for a given store_client | |
223 | /// object) must specify zero offset. | |
224 | /// | |
225 | /// The requested HTTP body portion size is specified via the | |
226 | /// StoreIOBuffer::length field. The function may return fewer body bytes. | |
227 | /// | |
228 | /// See STCB for result delivery details. | |
8a648e8d | 229 | void storeClientCopy(store_client *, StoreEntry *, StoreIOBuffer, STCB *, void *); |
122a6e3c | 230 | |
8a648e8d | 231 | store_client* storeClientListAdd(StoreEntry * e, void *data); |
8a648e8d FC |
232 | int storeUnregister(store_client * sc, StoreEntry * e, void *data); |
233 | int storePendingNClients(const StoreEntry * e); | |
234 | int storeClientIsThisAClient(store_client * sc, void *someClient); | |
e87137f1 | 235 | |
ff9d9458 | 236 | #endif /* SQUID_SRC_STORECLIENT_H */ |
f53969cc | 237 |