summaryrefslogtreecommitdiff
path: root/src/components/utils/src
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/utils/src')
-rw-r--r--src/components/utils/src/conditional_variable_boost.cc135
-rw-r--r--src/components/utils/src/conditional_variable_posix.cc149
-rw-r--r--src/components/utils/src/date_time.cc123
-rw-r--r--src/components/utils/src/file_system.cc317
-rw-r--r--src/components/utils/src/lock_boost.cc (renamed from src/components/utils/src/lock_posix.cc)115
-rw-r--r--src/components/utils/src/log_message_loop_thread.cc7
-rw-r--r--src/components/utils/src/logger.cc3
-rw-r--r--src/components/utils/src/semantic_version.cc39
-rw-r--r--src/components/utils/src/signals_posix.cc44
-rw-r--r--src/components/utils/src/system_time_handler.cc62
10 files changed, 511 insertions, 483 deletions
diff --git a/src/components/utils/src/conditional_variable_boost.cc b/src/components/utils/src/conditional_variable_boost.cc
new file mode 100644
index 0000000000..a74aa3eaa6
--- /dev/null
+++ b/src/components/utils/src/conditional_variable_boost.cc
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2013, Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "utils/conditional_variable.h"
+
+#include <errno.h>
+#include <time.h>
+
+#include "utils/lock.h"
+#include "utils/logger.h"
+#include <boost/exception/diagnostic_information.hpp>
+
+namespace {
+const long kNanosecondsPerSecond = 1000000000;
+const long kMillisecondsPerSecond = 1000;
+const long kNanosecondsPerMillisecond = 1000000;
+} // namespace
+
+namespace sync_primitives {
+
+CREATE_LOGGERPTR_GLOBAL(logger_, "Utils")
+
+ConditionalVariable::ConditionalVariable() {}
+
+ConditionalVariable::~ConditionalVariable() {}
+
+void ConditionalVariable::NotifyOne() {
+ cond_var_.notify_one();
+}
+
+void ConditionalVariable::Broadcast() {
+ cond_var_.notify_all();
+}
+
+bool ConditionalVariable::Wait(BaseLock& lock) {
+ // NOTE this grossness is due to boost mutex and recursive mutex not sharing a
+ // superclass
+ try {
+ lock.AssertTakenAndMarkFree();
+ // What kind of lock are we ?
+ if (Lock* test_lock = dynamic_cast<Lock*>(&lock)) {
+ // Regular lock
+ cond_var_.wait<boost::mutex>(test_lock->mutex_);
+ } else if (RecursiveLock* test_rec_lock =
+ dynamic_cast<RecursiveLock*>(&lock)) {
+ // Recursive lock
+ cond_var_.wait<boost::recursive_mutex>(test_rec_lock->mutex_);
+ } else {
+ // unknown, give up the lock
+ LOG4CXX_ERROR(logger_, "Unknown lock type!");
+ NOTREACHED();
+ }
+ lock.AssertFreeAndMarkTaken();
+ } catch (const boost::exception& error) {
+ std::string error_string = boost::diagnostic_information(error);
+ LOG4CXX_FATAL(logger_, error_string);
+ NOTREACHED();
+ }
+ return true;
+}
+
+bool ConditionalVariable::Wait(AutoLock& auto_lock) {
+ BaseLock& lock = auto_lock.GetLock();
+ return Wait(lock);
+}
+
+ConditionalVariable::WaitStatus ConditionalVariable::WaitFor(
+ AutoLock& auto_lock, uint32_t milliseconds) {
+ BaseLock& lock = auto_lock.GetLock();
+
+ WaitStatus wait_status = kNoTimeout;
+ try {
+ lock.AssertTakenAndMarkFree();
+ bool timeout = true;
+
+ // What kind of lock are we ?
+ if (Lock* test_lock = dynamic_cast<Lock*>(&lock)) {
+ // Regular lock
+ // cond_var_.wait<boost::mutex>(test_lock->mutex_);
+ timeout = cond_var_.timed_wait<boost::mutex>(
+ test_lock->mutex_, boost::posix_time::milliseconds(milliseconds));
+ } else if (RecursiveLock* test_rec_lock =
+ dynamic_cast<RecursiveLock*>(&lock)) {
+ // Recursive lock
+ // cond_var_.wait<boost::recursive_mutex>(test_rec_lock->mutex_);
+ timeout = cond_var_.timed_wait<boost::recursive_mutex>(
+ test_rec_lock->mutex_, boost::posix_time::milliseconds(milliseconds));
+ } else {
+ // this is an unknown lock, we have an issue
+ LOG4CXX_ERROR(logger_, "Unknown lock type!");
+ NOTREACHED();
+ }
+
+ if (!timeout) {
+ wait_status = kTimeout;
+ }
+ lock.AssertFreeAndMarkTaken();
+ } catch (const boost::exception& error) {
+ std::string error_string = boost::diagnostic_information(error);
+ LOG4CXX_FATAL(logger_, error_string);
+ NOTREACHED();
+ }
+
+ return wait_status;
+}
+
+} // namespace sync_primitives
diff --git a/src/components/utils/src/conditional_variable_posix.cc b/src/components/utils/src/conditional_variable_posix.cc
deleted file mode 100644
index 50ebc74556..0000000000
--- a/src/components/utils/src/conditional_variable_posix.cc
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright (c) 2013, Ford Motor Company
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided with the
- * distribution.
- *
- * Neither the name of the Ford Motor Company nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#include "utils/conditional_variable.h"
-
-#include <errno.h>
-#include <time.h>
-
-#include "utils/lock.h"
-#include "utils/logger.h"
-
-namespace {
-const long kNanosecondsPerSecond = 1000000000;
-const long kMillisecondsPerSecond = 1000;
-const long kNanosecondsPerMillisecond = 1000000;
-}
-
-namespace sync_primitives {
-
-CREATE_LOGGERPTR_GLOBAL(logger_, "Utils")
-
-ConditionalVariable::ConditionalVariable() {
- pthread_condattr_t attrs;
- int initialized = pthread_condattr_init(&attrs);
- if (initialized != 0)
- LOG4CXX_ERROR(logger_,
- "Failed to initialize "
- "conditional variable attributes");
- pthread_condattr_setclock(&attrs, CLOCK_MONOTONIC);
- initialized = pthread_cond_init(&cond_var_, &attrs);
- if (initialized != 0)
- LOG4CXX_ERROR(logger_,
- "Failed to initialize "
- "conditional variable");
- int rv = pthread_condattr_destroy(&attrs);
- if (rv != 0)
- LOG4CXX_ERROR(logger_,
- "Failed to destroy "
- "conditional variable attributes");
-}
-
-ConditionalVariable::~ConditionalVariable() {
- pthread_cond_destroy(&cond_var_);
-}
-
-void ConditionalVariable::NotifyOne() {
- int signaled = pthread_cond_signal(&cond_var_);
- if (signaled != 0)
- LOG4CXX_ERROR(logger_, "Failed to signal conditional variable");
-}
-
-void ConditionalVariable::Broadcast() {
- int signaled = pthread_cond_broadcast(&cond_var_);
- if (signaled != 0)
- LOG4CXX_ERROR(logger_, "Failed to broadcast conditional variable");
-}
-
-bool ConditionalVariable::Wait(Lock& lock) {
- lock.AssertTakenAndMarkFree();
- int wait_status = pthread_cond_wait(&cond_var_, &lock.mutex_);
- lock.AssertFreeAndMarkTaken();
- if (wait_status != 0) {
- LOG4CXX_ERROR(logger_, "Failed to wait for conditional variable");
- return false;
- }
- return true;
-}
-
-bool ConditionalVariable::Wait(AutoLock& auto_lock) {
- Lock& lock = auto_lock.GetLock();
- lock.AssertTakenAndMarkFree();
- int wait_status = pthread_cond_wait(&cond_var_, &lock.mutex_);
- lock.AssertFreeAndMarkTaken();
- if (wait_status != 0) {
- LOG4CXX_ERROR(logger_, "Failed to wait for conditional variable");
- return false;
- }
- return true;
-}
-
-ConditionalVariable::WaitStatus ConditionalVariable::WaitFor(
- AutoLock& auto_lock, uint32_t milliseconds) {
- struct timespec now;
- clock_gettime(CLOCK_MONOTONIC, &now);
- timespec wait_interval;
- wait_interval.tv_sec = now.tv_sec + (milliseconds / kMillisecondsPerSecond);
- wait_interval.tv_nsec =
- now.tv_nsec +
- (milliseconds % kMillisecondsPerSecond) * kNanosecondsPerMillisecond;
- wait_interval.tv_sec += wait_interval.tv_nsec / kNanosecondsPerSecond;
- wait_interval.tv_nsec %= kNanosecondsPerSecond;
- Lock& lock = auto_lock.GetLock();
- lock.AssertTakenAndMarkFree();
- int timedwait_status =
- pthread_cond_timedwait(&cond_var_, &lock.mutex_, &wait_interval);
- lock.AssertFreeAndMarkTaken();
- WaitStatus wait_status = kNoTimeout;
- switch (timedwait_status) {
- case 0: {
- wait_status = kNoTimeout;
- break;
- }
- case EINTR: {
- wait_status = kNoTimeout;
- break;
- }
- case ETIMEDOUT: {
- wait_status = kTimeout;
- break;
- }
- default: {
- LOG4CXX_ERROR(
- logger_,
- "Failed to timewait for conditional variable timedwait_status: "
- << timedwait_status);
- }
- }
- return wait_status;
-}
-
-} // namespace sync_primitives
diff --git a/src/components/utils/src/date_time.cc b/src/components/utils/src/date_time.cc
index fdf0926eb2..3ca6050b3f 100644
--- a/src/components/utils/src/date_time.cc
+++ b/src/components/utils/src/date_time.cc
@@ -30,94 +30,71 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/time.h>
-#include <stdint.h>
#include "utils/date_time.h"
-namespace date_time {
+#include <stdint.h>
+#include <sys/time.h>
+#include "boost/date_time/posix_time/posix_time.hpp"
-TimevalStruct DateTime::getCurrentTime() {
- TimevalStruct currentTime;
- timezone timeZone;
+namespace bpt = boost::posix_time;
+using namespace boost::date_time;
+namespace date_time {
- gettimeofday(&currentTime, &timeZone);
+/* Set of helper functions for the TimeDuration struct
+ */
- return currentTime;
+TimeDuration getCurrentTime() {
+ return bpt::microsec_clock::local_time() - bpt::from_time_t(0);
+}
+TimeDuration TimeDurationZero() {
+ return TimeDuration(0, 0, 0, 0);
+}
+int64_t getSecs(const TimeDuration& t) {
+ return t.total_seconds();
}
-int64_t date_time::DateTime::getSecs(const TimevalStruct& time) {
- const TimevalStruct times = ConvertionUsecs(time);
- return static_cast<int64_t>(times.tv_sec);
+int64_t getmSecs(const TimeDuration& t) {
+ return t.total_milliseconds();
}
-int64_t DateTime::getmSecs(const TimevalStruct& time) {
- const TimevalStruct times = ConvertionUsecs(time);
- return static_cast<int64_t>(times.tv_sec) * MILLISECONDS_IN_SECOND +
- times.tv_usec / MICROSECONDS_IN_MILLISECOND;
+int64_t getuSecs(const TimeDuration& t) {
+ return t.total_microseconds();
}
-int64_t DateTime::getuSecs(const TimevalStruct& time) {
- const TimevalStruct times = ConvertionUsecs(time);
- return static_cast<int64_t>(times.tv_sec) * MILLISECONDS_IN_SECOND *
- MICROSECONDS_IN_MILLISECOND +
- times.tv_usec;
+int64_t get_just_mSecs(const TimeDuration& t) {
+ return t.total_milliseconds() % MILLISECONDS_IN_SECOND;
}
-int64_t DateTime::calculateTimeSpan(const TimevalStruct& sinceTime) {
- return calculateTimeDiff(getCurrentTime(), sinceTime);
+int64_t get_just_uSecs(const TimeDuration& t) {
+ return t.total_microseconds() % MICROSECONDS_IN_SECOND;
}
-int64_t DateTime::calculateTimeDiff(const TimevalStruct& time1,
- const TimevalStruct& time2) {
- const TimevalStruct times1 = ConvertionUsecs(time1);
- const TimevalStruct times2 = ConvertionUsecs(time2);
- TimevalStruct ret;
- if (Greater(times1, times2)) {
- ret = Sub(times1, times2);
- } else {
- ret = Sub(times2, times1);
- }
- return getmSecs(ret);
+int64_t calculateTimeSpan(const TimeDuration& sinceTime) {
+ return calculateTimeDiff(getCurrentTime(), sinceTime);
}
-void DateTime::AddMilliseconds(TimevalStruct& time, uint32_t milliseconds) {
- const uint32_t sec = milliseconds / MILLISECONDS_IN_SECOND;
- const uint32_t usec =
- (milliseconds % MILLISECONDS_IN_SECOND) * MICROSECONDS_IN_MILLISECOND;
- time.tv_sec += sec;
- time.tv_usec += usec;
- time = ConvertionUsecs(time);
+int64_t calculateTimeDiff(const TimeDuration& time1,
+ const TimeDuration& time2) {
+ return std::abs((time1 + -time2).total_milliseconds());
}
-TimevalStruct DateTime::Sub(const TimevalStruct& time1,
- const TimevalStruct& time2) {
- const TimevalStruct times1 = ConvertionUsecs(time1);
- const TimevalStruct times2 = ConvertionUsecs(time2);
- TimevalStruct ret;
- timersub(&times1, &times2, &ret);
- return ret;
+void AddMilliseconds(TimeDuration& t, uint32_t milliseconds) {
+ t += bpt::milliseconds(milliseconds);
}
-bool DateTime::Greater(const TimevalStruct& time1, const TimevalStruct& time2) {
- const TimevalStruct times1 = ConvertionUsecs(time1);
- const TimevalStruct times2 = ConvertionUsecs(time2);
- return timercmp(&times1, &times2, > );
+bool Greater(const TimeDuration& time1, const TimeDuration& time2) {
+ return time1 > time2;
}
-bool DateTime::Less(const TimevalStruct& time1, const TimevalStruct& time2) {
- const TimevalStruct times1 = ConvertionUsecs(time1);
- const TimevalStruct times2 = ConvertionUsecs(time2);
- return timercmp(&times1, &times2, < );
+bool Less(const TimeDuration& time1, const TimeDuration& time2) {
+ return time1 < time2;
}
-bool DateTime::Equal(const TimevalStruct& time1, const TimevalStruct& time2) {
- const TimevalStruct times1 = ConvertionUsecs(time1);
- const TimevalStruct times2 = ConvertionUsecs(time2);
- return !timercmp(&times1, &times2, != );
+bool Equal(const TimeDuration& time1, const TimeDuration& time2) {
+ return time1 == time2;
}
-TimeCompare date_time::DateTime::compareTime(const TimevalStruct& time1,
- const TimevalStruct& time2) {
+TimeCompare compareTime(const TimeDuration& time1, const TimeDuration& time2) {
if (Greater(time1, time2))
return GREATER;
if (Less(time1, time2))
@@ -125,28 +102,4 @@ TimeCompare date_time::DateTime::compareTime(const TimevalStruct& time1,
return EQUAL;
}
-TimevalStruct date_time::DateTime::ConvertionUsecs(const TimevalStruct& time) {
- if (time.tv_usec >= MICROSECONDS_IN_SECOND) {
- TimevalStruct time1;
- time1.tv_sec = static_cast<int64_t>(time.tv_sec) +
- (time.tv_usec / MICROSECONDS_IN_SECOND);
- time1.tv_usec = static_cast<int64_t>(time.tv_usec) % MICROSECONDS_IN_SECOND;
- return time1;
- }
- return time;
-}
-
} // namespace date_time
-
-bool operator<(const TimevalStruct& time1, const TimevalStruct& time2) {
- return date_time::DateTime::Less(time1, time2);
-}
-
-bool operator==(const TimevalStruct& time1, const TimevalStruct& time2) {
- return date_time::DateTime::Equal(time1, time2);
-}
-
-const TimevalStruct operator-(const TimevalStruct& time1,
- const TimevalStruct& time2) {
- return date_time::DateTime::Sub(time1, time2);
-}
diff --git a/src/components/utils/src/file_system.cc b/src/components/utils/src/file_system.cc
index 62a91ad1f3..f98aeda056 100644
--- a/src/components/utils/src/file_system.cc
+++ b/src/components/utils/src/file_system.cc
@@ -33,125 +33,114 @@
#include "utils/file_system.h"
#include "utils/logger.h"
-#include <sys/statvfs.h>
#include <sys/stat.h>
+#include <sys/statvfs.h>
#include <sys/types.h>
#include <sstream>
#include <dirent.h>
#include <unistd.h>
// TODO(VS): lint error: Streams are highly discouraged.
-#include <fstream>
+#include <algorithm>
+#include <boost/filesystem.hpp>
#include <cstddef>
#include <cstdio>
-#include <algorithm>
+#include <fstream>
CREATE_LOGGERPTR_GLOBAL(logger_, "Utils")
+// Easier reference
+namespace fs = boost::filesystem;
+using boost::system::error_code;
+
uint64_t file_system::GetAvailableDiskSpace(const std::string& path) {
- struct statvfs fsInfo = {0};
- if (statvfs(path.c_str(), &fsInfo) == 0) {
- return fsInfo.f_bsize * fsInfo.f_bfree;
- } else {
+ error_code ec;
+ fs::space_info si = fs::space(path, ec);
+
+ if (ec) {
+ // If something went wrong, assume no free space
return 0;
+ } else {
+ return si.free;
}
}
-int64_t file_system::FileSize(const std::string& path) {
- if (file_system::FileExists(path)) {
- struct stat file_info = {0};
- if (0 != stat(path.c_str(), &file_info)) {
- LOG4CXX_WARN_WITH_ERRNO(logger_, "Could not get file size: " << path);
- } else {
- return file_info.st_size;
- }
+uint64_t file_system::FileSize(const std::string& path) {
+ error_code ec;
+ // Boost returns sizes as unsigned
+ uint64_t fsize = (uint64_t)fs::file_size(path, ec);
+
+ if (ec) {
+ LOG4CXX_WARN_WITH_ERRNO(logger_, "Could not get file size: " << path);
+ return 0;
}
- return 0;
+ return fsize;
}
size_t file_system::DirectorySize(const std::string& path) {
- size_t size = 0;
- int32_t return_code = 0;
- DIR* directory = NULL;
- struct dirent dir_element_;
- struct dirent* dir_element = &dir_element_;
- struct dirent* result = NULL;
- struct stat file_info = {0};
- directory = opendir(path.c_str());
- if (NULL != directory) {
- return_code = readdir_r(directory, dir_element, &result);
- for (; NULL != result && 0 == return_code;
- return_code = readdir_r(directory, dir_element, &result)) {
- if (0 == strcmp(result->d_name, "..") ||
- 0 == strcmp(result->d_name, ".")) {
- continue;
- }
- std::string full_element_path = path + "/" + result->d_name;
- if (file_system::IsDirectory(full_element_path)) {
- size += DirectorySize(full_element_path);
- } else {
- stat(full_element_path.c_str(), &file_info);
- size += file_info.st_size;
- }
+ size_t dir_size = 0;
+ error_code ec;
+ // Recursively iterate through directory to accumulate file sizes
+ fs::recursive_directory_iterator iter(path, ec);
+ // Directory does not exist
+ if (ec) {
+ return 0;
+ }
+ // default constructor gives end iterator
+ fs::recursive_directory_iterator end;
+ while (iter != end) {
+ size_t fsize = fs::file_size(iter->path(), ec);
+ // No error means we can add the file
+ if (!ec) {
+ dir_size += fsize;
}
+ iter++; // next entry
}
- closedir(directory);
- return size;
+ return dir_size;
}
+// NOTE that boost makes 0777 permissions by default
std::string file_system::CreateDirectory(const std::string& name) {
- if (!DirectoryExists(name)) {
- if (0 != mkdir(name.c_str(), S_IRWXU)) {
- LOG4CXX_WARN_WITH_ERRNO(logger_, "Unable to create directory: " << name);
- }
+ error_code ec;
+ bool success = fs::create_directory(name, ec);
+ if (!success || ec) {
+ LOG4CXX_WARN_WITH_ERRNO(logger_, "Unable to create directory: " << name);
+ } else {
+ // Set 0700 permissions to maintain previous API
+ fs::permissions(name, fs::perms::owner_all, ec);
}
-
return name;
}
bool file_system::CreateDirectoryRecursively(const std::string& path) {
- size_t pos = 0;
- bool ret_val = true;
-
- while (ret_val == true && pos <= path.length()) {
- pos = path.find('/', pos + 1);
- if (!DirectoryExists(path.substr(0, pos))) {
- if (0 != mkdir(path.substr(0, pos).c_str(), S_IRWXU)) {
- ret_val = false;
- }
- }
- }
+ error_code ec;
+ // Create directory and all parents
+ fs::create_directories(path, ec);
- return ret_val;
-}
+ if (ec) {
+ LOG4CXX_WARN_WITH_ERRNO(logger_,
+ "Unable to create directory recursively: "
+ << path << " reason: " << ec.message());
-bool file_system::IsDirectory(const std::string& name) {
- struct stat status = {0};
-
- if (-1 == stat(name.c_str(), &status)) {
return false;
}
-
- return S_ISDIR(status.st_mode);
+ // return true if we made something or if it already existed
+ return true;
}
+bool file_system::IsDirectory(const std::string& name) {
+ error_code ec;
+ return fs::is_directory(name, ec);
+}
+// NOTE this may be a duplicate of IsDirectory since it already checks
+// existence
bool file_system::DirectoryExists(const std::string& name) {
- struct stat status = {0};
-
- if (-1 == stat(name.c_str(), &status) || !S_ISDIR(status.st_mode)) {
- return false;
- }
-
- return true;
+ return FileExists(name) && IsDirectory(name);
}
bool file_system::FileExists(const std::string& name) {
- struct stat status = {0};
-
- if (-1 == stat(name.c_str(), &status)) {
- return false;
- }
- return true;
+ error_code ec;
+ return fs::exists(name, ec);
}
bool file_system::Write(const std::string& file_name,
@@ -200,80 +189,75 @@ void file_system::Close(std::ofstream* file_stream) {
}
std::string file_system::CurrentWorkingDirectory() {
- const size_t filename_max_length = 1024;
- char path[filename_max_length];
- if (0 == getcwd(path, filename_max_length)) {
+ error_code ec;
+ fs::path currpath = fs::current_path(ec);
+ if (ec) {
LOG4CXX_WARN(logger_, "Could not get CWD");
}
- return std::string(path);
+ return currpath.string();
}
std::string file_system::GetAbsolutePath(const std::string& path) {
- char abs_path[PATH_MAX];
- if (NULL == realpath(path.c_str(), abs_path)) {
- return std::string();
+ error_code ec;
+ fs::path absolute = fs::canonical(path, ec);
+ if (ec) {
+ return std::string(); // invalid path
}
-
- return std::string(abs_path);
+ return absolute.string();
}
bool file_system::IsFileNameValid(const std::string& file_name) {
return file_name.end() == std::find(file_name.begin(), file_name.end(), '/');
}
+// Does not remove if file is write-protected
bool file_system::DeleteFile(const std::string& name) {
if (FileExists(name) && IsAccessible(name, W_OK)) {
- return !remove(name.c_str());
+ error_code ec;
+ bool success = fs::remove(name.c_str(), ec);
+ return success && !ec;
}
return false;
}
void file_system::remove_directory_content(const std::string& directory_name) {
- int32_t return_code = 0;
- DIR* directory = NULL;
- struct dirent dir_element_;
- struct dirent* dir_element = &dir_element_;
- struct dirent* result = NULL;
-
- directory = opendir(directory_name.c_str());
-
- if (NULL != directory) {
- return_code = readdir_r(directory, dir_element, &result);
-
- for (; NULL != result && 0 == return_code;
- return_code = readdir_r(directory, dir_element, &result)) {
- if (0 == strcmp(result->d_name, "..") ||
- 0 == strcmp(result->d_name, ".")) {
- continue;
- }
-
- std::string full_element_path = directory_name + "/" + result->d_name;
-
- if (file_system::IsDirectory(full_element_path)) {
- remove_directory_content(full_element_path);
- rmdir(full_element_path.c_str());
- } else {
- if (0 != remove(full_element_path.c_str())) {
- LOG4CXX_WARN_WITH_ERRNO(
- logger_, "Unable to remove file: " << full_element_path);
- }
- }
- }
+ error_code ec;
+ fs::directory_iterator dir_iter(directory_name, ec);
+
+ if (ec) {
+ LOG4CXX_WARN_WITH_ERRNO(logger_,
+ "Unable to empty directory: " << directory_name);
}
- closedir(directory);
+ // According to Boost's documentation, removing shouldn't invalidate the
+ // iterator, although it may cause the removed entry to appear again,
+ // duplicating the warning message. See here:
+ // https://www.boost.org/doc/libs/1_67_0/libs/filesystem/doc/reference.html#Class-directory_iterator
+ for (auto& dirent : dir_iter) {
+ fs::remove_all(dirent, ec);
+ if (ec) {
+ LOG4CXX_WARN_WITH_ERRNO(
+ logger_, "Unable to remove file: " << dirent.path().string());
+ }
+ }
}
bool file_system::RemoveDirectory(const std::string& directory_name,
bool is_recursively) {
- if (DirectoryExists(directory_name) && IsAccessible(directory_name, W_OK)) {
- if (is_recursively) {
- remove_directory_content(directory_name);
- }
-
- return !rmdir(directory_name.c_str());
+ // Make sure the directory exists
+ if (!DirectoryExists(directory_name) && IsAccessible(directory_name, W_OK)) {
+ return false;
}
- return false;
+ error_code ec;
+ bool success;
+ // If recursive, just force full remove
+ if (is_recursively) {
+ success = (fs::remove_all(directory_name, ec) != 0);
+ } else {
+ // Otherwise try to remove
+ success = fs::remove(directory_name, ec);
+ }
+ return success && !ec;
}
bool file_system::IsAccessible(const std::string& name, int32_t how) {
@@ -290,34 +274,20 @@ bool file_system::IsReadingAllowed(const std::string& name) {
std::vector<std::string> file_system::ListFiles(
const std::string& directory_name) {
+ error_code ec;
+
+ fs::directory_iterator dir_iter(directory_name, ec);
std::vector<std::string> listFiles;
- if (!DirectoryExists(directory_name)) {
+
+ // In case the directory doesn't exist / can't be read, second check may be
+ // redundant
+ if (ec || !DirectoryExists(directory_name)) {
return listFiles;
}
- int32_t return_code = 0;
- DIR* directory = NULL;
- struct dirent dir_element_;
- struct dirent* dir_element = &dir_element_;
- struct dirent* result = NULL;
-
- directory = opendir(directory_name.c_str());
- if (NULL != directory) {
- return_code = readdir_r(directory, dir_element, &result);
-
- for (; NULL != result && 0 == return_code;
- return_code = readdir_r(directory, dir_element, &result)) {
- if (0 == strcmp(result->d_name, "..") ||
- 0 == strcmp(result->d_name, ".")) {
- continue;
- }
-
- listFiles.push_back(std::string(result->d_name));
- }
-
- closedir(directory);
+ for (auto& dirent : dir_iter) {
+ listFiles.push_back(dirent.path().filename().string());
}
-
return listFiles;
}
@@ -390,47 +360,42 @@ bool file_system::CreateFile(const std::string& path) {
}
}
-uint64_t file_system::GetFileModificationTime(const std::string& path) {
- struct stat info;
- if (0 != stat(path.c_str(), &info)) {
- LOG4CXX_WARN_WITH_ERRNO(logger_, "Could not get file mod time: " << path);
+time_t file_system::GetFileModificationTime(const std::string& path) {
+ error_code ec;
+ std::time_t time = fs::last_write_time(path, ec);
+ if (ec) {
+ return 0;
}
- return static_cast<uint64_t>(info.st_mtim.tv_nsec);
+ return time;
}
bool file_system::CopyFile(const std::string& src, const std::string& dst) {
if (!FileExists(src) || FileExists(dst) || !CreateFile(dst)) {
return false;
}
- std::vector<uint8_t> data;
- if (!ReadBinaryFile(src, data) || !WriteBinaryFile(dst, data)) {
- DeleteFile(dst);
+ error_code ec;
+ fs::copy_file(src, dst, ec);
+ if (ec) {
+ // something failed
return false;
}
return true;
}
bool file_system::MoveFile(const std::string& src, const std::string& dst) {
+ error_code ec;
+
if (std::rename(src.c_str(), dst.c_str()) == 0) {
return true;
- } else {
- // In case of src and dst on different file systems std::rename returns
- // an error (at least on QNX).
- // Seems, streams are not recommended for use, so have
- // to find another way to do this.
- std::ifstream s_src(src, std::ios::binary);
- if (!s_src.good()) {
- return false;
- }
- std::ofstream s_dst(dst, std::ios::binary);
- if (!s_dst.good()) {
- return false;
- }
- s_dst << s_src.rdbuf();
- s_dst.close();
- s_src.close();
- DeleteFile(src);
- return true;
}
- return false;
+ // In case of src and dst on different file systems std::rename returns
+ // an error (at least on QNX).
+ // Instead, copy the file over and delete the old one
+ bool success = CopyFile(src, dst);
+ if (!success) {
+ return false;
+ }
+ DeleteFile(src);
+
+ return true;
}
diff --git a/src/components/utils/src/lock_posix.cc b/src/components/utils/src/lock_boost.cc
index 9b90ad20b9..2299bcf77d 100644
--- a/src/components/utils/src/lock_posix.cc
+++ b/src/components/utils/src/lock_boost.cc
@@ -30,117 +30,98 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include "utils/lock.h"
#include <errno.h>
#include <stdint.h>
-#include <stdio.h>
#include <string.h>
#include <cstring>
+#include "utils/lock.h"
#include "utils/logger.h"
namespace sync_primitives {
CREATE_LOGGERPTR_GLOBAL(logger_, "Utils")
-Lock::Lock()
-#ifndef NDEBUG
- : lock_taken_(0)
- , is_mutex_recursive_(false)
-#endif // NDEBUG
-{
- Init(false);
-}
-
-Lock::Lock(bool is_recursive)
-#ifndef NDEBUG
- : lock_taken_(0)
- , is_mutex_recursive_(is_recursive)
-#endif // NDEBUG
-{
- Init(is_recursive);
-}
+Lock::Lock() : lock_taken_(0) {}
Lock::~Lock() {
-#ifndef NDEBUG
if (lock_taken_ > 0) {
- LOG4CXX_ERROR(logger_, "Destroying non-released mutex " << &mutex_);
- }
-#endif
- int32_t status = pthread_mutex_destroy(&mutex_);
- if (status != 0) {
- LOG4CXX_ERROR(logger_,
- "Failed to destroy mutex " << &mutex_ << ": "
- << strerror(status));
+ LOG4CXX_FATAL(logger_, "Destroying non-released regular mutex " << &mutex_);
}
}
void Lock::Acquire() {
- const int32_t status = pthread_mutex_lock(&mutex_);
- if (status != 0) {
- LOG4CXX_FATAL(logger_,
- "Failed to acquire mutex " << &mutex_ << ": "
- << strerror(status));
- NOTREACHED();
- } else {
- AssertFreeAndMarkTaken();
- }
+ mutex_.lock();
+ AssertFreeAndMarkTaken();
}
void Lock::Release() {
AssertTakenAndMarkFree();
- const int32_t status = pthread_mutex_unlock(&mutex_);
- if (status != 0) {
- LOG4CXX_ERROR(logger_,
- "Failed to unlock mutex" << &mutex_ << ": "
- << strerror(status));
- }
+ mutex_.unlock();
}
bool Lock::Try() {
- const int32_t status = pthread_mutex_trylock(&mutex_);
- if (status == 0) {
-#ifndef NDEBUG
- lock_taken_++;
-#endif
- return true;
+ bool status = mutex_.try_lock();
+ if (status) {
+ AssertFreeAndMarkTaken();
}
- return false;
+ return status;
}
-#ifndef NDEBUG
void Lock::AssertFreeAndMarkTaken() {
- if ((lock_taken_ > 0) && !is_mutex_recursive_) {
- LOG4CXX_ERROR(logger_, "Locking already taken not recursive mutex");
+ if (lock_taken_ != 0) {
+ LOG4CXX_FATAL(logger_, "Locking already taken not recursive mutex");
NOTREACHED();
}
lock_taken_++;
}
+
void Lock::AssertTakenAndMarkFree() {
if (lock_taken_ == 0) {
- LOG4CXX_ERROR(logger_, "Unlocking a mutex that is not taken");
+ LOG4CXX_FATAL(logger_, "Unlocking a mutex that is not taken");
NOTREACHED();
}
lock_taken_--;
}
-#endif
-void Lock::Init(bool is_recursive) {
- pthread_mutexattr_t attr;
- pthread_mutexattr_init(&attr);
+// Recursive lock looks the same on the surface, some code duplication is
+// necessary since they don't have a shared parent superclass
+RecursiveLock::RecursiveLock() : lock_taken_(0) {}
- const int32_t mutex_type =
- is_recursive ? PTHREAD_MUTEX_RECURSIVE : PTHREAD_MUTEX_ERRORCHECK;
+RecursiveLock::~RecursiveLock() {
+ if (lock_taken_ > 0) {
+ LOG4CXX_FATAL(logger_,
+ "Destroying non-released recursive mutex " << &mutex_);
+ }
+}
- pthread_mutexattr_settype(&attr, mutex_type);
- const int32_t status = pthread_mutex_init(&mutex_, &attr);
+void RecursiveLock::Acquire() {
+ mutex_.lock();
+ AssertFreeAndMarkTaken();
+}
- pthread_mutexattr_destroy(&attr);
+void RecursiveLock::Release() {
+ AssertTakenAndMarkFree();
+ mutex_.unlock();
+}
- if (status != 0) {
- LOG4CXX_FATAL(logger_,
- "Failed to initialize mutex. " << std::strerror(status));
- DCHECK(status != 0);
+bool RecursiveLock::Try() {
+ bool status = mutex_.try_lock();
+ if (status) {
+ AssertFreeAndMarkTaken();
}
+ return status;
+}
+
+void RecursiveLock::AssertFreeAndMarkTaken() {
+ lock_taken_++;
+}
+
+void RecursiveLock::AssertTakenAndMarkFree() {
+ if (lock_taken_ == 0) {
+ LOG4CXX_FATAL(logger_, "Unlocking a recursive mutex that is not taken");
+ NOTREACHED();
+ }
+ lock_taken_--;
}
} // namespace sync_primitives
diff --git a/src/components/utils/src/log_message_loop_thread.cc b/src/components/utils/src/log_message_loop_thread.cc
index 2b7f28fbfd..182eb64534 100644
--- a/src/components/utils/src/log_message_loop_thread.cc
+++ b/src/components/utils/src/log_message_loop_thread.cc
@@ -35,7 +35,7 @@
namespace logger {
-void LogMessageHandler::Handle(const LogMessage message) {
+void LogMessageLoopThread::Handle(const LogMessage message) {
message.logger->forcedLog(message.level,
message.entry,
message.timeStamp,
@@ -44,14 +44,13 @@ void LogMessageHandler::Handle(const LogMessage message) {
}
LogMessageLoopThread::LogMessageLoopThread()
- : LogMessageLoopThreadTemplate("Logger",
- handler_ = new LogMessageHandler()) {}
+ : LogMessageLoopThreadTemplate("Logger", this) {}
LogMessageLoopThread::~LogMessageLoopThread() {
// we'll have to drop messages
// while deleting logger thread
logger_status = DeletingLoggerThread;
- delete handler_;
+ LogMessageLoopThreadTemplate::Shutdown();
}
} // namespace logger
diff --git a/src/components/utils/src/logger.cc b/src/components/utils/src/logger.cc
index 4e93ca3d14..af21aeac77 100644
--- a/src/components/utils/src/logger.cc
+++ b/src/components/utils/src/logger.cc
@@ -39,6 +39,9 @@ void deinit_logger() {
CREATE_LOGGERPTR_LOCAL(logger_, "Utils")
LOG4CXX_DEBUG(logger_, "Logger deinitialization");
logger::set_logs_enabled(false);
+ if (logger::logger_status == logger::LoggerThreadCreated) {
+ logger::flush_logger();
+ }
logger::delete_log_message_loop_thread();
log4cxx::LoggerPtr rootLogger = log4cxx::Logger::getRootLogger();
log4cxx::spi::LoggerRepositoryPtr repository =
diff --git a/src/components/utils/src/semantic_version.cc b/src/components/utils/src/semantic_version.cc
new file mode 100644
index 0000000000..9f0991e991
--- /dev/null
+++ b/src/components/utils/src/semantic_version.cc
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018, Livio
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "utils/semantic_version.h"
+
+namespace utils {
+
+const SemanticVersion base_rpc_version(4, 5, 1);
+const SemanticVersion rpc_version_5(5, 0, 0);
+
+} // namespace utils \ No newline at end of file
diff --git a/src/components/utils/src/signals_posix.cc b/src/components/utils/src/signals_posix.cc
index 274c254716..e13dc04f40 100644
--- a/src/components/utils/src/signals_posix.cc
+++ b/src/components/utils/src/signals_posix.cc
@@ -29,13 +29,16 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include <sys/wait.h>
#include <csignal>
#include <cstdlib>
#include <stdint.h>
+#include <iostream>
#include "utils/signals.h"
-bool utils::UnsibscribeFromTermination() {
+namespace utils {
+bool Signals::UnsubscribeFromTermination() {
// Disable some system signals receiving in thread
// by blocking those signals
// (system signals processes only in the main thread)
@@ -51,6 +54,42 @@ bool utils::UnsibscribeFromTermination() {
return !pthread_sigmask(SIG_BLOCK, &signal_set, NULL);
}
+bool Signals::UnsubscribeFromLowVoltageSignals(
+ const main_namespace::LowVoltageSignalsOffset& offset_data) {
+ // Disable Low Voltage signals in main thread
+ // due to all further threads will inherit signals mask
+ sigset_t signal_set;
+ sigemptyset(&signal_set);
+ const int SIGLOWVOLTAGE = SIGRTMIN + offset_data.low_voltage_signal_offset;
+ const int SIGWAKEUP = SIGRTMIN + offset_data.wake_up_signal_offset;
+ const int SIGIGNOFF = SIGRTMIN + offset_data.ignition_off_signal_offset;
+ sigaddset(&signal_set, SIGLOWVOLTAGE);
+ sigaddset(&signal_set, SIGWAKEUP);
+ sigaddset(&signal_set, SIGIGNOFF);
+
+ // Set signals mask to be blocked by thread
+ return !pthread_sigmask(SIG_BLOCK, &signal_set, nullptr);
+}
+
+void Signals::SendSignal(const int signo, const pid_t pid) {
+ if (kill(pid, signo) == -1) {
+ std::cerr << "Error sending signal: " << strsignal(signo) << " to " << pid
+ << " .Error: " << strerror(errno) << std::endl;
+ }
+}
+
+pid_t Signals::Fork() {
+ return fork();
+}
+
+void Signals::ExitProcess(const int status) {
+ exit(status);
+}
+
+void Signals::WaitPid(pid_t cpid, int* status, int options) {
+ waitpid(cpid, status, options);
+}
+
namespace {
bool CatchSIGSEGV(sighandler_t handler) {
struct sigaction act;
@@ -63,7 +102,7 @@ bool CatchSIGSEGV(sighandler_t handler) {
}
} // namespace
-bool utils::WaitTerminationSignals(sighandler_t sig_handler) {
+bool Signals::WaitTerminationSignals(sighandler_t sig_handler) {
sigset_t signal_set;
int sig = -1;
@@ -81,3 +120,4 @@ bool utils::WaitTerminationSignals(sighandler_t sig_handler) {
}
return false;
}
+} // namespace utils
diff --git a/src/components/utils/src/system_time_handler.cc b/src/components/utils/src/system_time_handler.cc
new file mode 100644
index 0000000000..0c3c62cc53
--- /dev/null
+++ b/src/components/utils/src/system_time_handler.cc
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2018, Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "utils/system_time_handler.h"
+
+namespace utils {
+
+SystemTimeHandler::SystemTimeHandler() {}
+
+SystemTimeHandler::~SystemTimeHandler() {}
+
+void SystemTimeHandler::QuerySystemTime() {
+ DoSystemTimeQuery();
+}
+
+void SystemTimeHandler::SubscribeOnSystemTime(SystemTimeListener* listener) {
+ DoSubscribe(listener);
+}
+
+void SystemTimeHandler::UnsubscribeFromSystemTime(
+ SystemTimeListener* listener) {
+ DoUnsubscribe(listener);
+}
+
+time_t SystemTimeHandler::GetUTCTime() {
+ return FetchSystemTime();
+}
+
+bool SystemTimeHandler::system_time_can_be_received() const {
+ return utc_time_can_be_received();
+}
+
+} // namespace utils