]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
log: Create log_clock to replace use of utime_t
authorAdam C. Emerson <aemerson@redhat.com>
Thu, 5 Oct 2017 22:17:16 +0000 (18:17 -0400)
committerAdam C. Emerson <aemerson@redhat.com>
Fri, 6 Oct 2017 21:29:06 +0000 (17:29 -0400)
We create a new time type to support using coarse timestamps (for
performance) by default while still allowing the user to switch to
fine timestamps.

Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
src/common/ceph_time.cc
src/log/LogClock.h [new file with mode: 0644]

index cd41d0581ed8327d744011f23f7bd0eba11f5889..f5072b7923d33144ca0e2e065ded673faac8a47c 100644 (file)
@@ -14,6 +14,7 @@
 
 // For ceph_timespec
 #include "ceph_time.h"
+#include "log/LogClock.h"
 #include "config.h"
 
 #if defined(__APPLE__)
@@ -80,6 +81,26 @@ namespace ceph {
       const struct ceph_timespec& ts) {
       return time_point(seconds(ts.tv_sec) + nanoseconds(ts.tv_nsec));
     }
+
+  }
+
+  namespace logging {
+    void log_clock::to_ceph_timespec(const time_point& t,
+                                    struct ceph_timespec& ts) {
+      ts.tv_sec = to_time_t(t);
+      ts.tv_nsec = (t.time_since_epoch() %std::chrono::seconds(1)).count();
+    }
+    struct ceph_timespec log_clock::to_ceph_timespec(
+      const time_point& t) {
+      struct ceph_timespec ts;
+      to_ceph_timespec(t, ts);
+      return ts;
+    }
+    log_clock::time_point log_clock::from_ceph_timespec(
+      const struct ceph_timespec& ts) {
+      return time_point(std::chrono::seconds(ts.tv_sec) +
+                       std::chrono::nanoseconds(ts.tv_nsec));
+    }
   }
 
   using std::chrono::duration_cast;
@@ -132,4 +153,6 @@ namespace ceph {
   operator<< <coarse_mono_clock>(std::ostream& m, const coarse_mono_time& t);
   template std::ostream&
   operator<< <coarse_real_clock>(std::ostream& m, const coarse_real_time& t);
+  template std::ostream&
+  operator<< <logging::log_clock>(std::ostream& m, const logging::log_time& t);
 }
diff --git a/src/log/LogClock.h b/src/log/LogClock.h
new file mode 100644 (file)
index 0000000..e790dbd
--- /dev/null
@@ -0,0 +1,136 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#ifndef CEPH_LOG_CLOCK_H
+#define CEPH_LOG_CLOCK_H
+
+#include <cstdio>
+#include <chrono>
+#include <ctime>
+#include <sys/time.h>
+
+#include "include/assert.h"
+#include "common/ceph_time.h"
+
+namespace ceph {
+namespace logging {
+class log_clock {
+public:
+  using duration = timespan;
+  using rep = duration::rep;
+  using period = duration::period;
+  // The second template parameter defaults to the clock's duration
+  // type.
+  using time_point = std::chrono::time_point<log_clock>;
+  static constexpr const bool is_steady = false;
+
+  void coarsen() {
+    appropriate_now = coarse_now;
+  }
+
+  void refine() {
+    appropriate_now = fine_now;
+  }
+
+  time_point now() noexcept {
+    return appropriate_now();
+  }
+
+  static bool is_zero(const time_point& t) {
+    return (t == time_point::min());
+  }
+
+  // Allow conversion to/from any clock with the same interface as
+  // std::chrono::system_clock)
+  template<typename Clock, typename Duration>
+  static time_point to_system_time_point(
+    const std::chrono::time_point<Clock, Duration>& t) {
+    return time_point(seconds(Clock::to_time_t(t)) +
+                     std::chrono::duration_cast<duration>(
+                       t.time_since_epoch() % std::chrono::seconds(1)));
+  }
+  template<typename Clock, typename Duration>
+  static std::chrono::time_point<Clock, Duration> to_system_time_point(
+    const time_point& t) {
+    return (Clock::from_time_t(to_time_t(t)) +
+           std::chrono::duration_cast<Duration>(t.time_since_epoch() %
+                                                std::chrono::seconds(1)));
+  }
+
+  static time_t to_time_t(const time_point& t) noexcept {
+    return std::chrono::duration_cast<std::chrono::seconds>(
+      t.time_since_epoch()).count();
+  }
+  static time_point from_time_t(const time_t& t) noexcept {
+    return time_point(std::chrono::seconds(t));
+  }
+
+  static void to_timespec(const time_point& t, struct timespec& ts) {
+    ts.tv_sec = to_time_t(t);
+    ts.tv_nsec = (t.time_since_epoch() % std::chrono::seconds(1)).count();
+  }
+  static struct timespec to_timespec(const time_point& t) {
+    struct timespec ts;
+    to_timespec(t, ts);
+    return ts;
+  }
+  static time_point from_timespec(const struct timespec& ts) {
+    return time_point(std::chrono::seconds(ts.tv_sec) +
+                     std::chrono::nanoseconds(ts.tv_nsec));
+  }
+
+  static void to_ceph_timespec(const time_point& t,
+                              struct ceph_timespec& ts);
+  static struct ceph_timespec to_ceph_timespec(const time_point& t);
+  static time_point from_ceph_timespec(const struct ceph_timespec& ts);
+
+  static void to_timeval(const time_point& t, struct timeval& tv) {
+    tv.tv_sec = to_time_t(t);
+    tv.tv_usec = std::chrono::duration_cast<std::chrono::microseconds>(
+      t.time_since_epoch() % std::chrono::seconds(1)).count();
+  }
+  static struct timeval to_timeval(const time_point& t) {
+    struct timeval tv;
+    to_timeval(t, tv);
+    return tv;
+  }
+  static time_point from_timeval(const struct timeval& tv) {
+    return time_point(std::chrono::seconds(tv.tv_sec) +
+                     std::chrono::microseconds(tv.tv_usec));
+  }
+
+  static double to_double(const time_point& t) {
+    return std::chrono::duration<double>(t.time_since_epoch()).count();
+  }
+  static time_point from_double(const double d) {
+    return time_point(std::chrono::duration_cast<duration>(
+                       std::chrono::duration<double>(d)));
+  }
+private:
+  static time_point coarse_now() {
+    return time_point(coarse_real_clock::now().time_since_epoch());
+  }
+  static time_point fine_now() {
+    return time_point(real_clock::now().time_since_epoch());
+  }
+  time_point(*appropriate_now)() = coarse_now;
+};
+using log_time = log_clock::time_point;
+inline int append_time(const log_time& t, char *out, int outlen) {
+  auto tv = log_clock::to_timeval(t);
+  std::tm bdt;
+  localtime_r(&tv.tv_sec, &bdt);
+
+  auto r = std::snprintf(out, outlen,
+                        "%04d-%02d-%02d %02d:%02d:%02d.%06ld",
+                        bdt.tm_year + 1900, bdt.tm_mon + 1, bdt.tm_mday,
+                        bdt.tm_hour, bdt.tm_min, bdt.tm_sec, tv.tv_usec);
+  // Since our caller just adds the return value to something without
+  // checking it…
+  ceph_assert(r >= 0);
+  return r;
+}
+}
+}
+
+#endif