| 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 |