Do not reschedule all alarms when adding a new alarm

BUG=338900

Review URL: https://codereview.chromium.org/145353013

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@247823 0039d316-1c4b-4281-b951-d872f2087c98
parent f45f5fb9
......@@ -236,8 +236,10 @@ void AlarmManager::RemoveAlarmIterator(const AlarmIterator& iter) {
// Cancel the timer if there are no more alarms.
// We don't need to reschedule the poll otherwise, because in
// the worst case we would just poll one extra time.
if (alarms_.empty())
if (alarms_.empty()) {
timer_.Stop();
next_poll_time_ = base::Time();
}
}
void AlarmManager::OnAlarm(AlarmIterator it) {
......@@ -278,8 +280,10 @@ void AlarmManager::AddAlarmImpl(const std::string& extension_id,
RemoveAlarmIterator(old_alarm);
alarms_[extension_id].push_back(alarm);
ScheduleNextPoll();
base::Time alarm_time =
base::Time::FromJsTime(alarm.js_alarm->scheduled_time);
if (next_poll_time_.is_null() || alarm_time < next_poll_time_)
SetNextPollTime(alarm_time);
}
void AlarmManager::WriteToStorage(const std::string& extension_id) {
......@@ -313,16 +317,22 @@ void AlarmManager::ReadFromStorage(const std::string& extension_id,
ready_actions_.erase(extension_id);
}
void AlarmManager::SetNextPollTime(const base::Time& time) {
next_poll_time_ = time;
timer_.Start(FROM_HERE,
std::max(base::TimeDelta::FromSeconds(0), time - clock_->Now()),
this,
&AlarmManager::PollAlarms);
}
void AlarmManager::ScheduleNextPoll() {
// If there are no alarms, stop the timer.
if (alarms_.empty()) {
timer_.Stop();
next_poll_time_ = base::Time();
return;
}
// TODO(yoz): Try not to reschedule every single time if we're adding
// a lot of alarms.
// Find the soonest alarm that is scheduled to run and the smallest
// granularity of any alarm.
// alarms_ guarantees that none of its contained lists are empty.
......@@ -356,13 +366,7 @@ void AlarmManager::ScheduleNextPoll() {
next_poll = soonest_alarm_time;
// Schedule the poll.
test_next_poll_time_ = next_poll;
base::TimeDelta delay = std::max(base::TimeDelta::FromSeconds(0),
next_poll - clock_->Now());
timer_.Start(FROM_HERE,
delay,
this,
&AlarmManager::PollAlarms);
SetNextPollTime(next_poll);
}
void AlarmManager::PollAlarms() {
......
......@@ -184,6 +184,10 @@ class AlarmManager
void ReadFromStorage(const std::string& extension_id,
scoped_ptr<base::Value> value);
// Set the timer to go off at the specified |time|, and set |next_poll_time|
// appropriately.
void SetNextPollTime(const base::Time& time);
// Schedules the next poll of alarms for when the next soonest alarm runs,
// but not more often than the minimum granularity of all alarms.
void ScheduleNextPoll();
......@@ -226,8 +230,8 @@ class AlarmManager
// The previous time that alarms were run.
base::Time last_poll_time_;
// Next poll's time. Used only by unit tests.
base::Time test_next_poll_time_;
// Next poll's time.
base::Time next_poll_time_;
DISALLOW_COPY_AND_ASSIGN(AlarmManager);
};
......
......@@ -441,7 +441,7 @@ class ExtensionAlarmsSchedulingTest : public ExtensionAlarmsTest {
CHECK(alarm);
const base::Time scheduled_time =
base::Time::FromJsTime(alarm->js_alarm->scheduled_time);
EXPECT_EQ(scheduled_time, alarm_manager_->test_next_poll_time_);
EXPECT_EQ(scheduled_time, alarm_manager_->next_poll_time_);
}
static void RemoveAlarmCallback (bool success) { EXPECT_TRUE(success); }
......@@ -501,7 +501,7 @@ TEST_F(ExtensionAlarmsSchedulingTest, PollScheduling) {
base::MessageLoop::current()->Run();
EXPECT_EQ(base::Time::FromJsTime(3 * 60000) +
base::TimeDelta::FromMinutes(3),
alarm_manager_->test_next_poll_time_);
alarm_manager_->next_poll_time_);
RemoveAllAlarms();
}
{
......@@ -521,7 +521,7 @@ TEST_F(ExtensionAlarmsSchedulingTest, PollScheduling) {
base::MessageLoop::current()->Run();
EXPECT_EQ(base::Time::FromJsTime(4 * 60000) +
base::TimeDelta::FromMinutes(4),
alarm_manager_->test_next_poll_time_);
alarm_manager_->next_poll_time_);
RemoveAllAlarms();
}
}
......@@ -535,7 +535,7 @@ TEST_F(ExtensionAlarmsSchedulingTest, ReleasedExtensionPollsInfrequently) {
// On startup (when there's no "last poll"), we let alarms fire as
// soon as they're scheduled.
EXPECT_DOUBLE_EQ(300010, alarm_manager_->test_next_poll_time_.ToJsTime());
EXPECT_DOUBLE_EQ(300010, alarm_manager_->next_poll_time_.ToJsTime());
alarm_manager_->last_poll_time_ = base::Time::FromJsTime(290000);
// In released extensions, we set the granularity to at least 1
......@@ -544,7 +544,7 @@ TEST_F(ExtensionAlarmsSchedulingTest, ReleasedExtensionPollsInfrequently) {
alarm_manager_->ScheduleNextPoll();
EXPECT_DOUBLE_EQ((alarm_manager_->last_poll_time_ +
base::TimeDelta::FromMinutes(1)).ToJsTime(),
alarm_manager_->test_next_poll_time_.ToJsTime());
alarm_manager_->next_poll_time_.ToJsTime());
}
TEST_F(ExtensionAlarmsSchedulingTest, TimerRunning) {
......@@ -576,7 +576,7 @@ TEST_F(ExtensionAlarmsSchedulingTest, MinimumGranularity) {
alarm_manager_->ScheduleNextPoll();
EXPECT_DOUBLE_EQ((alarm_manager_->last_poll_time_ +
base::TimeDelta::FromMinutes(1)).ToJsTime(),
alarm_manager_->test_next_poll_time_.ToJsTime());
alarm_manager_->next_poll_time_.ToJsTime());
}
TEST_F(ExtensionAlarmsSchedulingTest, DifferentMinimumGranularities) {
......@@ -601,7 +601,7 @@ TEST_F(ExtensionAlarmsSchedulingTest, DifferentMinimumGranularities) {
// first alarm should go off.
EXPECT_DOUBLE_EQ((alarm_manager_->last_poll_time_ +
base::TimeDelta::FromSeconds(12)).ToJsTime(),
alarm_manager_->test_next_poll_time_.ToJsTime());
alarm_manager_->next_poll_time_.ToJsTime());
}
// Test that scheduled alarms go off at set intervals, even if their actual
......@@ -616,7 +616,7 @@ TEST_F(ExtensionAlarmsSchedulingTest, RepeatingAlarmsScheduledPredictably) {
// We expect the first poll to happen two minutes from the start.
EXPECT_DOUBLE_EQ((alarm_manager_->last_poll_time_ +
base::TimeDelta::FromSeconds(120)).ToJsTime(),
alarm_manager_->test_next_poll_time_.ToJsTime());
alarm_manager_->next_poll_time_.ToJsTime());
// Poll more than two minutes later.
test_clock_->Advance(base::TimeDelta::FromSeconds(125));
......@@ -630,7 +630,7 @@ TEST_F(ExtensionAlarmsSchedulingTest, RepeatingAlarmsScheduledPredictably) {
// Last poll was at 125 seconds; next poll should be at 240 seconds.
EXPECT_DOUBLE_EQ((alarm_manager_->last_poll_time_ +
base::TimeDelta::FromSeconds(115)).ToJsTime(),
alarm_manager_->test_next_poll_time_.ToJsTime());
alarm_manager_->next_poll_time_.ToJsTime());
// Completely miss a scheduled trigger.
test_clock_->Advance(base::TimeDelta::FromSeconds(255)); // Total Time: 380s
......@@ -644,7 +644,7 @@ TEST_F(ExtensionAlarmsSchedulingTest, RepeatingAlarmsScheduledPredictably) {
// Last poll was at 380 seconds; next poll should be at 480 seconds.
EXPECT_DOUBLE_EQ((alarm_manager_->last_poll_time_ +
base::TimeDelta::FromSeconds(100)).ToJsTime(),
alarm_manager_->test_next_poll_time_.ToJsTime());
alarm_manager_->next_poll_time_.ToJsTime());
}
} // namespace extensions
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment