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 |