Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(390)

Side by Side Diff: third_party/cacheinvalidation/src/java/com/google/ipc/invalidation/ticl/RecurringTask.java

Issue 1162033004: Pull cacheinvalidations code directory into chromium repo. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright 2011 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package com.google.ipc.invalidation.ticl;
18
19 import com.google.ipc.invalidation.external.client.SystemResources.Logger;
20 import com.google.ipc.invalidation.external.client.SystemResources.Scheduler;
21 import com.google.ipc.invalidation.ticl.proto.Client.ExponentialBackoffState;
22 import com.google.ipc.invalidation.ticl.proto.JavaClient.RecurringTaskState;
23 import com.google.ipc.invalidation.util.ExponentialBackoffDelayGenerator;
24 import com.google.ipc.invalidation.util.InternalBase;
25 import com.google.ipc.invalidation.util.Marshallable;
26 import com.google.ipc.invalidation.util.NamedRunnable;
27 import com.google.ipc.invalidation.util.Preconditions;
28 import com.google.ipc.invalidation.util.Smearer;
29 import com.google.ipc.invalidation.util.TextBuilder;
30
31
32 /**
33 * An abstraction for scheduling recurring tasks. Combines idempotent scheduling and smearing with
34 * conditional retries and exponential backoff. Does not implement throttling. D esigned to support a
35 * variety of use cases, including:
36 *
37 * <ul>
38 * <li>Idempotent scheduling, e.g., ensuring that a batching task is scheduled e xactly once.
39 * <li>Recurring tasks, e.g., periodic heartbeats.
40 * <li>Retriable actions aimed at state change, e.g., sending initialization mes sages.
41 * </ul>
42 * Each instance of this class manages the state for a single task. Examples:
43 *
44 * <pre>
45 * batchingTask = new RecurringTask("Batching", scheduler, logger, smearer, null ,
46 * batchingDelayMs, NO_DELAY) {
47 * @Override
48 * public boolean runTask() {
49 * throttle.fire();
50 * return false; // don't reschedule.
51 * }
52 * };
53 * heartbeatTask = new RecurringTask("Heartbeat", scheduler, logger, smearer, nu ll,
54 * heartbeatDelayMs, NO_DELAY) {
55 * @Override
56 * public boolean runTask() {
57 * sendInfoMessageToServer(false, !registrationManager.isStateInSyncWithServe r());
58 * return true; // reschedule
59 * }
60 * };
61 * initializeTask = new RecurringTask("Token", scheduler, logger, smearer, expDe layGen, NO_DELAY,
62 * networkTimeoutMs) {
63 * @Override
64 * public boolean runTask() {
65 * // If token is still not assigned (as expected), sends a request. Otherwise , ignore.
66 * if (clientToken == null) {
67 * // Allocate a nonce and send a message requesting a new token.
68 * setNonce(ByteString.copyFromUtf8(Long.toString(internalScheduler.getCurre ntTimeMs())));
69 * protocolHandler.sendInitializeMessage(applicationClientId, nonce, debugSt ring);
70 * return true; // reschedule to check state, retry if necessary after time out
71 * } else {
72 * return false; // don't reschedule
73 * }
74 * }
75 * };
76 *</pre>
77 *
78 */
79 public abstract class RecurringTask extends InternalBase
80 implements Marshallable<RecurringTaskState> {
81
82 /** Name of the task (for debugging purposes mostly). */
83 private final String name;
84
85 /** A logger */
86 private final Logger logger;
87
88 /** Scheduler for the scheduling the task as needed. */
89 private final Scheduler scheduler;
90
91 /**
92 * The time after which the task is scheduled first. If no delayGenerator is s pecified, this is
93 * also the delay used for retries.
94 */
95 private final int initialDelayMs;
96
97 /** For a task that is retried, add this time to the delay. */
98 private final int timeoutDelayMs;
99
100 /** A smearer for spreading the delays. */
101 private final Smearer smearer;
102
103 /** A delay generator for exponential backoff. */
104 private final TiclExponentialBackoffDelayGenerator delayGenerator;
105
106 /** The runnable that is scheduled for the task. */
107 private final NamedRunnable runnable;
108
109 /** If the task has been currently scheduled. */
110 private boolean isScheduled;
111
112 /**
113 * Creates a recurring task with the given parameters. The specs of the parame ters are given in
114 * the instance variables.
115 * <p>
116 * The created task is first scheduled with a smeared delay of {@code initialD elayMs}. If the
117 * {@code this.run()} returns true on its execution, the task is rescheduled a fter a
118 * {@code timeoutDelayMs} + smeared delay of {@code initialDelayMs} or {@code timeoutDelayMs} +
119 * {@code delayGenerator.getNextDelay()} depending on whether the {@code delay Generator} is null
120 * or not.
121 */
122
123 public RecurringTask(String name, Scheduler scheduler, Logger logger, Smearer smearer,
124 TiclExponentialBackoffDelayGenerator delayGenerator,
125 final int initialDelayMs, final int timeoutDelayMs) {
126 this.delayGenerator = delayGenerator;
127 this.name = Preconditions.checkNotNull(name);
128 this.logger = Preconditions.checkNotNull(logger);
129 this.scheduler = Preconditions.checkNotNull(scheduler);
130 this.smearer = Preconditions.checkNotNull(smearer);
131 this.initialDelayMs = initialDelayMs;
132 this.isScheduled = false;
133 this.timeoutDelayMs = timeoutDelayMs;
134
135 // Create a runnable that runs the task. If the task asks for a retry, resch edule it after
136 // at a timeout delay. Otherwise, resets the delayGenerator.
137 this.runnable = createRunnable();
138 }
139
140 /**
141 * Creates a recurring task from {@code marshalledState}. Other parameters are as in the
142 * constructor above.
143 */
144 RecurringTask(String name, Scheduler scheduler, Logger logger, Smearer smearer ,
145 TiclExponentialBackoffDelayGenerator delayGenerator,
146 RecurringTaskState marshalledState) {
147 this(name, scheduler, logger, smearer, delayGenerator, marshalledState.getIn itialDelayMs(),
148 marshalledState.getTimeoutDelayMs());
149 this.isScheduled = marshalledState.getScheduled();
150 }
151
152 private NamedRunnable createRunnable() {
153 return new NamedRunnable(name) {
154 @Override
155 public void run() {
156 Preconditions.checkState(scheduler.isRunningOnThread(), "Not on schedule r thread");
157 isScheduled = false;
158 if (runTask()) {
159 // The task asked to be rescheduled, so reschedule it after a timeout has occured.
160 Preconditions.checkState((delayGenerator != null) || (initialDelayMs ! = 0),
161 "Spinning: No exp back off and initialdelay is zero");
162 ensureScheduled(true, "Retry");
163 } else if (delayGenerator != null) {
164 // The task asked not to be rescheduled. Treat it as having "succeede d" and reset the
165 // delay generator.
166 delayGenerator.reset();
167 }
168 }
169 };
170 }
171
172 /**
173 * Run the task and return true if the task should be rescheduled after a time out. If false is
174 * returned, the task is not scheduled again until {@code ensureScheduled} is called again.
175 */
176 public abstract boolean runTask();
177
178 /** Returns the smearer used for randomizing delays. */
179 Smearer getSmearer() {
180 return smearer;
181 }
182
183 /** Returns the delay generator, if any. */
184 ExponentialBackoffDelayGenerator getDelayGenerator() {
185 return delayGenerator;
186 }
187
188 /**
189 * Ensures that the task is scheduled (with {@code debugReason} as the reason to be printed
190 * for debugging purposes). If the task has been scheduled, it is not schedule d again.
191 * <p>
192 * REQUIRES: Must be called from the scheduler thread.
193 */
194
195 public void ensureScheduled(String debugReason) {
196 ensureScheduled(false, debugReason);
197 }
198
199 /**
200 * Ensures that the task is scheduled if it is already not scheduled. If alrea dy scheduled, this
201 * method is a no-op.
202 *
203 * @param isRetry If this is {@code false}, smears the {@code initialDelayMs} and uses that delay
204 * for scheduling. If {@code isRetry} is true, it determines the new de lay to be
205 * {@code timeoutDelayMs} + {@ocde delayGenerator.getNextDelay()} if
206 * {@code delayGenerator} is non-null. If {@code delayGenerator} is nul l, schedules the
207 * task after a delay of {@code timeoutDelayMs} + smeared value of {@co de initialDelayMs}
208 * <p>
209 * REQUIRES: Must be called from the scheduler thread.
210 */
211 private void ensureScheduled(boolean isRetry, String debugReason) {
212 Preconditions.checkState(scheduler.isRunningOnThread());
213 if (isScheduled) {
214 return;
215 }
216 final int delayMs;
217
218 if (isRetry) {
219 // For a retried task, determine the delay to be timeout + extra delay (de pending on whether
220 // a delay generator was provided or not).
221 if (delayGenerator != null) {
222 delayMs = timeoutDelayMs + delayGenerator.getNextDelay();
223 } else {
224 delayMs = timeoutDelayMs + smearer.getSmearedDelay(initialDelayMs);
225 }
226 } else {
227 delayMs = smearer.getSmearedDelay(initialDelayMs);
228 }
229
230 logger.fine("[%s] Scheduling %s with a delay %s, Now = %s", debugReason, nam e, delayMs,
231 scheduler.getCurrentTimeMs());
232 scheduler.schedule(delayMs, runnable);
233 isScheduled = true;
234 }
235
236 /** For use only in the Android scheduler. */
237 public NamedRunnable getRunnable() {
238 return runnable;
239 }
240
241 @Override
242 public RecurringTaskState marshal() {
243 ExponentialBackoffState backoffState =
244 (delayGenerator == null) ? null : delayGenerator.marshal();
245 return RecurringTaskState.create(initialDelayMs, timeoutDelayMs, isScheduled , backoffState);
246 }
247
248 @Override
249 public void toCompactString(TextBuilder builder) {
250 builder.append("<RecurringTask: name=").append(name)
251 .append(", initialDelayMs=").append(initialDelayMs)
252 .append(", timeoutDelayMs=").append(timeoutDelayMs)
253 .append(", isScheduled=").append(isScheduled)
254 .append(">");
255 }
256 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698