OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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/disk_cache/simple/simple_backend_impl.h" | 5 #include "net/disk_cache/simple/simple_backend_impl.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cstdlib> | 8 #include <cstdlib> |
9 #include <functional> | 9 #include <functional> |
10 | 10 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
66 if (!g_sequenced_worker_pool) { | 66 if (!g_sequenced_worker_pool) { |
67 int max_worker_threads = kDefaultMaxWorkerThreads; | 67 int max_worker_threads = kDefaultMaxWorkerThreads; |
68 | 68 |
69 const std::string thread_count_field_trial = | 69 const std::string thread_count_field_trial = |
70 base::FieldTrialList::FindFullName("SimpleCacheMaxThreads"); | 70 base::FieldTrialList::FindFullName("SimpleCacheMaxThreads"); |
71 if (!thread_count_field_trial.empty()) { | 71 if (!thread_count_field_trial.empty()) { |
72 max_worker_threads = | 72 max_worker_threads = |
73 std::max(1, std::atoi(thread_count_field_trial.c_str())); | 73 std::max(1, std::atoi(thread_count_field_trial.c_str())); |
74 } | 74 } |
75 | 75 |
76 g_sequenced_worker_pool = new SequencedWorkerPool(max_worker_threads, | 76 g_sequenced_worker_pool = |
77 kThreadNamePrefix); | 77 new SequencedWorkerPool(max_worker_threads, kThreadNamePrefix); |
78 g_sequenced_worker_pool->AddRef(); // Leak it. | 78 g_sequenced_worker_pool->AddRef(); // Leak it. |
79 } | 79 } |
80 } | 80 } |
81 | 81 |
82 bool g_fd_limit_histogram_has_been_populated = false; | 82 bool g_fd_limit_histogram_has_been_populated = false; |
83 | 83 |
84 void MaybeHistogramFdLimit(net::CacheType cache_type) { | 84 void MaybeHistogramFdLimit(net::CacheType cache_type) { |
85 if (g_fd_limit_histogram_has_been_populated) | 85 if (g_fd_limit_histogram_has_been_populated) |
86 return; | 86 return; |
87 | 87 |
88 // Used in histograms; add new entries at end. | 88 // Used in histograms; add new entries at end. |
89 enum FdLimitStatus { | 89 enum FdLimitStatus { |
90 FD_LIMIT_STATUS_UNSUPPORTED = 0, | 90 FD_LIMIT_STATUS_UNSUPPORTED = 0, |
91 FD_LIMIT_STATUS_FAILED = 1, | 91 FD_LIMIT_STATUS_FAILED = 1, |
92 FD_LIMIT_STATUS_SUCCEEDED = 2, | 92 FD_LIMIT_STATUS_SUCCEEDED = 2, |
93 FD_LIMIT_STATUS_MAX = 3 | 93 FD_LIMIT_STATUS_MAX = 3 |
94 }; | 94 }; |
95 FdLimitStatus fd_limit_status = FD_LIMIT_STATUS_UNSUPPORTED; | 95 FdLimitStatus fd_limit_status = FD_LIMIT_STATUS_UNSUPPORTED; |
96 int soft_fd_limit = 0; | 96 int soft_fd_limit = 0; |
97 int hard_fd_limit = 0; | 97 int hard_fd_limit = 0; |
98 | 98 |
99 #if defined(OS_POSIX) | 99 #if defined(OS_POSIX) |
100 struct rlimit nofile; | 100 struct rlimit nofile; |
101 if (!getrlimit(RLIMIT_NOFILE, &nofile)) { | 101 if (!getrlimit(RLIMIT_NOFILE, &nofile)) { |
102 soft_fd_limit = nofile.rlim_cur; | 102 soft_fd_limit = nofile.rlim_cur; |
103 hard_fd_limit = nofile.rlim_max; | 103 hard_fd_limit = nofile.rlim_max; |
104 fd_limit_status = FD_LIMIT_STATUS_SUCCEEDED; | 104 fd_limit_status = FD_LIMIT_STATUS_SUCCEEDED; |
105 } else { | 105 } else { |
106 fd_limit_status = FD_LIMIT_STATUS_FAILED; | 106 fd_limit_status = FD_LIMIT_STATUS_FAILED; |
107 } | 107 } |
108 #endif | 108 #endif |
109 | 109 |
110 SIMPLE_CACHE_UMA(ENUMERATION, | 110 SIMPLE_CACHE_UMA(ENUMERATION, |
111 "FileDescriptorLimitStatus", cache_type, | 111 "FileDescriptorLimitStatus", |
112 fd_limit_status, FD_LIMIT_STATUS_MAX); | 112 cache_type, |
| 113 fd_limit_status, |
| 114 FD_LIMIT_STATUS_MAX); |
113 if (fd_limit_status == FD_LIMIT_STATUS_SUCCEEDED) { | 115 if (fd_limit_status == FD_LIMIT_STATUS_SUCCEEDED) { |
114 SIMPLE_CACHE_UMA(SPARSE_SLOWLY, | 116 SIMPLE_CACHE_UMA( |
115 "FileDescriptorLimitSoft", cache_type, soft_fd_limit); | 117 SPARSE_SLOWLY, "FileDescriptorLimitSoft", cache_type, soft_fd_limit); |
116 SIMPLE_CACHE_UMA(SPARSE_SLOWLY, | 118 SIMPLE_CACHE_UMA( |
117 "FileDescriptorLimitHard", cache_type, hard_fd_limit); | 119 SPARSE_SLOWLY, "FileDescriptorLimitHard", cache_type, hard_fd_limit); |
118 } | 120 } |
119 | 121 |
120 g_fd_limit_histogram_has_been_populated = true; | 122 g_fd_limit_histogram_has_been_populated = true; |
121 } | 123 } |
122 | 124 |
123 // Detects if the files in the cache directory match the current disk cache | 125 // Detects if the files in the cache directory match the current disk cache |
124 // backend type and version. If the directory contains no cache, occupies it | 126 // backend type and version. If the directory contains no cache, occupies it |
125 // with the fresh structure. | 127 // with the fresh structure. |
126 bool FileStructureConsistent(const base::FilePath& path) { | 128 bool FileStructureConsistent(const base::FilePath& path) { |
127 if (!base::PathExists(path) && !base::CreateDirectory(path)) { | 129 if (!base::PathExists(path) && !base::CreateDirectory(path)) { |
128 LOG(ERROR) << "Failed to create directory: " << path.LossyDisplayName(); | 130 LOG(ERROR) << "Failed to create directory: " << path.LossyDisplayName(); |
129 return false; | 131 return false; |
130 } | 132 } |
131 return disk_cache::UpgradeSimpleCacheOnDisk(path); | 133 return disk_cache::UpgradeSimpleCacheOnDisk(path); |
132 } | 134 } |
133 | 135 |
134 // A context used by a BarrierCompletionCallback to track state. | 136 // A context used by a BarrierCompletionCallback to track state. |
135 struct BarrierContext { | 137 struct BarrierContext { |
136 BarrierContext(int expected) | 138 BarrierContext(int expected) |
137 : expected(expected), | 139 : expected(expected), count(0), had_error(false) {} |
138 count(0), | |
139 had_error(false) {} | |
140 | 140 |
141 const int expected; | 141 const int expected; |
142 int count; | 142 int count; |
143 bool had_error; | 143 bool had_error; |
144 }; | 144 }; |
145 | 145 |
146 void BarrierCompletionCallbackImpl( | 146 void BarrierCompletionCallbackImpl( |
147 BarrierContext* context, | 147 BarrierContext* context, |
148 const net::CompletionCallback& final_callback, | 148 const net::CompletionCallback& final_callback, |
149 int result) { | 149 int result) { |
(...skipping 11 matching lines...) Expand all Loading... |
161 } | 161 } |
162 | 162 |
163 // A barrier completion callback is a net::CompletionCallback that waits for | 163 // A barrier completion callback is a net::CompletionCallback that waits for |
164 // |count| successful results before invoking |final_callback|. In the case of | 164 // |count| successful results before invoking |final_callback|. In the case of |
165 // an error, the first error is passed to |final_callback| and all others | 165 // an error, the first error is passed to |final_callback| and all others |
166 // are ignored. | 166 // are ignored. |
167 net::CompletionCallback MakeBarrierCompletionCallback( | 167 net::CompletionCallback MakeBarrierCompletionCallback( |
168 int count, | 168 int count, |
169 const net::CompletionCallback& final_callback) { | 169 const net::CompletionCallback& final_callback) { |
170 BarrierContext* context = new BarrierContext(count); | 170 BarrierContext* context = new BarrierContext(count); |
171 return base::Bind(&BarrierCompletionCallbackImpl, | 171 return base::Bind( |
172 base::Owned(context), final_callback); | 172 &BarrierCompletionCallbackImpl, base::Owned(context), final_callback); |
173 } | 173 } |
174 | 174 |
175 // A short bindable thunk that ensures a completion callback is always called | 175 // A short bindable thunk that ensures a completion callback is always called |
176 // after running an operation asynchronously. | 176 // after running an operation asynchronously. |
177 void RunOperationAndCallback( | 177 void RunOperationAndCallback( |
178 const Callback<int(const net::CompletionCallback&)>& operation, | 178 const Callback<int(const net::CompletionCallback&)>& operation, |
179 const net::CompletionCallback& operation_callback) { | 179 const net::CompletionCallback& operation_callback) { |
180 const int operation_result = operation.Run(operation_callback); | 180 const int operation_result = operation.Run(operation_callback); |
181 if (operation_result != net::ERR_IO_PENDING) | 181 if (operation_result != net::ERR_IO_PENDING) |
182 operation_callback.Run(operation_result); | 182 operation_callback.Run(operation_result); |
183 } | 183 } |
184 | 184 |
185 void RecordIndexLoad(net::CacheType cache_type, | 185 void RecordIndexLoad(net::CacheType cache_type, |
186 base::TimeTicks constructed_since, | 186 base::TimeTicks constructed_since, |
187 int result) { | 187 int result) { |
188 const base::TimeDelta creation_to_index = base::TimeTicks::Now() - | 188 const base::TimeDelta creation_to_index = |
189 constructed_since; | 189 base::TimeTicks::Now() - constructed_since; |
190 if (result == net::OK) { | 190 if (result == net::OK) { |
191 SIMPLE_CACHE_UMA(TIMES, "CreationToIndex", cache_type, creation_to_index); | 191 SIMPLE_CACHE_UMA(TIMES, "CreationToIndex", cache_type, creation_to_index); |
192 } else { | 192 } else { |
193 SIMPLE_CACHE_UMA(TIMES, | 193 SIMPLE_CACHE_UMA( |
194 "CreationToIndexFail", cache_type, creation_to_index); | 194 TIMES, "CreationToIndexFail", cache_type, creation_to_index); |
195 } | 195 } |
196 } | 196 } |
197 | 197 |
198 } // namespace | 198 } // namespace |
199 | 199 |
200 SimpleBackendImpl::SimpleBackendImpl(const FilePath& path, | 200 SimpleBackendImpl::SimpleBackendImpl(const FilePath& path, |
201 int max_bytes, | 201 int max_bytes, |
202 net::CacheType cache_type, | 202 net::CacheType cache_type, |
203 base::SingleThreadTaskRunner* cache_thread, | 203 base::SingleThreadTaskRunner* cache_thread, |
204 net::NetLog* net_log) | 204 net::NetLog* net_log) |
205 : path_(path), | 205 : path_(path), |
206 cache_type_(cache_type), | 206 cache_type_(cache_type), |
207 cache_thread_(cache_thread), | 207 cache_thread_(cache_thread), |
208 orig_max_size_(max_bytes), | 208 orig_max_size_(max_bytes), |
209 entry_operations_mode_( | 209 entry_operations_mode_(cache_type == net::DISK_CACHE |
210 cache_type == net::DISK_CACHE ? | 210 ? SimpleEntryImpl::OPTIMISTIC_OPERATIONS |
211 SimpleEntryImpl::OPTIMISTIC_OPERATIONS : | 211 : SimpleEntryImpl::NON_OPTIMISTIC_OPERATIONS), |
212 SimpleEntryImpl::NON_OPTIMISTIC_OPERATIONS), | |
213 net_log_(net_log) { | 212 net_log_(net_log) { |
214 MaybeHistogramFdLimit(cache_type_); | 213 MaybeHistogramFdLimit(cache_type_); |
215 } | 214 } |
216 | 215 |
217 SimpleBackendImpl::~SimpleBackendImpl() { | 216 SimpleBackendImpl::~SimpleBackendImpl() { |
218 index_->WriteToDisk(); | 217 index_->WriteToDisk(); |
219 } | 218 } |
220 | 219 |
221 int SimpleBackendImpl::Init(const CompletionCallback& completion_callback) { | 220 int SimpleBackendImpl::Init(const CompletionCallback& completion_callback) { |
222 MaybeCreateSequencedWorkerPool(); | 221 MaybeCreateSequencedWorkerPool(); |
223 | 222 |
224 worker_pool_ = g_sequenced_worker_pool->GetTaskRunnerWithShutdownBehavior( | 223 worker_pool_ = g_sequenced_worker_pool->GetTaskRunnerWithShutdownBehavior( |
225 SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); | 224 SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); |
226 | 225 |
227 index_.reset(new SimpleIndex(MessageLoopProxy::current(), this, cache_type_, | 226 index_.reset(new SimpleIndex( |
228 make_scoped_ptr(new SimpleIndexFile( | 227 MessageLoopProxy::current(), |
229 cache_thread_.get(), worker_pool_.get(), | 228 this, |
230 cache_type_, path_)))); | 229 cache_type_, |
| 230 make_scoped_ptr(new SimpleIndexFile( |
| 231 cache_thread_.get(), worker_pool_.get(), cache_type_, path_)))); |
231 index_->ExecuteWhenReady( | 232 index_->ExecuteWhenReady( |
232 base::Bind(&RecordIndexLoad, cache_type_, base::TimeTicks::Now())); | 233 base::Bind(&RecordIndexLoad, cache_type_, base::TimeTicks::Now())); |
233 | 234 |
234 PostTaskAndReplyWithResult( | 235 PostTaskAndReplyWithResult( |
235 cache_thread_, | 236 cache_thread_, |
236 FROM_HERE, | 237 FROM_HERE, |
237 base::Bind(&SimpleBackendImpl::InitCacheStructureOnDisk, path_, | 238 base::Bind( |
238 orig_max_size_), | 239 &SimpleBackendImpl::InitCacheStructureOnDisk, path_, orig_max_size_), |
239 base::Bind(&SimpleBackendImpl::InitializeIndex, AsWeakPtr(), | 240 base::Bind(&SimpleBackendImpl::InitializeIndex, |
| 241 AsWeakPtr(), |
240 completion_callback)); | 242 completion_callback)); |
241 return net::ERR_IO_PENDING; | 243 return net::ERR_IO_PENDING; |
242 } | 244 } |
243 | 245 |
244 bool SimpleBackendImpl::SetMaxSize(int max_bytes) { | 246 bool SimpleBackendImpl::SetMaxSize(int max_bytes) { |
245 orig_max_size_ = max_bytes; | 247 orig_max_size_ = max_bytes; |
246 return index_->SetMaxSize(max_bytes); | 248 return index_->SetMaxSize(max_bytes); |
247 } | 249 } |
248 | 250 |
249 int SimpleBackendImpl::GetMaxFileSize() const { | 251 int SimpleBackendImpl::GetMaxFileSize() const { |
(...skipping 13 matching lines...) Expand all Loading... |
263 | 265 |
264 void SimpleBackendImpl::OnDoomComplete(uint64 entry_hash) { | 266 void SimpleBackendImpl::OnDoomComplete(uint64 entry_hash) { |
265 // TODO(ttuttle): Revert to DCHECK once http://crbug.com/317138 is fixed. | 267 // TODO(ttuttle): Revert to DCHECK once http://crbug.com/317138 is fixed. |
266 CHECK_EQ(1u, entries_pending_doom_.count(entry_hash)); | 268 CHECK_EQ(1u, entries_pending_doom_.count(entry_hash)); |
267 base::hash_map<uint64, std::vector<Closure> >::iterator it = | 269 base::hash_map<uint64, std::vector<Closure> >::iterator it = |
268 entries_pending_doom_.find(entry_hash); | 270 entries_pending_doom_.find(entry_hash); |
269 std::vector<Closure> to_run_closures; | 271 std::vector<Closure> to_run_closures; |
270 to_run_closures.swap(it->second); | 272 to_run_closures.swap(it->second); |
271 entries_pending_doom_.erase(it); | 273 entries_pending_doom_.erase(it); |
272 | 274 |
273 std::for_each(to_run_closures.begin(), to_run_closures.end(), | 275 std::for_each(to_run_closures.begin(), |
| 276 to_run_closures.end(), |
274 std::mem_fun_ref(&Closure::Run)); | 277 std::mem_fun_ref(&Closure::Run)); |
275 } | 278 } |
276 | 279 |
277 void SimpleBackendImpl::DoomEntries(std::vector<uint64>* entry_hashes, | 280 void SimpleBackendImpl::DoomEntries(std::vector<uint64>* entry_hashes, |
278 const net::CompletionCallback& callback) { | 281 const net::CompletionCallback& callback) { |
279 scoped_ptr<std::vector<uint64> > | 282 scoped_ptr<std::vector<uint64> > mass_doom_entry_hashes( |
280 mass_doom_entry_hashes(new std::vector<uint64>()); | 283 new std::vector<uint64>()); |
281 mass_doom_entry_hashes->swap(*entry_hashes); | 284 mass_doom_entry_hashes->swap(*entry_hashes); |
282 | 285 |
283 std::vector<uint64> to_doom_individually_hashes; | 286 std::vector<uint64> to_doom_individually_hashes; |
284 | 287 |
285 // For each of the entry hashes, there are two cases: | 288 // For each of the entry hashes, there are two cases: |
286 // 1. The entry is either open or pending doom, and so it should be doomed | 289 // 1. The entry is either open or pending doom, and so it should be doomed |
287 // individually to avoid flakes. | 290 // individually to avoid flakes. |
288 // 2. The entry is not in use at all, so we can call | 291 // 2. The entry is not in use at all, so we can call |
289 // SimpleSynchronousEntry::DoomEntrySet and delete the files en masse. | 292 // SimpleSynchronousEntry::DoomEntrySet and delete the files en masse. |
290 for (int i = mass_doom_entry_hashes->size() - 1; i >= 0; --i) { | 293 for (int i = mass_doom_entry_hashes->size() - 1; i >= 0; --i) { |
291 const uint64 entry_hash = (*mass_doom_entry_hashes)[i]; | 294 const uint64 entry_hash = (*mass_doom_entry_hashes)[i]; |
292 // TODO(ttuttle): Revert to DCHECK once http://crbug.com/317138 is fixed. | 295 // TODO(ttuttle): Revert to DCHECK once http://crbug.com/317138 is fixed. |
293 CHECK(active_entries_.count(entry_hash) == 0 || | 296 CHECK(active_entries_.count(entry_hash) == 0 || |
294 entries_pending_doom_.count(entry_hash) == 0) | 297 entries_pending_doom_.count(entry_hash) == 0) |
295 << "The entry 0x" << std::hex << entry_hash | 298 << "The entry 0x" << std::hex << entry_hash |
296 << " is both active and pending doom."; | 299 << " is both active and pending doom."; |
297 if (!active_entries_.count(entry_hash) && | 300 if (!active_entries_.count(entry_hash) && |
298 !entries_pending_doom_.count(entry_hash)) { | 301 !entries_pending_doom_.count(entry_hash)) { |
299 continue; | 302 continue; |
300 } | 303 } |
301 | 304 |
302 to_doom_individually_hashes.push_back(entry_hash); | 305 to_doom_individually_hashes.push_back(entry_hash); |
303 | 306 |
304 (*mass_doom_entry_hashes)[i] = mass_doom_entry_hashes->back(); | 307 (*mass_doom_entry_hashes)[i] = mass_doom_entry_hashes->back(); |
305 mass_doom_entry_hashes->resize(mass_doom_entry_hashes->size() - 1); | 308 mass_doom_entry_hashes->resize(mass_doom_entry_hashes->size() - 1); |
306 } | 309 } |
307 | 310 |
308 net::CompletionCallback barrier_callback = | 311 net::CompletionCallback barrier_callback = MakeBarrierCompletionCallback( |
309 MakeBarrierCompletionCallback(to_doom_individually_hashes.size() + 1, | 312 to_doom_individually_hashes.size() + 1, callback); |
310 callback); | |
311 for (std::vector<uint64>::const_iterator | 313 for (std::vector<uint64>::const_iterator |
312 it = to_doom_individually_hashes.begin(), | 314 it = to_doom_individually_hashes.begin(), |
313 end = to_doom_individually_hashes.end(); it != end; ++it) { | 315 end = to_doom_individually_hashes.end(); |
| 316 it != end; |
| 317 ++it) { |
314 const int doom_result = DoomEntryFromHash(*it, barrier_callback); | 318 const int doom_result = DoomEntryFromHash(*it, barrier_callback); |
315 // TODO(ttuttle): Revert to DCHECK once http://crbug.com/317138 is fixed. | 319 // TODO(ttuttle): Revert to DCHECK once http://crbug.com/317138 is fixed. |
316 CHECK_EQ(net::ERR_IO_PENDING, doom_result); | 320 CHECK_EQ(net::ERR_IO_PENDING, doom_result); |
317 index_->Remove(*it); | 321 index_->Remove(*it); |
318 } | 322 } |
319 | 323 |
320 for (std::vector<uint64>::const_iterator it = mass_doom_entry_hashes->begin(), | 324 for (std::vector<uint64>::const_iterator it = mass_doom_entry_hashes->begin(), |
321 end = mass_doom_entry_hashes->end(); | 325 end = mass_doom_entry_hashes->end(); |
322 it != end; ++it) { | 326 it != end; |
| 327 ++it) { |
323 index_->Remove(*it); | 328 index_->Remove(*it); |
324 OnDoomStart(*it); | 329 OnDoomStart(*it); |
325 } | 330 } |
326 | 331 |
327 // Taking this pointer here avoids undefined behaviour from calling | 332 // Taking this pointer here avoids undefined behaviour from calling |
328 // base::Passed before mass_doom_entry_hashes.get(). | 333 // base::Passed before mass_doom_entry_hashes.get(). |
329 std::vector<uint64>* mass_doom_entry_hashes_ptr = | 334 std::vector<uint64>* mass_doom_entry_hashes_ptr = |
330 mass_doom_entry_hashes.get(); | 335 mass_doom_entry_hashes.get(); |
331 PostTaskAndReplyWithResult( | 336 PostTaskAndReplyWithResult(worker_pool_, |
332 worker_pool_, FROM_HERE, | 337 FROM_HERE, |
333 base::Bind(&SimpleSynchronousEntry::DoomEntrySet, | 338 base::Bind(&SimpleSynchronousEntry::DoomEntrySet, |
334 mass_doom_entry_hashes_ptr, path_), | 339 mass_doom_entry_hashes_ptr, |
335 base::Bind(&SimpleBackendImpl::DoomEntriesComplete, | 340 path_), |
336 AsWeakPtr(), base::Passed(&mass_doom_entry_hashes), | 341 base::Bind(&SimpleBackendImpl::DoomEntriesComplete, |
337 barrier_callback)); | 342 AsWeakPtr(), |
| 343 base::Passed(&mass_doom_entry_hashes), |
| 344 barrier_callback)); |
338 } | 345 } |
339 | 346 |
340 net::CacheType SimpleBackendImpl::GetCacheType() const { | 347 net::CacheType SimpleBackendImpl::GetCacheType() const { |
341 return net::DISK_CACHE; | 348 return net::DISK_CACHE; |
342 } | 349 } |
343 | 350 |
344 int32 SimpleBackendImpl::GetEntryCount() const { | 351 int32 SimpleBackendImpl::GetEntryCount() const { |
345 // TODO(pasko): Use directory file count when index is not ready. | 352 // TODO(pasko): Use directory file count when index is not ready. |
346 return index_->GetEntryCount(); | 353 return index_->GetEntryCount(); |
347 } | 354 } |
348 | 355 |
349 int SimpleBackendImpl::OpenEntry(const std::string& key, | 356 int SimpleBackendImpl::OpenEntry(const std::string& key, |
350 Entry** entry, | 357 Entry** entry, |
351 const CompletionCallback& callback) { | 358 const CompletionCallback& callback) { |
352 const uint64 entry_hash = simple_util::GetEntryHashKey(key); | 359 const uint64 entry_hash = simple_util::GetEntryHashKey(key); |
353 | 360 |
354 // TODO(gavinp): Factor out this (not quite completely) repetitive code | 361 // TODO(gavinp): Factor out this (not quite completely) repetitive code |
355 // block from OpenEntry/CreateEntry/DoomEntry. | 362 // block from OpenEntry/CreateEntry/DoomEntry. |
356 base::hash_map<uint64, std::vector<Closure> >::iterator it = | 363 base::hash_map<uint64, std::vector<Closure> >::iterator it = |
357 entries_pending_doom_.find(entry_hash); | 364 entries_pending_doom_.find(entry_hash); |
358 if (it != entries_pending_doom_.end()) { | 365 if (it != entries_pending_doom_.end()) { |
359 Callback<int(const net::CompletionCallback&)> operation = | 366 Callback<int(const net::CompletionCallback&)> operation = base::Bind( |
360 base::Bind(&SimpleBackendImpl::OpenEntry, | 367 &SimpleBackendImpl::OpenEntry, base::Unretained(this), key, entry); |
361 base::Unretained(this), key, entry); | 368 it->second.push_back( |
362 it->second.push_back(base::Bind(&RunOperationAndCallback, | 369 base::Bind(&RunOperationAndCallback, operation, callback)); |
363 operation, callback)); | |
364 return net::ERR_IO_PENDING; | 370 return net::ERR_IO_PENDING; |
365 } | 371 } |
366 scoped_refptr<SimpleEntryImpl> simple_entry = | 372 scoped_refptr<SimpleEntryImpl> simple_entry = |
367 CreateOrFindActiveEntry(entry_hash, key); | 373 CreateOrFindActiveEntry(entry_hash, key); |
368 CompletionCallback backend_callback = | 374 CompletionCallback backend_callback = |
369 base::Bind(&SimpleBackendImpl::OnEntryOpenedFromKey, | 375 base::Bind(&SimpleBackendImpl::OnEntryOpenedFromKey, |
370 AsWeakPtr(), | 376 AsWeakPtr(), |
371 key, | 377 key, |
372 entry, | 378 entry, |
373 simple_entry, | 379 simple_entry, |
374 callback); | 380 callback); |
375 return simple_entry->OpenEntry(entry, backend_callback); | 381 return simple_entry->OpenEntry(entry, backend_callback); |
376 } | 382 } |
377 | 383 |
378 int SimpleBackendImpl::CreateEntry(const std::string& key, | 384 int SimpleBackendImpl::CreateEntry(const std::string& key, |
379 Entry** entry, | 385 Entry** entry, |
380 const CompletionCallback& callback) { | 386 const CompletionCallback& callback) { |
381 DCHECK_LT(0u, key.size()); | 387 DCHECK_LT(0u, key.size()); |
382 const uint64 entry_hash = simple_util::GetEntryHashKey(key); | 388 const uint64 entry_hash = simple_util::GetEntryHashKey(key); |
383 | 389 |
384 base::hash_map<uint64, std::vector<Closure> >::iterator it = | 390 base::hash_map<uint64, std::vector<Closure> >::iterator it = |
385 entries_pending_doom_.find(entry_hash); | 391 entries_pending_doom_.find(entry_hash); |
386 if (it != entries_pending_doom_.end()) { | 392 if (it != entries_pending_doom_.end()) { |
387 Callback<int(const net::CompletionCallback&)> operation = | 393 Callback<int(const net::CompletionCallback&)> operation = base::Bind( |
388 base::Bind(&SimpleBackendImpl::CreateEntry, | 394 &SimpleBackendImpl::CreateEntry, base::Unretained(this), key, entry); |
389 base::Unretained(this), key, entry); | 395 it->second.push_back( |
390 it->second.push_back(base::Bind(&RunOperationAndCallback, | 396 base::Bind(&RunOperationAndCallback, operation, callback)); |
391 operation, callback)); | |
392 return net::ERR_IO_PENDING; | 397 return net::ERR_IO_PENDING; |
393 } | 398 } |
394 scoped_refptr<SimpleEntryImpl> simple_entry = | 399 scoped_refptr<SimpleEntryImpl> simple_entry = |
395 CreateOrFindActiveEntry(entry_hash, key); | 400 CreateOrFindActiveEntry(entry_hash, key); |
396 return simple_entry->CreateEntry(entry, callback); | 401 return simple_entry->CreateEntry(entry, callback); |
397 } | 402 } |
398 | 403 |
399 int SimpleBackendImpl::DoomEntry(const std::string& key, | 404 int SimpleBackendImpl::DoomEntry(const std::string& key, |
400 const net::CompletionCallback& callback) { | 405 const net::CompletionCallback& callback) { |
401 const uint64 entry_hash = simple_util::GetEntryHashKey(key); | 406 const uint64 entry_hash = simple_util::GetEntryHashKey(key); |
402 | 407 |
403 base::hash_map<uint64, std::vector<Closure> >::iterator it = | 408 base::hash_map<uint64, std::vector<Closure> >::iterator it = |
404 entries_pending_doom_.find(entry_hash); | 409 entries_pending_doom_.find(entry_hash); |
405 if (it != entries_pending_doom_.end()) { | 410 if (it != entries_pending_doom_.end()) { |
406 Callback<int(const net::CompletionCallback&)> operation = | 411 Callback<int(const net::CompletionCallback&)> operation = |
407 base::Bind(&SimpleBackendImpl::DoomEntry, base::Unretained(this), key); | 412 base::Bind(&SimpleBackendImpl::DoomEntry, base::Unretained(this), key); |
408 it->second.push_back(base::Bind(&RunOperationAndCallback, | 413 it->second.push_back( |
409 operation, callback)); | 414 base::Bind(&RunOperationAndCallback, operation, callback)); |
410 return net::ERR_IO_PENDING; | 415 return net::ERR_IO_PENDING; |
411 } | 416 } |
412 scoped_refptr<SimpleEntryImpl> simple_entry = | 417 scoped_refptr<SimpleEntryImpl> simple_entry = |
413 CreateOrFindActiveEntry(entry_hash, key); | 418 CreateOrFindActiveEntry(entry_hash, key); |
414 return simple_entry->DoomEntry(callback); | 419 return simple_entry->DoomEntry(callback); |
415 } | 420 } |
416 | 421 |
417 int SimpleBackendImpl::DoomAllEntries(const CompletionCallback& callback) { | 422 int SimpleBackendImpl::DoomAllEntries(const CompletionCallback& callback) { |
418 return DoomEntriesBetween(Time(), Time(), callback); | 423 return DoomEntriesBetween(Time(), Time(), callback); |
419 } | 424 } |
420 | 425 |
421 void SimpleBackendImpl::IndexReadyForDoom(Time initial_time, | 426 void SimpleBackendImpl::IndexReadyForDoom(Time initial_time, |
422 Time end_time, | 427 Time end_time, |
423 const CompletionCallback& callback, | 428 const CompletionCallback& callback, |
424 int result) { | 429 int result) { |
425 if (result != net::OK) { | 430 if (result != net::OK) { |
426 callback.Run(result); | 431 callback.Run(result); |
427 return; | 432 return; |
428 } | 433 } |
429 scoped_ptr<std::vector<uint64> > removed_key_hashes( | 434 scoped_ptr<std::vector<uint64> > removed_key_hashes( |
430 index_->GetEntriesBetween(initial_time, end_time).release()); | 435 index_->GetEntriesBetween(initial_time, end_time).release()); |
431 DoomEntries(removed_key_hashes.get(), callback); | 436 DoomEntries(removed_key_hashes.get(), callback); |
432 } | 437 } |
433 | 438 |
434 int SimpleBackendImpl::DoomEntriesBetween( | 439 int SimpleBackendImpl::DoomEntriesBetween(const Time initial_time, |
435 const Time initial_time, | 440 const Time end_time, |
436 const Time end_time, | 441 const CompletionCallback& callback) { |
437 const CompletionCallback& callback) { | |
438 return index_->ExecuteWhenReady( | 442 return index_->ExecuteWhenReady( |
439 base::Bind(&SimpleBackendImpl::IndexReadyForDoom, AsWeakPtr(), | 443 base::Bind(&SimpleBackendImpl::IndexReadyForDoom, |
440 initial_time, end_time, callback)); | 444 AsWeakPtr(), |
| 445 initial_time, |
| 446 end_time, |
| 447 callback)); |
441 } | 448 } |
442 | 449 |
443 int SimpleBackendImpl::DoomEntriesSince( | 450 int SimpleBackendImpl::DoomEntriesSince(const Time initial_time, |
444 const Time initial_time, | 451 const CompletionCallback& callback) { |
445 const CompletionCallback& callback) { | |
446 return DoomEntriesBetween(initial_time, Time(), callback); | 452 return DoomEntriesBetween(initial_time, Time(), callback); |
447 } | 453 } |
448 | 454 |
449 int SimpleBackendImpl::OpenNextEntry(void** iter, | 455 int SimpleBackendImpl::OpenNextEntry(void** iter, |
450 Entry** next_entry, | 456 Entry** next_entry, |
451 const CompletionCallback& callback) { | 457 const CompletionCallback& callback) { |
452 CompletionCallback get_next_entry = | 458 CompletionCallback get_next_entry = |
453 base::Bind(&SimpleBackendImpl::GetNextEntryInIterator, AsWeakPtr(), iter, | 459 base::Bind(&SimpleBackendImpl::GetNextEntryInIterator, |
454 next_entry, callback); | 460 AsWeakPtr(), |
| 461 iter, |
| 462 next_entry, |
| 463 callback); |
455 return index_->ExecuteWhenReady(get_next_entry); | 464 return index_->ExecuteWhenReady(get_next_entry); |
456 } | 465 } |
457 | 466 |
458 void SimpleBackendImpl::EndEnumeration(void** iter) { | 467 void SimpleBackendImpl::EndEnumeration(void** iter) { |
459 SimpleIndex::HashList* entry_list = | 468 SimpleIndex::HashList* entry_list = |
460 static_cast<SimpleIndex::HashList*>(*iter); | 469 static_cast<SimpleIndex::HashList*>(*iter); |
461 delete entry_list; | 470 delete entry_list; |
462 *iter = NULL; | 471 *iter = NULL; |
463 } | 472 } |
464 | 473 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
503 } | 512 } |
504 DCHECK(result.max_size); | 513 DCHECK(result.max_size); |
505 } | 514 } |
506 return result; | 515 return result; |
507 } | 516 } |
508 | 517 |
509 scoped_refptr<SimpleEntryImpl> SimpleBackendImpl::CreateOrFindActiveEntry( | 518 scoped_refptr<SimpleEntryImpl> SimpleBackendImpl::CreateOrFindActiveEntry( |
510 const uint64 entry_hash, | 519 const uint64 entry_hash, |
511 const std::string& key) { | 520 const std::string& key) { |
512 DCHECK_EQ(entry_hash, simple_util::GetEntryHashKey(key)); | 521 DCHECK_EQ(entry_hash, simple_util::GetEntryHashKey(key)); |
513 std::pair<EntryMap::iterator, bool> insert_result = | 522 std::pair<EntryMap::iterator, bool> insert_result = active_entries_.insert( |
514 active_entries_.insert(std::make_pair(entry_hash, | 523 std::make_pair(entry_hash, base::WeakPtr<SimpleEntryImpl>())); |
515 base::WeakPtr<SimpleEntryImpl>())); | |
516 EntryMap::iterator& it = insert_result.first; | 524 EntryMap::iterator& it = insert_result.first; |
517 if (insert_result.second) | 525 if (insert_result.second) |
518 DCHECK(!it->second.get()); | 526 DCHECK(!it->second.get()); |
519 if (!it->second.get()) { | 527 if (!it->second.get()) { |
520 SimpleEntryImpl* entry = new SimpleEntryImpl( | 528 SimpleEntryImpl* entry = new SimpleEntryImpl( |
521 cache_type_, path_, entry_hash, entry_operations_mode_, this, net_log_); | 529 cache_type_, path_, entry_hash, entry_operations_mode_, this, net_log_); |
522 entry->SetKey(key); | 530 entry->SetKey(key); |
523 it->second = entry->AsWeakPtr(); | 531 it->second = entry->AsWeakPtr(); |
524 } | 532 } |
525 DCHECK(it->second.get()); | 533 DCHECK(it->second.get()); |
526 // It's possible, but unlikely, that we have an entry hash collision with a | 534 // It's possible, but unlikely, that we have an entry hash collision with a |
527 // currently active entry. | 535 // currently active entry. |
528 if (key != it->second->key()) { | 536 if (key != it->second->key()) { |
529 it->second->Doom(); | 537 it->second->Doom(); |
530 DCHECK_EQ(0U, active_entries_.count(entry_hash)); | 538 DCHECK_EQ(0U, active_entries_.count(entry_hash)); |
531 return CreateOrFindActiveEntry(entry_hash, key); | 539 return CreateOrFindActiveEntry(entry_hash, key); |
532 } | 540 } |
533 return make_scoped_refptr(it->second.get()); | 541 return make_scoped_refptr(it->second.get()); |
534 } | 542 } |
535 | 543 |
536 int SimpleBackendImpl::OpenEntryFromHash(uint64 entry_hash, | 544 int SimpleBackendImpl::OpenEntryFromHash(uint64 entry_hash, |
537 Entry** entry, | 545 Entry** entry, |
538 const CompletionCallback& callback) { | 546 const CompletionCallback& callback) { |
539 base::hash_map<uint64, std::vector<Closure> >::iterator it = | 547 base::hash_map<uint64, std::vector<Closure> >::iterator it = |
540 entries_pending_doom_.find(entry_hash); | 548 entries_pending_doom_.find(entry_hash); |
541 if (it != entries_pending_doom_.end()) { | 549 if (it != entries_pending_doom_.end()) { |
542 Callback<int(const net::CompletionCallback&)> operation = | 550 Callback<int(const net::CompletionCallback&)> operation = |
543 base::Bind(&SimpleBackendImpl::OpenEntryFromHash, | 551 base::Bind(&SimpleBackendImpl::OpenEntryFromHash, |
544 base::Unretained(this), entry_hash, entry); | 552 base::Unretained(this), |
545 it->second.push_back(base::Bind(&RunOperationAndCallback, | 553 entry_hash, |
546 operation, callback)); | 554 entry); |
| 555 it->second.push_back( |
| 556 base::Bind(&RunOperationAndCallback, operation, callback)); |
547 return net::ERR_IO_PENDING; | 557 return net::ERR_IO_PENDING; |
548 } | 558 } |
549 | 559 |
550 EntryMap::iterator has_active = active_entries_.find(entry_hash); | 560 EntryMap::iterator has_active = active_entries_.find(entry_hash); |
551 if (has_active != active_entries_.end()) { | 561 if (has_active != active_entries_.end()) { |
552 return OpenEntry(has_active->second->key(), entry, callback); | 562 return OpenEntry(has_active->second->key(), entry, callback); |
553 } | 563 } |
554 | 564 |
555 scoped_refptr<SimpleEntryImpl> simple_entry = new SimpleEntryImpl( | 565 scoped_refptr<SimpleEntryImpl> simple_entry = new SimpleEntryImpl( |
556 cache_type_, path_, entry_hash, entry_operations_mode_, this, net_log_); | 566 cache_type_, path_, entry_hash, entry_operations_mode_, this, net_log_); |
557 CompletionCallback backend_callback = | 567 CompletionCallback backend_callback = |
558 base::Bind(&SimpleBackendImpl::OnEntryOpenedFromHash, | 568 base::Bind(&SimpleBackendImpl::OnEntryOpenedFromHash, |
559 AsWeakPtr(), entry_hash, entry, simple_entry, callback); | 569 AsWeakPtr(), |
| 570 entry_hash, |
| 571 entry, |
| 572 simple_entry, |
| 573 callback); |
560 return simple_entry->OpenEntry(entry, backend_callback); | 574 return simple_entry->OpenEntry(entry, backend_callback); |
561 } | 575 } |
562 | 576 |
563 int SimpleBackendImpl::DoomEntryFromHash(uint64 entry_hash, | 577 int SimpleBackendImpl::DoomEntryFromHash(uint64 entry_hash, |
564 const CompletionCallback& callback) { | 578 const CompletionCallback& callback) { |
565 Entry** entry = new Entry*(); | 579 Entry** entry = new Entry*(); |
566 scoped_ptr<Entry*> scoped_entry(entry); | 580 scoped_ptr<Entry*> scoped_entry(entry); |
567 | 581 |
568 base::hash_map<uint64, std::vector<Closure> >::iterator pending_it = | 582 base::hash_map<uint64, std::vector<Closure> >::iterator pending_it = |
569 entries_pending_doom_.find(entry_hash); | 583 entries_pending_doom_.find(entry_hash); |
570 if (pending_it != entries_pending_doom_.end()) { | 584 if (pending_it != entries_pending_doom_.end()) { |
571 Callback<int(const net::CompletionCallback&)> operation = | 585 Callback<int(const net::CompletionCallback&)> operation = |
572 base::Bind(&SimpleBackendImpl::DoomEntryFromHash, | 586 base::Bind(&SimpleBackendImpl::DoomEntryFromHash, |
573 base::Unretained(this), entry_hash); | 587 base::Unretained(this), |
574 pending_it->second.push_back(base::Bind(&RunOperationAndCallback, | 588 entry_hash); |
575 operation, callback)); | 589 pending_it->second.push_back( |
| 590 base::Bind(&RunOperationAndCallback, operation, callback)); |
576 return net::ERR_IO_PENDING; | 591 return net::ERR_IO_PENDING; |
577 } | 592 } |
578 | 593 |
579 EntryMap::iterator active_it = active_entries_.find(entry_hash); | 594 EntryMap::iterator active_it = active_entries_.find(entry_hash); |
580 if (active_it != active_entries_.end()) | 595 if (active_it != active_entries_.end()) |
581 return active_it->second->DoomEntry(callback); | 596 return active_it->second->DoomEntry(callback); |
582 | 597 |
583 // There's no pending dooms, nor any open entry. We can make a trivial | 598 // There's no pending dooms, nor any open entry. We can make a trivial |
584 // call to DoomEntries() to delete this entry. | 599 // call to DoomEntries() to delete this entry. |
585 std::vector<uint64> entry_hash_vector; | 600 std::vector<uint64> entry_hash_vector; |
(...skipping 14 matching lines...) Expand all Loading... |
600 if (*iter == NULL) { | 615 if (*iter == NULL) { |
601 *iter = index()->GetAllHashes().release(); | 616 *iter = index()->GetAllHashes().release(); |
602 } | 617 } |
603 SimpleIndex::HashList* entry_list = | 618 SimpleIndex::HashList* entry_list = |
604 static_cast<SimpleIndex::HashList*>(*iter); | 619 static_cast<SimpleIndex::HashList*>(*iter); |
605 while (entry_list->size() > 0) { | 620 while (entry_list->size() > 0) { |
606 uint64 entry_hash = entry_list->back(); | 621 uint64 entry_hash = entry_list->back(); |
607 entry_list->pop_back(); | 622 entry_list->pop_back(); |
608 if (index()->Has(entry_hash)) { | 623 if (index()->Has(entry_hash)) { |
609 *next_entry = NULL; | 624 *next_entry = NULL; |
610 CompletionCallback continue_iteration = base::Bind( | 625 CompletionCallback continue_iteration = |
611 &SimpleBackendImpl::CheckIterationReturnValue, | 626 base::Bind(&SimpleBackendImpl::CheckIterationReturnValue, |
612 AsWeakPtr(), | 627 AsWeakPtr(), |
613 iter, | 628 iter, |
614 next_entry, | 629 next_entry, |
615 callback); | 630 callback); |
616 int error_code_open = OpenEntryFromHash(entry_hash, | 631 int error_code_open = |
617 next_entry, | 632 OpenEntryFromHash(entry_hash, next_entry, continue_iteration); |
618 continue_iteration); | |
619 if (error_code_open == net::ERR_IO_PENDING) | 633 if (error_code_open == net::ERR_IO_PENDING) |
620 return; | 634 return; |
621 if (error_code_open != net::ERR_FAILED) { | 635 if (error_code_open != net::ERR_FAILED) { |
622 callback.Run(error_code_open); | 636 callback.Run(error_code_open); |
623 return; | 637 return; |
624 } | 638 } |
625 } | 639 } |
626 } | 640 } |
627 callback.Run(net::ERR_FAILED); | 641 callback.Run(net::ERR_FAILED); |
628 } | 642 } |
629 | 643 |
630 void SimpleBackendImpl::OnEntryOpenedFromHash( | 644 void SimpleBackendImpl::OnEntryOpenedFromHash( |
631 uint64 hash, | 645 uint64 hash, |
632 Entry** entry, | 646 Entry** entry, |
633 scoped_refptr<SimpleEntryImpl> simple_entry, | 647 scoped_refptr<SimpleEntryImpl> simple_entry, |
634 const CompletionCallback& callback, | 648 const CompletionCallback& callback, |
635 int error_code) { | 649 int error_code) { |
636 if (error_code != net::OK) { | 650 if (error_code != net::OK) { |
637 callback.Run(error_code); | 651 callback.Run(error_code); |
638 return; | 652 return; |
639 } | 653 } |
640 DCHECK(*entry); | 654 DCHECK(*entry); |
641 std::pair<EntryMap::iterator, bool> insert_result = | 655 std::pair<EntryMap::iterator, bool> insert_result = active_entries_.insert( |
642 active_entries_.insert(std::make_pair(hash, | 656 std::make_pair(hash, base::WeakPtr<SimpleEntryImpl>())); |
643 base::WeakPtr<SimpleEntryImpl>())); | |
644 EntryMap::iterator& it = insert_result.first; | 657 EntryMap::iterator& it = insert_result.first; |
645 const bool did_insert = insert_result.second; | 658 const bool did_insert = insert_result.second; |
646 if (did_insert) { | 659 if (did_insert) { |
647 // There is no active entry corresponding to this hash. The entry created | 660 // There is no active entry corresponding to this hash. The entry created |
648 // is put in the map of active entries and returned to the caller. | 661 // is put in the map of active entries and returned to the caller. |
649 it->second = simple_entry->AsWeakPtr(); | 662 it->second = simple_entry->AsWeakPtr(); |
650 callback.Run(error_code); | 663 callback.Run(error_code); |
651 } else { | 664 } else { |
652 // The entry was made active with the key while the creation from hash | 665 // The entry was made active with the key while the creation from hash |
653 // occurred. The entry created from hash needs to be closed, and the one | 666 // occurred. The entry created from hash needs to be closed, and the one |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
690 return; | 703 return; |
691 } | 704 } |
692 callback.Run(error_code); | 705 callback.Run(error_code); |
693 } | 706 } |
694 | 707 |
695 void SimpleBackendImpl::DoomEntriesComplete( | 708 void SimpleBackendImpl::DoomEntriesComplete( |
696 scoped_ptr<std::vector<uint64> > entry_hashes, | 709 scoped_ptr<std::vector<uint64> > entry_hashes, |
697 const net::CompletionCallback& callback, | 710 const net::CompletionCallback& callback, |
698 int result) { | 711 int result) { |
699 std::for_each( | 712 std::for_each( |
700 entry_hashes->begin(), entry_hashes->end(), | 713 entry_hashes->begin(), |
701 std::bind1st(std::mem_fun(&SimpleBackendImpl::OnDoomComplete), | 714 entry_hashes->end(), |
702 this)); | 715 std::bind1st(std::mem_fun(&SimpleBackendImpl::OnDoomComplete), this)); |
703 callback.Run(result); | 716 callback.Run(result); |
704 } | 717 } |
705 | 718 |
706 void SimpleBackendImpl::FlushWorkerPoolForTesting() { | 719 void SimpleBackendImpl::FlushWorkerPoolForTesting() { |
707 if (g_sequenced_worker_pool) | 720 if (g_sequenced_worker_pool) |
708 g_sequenced_worker_pool->FlushForTesting(); | 721 g_sequenced_worker_pool->FlushForTesting(); |
709 } | 722 } |
710 | 723 |
711 } // namespace disk_cache | 724 } // namespace disk_cache |
OLD | NEW |