mirror of
https://github.com/ceph/ceph
synced 2025-01-19 17:41:39 +00:00
Merge PR #27799 into master
* refs/pull/27799/head: common/utime: don't pass %z to utime if there is a 'Z' test: test json encode/decode of utime_t mgr/ssh: parse new datetime mgr/devicehealth: parse new datetime mgr/crash: parse both old and new timestamp formats mgr/telemetry: use cluster-provided timestamp unmolested mon/MonMap: dump timestamps in UTC qa/tasks/ceph: tolerate 'T' or ' ' as date and time separator PendingReleaseNotes: note about change to ISO 8601 throughout test/cli: update regexs for timestamps log/LogClock: render timestamp in ISO 8601 format common/ceph_time: stringify in ISO 8601 format unittest_utime: add tests common/utime: make parse() handle (our) ISO 8601 output include/utime: make default string rendering ISO 8601 conformant include/utime: remove unused s[n]printf methods include/utime: make gmtime() output conformant ISO 8601 Reviewed-by: Kanika Murarka <kmurarka@redhat.com> Reviewed-by: Adam C. Emerson <aemerson@redhat.com>
This commit is contained in:
commit
5686d1ccd5
@ -70,3 +70,19 @@
|
||||
discovery. Update of zabbix_template.xml is needed
|
||||
to receive per-pool (read/write throughput, diskspace usage)
|
||||
and per-osd (latency, status, pgs) statistics
|
||||
|
||||
* The format of all date + time stamps has been modified to fully
|
||||
conform to ISO 8601. The old format (``YYYY-MM-DD
|
||||
HH:MM:SS.ssssss``) excluded the ``T`` separator between the date and
|
||||
time and was rendered using the local time zone without any explicit
|
||||
indication. The new format includes the separator as well as a
|
||||
``+nnnn`` or ``-nnnn`` suffix to indicate the time zone, or a ``Z``
|
||||
suffix if the time is UTC. For example,
|
||||
``2019-04-26T18:40:06.225953+0100``.
|
||||
|
||||
Any code or scripts that was previously parsing date and/or time
|
||||
values from the JSON or XML structure CLI output should be checked
|
||||
to ensure it can handle ISO 8601 conformant values. Any code
|
||||
parsing date or time values from the unstructured human-readable
|
||||
output should be modified to parse the structured output instead, as
|
||||
the human-readable output may change without notice.
|
||||
|
@ -1291,7 +1291,9 @@ def osd_scrub_pgs(ctx, config):
|
||||
loop = False
|
||||
thiscnt = 0
|
||||
for (pgid, tmval) in timez:
|
||||
pgtm = time.strptime(tmval[0:tmval.find('.')], '%Y-%m-%d %H:%M:%S')
|
||||
t = tmval[0:tmval.find('.')]
|
||||
t.replace(' ', 'T')
|
||||
pgtm = time.strptime(t, '%Y-%m-%dT%H:%M:%S')
|
||||
if pgtm > check_time_now:
|
||||
thiscnt += 1
|
||||
else:
|
||||
|
@ -111,19 +111,22 @@ namespace ceph {
|
||||
char oldfill = m.fill();
|
||||
m.fill('0');
|
||||
// localtime. this looks like an absolute time.
|
||||
// aim for http://en.wikipedia.org/wiki/ISO_8601
|
||||
// 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));
|
||||
t.time_since_epoch() % seconds(1)).count()
|
||||
<< tz;
|
||||
m.fill(oldfill);
|
||||
m.unsetf(std::ios::right);
|
||||
return m;
|
||||
|
@ -241,14 +241,14 @@ public:
|
||||
out << (long)sec() << "." << std::setw(6) << usec();
|
||||
} else {
|
||||
// this looks like an absolute time.
|
||||
// aim for http://en.wikipedia.org/wiki/ISO_8601
|
||||
// conform to 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
|
||||
<< ' '
|
||||
<< 'T'
|
||||
<< std::setw(2) << bdt.tm_hour
|
||||
<< ':' << std::setw(2) << bdt.tm_min
|
||||
<< ':' << std::setw(2) << bdt.tm_sec;
|
||||
@ -270,14 +270,14 @@ public:
|
||||
out << (long)sec() << "." << std::setw(6) << usec();
|
||||
} else {
|
||||
// this looks like an absolute time.
|
||||
// aim for http://en.wikipedia.org/wiki/ISO_8601
|
||||
// conform to 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
|
||||
<< ' '
|
||||
<< 'T'
|
||||
<< std::setw(2) << bdt.tm_hour
|
||||
<< ':' << std::setw(2) << bdt.tm_min
|
||||
<< ':' << std::setw(2) << bdt.tm_sec;
|
||||
@ -299,7 +299,6 @@ public:
|
||||
out << (long)sec() << "." << std::setw(6) << usec();
|
||||
} else {
|
||||
// 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);
|
||||
@ -325,50 +324,32 @@ public:
|
||||
out << (long)sec() << "." << std::setw(6) << usec();
|
||||
} else {
|
||||
// this looks like an absolute time.
|
||||
// aim for http://en.wikipedia.org/wiki/ISO_8601
|
||||
// conform to 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
|
||||
<< ' '
|
||||
<< 'T'
|
||||
<< 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;
|
||||
char buf[32] = { 0 };
|
||||
strftime(buf, sizeof(buf), "%z", &bdt);
|
||||
out << buf;
|
||||
}
|
||||
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 invoke_date(const std::string& date_str, utime_t *result) {
|
||||
char buf[256];
|
||||
|
||||
SubProcess bin_date("/bin/date", SubProcess::CLOSE, SubProcess::PIPE, SubProcess::KEEP);
|
||||
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();
|
||||
@ -402,17 +383,45 @@ public:
|
||||
|
||||
const char *p = strptime(date.c_str(), "%Y-%m-%d", &tm);
|
||||
if (p) {
|
||||
if (*p == ' ') {
|
||||
if (*p == ' ' || *p == 'T') {
|
||||
p++;
|
||||
p = strptime(p, " %H:%M:%S", &tm);
|
||||
if (!p)
|
||||
// strptime doesn't understand fractional/decimal seconds, and
|
||||
// it also only takes format chars or literals, so we have to
|
||||
// get creative.
|
||||
char fmt[32] = {0};
|
||||
strncpy(fmt, p, sizeof(fmt) - 1);
|
||||
fmt[0] = '%';
|
||||
fmt[1] = 'H';
|
||||
fmt[2] = ':';
|
||||
fmt[3] = '%';
|
||||
fmt[4] = 'M';
|
||||
fmt[6] = '%';
|
||||
fmt[7] = 'S';
|
||||
const char *subsec = 0;
|
||||
char *q = fmt + 8;
|
||||
if (*q == '.') {
|
||||
++q;
|
||||
subsec = p + 9;
|
||||
q = fmt + 9;
|
||||
while (*q && isdigit(*q)) {
|
||||
++q;
|
||||
}
|
||||
}
|
||||
// look for tz...
|
||||
if (*q == '-' || *q == '+') {
|
||||
*q = '%';
|
||||
*(q+1) = 'z';
|
||||
*(q+2) = 0;
|
||||
}
|
||||
p = strptime(p, fmt, &tm);
|
||||
if (!p) {
|
||||
return -EINVAL;
|
||||
if (nsec && *p == '.') {
|
||||
++p;
|
||||
}
|
||||
if (nsec && subsec) {
|
||||
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 = 0; (i < sizeof(buf) - 1) && isdigit(*subsec); ++i, ++subsec) {
|
||||
buf[i] = *subsec;
|
||||
}
|
||||
for (; i < sizeof(buf) - 1; ++i) {
|
||||
buf[i] = '0';
|
||||
@ -439,10 +448,19 @@ public:
|
||||
*nsec = (uint64_t)usec * 1000;
|
||||
}
|
||||
}
|
||||
|
||||
// apply the tm_gmtoff manually below, since none of mktime,
|
||||
// gmtime, and localtime seem to do it. zero it out here just in
|
||||
// case some other libc *does* apply it. :(
|
||||
auto gmtoff = tm.tm_gmtoff;
|
||||
tm.tm_gmtoff = 0;
|
||||
|
||||
time_t t = internal_timegm(&tm);
|
||||
if (epoch)
|
||||
*epoch = (uint64_t)t;
|
||||
|
||||
*epoch -= gmtoff;
|
||||
|
||||
if (out_date) {
|
||||
char buf[32];
|
||||
strftime(buf, sizeof(buf), "%F", &tm);
|
||||
|
@ -131,18 +131,20 @@ 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);
|
||||
char tz[32] = { 0 };
|
||||
strftime(tz, sizeof(tz), "%z", &bdt);
|
||||
|
||||
int r;
|
||||
if (coarse) {
|
||||
r = std::snprintf(out, outlen, "%04d-%02d-%02d %02d:%02d:%02d.%03ld",
|
||||
r = std::snprintf(out, outlen, "%04d-%02d-%02dT%02d:%02d:%02d.%03ld%s",
|
||||
bdt.tm_year + 1900, bdt.tm_mon + 1, bdt.tm_mday,
|
||||
bdt.tm_hour, bdt.tm_min, bdt.tm_sec,
|
||||
static_cast<long>(tv.tv_usec / 1000));
|
||||
static_cast<long>(tv.tv_usec / 1000), tz);
|
||||
} else {
|
||||
r = std::snprintf(out, outlen, "%04d-%02d-%02d %02d:%02d:%02d.%06ld",
|
||||
r = std::snprintf(out, outlen, "%04d-%02d-%02dT%02d:%02d:%02d.%06ld%s",
|
||||
bdt.tm_year + 1900, bdt.tm_mon + 1, bdt.tm_mday,
|
||||
bdt.tm_hour, bdt.tm_min, bdt.tm_sec,
|
||||
static_cast<long>(tv.tv_usec));
|
||||
static_cast<long>(tv.tv_usec), tz);
|
||||
}
|
||||
// Since our caller just adds the return value to something without
|
||||
// checking it…
|
||||
|
@ -268,7 +268,7 @@ TEST(Log, TimeFormat)
|
||||
ceph::logging::append_time(t, buf, buflen);
|
||||
auto c = std::strrchr(buf, '.');
|
||||
ASSERT_NE(c, nullptr);
|
||||
ASSERT_EQ(3u, strlen(c + 1));
|
||||
ASSERT_EQ(8u, strlen(c + 1));
|
||||
}
|
||||
{
|
||||
clock.refine();
|
||||
@ -276,7 +276,7 @@ TEST(Log, TimeFormat)
|
||||
ceph::logging::append_time(t, buf, buflen);
|
||||
auto c = std::strrchr(buf, '.');
|
||||
ASSERT_NE(c, nullptr);
|
||||
ASSERT_EQ(6u, std::strlen(c + 1));
|
||||
ASSERT_EQ(11u, std::strlen(c + 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -331,8 +331,8 @@ void MonMap::dump(Formatter *f) const
|
||||
{
|
||||
f->dump_unsigned("epoch", epoch);
|
||||
f->dump_stream("fsid") << fsid;
|
||||
f->dump_stream("modified") << last_changed;
|
||||
f->dump_stream("created") << created;
|
||||
last_changed.gmtime(f->dump_stream("modified"));
|
||||
created.gmtime(f->dump_stream("created"));
|
||||
f->dump_unsigned("min_mon_release", ceph::to_integer<unsigned>(min_mon_release));
|
||||
f->dump_string("min_mon_release_name", ceph::to_string(min_mon_release));
|
||||
f->open_object_section("features");
|
||||
|
@ -6,7 +6,8 @@ import six
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
DATEFMT = '%Y-%m-%d %H:%M:%S.%f'
|
||||
DATEFMT = '%Y-%m-%dT%H:%M:%S.%f'
|
||||
OLD_DATEFMT = '%Y-%m-%d %H:%M:%S.%f'
|
||||
|
||||
|
||||
class Module(MgrModule):
|
||||
@ -36,7 +37,10 @@ class Module(MgrModule):
|
||||
def time_from_string(timestr):
|
||||
# drop the 'Z' timezone indication, it's always UTC
|
||||
timestr = timestr.rstrip('Z')
|
||||
return datetime.datetime.strptime(timestr, DATEFMT)
|
||||
try:
|
||||
return datetime.datetime.strptime(timestr, DATEFMT)
|
||||
except ValueError:
|
||||
return datetime.datetime.strptime(timestr, OLD_DATEFMT)
|
||||
|
||||
def timestamp_filter(self, f):
|
||||
"""
|
||||
@ -171,10 +175,14 @@ class Module(MgrModule):
|
||||
|
||||
def self_test(self):
|
||||
# test time conversion
|
||||
timestr = '2018-06-22 20:35:38.058818Z'
|
||||
timestr = '2018-06-22T20:35:38.058818Z'
|
||||
old_timestr = '2018-06-22 20:35:38.058818Z'
|
||||
dt = self.time_from_string(timestr)
|
||||
if dt != datetime.datetime(2018, 6, 22, 20, 35, 38, 58818):
|
||||
raise RuntimeError('time_from_string() failed')
|
||||
dt = self.time_from_string(old_timestr)
|
||||
if dt != datetime.datetime(2018, 6, 22, 20, 35, 38, 58818):
|
||||
raise RuntimeError('time_from_string() (old) failed')
|
||||
|
||||
COMMANDS = [
|
||||
{
|
||||
|
@ -478,11 +478,11 @@ class Module(MgrModule):
|
||||
dev['life_expectancy_max'] == '0.000000':
|
||||
continue
|
||||
# life_expectancy_(min/max) is in the format of:
|
||||
# '%Y-%m-%d %H:%M:%S.%f', e.g.:
|
||||
# '2019-01-20 21:12:12.000000'
|
||||
# '%Y-%m-%dT%H:%M:%S.%f%z', e.g.:
|
||||
# '2019-01-20T21:12:12.000000Z'
|
||||
life_expectancy_max = datetime.strptime(
|
||||
dev['life_expectancy_max'],
|
||||
'%Y-%m-%d %H:%M:%S.%f')
|
||||
'%Y-%m-%dT%H:%M:%S.%f%z')
|
||||
self.log.debug('device %s expectancy max %s', dev,
|
||||
life_expectancy_max)
|
||||
|
||||
|
@ -18,7 +18,7 @@ except ImportError as e:
|
||||
remoto = None
|
||||
remoto_import_error = str(e)
|
||||
|
||||
DATEFMT = '%Y-%m-%d %H:%M:%S.%f'
|
||||
DATEFMT = '%Y-%m-%dT%H:%M:%S.%f%z'
|
||||
|
||||
# high-level TODO:
|
||||
# - bring over some of the protections from ceph-deploy that guard against
|
||||
@ -183,8 +183,6 @@ class SSHOrchestrator(MgrModule, orchestrator.Orchestrator):
|
||||
|
||||
@staticmethod
|
||||
def time_from_string(timestr):
|
||||
# drop the 'Z' timezone indication, it's always UTC
|
||||
timestr = timestr.rstrip('Z')
|
||||
return datetime.datetime.strptime(timestr, DATEFMT)
|
||||
|
||||
def _get_cluster_fsid(self):
|
||||
|
@ -122,10 +122,6 @@ class Module(MgrModule):
|
||||
self.get_module_option(opt['name']))
|
||||
self.log.debug(' %s = %s', opt['name'], getattr(self, opt['name']))
|
||||
|
||||
@staticmethod
|
||||
def parse_timestamp(timestamp):
|
||||
return datetime.strptime(timestamp, '%Y-%m-%d %H:%M:%S.%f')
|
||||
|
||||
def load(self):
|
||||
self.last_upload = self.get_store('last_upload', None)
|
||||
if self.last_upload is not None:
|
||||
@ -205,7 +201,7 @@ class Module(MgrModule):
|
||||
df = self.get('df')
|
||||
|
||||
report['report_id'] = self.report_id
|
||||
report['created'] = self.parse_timestamp(mon_map['created']).isoformat()
|
||||
report['created'] = mon_map['created']
|
||||
|
||||
report['mon'] = {
|
||||
'count': len(mon_map['mons']),
|
||||
|
@ -860,6 +860,12 @@ add_executable(unittest_ipaddr
|
||||
add_ceph_unittest(unittest_ipaddr)
|
||||
target_link_libraries(unittest_ipaddr mon global)
|
||||
|
||||
# unittest_utime
|
||||
add_executable(unittest_utime
|
||||
test_utime.cc)
|
||||
add_ceph_unittest(unittest_utime)
|
||||
target_link_libraries(unittest_utime mon global)
|
||||
|
||||
# unittest_texttable
|
||||
add_executable(unittest_texttable
|
||||
test_texttable.cc
|
||||
|
@ -18,8 +18,8 @@
|
||||
monmaptool: monmap file mymonmap
|
||||
epoch 0
|
||||
fsid [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (re)
|
||||
last_changed \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+ (re)
|
||||
created \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+ (re)
|
||||
last_changed \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+.\d\d\d\d (re)
|
||||
created \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+.\d\d\d\d (re)
|
||||
min_mon_release 0 (unknown)
|
||||
0: v1:2.3.4.5:6789/0 mon.foo
|
||||
|
||||
|
@ -21,8 +21,8 @@
|
||||
monmaptool: monmap file mymonmap
|
||||
epoch 0
|
||||
fsid [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (re)
|
||||
last_changed \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+ (re)
|
||||
created \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+ (re)
|
||||
last_changed \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+.\d\d\d\d (re)
|
||||
created \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+.\d\d\d\d (re)
|
||||
min_mon_release 0 (unknown)
|
||||
0: v1:2.3.4.5:6789/0 mon.foo
|
||||
1: [v2:172.21.15.68:6791/0,v1:172.21.15.68:6792/0] mon.fiz
|
||||
|
@ -15,8 +15,8 @@
|
||||
monmaptool: monmap file mymonmap
|
||||
epoch 0
|
||||
fsid [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (re)
|
||||
last_changed \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+ (re)
|
||||
created \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+ (re)
|
||||
last_changed \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+.\d\d\d\d (re)
|
||||
created \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+.\d\d\d\d (re)
|
||||
min_mon_release 0 (unknown)
|
||||
0: v1:2.3.4.5:6789/0 mon.foo
|
||||
|
||||
@ -35,6 +35,6 @@
|
||||
monmaptool: monmap file mymonmap
|
||||
epoch 0
|
||||
fsid [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (re)
|
||||
last_changed \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+ (re)
|
||||
created \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+ (re)
|
||||
last_changed \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+.\d\d\d\d (re)
|
||||
created \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+.\d\d\d\d (re)
|
||||
min_mon_release 0 (unknown)
|
||||
|
@ -7,14 +7,14 @@
|
||||
monmaptool: monmap file mymonmap
|
||||
epoch 0
|
||||
fsid [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (re)
|
||||
last_changed \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+ (re)
|
||||
created \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+ (re)
|
||||
last_changed \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+.\d\d\d\d (re)
|
||||
created \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+.\d\d\d\d (re)
|
||||
min_mon_release 0 (unknown)
|
||||
|
||||
$ monmaptool --print -- mymonmap
|
||||
monmaptool: monmap file mymonmap
|
||||
epoch 0
|
||||
fsid [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (re)
|
||||
last_changed \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+ (re)
|
||||
created \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+ (re)
|
||||
last_changed \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+.\d\d\d\d (re)
|
||||
created \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+.\d\d\d\d (re)
|
||||
min_mon_release 0 (unknown)
|
||||
|
@ -7,7 +7,7 @@
|
||||
monmaptool: monmap file mymonmap
|
||||
epoch 0
|
||||
fsid [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (re)
|
||||
last_changed \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+ (re)
|
||||
created \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+ (re)
|
||||
last_changed \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+.\d\d\d\d (re)
|
||||
created \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+.\d\d\d\d (re)
|
||||
min_mon_release 0 (unknown)
|
||||
0: v1:2.3.4.5:6789/0 mon.foo
|
||||
|
@ -16,8 +16,8 @@
|
||||
monmaptool: monmap file mymonmap
|
||||
epoch 0
|
||||
fsid [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (re)
|
||||
last_changed \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+ (re)
|
||||
created \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+ (re)
|
||||
last_changed \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+.\d\d\d\d (re)
|
||||
created \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+.\d\d\d\d (re)
|
||||
min_mon_release 0 (unknown)
|
||||
0: v1:2.3.4.5:6789/0 mon.foo
|
||||
|
||||
|
@ -14,8 +14,8 @@
|
||||
monmaptool: monmap file mymonmap
|
||||
epoch 0
|
||||
fsid [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (re)
|
||||
last_changed \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+ (re)
|
||||
created \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+ (re)
|
||||
last_changed \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+.\d\d\d\d (re)
|
||||
created \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+.\d\d\d\d (re)
|
||||
min_mon_release 0 (unknown)
|
||||
|
||||
$ NEW_FSID="$(monmaptool --print mymonmap|grep ^fsid)"
|
||||
|
@ -16,8 +16,8 @@
|
||||
osdmaptool: osdmap file 'myosdmap'
|
||||
epoch 1
|
||||
fsid [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (re)
|
||||
created \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+ (re)
|
||||
modified \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+ (re)
|
||||
created \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+.\d\d\d\d (re)
|
||||
modified \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+.\d\d\d\d (re)
|
||||
flags
|
||||
crush_version 1
|
||||
full_ratio 0
|
||||
@ -42,8 +42,8 @@
|
||||
osdmaptool: osdmap file 'myosdmap'
|
||||
epoch 1
|
||||
fsid [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (re)
|
||||
created \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+ (re)
|
||||
modified \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+ (re)
|
||||
created \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+.\d\d\d\d (re)
|
||||
modified \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+.\d\d\d\d (re)
|
||||
flags
|
||||
crush_version 1
|
||||
full_ratio 0
|
||||
|
@ -76,8 +76,8 @@
|
||||
osdmaptool: osdmap file 'myosdmap'
|
||||
epoch 1
|
||||
fsid [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (re)
|
||||
created \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+ (re)
|
||||
modified \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+ (re)
|
||||
created \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+.\d\d\d\d (re)
|
||||
modified \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+.\d\d\d\d (re)
|
||||
flags
|
||||
crush_version 1
|
||||
full_ratio 0
|
||||
|
@ -788,8 +788,8 @@
|
||||
osdmaptool: osdmap file 'om'
|
||||
epoch 1
|
||||
fsid [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (re)
|
||||
created \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+ (re)
|
||||
modified \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+ (re)
|
||||
created \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+.\d\d\d\d (re)
|
||||
modified \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+.\d\d\d\d (re)
|
||||
flags
|
||||
crush_version 1
|
||||
full_ratio 0
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "common/ceph_json.h"
|
||||
#include "common/Clock.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
@ -56,3 +57,25 @@ TEST(formatter, bug_37706) {
|
||||
ASSERT_EQ(pgs.back(), "1.0");
|
||||
}
|
||||
|
||||
TEST(formatter, utime)
|
||||
{
|
||||
JSONFormatter formatter;
|
||||
|
||||
utime_t input = ceph_clock_now();
|
||||
input.gmtime_nsec(formatter.dump_stream("timestamp"));
|
||||
|
||||
bufferlist bl;
|
||||
formatter.flush(bl);
|
||||
|
||||
JSONParser parser;
|
||||
EXPECT_TRUE(parser.parse(bl.c_str(), bl.length()));
|
||||
|
||||
cout << input << " -> '" << std::string(bl.c_str(), bl.length())
|
||||
<< std::endl;
|
||||
|
||||
utime_t output;
|
||||
decode_json_obj(output, &parser);
|
||||
cout << " -> " << output << std::endl;
|
||||
EXPECT_EQ(input.sec(), output.sec());
|
||||
EXPECT_EQ(input.nsec(), output.nsec());
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "common/ceph_time.h"
|
||||
#include "include/rados.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "include/stringify.h"
|
||||
|
||||
|
||||
using ceph::real_clock;
|
||||
@ -176,3 +177,18 @@ TEST(TimePoints, SignedSubtraciton) {
|
||||
ASSERT_GT(cmtb - cmta, ceph::signedspan::zero());
|
||||
ASSERT_GT((cmtb - cmta).count(), 0);
|
||||
}
|
||||
|
||||
TEST(TimePoints, stringify) {
|
||||
ceph::real_clock::time_point tp(seconds(1556122013) + nanoseconds(39923122));
|
||||
string s = stringify(tp);
|
||||
ASSERT_EQ(s.size(), strlen("2019-04-24T11:06:53.039923-0500"));
|
||||
ASSERT_TRUE(s[26] == '-' || s[26] == '+');
|
||||
ASSERT_EQ(s.substr(0, 9), "2019-04-2");
|
||||
|
||||
ceph::coarse_real_clock::time_point ctp(seconds(1556122013) +
|
||||
nanoseconds(399000000));
|
||||
s = stringify(ctp);
|
||||
ASSERT_EQ(s.size(), strlen("2019-04-24T11:06:53.399000-0500"));
|
||||
ASSERT_TRUE(s[26] == '-' || s[26] == '+');
|
||||
ASSERT_EQ(s.substr(0, 9), "2019-04-2");
|
||||
}
|
||||
|
66
src/test/test_utime.cc
Normal file
66
src/test/test_utime.cc
Normal file
@ -0,0 +1,66 @@
|
||||
#include "include/utime.h"
|
||||
#include "global/global_context.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "include/stringify.h"
|
||||
#include "common/ceph_context.h"
|
||||
|
||||
TEST(utime_t, localtime)
|
||||
{
|
||||
utime_t t(1556122013, 839991182);
|
||||
string s = stringify(t);
|
||||
cout << s << std::endl;
|
||||
// time zone may vary where unit test is run, so be cirsumspect...
|
||||
ASSERT_EQ(s.size(), strlen("2019-04-24T11:06:53.839991-0500"));
|
||||
ASSERT_TRUE(s[26] == '-' || s[26] == '+');
|
||||
ASSERT_EQ(s.substr(0, 9), "2019-04-2");
|
||||
}
|
||||
|
||||
TEST(utime_t, gmtime)
|
||||
{
|
||||
utime_t t(1556122013, 39991182);
|
||||
{
|
||||
ostringstream ss;
|
||||
t.gmtime(ss);
|
||||
ASSERT_EQ(ss.str(), "2019-04-24T16:06:53.039991Z");
|
||||
}
|
||||
{
|
||||
ostringstream ss;
|
||||
t.gmtime_nsec(ss);
|
||||
ASSERT_EQ(ss.str(), "2019-04-24T16:06:53.039991182Z");
|
||||
}
|
||||
}
|
||||
|
||||
TEST(utime_t, asctime)
|
||||
{
|
||||
utime_t t(1556122013, 839991182);
|
||||
ostringstream ss;
|
||||
t.asctime(ss);
|
||||
string s = ss.str();
|
||||
ASSERT_EQ(s, "Wed Apr 24 16:06:53 2019");
|
||||
}
|
||||
|
||||
const char *v[][2] = {
|
||||
{ "2019-04-24T16:06:53.039991Z", "2019-04-24T16:06:53.039991Z" },
|
||||
{ "2019-04-24 16:06:53.039991Z", "2019-04-24T16:06:53.039991Z" },
|
||||
{ "2019-04-24 16:06:53.039991+0000", "2019-04-24T16:06:53.039991Z" },
|
||||
{ "2019-04-24 16:06:53.039991-0100", "2019-04-24T17:06:53.039991Z" },
|
||||
{ "2019-04-24 16:06:53.039991+0430", "2019-04-24T11:36:53.039991Z" },
|
||||
{ "2019-04-24 16:06:53+0000", "2019-04-24T16:06:53.000000Z" },
|
||||
{ "2019-04-24T16:06:53-0100", "2019-04-24T17:06:53.000000Z" },
|
||||
{ "2019-04-24 16:06:53+0430", "2019-04-24T11:36:53.000000Z" },
|
||||
{ "2019-04-24", "2019-04-24T00:00:00.000000Z" },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
TEST(utime_t, parse_date)
|
||||
{
|
||||
for (unsigned i = 0; v[i][0]; ++i) {
|
||||
cout << v[i][0] << " -> " << v[i][1] << std::endl;
|
||||
utime_t t;
|
||||
bool r = t.parse(string(v[i][0]));
|
||||
ASSERT_TRUE(r);
|
||||
ostringstream ss;
|
||||
t.gmtime(ss);
|
||||
ASSERT_EQ(ss.str(), v[i][1]);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user