blob: 492a0f0af0f826d0c18b1747b1bdaecd3f0bab04 [file] [log] [blame]
// Copyright 2012 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// An abstraction for scheduling recurring tasks. Combines idempotent scheduling
// and smearing with conditional retries and exponential backoff. Does not
// implement throttling. Designed to support a variety of use cases, including
// the following capabilities.
//
// * Idempotent scheduling, e.g., ensuring that a batching task is scheduled
// exactly once.
// * Recurring tasks, e.g., periodic heartbeats.
// * Retriable actions aimed at state change, e.g., sending initialization
// messages.
//
// Each instance of this class manages the state for a single task. See the
// invalidation-client-impl.cc for examples.
#ifndef GOOGLE_CACHEINVALIDATION_IMPL_RECURRING_TASK_H_
#define GOOGLE_CACHEINVALIDATION_IMPL_RECURRING_TASK_H_
#include "google/cacheinvalidation/include/system-resources.h"
#include "google/cacheinvalidation/impl/exponential-backoff-delay-generator.h"
#include "google/cacheinvalidation/impl/smearer.h"
namespace invalidation {
class RecurringTask {
public:
/* Creates a recurring task with the given parameters. The specs of the
* parameters are given in the instance variables.
*
* The created task is first scheduled with a smeared delay of
* |initial_delay|. If the |this->run()| returns true on its execution, the
* task is rescheduled after a |timeout_delay| + smeared delay of
* |initial_delay| or |timeout_delay| + |delay_generator->GetNextDelay()|
* depending on whether the |delay_generator| is null or not.
*
* Space for |scheduler|, |logger|, |smearer| is owned by the caller.
* Space for |delay_generator| is owned by the callee.
*/
RecurringTask(string name, Scheduler* scheduler, Logger* logger,
Smearer* smearer, ExponentialBackoffDelayGenerator* delay_generator,
TimeDelta initial_delay, TimeDelta timeout_delay);
virtual ~RecurringTask() {}
/* Run the task and return true if the task should be rescheduled after a
* timeout. If false is returned, the task is not scheduled again until
* |ensure_scheduled| is called again.
*/
virtual bool RunTask() = 0;
/* Ensures that the task is scheduled (with |debug_reason| as the reason to be
* printed for debugging purposes). If the task has been scheduled, it is
* not scheduled again.
*
* REQUIRES: Must be called from the scheduler thread.
*/
void EnsureScheduled(string debug_reason);
/* Space for the returned Smearer is still owned by this class. */
Smearer* smearer() {
return smearer_;
}
private:
/* Run the task and check if it needs to be rescheduled. If so, reschedule it
* after the appropriate delay.
*/
void RunTaskAndRescheduleIfNeeded();
/* Ensures that the task is scheduled if it is already not scheduled. If
* already scheduled, this method is a no-op. If |is_retry| is |false|, smears
* the |initial_delay_| and uses that delay for scheduling. If |is_retry| is
* true, it determines the new delay to be
* |timeout_delay_ + delay_generator.GetNextDelay()| if |delay_generator| is
* non-null. If |delay_generator| is null, schedules the task after a delay of
* |timeout_delay_| + smeared value of |initial_delay_|.
*
* REQUIRES: Must be called from the scheduler thread.
*/
void EnsureScheduled(bool is_retry, string debug_reason);
/* Name of the task (for debugging purposes mostly). */
string name_;
/* Scheduler for the scheduling the task as needed. */
Scheduler* scheduler_;
/* A logger. */
Logger* logger_;
/* A smearer for spreading the delays. */
Smearer* smearer_;
/* A delay generator for exponential backoff. */
scoped_ptr<ExponentialBackoffDelayGenerator> delay_generator_;
/*
* The time after which the task is scheduled first. If no delayGenerator is
* specified, this is also the delay used for retries.
*/
TimeDelta initial_delay_;
/* For a task that is retried, add this time to the delay. */
TimeDelta timeout_delay_;
/* If the task has been currently scheduled. */
bool is_scheduled_;
DISALLOW_COPY_AND_ASSIGN(RecurringTask);
};
} // namespace invalidation
#endif // GOOGLE_CACHEINVALIDATION_IMPL_RECURRING_TASK_H_