diff options
Diffstat (limited to 'src/H5retry_private.h')
-rw-r--r-- | src/H5retry_private.h | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/src/H5retry_private.h b/src/H5retry_private.h new file mode 100644 index 0000000..03568ef --- /dev/null +++ b/src/H5retry_private.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2019 The HDF Group. All rights reserved. + * + * This file is part of HDF5. The full HDF5 copyright notice, including + * terms governing use, modification, and redistribution, is contained in + * the COPYING file, which can be found at the root of the source code + * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. + * If you do not have access to either file, you may request a copy from + * help@hdfgroup.org. + */ + +#ifndef _H5retry_private_H +#define _H5retry_private_H + +/* + * Data types and functions for retry loops. + */ + +/* State for a retry loop. No user-serviceable parts inside. */ +typedef struct h5_retry_t { + uint64_t maxival; /* maximum sleep interval (nanoseconds) */ + unsigned maxtries; /* maximum permissible tries */ + unsigned tries; /* remaining tries */ + uint64_t ival; /* nanoseconds sleep interval before clamping to + * maxival + */ +} h5_retry_t; + +/* Default minimum/maximum retry intervals: 1/10s minimum, 1s maximum. */ +#define H5_RETRY_DEFAULT_MINIVAL ( 100ULL * 1000ULL * 1000ULL) +#define H5_RETRY_DEFAULT_MAXIVAL ( 1000ULL * 1000ULL * 1000ULL) +/* One hour: */ +#define H5_RETRY_ONE_HOUR (3600ULL * 1000ULL * 1000ULL * 1000ULL) + +/* Establish state for a retry loop in `r`. The loop will retry no + * more than `maxtries` times, sleeping for no fewer than `minival` + * nanoseconds between tries. After each try, the sleep time will + * increase to `maxival` nanoseconds or twice the previous sleep time, + * whichever is less. + * + * `h5_retry_init` always returns true. This is to help one use + * it in a loop like this: + * + * for (do_try = h5_retry_init(&r, 100, H5_RETRY_DEFAULT_MINIVAL, + * H5_RETRY_DEFAULT_MAXIVAL); + * do_try; + * do_try = h5_retry_next(&r)) { + * . + * . + * . + * } + * + * Note well: the program will enter the body of the loop, above, no more + * than 101 times: once for an initial try, and then 100 times for retries. + */ +static inline bool +h5_retry_init(struct h5_retry_t *r, unsigned int maxtries, uint64_t minival, + uint64_t maxival) +{ + memset(r, '\0', sizeof(*r)); + assert(0 < maxtries); + assert(0 < minival && minival <= maxival); + r->tries = r->maxtries = maxtries; + r->ival = minival; + r->maxival = maxival; + return true; +} + +/* If any tries remain, sleep for the mininum interval, or twice the + * previous sleep time, and return true. If no tries remain, return false. + */ +static inline bool +h5_retry_next(struct h5_retry_t *r) +{ + uint64_t ival; + + if (r->tries == 0) + return false; + --r->tries; + ival = r->ival; + if (r->maxival < ival) + ival = r->maxival; + else if (UINT64_MAX - ival >= ival) + r->ival += ival; + + H5_nanosleep(ival); + + return true; +} + +/* Return the number of retries performed since `h5_retry_init()` + * was called on `r`. + */ +static inline unsigned +h5_retry_retries(struct h5_retry_t *r) +{ + return r->maxtries - r->tries; +} + +#endif /* _H5retry_private_H */ |