Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(415)

Side by Side Diff: net/http/http_cache_shared_writers.cc

Issue 2519473002: Fixes the cache lock issue. (Closed)
Patch Set: Test only change to fix a memory leak. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 <memory>
12 #include <utility>
13 #include "base/bind.h"
14 #include "base/callback_helpers.h"
15 #include "base/compiler_specific.h"
16 #include "base/format_macros.h"
17 #include "base/location.h"
18 #include "base/macros.h"
19 #include "base/single_thread_task_runner.h"
20 #include "net/disk_cache/disk_cache.h"
21 #include "net/http/http_cache_shared_writers.h"
22 #include "net/http/http_cache_transaction.h"
23
24 namespace net {
25
26 HttpCache::SharedWriters::SharedWriters(
27 HttpCache* cache,
28 ActiveEntry* entry,
29 Transaction* cache_transaction,
30 RequestPriority priority,
31 std::unique_ptr<HttpTransaction> network_transaction)
32 : cache_(cache->GetWeakPtr()),
33 entry_(entry),
34 priority_(priority),
35 weak_factory_(this) {
36 cache_transaction->SetShared();
37 all_writers_.insert(cache_transaction);
38 network_transaction_ = std::move(network_transaction);
39 io_callback_ = base::Bind(&HttpCache::SharedWriters::OnIOComplete,
40 weak_factory_.GetWeakPtr());
41 }
42
43 HttpCache::SharedWriters::~SharedWriters() {}
44
45 bool HttpCache::SharedWriters::AddTransaction(Transaction* transaction) {
46 transaction->SetShared();
47
48 if (!validating_transaction_) {
49 validating_transaction_ = transaction;
50 return true;
51 }
52
53 waiting_for_validation_.push_back(transaction);
54 return false;
55 }
56
57 bool HttpCache::SharedWriters::empty() {
58 int count = all_writers_.size() + waiting_for_validation_.size() +
59 (validating_transaction_ ? 1 : 0);
60 return count ? false : true;
61 }
62
63 int HttpCache::SharedWriters::DoLoop(int result) {
64 DCHECK(next_state_ != STATE_NONE);
65
66 int rv = result;
67
68 do {
69 State state = next_state_;
70 next_state_ = STATE_NONE;
71
72 switch (state) {
73 case STATE_NETWORK_READ:
74 DCHECK_EQ(OK, rv);
75 rv = DoNetworkRead();
76 break;
77 case STATE_NETWORK_READ_COMPLETE:
78 rv = DoNetworkReadComplete(rv);
79 break;
80 case STATE_CACHE_WRITE_DATA:
81 rv = DoCacheWriteData(rv);
82 break;
83 case STATE_CACHE_WRITE_DATA_COMPLETE:
84 rv = DoCacheWriteDataComplete(rv);
85 break;
86 case STATE_CACHE_WRITE_TRUNCATED_RESPONSE:
87 rv = DoCacheWriteTruncatedResponse();
88 break;
89 case STATE_CACHE_WRITE_TRUNCATED_RESPONSE_COMPLETE:
90 rv = DoCacheWriteTruncatedResponseComplete(rv);
91 break;
92 default:
93 NOTREACHED() << "bad state";
94 rv = ERR_FAILED;
95 break;
96 }
97 } while (next_state_ != STATE_DONE && rv != ERR_IO_PENDING &&
98 next_state_ != STATE_NONE);
99
100 // Save the callback as this object may be destroyed in the cache callback.
101 bool destroyed = false;
102 CompletionCallback callback = callback_;
103 if (next_state_ == STATE_DONE && cache_callback_) {
104 base::ResetAndReturn(&cache_callback_).Run(&destroyed);
105 }
106
107 if (rv != ERR_IO_PENDING && !callback.is_null()) {
108 if (!destroyed) {
109 read_buf_ = NULL; // Release the buffer before invoking the callback.
110 base::ResetAndReturn(&callback_).Run(rv);
111 } else {
112 base::ResetAndReturn(&callback).Run(rv);
113 }
114 }
115 // This object may have been destroyed in the callback or cache_callback_.
116
117 return rv;
118 }
119
120 int HttpCache::SharedWriters::Read(scoped_refptr<IOBuffer> buf,
121 int buf_len,
122 const CompletionCallback& callback,
123 Transaction* transaction,
124 bool* read_in_progress) {
125 DCHECK(buf);
126 DCHECK_GT(buf_len, 0);
127 DCHECK(!callback.is_null());
128
129 // If another transaction is already reading from the network, then this
130 // transaction waits for the read to complete and gets its buffer filled
131 // with the data returned from that read.
132 if (active_transaction_) {
133 WaitingForRead waiting_transaction(transaction, buf, buf_len, callback);
134 waiting_for_read_.push_back(waiting_transaction);
135 *read_in_progress = true;
136 return ERR_IO_PENDING;
137 }
138
139 DCHECK_EQ(next_state_, STATE_NONE);
140 DCHECK(callback_.is_null());
141
142 active_transaction_ = transaction;
143
144 read_buf_ = std::move(buf);
145 io_buf_len_ = buf_len;
146
147 next_state_ = STATE_NETWORK_READ;
148 int rv = DoLoop(OK);
149
150 if (rv == ERR_IO_PENDING) {
151 DCHECK(callback_.is_null());
152 callback_ = callback;
153 }
154 return rv;
155 }
156
157 int HttpCache::SharedWriters::DoNetworkRead() {
158 next_state_ = STATE_NETWORK_READ_COMPLETE;
159 return network_transaction_->Read(read_buf_.get(), io_buf_len_, io_callback_);
160 }
161
162 int HttpCache::SharedWriters::DoNetworkReadComplete(int result) {
163 // Remember at this point active_transaction_ may or may not be alive.
164 if (result < 0) {
165 // Empty SharedWriters of all transactions.
166 OnNetworkReadFailure(result);
167 return result;
168 }
169
170 if (result == 0) {
171 // Check if the response is actually completed or if not, attempt to mark
172 // the entry as truncated.
173 if (cache_->IsResponseCompleted(entry_,
jkarlin 2017/02/07 15:20:30 This checking if the response is completed is new
shivanisha 2017/02/07 20:56:47 This checking is not new but was being done in HCT
174 network_transaction_->GetResponseInfo())) {
175 ProcessWaitingForReadTransactions(result);
176 ResponseDataComplete();
177 } else {
178 OnNetworkReadFailure(result);
179 }
180 return result;
181 }
182
183 // Successful non zero response.
184
185 // if no consumer exists, then invoke cache write itself.
186 if (!active_transaction_)
187 next_state_ = STATE_CACHE_WRITE_DATA;
188
189 return result;
190 }
191
192 void HttpCache::SharedWriters::OnNetworkReadFailure(int result) {
193 FailureCleanup(result, false);
194 if (AttemptTruncation()) {
195 rv_post_truncation_ = result;
196 } else {
197 next_state_ = STATE_DONE;
198 cache_callback_ = base::Bind(&HttpCache::ResponseDoneSharedWriters,
199 cache_->GetWeakPtr(), entry_, false);
200 }
201 }
202
203 bool HttpCache::SharedWriters::AttemptTruncation() {
204 if (cache_->CanResumeEntry(true, "GET",
205 network_transaction_->GetResponseInfo(), entry_)) {
206 next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE;
207 return true;
208 } else {
209 return false;
210 }
211 }
212
213 int HttpCache::SharedWriters::DoCacheWriteTruncatedResponse() {
214 next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE_COMPLETE;
215 return cache_->WriteResponseInfo(entry_,
216 network_transaction_->GetResponseInfo(),
217 io_callback_, true, &io_buf_len_);
218 }
219
220 int HttpCache::SharedWriters::DoCacheWriteTruncatedResponseComplete(
221 int result) {
222 bool success = true;
223 if (result != io_buf_len_) {
224 DLOG(ERROR) << "failed to write response info to cache";
225 success = false;
226 }
227
228 next_state_ = STATE_DONE;
229 cache_callback_ = base::Bind(&HttpCache::ResponseDoneSharedWriters,
230 cache_->GetWeakPtr(), entry_, success);
231
232 // If consumer exists, return the saved value.
233 int rv = 0;
234 if (callback_) {
235 rv = rv_post_truncation_;
236 rv_post_truncation_ = 0;
237 } else {
238 rv = result;
239 }
240 return rv;
241 }
242
243 int HttpCache::SharedWriters::CacheWrite(scoped_refptr<IOBuffer> buf,
244 int write_len,
245 const CompletionCallback& callback,
246 Transaction* transaction) {
247 DCHECK_EQ(next_state_, STATE_NONE);
248 DCHECK(buf);
249 DCHECK_GE(write_len, 0);
250 DCHECK(callback_.is_null());
251 DCHECK(!callback.is_null());
252 DCHECK_EQ(active_transaction_, transaction);
253
254 read_buf_ = std::move(buf);
255 next_state_ = STATE_CACHE_WRITE_DATA;
256 int rv = DoLoop(write_len);
257
258 if (rv == ERR_IO_PENDING) {
259 DCHECK(callback_.is_null());
260 callback_ = callback;
261 }
262
263 return rv;
264 }
265
266 int HttpCache::SharedWriters::DoCacheWriteData(int num_bytes) {
267 next_state_ = STATE_CACHE_WRITE_DATA_COMPLETE;
268 write_len_ = num_bytes;
269 int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex);
270 return entry_->disk_entry->WriteData(kResponseContentIndex, current_size,
271 read_buf_.get(), num_bytes, io_callback_,
272 true);
273 }
274
275 int HttpCache::SharedWriters::DoCacheWriteDataComplete(int result) {
276 if (result != write_len_) {
277 // Need to take care of all the transactions in SharedWriters and
278 // delete SharedWriters as without the cache, we cannot continue the shared
279 // logic.
280 OnCacheWriteFailure();
281 } else {
282 OnCacheWriteSuccess(result);
283 }
284
285 return result;
286 }
287
288 void HttpCache::SharedWriters::OnCacheWriteSuccess(int result) {
289 // Save the data in all the waiting transactions' read buffers.
290 for (auto it = waiting_for_read_.begin(); it != waiting_for_read_.end();
291 it++) {
292 it->write_len = std::min(it->read_buf_len, result);
293 memcpy(it->read_buf->data(), read_buf_->data(), it->write_len);
294 }
295 // Notify waiting_for_read_. Tasks will be posted for all the
296 // transactions.
297 ProcessWaitingForReadTransactions(write_len_);
298
299 if (result > 0) { // not the end of response
300 active_transaction_ = nullptr;
301 return;
302 }
303
304 DCHECK_EQ(result, 0);
305
306 ResponseDataComplete();
307 }
308
309 void HttpCache::SharedWriters::ResponseDataComplete() {
310 ResetActiveTransaction();
311
312 // If there is a transaction validating currently, return.
313 if (validating_transaction_)
314 return;
315
316 // Else empty the SharedWriters object.
317 MoveIdleWritersToReaders();
318 DCHECK(all_writers_.empty());
319
320 MoveToPendingQueue();
321
322 // Inform cache_ so it can take care of entry_.
323 next_state_ = STATE_DONE;
324 cache_callback_ = base::Bind(&HttpCache::ResponseDoneSharedWriters,
325 cache_->GetWeakPtr(), entry_, true);
326 }
327
328 void HttpCache::SharedWriters::OnCacheWriteFailure() {
329 Transaction* current_writer = active_transaction_;
330
331 // Needs network_transaction_ to be valid so needs to be invoked before
332 // ContinueWithoutSharedWriting.
333 FailureCleanup(net::ERR_CACHE_WRITE_FAILURE, true);
334
335 if (current_writer) // If the transaction is still alive in this callback.
336 current_writer->ContinueWithoutSharedWriting(
337 std::move(network_transaction_), false);
338
339 // Inform cache_ so it can take care of entry_.
340 next_state_ = STATE_DONE;
341 cache_callback_ = base::Bind(&HttpCache::ResponseDoneSharedWriters,
342 cache_->GetWeakPtr(), entry_, false);
343 }
344
345 void HttpCache::SharedWriters::MoveIdleWritersToReaders() {
346 // Should be invoked after waiting_for_read_ are all processed so that
347 // all_writers_ only contains the idle writers.
348 DCHECK(waiting_for_read_.empty());
349 DCHECK(!active_transaction_);
350 for (auto idle_writer : all_writers_) {
351 entry_->readers.insert(idle_writer);
352 idle_writer->ResetShared(false, true);
353 }
354 all_writers_.clear();
355 }
356
357 void HttpCache::SharedWriters::ProcessWaitingForReadTransactions(int result) {
358 for (auto it = waiting_for_read_.begin(); it != waiting_for_read_.end();
359 it++) {
360 Transaction* transaction = it->transaction;
361
362 if (result > 0) { // success
363 // Fill result with the length of buffer filled for this transaction which
364 // may be different from the transaction that actually wrote to the cache
365 // based on the buffer size.
366 result = it->write_len;
367 } else {
368 // If its response completion or failure, this transaction needs to be
369 // removed.
370 transaction->ResetShared();
371 all_writers_.erase(transaction);
372 }
373
374 // Post task to notify transaction.
375 base::ThreadTaskRunnerHandle::Get()->PostTask(
376 FROM_HERE, base::Bind(it->callback, result));
377 }
378
379 waiting_for_read_.clear();
380 }
381
382 void HttpCache::SharedWriters::FailureCleanup(int error,
383 bool continue_network_reading) {
384 ResetActiveTransaction(continue_network_reading);
385
386 // Notify waiting_for_read_ of the failure. Tasks will be posted for all the
387 // transactions.
388 ProcessWaitingForReadTransactions(error);
389
390 // Idle readers should know to fail when Read is invoked by their consumers.
391 SetIdleWritersFailState(error);
392 DCHECK(all_writers_.empty());
393
394 // If there exists a validating_transaction_, it may be waiting
395 // to read response headers from the cache or waiting for receiving
396 // validation response from the network. In both scenarios, it should be safe
397 // to fail.
398 if (validating_transaction_) {
399 validating_transaction_->SetSharedWritingFailState(error);
400 validating_transaction_->ResetShared(true);
401 validating_transaction_ = nullptr;
402 }
403
404 MoveToPendingQueue();
405 }
406
407 void HttpCache::SharedWriters::StopCaching(Transaction* transaction) {
408 // If this is the only transaction in SharedWriters either in validation or
409 // reading stage, then stopping will be successful. If not, then we will not
410 // stop caching since there are other consumers waiting to read from the
411 // cache.
412 bool result = false;
413 if (transaction == validating_transaction_) {
414 if (all_writers_.empty()) {
415 result = true;
416 validating_transaction_ = nullptr;
417 }
418 } else if (all_writers_.size() == 1 && all_writers_.count(transaction) &&
419 !validating_transaction_) {
420 if (active_transaction_ == transaction) {
421 active_transaction_ = nullptr;
422 }
423 all_writers_.erase(transaction);
424 result = true;
425 }
426 if (result) {
427 transaction->ContinueWithoutSharedWriting(std::move(network_transaction_),
428 true);
429 entry_->writer = transaction;
430 MoveToPendingQueue();
431 }
432 // If stopped, let the cache_ destroy |this|.
433 if (result)
434 cache_->ResetSharedWriters(entry_);
435 }
436
437 void HttpCache::SharedWriters::ResetActiveTransaction(
438 bool continue_network_reading) {
439 // If active_transaction_ is already destroyed, return.
440 if (!active_transaction_)
441 return;
442 active_transaction_->ResetShared(continue_network_reading);
443 all_writers_.erase(active_transaction_);
444 active_transaction_ = nullptr;
445 PriorityChanged();
446 }
447
448 void HttpCache::SharedWriters::SetIdleWritersFailState(int result) {
449 // Since this is only for idle transactions, all waiting_for_read_ and
450 // active_transaction_ should be empty.
451 DCHECK(waiting_for_read_.empty());
452 DCHECK(!active_transaction_);
453
454 for (auto transaction : all_writers_) {
455 transaction->SetSharedWritingFailState(result);
456 transaction->ResetShared();
457 }
458
459 all_writers_.clear();
460 }
461
462 void HttpCache::SharedWriters::OnValidationMatch(Transaction* transaction,
463 RequestPriority priority) {
464 DCHECK_EQ(validating_transaction_, transaction);
465 ValidationDoneContinue(transaction, priority);
466 }
467
468 void HttpCache::SharedWriters::ValidationDoneContinue(
469 Transaction* transaction,
470 RequestPriority priority) {
471 validating_transaction_ = nullptr;
472 if (priority > priority_) {
473 network_transaction_->SetPriority(priority);
474 priority_ = priority;
475 }
476 all_writers_.insert(transaction);
477 ProcessFirstWaitingValidation();
478 }
479
480 void HttpCache::SharedWriters::PriorityChanged() {
481 RequestPriority current_highest = getCurrentHighestPriority();
482 if (priority_ != current_highest) {
483 network_transaction_->SetPriority(current_highest);
484 priority_ = current_highest;
485 }
486 }
487
488 RequestPriority HttpCache::SharedWriters::getCurrentHighestPriority() {
489 RequestPriority priority = MINIMUM_PRIORITY;
490 for (auto transaction : all_writers_)
491 priority = std::max(transaction->priority(), priority);
492 return priority;
493 }
494
495 void HttpCache::SharedWriters::ProcessFirstWaitingValidation() {
496 if (!waiting_for_validation_.empty() || validating_transaction_)
497 base::ThreadTaskRunnerHandle::Get()->PostTask(
498 FROM_HERE,
499 base::Bind(&HttpCache::SharedWriters::OnProcessFirstWaitingValidation,
500 weak_factory_.GetWeakPtr()));
501 }
502
503 void HttpCache::SharedWriters::OnProcessFirstWaitingValidation() {
504 if (waiting_for_validation_.empty() && !validating_transaction_)
505 return;
506
507 Transaction* transaction = nullptr;
508 if (validating_transaction_) {
509 transaction = validating_transaction_;
jkarlin 2017/02/07 15:20:30 Seems like you could cut out two lines: Transacti
shivanisha 2017/02/07 20:56:47 Done.
510 } else {
511 transaction = waiting_for_validation_.front();
512 waiting_for_validation_.erase(waiting_for_validation_.begin());
513 validating_transaction_ = transaction;
514 }
515 transaction->io_callback().Run(OK);
516 }
517
518 std::unique_ptr<HttpTransaction> HttpCache::SharedWriters::OnValidationNoMatch(
519 const std::string& key,
520 Transaction* transaction,
521 std::unique_ptr<HttpTransaction> network_transaction,
522 RequestPriority priority) {
523 DCHECK_EQ(validating_transaction_, transaction);
524 // If there is no transaction in all_writers_, its ok to rewrite the entry
525 // response.
526 if (all_writers_.empty()) {
527 network_transaction_ = std::move(network_transaction);
528 ValidationDoneContinue(transaction, priority);
529 return std::unique_ptr<HttpTransaction>();
530 }
531
532 transaction->ResetShared();
533 validating_transaction_ = nullptr;
534 MoveToPendingQueue();
535 cache_->DoomEntryRestartPendingQueue(key, entry_);
536 return network_transaction;
537 }
538
539 void HttpCache::SharedWriters::DoneReading(Transaction* transaction) {
540 // Should only be invoked when the transaction is not currently reading.
541 DCHECK_NE(transaction, active_transaction_);
542 auto it = waiting_for_read_.begin();
543 for (; it != waiting_for_read_.end(); it++)
544 DCHECK_NE(transaction, it->transaction);
545
546 // The transaction should be part of all_writers.
547 size_t result = all_writers_.erase(transaction);
548 DCHECK_EQ(result, (size_t)1);
549 transaction->ResetShared();
550
551 // If active_transaction_ is set, then wait for active_transaction_ to detect
552 // the end
553 // of stream.
554 if (active_transaction_) {
555 return;
556 }
557 DCHECK(waiting_for_read_.empty());
558 // If there is a transaction validating currently, return.
559 if (validating_transaction_) {
560 return;
561 }
562
563 // Else empty the SharedWriters object.
564 MoveIdleWritersToReaders();
565 MoveToPendingQueue();
566 DCHECK(empty());
567 cache_->ResetSharedWritersProcessPendingQueue(entry_);
568 }
569
570 void HttpCache::SharedWriters::RemoveIdleTransaction(Transaction* transaction) {
571 // The transaction should be part of all_writers.
572 auto it = all_writers_.find(transaction);
573 DCHECK(it != all_writers_.end());
574 all_writers_.erase(transaction);
575 transaction->ResetShared();
576 PriorityChanged();
577 // If the response is not complete and there are no more consumers for this,
578 // attempt to mark it as truncated. If |this| is empty, it will also be
579 // destroyed in this call.
580 if (empty())
581 cache_->RemovedSharedWriterTransaction(transaction, entry_);
582 }
583
584 void HttpCache::SharedWriters::RemoveWaitingForReadTransaction(
585 Transaction* transaction) {
586 auto it = waiting_for_read_.begin();
587 for (; it != waiting_for_read_.end(); it++) {
588 if (transaction == it->transaction) {
589 waiting_for_read_.erase(it);
590 all_writers_.erase(transaction);
591 transaction->ResetShared();
592 PriorityChanged();
593 // If a waiting transaction existed, there should have been an
594 // active_transaction_.
595 DCHECK(active_transaction_);
596 break;
597 }
598 }
599 }
600
601 void HttpCache::SharedWriters::RemoveValidatingTransaction(
602 Transaction* transaction) {
603 DCHECK_EQ(validating_transaction_, transaction);
604 validating_transaction_ = nullptr;
605 transaction->ResetShared();
606 ProcessFirstWaitingValidation();
607 if (empty())
608 cache_->ResetSharedWritersProcessPendingQueue(entry_);
609 }
610
611 bool HttpCache::SharedWriters::RemoveWaitingTransaction(
612 Transaction* transaction) {
613 auto it = std::find(waiting_for_validation_.begin(),
614 waiting_for_validation_.end(), transaction);
615 if (it != waiting_for_validation_.end()) {
616 transaction->ResetShared();
617 waiting_for_validation_.erase(it);
618 return true;
619 }
620 return false;
621 }
622
623 void HttpCache::SharedWriters::RemoveActiveTransaction(
624 Transaction* transaction) {
625 DCHECK_EQ(active_transaction_, transaction);
626 ResetActiveTransaction();
627 callback_.Reset();
628 // If the response is not complete and there are no more consumers for this,
629 // attempt to mark it as truncated. If |this| is empty, it will also be
630 // destroyed in this call.
631 if (empty())
632 cache_->RemovedSharedWriterTransaction(transaction, entry_);
633 }
634
635 void HttpCache::SharedWriters::MoveFromPendingQueue() {
636 auto it = entry_->pending_queue.begin();
637 while (it != entry_->pending_queue.end()) {
638 Transaction* transaction = *it;
639 if (transaction->IsEligibleForSharedWriting()) {
640 transaction->SetShared();
641 waiting_for_validation_.push_back(transaction);
642 it = entry_->pending_queue.erase(it);
643 } else {
644 ++it;
645 }
646 }
647 }
648
649 void HttpCache::SharedWriters::MoveToPendingQueue() {
650 // For maintaining the order of the transactions as they arrived, append
651 // these to the front of the pending_queue. Note that the order is preserved
652 // only among the transactions that are eligible for sharing. For others, they
653 // may have arrived earlier but may be processed later which is fair since
654 // they have to anyways wait till the entry is written to the cache.
655 while (!waiting_for_validation_.empty()) {
656 Transaction* transaction = waiting_for_validation_.back();
657 transaction->ResetShared(true);
658 entry_->pending_queue.push_front(transaction);
659 waiting_for_validation_.pop_back();
660 }
661 }
662
663 bool HttpCache::SharedWriters::CanAddNewTransaction() {
664 if (next_state_ == STATE_CACHE_WRITE_TRUNCATED_RESPONSE_COMPLETE)
665 return false;
666 return true;
667 }
668
669 HttpCache::SharedWriters::WaitingForRead::WaitingForRead(
670 Transaction* cache_transaction,
671 scoped_refptr<IOBuffer> buf,
672 int len,
673 const CompletionCallback& consumer_callback)
674 : transaction(cache_transaction),
675 read_buf(std::move(buf)),
676 read_buf_len(len),
677 write_len(0),
678 callback(consumer_callback) {}
679
680 HttpCache::SharedWriters::WaitingForRead::~WaitingForRead() {}
681
682 HttpCache::SharedWriters::WaitingForRead::WaitingForRead(
683 const WaitingForRead&) = default;
684
685 void HttpCache::SharedWriters::OnIOComplete(int result) {
686 DoLoop(result);
687 }
688
689 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698