forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathhttp_cache_writers.h
294 lines (233 loc) · 11.2 KB
/
http_cache_writers.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
// Copyright (c) 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_HTTP_HTTP_CACHE_WRITERS_H_
#define NET_HTTP_HTTP_CACHE_WRITERS_H_
#include <list>
#include <map>
#include <memory>
#include "base/memory/weak_ptr.h"
#include "net/base/completion_once_callback.h"
#include "net/http/http_cache.h"
namespace net {
class HttpResponseInfo;
class PartialData;
// If multiple HttpCache::Transactions are accessing the same cache entry
// simultaneously, their access to the data read from network is synchronized
// by HttpCache::Writers. This enables each of those transactions to drive
// reading the response body from the network ensuring a slow consumer does not
// starve other consumers of the same resource.
//
// Writers represents the set of all HttpCache::Transactions that are reading
// from the network using the same network transaction and writing to the same
// cache entry. It is owned by the ActiveEntry. The writers object must be
// deleted when HttpCache::WritersDoneWritingToEntry is called as it doesn't
// expect any of its ongoing IO transactions (e.g., network reads or cache
// writers) to complete after that point and won't know what to do with them.
class NET_EXPORT_PRIVATE HttpCache::Writers {
public:
// This is the information maintained by Writers in the context of each
// transaction.
// |partial| is owned by the transaction and to be sure there are no
// dangling pointers, it must be ensured that transaction's reference and
// this information will be removed from writers once the transaction is
// deleted.
struct NET_EXPORT_PRIVATE TransactionInfo {
TransactionInfo(PartialData* partial,
bool truncated,
HttpResponseInfo info);
~TransactionInfo();
TransactionInfo& operator=(const TransactionInfo&);
TransactionInfo(const TransactionInfo&);
PartialData* partial;
bool truncated;
HttpResponseInfo response_info;
};
// |cache| and |entry| must outlive this object.
Writers(HttpCache* cache, HttpCache::ActiveEntry* entry);
~Writers();
// Retrieves data from the network transaction associated with the Writers
// object. This may be done directly (via a network read into |*buf->data()|)
// or indirectly (by copying from another transactions buffer into
// |*buf->data()| on network read completion) depending on whether or not a
// read is currently in progress. May return the result synchronously or
// return ERR_IO_PENDING: if ERR_IO_PENDING is returned, |callback| will be
// run to inform the consumer of the result of the Read().
// |transaction| may be removed while Read() is ongoing. In that case Writers
// will still complete the Read() processing but will not invoke the
// |callback|.
int Read(scoped_refptr<IOBuffer> buf,
int buf_len,
CompletionOnceCallback callback,
Transaction* transaction);
// Invoked when StopCaching is called on a member transaction.
// It stops caching only if there are no other transactions. Returns true if
// caching can be stopped.
// |keep_entry| should be true if the entry needs to be preserved after
// truncation.
bool StopCaching(bool keep_entry);
// Membership functions like AddTransaction and RemoveTransaction are invoked
// by HttpCache on behalf of the HttpCache::Transaction.
// Adds an HttpCache::Transaction to Writers.
// Should only be invoked if CanAddWriters() returns true.
// |parallel_writing_pattern| governs whether writing is an exclusive
// operation implying that Writers can contain at most one transaction till
// the completion of the response body. It is illegal to invoke with
// |parallel_writing_pattern| as PARALLEL_WRITING_NOT_JOIN* if there is
// already a transaction present.
// |transaction| can be destroyed at any point and it should invoke
// HttpCache::DoneWithEntry() during its destruction. This will also ensure
// any pointers in |info| are not accessed after the transaction is destroyed.
void AddTransaction(Transaction* transaction,
ParallelWritingPattern initial_writing_pattern,
RequestPriority priority,
const TransactionInfo& info);
// Invoked when the transaction is done working with the entry.
void RemoveTransaction(Transaction* transaction, bool success);
// Invoked when there is a change in a member transaction's priority or a
// member transaction is removed.
void UpdatePriority();
// Returns true if this object is empty.
bool IsEmpty() const { return all_writers_.empty(); }
// Invoked during HttpCache's destruction.
void Clear() { all_writers_.clear(); }
// Returns true if |transaction| is part of writers.
bool HasTransaction(const Transaction* transaction) const {
return all_writers_.count(const_cast<Transaction*>(transaction)) > 0;
}
// Returns true if more writers can be added for shared writing. Also fills in
// the |reason| for why a transaction cannot be added.
bool CanAddWriters(ParallelWritingPattern* reason);
// Returns if only one transaction can be a member of writers.
bool IsExclusive() const { return is_exclusive_; }
// Returns the network transaction which may be nullptr for range requests.
const HttpTransaction* network_transaction() const {
return network_transaction_.get();
}
void CloseConnectionOnDestruction();
// Returns the load state of the |network_transaction_| if present else
// returns LOAD_STATE_IDLE.
LoadState GetLoadState() const;
// Sets the network transaction argument to |network_transaction_|. Must be
// invoked before Read can be invoked.
void SetNetworkTransaction(
Transaction* transaction,
std::unique_ptr<HttpTransaction> network_transaction);
// Resets the network transaction to nullptr. Required for range requests as
// they might use the current network transaction only for part of the
// request. Must only be invoked for range requests.
void ResetNetworkTransaction();
// Returns if response is only being read from the network.
bool network_read_only() const { return network_read_only_; }
int GetTransactionsCount() const { return all_writers_.size(); }
private:
friend class WritersTest;
enum class State {
UNSET,
NONE,
NETWORK_READ,
NETWORK_READ_COMPLETE,
CACHE_WRITE_DATA,
CACHE_WRITE_DATA_COMPLETE,
};
// These transactions are waiting on Read. After the active transaction
// completes writing the data to the cache, their buffer would be filled with
// the data and their callback will be invoked.
struct WaitingForRead {
scoped_refptr<IOBuffer> read_buf;
int read_buf_len;
int write_len;
CompletionOnceCallback callback;
WaitingForRead(scoped_refptr<IOBuffer> read_buf,
int len,
CompletionOnceCallback consumer_callback);
~WaitingForRead();
WaitingForRead(WaitingForRead&&);
};
using WaitingForReadMap = std::map<Transaction*, WaitingForRead>;
using TransactionMap = std::map<Transaction*, TransactionInfo>;
// Runs the state transition loop. Resets and calls |callback_| on exit,
// unless the return value is ERR_IO_PENDING.
int DoLoop(int result);
// State machine functions.
int DoNetworkRead();
int DoNetworkReadComplete(int result);
int DoCacheWriteData(int num_bytes);
int DoCacheWriteDataComplete(int result);
// Helper functions for callback.
void OnNetworkReadFailure(int result);
void OnCacheWriteFailure();
void OnDataReceived(int result);
// Completes any pending IO_PENDING read operations by copying any received
// bytes from read_buf_ to the given buffer and posts a task to run the
// callback with |result|.
void CompleteWaitingForReadTransactions(int result);
// Removes idle writers, passing |result| which is to be used for any
// subsequent read transaction.
void RemoveIdleWriters(int result);
// Invoked when |active_transaction_| fails to read from network or write to
// cache. |error| indicates network read error code or cache write error.
void ProcessFailure(int error);
// Returns true if |this| only contains idle writers. Idle writers are those
// that are waiting for Read to be invoked by the consumer.
bool ContainsOnlyIdleWriters() const;
// Returns true if its worth marking the entry as truncated.
// TODO(shivanisha): Refactor this so that it could be const.
bool ShouldTruncate();
// Enqueues a truncation operation to the entry. Ignores the response.
void TruncateEntry();
// Remove the transaction.
void EraseTransaction(Transaction* transaction, int result);
TransactionMap::iterator EraseTransaction(TransactionMap::iterator it,
int result);
void SetCacheCallback(bool success, const TransactionSet& make_readers);
// IO Completion callback function.
void OnIOComplete(int result);
State next_state_ = State::NONE;
// True if only reading from network and not writing to cache.
bool network_read_only_ = false;
HttpCache* cache_ = nullptr;
// Owner of |this|.
ActiveEntry* entry_ = nullptr;
std::unique_ptr<HttpTransaction> network_transaction_ = nullptr;
scoped_refptr<IOBuffer> read_buf_ = nullptr;
int io_buf_len_ = 0;
int write_len_ = 0;
// The cache transaction that is the current consumer of network_transaction_
// ::Read or writing to the entry and is waiting for the operation to be
// completed. This is used to ensure there is at most one consumer of
// network_transaction_ at a time.
Transaction* active_transaction_ = nullptr;
// Transactions whose consumers have invoked Read, but another transaction is
// currently the |active_transaction_|. After the network read and cache write
// is complete, the waiting transactions will be notified.
WaitingForReadMap waiting_for_read_;
// Includes all transactions. ResetStateForEmptyWriters should be invoked
// whenever all_writers_ becomes empty.
TransactionMap all_writers_;
// True if multiple transactions are not allowed e.g. for partial requests.
bool is_exclusive_ = false;
ParallelWritingPattern parallel_writing_pattern_ = PARALLEL_WRITING_NONE;
// Current priority of the request. It is always the maximum of all the writer
// transactions.
RequestPriority priority_ = MINIMUM_PRIORITY;
// Response info of the most recent transaction added to Writers will be used
// to write back the headers along with the truncated bit set. This is done so
// that we don't overwrite headers written by a more recent transaction with
// older headers while truncating.
HttpResponseInfo response_info_truncation_;
// Do not mark a partial request as truncated if it is not already a truncated
// entry to start with.
bool partial_do_not_truncate_ = false;
// True if the entry should be kept, even if the response was not completely
// written.
bool should_keep_entry_ = true;
CompletionOnceCallback callback_; // Callback for active_transaction_.
// Since cache_ can destroy |this|, |cache_callback_| is only invoked at the
// end of DoLoop().
base::OnceClosure cache_callback_; // Callback for cache_.
base::WeakPtrFactory<Writers> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(Writers);
};
} // namespace net
#endif // NET_HTTP_HTTP_CACHE_WRITERS_H_