| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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 "components/translate/core/browser/ranker_model_loader.h" | 5 #include "components/translate/core/browser/ranker_model_loader.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 namespace translate { | 26 namespace translate { |
| 27 namespace { | 27 namespace { |
| 28 | 28 |
| 29 using chrome_intelligence::RankerModel; | 29 using chrome_intelligence::RankerModel; |
| 30 using chrome_intelligence::RankerModelProto; | 30 using chrome_intelligence::RankerModelProto; |
| 31 | 31 |
| 32 constexpr int kUrlFetcherId = 2; | 32 constexpr int kUrlFetcherId = 2; |
| 33 | 33 |
| 34 // The maximum number of model download attempts to make. Download may fail | 34 // The maximum number of model download attempts to make. Download may fail |
| 35 // due to server error or network availability issues. | 35 // due to server error or network availability issues. |
| 36 constexpr int kMaxRetryOn5xx = 8; | 36 constexpr int kMaxDownloadAttempts = 8; |
| 37 | 37 |
| 38 // The minimum duration, in minutes, between download attempts. | 38 // The minimum duration, in minutes, between download attempts. |
| 39 constexpr int kMinRetryDelayMins = 3; | 39 constexpr int kMinRetryDelayMins = 3; |
| 40 | 40 |
| 41 // Suffixes for the various histograms produced by the backend. | 41 // Suffixes for the various histograms produced by the backend. |
| 42 const char kWriteTimerHistogram[] = ".Timer.WriteModel"; | 42 const char kWriteTimerHistogram[] = ".Timer.WriteModel"; |
| 43 const char kReadTimerHistogram[] = ".Timer.ReadModel"; | 43 const char kReadTimerHistogram[] = ".Timer.ReadModel"; |
| 44 const char kDownloadTimerHistogram[] = ".Timer.DownloadModel"; | 44 const char kDownloadTimerHistogram[] = ".Timer.DownloadModel"; |
| 45 const char kParsetimerHistogram[] = ".Timer.ParseModel"; | 45 const char kParsetimerHistogram[] = ".Timer.ParseModel"; |
| 46 const char kModelStatusHistogram[] = ".Model.Status"; | 46 const char kModelStatusHistogram[] = ".Model.Status"; |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 141 // or the cached model is invalid/expired. | 141 // or the cached model is invalid/expired. |
| 142 const GURL model_url_; | 142 const GURL model_url_; |
| 143 | 143 |
| 144 // This will prefix all UMA metrics generated by the model loader. | 144 // This will prefix all UMA metrics generated by the model loader. |
| 145 const std::string uma_prefix_; | 145 const std::string uma_prefix_; |
| 146 | 146 |
| 147 // Used to download model data from |model_url_|. | 147 // Used to download model data from |model_url_|. |
| 148 // TODO(rogerm): Use net::URLFetcher directly? | 148 // TODO(rogerm): Use net::URLFetcher directly? |
| 149 std::unique_ptr<TranslateURLFetcher> url_fetcher_; | 149 std::unique_ptr<TranslateURLFetcher> url_fetcher_; |
| 150 | 150 |
| 151 // The number of times the backend has attempted to download the model. |
| 152 int download_attempts_; |
| 153 |
| 151 // The next time before which no new attempts to download the model should be | 154 // The next time before which no new attempts to download the model should be |
| 152 // attempted. | 155 // attempted. |
| 153 base::TimeTicks next_earliest_download_time_; | 156 base::TimeTicks next_earliest_download_time_; |
| 154 | 157 |
| 155 // Tracks the last time of the last attempt to download a model. Used for UMA | 158 // Tracks the last time of the last attempt to download a model. Used for UMA |
| 156 // reporting of download duration. | 159 // reporting of download duration. |
| 157 base::TimeTicks download_start_time_; | 160 base::TimeTicks download_start_time_; |
| 158 | 161 |
| 159 DISALLOW_COPY_AND_ASSIGN(Backend); | 162 DISALLOW_COPY_AND_ASSIGN(Backend); |
| 160 }; | 163 }; |
| 161 | 164 |
| 162 RankerModelLoader::Backend::Backend( | 165 RankerModelLoader::Backend::Backend( |
| 163 const ValidateModelCallback& validate_model_cb, | 166 const ValidateModelCallback& validate_model_cb, |
| 164 const InternalOnModelAvailableCallback& internal_on_model_available_cb, | 167 const InternalOnModelAvailableCallback& internal_on_model_available_cb, |
| 165 const base::FilePath& model_path, | 168 const base::FilePath& model_path, |
| 166 const GURL& model_url, | 169 const GURL& model_url, |
| 167 const std::string& uma_prefix) | 170 const std::string& uma_prefix) |
| 168 : origin_task_runner_(base::SequencedTaskRunnerHandle::Get()), | 171 : origin_task_runner_(base::SequencedTaskRunnerHandle::Get()), |
| 169 validate_model_cb_(validate_model_cb), | 172 validate_model_cb_(validate_model_cb), |
| 170 internal_on_model_available_cb_(internal_on_model_available_cb), | 173 internal_on_model_available_cb_(internal_on_model_available_cb), |
| 171 model_path_(model_path), | 174 model_path_(model_path), |
| 172 model_url_(model_url), | 175 model_url_(model_url), |
| 173 uma_prefix_(uma_prefix) { | 176 uma_prefix_(uma_prefix), |
| 177 url_fetcher_(base::MakeUnique<TranslateURLFetcher>(kUrlFetcherId)), |
| 178 download_attempts_(0) { |
| 174 sequence_checker_.DetachFromSequence(); | 179 sequence_checker_.DetachFromSequence(); |
| 175 } | 180 } |
| 176 | 181 |
| 177 RankerModelLoader::Backend::~Backend() {} | 182 RankerModelLoader::Backend::~Backend() {} |
| 178 | 183 |
| 179 RankerModelStatus RankerModelLoader::Backend::ReportModelStatus( | 184 RankerModelStatus RankerModelLoader::Backend::ReportModelStatus( |
| 180 RankerModelStatus model_status) { | 185 RankerModelStatus model_status) { |
| 181 base::HistogramBase* histogram = base::LinearHistogram::FactoryGet( | 186 base::HistogramBase* histogram = base::LinearHistogram::FactoryGet( |
| 182 uma_prefix_ + kModelStatusHistogram, 1, | 187 uma_prefix_ + kModelStatusHistogram, 1, |
| 183 static_cast<int>(RankerModelStatus::MAX), | 188 static_cast<int>(RankerModelStatus::MAX), |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 251 } | 256 } |
| 252 | 257 |
| 253 // Reaching this point means that a model download is required. If there is | 258 // Reaching this point means that a model download is required. If there is |
| 254 // no download URL configured, then there is nothing further to do. | 259 // no download URL configured, then there is nothing further to do. |
| 255 AsyncLoadFromURL(); | 260 AsyncLoadFromURL(); |
| 256 } | 261 } |
| 257 | 262 |
| 258 void RankerModelLoader::Backend::AsyncLoadFromURL() { | 263 void RankerModelLoader::Backend::AsyncLoadFromURL() { |
| 259 DCHECK(sequence_checker_.CalledOnValidSequence()); | 264 DCHECK(sequence_checker_.CalledOnValidSequence()); |
| 260 | 265 |
| 261 if (!model_url_.is_valid()) | 266 if (!model_url_.is_valid()) { |
| 267 // Notify the loader that model loading has been abandoned. |
| 268 TransferModelToClient(nullptr, true); |
| 262 return; | 269 return; |
| 270 } |
| 263 | 271 |
| 264 // Do nothing if the download attempts should be throttled. | 272 // Do nothing if the download attempts should be throttled. |
| 265 if (base::TimeTicks::Now() < next_earliest_download_time_) { | 273 if (base::TimeTicks::Now() < next_earliest_download_time_) { |
| 266 DVLOG(2) << "Last download attempt was too recent."; | 274 DVLOG(2) << "Last download attempt was too recent."; |
| 267 return; | 275 return; |
| 268 } | 276 } |
| 269 | 277 |
| 270 // Otherwise, initialize the model fetcher to be non-null and trigger an | |
| 271 // initial download attempt. | |
| 272 if (!url_fetcher_) { | |
| 273 url_fetcher_ = base::MakeUnique<TranslateURLFetcher>(kUrlFetcherId); | |
| 274 url_fetcher_->set_max_retry_on_5xx(kMaxRetryOn5xx); | |
| 275 } | |
| 276 | |
| 277 // If a request is already in flight, do not issue a new one. | 278 // If a request is already in flight, do not issue a new one. |
| 278 if (url_fetcher_->state() == TranslateURLFetcher::REQUESTING) { | 279 if (url_fetcher_->state() == TranslateURLFetcher::REQUESTING) { |
| 279 DVLOG(2) << "Download is in progress."; | 280 DVLOG(2) << "Download is in progress."; |
| 280 return; | 281 return; |
| 281 } | 282 } |
| 282 | 283 |
| 284 // If all allowed attempts have been exhausted, notify the loader that the |
| 285 // backend has abandoned the download. |
| 286 if (++download_attempts_ > kMaxDownloadAttempts) { |
| 287 DVLOG(2) << "Model download abandoned."; |
| 288 ReportModelStatus(RankerModelStatus::DOWNLOAD_FAILED); |
| 289 TransferModelToClient(nullptr, true); |
| 290 return; |
| 291 } |
| 292 |
| 283 DVLOG(2) << "Downloading model from: " << model_url_; | 293 DVLOG(2) << "Downloading model from: " << model_url_; |
| 284 | 294 |
| 285 // Reset the time of the next earliest allowable download attempt. | 295 // Kick off the next download attempt and reset the time of the next earliest |
| 296 // allowable download attempt. |
| 297 download_start_time_ = base::TimeTicks::Now(); |
| 286 next_earliest_download_time_ = | 298 next_earliest_download_time_ = |
| 287 base::TimeTicks::Now() + base::TimeDelta::FromMinutes(kMinRetryDelayMins); | 299 download_start_time_ + base::TimeDelta::FromMinutes(kMinRetryDelayMins); |
| 288 | 300 url_fetcher_->Request( |
| 289 // Kick off the next download attempt. | |
| 290 download_start_time_ = base::TimeTicks::Now(); | |
| 291 bool result = url_fetcher_->Request( | |
| 292 model_url_, base::Bind(&RankerModelLoader::Backend::OnDownloadComplete, | 301 model_url_, base::Bind(&RankerModelLoader::Backend::OnDownloadComplete, |
| 293 base::Unretained(this))); | 302 base::Unretained(this))); |
| 294 | |
| 295 // The maximum number of download attempts has been surpassed. Don't make | |
| 296 // any further attempts. | |
| 297 if (!result) { | |
| 298 DVLOG(2) << "Model download abandoned."; | |
| 299 ReportModelStatus(RankerModelStatus::DOWNLOAD_FAILED); | |
| 300 url_fetcher_.reset(); | |
| 301 | |
| 302 // Notify the loader that model loading has been abandoned. | |
| 303 TransferModelToClient(nullptr, true); | |
| 304 } | |
| 305 } | 303 } |
| 306 | 304 |
| 307 void RankerModelLoader::Backend::OnDownloadComplete(int /* id */, | 305 void RankerModelLoader::Backend::OnDownloadComplete(int /* id */, |
| 308 bool success, | 306 bool success, |
| 309 const std::string& data) { | 307 const std::string& data) { |
| 310 DCHECK(sequence_checker_.CalledOnValidSequence()); | 308 DCHECK(sequence_checker_.CalledOnValidSequence()); |
| 311 | 309 |
| 312 // Record the duration of the download. | 310 // Record the duration of the download. |
| 313 base::TimeDelta duration = base::TimeTicks::Now() - download_start_time_; | 311 base::TimeDelta duration = base::TimeTicks::Now() - download_start_time_; |
| 314 base::HistogramBase* counter = base::Histogram::FactoryTimeGet( | 312 base::HistogramBase* counter = base::Histogram::FactoryTimeGet( |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 414 std::unique_ptr<RankerModel> model, | 412 std::unique_ptr<RankerModel> model, |
| 415 bool finished) { | 413 bool finished) { |
| 416 DCHECK(sequence_checker_.CalledOnValidSequence()); | 414 DCHECK(sequence_checker_.CalledOnValidSequence()); |
| 417 if (finished) | 415 if (finished) |
| 418 state_ = LoaderState::FINISHED; | 416 state_ = LoaderState::FINISHED; |
| 419 if (model) | 417 if (model) |
| 420 callback.Run(std::move(model)); | 418 callback.Run(std::move(model)); |
| 421 } | 419 } |
| 422 | 420 |
| 423 } // namespace translate | 421 } // namespace translate |
| OLD | NEW |