From: Pietro Cerutti Date: Fri, 30 Aug 2019 11:43:48 +0000 (+0000) Subject: unify time handling X-Git-Tag: 2019-10-25~69 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=22c5f2297bcb809de1f9b0520e13e8950db510bf;p=neomutt unify time handling - Add mutt_date_epoch_ms API, convert gettimeofdays to use the new API - Add mutt_date_sleep_ms as a general sleep API --- diff --git a/autocrypt/autocrypt.c b/autocrypt/autocrypt.c index e4bf134b1..f8ca0a684 100644 --- a/autocrypt/autocrypt.c +++ b/autocrypt/autocrypt.c @@ -30,7 +30,6 @@ #include #include #include -#include #include "autocrypt_private.h" #include "mutt/mutt.h" #include "address/lib.h" @@ -260,7 +259,6 @@ cleanup: int mutt_autocrypt_process_autocrypt_header(struct Email *e, struct Envelope *env) { struct AutocryptHeader *valid_ac_hdr = NULL; - struct timeval now; struct AutocryptPeer *peer = NULL; struct AutocryptPeerHistory *peerhist = NULL; struct Buffer *keyid = NULL; @@ -290,8 +288,7 @@ int mutt_autocrypt_process_autocrypt_header(struct Email *e, struct Envelope *en /* Ignore emails that appear to be more than a week in the future, * since they can block all future updates during that time. */ - gettimeofday(&now, NULL); - if (e->date_sent > (now.tv_sec + 7 * 24 * 60 * 60)) + if (e->date_sent > (mutt_date_epoch_ms() / 1000 + (7 * 24 * 60 * 60))) return 0; for (struct AutocryptHeader *ac_hdr = env->autocrypt; ac_hdr; ac_hdr = ac_hdr->next) @@ -409,7 +406,6 @@ cleanup: */ int mutt_autocrypt_process_gossip_header(struct Email *e, struct Envelope *prot_headers) { - struct timeval now; struct AutocryptPeer *peer = NULL; struct AutocryptGossipHistory *gossip_hist = NULL; struct Address *peer_addr = NULL; @@ -434,8 +430,7 @@ int mutt_autocrypt_process_gossip_header(struct Email *e, struct Envelope *prot_ /* Ignore emails that appear to be more than a week in the future, * since they can block all future updates during that time. */ - gettimeofday(&now, NULL); - if (e->date_sent > (now.tv_sec + (7 * 24 * 60 * 60))) + if (e->date_sent > (mutt_date_epoch_ms() / 1000 + (7 * 24 * 60 * 60))) return 0; struct Buffer *keyid = mutt_buffer_pool_get(); diff --git a/conn/conn_raw.c b/conn/conn_raw.c index 05301e46f..22cded440 100644 --- a/conn/conn_raw.c +++ b/conn/conn_raw.c @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include "mutt/mutt.h" @@ -326,7 +325,8 @@ int raw_socket_poll(struct Connection *conn, time_t wait_secs) { fd_set rfds; unsigned long wait_millis; - struct timeval tv, pre_t, post_t; + struct timeval tv; + size_t pre_t, post_t; if (conn->fd < 0) return -1; @@ -341,9 +341,9 @@ int raw_socket_poll(struct Connection *conn, time_t wait_secs) FD_ZERO(&rfds); FD_SET(conn->fd, &rfds); - gettimeofday(&pre_t, NULL); + pre_t = mutt_date_epoch_ms(); const int rc = select(conn->fd + 1, &rfds, NULL, NULL, &tv); - gettimeofday(&post_t, NULL); + post_t = mutt_date_epoch_ms(); if ((rc > 0) || ((rc < 0) && (errno != EINTR))) return rc; @@ -351,11 +351,10 @@ int raw_socket_poll(struct Connection *conn, time_t wait_secs) if (SigInt) mutt_query_exit(); - wait_millis += (pre_t.tv_sec * 1000UL) + (pre_t.tv_usec / 1000); - const unsigned long post_t_millis = (post_t.tv_sec * 1000UL) + (post_t.tv_usec / 1000); - if (wait_millis <= post_t_millis) + wait_millis += pre_t; + if (wait_millis <= post_t) return 0; - wait_millis -= post_t_millis; + wait_millis -= post_t; } } diff --git a/hcache/hcache.c b/hcache/hcache.c index 75a8afb98..b209d0c12 100644 --- a/hcache/hcache.c +++ b/hcache/hcache.c @@ -130,7 +130,7 @@ static bool crc_matches(const char *d, unsigned int crc) if (!d) return false; - unsigned int mycrc = *(unsigned int *) (d + sizeof(union Validate)); + unsigned int mycrc = *(unsigned int *) (d + sizeof(size_t)); return crc == mycrc; } diff --git a/hcache/hcache.h b/hcache/hcache.h index 1c23895c4..8d7857f6b 100644 --- a/hcache/hcache.h +++ b/hcache/hcache.h @@ -82,14 +82,6 @@ typedef struct EmailCache header_cache_t; */ typedef int (*hcache_namer_t)(const char *path, char *dest, size_t dlen); -/** - * union Validate - Header cache validity - */ -union Validate { - struct timeval timeval; - unsigned int uidvalidity; -}; - /* These Config Variables are only used in hcache/hcache.c */ extern char *C_HeaderCacheBackend; diff --git a/hcache/hcachever.sh b/hcache/hcachever.sh index 68f095781..db3457382 100755 --- a/hcache/hcachever.sh +++ b/hcache/hcachever.sh @@ -1,6 +1,6 @@ #!/bin/sh -BASEVERSION=3 +BASEVERSION=4 STRUCTURES="Address Body Buffer Email Envelope ListNode Parameter" cleanstruct () { diff --git a/hcache/serialize.c b/hcache/serialize.c index e9ad70707..94da047e4 100644 --- a/hcache/serialize.c +++ b/hcache/serialize.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include "mutt/mutt.h" #include "address/lib.h" @@ -73,6 +72,22 @@ unsigned char *serial_dump_int(unsigned int i, unsigned char *d, int *off) return d; } +/** + * serial_dump_size_t - Pack a size_t into a binary blob + * @param s Size_t to save + * @param d Binary blob to add to + * @param off Offset into the blob + * @retval ptr End of the newly packed binary + */ +unsigned char *serial_dump_size_t(size_t s, unsigned char *d, int *off) +{ + lazy_realloc(&d, *off + sizeof(size_t)); + memcpy(d + *off, &s, sizeof(size_t)); + (*off) += sizeof(size_t); + + return d; +} + /** * serial_restore_int - Unpack an integer from a binary blob * @param i Integer to write to @@ -564,7 +579,7 @@ void serial_restore_envelope(struct Envelope *env, const unsigned char *d, int * * This function transforms a e into a char so that it is usable by * db_store. */ -void *mutt_hcache_dump(header_cache_t *hc, const struct Email *e, int *off, unsigned int uidvalidity) +void *mutt_hcache_dump(header_cache_t *hc, const struct Email *e, int *off, size_t uidvalidity) { struct Email nh; bool convert = !CharsetIsUtf8; @@ -572,16 +587,7 @@ void *mutt_hcache_dump(header_cache_t *hc, const struct Email *e, int *off, unsi *off = 0; unsigned char *d = mutt_mem_malloc(4096); - if (uidvalidity == 0) - { - struct timeval now; - gettimeofday(&now, NULL); - memcpy(d, &now, sizeof(struct timeval)); - } - else - memcpy(d, &uidvalidity, sizeof(uidvalidity)); - *off += sizeof(union Validate); - + d = serial_dump_size_t((uidvalidity != 0) ? uidvalidity : mutt_date_epoch_ms(), d, off); d = serial_dump_int(hc->crc, d, off); lazy_realloc(&d, *off + sizeof(struct Email)); @@ -634,7 +640,7 @@ struct Email *mutt_hcache_restore(const unsigned char *d) bool convert = !CharsetIsUtf8; /* skip validate */ - off += sizeof(union Validate); + off += sizeof(size_t); /* skip crc */ off += sizeof(unsigned int); diff --git a/hcache/serialize.h b/hcache/serialize.h index b27e0c083..e3f317b8e 100644 --- a/hcache/serialize.h +++ b/hcache/serialize.h @@ -45,6 +45,7 @@ unsigned char *serial_dump_char(char *c, unsigned char *d, int *off, bool conver unsigned char *serial_dump_char_size(char *c, unsigned char *d, int *off, ssize_t size, bool convert); unsigned char *serial_dump_envelope(struct Envelope *e, unsigned char *d, int *off, bool convert); unsigned char *serial_dump_int(unsigned int i, unsigned char *d, int *off); +unsigned char *serial_dump_size_t(size_t s, unsigned char *d, int *off); unsigned char *serial_dump_parameter(struct ParameterList *pl, unsigned char *d, int *off, bool convert); unsigned char *serial_dump_stailq(struct ListHead *l, unsigned char *d, int *off, bool convert); @@ -57,7 +58,7 @@ void serial_restore_int(unsigned int *i, const unsigned char *d, int * void serial_restore_parameter(struct ParameterList *pl, const unsigned char *d, int *off, bool convert); void serial_restore_stailq(struct ListHead *l, const unsigned char *d, int *off, bool convert); -void * mutt_hcache_dump(header_cache_t *hc, const struct Email *e, int *off, unsigned int uidvalidity); +void * mutt_hcache_dump(header_cache_t *hc, const struct Email *e, int *off, size_t uidvalidity); struct Email *mutt_hcache_restore(const unsigned char *d); #endif /* MUTT_HCACHE_SERIALIZE_H */ diff --git a/imap/util.c b/imap/util.c index 96ad89a24..c7c0f9a36 100644 --- a/imap/util.c +++ b/imap/util.c @@ -469,10 +469,11 @@ struct Email *imap_hcache_get(struct ImapMboxData *mdata, unsigned int uid) void *uv = mutt_hcache_fetch(mdata->hcache, key, mutt_str_strlen(key)); if (uv) { - if (*(unsigned int *) uv == mdata->uid_validity) + const size_t *const uid_validity = uv; + if (*uid_validity == mdata->uid_validity) e = mutt_hcache_restore(uv); else - mutt_debug(LL_DEBUG3, "hcache uidvalidity mismatch: %u\n", *(unsigned int *) uv); + mutt_debug(LL_DEBUG3, "hcache uidvalidity mismatch: %zu\n", *uid_validity); mutt_hcache_free(mdata->hcache, &uv); } diff --git a/maildir/shared.c b/maildir/shared.c index f57cdac5d..2676943c7 100644 --- a/maildir/shared.c +++ b/maildir/shared.c @@ -738,9 +738,9 @@ void maildir_delayed_parsing(struct Mailbox *m, struct Maildir **md, struct Prog keylen = maildir_hcache_keylen(key); } void *data = mutt_hcache_fetch(hc, key, keylen); - struct timeval *when = data; + size_t *when = data; - if (data && !ret && (lastchanged.st_mtime <= when->tv_sec)) + if (data && !ret && (lastchanged.st_mtime <= (*when / 1000))) { struct Email *e = mutt_hcache_restore((unsigned char *) data); e->old = p->email->old; diff --git a/mutt/date.c b/mutt/date.c index cdf6ee2fe..5684e9afe 100644 --- a/mutt/date.c +++ b/mutt/date.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include "date.h" #include "logging.h" @@ -402,6 +403,19 @@ int mutt_date_check_month(const char *s) return -1; /* error */ } +/** + * mutt_date_epoch_ms - Return the number of milliseconds since the Unix epoch + * @retval ms The number of ms since the Unix epoch, or 0 on failure + */ +size_t mutt_date_epoch_ms(void) +{ + struct timeval tv = { 0, 0 }; + gettimeofday(&tv, NULL); + /* We assume that gettimeofday doesn't modify its first argument on failure. + * We also kind of assume that gettimeofday does not fail. */ + return tv.tv_sec * 1000 + tv.tv_usec / 1000; +} + /** * mutt_date_is_day_name - Is the string a valid day name * @param s String to check @@ -755,3 +769,16 @@ size_t mutt_date_localtime_format(char *buf, size_t buflen, const char *format, struct tm tm = mutt_date_localtime(t); return strftime(buf, buflen, format, &tm); } + +/** + * mutt_date_sleep_ms - Sleep for milliseconds + * @param ms Number of milliseconds to sleep + */ +void mutt_date_sleep_ms(size_t ms) +{ + const struct timespec sleep = { + .tv_sec = ms / 1000, + .tv_nsec = (ms % 1000) * 1000000UL, + }; + nanosleep(&sleep, NULL); +} diff --git a/mutt/date.h b/mutt/date.h index 20aa991c9..81e4755f6 100644 --- a/mutt/date.h +++ b/mutt/date.h @@ -48,6 +48,7 @@ struct Tz time_t mutt_date_add_timeout(time_t now, long timeout); int mutt_date_check_month(const char *s); +size_t mutt_date_epoch_ms(void); struct tm mutt_date_gmtime(time_t t); bool mutt_date_is_day_name(const char *s); size_t mutt_date_localtime_format(char *buf, size_t buflen, const char *format, time_t t); @@ -60,5 +61,6 @@ int mutt_date_make_tls(char *buf, size_t buflen, time_t timestamp); void mutt_date_normalize_time(struct tm *tm); time_t mutt_date_parse_date(const char *s, struct Tz *tz_out); time_t mutt_date_parse_imap(const char *s); +void mutt_date_sleep_ms(size_t ms); #endif /* MUTT_LIB_DATE_H */ diff --git a/mutt_logging.c b/mutt_logging.c index ed286d097..655c8cd73 100644 --- a/mutt_logging.c +++ b/mutt_logging.c @@ -34,8 +34,6 @@ #include #include #include -#include -#include #include "mutt/mutt.h" #include "config/lib.h" #include "curs_lib.h" @@ -45,31 +43,14 @@ #include "muttlib.h" #include "options.h" -struct timeval LastError = { 0 }; +size_t LastError = 0; ///< Time of the last error message (in milliseconds since the Unix epoch) short C_DebugLevel = 0; ///< Config: Logging level for debug logs char *C_DebugFile = NULL; ///< Config: File to save debug logs char *CurrentFile = NULL; /**< The previous log file name */ const int NumOfLogs = 5; /**< How many log files to rotate */ -#define S_TO_NS 1000000000UL -#define S_TO_US 1000000UL -#define US_TO_NS 1000UL - -/** - * micro_elapsed - Number of microseconds between two timevals - * @param begin Begin time - * @param end End time - * @retval num Microseconds elapsed - * @retval LONG_MAX Begin time was zero - */ -static long micro_elapsed(const struct timeval *begin, const struct timeval *end) -{ - if ((begin->tv_sec == 0) && (end->tv_sec != 0)) - return LONG_MAX; - - return (end->tv_sec - begin->tv_sec) * S_TO_US + (end->tv_usec - begin->tv_usec); -} +#define S_TO_MS 1000L /** * error_pause - Wait for an error message to be read @@ -78,28 +59,13 @@ static long micro_elapsed(const struct timeval *begin, const struct timeval *end */ static void error_pause(void) { - struct timeval now = { 0 }; - - if (gettimeofday(&now, NULL) < 0) - { - mutt_debug(LL_DEBUG1, "gettimeofday failed: %d\n", errno); - return; - } - - unsigned long sleep = C_SleepTime * S_TO_NS; - long micro = micro_elapsed(&LastError, &now); - if ((micro * US_TO_NS) >= sleep) + const size_t elapsed = mutt_date_epoch_ms() - LastError; + const size_t sleep = C_SleepTime * S_TO_MS; + if ((LastError == 0) || (elapsed >= sleep)) return; - sleep -= (micro * US_TO_NS); - - struct timespec wait = { - .tv_sec = (sleep / S_TO_NS), - .tv_nsec = (sleep % S_TO_NS), - }; - mutt_refresh(); - nanosleep(&wait, NULL); + mutt_date_sleep_ms(sleep - elapsed); } /** @@ -214,13 +180,12 @@ int log_disp_curses(time_t stamp, const char *file, int line, if ((level <= LL_ERROR) && !dupe) { OptMsgErr = true; - if (gettimeofday(&LastError, NULL) < 0) - mutt_debug(LL_DEBUG1, "gettimeofday failed: %d\n", errno); + LastError = mutt_date_epoch_ms(); } else { OptMsgErr = false; - LastError.tv_sec = 0; + LastError = 0; } return ret; diff --git a/notmuch/nm_db.c b/notmuch/nm_db.c index 739945e07..46a00983c 100644 --- a/notmuch/nm_db.c +++ b/notmuch/nm_db.c @@ -32,7 +32,6 @@ #include #include #include -#include #include "notmuch_private.h" #include "mutt/mutt.h" #include "email/lib.h" @@ -92,10 +91,6 @@ notmuch_database_t *nm_db_do_open(const char *filename, bool writable, bool verb const notmuch_database_mode_t mode = writable ? NOTMUCH_DATABASE_MODE_READ_WRITE : NOTMUCH_DATABASE_MODE_READ_ONLY; - const struct timespec wait = { - .tv_sec = 0, .tv_nsec = 500000000, /* Half a second */ - }; - do { #if LIBNOTMUCH_CHECK_VERSION(4, 2, 0) @@ -110,7 +105,7 @@ notmuch_database_t *nm_db_do_open(const char *filename, bool writable, bool verb if (verbose && ct && ((ct % 2) == 0)) mutt_error(_("Waiting for notmuch DB... (%d sec)"), ct / 2); - nanosleep(&wait, NULL); + mutt_date_sleep_ms(500000); /* Half a second */ ct++; } while (true);