blob: e9afe787a9bd1f2943da02b902e0a786fae83f43 [file] [log] [blame]
// Copyright 2012 Google Inc. All Rights Reserved.
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Author: tkaftal@google.com (Tomasz Kaftal)
//
// The implementation of walltime functionalities.
#ifndef _GNU_SOURCE // gcc3 at least defines it on the command line
#define _GNU_SOURCE // Linux wants that for strptime in time.h
#endif
#include "kudu/gutil/walltime.h"
#if defined(__APPLE__)
#include <mach/clock.h>
#include <mach/mach.h>
#endif // defined(__APPLE__)
#if defined(__APPLE__)
namespace walltime_internal {
GoogleOnceType timebase_info_once = GOOGLE_ONCE_INIT;
mach_timebase_info_data_t timebase_info;
void InitializeTimebaseInfo() {
CHECK_EQ(KERN_SUCCESS, mach_timebase_info(&timebase_info))
<< "unable to initialize mach_timebase_info";
}
} // namespace walltime_internal
#endif
static void StringAppendStrftime(std::string* dst,
const char* format,
const struct tm* tm) {
char space[1024];
int result = strftime(space, sizeof(space), format, tm);
if ((result >= 0) && (result < sizeof(space))) {
// It fit
dst->append(space, result);
return;
}
int length = sizeof(space);
for (int sanity = 0; sanity < 5; ++sanity) {
length *= 2;
auto buf = new char[length];
result = strftime(buf, length, format, tm);
if ((result >= 0) && (result < length)) {
// It fit
dst->append(buf, result);
delete[] buf;
return;
}
delete[] buf;
}
// sanity failure
return;
}
WallTime WallTime_Now() {
#if defined(__APPLE__)
mach_timespec_t ts;
walltime_internal::GetCurrentTime(&ts);
return ts.tv_sec + ts.tv_nsec / static_cast<double>(1e9);
#else
timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
return ts.tv_sec + ts.tv_nsec / static_cast<double>(1e9);
#endif // defined(__APPLE__)
}
void StringAppendStrftime(std::string* dst,
const char* format,
time_t when,
bool local) {
struct tm tm;
bool conversion_error;
if (local) {
conversion_error = (localtime_r(&when, &tm) == nullptr);
} else {
conversion_error = (gmtime_r(&when, &tm) == nullptr);
}
if (conversion_error) {
// If we couldn't convert the time, don't append anything.
return;
}
StringAppendStrftime(dst, format, &tm);
}
std::string TimestampAsString(time_t timestamp_secs) {
std::string ret;
StringAppendStrftime(&ret, "%Y-%m-%d %H:%M:%S %Z", timestamp_secs, true);
return ret;
}
std::string LocalTimeAsString() {
return TimestampAsString(time(nullptr));
}