| OLD | NEW |
| (Empty) |
| 1 // Copyright 2007-2009 Google Inc. | |
| 2 // | |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
| 4 // you may not use this file except in compliance with the License. | |
| 5 // You may obtain a copy of the License at | |
| 6 // | |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 | |
| 8 // | |
| 9 // Unless required by applicable law or agreed to in writing, software | |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 12 // See the License for the specific language governing permissions and | |
| 13 // limitations under the License. | |
| 14 // ======================================================================== | |
| 15 | |
| 16 #include "omaha/core/scheduler.h" | |
| 17 #include <algorithm> | |
| 18 #include "omaha/base/debug.h" | |
| 19 #include "omaha/base/error.h" | |
| 20 #include "omaha/base/highres_timer-win32.h" | |
| 21 #include "omaha/base/logging.h" | |
| 22 #include "omaha/base/queue_timer.h" | |
| 23 #include "omaha/common/config_manager.h" | |
| 24 #include "omaha/core/core.h" | |
| 25 #include "omaha/core/core_metrics.h" | |
| 26 | |
| 27 namespace omaha { | |
| 28 | |
| 29 Scheduler::Scheduler(const Core& core) | |
| 30 : core_(core) { | |
| 31 CORE_LOG(L1, (_T("[Scheduler::Scheduler]"))); | |
| 32 } | |
| 33 | |
| 34 Scheduler::~Scheduler() { | |
| 35 CORE_LOG(L1, (_T("[Scheduler::~Scheduler]"))); | |
| 36 | |
| 37 if (update_timer_.get()) { | |
| 38 update_timer_.reset(NULL); | |
| 39 } | |
| 40 | |
| 41 if (code_red_timer_.get()) { | |
| 42 code_red_timer_.reset(NULL); | |
| 43 } | |
| 44 | |
| 45 if (timer_queue_) { | |
| 46 // The destructor blocks on deleting the timer queue and it waits for | |
| 47 // all timer callbacks to complete. | |
| 48 ::DeleteTimerQueueEx(timer_queue_, INVALID_HANDLE_VALUE); | |
| 49 } | |
| 50 } | |
| 51 | |
| 52 HRESULT Scheduler::Initialize() { | |
| 53 CORE_LOG(L1, (_T("[Scheduler::Initialize]"))); | |
| 54 | |
| 55 timer_queue_ = ::CreateTimerQueue(); | |
| 56 if (!timer_queue_) { | |
| 57 return HRESULTFromLastError(); | |
| 58 } | |
| 59 | |
| 60 cr_debug_timer_.reset(new HighresTimer); | |
| 61 | |
| 62 update_timer_.reset(new QueueTimer(timer_queue_, | |
| 63 &Scheduler::TimerCallback, | |
| 64 this)); | |
| 65 code_red_timer_.reset(new QueueTimer(timer_queue_, | |
| 66 &Scheduler::TimerCallback, | |
| 67 this)); | |
| 68 | |
| 69 ConfigManager* config_manager = ConfigManager::Instance(); | |
| 70 int cr_timer_interval_ms = config_manager->GetCodeRedTimerIntervalMs(); | |
| 71 VERIFY1(SUCCEEDED(ScheduleCodeRedTimer(cr_timer_interval_ms))); | |
| 72 | |
| 73 int au_timer_interval_ms = config_manager->GetUpdateWorkerStartUpDelayMs(); | |
| 74 VERIFY1(SUCCEEDED(ScheduleUpdateTimer(au_timer_interval_ms))); | |
| 75 | |
| 76 return S_OK; | |
| 77 } | |
| 78 | |
| 79 void Scheduler::TimerCallback(QueueTimer* timer) { | |
| 80 ASSERT1(timer); | |
| 81 Scheduler* scheduler = static_cast<Scheduler*>(timer->ctx()); | |
| 82 ASSERT1(scheduler); | |
| 83 scheduler->HandleCallback(timer); | |
| 84 } | |
| 85 | |
| 86 // First, do the useful work and then reschedule the timer. Otherwise, it is | |
| 87 // possible that timer notifications overlap, and the timer can't be further | |
| 88 // rescheduled: http://b/1228095 | |
| 89 void Scheduler::HandleCallback(QueueTimer* timer) { | |
| 90 ConfigManager* config_manager = ConfigManager::Instance(); | |
| 91 if (update_timer_.get() == timer) { | |
| 92 core_.StartUpdateWorker(); | |
| 93 int au_timer_interval_ms = config_manager->GetAutoUpdateTimerIntervalMs(); | |
| 94 VERIFY1(SUCCEEDED(ScheduleUpdateTimer(au_timer_interval_ms))); | |
| 95 } else if (code_red_timer_.get() == timer) { | |
| 96 core_.StartCodeRed(); | |
| 97 int actual_time_ms = static_cast<int>(cr_debug_timer_->GetElapsedMs()); | |
| 98 metric_core_cr_actual_timer_interval_ms = actual_time_ms; | |
| 99 CORE_LOG(L3, (_T("[code red actual period][%d ms]"), actual_time_ms)); | |
| 100 int cr_timer_interval_ms = config_manager->GetCodeRedTimerIntervalMs(); | |
| 101 VERIFY1(SUCCEEDED(ScheduleCodeRedTimer(cr_timer_interval_ms))); | |
| 102 } else { | |
| 103 ASSERT1(false); | |
| 104 } | |
| 105 | |
| 106 // Since core is a long lived process, aggregate its metrics once in a while. | |
| 107 core_.AggregateMetrics(); | |
| 108 } | |
| 109 | |
| 110 HRESULT Scheduler::ScheduleUpdateTimer(int interval_ms) { | |
| 111 HRESULT hr = update_timer_->Start(interval_ms, 0, WT_EXECUTEONLYONCE); | |
| 112 if (FAILED(hr)) { | |
| 113 CORE_LOG(LE, (_T("[can't start update queue timer][0x%08x]"), hr)); | |
| 114 } | |
| 115 return hr; | |
| 116 } | |
| 117 | |
| 118 HRESULT Scheduler::ScheduleCodeRedTimer(int interval_ms) { | |
| 119 metric_core_cr_expected_timer_interval_ms = interval_ms; | |
| 120 cr_debug_timer_->Start(); | |
| 121 HRESULT hr = code_red_timer_->Start(interval_ms, 0, WT_EXECUTEONLYONCE); | |
| 122 if (FAILED(hr)) { | |
| 123 CORE_LOG(LE, (_T("[can't start Code Red queue timer][0x%08x]"), hr)); | |
| 124 } | |
| 125 return hr; | |
| 126 } | |
| 127 | |
| 128 } // namespace omaha | |
| 129 | |
| OLD | NEW |