]> granicus.if.org Git - neomutt/commitdiff
unify time handling 1823/head
authorPietro Cerutti <gahr@gahr.ch>
Fri, 30 Aug 2019 11:43:48 +0000 (11:43 +0000)
committerRichard Russon <rich@flatcap.org>
Fri, 30 Aug 2019 14:49:12 +0000 (15:49 +0100)
- Add mutt_date_epoch_ms API, convert gettimeofdays to use the new API
- Add mutt_date_sleep_ms as a general sleep API

13 files changed:
autocrypt/autocrypt.c
conn/conn_raw.c
hcache/hcache.c
hcache/hcache.h
hcache/hcachever.sh
hcache/serialize.c
hcache/serialize.h
imap/util.c
maildir/shared.c
mutt/date.c
mutt/date.h
mutt_logging.c
notmuch/nm_db.c

index e4bf134b1f4840fe53d2e222e8807994a6fc7b09..f8ca0a684c44c852a9ea779ff0e7b9ed1cf5e756 100644 (file)
@@ -30,7 +30,6 @@
 #include <errno.h>
 #include <string.h>
 #include <sys/stat.h>
-#include <sys/time.h>
 #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();
index 05301e46f194d1ad023c44667446e77a1a8f7813..22cded44008ca1c40eb3424f1e01a0fd6d85f4b9 100644 (file)
@@ -40,7 +40,6 @@
 #include <string.h>
 #include <sys/select.h>
 #include <sys/socket.h>
-#include <sys/time.h>
 #include <time.h>
 #include <unistd.h>
 #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;
   }
 }
 
index 75a8afb982af36f9c75dff0a50422df85565d357..b209d0c12892037b5ff34107b8f6ba18d3e939f2 100644 (file)
@@ -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;
 }
index 1c23895c4c84216f920cdd22088478dec431545c..8d7857f6b9cadbb57cf6002c9cf22e25109b3236 100644 (file)
@@ -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;
 
index 68f09578156d80981d5d8d1f12c181f0a6fc4800..db34573828e27619714a961aeeb61f5fffd5adb9 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-BASEVERSION=3
+BASEVERSION=4
 STRUCTURES="Address Body Buffer Email Envelope ListNode Parameter"
 
 cleanstruct () {
index e9ad70707d84cd974d68c6af67a77c14b9ba1124..94da047e4a042bd9fcacddd3957e91f8c53e3dcd 100644 (file)
@@ -33,7 +33,6 @@
 #include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/time.h>
 #include <sys/types.h>
 #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);
index b27e0c083b7be9c3b8cef721bef67099d299801b..e3f317b8ec28b19a37293325d65367d90f512182 100644 (file)
@@ -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 */
index 96ad89a24eb4e3437cd932a7c301d6b3730d7de3..c7c0f9a3649b24bbe4c88daa008f7bad7d57aaab 100644 (file)
@@ -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);
   }
 
index f57cdac5d82ccc8a2f36a8637fe5a224525be2c3..2676943c7224a1ed78ca4af0a4b9299cd76efcfb 100644 (file)
@@ -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;
index cdf6ee2fe4b3951201b61113f80303e034f5518f..5684e9afeffdf784e3eb2d069476619f1c4360a5 100644 (file)
@@ -32,6 +32,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/time.h>
 #include <time.h>
 #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);
+}
index 20aa991c938d10d2dbff9f7e9dbbe3431141b7a7..81e4755f6d1b9408e69041aac8c5647150620373 100644 (file)
@@ -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 */
index ed286d0972c7e3408200375814d2534ebe455443..655c8cd73b1c18c9e52f1360f65dbd7888e5a4cc 100644 (file)
@@ -34,8 +34,6 @@
 #include <stdint.h>
 #include <stdio.h>
 #include <string.h>
-#include <sys/time.h>
-#include <time.h>
 #include "mutt/mutt.h"
 #include "config/lib.h"
 #include "curs_lib.h"
 #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;
index 739945e07962854222b1577d73ec2ecfe75901d9..46a00983c18ee76e48ae5c9162905c5cbdc3819e 100644 (file)
@@ -32,7 +32,6 @@
 #include <stdbool.h>
 #include <stdio.h>
 #include <sys/stat.h>
-#include <time.h>
 #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);