Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(67)

Side by Side Diff: net/http/http_cache.cc

Issue 3195017: Http cache: Make sure that the memory used to receive the... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 10 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/http/http_cache.h ('k') | net/http/http_cache_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/http/http_cache.h" 5 #include "net/http/http_cache.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
10 10
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 disk_entry->Close(); 56 disk_entry->Close();
57 disk_entry = NULL; 57 disk_entry = NULL;
58 } 58 }
59 } 59 }
60 60
61 //----------------------------------------------------------------------------- 61 //-----------------------------------------------------------------------------
62 62
63 // This structure keeps track of work items that are attempting to create or 63 // This structure keeps track of work items that are attempting to create or
64 // open cache entries or the backend itself. 64 // open cache entries or the backend itself.
65 struct HttpCache::PendingOp { 65 struct HttpCache::PendingOp {
66 PendingOp() : disk_entry(NULL), writer(NULL), callback(NULL) {} 66 PendingOp() : disk_entry(NULL), backend(NULL), writer(NULL), callback(NULL) {}
67 ~PendingOp() {} 67 ~PendingOp() {}
68 68
69 disk_cache::Entry* disk_entry; 69 disk_cache::Entry* disk_entry;
70 disk_cache::Backend* backend;
70 WorkItem* writer; 71 WorkItem* writer;
71 CompletionCallback* callback; // BackendCallback. 72 CompletionCallback* callback; // BackendCallback.
72 WorkItemList pending_queue; 73 WorkItemList pending_queue;
73 }; 74 };
74 75
75 //----------------------------------------------------------------------------- 76 //-----------------------------------------------------------------------------
76 77
77 // The type of operation represented by a work item. 78 // The type of operation represented by a work item.
78 enum WorkItemOperation { 79 enum WorkItemOperation {
79 WI_CREATE_BACKEND, 80 WI_CREATE_BACKEND,
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 137
137 // This class is a specialized type of CompletionCallback that allows us to 138 // This class is a specialized type of CompletionCallback that allows us to
138 // pass multiple arguments to the completion routine. 139 // pass multiple arguments to the completion routine.
139 class HttpCache::BackendCallback : public CallbackRunner<Tuple1<int> > { 140 class HttpCache::BackendCallback : public CallbackRunner<Tuple1<int> > {
140 public: 141 public:
141 BackendCallback(HttpCache* cache, PendingOp* pending_op) 142 BackendCallback(HttpCache* cache, PendingOp* pending_op)
142 : cache_(cache), pending_op_(pending_op) {} 143 : cache_(cache), pending_op_(pending_op) {}
143 ~BackendCallback() {} 144 ~BackendCallback() {}
144 145
145 virtual void RunWithParams(const Tuple1<int>& params) { 146 virtual void RunWithParams(const Tuple1<int>& params) {
146 if (cache_) 147 if (cache_) {
147 cache_->OnIOComplete(params.a, pending_op_); 148 cache_->OnIOComplete(params.a, pending_op_);
149 } else {
150 // The callback was cancelled so we should delete the pending_op that
151 // was used with this callback.
152 delete pending_op_;
153 }
148 delete this; 154 delete this;
149 } 155 }
150 156
151 void Cancel() { 157 void Cancel() {
152 cache_ = NULL; 158 cache_ = NULL;
153 } 159 }
154 160
155 private: 161 private:
156 HttpCache* cache_; 162 HttpCache* cache_;
157 PendingOp* pending_op_; 163 PendingOp* pending_op_;
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 242
237 //----------------------------------------------------------------------------- 243 //-----------------------------------------------------------------------------
238 244
239 HttpCache::HttpCache(HostResolver* host_resolver, ProxyService* proxy_service, 245 HttpCache::HttpCache(HostResolver* host_resolver, ProxyService* proxy_service,
240 SSLConfigService* ssl_config_service, 246 SSLConfigService* ssl_config_service,
241 HttpAuthHandlerFactory* http_auth_handler_factory, 247 HttpAuthHandlerFactory* http_auth_handler_factory,
242 HttpNetworkDelegate* network_delegate, 248 HttpNetworkDelegate* network_delegate,
243 NetLog* net_log, 249 NetLog* net_log,
244 BackendFactory* backend_factory) 250 BackendFactory* backend_factory)
245 : backend_factory_(backend_factory), 251 : backend_factory_(backend_factory),
246 temp_backend_(NULL),
247 building_backend_(false), 252 building_backend_(false),
248 mode_(NORMAL), 253 mode_(NORMAL),
249 network_layer_(HttpNetworkLayer::CreateFactory(host_resolver, 254 network_layer_(HttpNetworkLayer::CreateFactory(host_resolver,
250 proxy_service, ssl_config_service, http_auth_handler_factory, 255 proxy_service, ssl_config_service, http_auth_handler_factory,
251 network_delegate, net_log)), 256 network_delegate, net_log)),
252 ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)), 257 ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)),
253 enable_range_support_(true) { 258 enable_range_support_(true) {
254 } 259 }
255 260
256 HttpCache::HttpCache(HttpNetworkSession* session, 261 HttpCache::HttpCache(HttpNetworkSession* session,
257 BackendFactory* backend_factory) 262 BackendFactory* backend_factory)
258 : backend_factory_(backend_factory), 263 : backend_factory_(backend_factory),
259 temp_backend_(NULL),
260 building_backend_(false), 264 building_backend_(false),
261 mode_(NORMAL), 265 mode_(NORMAL),
262 network_layer_(HttpNetworkLayer::CreateFactory(session)), 266 network_layer_(HttpNetworkLayer::CreateFactory(session)),
263 ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)), 267 ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)),
264 enable_range_support_(true) { 268 enable_range_support_(true) {
265 } 269 }
266 270
267 HttpCache::HttpCache(HttpTransactionFactory* network_layer, 271 HttpCache::HttpCache(HttpTransactionFactory* network_layer,
268 BackendFactory* backend_factory) 272 BackendFactory* backend_factory)
269 : backend_factory_(backend_factory), 273 : backend_factory_(backend_factory),
270 temp_backend_(NULL),
271 building_backend_(false), 274 building_backend_(false),
272 mode_(NORMAL), 275 mode_(NORMAL),
273 network_layer_(network_layer), 276 network_layer_(network_layer),
274 ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)), 277 ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)),
275 enable_range_support_(true) { 278 enable_range_support_(true) {
276 } 279 }
277 280
278 HttpCache::~HttpCache() { 281 HttpCache::~HttpCache() {
279 // If we have any active entries remaining, then we need to deactivate them. 282 // If we have any active entries remaining, then we need to deactivate them.
280 // We may have some pending calls to OnProcessPendingQueue, but since those 283 // We may have some pending calls to OnProcessPendingQueue, but since those
281 // won't run (due to our destruction), we can simply ignore the corresponding 284 // won't run (due to our destruction), we can simply ignore the corresponding
282 // will_process_pending_queue flag. 285 // will_process_pending_queue flag.
283 while (!active_entries_.empty()) { 286 while (!active_entries_.empty()) {
284 ActiveEntry* entry = active_entries_.begin()->second; 287 ActiveEntry* entry = active_entries_.begin()->second;
285 entry->will_process_pending_queue = false; 288 entry->will_process_pending_queue = false;
286 entry->pending_queue.clear(); 289 entry->pending_queue.clear();
287 entry->readers.clear(); 290 entry->readers.clear();
288 entry->writer = NULL; 291 entry->writer = NULL;
289 DeactivateEntry(entry); 292 DeactivateEntry(entry);
290 } 293 }
291 294
292 STLDeleteElements(&doomed_entries_); 295 STLDeleteElements(&doomed_entries_);
293 296
294 PendingOpsMap::iterator pending_it = pending_ops_.begin(); 297 PendingOpsMap::iterator pending_it = pending_ops_.begin();
295 for (; pending_it != pending_ops_.end(); ++pending_it) { 298 for (; pending_it != pending_ops_.end(); ++pending_it) {
296 // We are not notifying the transactions about the cache going away, even 299 // We are not notifying the transactions about the cache going away, even
297 // though they are waiting for a callback that will never fire. 300 // though they are waiting for a callback that will never fire.
298 PendingOp* pending_op = pending_it->second; 301 PendingOp* pending_op = pending_it->second;
299 delete pending_op->writer; 302 delete pending_op->writer;
303 bool delete_pending_op = true;
300 if (building_backend_) { 304 if (building_backend_) {
301 // If we don't have a backend, when its construction finishes it will 305 // If we don't have a backend, when its construction finishes it will
302 // deliver the callbacks. 306 // deliver the callbacks.
303 BackendCallback* callback = 307 BackendCallback* callback =
304 static_cast<BackendCallback*>(pending_op->callback); 308 static_cast<BackendCallback*>(pending_op->callback);
305 if (callback) 309 if (callback) {
310 // The callback will delete the pending operation.
306 callback->Cancel(); 311 callback->Cancel();
312 delete_pending_op = false;
313 }
307 } else { 314 } else {
308 delete pending_op->callback; 315 delete pending_op->callback;
309 } 316 }
310 317
311 STLDeleteElements(&pending_op->pending_queue); 318 STLDeleteElements(&pending_op->pending_queue);
312 delete pending_op; 319 if (delete_pending_op)
320 delete pending_op;
313 } 321 }
314 } 322 }
315 323
316 int HttpCache::GetBackend(disk_cache::Backend** backend, 324 int HttpCache::GetBackend(disk_cache::Backend** backend,
317 CompletionCallback* callback) { 325 CompletionCallback* callback) {
318 DCHECK(callback != NULL); 326 DCHECK(callback != NULL);
319 327
320 if (disk_cache_.get()) { 328 if (disk_cache_.get()) {
321 *backend = disk_cache_.get(); 329 *backend = disk_cache_.get();
322 return OK; 330 return OK;
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
410 pending_op->pending_queue.push_back(item.release()); 418 pending_op->pending_queue.push_back(item.release());
411 return ERR_IO_PENDING; 419 return ERR_IO_PENDING;
412 } 420 }
413 421
414 DCHECK(pending_op->pending_queue.empty()); 422 DCHECK(pending_op->pending_queue.empty());
415 423
416 pending_op->writer = item.release(); 424 pending_op->writer = item.release();
417 BackendCallback* my_callback = new BackendCallback(this, pending_op); 425 BackendCallback* my_callback = new BackendCallback(this, pending_op);
418 pending_op->callback = my_callback; 426 pending_op->callback = my_callback;
419 427
420 int rv = backend_factory_->CreateBackend(&temp_backend_, my_callback); 428 int rv = backend_factory_->CreateBackend(&pending_op->backend, my_callback);
421 if (rv != ERR_IO_PENDING) { 429 if (rv != ERR_IO_PENDING) {
422 pending_op->writer->ClearCallback(); 430 pending_op->writer->ClearCallback();
423 my_callback->Run(rv); 431 my_callback->Run(rv);
424 } 432 }
425 433
426 return rv; 434 return rv;
427 } 435 }
428 436
429 int HttpCache::GetBackendForTransaction(Transaction* trans) { 437 int HttpCache::GetBackendForTransaction(Transaction* trans) {
430 if (disk_cache_.get()) 438 if (disk_cache_.get())
(...skipping 578 matching lines...) Expand 10 before | Expand all | Expand 10 after
1009 } 1017 }
1010 } 1018 }
1011 1019
1012 void HttpCache::OnBackendCreated(int result, PendingOp* pending_op) { 1020 void HttpCache::OnBackendCreated(int result, PendingOp* pending_op) {
1013 scoped_ptr<WorkItem> item(pending_op->writer); 1021 scoped_ptr<WorkItem> item(pending_op->writer);
1014 WorkItemOperation op = item->operation(); 1022 WorkItemOperation op = item->operation();
1015 DCHECK_EQ(WI_CREATE_BACKEND, op); 1023 DCHECK_EQ(WI_CREATE_BACKEND, op);
1016 1024
1017 // We don't need the callback anymore. 1025 // We don't need the callback anymore.
1018 pending_op->callback = NULL; 1026 pending_op->callback = NULL;
1027 disk_cache::Backend* backend = pending_op->backend;
1019 1028
1020 if (backend_factory_.get()) { 1029 if (backend_factory_.get()) {
1021 // We may end up calling OnBackendCreated multiple times if we have pending 1030 // We may end up calling OnBackendCreated multiple times if we have pending
1022 // work items. The first call saves the backend and releases the factory, 1031 // work items. The first call saves the backend and releases the factory,
1023 // and the last call clears building_backend_. 1032 // and the last call clears building_backend_.
1024 backend_factory_.reset(); // Reclaim memory. 1033 backend_factory_.reset(); // Reclaim memory.
1025 if (result == OK) 1034 if (result == OK)
1026 disk_cache_.reset(temp_backend_); 1035 disk_cache_.reset(backend);
1027 } 1036 }
1028 1037
1029 if (!pending_op->pending_queue.empty()) { 1038 if (!pending_op->pending_queue.empty()) {
1030 WorkItem* pending_item = pending_op->pending_queue.front(); 1039 WorkItem* pending_item = pending_op->pending_queue.front();
1031 pending_op->pending_queue.pop_front(); 1040 pending_op->pending_queue.pop_front();
1032 DCHECK_EQ(WI_CREATE_BACKEND, pending_item->operation()); 1041 DCHECK_EQ(WI_CREATE_BACKEND, pending_item->operation());
1033 1042
1034 // We want to process a single callback at a time, because the cache may 1043 // We want to process a single callback at a time, because the cache may
1035 // go away from the callback. 1044 // go away from the callback.
1036 pending_op->writer = pending_item; 1045 pending_op->writer = pending_item;
1037 1046
1038 MessageLoop::current()->PostTask( 1047 MessageLoop::current()->PostTask(
1039 FROM_HERE, 1048 FROM_HERE,
1040 task_factory_.NewRunnableMethod(&HttpCache::OnBackendCreated, 1049 task_factory_.NewRunnableMethod(&HttpCache::OnBackendCreated,
1041 result, pending_op)); 1050 result, pending_op));
1042 } else { 1051 } else {
1043 building_backend_ = false; 1052 building_backend_ = false;
1044 DeletePendingOp(pending_op); 1053 DeletePendingOp(pending_op);
1045 } 1054 }
1046 1055
1047 // The cache may be gone when we return from the callback. 1056 // The cache may be gone when we return from the callback.
1048 if (!item->DoCallback(result, temp_backend_)) 1057 if (!item->DoCallback(result, backend))
1049 item->NotifyTransaction(result, NULL); 1058 item->NotifyTransaction(result, NULL);
1050 } 1059 }
1051 1060
1052 } // namespace net 1061 } // namespace net
OLDNEW
« no previous file with comments | « net/http/http_cache.h ('k') | net/http/http_cache_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698