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 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 // Calls back the transaction with the result of the operation. | 97 // Calls back the transaction with the result of the operation. |
98 void NotifyTransaction(int result, ActiveEntry* entry) { | 98 void NotifyTransaction(int result, ActiveEntry* entry) { |
99 // TODO(rvargas): convert to DCHECK after fixing bug 47895. | 99 // TODO(rvargas): convert to DCHECK after fixing bug 47895. |
100 CHECK(!entry || entry->disk_entry); | 100 CHECK(!entry || entry->disk_entry); |
101 if (entry_) | 101 if (entry_) |
102 *entry_ = entry; | 102 *entry_ = entry; |
103 if (trans_) | 103 if (trans_) |
104 trans_->io_callback()->Run(result); | 104 trans_->io_callback()->Run(result); |
105 } | 105 } |
106 | 106 |
107 // Notifies the caller about the operation completion. | 107 // Notifies the caller about the operation completion. Returns true if the |
108 void DoCallback(int result, disk_cache::Backend* backend) { | 108 // callback was invoked. |
| 109 bool DoCallback(int result, disk_cache::Backend* backend) { |
109 if (backend_) | 110 if (backend_) |
110 *backend_ = backend; | 111 *backend_ = backend; |
111 if (callback_) | 112 if (callback_) { |
112 callback_->Run(result); | 113 callback_->Run(result); |
| 114 return true; |
| 115 } |
| 116 return false; |
113 } | 117 } |
114 | 118 |
115 WorkItemOperation operation() { return operation_; } | 119 WorkItemOperation operation() { return operation_; } |
116 void ClearTransaction() { trans_ = NULL; } | 120 void ClearTransaction() { trans_ = NULL; } |
117 void ClearEntry() { entry_ = NULL; } | 121 void ClearEntry() { entry_ = NULL; } |
118 void ClearCallback() { callback_ = NULL; } | 122 void ClearCallback() { callback_ = NULL; } |
119 bool Matches(Transaction* trans) const { return trans == trans_; } | 123 bool Matches(Transaction* trans) const { return trans == trans_; } |
120 bool IsValid() const { return trans_ || entry_ || callback_; } | 124 bool IsValid() const { return trans_ || entry_ || callback_; } |
121 | 125 |
122 private: | 126 private: |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
290 for (; pending_it != pending_ops_.end(); ++pending_it) { | 294 for (; pending_it != pending_ops_.end(); ++pending_it) { |
291 // We are not notifying the transactions about the cache going away, even | 295 // We are not notifying the transactions about the cache going away, even |
292 // though they are waiting for a callback that will never fire. | 296 // though they are waiting for a callback that will never fire. |
293 PendingOp* pending_op = pending_it->second; | 297 PendingOp* pending_op = pending_it->second; |
294 delete pending_op->writer; | 298 delete pending_op->writer; |
295 if (building_backend_) { | 299 if (building_backend_) { |
296 // If we don't have a backend, when its construction finishes it will | 300 // If we don't have a backend, when its construction finishes it will |
297 // deliver the callbacks. | 301 // deliver the callbacks. |
298 BackendCallback* callback = | 302 BackendCallback* callback = |
299 static_cast<BackendCallback*>(pending_op->callback); | 303 static_cast<BackendCallback*>(pending_op->callback); |
300 callback->Cancel(); | 304 if (callback) |
| 305 callback->Cancel(); |
301 } else { | 306 } else { |
302 delete pending_op->callback; | 307 delete pending_op->callback; |
303 } | 308 } |
304 | 309 |
305 STLDeleteElements(&pending_op->pending_queue); | 310 STLDeleteElements(&pending_op->pending_queue); |
306 delete pending_op; | 311 delete pending_op; |
307 } | 312 } |
308 } | 313 } |
309 | 314 |
310 int HttpCache::GetBackend(disk_cache::Backend** backend, | 315 int HttpCache::GetBackend(disk_cache::Backend** backend, |
(...skipping 689 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1000 } | 1005 } |
1001 } | 1006 } |
1002 } | 1007 } |
1003 } | 1008 } |
1004 | 1009 |
1005 void HttpCache::OnBackendCreated(int result, PendingOp* pending_op) { | 1010 void HttpCache::OnBackendCreated(int result, PendingOp* pending_op) { |
1006 scoped_ptr<WorkItem> item(pending_op->writer); | 1011 scoped_ptr<WorkItem> item(pending_op->writer); |
1007 WorkItemOperation op = item->operation(); | 1012 WorkItemOperation op = item->operation(); |
1008 DCHECK_EQ(WI_CREATE_BACKEND, op); | 1013 DCHECK_EQ(WI_CREATE_BACKEND, op); |
1009 | 1014 |
1010 backend_factory_.reset(); // Reclaim memory. | 1015 // We don't need the callback anymore. |
| 1016 pending_op->callback = NULL; |
1011 | 1017 |
1012 if (result == OK) | 1018 if (backend_factory_.get()) { |
1013 disk_cache_.reset(temp_backend_); | 1019 // We may end up calling OnBackendCreated multiple times if we have pending |
| 1020 // work items. The first call saves the backend and releases the factory, |
| 1021 // and the last call clears building_backend_. |
| 1022 backend_factory_.reset(); // Reclaim memory. |
| 1023 if (result == OK) |
| 1024 disk_cache_.reset(temp_backend_); |
| 1025 } |
1014 | 1026 |
1015 item->DoCallback(result, temp_backend_); | 1027 if (!pending_op->pending_queue.empty()) { |
1016 | 1028 WorkItem* pending_item = pending_op->pending_queue.front(); |
1017 // Notify all callers and delete all pending work items. | |
1018 while (!pending_op->pending_queue.empty()) { | |
1019 scoped_ptr<WorkItem> pending_item(pending_op->pending_queue.front()); | |
1020 pending_op->pending_queue.pop_front(); | 1029 pending_op->pending_queue.pop_front(); |
1021 DCHECK_EQ(WI_CREATE_BACKEND, pending_item->operation()); | 1030 DCHECK_EQ(WI_CREATE_BACKEND, pending_item->operation()); |
1022 | 1031 |
1023 // This could be an external caller or a transaction waiting on Start(). | 1032 // We want to process a single callback at a time, because the cache may |
1024 pending_item->DoCallback(result, temp_backend_); | 1033 // go away from the callback. |
1025 pending_item->NotifyTransaction(result, NULL); | 1034 pending_op->writer = pending_item; |
| 1035 |
| 1036 MessageLoop::current()->PostTask( |
| 1037 FROM_HERE, |
| 1038 task_factory_.NewRunnableMethod(&HttpCache::OnBackendCreated, |
| 1039 result, pending_op)); |
| 1040 } else { |
| 1041 building_backend_ = false; |
| 1042 DeletePendingOp(pending_op); |
1026 } | 1043 } |
1027 | 1044 |
1028 DeletePendingOp(pending_op); | 1045 // The cache may be gone when we return from the callback. |
1029 building_backend_ = false; | 1046 if (!item->DoCallback(result, temp_backend_)) |
| 1047 item->NotifyTransaction(result, NULL); |
1030 } | 1048 } |
1031 | 1049 |
1032 } // namespace net | 1050 } // namespace net |
OLD | NEW |