From 8551ec93d2864d8122472d8531a5268ee500d38d Mon Sep 17 00:00:00 2001
From: Micael Karlberg <bmk@erlang.org>
Date: Wed, 22 May 2019 12:28:09 +0200
Subject: [esock] Replace usage of clock_gettime(CLOCK_REALTIME, ...)

The usage of the function clock_gettime(CLOCK_REALTIME, ...)
has been replaced with enif_monotonic_time(ERL_NIF_USEC) and
enif_time_offset(ERL_NIF_USEC). For now its if-def'ed so that
we still *can* use clock_gettime, but for the momemnt its
not used even if its available.

OTP-15566, OTP-15686
---
 erts/emulator/nifs/common/socket_dbg.c  | 57 ++----------------------
 erts/emulator/nifs/common/socket_util.c | 77 ++++++++++++++++++++++++++++-----
 erts/emulator/nifs/common/socket_util.h |  3 ++
 3 files changed, 71 insertions(+), 66 deletions(-)

diff --git a/erts/emulator/nifs/common/socket_dbg.c b/erts/emulator/nifs/common/socket_dbg.c
index 96f75a328f..7dfc4b77bc 100644
--- a/erts/emulator/nifs/common/socket_dbg.c
+++ b/erts/emulator/nifs/common/socket_dbg.c
@@ -30,6 +30,7 @@
 #include <time.h>
 
 #include <erl_nif.h>
+#include "socket_util.h"
 #include "socket_dbg.h"
 
 #define TSELF()            enif_thread_self()
@@ -38,12 +39,6 @@
 
 static FILE* dbgout = NULL;
 
-#if defined(CLOCK_REALTIME)
-static int realtime(struct timespec* tsP);
-static int timespec2str(char *buf, unsigned int len, struct timespec *ts);
-#endif
-
-
 extern
 void esock_dbg_init(char* filename)
 {
@@ -73,10 +68,7 @@ void esock_dbg_printf( const char* prefix, const char* format, ... )
 {
   va_list         args;
   char            f[512 + sizeof(format)]; // This has to suffice...
-#if defined(CLOCK_REALTIME)
   char            stamp[30];
-  struct timespec ts;
-#endif
   int             res;
 
   /*
@@ -85,64 +77,21 @@ void esock_dbg_printf( const char* prefix, const char* format, ... )
    * But then I must change the API....something for later.
    */
 
-#if defined(CLOCK_REALTIME)
-  if (!realtime(&ts) &&
-      (timespec2str(stamp, sizeof(stamp), &ts) == 0)) {
+  if (esock_timestamp(stamp, sizeof(stamp))) {
       res = enif_snprintf(f, sizeof(f), "%s [%s] [%s] %s",
                           prefix, stamp, TSNAME(), format);
   } else {
       res = enif_snprintf(f, sizeof(f), "%s [%s] %s",
                           prefix, TSNAME(), format);
   }
-#else
-  res = enif_snprintf(f, sizeof(f), "%s [%s] %s",
-                      prefix, TSNAME(), format);
-#endif
   
   if (res > 0) {
       va_start (args, format);
       enif_vfprintf (dbgout, f, args);
       va_end (args);
-      fflush(stdout);
+      fflush(dbgout);
   }
 
   return;
 }
 
-
-#if defined(CLOCK_REALTIME)
-static
-int realtime(struct timespec* tsP)
-{
-    return clock_gettime(CLOCK_REALTIME, tsP);
-}
-
-
-
-
-/*
- * Convert a timespec struct into a readable/printable string
- */
-static
-int timespec2str(char *buf, unsigned int len, struct timespec *ts)
-{
-  int       ret, buflen;
-  struct tm t;
-
-  tzset();
-  if (localtime_r(&(ts->tv_sec), &t) == NULL)
-    return 1;
-
-  ret = strftime(buf, len, "%F %T", &t);
-  if (ret == 0)
-    return 2;
-  len -= ret - 1;
-  buflen = strlen(buf);
-
-  ret = snprintf(&buf[buflen], len, ".%06ld", ts->tv_nsec/1000);
-  if (ret >= len)
-    return 3;
-
-  return 0;
-}
-#endif
diff --git a/erts/emulator/nifs/common/socket_util.c b/erts/emulator/nifs/common/socket_util.c
index 8ad95cb6b7..0a87c9a3ca 100644
--- a/erts/emulator/nifs/common/socket_util.c
+++ b/erts/emulator/nifs/common/socket_util.c
@@ -52,6 +52,10 @@
 extern char* erl_errno_id(int error); /* THIS IS JUST TEMPORARY??? */
 
 #if defined(CLOCK_REALTIME)
+// #define ESOCK_USE_CLOCK_REALTIME 1
+#endif
+
+#if defined(ESOCK_USE_CLOCK_REALTIME)
 static int realtime(struct timespec* tsP);
 static int timespec2str(char *buf,
                         unsigned int len,
@@ -1510,10 +1514,7 @@ void esock_warning_msg( const char* format, ... )
 {
   va_list         args;
   char            f[512 + sizeof(format)]; // This has to suffice...
-#if defined(CLOCK_REALTIME)
   char            stamp[64]; // Just in case...
-  struct timespec ts;
-#endif
   int             res;
 
   /*
@@ -1525,18 +1526,13 @@ void esock_warning_msg( const char* format, ... )
   // 2018-06-29 12:13:21.232089
   // 29-Jun-2018::13:47:25.097097
 
-#if defined(CLOCK_REALTIME)
-  if (!realtime(&ts) &&
-      (timespec2str(stamp, sizeof(stamp), &ts) == 0)) {
+  if (esock_timestamp(stamp, sizeof(stamp))) {
       res = enif_snprintf(f, sizeof(f),
                           "=WARNING MSG==== %s ===\r\n%s",
                           stamp, format);
   } else {
       res = enif_snprintf(f, sizeof(f), "=WARNING MSG==== %s", format);
   }
-#else
-  res = enif_snprintf(f, sizeof(f), "=WARNING MSG==== %s", format);
-#endif
 
   if (res > 0) {
       va_start (args, format);
@@ -1549,11 +1545,67 @@ void esock_warning_msg( const char* format, ... )
 }
 
 
-#if defined(CLOCK_REALTIME)
+/* *** esock_timestamp ***
+ *
+ * Create a timestamp string.
+ * If awailable, it uses the realtime(CLOCK_REALTIME) function(s)
+ * and produces a nice readable timetamp. But if not, it produces
+ * a timestamp in the form of an Epoch.
+ */
+
+/* We should really have: ESOCK_USE_PRETTY_TIMESTAMP */
+extern
+BOOLEAN_T esock_timestamp(char *buf, unsigned int len)
+{
+#if defined(ESOCK_USE_CLOCK_REALTIME)
+
+    struct timespec ts;
+
+    if (!realtime(&ts) && (timespec2str(buf, len, &ts) == 0)) {
+        return TRUE;
+    } else {
+        return FALSE;
+    }
+
+#else
+
+    int        ret, buflen;
+    ErlNifTime monTime = enif_monotonic_time(ERL_NIF_USEC);
+    ErlNifTime offTime = enif_time_offset(ERL_NIF_USEC);
+    ErlNifTime time    = monTime + offTime;
+    time_t     sec     = time / 1000000; // (if _MSEC) sec  = time / 1000;
+    time_t     usec    = time % 1000000; // (if _MSEC) msec = time % 1000;
+    struct tm  t;
+
+    /* Ideally, we would convert this plain integer into a
+     * nice readable string, but...
+     */
+
+    if (localtime_r(&sec, &t) == NULL)
+        return FALSE;
+
+    ret = strftime(buf, len, "%d-%B-%Y::%T", &t);
+    if (ret == 0)
+        return FALSE;
+    len -= ret - 1;
+    buflen = strlen(buf);
+
+    ret = enif_snprintf(&buf[buflen], len, ".%06b64d", usec);
+    if (ret >= len)
+        return FALSE;
+
+    return TRUE;
+
+#endif
+}
+
+
+
+#if defined(ESOCK_USE_CLOCK_REALTIME)
 static
 int realtime(struct timespec* tsP)
 {
-  return clock_gettime(CLOCK_REALTIME, tsP);
+    return clock_gettime(CLOCK_REALTIME, tsP);
 }
 
 
@@ -1579,7 +1631,7 @@ int timespec2str(char *buf, unsigned int len, struct timespec *ts)
   len -= ret - 1;
   buflen = strlen(buf);
 
-  ret = snprintf(&buf[buflen], len, ".%06ld", ts->tv_nsec/1000);
+  ret = enif_snprintf(&buf[buflen], len, ".%06b64d", ts->tv_nsec/1000);
   if (ret >= len)
     return 3;
 
@@ -1588,6 +1640,7 @@ int timespec2str(char *buf, unsigned int len, struct timespec *ts)
 #endif
 
 
+
 /* =================================================================== *
  *                                                                     *
  *              Various (internal) utility functions                   *
diff --git a/erts/emulator/nifs/common/socket_util.h b/erts/emulator/nifs/common/socket_util.h
index 84b1c8085f..2688a920c4 100644
--- a/erts/emulator/nifs/common/socket_util.h
+++ b/erts/emulator/nifs/common/socket_util.h
@@ -198,6 +198,9 @@ ERL_NIF_TERM esock_make_error_str(ErlNifEnv* env, char* reason);
 extern
 ERL_NIF_TERM esock_make_error_errno(ErlNifEnv* env, int err);
 
+extern
+BOOLEAN_T esock_timestamp(char *buf, unsigned int len);
+
 extern
 void esock_warning_msg(const char* format, ... );
 
-- 
cgit v1.2.3