Chromium Code Reviews| Index: chrome/browser/chromeos/printing/cups_print_job_manager_impl.cc |
| diff --git a/chrome/browser/chromeos/printing/cups_print_job_manager_impl.cc b/chrome/browser/chromeos/printing/cups_print_job_manager_impl.cc |
| index d333cb94627dfad9331afc59102276e97efb1daa..16be4881082c354374dccec85f3eb31b9af16bc1 100644 |
| --- a/chrome/browser/chromeos/printing/cups_print_job_manager_impl.cc |
| +++ b/chrome/browser/chromeos/printing/cups_print_job_manager_impl.cc |
| @@ -33,6 +33,9 @@ namespace { |
| // The rate in milliseconds at which we will poll CUPS for print job updates. |
| const int kPollRate = 1000; |
| +// Threshold for giving up on communicating with CUPS. |
| +const int kRetryMax = 6; |
| + |
| // Returns the equivalient CupsPrintJob#State from a CupsJob#JobState. |
| chromeos::CupsPrintJob::State ConvertState(printing::CupsJob::JobState state) { |
| using cpj = chromeos::CupsPrintJob::State; |
| @@ -61,6 +64,13 @@ chromeos::CupsPrintJob::State ConvertState(printing::CupsJob::JobState state) { |
| return cpj::STATE_NONE; |
| } |
| +chromeos::QueryResult QueryCups(::printing::CupsConnection* connection, |
| + const std::vector<std::string>& printer_ids) { |
| + chromeos::QueryResult result; |
| + result.success = connection->GetJobs(printer_ids, &(result.queues)); |
|
Lei Zhang
2017/03/07 23:31:29
nit: Do you need the extra parenthesis around resu
skau
2017/03/10 01:07:00
Done.
|
| + return result; |
| +} |
| + |
| } // namespace |
| namespace chromeos { |
| @@ -134,6 +144,7 @@ bool CupsPrintJobManagerImpl::CreatePrintJob(const std::string& printer_name, |
| total_page_number); |
| std::string key = cpj->GetUniqueId(); |
| jobs_[key] = std::move(cpj); |
| + |
| CupsPrintJob* job = jobs_[key].get(); |
| NotifyJobCreated(job); |
| @@ -153,36 +164,68 @@ void CupsPrintJobManagerImpl::ScheduleQuery() { |
| void CupsPrintJobManagerImpl::ScheduleQuery(const base::TimeDelta& delay) { |
| if (!in_query_) { |
| in_query_ = true; |
| - content::BrowserThread::PostDelayedTask( |
| - content::BrowserThread::FILE_USER_BLOCKING, FROM_HERE, |
| - base::Bind(&CupsPrintJobManagerImpl::QueryCups, |
| + |
| + base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( |
| + FROM_HERE, |
| + base::Bind(&CupsPrintJobManagerImpl::PostQuery, |
| weak_ptr_factory_.GetWeakPtr()), |
| - base::TimeDelta::FromMilliseconds(kPollRate)); |
| + delay); |
| } |
| } |
| // Query CUPS asynchronously. Post results back to UI thread. |
|
Lei Zhang
2017/03/07 23:31:29
Can you move this to the header and consolidate it
skau
2017/03/10 01:07:00
Done.
|
| -void CupsPrintJobManagerImpl::QueryCups() { |
| - std::vector<::printing::CupsJob> jobs = cups_connection_.GetJobs(); |
| +void CupsPrintJobManagerImpl::PostQuery() { |
| + // The set of active printers is expected to be small. |
| + std::set<std::string> printer_ids; |
| + for (const auto& entry : jobs_) { |
| + printer_ids.insert(entry.second->printer().id()); |
| + } |
| + std::vector<std::string> ids{printer_ids.begin(), printer_ids.end()}; |
| - content::BrowserThread::PostTask( |
| - content::BrowserThread::ID::UI, FROM_HERE, |
| + content::BrowserThread::PostTaskAndReplyWithResult( |
| + content::BrowserThread::FILE_USER_BLOCKING, FROM_HERE, |
| + base::Bind(&QueryCups, &cups_connection_, ids), |
| base::Bind(&CupsPrintJobManagerImpl::UpdateJobs, |
| - weak_ptr_factory_.GetWeakPtr(), jobs)); |
| + weak_ptr_factory_.GetWeakPtr())); |
| } |
| // Use job information to update local job states. Previously completed jobs |
| // could be in |jobs| but those are ignored as we will not emit updates for them |
| // after they are completed. |
| -void CupsPrintJobManagerImpl::UpdateJobs( |
| - const std::vector<::printing::CupsJob>& jobs) { |
| +void CupsPrintJobManagerImpl::UpdateJobs(const QueryResult& result) { |
| + const std::vector<::printing::QueueStatus>& queues = result.queues; |
| + |
| + // Query has completed. Allow more queries. |
| in_query_ = false; |
| + // If the query failed, either retry or purge. |
| + if (!result.success) { |
| + retry_count_++; |
| + LOG(WARNING) << "Failed to query CUPS for queue status. Schedule retry (" |
| + << retry_count_ << ")"; |
| + if (retry_count_ > kRetryMax) { |
| + LOG(ERROR) << "CUPS is unreachable. Giving up on all jobs."; |
| + PurgeJobs(); |
| + } else { |
| + // Schedule another query with a larger delay. |
| + DCHECK_GE(1, retry_count_); |
| + ScheduleQuery( |
| + base::TimeDelta::FromMilliseconds(kPollRate * retry_count_)); |
| + } |
| + return; |
| + } |
| + |
| + // A query has completed. Reset retry counter. |
| + retry_count_ = 0; |
| + |
| std::vector<std::string> active_jobs; |
| - for (auto& job : jobs) { |
| - std::string key = CupsPrintJob::GetUniqueId(job.printer_id, job.id); |
| - const auto& entry = jobs_.find(key); |
| - if (entry != jobs_.end()) { |
| + for (const auto& queue : queues) { |
| + for (auto& job : queue.jobs) { |
| + std::string key = CupsPrintJob::GetUniqueId(job.printer_id, job.id); |
| + const auto& entry = jobs_.find(key); |
| + if (entry == jobs_.end()) |
| + continue; |
| + |
| CupsPrintJob* print_job = entry->second.get(); |
| // Update a job we're tracking. |
| @@ -199,18 +242,23 @@ void CupsPrintJobManagerImpl::UpdateJobs( |
| // Keep polling until all jobs complete or error. |
| if (!active_jobs.empty()) { |
| + // During normal operations, we poll at the default rate. |
| ScheduleQuery(); |
| } else if (!jobs_.empty()) { |
| // We're tracking jobs that we didn't receive an update for. Something bad |
| // has happened. |
| LOG(ERROR) << "Lost track of (" << jobs_.size() << ") jobs"; |
| - for (const auto& entry : jobs_) { |
| - // Declare all lost jobs errors. |
| - JobStateUpdated(entry.second.get(), CupsPrintJob::State::STATE_ERROR); |
| - } |
| + PurgeJobs(); |
| + } |
| +} |
| - jobs_.clear(); |
| +void CupsPrintJobManagerImpl::PurgeJobs() { |
| + for (const auto& entry : jobs_) { |
| + // Declare all lost jobs errors. |
| + JobStateUpdated(entry.second.get(), CupsPrintJob::State::STATE_ERROR); |
| } |
| + |
| + jobs_.clear(); |
| } |
| void CupsPrintJobManagerImpl::JobStateUpdated(CupsPrintJob* job, |