Makefile.common | 3 +-
configure.ac | 3 +
osaf/libs/core/Makefile.am | 7 +-
osaf/libs/core/cplusplus/Makefile.am | 21 +
osaf/libs/core/cplusplus/base/Makefile.am | 42 ++
osaf/libs/core/cplusplus/base/getenv.cc | 160 ++++++++
osaf/libs/core/cplusplus/base/getenv.h | 40 ++
osaf/libs/core/cplusplus/base/macros.h | 33 +
osaf/libs/core/cplusplus/base/process.cc | 204 ++++++++++
osaf/libs/core/cplusplus/base/process.h | 113 +++++
osaf/libs/core/cplusplus/base/tests/Makefile.am | 49 ++
osaf/libs/core/cplusplus/base/tests/getenv_test.cc | 105 +++++
osaf/libs/core/cplusplus/base/tests/mock_logtrace.cc | 32 +
osaf/libs/core/cplusplus/base/tests/mock_logtrace.h | 23 +
osaf/libs/core/cplusplus/base/tests/mock_osaf_abort.cc | 25 +
osaf/libs/core/cplusplus/base/tests/mock_osaf_abort.h | 23 +
osaf/libs/core/cplusplus/base/tests/mock_osafassert.cc | 27 +
osaf/libs/core/cplusplus/base/tests/mock_osafassert.h | 23 +
osaf/libs/core/cplusplus/base/tests/time_add_test.cc | 54 ++
osaf/libs/core/cplusplus/base/tests/time_compare_test.cc | 195 +++++++++
osaf/libs/core/cplusplus/base/tests/time_convert_test.cc | 89 ++++
osaf/libs/core/cplusplus/base/tests/time_subtract_test.cc | 52 ++
osaf/libs/core/cplusplus/base/time.h | 275 ++++++++++++++
23 files changed, 1594 insertions(+), 4 deletions(-)
Add the following C++ utility functions to the base component:
* getenv.h - parsing of environment variables with default values
* macros.h - selecting behaviour of copy constructors and assignment operators
* process.h - time supervised execution of programs
* time.h - conversion to/from POSIX timespec structures
diff --git a/Makefile.common b/Makefile.common
--- a/Makefile.common
+++ b/Makefile.common
@@ -6,7 +6,8 @@ CORE_INCLUDES = \
-I$(top_srcdir)/osaf/libs/core/include \
-I$(top_srcdir)/osaf/libs/core/leap/include \
-I$(top_srcdir)/osaf/libs/core/mds/include \
- -I$(top_srcdir)/osaf/libs/core/common/include
+ -I$(top_srcdir)/osaf/libs/core/common/include \
+ -I$(top_srcdir)/osaf/libs/core/cplusplus
AM_CPPFLAGS = \
$(CORE_INCLUDES) \
diff --git a/configure.ac b/configure.ac
--- a/configure.ac
+++ b/configure.ac
@@ -774,6 +774,9 @@ AC_CONFIG_FILES([
osaf/libs/saf/libSaSmf/Makefile
osaf/libs/saf/libSaSmf/pkgconfig/Makefile
osaf/libs/saf/libSaSmf/pkgconfig/opensaf-smf.pc
+ osaf/libs/core/cplusplus/Makefile
+ osaf/libs/core/cplusplus/base/Makefile
+ osaf/libs/core/cplusplus/base/tests/Makefile
osaf/services/Makefile
osaf/services/infrastructure/Makefile
osaf/services/infrastructure/dtms/Makefile
diff --git a/osaf/libs/core/Makefile.am b/osaf/libs/core/Makefile.am
--- a/osaf/libs/core/Makefile.am
+++ b/osaf/libs/core/Makefile.am
@@ -18,7 +18,7 @@ include $(top_srcdir)/Makefile.common
MAINTAINERCLEANFILES = Makefile.in
-SUBDIRS = include common leap mbcsv mds
+SUBDIRS = include common leap mbcsv mds cplusplus
LIB_VERSION = 0:2:0
@@ -30,11 +30,12 @@ libopensaf_core_la_CPPFLAGS = \
$(AM_CPPFLAGS)
libopensaf_core_la_LDFLAGS = \
- -lpthread -ldl -lrt \
+ -pthread -ldl -lrt -lstdc++ \
-version-number $(LIB_VERSION)
libopensaf_core_la_LIBADD = \
$(top_builddir)/osaf/libs/core/common/libopensaf_common.la \
$(top_builddir)/osaf/libs/core/leap/libleap.la \
$(top_builddir)/osaf/libs/core/mbcsv/libmbca.la \
- $(top_builddir)/osaf/libs/core/mds/libmds.la
+ $(top_builddir)/osaf/libs/core/mds/libmds.la \
+ $(top_builddir)/osaf/libs/core/cplusplus/base/libbase.la
diff --git a/osaf/libs/core/cplusplus/Makefile.am
b/osaf/libs/core/cplusplus/Makefile.am
new file mode 100644
--- /dev/null
+++ b/osaf/libs/core/cplusplus/Makefile.am
@@ -0,0 +1,21 @@
+# -*- OpenSAF -*-
+#
+# (C) Copyright 2016 The OpenSAF Foundation
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+# under the GNU Lesser General Public License Version 2.1, February 1999.
+# The complete license can be accessed from the following location:
+# http://opensource.org/licenses/lgpl-license.php
+# See the Copying file included with the OpenSAF distribution for full
+# licensing terms.
+#
+# Author(s): Ericsson AB
+#
+
+include $(top_srcdir)/Makefile.common
+
+MAINTAINERCLEANFILES = Makefile.in
+
+SUBDIRS = base
diff --git a/osaf/libs/core/cplusplus/base/Makefile.am
b/osaf/libs/core/cplusplus/base/Makefile.am
new file mode 100644
--- /dev/null
+++ b/osaf/libs/core/cplusplus/base/Makefile.am
@@ -0,0 +1,42 @@
+# -*- OpenSAF -*-
+#
+# (C) Copyright 2016 The OpenSAF Foundation
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+# under the GNU Lesser General Public License Version 2.1, February 1999.
+# The complete license can be accessed from the following location:
+# http://opensource.org/licenses/lgpl-license.php
+# See the Copying file included with the OpenSAF distribution for full
+# licensing terms.
+#
+# Author(s): Ericsson AB
+#
+
+include $(top_srcdir)/Makefile.common
+
+MAINTAINERCLEANFILES = Makefile.in
+
+DEFAULT_INCLUDES =
+
+SUBDIRS = tests
+
+noinst_HEADERS = \
+ getenv.h \
+ macros.h \
+ process.h \
+ time.h
+
+noinst_LTLIBRARIES = libbase.la
+
+libbase_CXXFLAGS =$(AM_CXXFLAGS)
+
+libbase_la_CPPFLAGS = \
+ $(AM_CPPFLAGS)
+
+libbase_la_LDFLAGS = -static
+
+libbase_la_SOURCES = \
+ getenv.cc \
+ process.cc
diff --git a/osaf/libs/core/cplusplus/base/getenv.cc
b/osaf/libs/core/cplusplus/base/getenv.cc
new file mode 100644
--- /dev/null
+++ b/osaf/libs/core/cplusplus/base/getenv.cc
@@ -0,0 +1,160 @@
+/* -*- OpenSAF -*-
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include "base/getenv.h"
+#include <stdint.h>
+#include <cerrno>
+#include <cstdlib>
+#include <cinttypes>
+#include <climits>
+#include <string>
+#include "logtrace.h"
+
+namespace {
+
+uint64_t GetEnvUnsigned(const char* environment_variable,
+ uint64_t default_value, uint64_t max_value);
+int64_t GetEnvSigned(const char* environment_variable,
+ int64_t default_value, int64_t max_value,
+ int64_t min_value);
+char* RemoveLeadingWhitespace(char* str);
+
+} // namespace
+
+namespace base {
+
+template<>
+const char* GetEnv<const char*>(const char* environment_variable,
+ const char* default_value) {
+ const char* str = getenv(environment_variable);
+ if (str == nullptr) {
+ TRACE("%s is not set; using default value '%s'", environment_variable,
+ default_value);
+ str = default_value;
+ } else {
+ TRACE("%s = '%s'", environment_variable, str);
+ }
+ return str;
+}
+
+template<>
+std::string GetEnv<std::string>(const char* environment_variable,
+ std::string default_value) {
+ return GetEnv(environment_variable, default_value.c_str());
+}
+
+template<>
+uint64_t GetEnv<uint64_t>(const char* environment_variable,
+ uint64_t default_value) {
+ return GetEnvUnsigned(environment_variable, default_value, UINT64_MAX);
+}
+
+template<>
+uint32_t GetEnv<uint32_t>(const char* environment_variable,
+ uint32_t default_value) {
+ return GetEnvUnsigned(environment_variable, default_value, UINT32_MAX);
+}
+
+template<>
+uint16_t GetEnv<uint16_t>(const char* environment_variable,
+ uint16_t default_value) {
+ return GetEnvUnsigned(environment_variable, default_value, UINT16_MAX);
+}
+
+template<>
+int64_t GetEnv<int64_t>(const char* environment_variable,
+ int64_t default_value) {
+ return GetEnvSigned(environment_variable, default_value, INT64_MAX,
+ INT64_MIN);
+}
+
+template<>
+int32_t GetEnv<int32_t>(const char* environment_variable,
+ int32_t default_value) {
+ return GetEnvSigned(environment_variable, default_value, INT32_MAX,
+ INT32_MIN);
+}
+
+template<>
+int16_t GetEnv<int16_t>(const char* environment_variable,
+ int16_t default_value) {
+ return GetEnvSigned(environment_variable, default_value, INT16_MAX,
+ INT16_MIN);
+}
+
+} // namespace base
+
+namespace {
+
+uint64_t GetEnvUnsigned(const char* environment_variable,
+ uint64_t default_value, uint64_t max_value) {
+ char* str = RemoveLeadingWhitespace(getenv(environment_variable));
+ uint64_t retval = default_value;
+ if (str != nullptr && *str != '\0') {
+ errno = 0;
+ char* endptr;
+ unsigned long long val = strtoull(str, &endptr, 0);
+ endptr = RemoveLeadingWhitespace(endptr);
+ if (errno == 0 && val <= max_value && *endptr == '\0') {
+ retval = val;
+ TRACE("%s = %" PRIu64, environment_variable, retval);
+ } else {
+ LOG_ER("%s has invalid value '%s'; using default value %" PRIu64,
+ environment_variable, str, default_value);
+ }
+ } else {
+ TRACE("%s is %s; using default value %" PRIu64, environment_variable,
+ str == nullptr ? "not set" : "empty", default_value);
+
+ }
+ return retval;
+}
+
+int64_t GetEnvSigned(const char* environment_variable, int64_t default_value,
+ int64_t max_value, int64_t min_value) {
+ char* str = RemoveLeadingWhitespace(getenv(environment_variable));
+ int64_t retval = default_value;
+ if (str != nullptr && *str != '\0') {
+ errno = 0;
+ char* endptr;
+ long long val = strtoll(str, &endptr, 0);
+ endptr = RemoveLeadingWhitespace(endptr);
+ if (errno == 0 && val >= min_value && val <= max_value && *endptr == '\0')
{
+ retval = val;
+ TRACE("%s = %" PRId64, environment_variable, retval);
+ } else {
+ LOG_ER("%s has invalid value '%s'; using default value %" PRId64,
+ environment_variable, str, default_value);
+ }
+ } else {
+ TRACE("%s is %s; using default value %" PRId64, environment_variable,
+ str == nullptr ? "not set" : "empty", default_value);
+ }
+ return retval;
+}
+
+char* RemoveLeadingWhitespace(char* str) {
+ if (str != nullptr) {
+ while (*str == ' ' || *str == '\t' || *str == '\r' || *str == '\n') ++str;
+ }
+ return str;
+}
+
+} // namespace
diff --git a/osaf/libs/core/cplusplus/base/getenv.h
b/osaf/libs/core/cplusplus/base/getenv.h
new file mode 100644
--- /dev/null
+++ b/osaf/libs/core/cplusplus/base/getenv.h
@@ -0,0 +1,40 @@
+/* -*- OpenSAF -*-
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+
+#ifndef OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_GETENV_H_
+#define OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_GETENV_H_
+
+namespace base {
+
+/**
+ * @brief Parse an environment variable with a default value.
+ *
+ * Returns the contents of an environment variable. If the variable is not set
+ * or not possible to parse, the @a default_value will be returned. This is a
+ * template functions, and the return type will be the same as the type of the
+ * @a default_value. Supported types are strings (const char*, std::string), as
+ * well as signed and unsigned integer types. When parsing integers, the
+ * prefixes 0x and 0 are supported for indicating that the number is
hexadecimal
+ * or octal, respectively. The parsed value is always logged using the OpenSAF
+ * logtrace functionality, and parse errors are logged to syslog.
+ */
+template<typename T>
+T GetEnv(const char* environment_variable, T default_value);
+
+} // namespace base
+
+#endif /* OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_GETENV_H_ */
diff --git a/osaf/libs/core/cplusplus/base/macros.h
b/osaf/libs/core/cplusplus/base/macros.h
new file mode 100644
--- /dev/null
+++ b/osaf/libs/core/cplusplus/base/macros.h
@@ -0,0 +1,33 @@
+/*
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+
+#ifndef OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_MACROS_H_
+#define OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_MACROS_H_
+
+#define USE_DEFAULT_COPY_AND_MOVE_OPERATORS(className) \
+ className(className&&) = default; \
+ className(const className&) = default; \
+ className& operator=(className&&) = default; \
+ className& operator=(const className&) = default
+
+#define DELETE_COPY_AND_MOVE_OPERATORS(className) \
+ className(className&&) = delete; \
+ className(const className&) = delete; \
+ className& operator=(className&&) = delete; \
+ className& operator=(const className&) = delete
+
+#endif /* OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_MACROS_H_ */
diff --git a/osaf/libs/core/cplusplus/base/process.cc
b/osaf/libs/core/cplusplus/base/process.cc
new file mode 100644
--- /dev/null
+++ b/osaf/libs/core/cplusplus/base/process.cc
@@ -0,0 +1,204 @@
+/* -*- OpenSAF -*-
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include "base/process.h"
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <cerrno>
+#include <cinttypes>
+#include <climits>
+#include <cstdlib>
+#include <cstring>
+#include <thread>
+#include "logtrace.h"
+#include "base/time.h"
+
+namespace {
+static char path_environment_variable[] = "PATH=/usr/local/sbin:" \
+ "/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
+}
+
+namespace base {
+
+Process::Process() :
+ mutex_{},
+ timer_id_{},
+ is_timer_created_{false},
+ process_group_id_{0} {
+}
+
+Process::~Process() {
+ StopTimer();
+}
+
+void Process::Kill(int sig_no, const Duration& wait_time) {
+ std::unique_lock<std::mutex> lock(mutex_);
+ pid_t pgid = process_group_id_;
+ process_group_id_ = 0;
+ lock.unlock();
+ if (pgid > 1) KillProc(-pgid, sig_no, wait_time);
+}
+
+void Process::KillProc(pid_t pid, int sig_no, const Duration& wait_time) {
+ LOG_NO("Sending signal %d to PID %d", sig_no, (int) pid);
+ if (kill(pid, sig_no) == 0) {
+ TimePoint timeout = Clock::now() + wait_time;
+ for (;;) {
+ int status;
+ pid_t wait_pid = waitpid(pid, &status, WNOHANG);
+ if (wait_pid == (pid_t) -1) {
+ if (errno == ECHILD) break;
+ if (errno != EINTR) osaf_abort(pid);
+ }
+ if (Clock::now() >= timeout) {
+ if (sig_no == SIGTERM) {
+ KillProc(pid, SIGKILL, wait_time);
+ } else {
+ LOG_WA("Failed to kill %d", (int) pid);
+ }
+ break;
+ }
+ if (wait_pid == 0) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
+ }
+ }
+ } else if (errno == EPERM) {
+ LOG_WA("kill(%d, %d) failed due to EPERM", (int) pid, sig_no);
+ } else if (errno != ESRCH) {
+ osaf_abort(pid);
+ }
+}
+
+void Process::Execute(int argc, char *argv[], const Duration& timeout) {
+ struct rlimit rlim;
+ int nofile = 1024;
+ char *const env[] = { path_environment_variable, nullptr };
+
+ TRACE_ENTER();
+ osafassert(argc >= 1 && argv[argc] == nullptr);
+ LOG_NO("Running '%s' with %d argument(s)", argv[0], argc - 1);
+
+ if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) {
+ if (rlim.rlim_cur != RLIM_INFINITY &&
+ rlim.rlim_cur <= INT_MAX && (int) rlim.rlim_cur >= 0) {
+ nofile = rlim.rlim_cur;
+ } else {
+ LOG_ER("RLIMIT_NOFILE is out of bounds: %llu",
+ (unsigned long long) rlim.rlim_cur);
+ }
+ } else {
+ LOG_ER("getrlimit(RLIMIT_NOFILE) failed: %s", strerror(errno));
+ }
+
+ pid_t child_pid = fork();
+ if (child_pid == 0) {
+ setpgid(0, 0);
+ for (int fd = 3; fd < nofile; ++fd) close(fd);
+ execve(argv[0], argv, env);
+ _Exit(123);
+ } else if (child_pid != (pid_t) -1 && child_pid != 1) {
+ if (setpgid(child_pid, 0) != 0) {
+ LOG_WA("setpgid(%u, 0) failed: %s",
+ (unsigned) child_pid, strerror(errno));
+ }
+ std::unique_lock<std::mutex> lock(mutex_);
+ process_group_id_ = child_pid;
+ StartTimer(timeout);
+ lock.unlock();
+ int status;
+ pid_t wait_pid;
+ do {
+ wait_pid = waitpid(child_pid, &status, 0);
+ } while (wait_pid == (pid_t) -1 && errno == EINTR);
+ lock.lock();
+ StopTimer();
+ bool killed = process_group_id_ == 0;
+ process_group_id_ = 0;
+ lock.unlock();
+ bool successful = false;
+ if (!killed && wait_pid != (pid_t) -1) {
+ if (!WIFEXITED(status)) {
+ LOG_ER("'%s' terminated abnormally", argv[0]);
+ } else if (WEXITSTATUS(status) != 0) {
+ if (WEXITSTATUS(status) == 123) {
+ LOG_ER("'%s' could not be executed", argv[0]);
+ } else {
+ LOG_ER("'%s' failed with exit code %d", argv[0],
+ WEXITSTATUS(status));
+ }
+ } else {
+ LOG_IN("'%s' exited successfully", argv[0]);
+ successful = true;
+ }
+ } else if (!killed) {
+ LOG_ER("'%s' failed in waitpid(%u): %s",
+ argv[0], (unsigned) child_pid, strerror(errno));
+ }
+ if (!successful) KillProc(-child_pid, SIGTERM, std::chrono::seconds(2));
+ } else {
+ LOG_ER("'%s' failed in fork(): %s", argv[0],
+ strerror(errno));
+ }
+ TRACE_LEAVE();
+}
+
+void Process::StartTimer(const Duration& timeout) {
+ if (timeout != std::chrono::seconds(0)) {
+ if (!is_timer_created_) {
+ sigevent event;
+ event.sigev_notify = SIGEV_THREAD;
+ event.sigev_value.sival_ptr = this;
+ event.sigev_notify_function = TimerExpirationEvent;
+ event.sigev_notify_attributes = nullptr;
+ int result;
+ do {
+ result = timer_create(CLOCK_MONOTONIC, &event, &timer_id_);
+ if (result == -1 && errno == EAGAIN) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
+ }
+ } while (result == -1 && errno == EAGAIN);
+ if (result != 0) osaf_abort(result);
+ is_timer_created_ = true;
+ }
+ itimerspec tmrspec;
+ tmrspec.it_interval = kZeroSeconds;
+ tmrspec.it_value = DurationToTimespec(timeout);
+ if (timer_settime(timer_id_, 0, &tmrspec, nullptr) != 0) osaf_abort(0);
+ } else {
+ StopTimer();
+ }
+}
+
+void Process::StopTimer() {
+ if (is_timer_created_) {
+ if (timer_delete(timer_id_) != 0) osaf_abort(0);
+ is_timer_created_ = false;
+ }
+}
+
+void Process::TimerExpirationEvent(sigval notification_data) {
+ LOG_ER("Process execution timed out; sending SIGTERM to the process group");
+ Process* instance = static_cast<Process*>(notification_data.sival_ptr);
+ instance->Kill(SIGTERM, std::chrono::seconds(2));
+}
+
+} // namespace base
+
diff --git a/osaf/libs/core/cplusplus/base/process.h
b/osaf/libs/core/cplusplus/base/process.h
new file mode 100644
--- /dev/null
+++ b/osaf/libs/core/cplusplus/base/process.h
@@ -0,0 +1,113 @@
+/* -*- OpenSAF -*-
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+
+#ifndef OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_PROCESS_H_
+#define OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_PROCESS_H_
+
+#include <csignal>
+#include <stdint.h>
+#include <ctime>
+#include <chrono>
+#include <mutex>
+#include "base/macros.h"
+
+namespace base {
+
+class Process {
+ DELETE_COPY_AND_MOVE_OPERATORS(Process);
+ public:
+ using Duration = std::chrono::steady_clock::duration;
+ Process();
+ virtual ~Process();
+ /**
+ * @brief Execute a program with a timeout.
+ *
+ * Execute a program in a new process group, with the parameters specified in
+ * @a argc and @a argv (analogous to the parameters taken by the main()
+ * function). The first index in argv must be the full path to the executable
+ * file. The rest of the parameters shall specify the arguments to the
+ * program. In addition, argv[argc] must be a NULL pointer. This function
+ * blocks until the called program has exited or until the @a timeout
expires,
+ * whichever happens first. If the @a timeout expires, all the processes in
+ * the new process group of the started program will be killed by calling the
+ * Kill() method of this class with the SIGTERM signal. A @a timeout of zero
+ * will give an infinite timeout.
+ *
+ * The program will be executed with an empty environment containing just a
+ * PATH variable with the fixed value set to the following string:
+ * /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
+ *
+ * You should not try to execute several programs concurrently using the same
+ * instance of this class, since the timeout handling only supports waiting
+ * for one program at a time.
+ */
+ void Execute(int argc, char *argv[], const Duration& timeout);
+ /**
+ * @brief Check if there is currently an executing process.
+ *
+ * Returns true if there is currently an executing process that was started
+ * using this instance of the Process class. Note that if the process(es) are
+ * currently being killed (i.e. because of a call to the Kill() method or
+ * because the timeout has expired), this method may return false even though
+ * not all processes have yet been killed.
+ */
+ bool is_executing() const {
+ return process_group_id_ > 1;
+ }
+ /**
+ * @brief Kill the currently executing program.
+ *
+ * This function kills the currently executing program by calling the
+ * KillProc() method on the new process group that was created when starting
+ * the program.
+ */
+ void Kill(int sig_no, const Duration& wait_time);
+ /**
+ * @brief Send a signal to a process (group) and wait for it to terminate.
+ *
+ * This is a utility function that works in a similar way as the killproc(8)
+ * command. It sends the signal @a sig_no to the process @a pid, and waits
for
+ * @a wait_time or until the process has terminated, whichever happens
+ * first. If @a sig_no is SIGTERM and the process does not terminate before
+ * the @a wait_time have passed, this function will retry by sending SIGKILL
+ * to @a pid and again waiting @a wait_time for it to terminate. In the
worst
+ * case, the total wait time can thus be two times @a wait_time when @a
sig_no
+ * is SIGTERM; however, in practice the process will terminate very quickly
+ * after receiving SIGKILL since this signal cannot be caught, and the the
+ * total wait time should thus not be much longer than @a wait_time.
+ *
+ * It is also possible to use this function to send a signal to a process
+ * group, by passing a negative value as @a pid (in a similar way as with the
+ * kill(2) function). In that case, this function will wait until all
+ * processes in the process group have terminated.
+ */
+ static void KillProc(pid_t pid, int sig_no, const Duration& wait_time);
+ private:
+ using Clock = std::chrono::steady_clock;
+ using TimePoint = std::chrono::steady_clock::time_point;
+ void StartTimer(const Duration& timeout);
+ void StopTimer();
+ static void TimerExpirationEvent(sigval notification_data);
+ std::mutex mutex_;
+ timer_t timer_id_;
+ bool is_timer_created_;
+ pid_t process_group_id_;
+};
+
+} // namespace base
+
+#endif /* OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_PROCESS_H_ */
diff --git a/osaf/libs/core/cplusplus/base/tests/Makefile.am
b/osaf/libs/core/cplusplus/base/tests/Makefile.am
new file mode 100644
--- /dev/null
+++ b/osaf/libs/core/cplusplus/base/tests/Makefile.am
@@ -0,0 +1,49 @@
+# -*- OpenSAF -*-
+#
+# (C) Copyright 2016 The OpenSAF Foundation
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+# under the GNU Lesser General Public License Version 2.1, February 1999.
+# The complete license can be accessed from the following location:
+# http://opensource.org/licenses/lgpl-license.php
+# See the Copying file included with the OpenSAF distribution for full
+# licensing terms.
+#
+# Author(s): Ericsson AB
+#
+
+include $(top_srcdir)/Makefile.common
+
+MAINTAINERCLEANFILES = Makefile.in
+
+TESTS = libbase_test
+
+check_PROGRAMS = $(TESTS)
+
+libbase_test_CXXFLAGS =$(AM_CXXFLAGS)
+
+libbase_test_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ -I$(top_srcdir)/osaf/libs/core/cplusplus \
+ -I$(GTEST_DIR)/include
+
+libbase_test_LDFLAGS = \
+ -pthread -lrt \
+ $(top_builddir)/osaf/libs/core/cplusplus/base/libbase_la-getenv.o \
+ $(top_builddir)/osaf/libs/core/cplusplus/base/libbase_la-process.o
+
+libbase_test_SOURCES = \
+ time_add_test.cc \
+ time_subtract_test.cc \
+ time_compare_test.cc \
+ time_convert_test.cc \
+ getenv_test.cc \
+ mock_logtrace.cc \
+ mock_osafassert.cc \
+ mock_osaf_abort.cc
+
+libbase_test_LDADD = \
+ $(GTEST_DIR)/lib/libgtest.la \
+ $(GTEST_DIR)/lib/libgtest_main.la
diff --git a/osaf/libs/core/cplusplus/base/tests/getenv_test.cc
b/osaf/libs/core/cplusplus/base/tests/getenv_test.cc
new file mode 100644
--- /dev/null
+++ b/osaf/libs/core/cplusplus/base/tests/getenv_test.cc
@@ -0,0 +1,105 @@
+/* -*- OpenSAF -*-
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+
+#include <cstdlib>
+#include <cstring>
+#include "base/getenv.h"
+#include "gtest/gtest.h"
+
+TEST(BaseGetEnv, StringDefault) {
+ unsetenv("HELLO");
+ std::string default_value{"DEFAULT_VALUE"};
+ std::string value = base::GetEnv("HELLO", default_value);
+ EXPECT_EQ(value, default_value);
+}
+
+TEST(BaseGetEnv, StringValue) {
+ setenv("HELLO", "THERE", 1);
+ std::string default_value{"DEFAULT_VALUE"};
+ std::string value = base::GetEnv("HELLO", default_value);
+ EXPECT_EQ(value, std::string{"THERE"});
+}
+
+TEST(BaseGetEnv, CharDefault) {
+ unsetenv("HELLO");
+ const char* default_value{"DEFAULT_VALUE"};
+ const char* value = base::GetEnv("HELLO", default_value);
+ EXPECT_EQ(strcmp(value, default_value), 0);
+}
+
+TEST(BaseGetEnv, CharValue) {
+ setenv("HELLO", "THERE", 1);
+ const char* default_value{"DEFAULT_VALUE"};
+ const char* value = base::GetEnv("HELLO", default_value);
+ EXPECT_EQ(strcmp(value, "THERE"), 0);
+}
+
+TEST(BaseGetEnv, NegativeSignedIntegerDefault) {
+ unsetenv("HELLO");
+ int64_t default_value{-1234567890123456789ll};
+ int64_t value = base::GetEnv("HELLO", default_value);
+ EXPECT_EQ(value, default_value);
+}
+
+TEST(BaseGetEnv, NegativeSignedIntegerValue) {
+ setenv("HELLO", "-2345678901234567890", 1);
+ int64_t default_value{-1234567890123456789ll};
+ int64_t value = base::GetEnv("HELLO", default_value);
+ EXPECT_EQ(value, -2345678901234567890ll);
+}
+
+TEST(BaseGetEnv, PositiveSignedIntegerDefault) {
+ unsetenv("HELLO");
+ int64_t default_value{1234567890123456789ll};
+ int64_t value = base::GetEnv("HELLO", default_value);
+ EXPECT_EQ(value, default_value);
+}
+
+TEST(BaseGetEnv, PositiveSignedIntegerValue) {
+ setenv("HELLO", "2345678901234567890", 1);
+ int64_t default_value{1234567890123456789ll};
+ int64_t value = base::GetEnv("HELLO", default_value);
+ EXPECT_EQ(value, 2345678901234567890ll);
+}
+
+TEST(BaseGetEnv, HexadecimalUnsignedIntegerDefault) {
+ unsetenv("HELLO");
+ uint64_t default_value{0xfefefefefefefefeull};
+ uint64_t value = base::GetEnv("HELLO", default_value);
+ EXPECT_EQ(value, default_value);
+}
+
+TEST(BaseGetEnv, HexadecimalUnsignedIntegerValue) {
+ setenv("HELLO", "0xabababababababab", 1);
+ uint64_t default_value{0xfefefefefefefefeull};
+ uint64_t value = base::GetEnv("HELLO", default_value);
+ EXPECT_EQ(value, 0xababababababababull);
+}
+
+TEST(BaseGetEnv, UnparsableInteger) {
+ setenv("HELLO", "THERE", 1);
+ uint32_t default_value{0xfefefefeul};
+ uint32_t value = base::GetEnv("HELLO", default_value);
+ EXPECT_EQ(value, default_value);
+}
+
+TEST(BaseGetEnv, IntegerWithTrailingGarbage) {
+ setenv("HELLO", "12ab", 1);
+ uint32_t default_value{0xcdcdcdcdul};
+ uint32_t value = base::GetEnv("HELLO", default_value);
+ EXPECT_EQ(value, default_value);
+}
diff --git a/osaf/libs/core/cplusplus/base/tests/mock_logtrace.cc
b/osaf/libs/core/cplusplus/base/tests/mock_logtrace.cc
new file mode 100644
--- /dev/null
+++ b/osaf/libs/core/cplusplus/base/tests/mock_logtrace.cc
@@ -0,0 +1,32 @@
+/* -*- OpenSAF -*-
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+
+#include "mock_logtrace.h"
+
+void _logtrace_log(const char *file, unsigned int line, int priority, const
char *format, ...) {
+ (void) file;
+ (void) line;
+ (void) priority;
+ (void) format;
+}
+
+void _logtrace_trace(const char *file, unsigned int line, unsigned int
category, const char *format, ...) {
+ (void) file;
+ (void) line;
+ (void) category;
+ (void) format;
+}
diff --git a/osaf/libs/core/cplusplus/base/tests/mock_logtrace.h
b/osaf/libs/core/cplusplus/base/tests/mock_logtrace.h
new file mode 100644
--- /dev/null
+++ b/osaf/libs/core/cplusplus/base/tests/mock_logtrace.h
@@ -0,0 +1,23 @@
+/* -*- OpenSAF -*-
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+
+#ifndef OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_TESTS_MOCK_LOGTRACE_H_
+#define OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_TESTS_MOCK_LOGTRACE_H_
+
+#include "logtrace.h"
+
+#endif
diff --git a/osaf/libs/core/cplusplus/base/tests/mock_osaf_abort.cc
b/osaf/libs/core/cplusplus/base/tests/mock_osaf_abort.cc
new file mode 100644
--- /dev/null
+++ b/osaf/libs/core/cplusplus/base/tests/mock_osaf_abort.cc
@@ -0,0 +1,25 @@
+/* -*- OpenSAF -*-
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+
+#include "mock_osaf_abort.h"
+#include <cstdlib>
+
+void osaf_abort(long i_cause)
+{
+ (void) i_cause;
+ abort();
+}
diff --git a/osaf/libs/core/cplusplus/base/tests/mock_osaf_abort.h
b/osaf/libs/core/cplusplus/base/tests/mock_osaf_abort.h
new file mode 100644
--- /dev/null
+++ b/osaf/libs/core/cplusplus/base/tests/mock_osaf_abort.h
@@ -0,0 +1,23 @@
+/* -*- OpenSAF -*-
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+
+#ifndef OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_TESTS_MOCK_OSAF_ABORT_H_
+#define OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_TESTS_MOCK_OSAF_ABORT_H_
+
+#include "osaf_utility.h"
+
+#endif
diff --git a/osaf/libs/core/cplusplus/base/tests/mock_osafassert.cc
b/osaf/libs/core/cplusplus/base/tests/mock_osafassert.cc
new file mode 100644
--- /dev/null
+++ b/osaf/libs/core/cplusplus/base/tests/mock_osafassert.cc
@@ -0,0 +1,27 @@
+/* -*- OpenSAF -*-
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+
+#include "mock_osafassert.h"
+#include <cstdlib>
+
+void __osafassert_fail(const char *file, int line, const char* func, const
char *assertion) {
+ (void) file;
+ (void) line;
+ (void) func;
+ (void) assertion;
+ abort();
+}
diff --git a/osaf/libs/core/cplusplus/base/tests/mock_osafassert.h
b/osaf/libs/core/cplusplus/base/tests/mock_osafassert.h
new file mode 100644
--- /dev/null
+++ b/osaf/libs/core/cplusplus/base/tests/mock_osafassert.h
@@ -0,0 +1,23 @@
+/* -*- OpenSAF -*-
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+
+#ifndef OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_TESTS_MOCK_OSAFASSERT_H_
+#define OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_TESTS_MOCK_OSAFASSERT_H_
+
+#include "ncsgl_defs.h"
+
+#endif
diff --git a/osaf/libs/core/cplusplus/base/tests/time_add_test.cc
b/osaf/libs/core/cplusplus/base/tests/time_add_test.cc
new file mode 100644
--- /dev/null
+++ b/osaf/libs/core/cplusplus/base/tests/time_add_test.cc
@@ -0,0 +1,54 @@
+/* -*- OpenSAF -*-
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+
+#include "base/time.h"
+#include "gtest/gtest.h"
+
+static const timespec kTwoDotFourSeconds = { 2, 400000000 };
+static const timespec kFourDotEightSeconds = { 4, 800000000 };
+static const timespec kNineDotSixSeconds = { 9, 600000000 };
+static const timespec number1 = { 576315623, 358743382 };
+static const timespec number2 = { 1279394477, 719128783 };
+static const timespec sum = { 1855710101, 77872165 };
+
+TEST(BaseTimeAdd, ZeroPlusZero) {
+ timespec result = base::kZeroSeconds + base::kZeroSeconds;
+ EXPECT_TRUE(result == base::kZeroSeconds);
+}
+
+TEST(BaseTimeAdd, TwoDotFourAddedWithItself) {
+ timespec result = kTwoDotFourSeconds;
+ result += result;
+ EXPECT_TRUE(result == kFourDotEightSeconds);
+}
+
+TEST(BaseTimeAdd, FourDotEightAddedWithItself) {
+ timespec result = kFourDotEightSeconds;
+ result += result;
+ EXPECT_TRUE(result == kNineDotSixSeconds);
+}
+
+TEST(BaseTimeAdd, AddRandomNumbers) {
+ timespec result = number1 + number2;
+ EXPECT_TRUE(result == sum);
+}
+
+TEST(BaseTimeAdd, FirstParameterAndResultAtSameAddress) {
+ timespec result = number1;
+ result += number2;
+ EXPECT_TRUE(result == sum);
+}
diff --git a/osaf/libs/core/cplusplus/base/tests/time_compare_test.cc
b/osaf/libs/core/cplusplus/base/tests/time_compare_test.cc
new file mode 100644
--- /dev/null
+++ b/osaf/libs/core/cplusplus/base/tests/time_compare_test.cc
@@ -0,0 +1,195 @@
+/* -*- OpenSAF -*-
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+
+#include "base/time.h"
+#include "gtest/gtest.h"
+
+static const timespec kZeroDotNineSeconds = { 0, 900000000 };
+static const timespec kOneDotOneSeconds = { 1, 100000000 };
+
+TEST(BaseTimeCompare, ZeroWithZero) {
+ EXPECT_FALSE(base::kZeroSeconds < base::kZeroSeconds);
+ EXPECT_TRUE(base::kZeroSeconds <= base::kZeroSeconds);
+ EXPECT_TRUE(base::kZeroSeconds == base::kZeroSeconds);
+ EXPECT_FALSE(base::kZeroSeconds != base::kZeroSeconds);
+ EXPECT_TRUE(base::kZeroSeconds >= base::kZeroSeconds);
+ EXPECT_FALSE(base::kZeroSeconds > base::kZeroSeconds);
+}
+
+TEST(BaseTimeCompare, ZeroWithZeroDotOne) {
+ EXPECT_TRUE(base::kZeroSeconds < base::kOneHundredMilliseconds);
+ EXPECT_TRUE(base::kZeroSeconds <= base::kOneHundredMilliseconds);
+ EXPECT_FALSE(base::kZeroSeconds == base::kOneHundredMilliseconds);
+ EXPECT_TRUE(base::kZeroSeconds != base::kOneHundredMilliseconds);
+ EXPECT_FALSE(base::kZeroSeconds >= base::kOneHundredMilliseconds);
+ EXPECT_FALSE(base::kZeroSeconds > base::kOneHundredMilliseconds);
+}
+
+TEST(BaseTimeCompare, ZeroDotOneWithZero) {
+ EXPECT_FALSE(base::kOneHundredMilliseconds < base::kZeroSeconds);
+ EXPECT_FALSE(base::kOneHundredMilliseconds <= base::kZeroSeconds);
+ EXPECT_FALSE(base::kOneHundredMilliseconds == base::kZeroSeconds);
+ EXPECT_TRUE(base::kOneHundredMilliseconds != base::kZeroSeconds);
+ EXPECT_TRUE(base::kOneHundredMilliseconds >= base::kZeroSeconds);
+ EXPECT_TRUE(base::kOneHundredMilliseconds > base::kZeroSeconds);
+}
+
+TEST(BaseTimeCompare, ZeroWithOne) {
+ EXPECT_TRUE(base::kZeroSeconds < base::kOneSecond);
+ EXPECT_TRUE(base::kZeroSeconds <= base::kOneSecond);
+ EXPECT_FALSE(base::kZeroSeconds == base::kOneSecond);
+ EXPECT_TRUE(base::kZeroSeconds != base::kOneSecond);
+ EXPECT_FALSE(base::kZeroSeconds >= base::kOneSecond);
+ EXPECT_FALSE(base::kZeroSeconds > base::kOneSecond);
+}
+
+TEST(BaseTimeCompare, OneWithZero) {
+ EXPECT_FALSE(base::kOneSecond < base::kZeroSeconds);
+ EXPECT_FALSE(base::kOneSecond <= base::kZeroSeconds);
+ EXPECT_FALSE(base::kOneSecond == base::kZeroSeconds);
+ EXPECT_TRUE(base::kOneSecond != base::kZeroSeconds);
+ EXPECT_TRUE(base::kOneSecond >= base::kZeroSeconds);
+ EXPECT_TRUE(base::kOneSecond > base::kZeroSeconds);
+}
+
+TEST(BaseTimeCompare, OneWithOne) {
+ EXPECT_FALSE(base::kOneSecond < base::kOneSecond);
+ EXPECT_TRUE(base::kOneSecond <= base::kOneSecond);
+ EXPECT_TRUE(base::kOneSecond == base::kOneSecond);
+ EXPECT_FALSE(base::kOneSecond != base::kOneSecond);
+ EXPECT_TRUE(base::kOneSecond >= base::kOneSecond);
+ EXPECT_FALSE(base::kOneSecond > base::kOneSecond);
+}
+
+TEST(BaseTimeCompare, OneWithOneDotOne) {
+ EXPECT_TRUE(base::kOneSecond < kOneDotOneSeconds);
+ EXPECT_TRUE(base::kOneSecond <= kOneDotOneSeconds);
+ EXPECT_FALSE(base::kOneSecond == kOneDotOneSeconds);
+ EXPECT_TRUE(base::kOneSecond != kOneDotOneSeconds);
+ EXPECT_FALSE(base::kOneSecond >= kOneDotOneSeconds);
+ EXPECT_FALSE(base::kOneSecond > kOneDotOneSeconds);
+}
+
+TEST(BaseTimeCompare, OneDotOneWithOne) {
+ EXPECT_FALSE(kOneDotOneSeconds < base::kOneSecond);
+ EXPECT_FALSE(kOneDotOneSeconds <= base::kOneSecond);
+ EXPECT_FALSE(kOneDotOneSeconds == base::kOneSecond);
+ EXPECT_TRUE(kOneDotOneSeconds != base::kOneSecond);
+ EXPECT_TRUE(kOneDotOneSeconds >= base::kOneSecond);
+ EXPECT_TRUE(kOneDotOneSeconds > base::kOneSecond);
+}
+
+TEST(BaseTimeCompare, ZeroDotNineWithZeroDotNine) {
+ EXPECT_FALSE(kZeroDotNineSeconds < kZeroDotNineSeconds);
+ EXPECT_TRUE(kZeroDotNineSeconds <= kZeroDotNineSeconds);
+ EXPECT_TRUE(kZeroDotNineSeconds == kZeroDotNineSeconds);
+ EXPECT_FALSE(kZeroDotNineSeconds != kZeroDotNineSeconds);
+ EXPECT_TRUE(kZeroDotNineSeconds >= kZeroDotNineSeconds);
+ EXPECT_FALSE(kZeroDotNineSeconds > kZeroDotNineSeconds);
+}
+
+TEST(BaseTimeCompare, ZeroDotNineWithOneDotOne) {
+ EXPECT_TRUE(kZeroDotNineSeconds < kOneDotOneSeconds);
+ EXPECT_TRUE(kZeroDotNineSeconds <= kOneDotOneSeconds);
+ EXPECT_FALSE(kZeroDotNineSeconds == kOneDotOneSeconds);
+ EXPECT_TRUE(kZeroDotNineSeconds != kOneDotOneSeconds);
+ EXPECT_FALSE(kZeroDotNineSeconds >= kOneDotOneSeconds);
+ EXPECT_FALSE(kZeroDotNineSeconds > kOneDotOneSeconds);
+}
+
+TEST(BaseTimeCompare, ZeroDotNineWithZeroDotOne) {
+ EXPECT_FALSE(kZeroDotNineSeconds < base::kOneHundredMilliseconds);
+ EXPECT_FALSE(kZeroDotNineSeconds <= base::kOneHundredMilliseconds);
+ EXPECT_FALSE(kZeroDotNineSeconds == base::kOneHundredMilliseconds);
+ EXPECT_TRUE(kZeroDotNineSeconds != base::kOneHundredMilliseconds);
+ EXPECT_TRUE(kZeroDotNineSeconds >= base::kOneHundredMilliseconds);
+ EXPECT_TRUE(kZeroDotNineSeconds > base::kOneHundredMilliseconds);
+}
+
+TEST(BaseTimeCompare, OneDotOneWithZeroDotNine) {
+ EXPECT_FALSE(kOneDotOneSeconds < kZeroDotNineSeconds);
+ EXPECT_FALSE(kOneDotOneSeconds <= kZeroDotNineSeconds);
+ EXPECT_FALSE(kOneDotOneSeconds == kZeroDotNineSeconds);
+ EXPECT_TRUE(kOneDotOneSeconds != kZeroDotNineSeconds);
+ EXPECT_TRUE(kOneDotOneSeconds >= kZeroDotNineSeconds);
+ EXPECT_TRUE(kOneDotOneSeconds > kZeroDotNineSeconds);
+}
+
+TEST(BaseTimeCompare, ZeroDotOneWithZeroDotNine) {
+ EXPECT_TRUE(base::kOneHundredMilliseconds < kZeroDotNineSeconds);
+ EXPECT_TRUE(base::kOneHundredMilliseconds <= kZeroDotNineSeconds);
+ EXPECT_FALSE(base::kOneHundredMilliseconds == kZeroDotNineSeconds);
+ EXPECT_TRUE(base::kOneHundredMilliseconds != kZeroDotNineSeconds);
+ EXPECT_FALSE(base::kOneHundredMilliseconds >= kZeroDotNineSeconds);
+ EXPECT_FALSE(base::kOneHundredMilliseconds > kZeroDotNineSeconds);
+}
+
+TEST(BaseTimeCompare, MaxOfTwoWithLargestLast) {
+ EXPECT_EQ(base::Max(kZeroDotNineSeconds, kOneDotOneSeconds),
+ kOneDotOneSeconds);
+ EXPECT_EQ(base::Max(base::kOneHundredMilliseconds,
+ base::kTwoHundredMilliseconds),
+ base::kTwoHundredMilliseconds);
+}
+
+TEST(BaseTimeCompare, MaxOfTwoWithLargestFirst) {
+ EXPECT_EQ(base::Max(kOneDotOneSeconds, kZeroDotNineSeconds),
+ kOneDotOneSeconds);
+ EXPECT_EQ(base::Max(base::kTwoHundredMilliseconds,
+ base::kOneHundredMilliseconds),
+ base::kTwoHundredMilliseconds);
+}
+
+TEST(BaseTimeCompare, MaxOfTwoEqual) {
+ EXPECT_EQ(base::Max(kOneDotOneSeconds, kOneDotOneSeconds),
+ kOneDotOneSeconds);
+}
+
+TEST(BaseTimeCompare, MaxOfThreeWithLargestLast) {
+ EXPECT_EQ(base::Max(kZeroDotNineSeconds, base::kOneSecond,
+ kOneDotOneSeconds),
+ kOneDotOneSeconds);
+ EXPECT_EQ(base::Max(base::kOneHundredMilliseconds,
+ base::kTwoHundredMilliseconds,
+ base::kThreeHundredMilliseconds),
+ base::kThreeHundredMilliseconds);
+}
+
+TEST(BaseTimeCompare, MaxOfThreeWithLargestInTheMiddle) {
+ EXPECT_EQ(base::Max(kZeroDotNineSeconds, kOneDotOneSeconds,
+ base::kOneSecond),
+ kOneDotOneSeconds);
+ EXPECT_EQ(base::Max(base::kOneHundredMilliseconds,
+ base::kThreeHundredMilliseconds,
+ base::kTwoHundredMilliseconds),
+ base::kThreeHundredMilliseconds);
+}
+
+TEST(BaseTimeCompare, MaxOfThreeWithLargestFirst) {
+ EXPECT_EQ(base::Max(kOneDotOneSeconds, base::kOneSecond,
+ kZeroDotNineSeconds),
+ kOneDotOneSeconds);
+ EXPECT_EQ(base::Max(base::kThreeHundredMilliseconds,
+ base::kOneHundredMilliseconds,
+ base::kTwoHundredMilliseconds),
+ base::kThreeHundredMilliseconds);
+}
+
+TEST(BaseTimeCompare, MaxOfThreeEqual) {
+ EXPECT_EQ(base::Max(kOneDotOneSeconds, kOneDotOneSeconds, kOneDotOneSeconds),
+ kOneDotOneSeconds);
+}
diff --git a/osaf/libs/core/cplusplus/base/tests/time_convert_test.cc
b/osaf/libs/core/cplusplus/base/tests/time_convert_test.cc
new file mode 100644
--- /dev/null
+++ b/osaf/libs/core/cplusplus/base/tests/time_convert_test.cc
@@ -0,0 +1,89 @@
+/* -*- OpenSAF -*-
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+
+#include "base/time.h"
+#include "gtest/gtest.h"
+
+static const timespec kTimespec = { 1576315623, 358743382 };
+static const timeval kTimeval = { 1576315623, 358743 };
+static const timespec kTruncatedTimespec = { 1576315623, 358743000 };
+
+TEST(BaseTimeConvert, TimespecToTimeval) {
+ timeval result = base::TimespecToTimeval(kTimespec);
+ EXPECT_EQ(result.tv_sec, kTimeval.tv_sec);
+ EXPECT_EQ(result.tv_usec, kTimeval.tv_usec);
+}
+
+TEST(BaseTimeConvert, TimevalToTimespec) {
+ EXPECT_EQ(base::TimevalToTimespec(kTimeval), kTruncatedTimespec);
+}
+
+TEST(BaseTimeConvert, MillisToTimespec) {
+ const timespec expected_result = { 1428499100, 961000000 };
+ EXPECT_EQ(base::MillisToTimespec(1428499100961ull), expected_result);
+}
+
+TEST(BaseTimeConvert, MicrosToTimespec) {
+ const timespec expected_result = { 2125428499, 100961000 };
+ EXPECT_EQ(base::MicrosToTimespec(2125428499100961ull), expected_result);
+}
+
+TEST(BaseTimeConvert, NanosToTimespec) {
+ const struct timespec expected_result = { 1725125428, 499100961 };
+ EXPECT_EQ(base::NanosToTimespec(1725125428499100961ull), expected_result);
+}
+
+TEST(BaseTimeConvert, DoubleToTimespec) {
+ const struct timespec expected_result = { 15714713, 125433700 };
+ const struct timespec expected_result2 = { -15714714, 874566300 };
+ EXPECT_EQ(base::DoubleToTimespec(15714713.1254337), expected_result);
+ EXPECT_EQ(base::DoubleToTimespec(-15714713.1254337), expected_result2);
+}
+
+TEST(BaseTimeConvert, DurationToTimespec) {
+ const struct timespec expected_result = { 1725125428, 499100961 };
+ std::chrono::nanoseconds duration{1725125428499100961ull};
+ EXPECT_EQ(base::DurationToTimespec(duration), expected_result);
+}
+
+TEST(BaseTimeConvert, TimespecToMillis) {
+ const struct timespec ts = { 1428499100, 961923266 };
+ EXPECT_EQ(base::TimespecToMillis(ts), 1428499100961ull);
+}
+
+TEST(BaseTimeConvert, TimespecToMicros) {
+ const struct timespec ts = { 1125428499, 100961923 };
+ EXPECT_EQ(base::TimespecToMicros(ts), 1125428499100961ull);
+}
+
+TEST(BaseTimeConvert, TimespecToNanos) {
+ const struct timespec ts = { 1725125428, 499100961 };
+ EXPECT_EQ(base::TimespecToNanos(ts), 1725125428499100961ull);
+}
+
+TEST(BaseTimeConvert, TimespecToDouble) {
+ const struct timespec ts = { 15714713, 125433700 };
+ const struct timespec ts2 = { -15714714, 874566300 };
+ EXPECT_EQ(base::TimespecToDouble(ts), 15714713.1254337);
+ EXPECT_EQ(base::TimespecToDouble(ts2), -15714713.1254337);
+}
+
+TEST(BaseTimeConvert, TimespecToDuration) {
+ const struct timespec ts = { 1725125428, 499100961 };
+ std::chrono::nanoseconds expected_result{1725125428499100961ull};
+ EXPECT_EQ(base::TimespecToDuration(ts), expected_result);
+}
diff --git a/osaf/libs/core/cplusplus/base/tests/time_subtract_test.cc
b/osaf/libs/core/cplusplus/base/tests/time_subtract_test.cc
new file mode 100644
--- /dev/null
+++ b/osaf/libs/core/cplusplus/base/tests/time_subtract_test.cc
@@ -0,0 +1,52 @@
+/* -*- OpenSAF -*-
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+
+#include "base/time.h"
+#include "gtest/gtest.h"
+
+static const timespec kOneDotOneSeconds = { 1, 100000000 };
+static const timespec kZeroDotTwoSeconds = { 0, 200000000 };
+static const timespec kZeroDotNineSeconds = { 0, 900000000 };
+static const timespec number1 = { 1576315623, 358743382 };
+static const timespec number2 = { 279394477, 639614599 };
+static const timespec difference = { 1296921145, 719128783 };
+
+TEST(BaseTimeSubtract, ZeroMinusZero) {
+ timespec result = base::kZeroSeconds - base::kZeroSeconds;
+ EXPECT_TRUE(result == base::kZeroSeconds);
+}
+
+TEST(BaseTimeSubtract, FifteenMinusFive) {
+ timespec result = base::kFifteenSeconds - base::kFiveSeconds;
+ EXPECT_TRUE(result == base::kTenSeconds);
+}
+
+TEST(BaseTimeSubtract, OneDotOneMinusZeroDotTwo) {
+ timespec result = kOneDotOneSeconds - kZeroDotTwoSeconds;
+ EXPECT_TRUE(result == kZeroDotNineSeconds);
+}
+
+TEST(BaseTimeSubtract, SubtractRandomNumbers) {
+ timespec result = number1 - number2;
+ EXPECT_TRUE(result == difference);
+}
+
+TEST(BaseTimeSubtract, FirstParameterAndResultAtSameAddress) {
+ timespec result = number1;
+ result -= number2;
+ EXPECT_TRUE(result == difference);
+}
diff --git a/osaf/libs/core/cplusplus/base/time.h
b/osaf/libs/core/cplusplus/base/time.h
new file mode 100644
--- /dev/null
+++ b/osaf/libs/core/cplusplus/base/time.h
@@ -0,0 +1,275 @@
+/*
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+
+#ifndef OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_TIME_H_
+#define OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_TIME_H_
+
+#include <stdint.h>
+#include <cassert>
+#include <chrono>
+#include <climits>
+#include <ctime>
+#include "osaf_time.h"
+
+static inline bool operator<(const timespec& ts1, const timespec& ts2) {
+ return osaf_timespec_compare(&ts1, &ts2) < 0;
+}
+
+static inline bool operator<=(const timespec& ts1, const timespec& ts2) {
+ return osaf_timespec_compare(&ts1, &ts2) <= 0;
+}
+
+static inline bool operator==(const timespec& ts1, const timespec& ts2) {
+ return osaf_timespec_compare(&ts1, &ts2) == 0;
+}
+
+static inline bool operator!=(const timespec& ts1, const timespec& ts2) {
+ return osaf_timespec_compare(&ts1, &ts2) != 0;
+}
+
+static inline bool operator>=(const timespec& ts1, const timespec& ts2) {
+ return osaf_timespec_compare(&ts1, &ts2) >= 0;
+}
+
+static inline bool operator>(const timespec& ts1, const timespec& ts2) {
+ return osaf_timespec_compare(&ts1, &ts2) > 0;
+}
+
+static inline timespec operator+(const timespec& ts1, const timespec& ts2) {
+ timespec sum;
+ osaf_timespec_add(&ts1, &ts2, &sum);
+ return sum;
+}
+
+static inline timespec operator-(const timespec& ts1, const timespec& ts2) {
+ timespec difference;
+ assert(ts1 >= ts2);
+ osaf_timespec_subtract(&ts1, &ts2, &difference);
+ return difference;
+}
+
+static inline timespec& operator+=(timespec& ts1, const timespec& ts2) {
+ osaf_timespec_add(&ts1, &ts2, &ts1);
+ return ts1;
+}
+
+static inline timespec& operator-=(timespec& ts1, const timespec& ts2) {
+ assert(ts1 >= ts2);
+ osaf_timespec_subtract(&ts1, &ts2, &ts1);
+ return ts1;
+}
+
+namespace base {
+
+constexpr static const timespec kZeroSeconds{ 0, 0 };
+constexpr static const timespec kOneMillisecond{ 0, 1000000 };
+constexpr static const timespec kTenMilliseconds{ 0, 10000000 };
+constexpr static const timespec kTwentyMilliseconds{ 0, 20000000 };
+constexpr static const timespec kThirtyMilliseconds{ 0, 30000000 };
+constexpr static const timespec kFourtyMilliseconds{ 0, 40000000 };
+constexpr static const timespec kFiftyMilliseconds{ 0, 50000000 };
+constexpr static const timespec kOneHundredMilliseconds{ 0, 100000000 };
+constexpr static const timespec kTwoHundredMilliseconds{ 0, 200000000 };
+constexpr static const timespec kThreeHundredMilliseconds{ 0, 300000000 };
+constexpr static const timespec kFourHundredMilliseconds{ 0, 400000000 };
+constexpr static const timespec kFiveHundredMilliseconds{ 0, 500000000 };
+constexpr static const timespec kOneSecond{ 1, 0 };
+constexpr static const timespec kFiveSeconds{ 5, 0 };
+constexpr static const timespec kTenSeconds{ 10, 0 };
+constexpr static const timespec kFifteenSeconds{ 15, 0 };
+constexpr static const timespec kTwentySeconds{ 20, 0 };
+constexpr static const timespec kTwentyfiveSeconds{ 25, 0 };
+constexpr static const timespec kThirtySeconds{ 30, 0 };
+constexpr static const timespec kOneMinute{ 1 * 60, 0 };
+constexpr static const timespec kFiveMinutes{ 5 * 60, 0 };
+constexpr static const timespec kTenMinutes{ 10 * 60, 0 };
+constexpr static const timespec kFifteenMinutes{ 15 * 60, 0 };
+constexpr static const timespec kTwentyMinutes{ 20 * 60, 0 };
+constexpr static const timespec kTwentyfiveMinutes{ 25 * 60, 0 };
+constexpr static const timespec kThirtyMinutes{ 30 * 60, 0 };
+constexpr static const timespec kOneHour{ 60 * 60, 0 };
+constexpr static const timespec kTimespecMax{ sizeof(time_t) == 8 ? INT64_MAX :
+ INT32_MAX, 999999999 };
+
+/**
+ * Read the current value of the system's real-time clock. For more
+ * information, refer to the POSIX function clock_gettime() and the clock id
+ * CLOCK_REALTIME.
+ */
+static inline timespec ReadRealtimeClock() {
+ timespec ts;
+ osaf_clock_gettime(CLOCK_REALTIME, &ts);
+ return ts;
+}
+
+/**
+ * Read the current value of the system's monotonic clock. For more
+ * information, refer to the POSIX function clock_gettime() and the clock id
+ * CLOCK_MONOTONIC.
+ */
+static inline timespec ReadMonotonicClock() {
+ timespec ts;
+ osaf_clock_gettime(CLOCK_MONOTONIC, &ts);
+ return ts;
+}
+
+/**
+ * Suspend execution of the calling thread for the specified @a duration.
+ */
+static inline void Sleep(const timespec& duration) {
+ osaf_nanosleep(&duration);
+}
+
+/**
+ * Convert the specified @a duration to a timespec structure.
+ */
+template<class Rep, class Period>
+static inline timespec DurationToTimespec(
+ const std::chrono::duration<Rep, Period>& duration) {
+ timespec ts;
+ std::chrono::nanoseconds nanos = duration;
+ osaf_nanos_to_timespec(nanos.count(), &ts);
+ return ts;
+}
+
+/**
+ * Convert the specified timeval structure to a timespec structure.
+ */
+static inline timespec TimevalToTimespec(const timeval& tv) {
+ timespec ts;
+ osaf_timeval_to_timespec(&tv, &ts);
+ return ts;
+}
+
+/**
+ * Convert the specified number of @a seconds to a timespec structure.
+ */
+static inline timespec DoubleToTimespec(double seconds) {
+ timespec ts;
+ osaf_double_to_timespec(seconds, &ts);
+ return ts;
+}
+
+/**
+ * Convert the specified number of @a milliseconds to a timespec structure.
+ */
+static inline timespec MillisToTimespec(uint64_t milliseconds) {
+ timespec ts;
+ osaf_millis_to_timespec(milliseconds, &ts);
+ return ts;
+}
+
+/**
+ * Convert the specified number of @a microseconds to a timespec structure.
+ */
+static inline timespec MicrosToTimespec(uint64_t microseconds) {
+ timespec ts;
+ osaf_micros_to_timespec(microseconds, &ts);
+ return ts;
+}
+
+/**
+ * Convert the specified number of @a nanoseconds to a timespec structure.
+ */
+static inline timespec NanosToTimespec(uint64_t nanoseconds) {
+ timespec ts;
+ osaf_nanos_to_timespec(nanoseconds, &ts);
+ return ts;
+}
+
+/**
+ * Convert the specified timespec structure @a ts to a duration with
nanosecond
+ * resolution.
+ */
+static inline std::chrono::nanoseconds TimespecToDuration(const timespec& ts) {
+ return std::chrono::nanoseconds{osaf_timespec_to_nanos(&ts)};
+}
+
+/**
+ * Convert the specified timeval structure to a timespec structure.
+ */
+static inline timeval TimespecToTimeval(const timespec& ts) {
+ timeval tv;
+ osaf_timespec_to_timeval(&ts, &tv);
+ return tv;
+}
+
+/**
+ * Convert the specified timespec structure @a ts to a double representing
time
+ * in the unit of seconds.
+ */
+static inline double TimespecToDouble(const timespec& ts) {
+ return osaf_timespec_to_double(&ts);
+}
+
+/**
+ * Convert the specified timespec structure @a ts to an integer representing
+ * time in the unit of milliseconds.
+ */
+static inline uint64_t TimespecToMillis(const timespec& ts) {
+ return osaf_timespec_to_millis(&ts);
+}
+
+/**
+ * Convert the specified timespec structure @a ts to an integer representing
+ * time in the unit of microseconds.
+ */
+static inline uint64_t TimespecToMicros(const timespec& ts) {
+ return osaf_timespec_to_micros(&ts);
+}
+
+/**
+ * Convert the specified timespec structure @a ts to an integer representing
+ * time in the unit of nanoseconds.
+ */
+static inline uint64_t TimespecToNanos(const timespec& ts) {
+ return osaf_timespec_to_nanos(&ts);
+}
+
+/**
+ * Return the smallest of the two specified timespec structures.
+ */
+static inline timespec Min(const timespec& ts1, const timespec& ts2) {
+ return osaf_timespec_compare(&ts1, &ts2) <= 0 ? ts1 : ts2;
+}
+
+/**
+ * Return the smallest of the three specified timespec structures.
+ */
+static inline timespec Min(const timespec& ts1, const timespec& ts2,
+ const timespec& ts3) {
+ return osaf_timespec_compare(&ts1, &ts2) <= 0 ? Min(ts1, ts3) : Min(ts2,
ts3);
+}
+
+/**
+ * Return the largest of the two specified timespec structures.
+ */
+static inline timespec Max(const timespec& ts1, const timespec& ts2) {
+ return osaf_timespec_compare(&ts1, &ts2) >= 0 ? ts1 : ts2;
+}
+
+/**
+ * Return the largest of the three specified timespec structures.
+ */
+static inline timespec Max(const timespec& ts1, const timespec& ts2,
+ const timespec& ts3) {
+ return osaf_timespec_compare(&ts1, &ts2) >= 0 ? Max(ts1, ts3) : Max(ts2,
ts3);
+}
+
+} // namespace base
+
+#endif /* OPENSAF_OSAF_LIBS_CORE_CPLUSPLUS_BASE_TIME_H_ */
------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=272487151&iu=/4140
_______________________________________________
Opensaf-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel