Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2016 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 "build/build_config.h" // For OS_POSIX | |
| 6 | |
| 7 #if defined(OS_POSIX) | |
| 8 #include <unistd.h> | |
| 9 #endif | |
| 10 | |
| 11 #include <algorithm> | |
| 12 #include <memory> | |
| 13 #include <utility> | |
| 14 #include "base/bind.h" | |
| 15 #include "base/callback_helpers.h" | |
| 16 #include "base/compiler_specific.h" | |
| 17 #include "base/format_macros.h" | |
| 18 #include "base/location.h" | |
| 19 #include "base/macros.h" | |
| 20 #include "base/single_thread_task_runner.h" | |
| 21 #include "net/http/http_cache_data_access.h" | |
| 22 #include "net/http/http_cache_shared_writers.h" | |
| 23 #include "net/http/http_cache_transaction.h" | |
| 24 | |
| 25 namespace net { | |
| 26 | |
| 27 HttpCache::SharedWriters::SharedWriters( | |
| 28 HttpCache* cache, | |
| 29 ActiveEntry* entry, | |
| 30 Transaction* cache_transaction, | |
| 31 RequestPriority priority, | |
| 32 std::unique_ptr<HttpTransaction> network_transaction) | |
| 33 : cache_(cache->GetWeakPtr()), | |
| 34 entry_(entry), | |
| 35 priority_(priority), | |
| 36 weak_factory_(this) { | |
| 37 cache_transaction->SetShared(); | |
| 38 all_writers_.insert(cache_transaction); | |
| 39 data_access_ = | |
| 40 base::MakeUnique<DataAccess>(std::move(network_transaction), entry); | |
| 41 io_callback_ = base::Bind(&HttpCache::SharedWriters::OnIOComplete, | |
| 42 weak_factory_.GetWeakPtr()); | |
| 43 } | |
| 44 | |
| 45 HttpCache::SharedWriters::~SharedWriters() {} | |
| 46 | |
| 47 bool HttpCache::SharedWriters::AddTransaction(Transaction* transaction) { | |
| 48 transaction->SetShared(); | |
| 49 | |
| 50 if (!validating_transaction_) { | |
| 51 validating_transaction_ = transaction; | |
|
Randy Smith (Not in Mondays)
2017/01/19 00:53:43
How hard would it be to move the validation work i
shivanisha
2017/01/19 21:13:06
Moving the validation work would mean moving the l
Randy Smith (Not in Mondays)
2017/01/20 19:54:31
Ok .... I can only repeat that this feels weird to
shivanisha
2017/01/25 19:46:13
I hear your concerns and that this means SW has an
shivanisha
2017/01/25 19:50:09
Other reviewers, any thoughts on this?
| |
| 52 return true; | |
| 53 } | |
| 54 | |
| 55 waiting_for_validation_.push_back(transaction); | |
| 56 return false; | |
| 57 } | |
| 58 | |
| 59 bool HttpCache::SharedWriters::empty() { | |
| 60 int count = all_writers_.size() + waiting_for_validation_.size() + | |
| 61 (validating_transaction_ ? 1 : 0); | |
| 62 return count ? false : true; | |
| 63 } | |
| 64 | |
| 65 int HttpCache::SharedWriters::DoLoop(int result) { | |
| 66 DCHECK(next_state_ != STATE_NONE); | |
| 67 | |
| 68 int rv = result; | |
| 69 | |
| 70 do { | |
| 71 State state = next_state_; | |
| 72 next_state_ = STATE_NONE; | |
| 73 switch (state) { | |
| 74 case STATE_NETWORK_READ: | |
| 75 DCHECK_EQ(OK, rv); | |
| 76 rv = DoNetworkRead(); | |
| 77 break; | |
| 78 case STATE_NETWORK_READ_COMPLETE: | |
| 79 rv = DoNetworkReadComplete(rv); | |
| 80 break; | |
| 81 case STATE_CACHE_WRITE_DATA: | |
| 82 rv = DoCacheWriteData(rv); | |
| 83 break; | |
| 84 case STATE_CACHE_WRITE_DATA_COMPLETE: | |
| 85 rv = DoCacheWriteDataComplete(rv); | |
| 86 break; | |
| 87 case STATE_CACHE_WRITE_TRUNCATED_RESPONSE: | |
| 88 rv = DoCacheWriteTruncatedResponse(); | |
| 89 break; | |
| 90 case STATE_CACHE_WRITE_TRUNCATED_RESPONSE_COMPLETE: | |
| 91 rv = DoCacheWriteTruncatedResponseComplete(rv); | |
| 92 break; | |
| 93 default: | |
| 94 NOTREACHED() << "bad state"; | |
| 95 rv = ERR_FAILED; | |
| 96 break; | |
| 97 } | |
| 98 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); | |
| 99 | |
| 100 if (rv != ERR_IO_PENDING && !callback_.is_null()) { | |
| 101 read_buf_ = NULL; // Release the buffer before invoking the callback. | |
| 102 base::ResetAndReturn(&callback_).Run(rv); | |
| 103 } | |
| 104 | |
| 105 return rv; | |
| 106 } | |
| 107 | |
| 108 int HttpCache::SharedWriters::Read(scoped_refptr<IOBuffer> buf, | |
| 109 int buf_len, | |
| 110 const CompletionCallback& callback, | |
| 111 Transaction* transaction, | |
| 112 bool* read_in_progress) { | |
| 113 DCHECK(buf); | |
| 114 DCHECK_GT(buf_len, 0); | |
| 115 DCHECK(!callback.is_null()); | |
| 116 | |
| 117 // If another transaction is already reading from the network, then this | |
| 118 // transaction waits for the read to complete and gets its buffer filled | |
| 119 // with the data returned from that read. | |
| 120 if (current_writer_) { | |
| 121 WaitingWriter waiting_writer(transaction, buf, buf_len); | |
| 122 waiting_writers_.push_back(waiting_writer); | |
| 123 *read_in_progress = true; | |
|
Randy Smith (Not in Mondays)
2017/01/19 00:53:43
So this strikes me as problematic API design--alon
shivanisha
2017/01/19 21:13:06
The difference in the design between the 2 cases i
Randy Smith (Not in Mondays)
2017/01/20 19:54:31
Let's talk this through in a VC--I'm having a lot
shivanisha
2017/01/25 19:46:13
Done. Discussed this with Randy over VC that it is
| |
| 124 return ERR_IO_PENDING; | |
| 125 } | |
| 126 | |
| 127 DCHECK_EQ(next_state_, STATE_NONE); | |
| 128 DCHECK(callback_.is_null()); | |
| 129 | |
| 130 current_writer_ = transaction; | |
| 131 | |
| 132 read_buf_ = std::move(buf); | |
| 133 io_buf_len_ = buf_len; | |
| 134 | |
| 135 next_state_ = STATE_NETWORK_READ; | |
| 136 int rv = DoLoop(OK); | |
| 137 | |
| 138 if (rv == ERR_IO_PENDING) { | |
| 139 DCHECK(callback_.is_null()); | |
| 140 callback_ = callback; | |
| 141 } | |
| 142 return rv; | |
| 143 } | |
| 144 | |
| 145 int HttpCache::SharedWriters::DoNetworkRead() { | |
| 146 next_state_ = STATE_NETWORK_READ_COMPLETE; | |
| 147 return data_access_->Read(read_buf_, io_buf_len_, io_callback_); | |
| 148 } | |
| 149 | |
| 150 int HttpCache::SharedWriters::DoNetworkReadComplete(int result) { | |
| 151 // Remember at this point current_writer_ may or may not be alive. | |
| 152 if (result < 0) { | |
| 153 // Empty SharedWriters of all transactions. | |
| 154 OnNetworkReadFailure(result); | |
| 155 return result; | |
| 156 } | |
| 157 | |
| 158 if (result == 0) { | |
| 159 // Check if the response is actually completed or if not, attempt to mark | |
| 160 // the entry as truncated. | |
| 161 if (cache_->IsResponseCompleted( | |
| 162 entry_, data_access_->network_transaction_->GetResponseInfo())) { | |
| 163 ProcessWaitingWriters(result); | |
| 164 ResponseDataComplete(); | |
| 165 } else { | |
| 166 OnNetworkReadFailure(result); | |
| 167 } | |
| 168 } else { // Successful non zero response. | |
| 169 // if no consumer exists, then invoke cache write itself. | |
| 170 if (!current_writer_) | |
| 171 next_state_ = STATE_CACHE_WRITE_DATA; | |
|
Randy Smith (Not in Mondays)
2017/01/19 00:53:42
Thought: It occurs to me that it might be useful f
shivanisha
2017/01/20 16:00:09
I remember talking to others about it and that Sim
| |
| 172 } | |
| 173 | |
| 174 return result; | |
| 175 } | |
| 176 | |
| 177 void HttpCache::SharedWriters::OnNetworkReadFailure(int result) { | |
| 178 FailureCleanup(result, false); | |
| 179 | |
| 180 if (cache_->CanResumeEntry( | |
| 181 true, "GET", data_access_->network_transaction_->GetResponseInfo(), | |
| 182 entry_)) { | |
| 183 next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE; | |
| 184 network_read_rv_ = result; | |
| 185 } else { | |
| 186 cache_->ResponseFailedSharedWriters(false, entry_); | |
| 187 } | |
| 188 } | |
| 189 | |
| 190 int HttpCache::SharedWriters::DoCacheWriteTruncatedResponse() { | |
| 191 next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE_COMPLETE; | |
| 192 return cache_->WriteResponseInfo( | |
| 193 entry_, data_access_->network_transaction_->GetResponseInfo(), | |
| 194 io_callback_, true, &io_buf_len_); | |
| 195 } | |
| 196 | |
| 197 int HttpCache::SharedWriters::DoCacheWriteTruncatedResponseComplete( | |
| 198 int result) { | |
| 199 bool success = true; | |
| 200 if (result != io_buf_len_) { | |
| 201 DLOG(ERROR) << "failed to write response info to cache"; | |
| 202 success = false; | |
| 203 } | |
| 204 // This object should be destroyed in the end of this flow. | |
| 205 destroy_ = true; | |
|
Randy Smith (Not in Mondays)
2017/01/19 00:53:43
Hmmm. Setting destroy_ to true means that on the
shivanisha
2017/01/25 19:46:13
Yup, simplified the destruction logic s.t. destroy
| |
| 206 | |
| 207 cache_->ResponseFailedSharedWriters(success, entry_); | |
| 208 | |
| 209 // Return the return value returned from the network read to the comsumer. | |
| 210 return network_read_rv_; | |
| 211 } | |
| 212 | |
| 213 int HttpCache::SharedWriters::CacheWrite(scoped_refptr<IOBuffer> buf, | |
| 214 int write_len, | |
| 215 const CompletionCallback& callback, | |
| 216 Transaction* transaction) { | |
| 217 DCHECK_EQ(next_state_, STATE_NONE); | |
| 218 DCHECK(buf); | |
| 219 DCHECK_GE(write_len, 0); | |
| 220 DCHECK(callback_.is_null()); | |
| 221 DCHECK(!callback.is_null()); | |
| 222 DCHECK_EQ(current_writer_, transaction); | |
| 223 | |
| 224 read_buf_ = std::move(buf); | |
| 225 next_state_ = STATE_CACHE_WRITE_DATA; | |
| 226 int rv = DoLoop(write_len); | |
| 227 | |
| 228 if (rv == ERR_IO_PENDING) { | |
| 229 DCHECK(callback_.is_null()); | |
| 230 callback_ = callback; | |
| 231 } | |
| 232 | |
| 233 return rv; | |
| 234 } | |
| 235 | |
| 236 int HttpCache::SharedWriters::DoCacheWriteData(int num_bytes) { | |
| 237 next_state_ = STATE_CACHE_WRITE_DATA_COMPLETE; | |
| 238 write_len_ = num_bytes; | |
| 239 return data_access_->CacheWrite(read_buf_, num_bytes, io_callback_); | |
| 240 } | |
| 241 | |
| 242 int HttpCache::SharedWriters::DoCacheWriteDataComplete(int result) { | |
| 243 if (result != write_len_) | |
| 244 // Need to take care of all the transactions in SharedWriters and | |
| 245 // delete SharedWriters as without the cache, we cannot continue the shared | |
| 246 // logic. | |
| 247 OnCacheWriteFailure(); | |
| 248 else | |
| 249 OnCacheWriteSuccess(result); | |
| 250 | |
| 251 return result; | |
| 252 } | |
| 253 | |
| 254 void HttpCache::SharedWriters::OnCacheWriteSuccess(int result) { | |
| 255 // Save the data in all the waiting transactions' read buffers. | |
| 256 for (auto it = waiting_writers_.begin(); it != waiting_writers_.end(); it++) { | |
| 257 it->write_len = std::min(it->read_buf_len, result); | |
| 258 memcpy(it->read_buf->data(), read_buf_->data(), it->write_len); | |
| 259 } | |
| 260 // Notify waiting_writers_. Tasks will be posted for all the | |
| 261 // transactions. | |
| 262 ProcessWaitingWriters(write_len_); | |
| 263 | |
| 264 if (result > 0) { // not the end of response | |
| 265 current_writer_ = nullptr; | |
| 266 return; | |
| 267 } | |
| 268 | |
| 269 DCHECK_EQ(result, 0); | |
| 270 | |
| 271 ResponseDataComplete(); | |
| 272 } | |
| 273 | |
| 274 void HttpCache::SharedWriters::ResponseDataComplete() { | |
| 275 ResetCurrentWriter(); | |
| 276 | |
| 277 // If there is a transaction validating currently, return. | |
| 278 if (validating_transaction_) | |
| 279 return; | |
| 280 | |
| 281 // Else empty the SharedWriters object. | |
| 282 MoveIdleWritersToReaders(); | |
| 283 DCHECK(all_writers_.empty()); | |
| 284 | |
| 285 MoveToPendingQueue(); | |
| 286 | |
| 287 destroy_ = true; | |
| 288 | |
| 289 // Inform cache_ so it can take care of entry_. | |
| 290 cache_->ResponseCompleteSharedWriters(entry_); | |
| 291 } | |
| 292 | |
| 293 void HttpCache::SharedWriters::OnCacheWriteFailure() { | |
| 294 Transaction* current_writer = current_writer_; | |
| 295 | |
| 296 // Needs data_access_ to be valid so needs to be invoked before | |
| 297 // ContinueWithoutSharedWriting. | |
| 298 FailureCleanup(ERR_CACHE_WRITE_FAILURE, true); | |
| 299 | |
| 300 destroy_ = true; | |
| 301 | |
| 302 if (current_writer) // If the transaction is still alive in this callback. | |
| 303 current_writer->ContinueWithoutSharedWriting(std::move(data_access_), | |
| 304 false); | |
| 305 | |
| 306 // Inform cache_ so it can take care of entry_. | |
| 307 cache_->ResponseFailedSharedWriters(false, entry_); | |
| 308 } | |
| 309 | |
| 310 void HttpCache::SharedWriters::MoveIdleWritersToReaders() { | |
| 311 // Should be invoked after waiting_writers_ are all processed so that | |
| 312 // all_writers_ only contains the idle writers. | |
| 313 DCHECK(waiting_writers_.empty()); | |
| 314 DCHECK(!current_writer_); | |
| 315 for (auto idle_writer : all_writers_) { | |
| 316 entry_->readers.insert(idle_writer); | |
| 317 idle_writer->ResetShared(false, true); | |
| 318 } | |
| 319 all_writers_.clear(); | |
| 320 } | |
| 321 | |
| 322 void HttpCache::SharedWriters::ProcessWaitingWriters(int result) { | |
| 323 for (auto it = waiting_writers_.begin(); it != waiting_writers_.end(); it++) { | |
| 324 Transaction* transaction = it->transaction; | |
| 325 | |
| 326 if (result > 0) { // success | |
| 327 // Fill result with the length of buffer filled for this transaction which | |
| 328 // may be different from the transaction that actually wrote to the cache | |
| 329 // based on the buffer size. | |
| 330 result = it->write_len; | |
| 331 } else { | |
| 332 // If its response completion or failure, this transaction needs to be | |
| 333 // removed. | |
| 334 transaction->ResetShared(); | |
| 335 all_writers_.erase(transaction); | |
| 336 } | |
| 337 | |
| 338 // Post task to notify transaction. | |
| 339 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 340 FROM_HERE, | |
| 341 base::Bind(&HttpCache::NotifyTransaction, cache_->GetWeakPtr(), | |
| 342 transaction->GetWeakPtr(), result)); | |
| 343 } | |
| 344 | |
| 345 waiting_writers_.clear(); | |
| 346 } | |
| 347 | |
| 348 void HttpCache::SharedWriters::FailureCleanup(int error, | |
| 349 bool continue_network_reading) { | |
| 350 ResetCurrentWriter(continue_network_reading); | |
| 351 | |
| 352 // Notify waiting_writers_ of the failure. Tasks will be posted for all the | |
| 353 // transactions. | |
| 354 ProcessWaitingWriters(error); | |
| 355 | |
| 356 // Idle readers should know to fail when Read is invoked by their consumers. | |
| 357 SetIdleWritersFailState(error); | |
| 358 DCHECK(all_writers_.empty()); | |
| 359 | |
| 360 // If there exists a validating_transaction_, it may be waiting | |
| 361 // to read response headers from the cache or waiting for receiving | |
| 362 // validation response from the network. In both scenarios, it should be safe | |
| 363 // to fail. | |
| 364 if (validating_transaction_) { | |
| 365 validating_transaction_->SetSharedWritingFailState(error); | |
| 366 validating_transaction_->ResetShared(true); | |
| 367 validating_transaction_ = nullptr; | |
| 368 } | |
| 369 | |
| 370 MoveToPendingQueue(); | |
| 371 } | |
| 372 | |
| 373 bool HttpCache::SharedWriters::StopCaching(Transaction* transaction) { | |
| 374 // If this is the only transaction in SharedWriters either in validation or | |
| 375 // reading stage, then stopping will be successful. If not, then we will not | |
| 376 // stop caching since there are other consumers waiting to read from the | |
| 377 // cache. | |
| 378 bool result = false; | |
| 379 if (transaction == validating_transaction_) { | |
| 380 if (all_writers_.empty()) { | |
| 381 result = true; | |
| 382 validating_transaction_ = nullptr; | |
| 383 } | |
| 384 } else if (all_writers_.size() == 1 && all_writers_.count(transaction) && | |
| 385 !validating_transaction_) { | |
| 386 if (current_writer_ == transaction) { | |
| 387 current_writer_ = nullptr; | |
| 388 } | |
| 389 all_writers_.erase(transaction); | |
| 390 result = true; | |
| 391 } | |
| 392 if (result) { | |
| 393 transaction->ContinueWithoutSharedWriting(std::move(data_access_), true); | |
| 394 entry_->writer = transaction; | |
| 395 MoveToPendingQueue(); | |
| 396 } | |
| 397 return result; | |
| 398 } | |
| 399 | |
| 400 void HttpCache::SharedWriters::ResetCurrentWriter( | |
| 401 bool continue_network_reading) { | |
| 402 // If current_writer_ is already destroyed, return. | |
| 403 if (!current_writer_) | |
| 404 return; | |
| 405 current_writer_->ResetShared(continue_network_reading); | |
| 406 all_writers_.erase(current_writer_); | |
| 407 current_writer_ = nullptr; | |
| 408 } | |
| 409 | |
| 410 void HttpCache::SharedWriters::SetIdleWritersFailState(int result) { | |
| 411 // Since this is only for idle transactions, all waiting_writers_ and | |
| 412 // current_writer_ should be empty. | |
| 413 DCHECK(waiting_writers_.empty()); | |
| 414 DCHECK(!current_writer_); | |
| 415 | |
| 416 for (auto transaction : all_writers_) { | |
| 417 transaction->SetSharedWritingFailState(result); | |
| 418 transaction->ResetShared(); | |
| 419 } | |
| 420 | |
| 421 all_writers_.clear(); | |
| 422 } | |
| 423 | |
| 424 void HttpCache::SharedWriters::OnValidationMatch(Transaction* transaction, | |
| 425 RequestPriority priority) { | |
| 426 DCHECK_EQ(validating_transaction_, transaction); | |
| 427 ValidationDoneContinue(transaction, priority); | |
| 428 } | |
| 429 | |
| 430 void HttpCache::SharedWriters::ValidationDoneContinue( | |
| 431 Transaction* transaction, | |
| 432 RequestPriority priority) { | |
| 433 validating_transaction_ = nullptr; | |
| 434 if (priority > priority_) { | |
| 435 data_access_->network_transaction_->SetPriority(priority); | |
| 436 priority_ = priority; | |
| 437 } | |
| 438 all_writers_.insert(transaction); | |
| 439 ProcessFirstWaitingValidation(); | |
| 440 } | |
| 441 | |
| 442 void HttpCache::SharedWriters::ProcessFirstWaitingValidation() { | |
| 443 if (!waiting_for_validation_.empty() || validating_transaction_) | |
| 444 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 445 FROM_HERE, | |
| 446 base::Bind(&HttpCache::SharedWriters::OnProcessFirstWaitingValidation, | |
| 447 weak_factory_.GetWeakPtr())); | |
| 448 } | |
| 449 | |
| 450 void HttpCache::SharedWriters::OnProcessFirstWaitingValidation() { | |
| 451 if (waiting_for_validation_.empty() && !validating_transaction_) | |
| 452 return; | |
| 453 | |
| 454 Transaction* transaction = nullptr; | |
| 455 if (validating_transaction_) { | |
| 456 transaction = validating_transaction_; | |
| 457 } else { | |
| 458 transaction = waiting_for_validation_.front(); | |
| 459 waiting_for_validation_.erase(waiting_for_validation_.begin()); | |
| 460 validating_transaction_ = transaction; | |
| 461 } | |
| 462 transaction->io_callback().Run(OK); | |
| 463 } | |
| 464 | |
| 465 std::unique_ptr<HttpTransaction> HttpCache::SharedWriters::OnValidationNoMatch( | |
| 466 Transaction* transaction, | |
| 467 std::unique_ptr<HttpTransaction> network_transaction, | |
| 468 RequestPriority priority) { | |
| 469 DCHECK_EQ(validating_transaction_, transaction); | |
| 470 // If there is no transaction in all_writers_, its ok to rewrite the entry | |
| 471 // response. | |
| 472 if (all_writers_.empty()) { | |
| 473 data_access_.reset(new DataAccess(std::move(network_transaction), entry_)); | |
| 474 ValidationDoneContinue(transaction, priority); | |
| 475 return std::unique_ptr<HttpTransaction>(); | |
| 476 } | |
| 477 | |
| 478 transaction->ResetShared(); | |
| 479 validating_transaction_ = nullptr; | |
| 480 MoveToPendingQueue(); | |
| 481 return network_transaction; | |
| 482 } | |
| 483 | |
| 484 void HttpCache::SharedWriters::DoneReading(Transaction* transaction) { | |
| 485 // If current_writer_ is set, then wait for current_writer_ to detect the end | |
| 486 // of stream. | |
| 487 if (current_writer_) { | |
| 488 return; | |
| 489 } | |
| 490 DCHECK(waiting_writers_.empty()); | |
| 491 RemoveIdleWriter(transaction); | |
| 492 // If there is a transaction validating currently, return. | |
| 493 if (validating_transaction_) { | |
| 494 return; | |
| 495 } | |
| 496 | |
| 497 // Else empty the SharedWriters object. | |
| 498 MoveIdleWritersToReaders(); | |
| 499 DCHECK(all_writers_.empty()); | |
| 500 | |
| 501 MoveToPendingQueue(); | |
| 502 } | |
| 503 | |
| 504 void HttpCache::SharedWriters::RemoveIdleWriter(Transaction* transaction) { | |
| 505 // The transaction should be part of all_writers. | |
| 506 auto it = all_writers_.find(transaction); | |
| 507 DCHECK(it != all_writers_.end()); | |
| 508 all_writers_.erase(transaction); | |
| 509 transaction->ResetShared(); | |
| 510 } | |
| 511 | |
| 512 void HttpCache::SharedWriters::RemoveWaitingWriter(Transaction* transaction) { | |
| 513 auto it = waiting_writers_.begin(); | |
| 514 for (; it != waiting_writers_.end(); it++) { | |
| 515 if (transaction == it->transaction) { | |
| 516 waiting_writers_.erase(it); | |
| 517 all_writers_.erase(transaction); | |
| 518 transaction->ResetShared(); | |
| 519 // If a waiting_writer_ existed, there should have been a current_writer_. | |
| 520 DCHECK(current_writer_); | |
| 521 break; | |
| 522 } | |
| 523 } | |
| 524 } | |
| 525 | |
| 526 void HttpCache::SharedWriters::RemoveValidatingTransaction( | |
| 527 Transaction* transaction) { | |
| 528 DCHECK_EQ(validating_transaction_, transaction); | |
| 529 validating_transaction_ = nullptr; | |
| 530 transaction->ResetShared(); | |
| 531 ProcessFirstWaitingValidation(); | |
| 532 } | |
| 533 | |
| 534 bool HttpCache::SharedWriters::RemoveWaitingTransaction( | |
| 535 Transaction* transaction) { | |
| 536 auto it = std::find(waiting_for_validation_.begin(), | |
| 537 waiting_for_validation_.end(), transaction); | |
| 538 if (it != waiting_for_validation_.end()) { | |
| 539 transaction->ResetShared(); | |
| 540 waiting_for_validation_.erase(it); | |
| 541 return true; | |
| 542 } | |
| 543 return false; | |
| 544 } | |
| 545 | |
| 546 void HttpCache::SharedWriters::RemoveCurrentWriter(Transaction* transaction) { | |
| 547 DCHECK_EQ(current_writer_, transaction); | |
| 548 ResetCurrentWriter(); | |
| 549 callback_.Reset(); | |
| 550 } | |
| 551 | |
| 552 void HttpCache::SharedWriters::MoveFromPendingQueue() { | |
| 553 auto it = entry_->pending_queue.begin(); | |
| 554 while (it != entry_->pending_queue.end()) { | |
| 555 Transaction* transaction = *it; | |
| 556 if (transaction->IsEligibleForSharedWriting()) { | |
| 557 transaction->SetShared(); | |
| 558 waiting_for_validation_.push_back(transaction); | |
| 559 it = entry_->pending_queue.erase(it); | |
| 560 } else { | |
| 561 ++it; | |
| 562 } | |
| 563 } | |
| 564 } | |
| 565 | |
| 566 void HttpCache::SharedWriters::MoveToPendingQueue() { | |
| 567 // For maintaining the order of the transactions as they arrived, append | |
| 568 // these to the front of the pending_queue. Note that the order is preserved | |
| 569 // only among the transactions that are eligible for sharing. For others, they | |
| 570 // may have arrived earlier but may be processed later which is fair since | |
| 571 // they have to anyways wait till the entry is written to the cache. | |
| 572 while (!waiting_for_validation_.empty()) { | |
| 573 Transaction* transaction = waiting_for_validation_.back(); | |
| 574 transaction->ResetShared(true); | |
| 575 entry_->pending_queue.push_front(transaction); | |
| 576 waiting_for_validation_.pop_back(); | |
| 577 } | |
| 578 } | |
| 579 | |
| 580 bool HttpCache::SharedWriters::CanReset() { | |
| 581 return !destroy_; | |
| 582 } | |
| 583 | |
| 584 HttpCache::SharedWriters::WaitingWriter::WaitingWriter( | |
| 585 Transaction* cache_transaction, | |
| 586 scoped_refptr<IOBuffer> buf, | |
| 587 int len) | |
| 588 : transaction(cache_transaction), | |
| 589 read_buf(std::move(buf)), | |
| 590 read_buf_len(len), | |
| 591 write_len(0) {} | |
| 592 | |
| 593 HttpCache::SharedWriters::WaitingWriter::~WaitingWriter() {} | |
| 594 | |
| 595 HttpCache::SharedWriters::WaitingWriter::WaitingWriter(const WaitingWriter&) = | |
| 596 default; | |
| 597 | |
| 598 void HttpCache::SharedWriters::OnIOComplete(int result) { | |
| 599 bool destroy = destroy_; | |
| 600 DoLoop(result); | |
| 601 | |
| 602 // Only check the local variable as this object may have been destroyed if | |
| 603 // destroy_ was not set to true. | |
| 604 if (destroy) | |
| 605 SelfDestroy(); | |
|
Randy Smith (Not in Mondays)
2017/01/19 00:53:43
Worth a DCHECK that DoLoop() didn't return ERR_IO_
shivanisha
2017/01/25 19:46:13
N/A now that self destruction is not needed.
| |
| 606 } | |
| 607 | |
| 608 void HttpCache::SharedWriters::SelfDestroy() { | |
|
Randy Smith (Not in Mondays)
2017/01/19 00:53:43
I don't think there's a need for a separate functi
shivanisha
2017/01/25 19:46:13
N/A now that self destruction is not needed.
| |
| 609 delete this; | |
| 610 } | |
| 611 | |
| 612 } // namespace net | |
| OLD | NEW |