]> git.ipfire.org Git - thirdparty/squid.git/blob - src/StoreClient.h
4560bc14e46077c8bd7ecd474175dc5f258318c8
[thirdparty/squid.git] / src / StoreClient.h
1 /*
2 * Copyright (C) 1996-2025 The Squid Software Foundation and contributors
3 *
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.
7 */
8
9 #ifndef SQUID_SRC_STORECLIENT_H
10 #define SQUID_SRC_STORECLIENT_H
11
12 #include "acl/ChecklistFiller.h"
13 #include "base/AsyncCall.h"
14 #include "base/forward.h"
15 #include "dlink.h"
16 #include "store/ParsingBuffer.h"
17 #include "StoreIOBuffer.h"
18 #include "StoreIOState.h"
19
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);
33
34 class StoreEntry;
35 class ACLFilledChecklist;
36 class LogTags;
37
38 // TODO: Merge store_client into StoreClient.
39 /// a storeGetPublic*() caller
40 class StoreClient: public Acl::ChecklistFiller
41 {
42
43 public:
44 ~StoreClient () override {}
45
46 /// \return LogTags (if the class logs transactions) or nil (otherwise)
47 virtual LogTags *loggingTags() const = 0;
48
49 protected:
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().
53 bool startCollapsingOn(const StoreEntry &, const bool doingRevalidation) const;
54
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(); }
60 /// whether Squid configuration allows collapsing for this transaction
61 bool onCollapsingPath() const;
62
63 /// whether startCollapsingOn() was called and returned true
64 mutable bool didCollapse = false;
65 };
66
67 #if USE_DELAY_POOLS
68 #include "DelayId.h"
69 #endif
70
71 /* keep track each client receiving data from that particular StoreEntry */
72
73 class store_client
74 {
75 CBDATA_CLASS(store_client);
76
77 public:
78 explicit store_client(StoreEntry *);
79 ~store_client();
80
81 /// the client will not use HTTP response bytes with lower offsets (if any)
82 auto discardableHttpEnd() const { return discardableHttpEnd_; }
83
84 int getType() const;
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
91 void doCopy (StoreEntry *e);
92 void readHeader(const char *buf, ssize_t len);
93 void readBody(const char *buf, ssize_t len);
94
95 /// Request StoreIOBuffer-described response data via an asynchronous STCB
96 /// callback. At most one outstanding request is allowed per store_client.
97 void copy(StoreEntry *, StoreIOBuffer, STCB *, void *);
98
99 void dumpStats(MemBuf * output, int clientNumber) const;
100
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
108 #if STORE_CLIENT_LIST_DEBUG
109
110 void *owner;
111 #endif
112
113 StoreEntry *entry; /* ptr to the parent StoreEntry, argh! */
114 StoreIOState::Pointer swapin_sio;
115
116 struct {
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
120 bool disk_io_pending;
121
122 /// whether the store_client::doCopy()-initiated STCB sequence is
123 /// currently in progress
124 bool store_copying;
125 } flags;
126
127 #if USE_DELAY_POOLS
128 DelayId delayId;
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
136 void setDelayId(DelayId delay_id);
137 #endif
138
139 dlink_node node;
140
141 private:
142 bool moreToRead() const;
143 bool canReadFromMemory() const;
144 bool answeredOnce() const { return answers >= 1; }
145 bool sendingHttpHeaders() const;
146 int64_t nextHttpReadOffset() const;
147
148 void fileRead();
149 void scheduleDiskRead();
150 void readFromMemory();
151 void scheduleRead();
152 bool startSwapin();
153 void handleBodyFromDisk();
154 void maybeWriteFromDiskToMemory(const StoreIOBuffer &);
155
156 bool parseHttpHeadersFromDisk();
157 bool tryParsingHttpHeaders();
158 void skipHttpHeadersFromDisk();
159
160 void fail();
161 void callback(ssize_t);
162 void noteCopiedBytes(size_t);
163 void noteNews();
164 void finishCallback();
165 static void FinishCallback(store_client *);
166
167 int type;
168 bool object_ok;
169
170 /// \copydoc atEof()
171 bool atEof_;
172
173 /// Storage and metadata associated with the current copy() request. Ought
174 /// to be ignored when not answering a copy() request.
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.
179 StoreIOBuffer copyInto;
180
181 // TODO: Convert to uint64_t after fixing mem_hdr::endOffset() and friends.
182 /// \copydoc discardableHttpEnd()
183 int64_t discardableHttpEnd_ = 0;
184
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
195
196 /* Until we finish stuffing code into store_client */
197
198 public:
199
200 struct Callback {
201 Callback() = default;
202
203 Callback (STCB *, void *);
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.
208 bool pending() const;
209
210 STCB *callback_handler = nullptr; ///< where to deliver the answer
211 CallbackData cbData; ///< the first STCB callback parameter
212 CodeContextPointer codeContext; ///< Store client context
213
214 /// a scheduled asynchronous finishCallback() call (or nil)
215 AsyncCall::Pointer notifier;
216 } _callback;
217 };
218
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.
229 void storeClientCopy(store_client *, StoreEntry *, StoreIOBuffer, STCB *, void *);
230
231 store_client* storeClientListAdd(StoreEntry * e, void *data);
232 int storeUnregister(store_client * sc, StoreEntry * e, void *data);
233 int storePendingNClients(const StoreEntry * e);
234 int storeClientIsThisAClient(store_client * sc, void *someClient);
235
236 #endif /* SQUID_SRC_STORECLIENT_H */
237