/** * virTimeBackOffWait * @var: Timeout variable (with type virTimeBackOffVar *). * * You must initialize @var first by calling the following function, * which also starts the timer: * * if (virTimeBackOffStart(&var, first, timeout) < 0) { * // handle errors * } * * Then you use a while loop: * * while (virTimeBackOffWait(&var)) { * //... * } * * The while loop that runs the body of the code repeatedly, with an * exponential backoff. It first waits for first milliseconds, then * runs the body, then waits for 2*first ms, then runs the body again. * Then 4*first ms, and so on. * * When timeout milliseconds is reached, the while loop ends. * * The body should use "break" or "goto" when whatever condition it is * testing for succeeds (or there is an unrecoverable error). */ bool virTimeBackOffWait(virTimeBackOffVar *var) { unsigned long long t, next; ignore_value(virTimeMillisNowRaw(&t)); VIR_DEBUG("t=%llu, limit=%llu", t, var->limit_t); if (t > var->limit_t) return 0; /* ends the while loop */ next = var->next; var->next *= 2; /* If sleeping would take us beyond the limit, then shorten the * sleep. This is so we always run the body just before the final * timeout. */ if (t + next > var->limit_t) next = var->limit_t - t; VIR_DEBUG("sleeping for %llu ms", next); usleep(next * 1000); return 1; }
/** * virTimeBackOffWait * @var: Timeout variable (with type virTimeBackOffVar *). * * You must initialize @var first by calling the following function, * which also starts the timer: * * if (virTimeBackOffStart(&var, first, timeout) < 0) { * // handle errors * } * * Then you use a while loop: * * while (virTimeBackOffWait(&var)) { * //... * } * * The while loop that runs the body of the code repeatedly, with an * exponential backoff. It first waits for first milliseconds, then * runs the body, then waits for 2*first ms, then runs the body again. * Then 4*first ms, and so on, up until wait time would reach * VIR_TIME_BACK_OFF_CAP (whole second). Then it switches to constant * waiting time of VIR_TIME_BACK_OFF_CAP. * * When timeout milliseconds is reached, the while loop ends. * * The body should use "break" or "goto" when whatever condition it is * testing for succeeds (or there is an unrecoverable error). */ bool virTimeBackOffWait(virTimeBackOffVar *var) { unsigned long long t, next; ignore_value(virTimeMillisNowRaw(&t)); VIR_DEBUG("t=%llu, limit=%llu", t, var->limit_t); if (t > var->limit_t) return 0; /* ends the while loop */ /* Compute next wait time. Cap at VIR_TIME_BACKOFF_CAP * to avoid long useless sleeps. */ next = var->next; if (var->next < VIR_TIME_BACKOFF_CAP) var->next *= 2; else if (var->next > VIR_TIME_BACKOFF_CAP) var->next = VIR_TIME_BACKOFF_CAP; /* If sleeping would take us beyond the limit, then shorten the * sleep. This is so we always run the body just before the final * timeout. */ if (t + next > var->limit_t) next = var->limit_t - t; VIR_DEBUG("sleeping for %llu ms", next); usleep(next * 1000); return 1; }
/** * virTimeMillisNow: * @now: filled with current time in milliseconds * * Retrieves the current system time, in milliseconds since the * epoch * * Returns 0 on success, -1 on error with error reported */ int virTimeMillisNow(unsigned long long *now) { if (virTimeMillisNowRaw(now) < 0) { virReportSystemError(errno, "%s", _("Unable to get current time")); return -1; } return 0; }
/** * virTimeStringNowRaw: * @buf: a buffer at least VIR_TIME_STRING_BUFLEN in length * * Initializes @buf to contain a formatted timestamp * corresponding to the current time. * * Returns 0 on success, -1 on error */ int virTimeStringNowRaw(char *buf) { unsigned long long now; if (virTimeMillisNowRaw(&now) < 0) return -1; return virTimeStringThenRaw(now, buf); }
/** * virTimeFieldsNowRaw: * @fields: filled with current time fields * * Retrieves the current time, in broken-down field format. * The time is always in UTC. * * Returns 0 on success, -1 on error with errno set */ int virTimeFieldsNowRaw(struct tm *fields) { unsigned long long now; if (virTimeMillisNowRaw(&now) < 0) return -1; return virTimeFieldsThenRaw(now, fields); }