OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2010 The Chromium OS 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 "update_engine/multi_range_http_fetcher.h" | |
6 | |
7 #include "update_engine/utils.h" | |
8 | |
9 namespace chromeos_update_engine { | |
10 | |
11 // Begins the transfer to the specified URL. | |
12 // State change: Stopped -> Downloading | |
13 // (corner case: Stopped -> Stopped for an empty request) | |
14 void MultiRangeHTTPFetcher::BeginTransfer(const std::string& url) { | |
15 CHECK(!base_fetcher_active_) << "BeginTransfer but already active."; | |
16 CHECK(!pending_transfer_ended_) << "BeginTransfer but pending."; | |
17 CHECK(!terminating_) << "BeginTransfer but terminating."; | |
18 | |
19 if (ranges_.empty()) { | |
20 // Note that after the callback returns this object may be destroyed. | |
21 if (delegate_) | |
22 delegate_->TransferComplete(this, true); | |
23 return; | |
24 } | |
25 url_ = url; | |
26 current_index_ = 0; | |
27 bytes_received_this_range_ = 0; | |
28 LOG(INFO) << "starting first transfer"; | |
29 base_fetcher_->set_delegate(this); | |
30 StartTransfer(); | |
31 } | |
32 | |
33 // State change: Downloading -> Pending transfer ended | |
34 void MultiRangeHTTPFetcher::TerminateTransfer() { | |
35 if (!base_fetcher_active_) { | |
36 LOG(INFO) << "Called TerminateTransfer but not active."; | |
37 // Note that after the callback returns this object may be destroyed. | |
38 if (delegate_) | |
39 delegate_->TransferTerminated(this); | |
40 return; | |
41 } | |
42 terminating_ = true; | |
43 | |
44 if (!pending_transfer_ended_) { | |
45 base_fetcher_->TerminateTransfer(); | |
46 } | |
47 } | |
48 | |
49 // State change: Stopped or Downloading -> Downloading | |
50 void MultiRangeHTTPFetcher::StartTransfer() { | |
51 if (current_index_ >= ranges_.size()) { | |
52 return; | |
53 } | |
54 LOG(INFO) << "Starting a transfer @" << ranges_[current_index_].first << "(" | |
55 << ranges_[current_index_].second << ")"; | |
56 bytes_received_this_range_ = 0; | |
57 base_fetcher_->SetOffset(ranges_[current_index_].first); | |
58 if (delegate_) | |
59 delegate_->SeekToOffset(ranges_[current_index_].first); | |
60 base_fetcher_active_ = true; | |
61 base_fetcher_->BeginTransfer(url_); | |
62 } | |
63 | |
64 // State change: Downloading -> Downloading | |
65 void MultiRangeHTTPFetcher::ReceivedBytes(HttpFetcher* fetcher, | |
66 const char* bytes, | |
67 int length) { | |
68 CHECK_LT(current_index_, ranges_.size()); | |
69 CHECK_EQ(fetcher, base_fetcher_.get()); | |
70 CHECK(!pending_transfer_ended_); | |
71 off_t next_size = length; | |
72 if (ranges_[current_index_].second >= 0) { | |
73 next_size = std::min(next_size, | |
74 ranges_[current_index_].second - | |
75 bytes_received_this_range_); | |
76 } | |
77 LOG_IF(WARNING, next_size <= 0) << "Asked to write length <= 0"; | |
78 if (delegate_) { | |
79 delegate_->ReceivedBytes(this, bytes, next_size); | |
80 } | |
81 bytes_received_this_range_ += length; | |
82 if (ranges_[current_index_].second >= 0 && | |
83 bytes_received_this_range_ >= ranges_[current_index_].second) { | |
84 // Terminates the current fetcher. Waits for its TransferTerminated | |
petkov
2010/12/17 13:37:25
this comment needs to be updated to reflect the fa
adlr
2010/12/17 19:34:15
Done.
| |
85 // callback before starting the next fetcher so that we don't end up | |
86 // signalling the delegate that the whole multi-transfer is complete | |
87 // before all fetchers are really done and cleaned up. | |
88 pending_transfer_ended_ = true; | |
89 LOG(INFO) << "terminating transfer"; | |
90 fetcher->TerminateTransfer(); | |
91 } | |
92 } | |
93 | |
94 // State change: Downloading or Pending transfer ended -> Stopped | |
95 void MultiRangeHTTPFetcher::TransferEnded(HttpFetcher* fetcher, | |
96 bool successful) { | |
97 CHECK(base_fetcher_active_) << "Transfer ended unexpectedly."; | |
petkov
2010/12/17 18:50:24
Btw, you could also CHECK here that fetcher == bas
adlr
2010/12/17 19:34:15
Done.
| |
98 pending_transfer_ended_ = false; | |
99 http_response_code_ = fetcher->http_response_code(); | |
100 LOG(INFO) << "TransferEnded w/ code " << http_response_code_; | |
101 if (terminating_) { | |
102 LOG(INFO) << "Terminating."; | |
103 Reset(); | |
104 // Note that after the callback returns this object may be destroyed. | |
105 if (delegate_) | |
106 delegate_->TransferTerminated(this); | |
107 return; | |
108 } | |
109 | |
110 // If we didn't get enough bytes, it's failure | |
111 if (ranges_[current_index_].second >= 0) { | |
112 if (bytes_received_this_range_ < ranges_[current_index_].second) { | |
113 // Failure | |
114 LOG(INFO) << "Didn't get enough bytes. Ending w/ failure."; | |
115 Reset(); | |
116 // Note that after the callback returns this object may be destroyed. | |
117 if (delegate_) | |
118 delegate_->TransferComplete(this, false); | |
119 return; | |
120 } | |
121 // We got enough bytes and there were bytes specified, so this is success. | |
122 successful = true; | |
123 } | |
124 | |
125 // If we have another fetcher, use that. | |
126 if (current_index_ + 1 < ranges_.size()) { | |
127 LOG(INFO) << "Starting next transfer."; | |
petkov
2010/12/17 13:37:25
maybe include the index in the log...
adlr
2010/12/17 19:34:15
Done.
| |
128 current_index_++; | |
129 StartTransfer(); | |
130 return; | |
131 } | |
132 | |
133 LOG(INFO) << "Done w/ all transfers"; | |
134 Reset(); | |
135 // Note that after the callback returns this object may be destroyed. | |
136 if (delegate_) | |
137 delegate_->TransferComplete(this, successful); | |
138 } | |
139 | |
140 void MultiRangeHTTPFetcher::TransferComplete(HttpFetcher* fetcher, | |
141 bool successful) { | |
142 LOG(INFO) << "Received transfer complete."; | |
143 TransferEnded(fetcher, successful); | |
144 } | |
145 void MultiRangeHTTPFetcher::TransferTerminated(HttpFetcher* fetcher) { | |
petkov
2010/12/17 13:37:25
add a blank line
adlr
2010/12/17 19:34:15
Done.
| |
146 LOG(INFO) << "Received transfer terminated."; | |
147 TransferEnded(fetcher, false); | |
148 } | |
149 | |
150 void MultiRangeHTTPFetcher::Reset() { | |
151 base_fetcher_active_ = pending_transfer_ended_ = terminating_ = false; | |
152 current_index_ = 0; | |
153 bytes_received_this_range_ = 0; | |
154 } | |
155 | |
156 } // namespace chromeos_update_engine | |
OLD | NEW |