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