Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "net/disk_cache/simple/simple_entry_impl.h" | |
| 6 | |
| 7 #include "base/bind.h" | |
| 8 #include "base/bind_helpers.h" | |
| 9 #include "base/callback.h" | |
| 10 #include "base/location.h" | |
| 11 #include "base/message_loop_proxy.h" | |
| 12 #include "base/threading/worker_pool.h" | |
| 13 #include "net/base/io_buffer.h" | |
| 14 #include "net/base/net_errors.h" | |
| 15 #include "net/disk_cache/simple/simple_synchronous_entry.h" | |
| 16 | |
| 17 | |
| 18 namespace { | |
| 19 | |
| 20 typedef disk_cache::Entry::CompletionCallback CompletionCallback; | |
| 21 typedef disk_cache::SimpleSynchronousEntry::SynchronousEntryCallback | |
| 22 SynchronousEntryCallback; | |
| 23 | |
| 24 } // namespace | |
| 25 | |
| 26 namespace disk_cache { | |
| 27 | |
| 28 using base::FilePath; | |
| 29 using base::MessageLoopProxy; | |
| 30 using base::Time; | |
| 31 using base::WeakPtr; | |
| 32 using base::WorkerPool; | |
| 33 | |
| 34 // A PendingOperation represents an operation on a SynchronousEntry while it is | |
| 35 // in flight. It informs the owning SimpleEntryImpl of IO completion if | |
| 36 // necessary, as well as calling the IO completion callback. | |
| 37 class SimpleEntryImpl::PendingOperation { | |
|
pasko-google - do not use
2013/02/11 13:59:25
maybe a PendingEntryOperation would be a better na
gavinp
2013/02/11 17:55:50
Done.
| |
| 38 public: | |
| 39 static SynchronousEntryCallback Create( | |
| 40 const WeakPtr<SimpleEntryImpl>& entry, | |
| 41 const CompletionCallback& completion_callback); | |
| 42 | |
| 43 private: | |
| 44 PendingOperation(const WeakPtr<SimpleEntryImpl>& entry, | |
| 45 const CompletionCallback& completion_callback); | |
| 46 | |
| 47 void OnIOComplete(SimpleSynchronousEntry* sync_entry, int result); | |
| 48 | |
| 49 WeakPtr<SimpleEntryImpl> entry_; | |
| 50 CompletionCallback completion_callback_; | |
| 51 }; | |
| 52 | |
| 53 // A PendingCreationOperation represents a pending operation that is creating a | |
| 54 // new SimpleSynchronousEntry, such as OpenEntry() or CreateEntry(). It ensures | |
| 55 // that a SimpleEntryImpl is only created after the underlying synchronous | |
| 56 // operation has succeeded. | |
| 57 class SimpleEntryImpl::PendingCreationOperation { | |
| 58 public: | |
| 59 static SynchronousEntryCallback Create( | |
| 60 const CompletionCallback& completion_callback, | |
| 61 Entry** out_entry); | |
| 62 | |
| 63 private: | |
| 64 PendingCreationOperation(const CompletionCallback& completion_callback, | |
| 65 Entry** out_entry); | |
| 66 | |
| 67 void OnIOComplete(SimpleSynchronousEntry* sync_entry, int result); | |
| 68 | |
| 69 CompletionCallback completion_callback_; | |
| 70 Entry** out_entry_; | |
| 71 }; | |
| 72 | |
| 73 // static | |
| 74 SynchronousEntryCallback SimpleEntryImpl::PendingOperation::Create( | |
| 75 const WeakPtr<SimpleEntryImpl>& entry, | |
| 76 const CompletionCallback& completion_callback) { | |
| 77 PendingOperation* operation = new PendingOperation(entry, | |
| 78 completion_callback); | |
| 79 DCHECK(operation); | |
| 80 return base::Bind(&PendingOperation::OnIOComplete, base::Owned(operation)); | |
| 81 } | |
| 82 | |
| 83 SimpleEntryImpl::PendingOperation::PendingOperation( | |
| 84 const WeakPtr<SimpleEntryImpl>& entry, | |
| 85 const CompletionCallback& completion_callback) | |
| 86 : entry_(entry), | |
| 87 completion_callback_(completion_callback) { | |
| 88 } | |
| 89 | |
| 90 void SimpleEntryImpl::PendingOperation::OnIOComplete( | |
| 91 SimpleSynchronousEntry* sync_entry, | |
| 92 int result) { | |
| 93 DCHECK(sync_entry); | |
| 94 if (entry_) | |
| 95 entry_->SetSynchronousEntry(sync_entry); | |
| 96 completion_callback_.Run(result); | |
| 97 } | |
| 98 | |
| 99 // static | |
| 100 SynchronousEntryCallback SimpleEntryImpl::PendingCreationOperation::Create( | |
| 101 const CompletionCallback& completion_callback, | |
| 102 Entry** out_entry) { | |
| 103 PendingCreationOperation* operation = | |
| 104 new PendingCreationOperation(completion_callback, out_entry); | |
| 105 DCHECK(operation); | |
| 106 return base::Bind(&PendingCreationOperation::OnIOComplete, | |
| 107 base::Owned(operation)); | |
| 108 } | |
| 109 | |
| 110 SimpleEntryImpl::PendingCreationOperation::PendingCreationOperation( | |
| 111 const CompletionCallback& completion_callback, | |
| 112 Entry** out_entry) : completion_callback_(completion_callback), | |
| 113 out_entry_(out_entry) { | |
| 114 } | |
| 115 | |
| 116 void SimpleEntryImpl::PendingCreationOperation::OnIOComplete( | |
| 117 SimpleSynchronousEntry* sync_entry, | |
| 118 int result) { | |
| 119 DCHECK_NE(net::ERR_IO_PENDING, result); | |
| 120 | |
| 121 if (result != net::OK) { | |
| 122 DCHECK(!sync_entry) << "sync_entry = " << sync_entry; | |
| 123 completion_callback_.Run(result); | |
| 124 return; | |
| 125 } | |
| 126 DCHECK(sync_entry); | |
| 127 *out_entry_ = new SimpleEntryImpl(sync_entry); | |
| 128 DCHECK(*out_entry_); | |
| 129 completion_callback_.Run(net::OK); | |
| 130 } | |
| 131 | |
| 132 // static | |
| 133 int SimpleEntryImpl::OpenEntry(const FilePath& path, | |
| 134 const std::string& key, | |
| 135 Entry** entry, | |
| 136 const CompletionCallback& callback) { | |
| 137 SynchronousEntryCallback sync_entry_callback = | |
| 138 PendingCreationOperation::Create(callback, entry); | |
| 139 | |
| 140 WorkerPool::PostTask(FROM_HERE, | |
| 141 base::Bind(&SimpleSynchronousEntry::OpenEntry, path, key, | |
| 142 MessageLoopProxy::current(), | |
| 143 sync_entry_callback), | |
| 144 true); | |
| 145 return net::ERR_IO_PENDING; | |
| 146 } | |
| 147 | |
| 148 // static | |
| 149 int SimpleEntryImpl::CreateEntry(const FilePath& path, | |
| 150 const std::string& key, | |
| 151 Entry** entry, | |
| 152 const CompletionCallback& callback) { | |
| 153 SynchronousEntryCallback sync_entry_callback = | |
| 154 PendingCreationOperation::Create(callback, entry); | |
| 155 WorkerPool::PostTask(FROM_HERE, | |
| 156 base::Bind(&SimpleSynchronousEntry::CreateEntry, path, | |
| 157 key, MessageLoopProxy::current(), | |
| 158 sync_entry_callback), | |
| 159 true); | |
| 160 return net::ERR_IO_PENDING; | |
| 161 } | |
| 162 | |
| 163 // static | |
| 164 int SimpleEntryImpl::DoomEntry(const FilePath& path, | |
| 165 const std::string& key, | |
| 166 const CompletionCallback& callback) { | |
| 167 WorkerPool::PostTask(FROM_HERE, | |
| 168 base::Bind(&SimpleSynchronousEntry::DoomEntry, path, key, | |
| 169 MessageLoopProxy::current(), callback), | |
| 170 true); | |
| 171 return net::ERR_IO_PENDING; | |
| 172 } | |
| 173 | |
| 174 void SimpleEntryImpl::Doom() { | |
| 175 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 176 WorkerPool::PostTask(FROM_HERE, | |
| 177 base::Bind(&SimpleSynchronousEntry::DoomAndClose, | |
| 178 base::Unretained(ReleaseSynchronousEntry())), | |
| 179 true); | |
| 180 has_been_doomed_ = true; | |
| 181 } | |
| 182 | |
| 183 void SimpleEntryImpl::Close() { | |
| 184 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 185 if (!has_been_doomed_) { | |
| 186 WorkerPool::PostTask(FROM_HERE, | |
| 187 base::Bind(&SimpleSynchronousEntry::Close, | |
| 188 base::Unretained( | |
| 189 ReleaseSynchronousEntry())), | |
| 190 true); | |
| 191 } | |
| 192 // Entry::Close() is expected to release this entry. See disk_cache.h for | |
| 193 // details. | |
| 194 delete this; | |
| 195 } | |
| 196 | |
| 197 std::string SimpleEntryImpl::GetKey() const { | |
| 198 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 199 return key_; | |
| 200 } | |
| 201 | |
| 202 Time SimpleEntryImpl::GetLastUsed() const { | |
| 203 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 204 DCHECK(synchronous_entry_); | |
| 205 return synchronous_entry_->last_used(); | |
|
pasko-google - do not use
2013/02/11 13:59:25
is there a hidden assumption that last used cannot
gavinp
2013/02/11 17:55:50
Hopefully. The reads will change a bit once checks
| |
| 206 } | |
| 207 | |
| 208 Time SimpleEntryImpl::GetLastModified() const { | |
| 209 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 210 DCHECK(synchronous_entry_); | |
| 211 return synchronous_entry_->last_modified(); | |
| 212 } | |
| 213 | |
| 214 int32 SimpleEntryImpl::GetDataSize(int index) const { | |
| 215 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 216 DCHECK(synchronous_entry_); | |
| 217 return synchronous_entry_->data_size(index); | |
| 218 } | |
| 219 | |
| 220 int SimpleEntryImpl::ReadData(int index, | |
| 221 int offset, | |
| 222 net::IOBuffer* buf, | |
| 223 int buf_len, | |
| 224 const CompletionCallback& callback) { | |
| 225 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 226 // TODO(gavinp): Add support for overlapping reads. The net::HttpCache does | |
| 227 // make overlapping read requests when multiple transactions access the same | |
| 228 // entry as read only. | |
|
pasko-google - do not use
2013/02/11 13:59:25
does it happen often? on what occasion?
gavinp
2013/02/11 17:55:50
Yes, if for instance a page uses google served jQu
| |
| 229 DCHECK(synchronous_entry_); | |
| 230 SynchronousEntryCallback sync_entry_callback = | |
| 231 PendingOperation::Create(weak_ptr_factory_.GetWeakPtr(), callback); | |
| 232 WorkerPool::PostTask(FROM_HERE, | |
| 233 base::Bind(&SimpleSynchronousEntry::ReadData, | |
| 234 base::Unretained(ReleaseSynchronousEntry()), | |
| 235 index, offset, scoped_refptr<IOBuffer>(buf), | |
| 236 buf_len, sync_entry_callback), | |
| 237 true); | |
| 238 return net::ERR_IO_PENDING; | |
| 239 } | |
| 240 | |
| 241 int SimpleEntryImpl::WriteData(int index, | |
| 242 int offset, | |
| 243 net::IOBuffer* buf, | |
| 244 int buf_len, | |
| 245 const CompletionCallback& callback, | |
| 246 bool truncate) { | |
| 247 for (int i = 0; i < buf_len; ++i) { | |
| 248 char c ALLOW_UNUSED = buf->data()[i]; | |
|
pasko-google - do not use
2013/02/11 13:59:25
It is hard to believe that this will be optimized
gavinp
2013/02/11 17:55:50
That is debugging code that made it into this uplo
| |
| 249 } | |
| 250 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 251 DCHECK(synchronous_entry_); | |
| 252 SynchronousEntryCallback sync_entry_callback = | |
| 253 PendingOperation::Create(weak_ptr_factory_.GetWeakPtr(), callback); | |
| 254 WorkerPool::PostTask(FROM_HERE, | |
| 255 base::Bind(&SimpleSynchronousEntry::WriteData, | |
| 256 base::Unretained(ReleaseSynchronousEntry()), | |
| 257 index, offset, scoped_refptr<IOBuffer>(buf), | |
| 258 buf_len, sync_entry_callback, truncate), | |
| 259 true); | |
| 260 return net::ERR_IO_PENDING; | |
| 261 } | |
| 262 | |
| 263 int SimpleEntryImpl::ReadSparseData(int64 offset, | |
| 264 net::IOBuffer* buf, | |
| 265 int buf_len, | |
| 266 const CompletionCallback& callback) { | |
| 267 // TODO(gavinp): Determine if the simple backend should support sparse data. | |
| 268 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 269 return net::ERR_FAILED; | |
| 270 } | |
| 271 | |
| 272 int SimpleEntryImpl::WriteSparseData(int64 offset, | |
| 273 net::IOBuffer* buf, | |
| 274 int buf_len, | |
| 275 const CompletionCallback& callback) { | |
| 276 // TODO(gavinp): Determine if the simple backend should support sparse data. | |
| 277 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 278 return net::ERR_FAILED; | |
| 279 } | |
| 280 | |
| 281 int SimpleEntryImpl::GetAvailableRange(int64 offset, | |
| 282 int len, | |
| 283 int64* start, | |
| 284 const CompletionCallback& callback) { | |
| 285 // TODO(gavinp): Determine if the simple backend should support sparse data. | |
| 286 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 287 return net::ERR_FAILED; | |
| 288 } | |
| 289 | |
| 290 bool SimpleEntryImpl::CouldBeSparse() const { | |
| 291 // TODO(gavinp): Determine if the simple backend should support sparse data. | |
| 292 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 293 return false; | |
| 294 } | |
| 295 | |
| 296 void SimpleEntryImpl::CancelSparseIO() { | |
| 297 // TODO(gavinp): Determine if the simple backend should support sparse data. | |
| 298 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 299 } | |
| 300 | |
| 301 int SimpleEntryImpl::ReadyForSparseIO(const CompletionCallback& callback) { | |
| 302 // TODO(gavinp): Determine if the simple backend should support sparse data. | |
| 303 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 304 return net::ERR_FAILED; | |
| 305 } | |
| 306 | |
| 307 SimpleEntryImpl::SimpleEntryImpl( | |
| 308 SimpleSynchronousEntry* synchronous_entry) | |
| 309 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), | |
| 310 key_(synchronous_entry->key()), | |
| 311 synchronous_entry_(synchronous_entry), | |
| 312 has_been_doomed_(false) { | |
| 313 DCHECK(synchronous_entry); | |
| 314 } | |
| 315 | |
| 316 SimpleEntryImpl::~SimpleEntryImpl() { | |
| 317 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 318 DCHECK(!synchronous_entry_) << "synchronous_entry_ = " << synchronous_entry_; | |
| 319 } | |
| 320 | |
| 321 SimpleSynchronousEntry* SimpleEntryImpl::ReleaseSynchronousEntry() { | |
| 322 DCHECK(synchronous_entry_); | |
| 323 SimpleSynchronousEntry* retval = synchronous_entry_; | |
| 324 synchronous_entry_ = NULL; | |
| 325 return retval; | |
| 326 } | |
| 327 | |
| 328 void SimpleEntryImpl::SetSynchronousEntry( | |
| 329 SimpleSynchronousEntry* synchronous_entry) { | |
| 330 DCHECK(!synchronous_entry_) << "synchronous_entry_ = " << synchronous_entry_; | |
| 331 synchronous_entry_ = synchronous_entry; | |
| 332 } | |
| 333 | |
| 334 } // namespace disk_cache | |
| OLD | NEW |