OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |