]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/common/ceph_time.cc
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / common / ceph_time.cc
index bb708bb4675646d467ff0fe4ab5033997c63901f..69b3cdde6e87d147d793a1fcb75f27c5a3adda3a 100644 (file)
 
 // For ceph_timespec
 #include "ceph_time.h"
+
+#include <fmt/chrono.h>
+#include <fmt/ostream.h>
+
 #include "log/LogClock.h"
 #include "config.h"
 #include "strtol.h"
@@ -52,277 +56,298 @@ int clock_gettime(int clk_id, struct timespec *tp)
 }
 #endif
 
+using namespace std::literals;
+
 namespace ceph {
-  namespace time_detail {
-    void real_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() % seconds(1)).count();
-    }
-    struct ceph_timespec real_clock::to_ceph_timespec(const time_point& t) {
-      struct ceph_timespec ts;
-      to_ceph_timespec(t, ts);
-      return ts;
-    }
-    real_clock::time_point real_clock::from_ceph_timespec(
-      const struct ceph_timespec& ts) {
-      return time_point(seconds(ts.tv_sec) + nanoseconds(ts.tv_nsec));
-    }
+using std::chrono::seconds;
+using std::chrono::nanoseconds;
+void real_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() % 1s).count();
+}
+struct ceph_timespec real_clock::to_ceph_timespec(const time_point& t) {
+  struct ceph_timespec ts;
+  to_ceph_timespec(t, ts);
+  return ts;
+}
+real_clock::time_point real_clock::from_ceph_timespec(
+  const struct ceph_timespec& ts) {
+  return time_point(seconds(ts.tv_sec) + nanoseconds(ts.tv_nsec));
+}
 
-    void coarse_real_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() % seconds(1)).count();
-    }
-    struct ceph_timespec coarse_real_clock::to_ceph_timespec(
-      const time_point& t) {
-      struct ceph_timespec ts;
-      to_ceph_timespec(t, ts);
-      return ts;
-    }
-    coarse_real_clock::time_point coarse_real_clock::from_ceph_timespec(
-      const struct ceph_timespec& ts) {
-      return time_point(seconds(ts.tv_sec) + nanoseconds(ts.tv_nsec));
-    }
+void coarse_real_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() % seconds(1)).count();
+}
+struct ceph_timespec coarse_real_clock::to_ceph_timespec(
+  const time_point& t) {
+  struct ceph_timespec ts;
+  to_ceph_timespec(t, ts);
+  return ts;
+}
+coarse_real_clock::time_point coarse_real_clock::from_ceph_timespec(
+  const struct ceph_timespec& ts) {
+  return time_point(seconds(ts.tv_sec) + nanoseconds(ts.tv_nsec));
+}
 
-  }
 
-  using std::chrono::duration_cast;
-  using std::chrono::seconds;
-  using std::chrono::microseconds;
+using std::chrono::duration_cast;
+using std::chrono::seconds;
+using std::chrono::microseconds;
 
-  template<typename Clock,
-          typename std::enable_if<Clock::is_steady>::type*>
-  std::ostream& operator<<(std::ostream& m,
-                          const std::chrono::time_point<Clock>& t) {
-    return m << std::fixed << std::chrono::duration<double>(
-               t.time_since_epoch()).count()
-            << 's';
-  }
+template<typename Clock,
+        typename std::enable_if<Clock::is_steady>::type*>
+std::ostream& operator<<(std::ostream& m,
+                        const std::chrono::time_point<Clock>& t) {
+  return m << std::fixed << std::chrono::duration<double>(
+    t.time_since_epoch()).count()
+          << 's';
+}
 
-  std::ostream& operator<<(std::ostream& m, const timespan& t) {
-    static_assert(std::is_unsigned_v<timespan::rep>);
-    m << std::chrono::duration_cast<std::chrono::seconds>(t).count();
-    if (auto ns = (t % 1s).count(); ns > 0) {
-      char oldfill = m.fill();
-      m.fill('0');
-      m << '.' << std::setw(9) << ns;
-      m.fill(oldfill);
-    }
-    return m << 's';
-  }
+template<typename Clock,
+        typename std::enable_if<!Clock::is_steady>::type*>
+std::ostream& operator<<(std::ostream& m,
+                        const std::chrono::time_point<Clock>& t) {
+  m.setf(std::ios::right);
+  char oldfill = m.fill();
+  m.fill('0');
+  // localtime.  this looks like an absolute time.
+  //  conform to http://en.wikipedia.org/wiki/ISO_8601
+  struct tm bdt;
+  time_t tt = Clock::to_time_t(t);
+  localtime_r(&tt, &bdt);
+  char tz[32] = { 0 };
+  strftime(tz, sizeof(tz), "%z", &bdt);
+  m << std::setw(4) << (bdt.tm_year+1900)  // 2007 -> '07'
+    << '-' << std::setw(2) << (bdt.tm_mon+1)
+    << '-' << std::setw(2) << bdt.tm_mday
+    << 'T'
+    << std::setw(2) << bdt.tm_hour
+    << ':' << std::setw(2) << bdt.tm_min
+    << ':' << std::setw(2) << bdt.tm_sec
+    << "." << std::setw(6) << duration_cast<microseconds>(
+      t.time_since_epoch() % seconds(1)).count()
+    << tz;
+  m.fill(oldfill);
+  m.unsetf(std::ios::right);
+  return m;
+}
 
-  template<typename Clock,
-          typename std::enable_if<!Clock::is_steady>::type*>
-  std::ostream& operator<<(std::ostream& m,
-                          const std::chrono::time_point<Clock>& t) {
-    m.setf(std::ios::right);
-    char oldfill = m.fill();
-    m.fill('0');
-    // localtime.  this looks like an absolute time.
-    //  conform to http://en.wikipedia.org/wiki/ISO_8601
-    struct tm bdt;
-    time_t tt = Clock::to_time_t(t);
-    localtime_r(&tt, &bdt);
-    char tz[32] = { 0 };
-    strftime(tz, sizeof(tz), "%z", &bdt);
-    m << std::setw(4) << (bdt.tm_year+1900)  // 2007 -> '07'
-      << '-' << std::setw(2) << (bdt.tm_mon+1)
-      << '-' << std::setw(2) << bdt.tm_mday
-      << 'T'
-      << std::setw(2) << bdt.tm_hour
-      << ':' << std::setw(2) << bdt.tm_min
-      << ':' << std::setw(2) << bdt.tm_sec
-      << "." << std::setw(6) << duration_cast<microseconds>(
-       t.time_since_epoch() % seconds(1)).count()
-      << tz;
-    m.fill(oldfill);
-    m.unsetf(std::ios::right);
-    return m;
-  }
+template std::ostream&
+operator<< <mono_clock>(std::ostream& m, const mono_time& t);
+template std::ostream&
+operator<< <real_clock>(std::ostream& m, const real_time& t);
+template std::ostream&
+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<< <mono_clock>(std::ostream& m, const mono_time& t);
-  template std::ostream&
-  operator<< <real_clock>(std::ostream& m, const real_time& t);
-  template std::ostream&
-  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);
+std::string timespan_str(timespan t)
+{
+  // FIXME: somebody pretty please make a version of this function
+  // that isn't as lame as this one!
+  uint64_t nsec = std::chrono::nanoseconds(t).count();
+  std::ostringstream ss;
+  if (nsec < 2000000000) {
+    ss << ((float)nsec / 1000000000) << "s";
+    return ss.str();
+  }
+  uint64_t sec = nsec / 1000000000;
+  if (sec < 120) {
+    ss << sec << "s";
+    return ss.str();
+  }
+  uint64_t min = sec / 60;
+  if (min < 120) {
+    ss << min << "m";
+    return ss.str();
+  }
+  uint64_t hr = min / 60;
+  if (hr < 48) {
+    ss << hr << "h";
+    return ss.str();
+  }
+  uint64_t day = hr / 24;
+  if (day < 14) {
+    ss << day << "d";
+    return ss.str();
+  }
+  uint64_t wk = day / 7;
+  if (wk < 12) {
+    ss << wk << "w";
+    return ss.str();
+  }
+  uint64_t mn = day / 30;
+  if (mn < 24) {
+    ss << mn << "M";
+    return ss.str();
+  }
+  uint64_t yr = day / 365;
+  ss << yr << "y";
+  return ss.str();
+}
 
-  std::string timespan_str(timespan t)
-  {
-    // FIXME: somebody pretty please make a version of this function
-    // that isn't as lame as this one!
-    uint64_t nsec = std::chrono::nanoseconds(t).count();
-    ostringstream ss;
-    if (nsec < 2000000000) {
-      ss << ((float)nsec / 1000000000) << "s";
-      return ss.str();
-    }
-    uint64_t sec = nsec / 1000000000;
-    if (sec < 120) {
-      ss << sec << "s";
-      return ss.str();
-    }
-    uint64_t min = sec / 60;
-    if (min < 120) {
-      ss << min << "m";
-      return ss.str();
-    }
-    uint64_t hr = min / 60;
-    if (hr < 48) {
-      ss << hr << "h";
-      return ss.str();
-    }
-    uint64_t day = hr / 24;
-    if (day < 14) {
-      ss << day << "d";
-      return ss.str();
-    }
-    uint64_t wk = day / 7;
-    if (wk < 12) {
-      ss << wk << "w";
-      return ss.str();
-    }
-    uint64_t mn = day / 30;
-    if (mn < 24) {
-      ss << mn << "M";
-      return ss.str();
-    }
-    uint64_t yr = day / 365;
+std::string exact_timespan_str(timespan t)
+{
+  uint64_t nsec = std::chrono::nanoseconds(t).count();
+  uint64_t sec = nsec / 1000000000;
+  nsec %= 1000000000;
+  uint64_t yr = sec / (60 * 60 * 24 * 365);
+  std::ostringstream ss;
+  if (yr) {
     ss << yr << "y";
-    return ss.str();
+    sec -= yr * (60 * 60 * 24 * 365);
+  }
+  uint64_t mn = sec / (60 * 60 * 24 * 30);
+  if (mn >= 3) {
+    ss << mn << "mo";
+    sec -= mn * (60 * 60 * 24 * 30);
+  }
+  uint64_t wk = sec / (60 * 60 * 24 * 7);
+  if (wk >= 2) {
+    ss << wk << "w";
+    sec -= wk * (60 * 60 * 24 * 7);
+  }
+  uint64_t day = sec / (60 * 60 * 24);
+  if (day >= 2) {
+    ss << day << "d";
+    sec -= day * (60 * 60 * 24);
+  }
+  uint64_t hr = sec / (60 * 60);
+  if (hr >= 2) {
+    ss << hr << "h";
+    sec -= hr * (60 * 60);
   }
+  uint64_t min = sec / 60;
+  if (min >= 2) {
+    ss << min << "m";
+    sec -= min * 60;
+  }
+  if (sec) {
+    ss << sec;
+  }
+  if (nsec) {
+    ss << ((float)nsec / 1000000000);
+  }
+  if (sec || nsec) {
+    ss << "s";
+  }
+  return ss.str();
+}
 
-  std::string exact_timespan_str(timespan t)
-  {
-    uint64_t nsec = std::chrono::nanoseconds(t).count();
-    uint64_t sec = nsec / 1000000000;
-    nsec %= 1000000000;
-    uint64_t yr = sec / (60 * 60 * 24 * 365);
-    ostringstream ss;
-    if (yr) {
-      ss << yr << "y";
-      sec -= yr * (60 * 60 * 24 * 365);
-    }
-    uint64_t mn = sec / (60 * 60 * 24 * 30);
-    if (mn >= 3) {
-      ss << mn << "mo";
-      sec -= mn * (60 * 60 * 24 * 30);
+std::chrono::seconds parse_timespan(const std::string& s)
+{
+  static std::map<std::string,int> units = {
+    { "s", 1 },
+    { "sec", 1 },
+    { "second", 1 },
+    { "seconds", 1 },
+    { "m", 60 },
+    { "min", 60 },
+    { "minute", 60 },
+    { "minutes", 60 },
+    { "h", 60*60 },
+    { "hr", 60*60 },
+    { "hour", 60*60 },
+    { "hours", 60*60 },
+    { "d", 24*60*60 },
+    { "day", 24*60*60 },
+    { "days", 24*60*60 },
+    { "w", 7*24*60*60 },
+    { "wk", 7*24*60*60 },
+    { "week", 7*24*60*60 },
+    { "weeks", 7*24*60*60 },
+    { "mo", 30*24*60*60 },
+    { "month", 30*24*60*60 },
+    { "months", 30*24*60*60 },
+    { "y", 365*24*60*60 },
+    { "yr", 365*24*60*60 },
+    { "year", 365*24*60*60 },
+    { "years", 365*24*60*60 },
+  };
+
+  auto r = 0s;
+  auto pos = 0u;
+  while (pos < s.size()) {
+    // skip whitespace
+    while (std::isspace(s[pos])) {
+      ++pos;
     }
-    uint64_t wk = sec / (60 * 60 * 24 * 7);
-    if (wk >= 2) {
-      ss << wk << "w";
-      sec -= wk * (60 * 60 * 24 * 7);
+    if (pos >= s.size()) {
+      break;
     }
-    uint64_t day = sec / (60 * 60 * 24);
-    if (day >= 2) {
-      ss << day << "d";
-      sec -= day * (60 * 60 * 24);
+
+    // consume any digits
+    auto val_start = pos;
+    while (std::isdigit(s[pos])) {
+      ++pos;
     }
-    uint64_t hr = sec / (60 * 60);
-    if (hr >= 2) {
-      ss << hr << "h";
-      sec -= hr * (60 * 60);
+    if (val_start == pos) {
+      throw std::invalid_argument("expected digit");
     }
-    uint64_t min = sec / 60;
-    if (min >= 2) {
-      ss << min << "m";
-      sec -= min * 60;
+    auto n = s.substr(val_start, pos - val_start);
+    std::string err;
+    auto val = strict_strtoll(n.c_str(), 10, &err);
+    if (err.size()) {
+      throw std::invalid_argument(err);
     }
-    if (sec) {
-      ss << sec;
+
+    // skip whitespace
+    while (std::isspace(s[pos])) {
+      ++pos;
     }
-    if (nsec) {
-      ss << ((float)nsec / 1000000000);
+
+    // consume unit
+    auto unit_start = pos;
+    while (std::isalpha(s[pos])) {
+      ++pos;
     }
-    if (sec || nsec) {
-      ss << "s";
+    if (unit_start != pos) {
+      auto unit = s.substr(unit_start, pos - unit_start);
+      auto p = units.find(unit);
+      if (p == units.end()) {
+       throw std::invalid_argument("unrecogized unit '"s + unit + "'");
+      }
+      val *= p->second;
+    } else if (pos < s.size()) {
+      throw std::invalid_argument("unexpected trailing '"s + s.substr(pos) + "'");
     }
-    return ss.str();
+    r += std::chrono::seconds(val);
   }
+  return r;
+}
 
-  std::chrono::seconds parse_timespan(const std::string& s)
-  {
-    static std::map<string,int> units = {
-      { "s", 1 },
-      { "sec", 1 },
-      { "second", 1 },
-      { "seconds", 1 },
-      { "m", 60 },
-      { "min", 60 },
-      { "minute", 60 },
-      { "minutes", 60 },
-      { "h", 60*60 },
-      { "hr", 60*60 },
-      { "hour", 60*60 },
-      { "hours", 60*60 },
-      { "d", 24*60*60 },
-      { "day", 24*60*60 },
-      { "days", 24*60*60 },
-      { "w", 7*24*60*60 },
-      { "wk", 7*24*60*60 },
-      { "week", 7*24*60*60 },
-      { "weeks", 7*24*60*60 },
-      { "mo", 30*24*60*60 },
-      { "month", 30*24*60*60 },
-      { "months", 30*24*60*60 },
-      { "y", 365*24*60*60 },
-      { "yr", 365*24*60*60 },
-      { "year", 365*24*60*60 },
-      { "years", 365*24*60*60 },
-    };
+}
 
-    auto r = 0s;
-    auto pos = 0u;
-    while (pos < s.size()) {
-      // skip whitespace
-      while (std::isspace(s[pos])) {
-       ++pos;
-      }
-      if (pos >= s.size()) {
-       break;
-      }
+namespace std {
+template<typename Rep, typename Period>
+ostream& operator<<(ostream& m, const chrono::duration<Rep, Period>& t) {
+  if constexpr (chrono::treat_as_floating_point_v<Rep> ||
+                Period::den > 1) {
+    using seconds_t = chrono::duration<float>;
+    ::fmt::print(m, "{:.9}", chrono::duration_cast<seconds_t>(t));
+  } else {
+    ::fmt::print(m, "{}", t);
+  }
+  return m;
+}
 
-      // consume any digits
-      auto val_start = pos;
-      while (std::isdigit(s[pos])) {
-       ++pos;
-      }
-      if (val_start == pos) {
-       throw invalid_argument("expected digit");
-      }
-      string n = s.substr(val_start, pos - val_start);
-      string err;
-      auto val = strict_strtoll(n.c_str(), 10, &err);
-      if (err.size()) {
-       throw invalid_argument(err);
-      }
+template ostream&
+operator<< <::ceph::timespan::rep,
+            ::ceph::timespan::period> (ostream&, const ::ceph::timespan&);
 
-      // skip whitespace
-      while (std::isspace(s[pos])) {
-       ++pos;
-      }
+template ostream&
+operator<< <::ceph::signedspan::rep,
+            ::ceph::signedspan::period> (ostream&, const ::ceph::signedspan&);
 
-      // consume unit
-      auto unit_start = pos;
-      while (std::isalpha(s[pos])) {
-       ++pos;
-      }
-      if (unit_start != pos) {
-       string unit = s.substr(unit_start, pos - unit_start);
-       auto p = units.find(unit);
-       if (p == units.end()) {
-         throw invalid_argument("unrecogized unit '"s + unit + "'");
-       }
-       val *= p->second;
-      } else if (pos < s.size()) {
-       throw invalid_argument("unexpected trailing '"s + s.substr(pos) + "'");
-      }
-      r += chrono::seconds(val);
-    }
-    return r;
-  }
+template ostream&
+operator<< <chrono::seconds::rep,
+            chrono::seconds::period> (ostream&, const chrono::seconds&);
 
-}
+template ostream&
+operator<< <chrono::milliseconds::rep,
+            chrono::milliseconds::period> (ostream&, const chrono::milliseconds&);
+
+} // namespace std