]>
git.proxmox.com Git - ceph.git/blob - ceph/src/include/utime.h
ba4f17e95826fd9ee6da65616151bbb72987c7e1
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
23 #include "include/types.h"
24 #include "include/timegm.h"
25 #include "common/strtol.h"
26 #include "common/ceph_time.h"
27 #include "include/denc.h"
33 /* WARNING: If add member in utime_t, please make sure the encode/decode funtion
34 * work well. For little-endian machine, we should make sure there is no padding
35 * in 32-bit machine and 64-bit machine.
36 * You should also modify the padding_check function.
41 __u32 tv_sec
, tv_nsec
;
45 bool is_zero() const {
46 return (tv
.tv_sec
== 0) && (tv
.tv_nsec
== 0);
49 if (tv
.tv_nsec
> 1000000000ul) {
50 tv
.tv_sec
+= tv
.tv_nsec
/ (1000000000ul);
51 tv
.tv_nsec
%= 1000000000ul;
56 utime_t() { tv
.tv_sec
= 0; tv
.tv_nsec
= 0; }
57 utime_t(time_t s
, int n
) { tv
.tv_sec
= s
; tv
.tv_nsec
= n
; normalize(); }
58 utime_t(const struct ceph_timespec
&v
) {
61 utime_t(const struct timespec v
)
64 tv
.tv_nsec
= v
.tv_nsec
;
66 explicit utime_t(const ceph::real_time
& rt
) {
67 ceph_timespec ts
= real_clock::to_ceph_timespec(rt
);
70 explicit utime_t(const ceph::coarse_real_time
& crt
) {
71 ceph_timespec ts
= coarse_real_clock::to_ceph_timespec(crt
);
74 utime_t(const struct timeval
&v
) {
77 utime_t(const struct timeval
*v
) {
80 void to_timespec(struct timespec
*ts
) const {
81 ts
->tv_sec
= tv
.tv_sec
;
82 ts
->tv_nsec
= tv
.tv_nsec
;
84 void set_from_double(double d
) {
85 tv
.tv_sec
= (__u32
)trunc(d
);
86 tv
.tv_nsec
= (__u32
)((d
- (double)tv
.tv_sec
) * (double)1000000000.0);
89 real_time
to_real_time() const {
92 return ceph::real_clock::from_ceph_timespec(ts
);
96 time_t sec() const { return tv
.tv_sec
; }
97 long usec() const { return tv
.tv_nsec
/1000; }
98 int nsec() const { return tv
.tv_nsec
; }
100 // ref accessors/modifiers
101 __u32
& sec_ref() { return tv
.tv_sec
; }
102 __u32
& nsec_ref() { return tv
.tv_nsec
; }
104 uint64_t to_nsec() const {
105 return (uint64_t)tv
.tv_nsec
+ (uint64_t)tv
.tv_sec
* 1000000000ull;
107 uint64_t to_msec() const {
108 return (uint64_t)tv
.tv_nsec
/ 1000000ull + (uint64_t)tv
.tv_sec
* 1000ull;
111 void copy_to_timeval(struct timeval
*v
) const {
112 v
->tv_sec
= tv
.tv_sec
;
113 v
->tv_usec
= tv
.tv_nsec
/1000;
115 void set_from_timeval(const struct timeval
*v
) {
116 tv
.tv_sec
= v
->tv_sec
;
117 tv
.tv_nsec
= v
->tv_usec
*1000;
119 void padding_check() {
125 "utime_t have padding");
127 void encode(bufferlist
&bl
) const {
128 #if defined(CEPH_LITTLE_ENDIAN)
129 bl
.append((char *)(this), sizeof(__u32
) + sizeof(__u32
));
131 ::encode(tv
.tv_sec
, bl
);
132 ::encode(tv
.tv_nsec
, bl
);
135 void decode(bufferlist::iterator
&p
) {
136 #if defined(CEPH_LITTLE_ENDIAN)
137 p
.copy(sizeof(__u32
) + sizeof(__u32
), (char *)(this));
139 ::decode(tv
.tv_sec
, p
);
140 ::decode(tv
.tv_nsec
, p
);
144 DENC(utime_t
, v
, p
) {
145 denc(v
.tv
.tv_sec
, p
);
146 denc(v
.tv
.tv_nsec
, p
);
150 void encode_timeval(struct ceph_timespec
*t
) const {
151 t
->tv_sec
= tv
.tv_sec
;
152 t
->tv_nsec
= tv
.tv_nsec
;
154 void decode_timeval(const struct ceph_timespec
*t
) {
155 tv
.tv_sec
= t
->tv_sec
;
156 tv
.tv_nsec
= t
->tv_nsec
;
159 utime_t
round_to_minute() {
162 localtime_r(&tt
, &bdt
);
165 return utime_t(tt
, 0);
168 utime_t
round_to_hour() {
171 localtime_r(&tt
, &bdt
);
175 return utime_t(tt
, 0);
179 operator double() const {
180 return (double)sec() + ((double)nsec() / 1000000000.0L);
182 operator ceph_timespec() const {
192 nanosleep(&ts
, NULL
);
196 ostream
& gmtime(ostream
& out
) const {
197 out
.setf(std::ios::right
);
198 char oldfill
= out
.fill();
200 if (sec() < ((time_t)(60*60*24*365*10))) {
201 // raw seconds. this looks like a relative time.
202 out
<< (long)sec() << "." << std::setw(6) << usec();
204 // localtime. this looks like an absolute time.
205 // aim for http://en.wikipedia.org/wiki/ISO_8601
209 out
<< std::setw(4) << (bdt
.tm_year
+1900) // 2007 -> '07'
210 << '-' << std::setw(2) << (bdt
.tm_mon
+1)
211 << '-' << std::setw(2) << bdt
.tm_mday
213 << std::setw(2) << bdt
.tm_hour
214 << ':' << std::setw(2) << bdt
.tm_min
215 << ':' << std::setw(2) << bdt
.tm_sec
;
216 out
<< "." << std::setw(6) << usec();
220 out
.unsetf(std::ios::right
);
225 ostream
& gmtime_nsec(ostream
& out
) const {
226 out
.setf(std::ios::right
);
227 char oldfill
= out
.fill();
229 if (sec() < ((time_t)(60*60*24*365*10))) {
230 // raw seconds. this looks like a relative time.
231 out
<< (long)sec() << "." << std::setw(6) << usec();
233 // localtime. this looks like an absolute time.
234 // aim for http://en.wikipedia.org/wiki/ISO_8601
238 out
<< std::setw(4) << (bdt
.tm_year
+1900) // 2007 -> '07'
239 << '-' << std::setw(2) << (bdt
.tm_mon
+1)
240 << '-' << std::setw(2) << bdt
.tm_mday
242 << std::setw(2) << bdt
.tm_hour
243 << ':' << std::setw(2) << bdt
.tm_min
244 << ':' << std::setw(2) << bdt
.tm_sec
;
245 out
<< "." << std::setw(9) << nsec();
249 out
.unsetf(std::ios::right
);
254 ostream
& asctime(ostream
& out
) const {
255 out
.setf(std::ios::right
);
256 char oldfill
= out
.fill();
258 if (sec() < ((time_t)(60*60*24*365*10))) {
259 // raw seconds. this looks like a relative time.
260 out
<< (long)sec() << "." << std::setw(6) << usec();
262 // localtime. this looks like an absolute time.
263 // aim for http://en.wikipedia.org/wiki/ISO_8601
269 asctime_r(&bdt
, buf
);
270 int len
= strlen(buf
);
271 if (buf
[len
- 1] == '\n')
276 out
.unsetf(std::ios::right
);
280 ostream
& localtime(ostream
& out
) const {
281 out
.setf(std::ios::right
);
282 char oldfill
= out
.fill();
284 if (sec() < ((time_t)(60*60*24*365*10))) {
285 // raw seconds. this looks like a relative time.
286 out
<< (long)sec() << "." << std::setw(6) << usec();
288 // localtime. this looks like an absolute time.
289 // aim for http://en.wikipedia.org/wiki/ISO_8601
292 localtime_r(&tt
, &bdt
);
293 out
<< std::setw(4) << (bdt
.tm_year
+1900) // 2007 -> '07'
294 << '-' << std::setw(2) << (bdt
.tm_mon
+1)
295 << '-' << std::setw(2) << bdt
.tm_mday
297 << std::setw(2) << bdt
.tm_hour
298 << ':' << std::setw(2) << bdt
.tm_min
299 << ':' << std::setw(2) << bdt
.tm_sec
;
300 out
<< "." << std::setw(6) << usec();
301 //out << '_' << bdt.tm_zone;
304 out
.unsetf(std::ios::right
);
308 int sprintf(char *out
, int outlen
) const {
311 localtime_r(&tt
, &bdt
);
313 return ::snprintf(out
, outlen
,
314 "%04d-%02d-%02d %02d:%02d:%02d.%06ld",
315 bdt
.tm_year
+ 1900, bdt
.tm_mon
+ 1, bdt
.tm_mday
,
316 bdt
.tm_hour
, bdt
.tm_min
, bdt
.tm_sec
, usec());
319 static int snprintf(char *out
, int outlen
, time_t tt
) {
321 localtime_r(&tt
, &bdt
);
323 return ::snprintf(out
, outlen
,
324 "%04d-%02d-%02d %02d:%02d:%02d",
325 bdt
.tm_year
+ 1900, bdt
.tm_mon
+ 1, bdt
.tm_mday
,
326 bdt
.tm_hour
, bdt
.tm_min
, bdt
.tm_sec
);
329 static int parse_date(const string
& date
, uint64_t *epoch
, uint64_t *nsec
,
330 string
*out_date
=NULL
, string
*out_time
=NULL
) {
332 memset(&tm
, 0, sizeof(tm
));
337 const char *p
= strptime(date
.c_str(), "%Y-%m-%d", &tm
);
341 p
= strptime(p
, " %H:%M:%S", &tm
);
344 if (nsec
&& *p
== '.') {
347 char buf
[10]; /* 9 digit + null termination */
348 for (i
= 0; (i
< sizeof(buf
) - 1) && isdigit(*p
); ++i
, ++p
) {
351 for (; i
< sizeof(buf
) - 1; ++i
) {
356 *nsec
= (uint64_t)strict_strtol(buf
, 10, &err
);
364 int r
= sscanf(date
.c_str(), "%d.%d", &sec
, &usec
);
373 *nsec
= (uint64_t)usec
* 1000;
376 time_t t
= internal_timegm(&tm
);
378 *epoch
= (uint64_t)t
;
382 strftime(buf
, sizeof(buf
), "%F", &tm
);
387 strftime(buf
, sizeof(buf
), "%T", &tm
);
394 WRITE_CLASS_ENCODER(utime_t
)
395 WRITE_CLASS_DENC(utime_t
)
398 // arithmetic operators
399 inline utime_t
operator+(const utime_t
& l
, const utime_t
& r
) {
400 return utime_t( l
.sec() + r
.sec() + (l
.nsec()+r
.nsec())/1000000000L,
401 (l
.nsec()+r
.nsec())%1000000000L );
403 inline utime_t
& operator+=(utime_t
& l
, const utime_t
& r
) {
404 l
.sec_ref() += r
.sec() + (l
.nsec()+r
.nsec())/1000000000L;
405 l
.nsec_ref() += r
.nsec();
406 l
.nsec_ref() %= 1000000000L;
409 inline utime_t
& operator+=(utime_t
& l
, double f
) {
410 double fs
= trunc(f
);
411 double ns
= (f
- fs
) * (double)1000000000.0;
412 l
.sec_ref() += (long)fs
;
413 l
.nsec_ref() += (long)ns
;
418 inline utime_t
operator-(const utime_t
& l
, const utime_t
& r
) {
419 return utime_t( l
.sec() - r
.sec() - (l
.nsec()<r
.nsec() ? 1:0),
420 l
.nsec() - r
.nsec() + (l
.nsec()<r
.nsec() ? 1000000000:0) );
422 inline utime_t
& operator-=(utime_t
& l
, const utime_t
& r
) {
423 l
.sec_ref() -= r
.sec();
424 if (l
.nsec() >= r
.nsec())
425 l
.nsec_ref() -= r
.nsec();
427 l
.nsec_ref() += 1000000000L - r
.nsec();
432 inline utime_t
& operator-=(utime_t
& l
, double f
) {
433 double fs
= trunc(f
);
434 double ns
= (f
- fs
) * (double)1000000000.0;
435 l
.sec_ref() -= (long)fs
;
439 l
.nsec_ref() = 1000000000L + l
.nsec_ref() - nsl
;
447 inline bool operator>(const utime_t
& a
, const utime_t
& b
)
449 return (a
.sec() > b
.sec()) || (a
.sec() == b
.sec() && a
.nsec() > b
.nsec());
451 inline bool operator<=(const utime_t
& a
, const utime_t
& b
)
453 return !(operator>(a
, b
));
455 inline bool operator<(const utime_t
& a
, const utime_t
& b
)
457 return (a
.sec() < b
.sec()) || (a
.sec() == b
.sec() && a
.nsec() < b
.nsec());
459 inline bool operator>=(const utime_t
& a
, const utime_t
& b
)
461 return !(operator<(a
, b
));
464 inline bool operator==(const utime_t
& a
, const utime_t
& b
)
466 return a
.sec() == b
.sec() && a
.nsec() == b
.nsec();
468 inline bool operator!=(const utime_t
& a
, const utime_t
& b
)
470 return a
.sec() != b
.sec() || a
.nsec() != b
.nsec();
477 inline std::ostream
& operator<<(std::ostream
& out
, const utime_t
& t
)
479 return t
.localtime(out
);