]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/include/utime.h
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / include / utime.h
index ba4f17e95826fd9ee6da65616151bbb72987c7e1..bc9f6429a12c1be8e4198b844886b40e5e39f2f4 100644 (file)
 #include "include/timegm.h"
 #include "common/strtol.h"
 #include "common/ceph_time.h"
+#include "common/safe_io.h"
+#include "common/SubProcess.h"
 #include "include/denc.h"
 
 
 // --------
 // utime_t
 
-/* WARNING: If add member in utime_t, please make sure the encode/decode funtion
+inline __u32 cap_to_u32_max(__u64 t) {
+  return std::min(t, (__u64)std::numeric_limits<uint32_t>::max());
+}
+/* WARNING: If add member in utime_t, please make sure the encode/decode function
  * work well. For little-endian machine, we should make sure there is no padding
  * in 32-bit machine and 64-bit machine.
  * You should also modify the padding_check function.
@@ -45,9 +50,10 @@ public:
   bool is_zero() const {
     return (tv.tv_sec == 0) && (tv.tv_nsec == 0);
   }
+
   void normalize() {
     if (tv.tv_nsec > 1000000000ul) {
-      tv.tv_sec += tv.tv_nsec / (1000000000ul);
+      tv.tv_sec = cap_to_u32_max(tv.tv_sec + tv.tv_nsec / (1000000000ul));
       tv.tv_nsec %= 1000000000ul;
     }
   }
@@ -60,17 +66,17 @@ public:
   }
   utime_t(const struct timespec v)
   {
+    // NOTE: this is used by ceph_clock_now() so should be kept
+    // as thin as possible.
     tv.tv_sec = v.tv_sec;
     tv.tv_nsec = v.tv_nsec;
   }
-  explicit utime_t(const ceph::real_time& rt) {
-    ceph_timespec ts = real_clock::to_ceph_timespec(rt);
-    decode_timeval(&ts);
-  }
-  explicit utime_t(const ceph::coarse_real_time& crt) {
-    ceph_timespec ts = coarse_real_clock::to_ceph_timespec(crt);
-    decode_timeval(&ts);
-  }
+  // conversion from ceph::real_time/coarse_real_time
+  template <typename Clock, typename std::enable_if_t<
+            ceph::converts_to_timespec_v<Clock>>* = nullptr>
+  explicit utime_t(const std::chrono::time_point<Clock>& t)
+    : utime_t(Clock::to_timespec(t)) {} // forward to timespec ctor
+
   utime_t(const struct timeval &v) {
     set_from_timeval(&v);
   }
@@ -83,7 +89,7 @@ public:
   }
   void set_from_double(double d) { 
     tv.tv_sec = (__u32)trunc(d);
-    tv.tv_nsec = (__u32)((d - (double)tv.tv_sec) * (double)1000000000.0);
+    tv.tv_nsec = (__u32)((d - (double)tv.tv_sec) * 1000000000.0);
   }
 
   real_time to_real_time() const {
@@ -128,16 +134,18 @@ public:
 #if defined(CEPH_LITTLE_ENDIAN)
     bl.append((char *)(this), sizeof(__u32) + sizeof(__u32));
 #else
-    ::encode(tv.tv_sec, bl);
-    ::encode(tv.tv_nsec, bl);
+    using ceph::encode;
+    encode(tv.tv_sec, bl);
+    encode(tv.tv_nsec, bl);
 #endif
   }
-  void decode(bufferlist::iterator &p) {
+  void decode(bufferlist::const_iterator &p) {
 #if defined(CEPH_LITTLE_ENDIAN)
     p.copy(sizeof(__u32) + sizeof(__u32), (char *)(this));
 #else
-    ::decode(tv.tv_sec, p);
-    ::decode(tv.tv_nsec, p);
+    using ceph::decode;
+    decode(tv.tv_sec, p);
+    decode(tv.tv_nsec, p);
 #endif
   }
 
@@ -175,6 +183,17 @@ public:
     return utime_t(tt, 0);
   }
 
+  utime_t round_to_day() {
+    struct tm bdt;
+    time_t tt = sec();
+    localtime_r(&tt, &bdt);
+    bdt.tm_sec = 0;
+    bdt.tm_min = 0;
+    bdt.tm_hour = 0;
+    tt = mktime(&bdt);
+    return utime_t(tt, 0);
+  }
+
   // cast to double
   operator double() const {
     return (double)sec() + ((double)nsec() / 1000000000.0L);
@@ -201,7 +220,7 @@ public:
       // raw seconds.  this looks like a relative time.
       out << (long)sec() << "." << std::setw(6) << usec();
     } else {
-      // localtime.  this looks like an absolute time.
+      // this looks like an absolute time.
       //  aim for http://en.wikipedia.org/wiki/ISO_8601
       struct tm bdt;
       time_t tt = sec();
@@ -230,7 +249,7 @@ public:
       // raw seconds.  this looks like a relative time.
       out << (long)sec() << "." << std::setw(6) << usec();
     } else {
-      // localtime.  this looks like an absolute time.
+      // this looks like an absolute time.
       //  aim for http://en.wikipedia.org/wiki/ISO_8601
       struct tm bdt;
       time_t tt = sec();
@@ -259,7 +278,7 @@ public:
       // raw seconds.  this looks like a relative time.
       out << (long)sec() << "." << std::setw(6) << usec();
     } else {
-      // localtime.  this looks like an absolute time.
+      // this looks like an absolute time.
       //  aim for http://en.wikipedia.org/wiki/ISO_8601
       struct tm bdt;
       time_t tt = sec();
@@ -285,7 +304,7 @@ public:
       // raw seconds.  this looks like a relative time.
       out << (long)sec() << "." << std::setw(6) << usec();
     } else {
-      // localtime.  this looks like an absolute time.
+      // this looks like an absolute time.
       //  aim for http://en.wikipedia.org/wiki/ISO_8601
       struct tm bdt;
       time_t tt = sec();
@@ -326,6 +345,32 @@ public:
         bdt.tm_hour, bdt.tm_min, bdt.tm_sec);
   }
 
+  static int invoke_date(const std::string& date_str, utime_t *result) {
+     char buf[256];
+
+     SubProcess bin_date("/bin/date", SubProcess::CLOSE, SubProcess::PIPE, SubProcess::KEEP);
+     bin_date.add_cmd_args("-d", date_str.c_str(), "+%s %N", NULL);
+
+     int r = bin_date.spawn();
+     if (r < 0) return r;
+
+     ssize_t n = safe_read(bin_date.get_stdout(), buf, sizeof(buf));
+
+     r = bin_date.join();
+     if (r || n <= 0) return -EINVAL;
+
+     uint64_t epoch, nsec;
+     std::istringstream iss(buf);
+
+     iss >> epoch;
+     iss >> nsec;
+
+     *result = utime_t(epoch, nsec);
+
+     return 0;
+  }
+
+
   static int parse_date(const string& date, uint64_t *epoch, uint64_t *nsec,
                         string *out_date=NULL, string *out_time=NULL) {
     struct tm tm;
@@ -390,26 +435,35 @@ public:
 
     return 0;
   }
+
+  bool parse(const string& s) {
+    uint64_t epoch, nsec;
+    int r = parse_date(s, &epoch, &nsec);
+    if (r < 0) {
+      return false;
+    }
+    *this = utime_t(epoch, nsec);
+    return true;
+  }
 };
 WRITE_CLASS_ENCODER(utime_t)
 WRITE_CLASS_DENC(utime_t)
 
-
 // arithmetic operators
 inline utime_t operator+(const utime_t& l, const utime_t& r) {
-  return utime_t( l.sec() + r.sec() + (l.nsec()+r.nsec())/1000000000L,
-                  (l.nsec()+r.nsec())%1000000000L );
+  __u64 sec = (__u64)l.sec() + r.sec();
+  return utime_t(cap_to_u32_max(sec), l.nsec() + r.nsec());
 }
 inline utime_t& operator+=(utime_t& l, const utime_t& r) {
-  l.sec_ref() += r.sec() + (l.nsec()+r.nsec())/1000000000L;
+  l.sec_ref() = cap_to_u32_max((__u64)l.sec() + r.sec());
   l.nsec_ref() += r.nsec();
-  l.nsec_ref() %= 1000000000L;
+  l.normalize();
   return l;
 }
 inline utime_t& operator+=(utime_t& l, double f) {
   double fs = trunc(f);
-  double ns = (f - fs) * (double)1000000000.0;
-  l.sec_ref() += (long)fs;
+  double ns = (f - fs) * 1000000000.0;
+  l.sec_ref() = cap_to_u32_max(l.sec() + (__u64)fs);
   l.nsec_ref() += (long)ns;
   l.normalize();
   return l;
@@ -431,7 +485,7 @@ inline utime_t& operator-=(utime_t& l, const utime_t& r) {
 }
 inline utime_t& operator-=(utime_t& l, double f) {
   double fs = trunc(f);
-  double ns = (f - fs) * (double)1000000000.0;
+  double ns = (f - fs) * 1000000000.0;
   l.sec_ref() -= (long)fs;
   long nsl = (long)ns;
   if (nsl) {
@@ -479,4 +533,9 @@ inline std::ostream& operator<<(std::ostream& out, const utime_t& t)
   return t.localtime(out);
 }
 
+inline std::string utimespan_str(const utime_t& age) {
+  auto age_ts = ceph::timespan(age.nsec()) + std::chrono::seconds(age.sec());
+  return timespan_str(age_ts);
+}
+
 #endif