osaf/libs/core/cplusplus/base/buffer.h | 26 +- osaf/libs/core/cplusplus/base/log_message.cc | 106 ------------- osaf/libs/core/cplusplus/base/log_message.h | 126 +++++++++++++++- osaf/libs/core/cplusplus/base/tests/log_message_test.cc | 14 +- osaf/libs/core/mds/mds_log.cc | 4 +- 5 files changed, 141 insertions(+), 135 deletions(-)
Make the use of temporary Buffer instances on the stack more efficient, by storing the buffer data in a character array inside the class instead of allocating it dynamically. diff --git a/osaf/libs/core/cplusplus/base/buffer.h b/osaf/libs/core/cplusplus/base/buffer.h --- a/osaf/libs/core/cplusplus/base/buffer.h +++ b/osaf/libs/core/cplusplus/base/buffer.h @@ -25,19 +25,14 @@ namespace base { -// An output buffer that can be used to build e.g. a message to be sent over a -// network. +// An output buffer with enough space to store @a Capacity bytes of data. It can +// be used to build e.g. a message to be sent over a network. +template <size_t Capacity> class Buffer { public: - // Allocate a buffer with enough space to store @a capacity bytes of data. - explicit Buffer(size_t capacity) : - buffer_{new char[capacity]}, - capacity_{capacity}, + Buffer() : size_{0} { } - ~Buffer() { - delete [] buffer_; - } // Reset the write position to the start of the buffer. void clear() { size_ = 0; } // Returns true if the buffer is empty. @@ -45,16 +40,18 @@ class Buffer { // Returns a pointer to the start of the buffer. const char* data() const { return buffer_; } // Returns a pointer to the end of the buffer where new data can be appended. - char* end() const { return buffer_ + size_; } + char* end() { return buffer_ + size_; } + // Returns a read-only pointer to the end of the buffer. + const char* end() const { return buffer_ + size_; } // Returns the number of bytes that have been written to the buffer. size_t size() const { return size_; } // Set new size of the buffer (e.g. after manually adding data at the end). void set_size(size_t s) { size_ = s; } // Returns the maximum number of bytes that can be stored in this buffer. - size_t capacity() const { return capacity_; } + static size_t capacity() { return Capacity; } // Append a single character to the end of the buffer. void AppendChar(char c) { - if (size_ != capacity_) buffer_[size_++] = c; + if (size_ != Capacity) buffer_[size_++] = c; } // This function is similar to AppendNumber(), except that leading zeros will // be printed - i.e. this method implements a fixed field width. @@ -77,7 +74,7 @@ class Buffer { } // Append a string of @a size characters to the end of the buffer. void AppendString(const char* str, size_t size) { - size_t bytes_to_copy = capacity_ - size_; + size_t bytes_to_copy = Capacity - size_; if (size < bytes_to_copy) bytes_to_copy = size; memcpy(buffer_ + size_, str, bytes_to_copy); size_ += bytes_to_copy; @@ -88,9 +85,8 @@ class Buffer { } private: - char* buffer_; - size_t capacity_; size_t size_; + char buffer_[Capacity]; DELETE_COPY_AND_MOVE_OPERATORS(Buffer); }; diff --git a/osaf/libs/core/cplusplus/base/log_message.cc b/osaf/libs/core/cplusplus/base/log_message.cc --- a/osaf/libs/core/cplusplus/base/log_message.cc +++ b/osaf/libs/core/cplusplus/base/log_message.cc @@ -16,115 +16,9 @@ */ #include "osaf/libs/core/cplusplus/base/log_message.h" -#include <time.h> -#include <cstdint> -#include "osaf/libs/core/common/include/osaf_time.h" -#include "osaf/libs/core/cplusplus/base/buffer.h" -#include "osaf/libs/core/cplusplus/base/time.h" namespace base { const struct timespec LogMessage::kNullTime{0, -1}; -void LogMessage::Write(Facility facility, Severity severity, - const struct timespec& time_stamp, - const HostName& host_name, - const AppName& app_name, - const ProcId& proc_id, - const MsgId& msg_id, - const StructuredElements& structured_elements, - const std::string& message, - Buffer* buffer) { - uint32_t priority = static_cast<uint32_t>(facility) * uint32_t{8} - + static_cast<uint32_t>(severity); - buffer->AppendChar('<'); - buffer->AppendNumber(priority, 100); - buffer->AppendString(">1 ", 3); - WriteTime(time_stamp, buffer); - buffer->AppendChar(' '); - buffer->AppendString(host_name.data(), host_name.size()); - buffer->AppendChar(' '); - buffer->AppendString(app_name.data(), app_name.size()); - buffer->AppendChar(' '); - buffer->AppendString(proc_id.data(), proc_id.size()); - buffer->AppendChar(' '); - buffer->AppendString(msg_id.data(), msg_id.size()); - buffer->AppendChar(' '); - if (structured_elements.empty()) { - buffer->AppendChar('-'); - } else { - for (const auto& elem : structured_elements) elem.Write(buffer); - } - if (!message.empty()) { - buffer->AppendChar(' '); - buffer->AppendString(message.data(), message.size()); - } -} - -void LogMessage::WriteTime(const struct timespec& ts, Buffer* buffer) { - struct tm local_time; - struct tm* local_ptr = localtime_r(&ts.tv_sec, &local_time); - if (local_ptr != nullptr && local_ptr->tm_year >= -1900 - && local_ptr->tm_year <= (9999 - 1900) - && ts.tv_nsec >= 0 && ts.tv_nsec < kNanosPerSec) { - buffer->AppendFixedWidthNumber(local_ptr->tm_year + 1900, 1000); - buffer->AppendChar('-'); - buffer->AppendFixedWidthNumber(local_ptr->tm_mon + 1, 10); - buffer->AppendChar('-'); - buffer->AppendFixedWidthNumber(local_ptr->tm_mday, 10); - buffer->AppendChar('T'); - buffer->AppendFixedWidthNumber(local_ptr->tm_hour, 10); - buffer->AppendChar(':'); - buffer->AppendFixedWidthNumber(local_ptr->tm_min, 10); - buffer->AppendChar(':'); - buffer->AppendFixedWidthNumber(local_ptr->tm_sec, 10); - uint32_t decimals = ts.tv_nsec / 1000; - if (decimals != 0) { - uint32_t power = 100000; - while (decimals % 10 == 0) { - decimals /= 10; - power /= 10; - } - buffer->AppendChar('.'); - buffer->AppendFixedWidthNumber(decimals, power); - } - char* buf = buffer->end(); - if ((buffer->capacity() - buffer->size()) >= 6 && - strftime(buf, 6, "%z", local_ptr) == 5) { - if (buf[1] != '0' || buf[2] != '0' || - buf[3] != '0' || buf[4] != '0') { - buf[5] = buf[4]; - buf[4] = buf[3]; - buf[3] = ':'; - buffer->set_size(buffer->size() + 6); - } else { - buffer->AppendChar('Z'); - } - } - } else { - buffer->AppendChar('-'); - } -} - -void LogMessage::Element::Write(Buffer* buffer) const { - buffer->AppendChar('['); - buffer->AppendString(id_.data(), id_.size()); - for (const Parameter& param : parameter_list_) { - buffer->AppendChar(' '); - param.Write(buffer); - } - buffer->AppendChar(']'); -} - -void LogMessage::Parameter::Write(Buffer* buffer) const { - buffer->AppendString(name_.data(), name_.size()); - buffer->AppendChar('='); - buffer->AppendChar('"'); - for (const char& c : value_) { - if (c == '"' || c == '\\' || c == ']') buffer->AppendChar('\\'); - buffer->AppendChar(c); - } - buffer->AppendChar('"'); -} - } // namespace base diff --git a/osaf/libs/core/cplusplus/base/log_message.h b/osaf/libs/core/cplusplus/base/log_message.h --- a/osaf/libs/core/cplusplus/base/log_message.h +++ b/osaf/libs/core/cplusplus/base/log_message.h @@ -18,13 +18,19 @@ #ifndef OSAF_LIBS_CORE_CPLUSPLUS_BASE_LOG_MESSAGE_H_ #define OSAF_LIBS_CORE_CPLUSPLUS_BASE_LOG_MESSAGE_H_ +#include <time.h> +#include <cstddef> +#include <cstdint> #include <list> #include <set> #include <string> +#include "osaf/libs/core/common/include/osaf_time.h" +#include "osaf/libs/core/cplusplus/base/buffer.h" +#include "osaf/libs/core/cplusplus/base/time.h" namespace base { -class Buffer; +template <size_t Capacity> class Buffer; // The LogMessage class implements support for formatting log records according // to RFC 5424 @@ -135,7 +141,8 @@ class LogMessage { Parameter(const SdName& name, const std::string& value) : name_{name}, value_{value} {} - void Write(Buffer* buffer) const; + template <size_t Capacity> + void Write(Buffer<Capacity>* buffer) const; bool operator==(const Parameter& param) const { return name_ == param.name_ && value_ == param.value_; } @@ -153,7 +160,8 @@ class LogMessage { const ParameterList& parameter_list) : id_{id}, parameter_list_{parameter_list} {} - void Write(Buffer* buffer) const; + template <size_t Capacity> + void Write(Buffer<Capacity>* buffer) const; bool operator<(const Element& elem) const { return id_ < elem.id_; } bool operator==(const Element& elem) const { return id_ == elem.id_ && parameter_list_ == elem.parameter_list_; @@ -169,6 +177,7 @@ class LogMessage { static const struct timespec kNullTime; // Format a log record according to rfc5424 and write it to the provided // buffer. + template <size_t Capacity> static void Write(Facility facility, Severity severity, const struct timespec& time_stamp, const HostName& host_name, @@ -177,10 +186,117 @@ class LogMessage { const MsgId& msg_id, const StructuredElements& structured_elements, const std::string& message, - Buffer* buffer); - static void WriteTime(const struct timespec& ts, Buffer* buffer); + Buffer<Capacity>* buffer); + template <size_t Capacity> + static void WriteTime(const struct timespec& ts, Buffer<Capacity>* buffer); }; +template <size_t Capacity> +void LogMessage::Write(Facility facility, Severity severity, + const struct timespec& time_stamp, + const HostName& host_name, + const AppName& app_name, + const ProcId& proc_id, + const MsgId& msg_id, + const StructuredElements& structured_elements, + const std::string& message, + Buffer<Capacity>* buffer) { + uint32_t priority = static_cast<uint32_t>(facility) * uint32_t{8} + + static_cast<uint32_t>(severity); + buffer->AppendChar('<'); + buffer->AppendNumber(priority, 100); + buffer->AppendString(">1 ", 3); + WriteTime(time_stamp, buffer); + buffer->AppendChar(' '); + buffer->AppendString(host_name.data(), host_name.size()); + buffer->AppendChar(' '); + buffer->AppendString(app_name.data(), app_name.size()); + buffer->AppendChar(' '); + buffer->AppendString(proc_id.data(), proc_id.size()); + buffer->AppendChar(' '); + buffer->AppendString(msg_id.data(), msg_id.size()); + buffer->AppendChar(' '); + if (structured_elements.empty()) { + buffer->AppendChar('-'); + } else { + for (const auto& elem : structured_elements) elem.Write(buffer); + } + if (!message.empty()) { + buffer->AppendChar(' '); + buffer->AppendString(message.data(), message.size()); + } +} + +template <size_t Capacity> +void LogMessage::WriteTime(const struct timespec& ts, + Buffer<Capacity>* buffer) { + struct tm local_time; + struct tm* local_ptr = localtime_r(&ts.tv_sec, &local_time); + if (local_ptr != nullptr && local_ptr->tm_year >= -1900 + && local_ptr->tm_year <= (9999 - 1900) + && ts.tv_nsec >= 0 && ts.tv_nsec < kNanosPerSec) { + buffer->AppendFixedWidthNumber(local_ptr->tm_year + 1900, 1000); + buffer->AppendChar('-'); + buffer->AppendFixedWidthNumber(local_ptr->tm_mon + 1, 10); + buffer->AppendChar('-'); + buffer->AppendFixedWidthNumber(local_ptr->tm_mday, 10); + buffer->AppendChar('T'); + buffer->AppendFixedWidthNumber(local_ptr->tm_hour, 10); + buffer->AppendChar(':'); + buffer->AppendFixedWidthNumber(local_ptr->tm_min, 10); + buffer->AppendChar(':'); + buffer->AppendFixedWidthNumber(local_ptr->tm_sec, 10); + uint32_t decimals = ts.tv_nsec / 1000; + if (decimals != 0) { + uint32_t power = 100000; + while (decimals % 10 == 0) { + decimals /= 10; + power /= 10; + } + buffer->AppendChar('.'); + buffer->AppendFixedWidthNumber(decimals, power); + } + char* buf = buffer->end(); + if ((buffer->capacity() - buffer->size()) >= 6 && + strftime(buf, 6, "%z", local_ptr) == 5) { + if (buf[1] != '0' || buf[2] != '0' || + buf[3] != '0' || buf[4] != '0') { + buf[5] = buf[4]; + buf[4] = buf[3]; + buf[3] = ':'; + buffer->set_size(buffer->size() + 6); + } else { + buffer->AppendChar('Z'); + } + } + } else { + buffer->AppendChar('-'); + } +} + +template <size_t Capacity> +void LogMessage::Element::Write(Buffer<Capacity>* buffer) const { + buffer->AppendChar('['); + buffer->AppendString(id_.data(), id_.size()); + for (const Parameter& param : parameter_list_) { + buffer->AppendChar(' '); + param.Write(buffer); + } + buffer->AppendChar(']'); +} + +template <size_t Capacity> +void LogMessage::Parameter::Write(Buffer<Capacity>* buffer) const { + buffer->AppendString(name_.data(), name_.size()); + buffer->AppendChar('='); + buffer->AppendChar('"'); + for (const char& c : value_) { + if (c == '"' || c == '\\' || c == ']') buffer->AppendChar('\\'); + buffer->AppendChar(c); + } + buffer->AppendChar('"'); +} + } // namespace base #endif // OSAF_LIBS_CORE_CPLUSPLUS_BASE_LOG_MESSAGE_H_ diff --git a/osaf/libs/core/cplusplus/base/tests/log_message_test.cc b/osaf/libs/core/cplusplus/base/tests/log_message_test.cc --- a/osaf/libs/core/cplusplus/base/tests/log_message_test.cc +++ b/osaf/libs/core/cplusplus/base/tests/log_message_test.cc @@ -39,7 +39,7 @@ static const char null_text[] = "<0>1 - TEST(LogMessageTest, WriteHelloWorld1) { setenv("TZ", "Europe/Stockholm", 1); tzset(); - base::Buffer buf{256}; + base::Buffer<256> buf{}; base::LogMessage::Write( base::LogMessage::Facility::kLocal0, base::LogMessage::Severity::kNotice, @@ -66,7 +66,7 @@ TEST(LogMessageTest, WriteHelloWorld1) { TEST(LogMessageTest, WriteHelloWorld2) { setenv("TZ", "Europe/Stockholm", 1); tzset(); - base::Buffer buf{256}; + base::Buffer<256> buf{}; base::LogMessage::Write( base::LogMessage::Facility::kLocal7, base::LogMessage::Severity::kDebug, @@ -93,7 +93,7 @@ TEST(LogMessageTest, WriteHelloWorld2) { TEST(LogMessageTest, WriteNullMessage) { setenv("TZ", "Europe/Stockholm", 1); tzset(); - base::Buffer buf(256); + base::Buffer<256> buf{}; base::LogMessage::Write( base::LogMessage::Facility::kKern, base::LogMessage::Severity::kEmerg, @@ -116,7 +116,7 @@ TEST(LogMessageTest, WriteNullMessage) { TEST(LogMessageTimeTest, WriteBCTime) { setenv("TZ", "Europe/Stockholm", 1); tzset(); - base::Buffer buf(256); + base::Buffer<256> buf{}; base::LogMessage::WriteTime({-62188992000, 0}, &buf); EXPECT_EQ(buf.size(), 1); EXPECT_EQ(memcmp(buf.data(), "-", 1), 0); @@ -125,7 +125,7 @@ TEST(LogMessageTimeTest, WriteBCTime) { TEST(LogMessageTimeTest, WriteFarFutureTime) { setenv("TZ", "Europe/Stockholm", 1); tzset(); - base::Buffer buf(256); + base::Buffer<256> buf{}; base::LogMessage::WriteTime({253423296000, 0}, &buf); EXPECT_EQ(buf.size(), 1); EXPECT_EQ(memcmp(buf.data(), "-", 1), 0); @@ -136,7 +136,7 @@ TEST(LogMessageTimeTest, WriteTimeInSmal static const char expected_result[] = "2016-10-10T16:24:02.505489"; setenv("TZ", "Europe/Stockholm", 1); tzset(); - base::Buffer buf(30); + base::Buffer<30> buf{}; base::LogMessage::WriteTime({1476109442, 505489184}, &buf); EXPECT_EQ(buf.size(), sizeof(expected_result) - 1); EXPECT_EQ(memcmp(buf.data(), expected_result, buf.size()), 0); @@ -146,7 +146,7 @@ TEST(LogMessageTimeTest, WriteTimeWithUt static const char expected_result[] = "2016-10-10T14:33:32.82328Z"; setenv("TZ", "UTC", 1); tzset(); - base::Buffer buf(256); + base::Buffer<256> buf{}; base::LogMessage::WriteTime({1476110012, 823280288}, &buf); EXPECT_EQ(buf.size(), sizeof(expected_result) - 1); EXPECT_EQ(memcmp(buf.data(), expected_result, buf.size()), 0); diff --git a/osaf/libs/core/mds/mds_log.cc b/osaf/libs/core/mds/mds_log.cc --- a/osaf/libs/core/mds/mds_log.cc +++ b/osaf/libs/core/mds/mds_log.cc @@ -59,7 +59,7 @@ class MdsLog { base::LogMessage::AppName app_name_; base::LogMessage::ProcId proc_id_; uint64_t msg_id_; - base::Buffer buffer_; + base::Buffer<512> buffer_; base::UnixClientSocket log_socket_; DELETE_COPY_AND_MOVE_OPERATORS(MdsLog); @@ -75,7 +75,7 @@ MdsLog::MdsLog(const char* host_name, co app_name_{base::LogMessage::AppName{app_name}}, proc_id_{base::LogMessage::ProcId{std::to_string(proc_id)}}, msg_id_{0}, - buffer_{512}, + buffer_{}, log_socket_{socket_name} { pthread_mutexattr_t attr; int result = pthread_mutexattr_init(&attr); ------------------------------------------------------------------------------ Developer Access Program for Intel Xeon Phi Processors Access to Intel Xeon Phi processor-based developer platforms. With one year of Intel Parallel Studio XE. Training and support from Colfax. Order your platform today. http://sdm.link/xeonphi _______________________________________________ Opensaf-devel mailing list Opensaf-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensaf-devel