1 /*
2 * virtime.c: Time handling functions
3 *
4 * Copyright (C) 2006-2014 Red Hat, Inc.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library. If not, see
18 * <http://www.gnu.org/licenses/>.
19 *
20 * The intent is that this file provides a set of time APIs which
21 * are async signal safe, to allow use in between fork/exec eg by
22 * the logging code.
23 *
24 * The reality is that wsnprintf is technically unsafe. We ought
25 * to roll out our int -> str conversions to avoid this.
26 *
27 * We do *not* use regular libvirt error APIs for most of the code,
28 * since those are not async signal safe, and we dont want logging
29 * APIs generating timestamps to blow away real errors
30 */
31
32 #include <config.h>
33
34 #include <unistd.h>
35 #include <sys/time.h>
36
37 #include "virtime.h"
38 #include "viralloc.h"
39 #include "virerror.h"
40 #include "virlog.h"
41
42 #define VIR_FROM_THIS VIR_FROM_NONE
43
44 VIR_LOG_INIT("util.time");
45
46 /**
47 * virTimeMillisNowRaw:
48 * @now: filled with current time in milliseconds
49 *
50 * Retrieves the current system time, in milliseconds since the
51 * epoch
52 *
53 * Returns 0 on success, -1 on error with errno set
54 */
virTimeMillisNowRaw(unsigned long long * now)55 int virTimeMillisNowRaw(unsigned long long *now)
56 {
57 *now = g_get_real_time() / 1000;
58 return 0;
59 }
60
61
62 /**
63 * virTimeFieldsNowRaw:
64 * @fields: filled with current time fields
65 *
66 * Retrieves the current time, in broken-down field format.
67 * The time is always in UTC.
68 *
69 * Returns 0 on success, -1 on error with errno set
70 */
virTimeFieldsNowRaw(struct tm * fields)71 int virTimeFieldsNowRaw(struct tm *fields)
72 {
73 unsigned long long now;
74
75 if (virTimeMillisNowRaw(&now) < 0)
76 return -1;
77
78 virTimeFieldsThen(now, fields);
79
80 return 0;
81 }
82
83
84 #define SECS_PER_HOUR (60 * 60)
85 #define SECS_PER_DAY (SECS_PER_HOUR * 24)
86 #define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
87 #define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
88
89 static const unsigned short int mon_yday[2][13] = {
90 /* Normal years. */
91 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
92 /* Leap years. */
93 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
94 };
95
96 #define is_leap_year(y) \
97 ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0))
98
99 /**
100 * virTimeFieldsThen:
101 * @when: the time to convert in milliseconds
102 * @fields: filled with time @when fields
103 *
104 * Converts the timestamp @when into broken-down field format.
105 * Time time is always in UTC
106 *
107 */
virTimeFieldsThen(unsigned long long when,struct tm * fields)108 void virTimeFieldsThen(unsigned long long when, struct tm *fields)
109 {
110 /* This code is taken from GLibC under terms of LGPLv2+ */
111 /* Remove the 'offset' or GMT manipulation since we don't care. See
112 * commit id '3ec12898' comments regarding localtime.
113 */
114 long int days, rem, y;
115 const unsigned short int *ip;
116 unsigned long long whenSecs = when / 1000ull;
117
118 days = whenSecs / SECS_PER_DAY;
119 rem = whenSecs % SECS_PER_DAY;
120
121 fields->tm_hour = rem / SECS_PER_HOUR;
122 rem %= SECS_PER_HOUR;
123 fields->tm_min = rem / 60;
124 fields->tm_sec = rem % 60;
125 /* January 1, 1970 was a Thursday. */
126 fields->tm_wday = (4 + days) % 7;
127 if (fields->tm_wday < 0)
128 fields->tm_wday += 7;
129 y = 1970;
130
131 while (days < 0 || days >= (is_leap_year(y) ? 366 : 365)) {
132 /* Guess a corrected year, assuming 365 days per year. */
133 long int yg = y + days / 365 - (days % 365 < 0);
134
135 /* Adjust DAYS and Y to match the guessed year. */
136 days -= ((yg - y) * 365
137 + LEAPS_THRU_END_OF(yg - 1)
138 - LEAPS_THRU_END_OF(y - 1));
139 y = yg;
140 }
141 fields->tm_year = y - 1900;
142
143 fields->tm_yday = days;
144 ip = mon_yday[is_leap_year(y)];
145 for (y = 11; days < (long int) ip[y]; --y)
146 continue;
147 days -= ip[y];
148 fields->tm_mon = y;
149 fields->tm_mday = days + 1;
150 }
151
152
153 /**
154 * virTimeStringNowRaw:
155 * @buf: a buffer at least VIR_TIME_STRING_BUFLEN in length
156 *
157 * Initializes @buf to contain a formatted timestamp
158 * corresponding to the current time.
159 *
160 * Returns 0 on success, -1 on error
161 */
virTimeStringNowRaw(char * buf)162 int virTimeStringNowRaw(char *buf)
163 {
164 unsigned long long now;
165
166 if (virTimeMillisNowRaw(&now) < 0)
167 return -1;
168
169 return virTimeStringThenRaw(now, buf);
170 }
171
172
173 /**
174 * virTimeStringThenRaw:
175 * @when: the time to format in milliseconds
176 * @buf: a buffer at least VIR_TIME_STRING_BUFLEN in length
177 *
178 * Initializes @buf to contain a formatted timestamp
179 * corresponding to the time @when.
180 *
181 * Returns 0 on success, -1 on error
182 */
virTimeStringThenRaw(unsigned long long when,char * buf)183 int virTimeStringThenRaw(unsigned long long when, char *buf)
184 {
185 struct tm fields;
186
187 virTimeFieldsThen(when, &fields);
188
189 fields.tm_year += 1900;
190 fields.tm_mon += 1;
191
192 if (g_snprintf(buf, VIR_TIME_STRING_BUFLEN,
193 "%4d-%02d-%02d %02d:%02d:%02d.%03d+0000",
194 fields.tm_year, fields.tm_mon, fields.tm_mday,
195 fields.tm_hour, fields.tm_min, fields.tm_sec,
196 (int) (when % 1000)) >= VIR_TIME_STRING_BUFLEN) {
197 errno = ERANGE;
198 return -1;
199 }
200
201 return 0;
202 }
203
204
205 /**
206 * virTimeMillisNow:
207 * @now: filled with current time in milliseconds
208 *
209 * Retrieves the current system time, in milliseconds since the
210 * epoch
211 *
212 * Returns 0 on success, -1 on error with error reported
213 */
virTimeMillisNow(unsigned long long * now)214 int virTimeMillisNow(unsigned long long *now)
215 {
216 if (virTimeMillisNowRaw(now) < 0) {
217 virReportSystemError(errno, "%s",
218 _("Unable to get current time"));
219 return -1;
220 }
221 return 0;
222 }
223
224
225 /**
226 * virTimeFieldsNow:
227 * @fields: filled with current time fields
228 *
229 * Retrieves the current time, in broken-down field format.
230 * The time is always in UTC.
231 *
232 * Returns 0 on success, -1 on error with errno reported
233 */
virTimeFieldsNow(struct tm * fields)234 int virTimeFieldsNow(struct tm *fields)
235 {
236 unsigned long long now;
237
238 if (virTimeMillisNow(&now) < 0)
239 return -1;
240
241 virTimeFieldsThen(now, fields);
242 return 0;
243 }
244
245
246 /**
247 * virTimeStringNow:
248 *
249 * Creates a string containing a formatted timestamp
250 * corresponding to the current time.
251 *
252 * This function is not async signal safe
253 *
254 * Returns a formatted allocated string, or NULL on error
255 */
virTimeStringNow(void)256 char *virTimeStringNow(void)
257 {
258 char *ret;
259
260 ret = g_new0(char, VIR_TIME_STRING_BUFLEN);
261
262 if (virTimeStringNowRaw(ret) < 0) {
263 virReportSystemError(errno, "%s",
264 _("Unable to format time"));
265 VIR_FREE(ret);
266 return NULL;
267 }
268
269 return ret;
270 }
271
272
273 /**
274 * virTimeStringThen:
275 * @when: the time to format in milliseconds
276 *
277 * Creates a string containing a formatted timestamp
278 * corresponding to the time @when.
279 *
280 * This function is not async signal safe
281 *
282 * Returns a formatted allocated string, or NULL on error
283 */
virTimeStringThen(unsigned long long when)284 char *virTimeStringThen(unsigned long long when)
285 {
286 char *ret;
287
288 ret = g_new0(char, VIR_TIME_STRING_BUFLEN);
289
290 if (virTimeStringThenRaw(when, ret) < 0) {
291 virReportSystemError(errno, "%s",
292 _("Unable to format time"));
293 VIR_FREE(ret);
294 return NULL;
295 }
296
297 return ret;
298 }
299
300 /**
301 * virTimeLocalOffsetFromUTC:
302 *
303 * This function is threadsafe, but is *not* async signal safe
304 * due to use of GLib APIs.
305 *
306 * @offset: pointer to time_t that will be set to the difference
307 * between localtime and UTC in seconds (east of UTC is a
308 * positive number, and west of UTC is a negative number.
309 *
310 * Returns 0 on success, -1 on error with error reported
311 */
312 int
virTimeLocalOffsetFromUTC(long * offset)313 virTimeLocalOffsetFromUTC(long *offset)
314 {
315 g_autoptr(GDateTime) now = g_date_time_new_now_local();
316 GTimeSpan diff = g_date_time_get_utc_offset(now);
317
318 /* GTimeSpan measures microseconds, we want seconds */
319 *offset = diff / 1000000;
320 return 0;
321 }
322
323 /**
324 * virTimeBackOffStart:
325 * @var: Timeout variable (with type virTimeBackOffVar).
326 * @first: Initial time to wait (milliseconds).
327 * @timeout: Timeout (milliseconds).
328 *
329 * Initialize the timeout variable @var and start the timer running.
330 *
331 * Returns 0 on success, -1 on error and raises a libvirt error.
332 */
333 int
virTimeBackOffStart(virTimeBackOffVar * var,unsigned long long first,unsigned long long timeout)334 virTimeBackOffStart(virTimeBackOffVar *var,
335 unsigned long long first, unsigned long long timeout)
336 {
337 if (virTimeMillisNow(&var->start_t) < 0)
338 return -1;
339
340 var->next = first;
341 var->limit_t = var->start_t + timeout;
342 return 0;
343 }
344
345
346 #define VIR_TIME_BACKOFF_CAP 1000
347
348 /**
349 * virTimeBackOffWait
350 * @var: Timeout variable (with type virTimeBackOffVar *).
351 *
352 * You must initialize @var first by calling the following function,
353 * which also starts the timer:
354 *
355 * if (virTimeBackOffStart(&var, first, timeout) < 0) {
356 * // handle errors
357 * }
358 *
359 * Then you use a while loop:
360 *
361 * while (virTimeBackOffWait(&var)) {
362 * //...
363 * }
364 *
365 * The while loop that runs the body of the code repeatedly, with an
366 * exponential backoff. It first waits for first milliseconds, then
367 * runs the body, then waits for 2*first ms, then runs the body again.
368 * Then 4*first ms, and so on, up until wait time would reach
369 * VIR_TIME_BACK_OFF_CAP (whole second). Then it switches to constant
370 * waiting time of VIR_TIME_BACK_OFF_CAP.
371 *
372 * When timeout milliseconds is reached, the while loop ends.
373 *
374 * The body should use "break" or "goto" when whatever condition it is
375 * testing for succeeds (or there is an unrecoverable error).
376 */
377 bool
virTimeBackOffWait(virTimeBackOffVar * var)378 virTimeBackOffWait(virTimeBackOffVar *var)
379 {
380 unsigned long long next, t = 0;
381
382 ignore_value(virTimeMillisNowRaw(&t));
383
384 VIR_DEBUG("t=%llu, limit=%llu", t, var->limit_t);
385
386 if (t > var->limit_t)
387 return false; /* ends the while loop */
388
389 /* Compute next wait time. Cap at VIR_TIME_BACKOFF_CAP
390 * to avoid long useless sleeps. */
391 next = var->next;
392 if (var->next < VIR_TIME_BACKOFF_CAP)
393 var->next *= 2;
394 else if (var->next > VIR_TIME_BACKOFF_CAP)
395 var->next = VIR_TIME_BACKOFF_CAP;
396
397 /* If sleeping would take us beyond the limit, then shorten the
398 * sleep. This is so we always run the body just before the final
399 * timeout.
400 */
401 if (t + next > var->limit_t)
402 next = var->limit_t - t;
403
404 VIR_DEBUG("sleeping for %llu ms", next);
405
406 g_usleep(next * 1000);
407 return true;
408 }
409