+++ /dev/null
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-/*
- * Ceph - scalable distributed file system
- *
- * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
- *
- * This is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1, as published by the Free Software
- * Foundation. See file COPYING.
- *
- */
-
-#ifndef CEPH_UTIME_H
-#define CEPH_UTIME_H
-
-#include <math.h>
-#include <sys/time.h>
-#include <time.h>
-#include <errno.h>
-
-#include "include/types.h"
-#include "include/timegm.h"
-#include "common/strtol.h"
-#include "common/ceph_time.h"
-#include "include/denc.h"
-
-
-// --------
-// utime_t
-
-/* WARNING: If add member in utime_t, please make sure the encode/decode funtion
- * 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.
- */
-class utime_t {
-public:
- struct {
- __u32 tv_sec, tv_nsec;
- } tv;
-
- 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_nsec %= 1000000000ul;
- }
- }
-
- // cons
- utime_t() { tv.tv_sec = 0; tv.tv_nsec = 0; }
- utime_t(time_t s, int n) { tv.tv_sec = s; tv.tv_nsec = n; normalize(); }
- utime_t(const struct ceph_timespec &v) {
- decode_timeval(&v);
- }
- utime_t(const struct timespec v)
- {
- 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);
- }
- utime_t(const struct timeval &v) {
- set_from_timeval(&v);
- }
- utime_t(const struct timeval *v) {
- set_from_timeval(v);
- }
- void to_timespec(struct timespec *ts) const {
- ts->tv_sec = tv.tv_sec;
- ts->tv_nsec = tv.tv_nsec;
- }
- void set_from_double(double d) {
- tv.tv_sec = (__u32)trunc(d);
- tv.tv_nsec = (__u32)((d - (double)tv.tv_sec) * (double)1000000000.0);
- }
-
- real_time to_real_time() const {
- ceph_timespec ts;
- encode_timeval(&ts);
- return ceph::real_clock::from_ceph_timespec(ts);
- }
-
- // accessors
- time_t sec() const { return tv.tv_sec; }
- long usec() const { return tv.tv_nsec/1000; }
- int nsec() const { return tv.tv_nsec; }
-
- // ref accessors/modifiers
- __u32& sec_ref() { return tv.tv_sec; }
- __u32& nsec_ref() { return tv.tv_nsec; }
-
- uint64_t to_nsec() const {
- return (uint64_t)tv.tv_nsec + (uint64_t)tv.tv_sec * 1000000000ull;
- }
- uint64_t to_msec() const {
- return (uint64_t)tv.tv_nsec / 1000000ull + (uint64_t)tv.tv_sec * 1000ull;
- }
-
- void copy_to_timeval(struct timeval *v) const {
- v->tv_sec = tv.tv_sec;
- v->tv_usec = tv.tv_nsec/1000;
- }
- void set_from_timeval(const struct timeval *v) {
- tv.tv_sec = v->tv_sec;
- tv.tv_nsec = v->tv_usec*1000;
- }
- void padding_check() {
- static_assert(
- sizeof(utime_t) ==
- sizeof(tv.tv_sec) +
- sizeof(tv.tv_nsec)
- ,
- "utime_t have padding");
- }
- void encode(bufferlist &bl) const {
-#if defined(CEPH_LITTLE_ENDIAN)
- bl.append((char *)(this), sizeof(__u32) + sizeof(__u32));
-#else
- ::encode(tv.tv_sec, bl);
- ::encode(tv.tv_nsec, bl);
-#endif
- }
- void decode(bufferlist::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);
-#endif
- }
-
- DENC(utime_t, v, p) {
- denc(v.tv.tv_sec, p);
- denc(v.tv.tv_nsec, p);
- }
-
-
- void encode_timeval(struct ceph_timespec *t) const {
- t->tv_sec = tv.tv_sec;
- t->tv_nsec = tv.tv_nsec;
- }
- void decode_timeval(const struct ceph_timespec *t) {
- tv.tv_sec = t->tv_sec;
- tv.tv_nsec = t->tv_nsec;
- }
-
- utime_t round_to_minute() {
- struct tm bdt;
- time_t tt = sec();
- localtime_r(&tt, &bdt);
- bdt.tm_sec = 0;
- tt = mktime(&bdt);
- return utime_t(tt, 0);
- }
-
- utime_t round_to_hour() {
- struct tm bdt;
- time_t tt = sec();
- localtime_r(&tt, &bdt);
- bdt.tm_sec = 0;
- bdt.tm_min = 0;
- tt = mktime(&bdt);
- return utime_t(tt, 0);
- }
-
- // cast to double
- operator double() const {
- return (double)sec() + ((double)nsec() / 1000000000.0L);
- }
- operator ceph_timespec() const {
- ceph_timespec ts;
- ts.tv_sec = sec();
- ts.tv_nsec = nsec();
- return ts;
- }
-
- void sleep() const {
- struct timespec ts;
- to_timespec(&ts);
- nanosleep(&ts, NULL);
- }
-
- // output
- ostream& gmtime(ostream& out) const {
- out.setf(std::ios::right);
- char oldfill = out.fill();
- out.fill('0');
- if (sec() < ((time_t)(60*60*24*365*10))) {
- // raw seconds. this looks like a relative time.
- out << (long)sec() << "." << std::setw(6) << usec();
- } else {
- // localtime. this looks like an absolute time.
- // aim for http://en.wikipedia.org/wiki/ISO_8601
- struct tm bdt;
- time_t tt = sec();
- gmtime_r(&tt, &bdt);
- out << std::setw(4) << (bdt.tm_year+1900) // 2007 -> '07'
- << '-' << std::setw(2) << (bdt.tm_mon+1)
- << '-' << std::setw(2) << bdt.tm_mday
- << ' '
- << std::setw(2) << bdt.tm_hour
- << ':' << std::setw(2) << bdt.tm_min
- << ':' << std::setw(2) << bdt.tm_sec;
- out << "." << std::setw(6) << usec();
- out << "Z";
- }
- out.fill(oldfill);
- out.unsetf(std::ios::right);
- return out;
- }
-
- // output
- ostream& gmtime_nsec(ostream& out) const {
- out.setf(std::ios::right);
- char oldfill = out.fill();
- out.fill('0');
- if (sec() < ((time_t)(60*60*24*365*10))) {
- // raw seconds. this looks like a relative time.
- out << (long)sec() << "." << std::setw(6) << usec();
- } else {
- // localtime. this looks like an absolute time.
- // aim for http://en.wikipedia.org/wiki/ISO_8601
- struct tm bdt;
- time_t tt = sec();
- gmtime_r(&tt, &bdt);
- out << std::setw(4) << (bdt.tm_year+1900) // 2007 -> '07'
- << '-' << std::setw(2) << (bdt.tm_mon+1)
- << '-' << std::setw(2) << bdt.tm_mday
- << ' '
- << std::setw(2) << bdt.tm_hour
- << ':' << std::setw(2) << bdt.tm_min
- << ':' << std::setw(2) << bdt.tm_sec;
- out << "." << std::setw(9) << nsec();
- out << "Z";
- }
- out.fill(oldfill);
- out.unsetf(std::ios::right);
- return out;
- }
-
- // output
- ostream& asctime(ostream& out) const {
- out.setf(std::ios::right);
- char oldfill = out.fill();
- out.fill('0');
- if (sec() < ((time_t)(60*60*24*365*10))) {
- // raw seconds. this looks like a relative time.
- out << (long)sec() << "." << std::setw(6) << usec();
- } else {
- // localtime. this looks like an absolute time.
- // aim for http://en.wikipedia.org/wiki/ISO_8601
- struct tm bdt;
- time_t tt = sec();
- gmtime_r(&tt, &bdt);
-
- char buf[128];
- asctime_r(&bdt, buf);
- int len = strlen(buf);
- if (buf[len - 1] == '\n')
- buf[len - 1] = '\0';
- out << buf;
- }
- out.fill(oldfill);
- out.unsetf(std::ios::right);
- return out;
- }
-
- ostream& localtime(ostream& out) const {
- out.setf(std::ios::right);
- char oldfill = out.fill();
- out.fill('0');
- if (sec() < ((time_t)(60*60*24*365*10))) {
- // raw seconds. this looks like a relative time.
- out << (long)sec() << "." << std::setw(6) << usec();
- } else {
- // localtime. this looks like an absolute time.
- // aim for http://en.wikipedia.org/wiki/ISO_8601
- struct tm bdt;
- time_t tt = sec();
- localtime_r(&tt, &bdt);
- out << std::setw(4) << (bdt.tm_year+1900) // 2007 -> '07'
- << '-' << std::setw(2) << (bdt.tm_mon+1)
- << '-' << std::setw(2) << bdt.tm_mday
- << ' '
- << std::setw(2) << bdt.tm_hour
- << ':' << std::setw(2) << bdt.tm_min
- << ':' << std::setw(2) << bdt.tm_sec;
- out << "." << std::setw(6) << usec();
- //out << '_' << bdt.tm_zone;
- }
- out.fill(oldfill);
- out.unsetf(std::ios::right);
- return out;
- }
-
- int sprintf(char *out, int outlen) const {
- struct tm bdt;
- time_t tt = sec();
- localtime_r(&tt, &bdt);
-
- return ::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, usec());
- }
-
- static int snprintf(char *out, int outlen, time_t tt) {
- struct tm bdt;
- localtime_r(&tt, &bdt);
-
- return ::snprintf(out, outlen,
- "%04d-%02d-%02d %02d:%02d:%02d",
- bdt.tm_year + 1900, bdt.tm_mon + 1, bdt.tm_mday,
- bdt.tm_hour, bdt.tm_min, bdt.tm_sec);
- }
-
- static int parse_date(const string& date, uint64_t *epoch, uint64_t *nsec,
- string *out_date=NULL, string *out_time=NULL) {
- struct tm tm;
- memset(&tm, 0, sizeof(tm));
-
- if (nsec)
- *nsec = 0;
-
- const char *p = strptime(date.c_str(), "%Y-%m-%d", &tm);
- if (p) {
- if (*p == ' ') {
- p++;
- p = strptime(p, " %H:%M:%S", &tm);
- if (!p)
- return -EINVAL;
- if (nsec && *p == '.') {
- ++p;
- unsigned i;
- char buf[10]; /* 9 digit + null termination */
- for (i = 0; (i < sizeof(buf) - 1) && isdigit(*p); ++i, ++p) {
- buf[i] = *p;
- }
- for (; i < sizeof(buf) - 1; ++i) {
- buf[i] = '0';
- }
- buf[i] = '\0';
- string err;
- *nsec = (uint64_t)strict_strtol(buf, 10, &err);
- if (!err.empty()) {
- return -EINVAL;
- }
- }
- }
- } else {
- int sec, usec;
- int r = sscanf(date.c_str(), "%d.%d", &sec, &usec);
- if (r != 2) {
- return -EINVAL;
- }
-
- time_t tt = sec;
- gmtime_r(&tt, &tm);
-
- if (nsec) {
- *nsec = (uint64_t)usec * 1000;
- }
- }
- time_t t = internal_timegm(&tm);
- if (epoch)
- *epoch = (uint64_t)t;
-
- if (out_date) {
- char buf[32];
- strftime(buf, sizeof(buf), "%F", &tm);
- *out_date = buf;
- }
- if (out_time) {
- char buf[32];
- strftime(buf, sizeof(buf), "%T", &tm);
- *out_time = buf;
- }
-
- return 0;
- }
-};
-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 );
-}
-inline utime_t& operator+=(utime_t& l, const utime_t& r) {
- l.sec_ref() += r.sec() + (l.nsec()+r.nsec())/1000000000L;
- l.nsec_ref() += r.nsec();
- l.nsec_ref() %= 1000000000L;
- 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;
- l.nsec_ref() += (long)ns;
- l.normalize();
- return l;
-}
-
-inline utime_t operator-(const utime_t& l, const utime_t& r) {
- return utime_t( l.sec() - r.sec() - (l.nsec()<r.nsec() ? 1:0),
- l.nsec() - r.nsec() + (l.nsec()<r.nsec() ? 1000000000:0) );
-}
-inline utime_t& operator-=(utime_t& l, const utime_t& r) {
- l.sec_ref() -= r.sec();
- if (l.nsec() >= r.nsec())
- l.nsec_ref() -= r.nsec();
- else {
- l.nsec_ref() += 1000000000L - r.nsec();
- l.sec_ref()--;
- }
- 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;
- long nsl = (long)ns;
- if (nsl) {
- l.sec_ref()--;
- l.nsec_ref() = 1000000000L + l.nsec_ref() - nsl;
- }
- l.normalize();
- return l;
-}
-
-
-// comparators
-inline bool operator>(const utime_t& a, const utime_t& b)
-{
- return (a.sec() > b.sec()) || (a.sec() == b.sec() && a.nsec() > b.nsec());
-}
-inline bool operator<=(const utime_t& a, const utime_t& b)
-{
- return !(operator>(a, b));
-}
-inline bool operator<(const utime_t& a, const utime_t& b)
-{
- return (a.sec() < b.sec()) || (a.sec() == b.sec() && a.nsec() < b.nsec());
-}
-inline bool operator>=(const utime_t& a, const utime_t& b)
-{
- return !(operator<(a, b));
-}
-
-inline bool operator==(const utime_t& a, const utime_t& b)
-{
- return a.sec() == b.sec() && a.nsec() == b.nsec();
-}
-inline bool operator!=(const utime_t& a, const utime_t& b)
-{
- return a.sec() != b.sec() || a.nsec() != b.nsec();
-}
-
-
-// output
-
-// ostream
-inline std::ostream& operator<<(std::ostream& out, const utime_t& t)
-{
- return t.localtime(out);
-}
-
-#endif