You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by al...@apache.org on 2016/10/13 15:07:28 UTC
[10/18] nifi-minifi-cpp git commit: MINIFI-34 Establishing CMake
build system to provide build functionality equivalent to pre-existing
Makefile.
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/b02af540/include/spdlog/details/line_logger.h
----------------------------------------------------------------------
diff --git a/include/spdlog/details/line_logger.h b/include/spdlog/details/line_logger.h
new file mode 100644
index 0000000..80d7cc1
--- /dev/null
+++ b/include/spdlog/details/line_logger.h
@@ -0,0 +1,221 @@
+/*************************************************************************/
+/* spdlog - an extremely fast and easy to use c++11 logging library. */
+/* Copyright (c) 2014 Gabi Melman. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#pragma once
+#include <type_traits>
+#include "../common.h"
+#include "../logger.h"
+
+// Line logger class - aggregates operator<< calls to fast ostream
+// and logs upon destruction
+
+namespace spdlog
+{
+namespace details
+{
+class line_logger
+{
+public:
+ line_logger(logger* callback_logger, level::level_enum msg_level, bool enabled):
+ _callback_logger(callback_logger),
+ _log_msg(msg_level),
+ _enabled(enabled)
+ {}
+
+ // No copy intended. Only move
+ line_logger(const line_logger& other) = delete;
+ line_logger& operator=(const line_logger&) = delete;
+ line_logger& operator=(line_logger&&) = delete;
+
+
+ line_logger(line_logger&& other) :
+ _callback_logger(other._callback_logger),
+ _log_msg(std::move(other._log_msg)),
+ _enabled(other._enabled)
+ {
+ other.disable();
+ }
+
+ //Log the log message using the callback logger
+ ~line_logger()
+ {
+ if (_enabled)
+ {
+#ifndef SPDLOG_NO_NAME
+ _log_msg.logger_name = _callback_logger->name();
+#endif
+#ifndef SPDLOG_NO_DATETIME
+ _log_msg.time = os::now();
+#endif
+
+#ifndef SPDLOG_NO_THREAD_ID
+ _log_msg.thread_id = os::thread_id();
+#endif
+ _callback_logger->_log_msg(_log_msg);
+ }
+ }
+
+ //
+ // Support for format string with variadic args
+ //
+
+
+ void write(const char* what)
+ {
+ if (_enabled)
+ _log_msg.raw << what;
+ }
+
+ template <typename... Args>
+ void write(const char* fmt, const Args&... args)
+ {
+ if (!_enabled)
+ return;
+ try
+ {
+ _log_msg.raw.write(fmt, args...);
+ }
+ catch (const fmt::FormatError& e)
+ {
+ throw spdlog_ex(fmt::format("formatting error while processing format string '{}': {}", fmt, e.what()));
+ }
+ }
+
+
+ //
+ // Support for operator<<
+ //
+ line_logger& operator<<(const char* what)
+ {
+ if (_enabled)
+ _log_msg.raw << what;
+ return *this;
+ }
+
+ line_logger& operator<<(const std::string& what)
+ {
+ if (_enabled)
+ _log_msg.raw << what;
+ return *this;
+ }
+
+ line_logger& operator<<(int what)
+ {
+ if (_enabled)
+ _log_msg.raw << what;
+ return *this;
+ }
+
+ line_logger& operator<<(unsigned int what)
+ {
+ if (_enabled)
+ _log_msg.raw << what;
+ return *this;
+ }
+
+
+ line_logger& operator<<(long what)
+ {
+ if (_enabled)
+ _log_msg.raw << what;
+ return *this;
+ }
+
+ line_logger& operator<<(unsigned long what)
+ {
+ if (_enabled)
+ _log_msg.raw << what;
+ return *this;
+ }
+
+ line_logger& operator<<(long long what)
+ {
+ if (_enabled)
+ _log_msg.raw << what;
+ return *this;
+ }
+
+ line_logger& operator<<(unsigned long long what)
+ {
+ if (_enabled)
+ _log_msg.raw << what;
+ return *this;
+ }
+
+ line_logger& operator<<(double what)
+ {
+ if (_enabled)
+ _log_msg.raw << what;
+ return *this;
+ }
+
+ line_logger& operator<<(long double what)
+ {
+ if (_enabled)
+ _log_msg.raw << what;
+ return *this;
+ }
+
+ line_logger& operator<<(float what)
+ {
+ if (_enabled)
+ _log_msg.raw << what;
+ return *this;
+ }
+
+ line_logger& operator<<(char what)
+ {
+ if (_enabled)
+ _log_msg.raw << what;
+ return *this;
+ }
+
+ //Support user types which implements operator<<
+ template<typename T>
+ line_logger& operator<<(const T& what)
+ {
+ if (_enabled)
+ _log_msg.raw.write("{}", what);
+ return *this;
+ }
+
+
+ void disable()
+ {
+ _enabled = false;
+ }
+
+ bool is_enabled() const
+ {
+ return _enabled;
+ }
+
+
+private:
+ logger* _callback_logger;
+ log_msg _log_msg;
+ bool _enabled;
+};
+} //Namespace details
+} // Namespace spdlog
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/b02af540/include/spdlog/details/log_msg.h
----------------------------------------------------------------------
diff --git a/include/spdlog/details/log_msg.h b/include/spdlog/details/log_msg.h
new file mode 100644
index 0000000..bf58aca
--- /dev/null
+++ b/include/spdlog/details/log_msg.h
@@ -0,0 +1,98 @@
+/*************************************************************************/
+/* spdlog - an extremely fast and easy to use c++11 logging library. */
+/* Copyright (c) 2014 Gabi Melman. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#pragma once
+
+#include <thread>
+#include "../common.h"
+#include "./format.h"
+
+namespace spdlog
+{
+namespace details
+{
+struct log_msg
+{
+ log_msg() = default;
+ log_msg(level::level_enum l):
+ logger_name(),
+ level(l),
+ raw(),
+ formatted() {}
+
+
+ log_msg(const log_msg& other) :
+ logger_name(other.logger_name),
+ level(other.level),
+ time(other.time),
+ thread_id(other.thread_id)
+ {
+ if (other.raw.size())
+ raw << fmt::BasicStringRef<char>(other.raw.data(), other.raw.size());
+ if (other.formatted.size())
+ formatted << fmt::BasicStringRef<char>(other.formatted.data(), other.formatted.size());
+ }
+
+ log_msg(log_msg&& other) :
+ logger_name(std::move(other.logger_name)),
+ level(other.level),
+ time(std::move(other.time)),
+ thread_id(other.thread_id),
+ raw(std::move(other.raw)),
+ formatted(std::move(other.formatted))
+ {
+ other.clear();
+ }
+
+ log_msg& operator=(log_msg&& other)
+ {
+ if (this == &other)
+ return *this;
+
+ logger_name = std::move(other.logger_name);
+ level = other.level;
+ time = std::move(other.time);
+ thread_id = other.thread_id;
+ raw = std::move(other.raw);
+ formatted = std::move(other.formatted);
+ other.clear();
+ return *this;
+ }
+
+ void clear()
+ {
+ level = level::off;
+ raw.clear();
+ formatted.clear();
+ }
+
+ std::string logger_name;
+ level::level_enum level;
+ log_clock::time_point time;
+ size_t thread_id;
+ fmt::MemoryWriter raw;
+ fmt::MemoryWriter formatted;
+};
+}
+}
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/b02af540/include/spdlog/details/logger_impl.h
----------------------------------------------------------------------
diff --git a/include/spdlog/details/logger_impl.h b/include/spdlog/details/logger_impl.h
new file mode 100644
index 0000000..d658ac0
--- /dev/null
+++ b/include/spdlog/details/logger_impl.h
@@ -0,0 +1,320 @@
+/*************************************************************************/
+/* spdlog - an extremely fast and easy to use c++11 logging library. */
+/* Copyright (c) 2014 Gabi Melman. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#pragma once
+//
+// Logger implementation
+//
+
+#include "./line_logger.h"
+
+
+// create logger with given name, sinks and the default pattern formatter
+// all other ctors will call this one
+template<class It>
+inline spdlog::logger::logger(const std::string& logger_name, const It& begin, const It& end) :
+ _name(logger_name),
+ _sinks(begin, end),
+ _formatter(std::make_shared<pattern_formatter>("%+"))
+{
+
+ // no support under vs2013 for member initialization for std::atomic
+ _level = level::info;
+}
+
+// ctor with sinks as init list
+inline spdlog::logger::logger(const std::string& logger_name, sinks_init_list sinks_list) :
+ logger(logger_name, sinks_list.begin(), sinks_list.end()) {}
+
+
+// ctor with single sink
+inline spdlog::logger::logger(const std::string& logger_name, spdlog::sink_ptr single_sink) :
+ logger(logger_name, {
+ single_sink
+}) {}
+
+
+inline spdlog::logger::~logger() = default;
+
+
+inline void spdlog::logger::set_formatter(spdlog::formatter_ptr msg_formatter)
+{
+ _set_formatter(msg_formatter);
+}
+
+inline void spdlog::logger::set_pattern(const std::string& pattern)
+{
+ _set_pattern(pattern);
+}
+
+//
+// log only if given level>=logger's log level
+//
+
+
+template <typename... Args>
+inline spdlog::details::line_logger spdlog::logger::_log_if_enabled(level::level_enum lvl, const char* fmt, const Args&... args)
+{
+ bool msg_enabled = should_log(lvl);
+ details::line_logger l(this, lvl, msg_enabled);
+ l.write(fmt, args...);
+ return l;
+}
+
+inline spdlog::details::line_logger spdlog::logger::_log_if_enabled(level::level_enum lvl)
+{
+ return details::line_logger(this, lvl, should_log(lvl));
+}
+
+template<typename T>
+inline spdlog::details::line_logger spdlog::logger::_log_if_enabled(level::level_enum lvl, const T& msg)
+{
+ bool msg_enabled = should_log(lvl);
+ details::line_logger l(this, lvl, msg_enabled);
+ l << msg;
+ return l;
+}
+
+//
+// logger.info(cppformat_string, arg1, arg2, arg3, ...) call style
+//
+template <typename... Args>
+inline spdlog::details::line_logger spdlog::logger::trace(const char* fmt, const Args&... args)
+{
+ return _log_if_enabled(level::trace, fmt, args...);
+}
+
+template <typename... Args>
+inline spdlog::details::line_logger spdlog::logger::debug(const char* fmt, const Args&... args)
+{
+ return _log_if_enabled(level::debug, fmt, args...);
+}
+
+template <typename... Args>
+inline spdlog::details::line_logger spdlog::logger::info(const char* fmt, const Args&... args)
+{
+ return _log_if_enabled(level::info, fmt, args...);
+}
+
+template <typename... Args>
+inline spdlog::details::line_logger spdlog::logger::notice(const char* fmt, const Args&... args)
+{
+ return _log_if_enabled(level::notice, fmt, args...);
+}
+
+template <typename... Args>
+inline spdlog::details::line_logger spdlog::logger::warn(const char* fmt, const Args&... args)
+{
+ return _log_if_enabled(level::warn, fmt, args...);
+}
+
+template <typename... Args>
+inline spdlog::details::line_logger spdlog::logger::error(const char* fmt, const Args&... args)
+{
+ return _log_if_enabled(level::err, fmt, args...);
+}
+
+template <typename... Args>
+inline spdlog::details::line_logger spdlog::logger::critical(const char* fmt, const Args&... args)
+{
+ return _log_if_enabled(level::critical, fmt, args...);
+}
+
+template <typename... Args>
+inline spdlog::details::line_logger spdlog::logger::alert(const char* fmt, const Args&... args)
+{
+ return _log_if_enabled(level::alert, fmt, args...);
+}
+
+template <typename... Args>
+inline spdlog::details::line_logger spdlog::logger::emerg(const char* fmt, const Args&... args)
+{
+ return _log_if_enabled(level::emerg, fmt, args...);
+}
+
+//
+// logger.info(msg) << ".." call style
+//
+template<typename T>
+inline spdlog::details::line_logger spdlog::logger::trace(const T& msg)
+{
+ return _log_if_enabled(level::trace, msg);
+}
+
+template<typename T>
+inline spdlog::details::line_logger spdlog::logger::debug(const T& msg)
+{
+ return _log_if_enabled(level::debug, msg);
+}
+
+
+template<typename T>
+inline spdlog::details::line_logger spdlog::logger::info(const T& msg)
+{
+ return _log_if_enabled(level::info, msg);
+}
+
+template<typename T>
+inline spdlog::details::line_logger spdlog::logger::notice(const T& msg)
+{
+ return _log_if_enabled(level::notice, msg);
+}
+
+template<typename T>
+inline spdlog::details::line_logger spdlog::logger::warn(const T& msg)
+{
+ return _log_if_enabled(level::warn, msg);
+}
+
+template<typename T>
+inline spdlog::details::line_logger spdlog::logger::error(const T& msg)
+{
+ return _log_if_enabled(level::err, msg);
+}
+
+template<typename T>
+inline spdlog::details::line_logger spdlog::logger::critical(const T& msg)
+{
+ return _log_if_enabled(level::critical, msg);
+}
+
+template<typename T>
+inline spdlog::details::line_logger spdlog::logger::alert(const T& msg)
+{
+ return _log_if_enabled(level::alert, msg);
+}
+
+template<typename T>
+inline spdlog::details::line_logger spdlog::logger::emerg(const T& msg)
+{
+ return _log_if_enabled(level::emerg, msg);
+}
+
+
+
+
+//
+// logger.info() << ".." call style
+//
+inline spdlog::details::line_logger spdlog::logger::trace()
+{
+ return _log_if_enabled(level::trace);
+}
+
+inline spdlog::details::line_logger spdlog::logger::debug()
+{
+ return _log_if_enabled(level::debug);
+}
+
+inline spdlog::details::line_logger spdlog::logger::info()
+{
+ return _log_if_enabled(level::info);
+}
+
+inline spdlog::details::line_logger spdlog::logger::notice()
+{
+ return _log_if_enabled(level::notice);
+}
+
+inline spdlog::details::line_logger spdlog::logger::warn()
+{
+ return _log_if_enabled(level::warn);
+}
+
+inline spdlog::details::line_logger spdlog::logger::error()
+{
+ return _log_if_enabled(level::err);
+}
+
+inline spdlog::details::line_logger spdlog::logger::critical()
+{
+ return _log_if_enabled(level::critical);
+}
+
+inline spdlog::details::line_logger spdlog::logger::alert()
+{
+ return _log_if_enabled(level::alert);
+}
+
+inline spdlog::details::line_logger spdlog::logger::emerg()
+{
+ return _log_if_enabled(level::emerg);
+}
+
+
+// always log, no matter what is the actual logger's log level
+template <typename... Args>
+inline spdlog::details::line_logger spdlog::logger::force_log(level::level_enum lvl, const char* fmt, const Args&... args)
+{
+ details::line_logger l(this, lvl, true);
+ l.write(fmt, args...);
+ return l;
+}
+
+//
+// name and level
+//
+inline const std::string& spdlog::logger::name() const
+{
+ return _name;
+}
+
+inline void spdlog::logger::set_level(spdlog::level::level_enum log_level)
+{
+ _level.store(log_level);
+}
+
+inline spdlog::level::level_enum spdlog::logger::level() const
+{
+ return static_cast<spdlog::level::level_enum>(_level.load(std::memory_order_relaxed));
+}
+
+inline bool spdlog::logger::should_log(spdlog::level::level_enum msg_level) const
+{
+ return msg_level >= _level.load(std::memory_order_relaxed);
+}
+
+//
+// protected virtual called at end of each user log call (if enabled) by the line_logger
+//
+inline void spdlog::logger::_log_msg(details::log_msg& msg)
+{
+ _formatter->format(msg);
+ for (auto &sink : _sinks)
+ sink->log(msg);
+}
+
+inline void spdlog::logger::_set_pattern(const std::string& pattern)
+{
+ _formatter = std::make_shared<pattern_formatter>(pattern);
+}
+inline void spdlog::logger::_set_formatter(formatter_ptr msg_formatter)
+{
+ _formatter = msg_formatter;
+}
+
+inline void spdlog::logger::flush() {
+ for (auto& sink : _sinks)
+ sink->flush();
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/b02af540/include/spdlog/details/mpmc_bounded_q.h
----------------------------------------------------------------------
diff --git a/include/spdlog/details/mpmc_bounded_q.h b/include/spdlog/details/mpmc_bounded_q.h
new file mode 100644
index 0000000..7cbcfd7
--- /dev/null
+++ b/include/spdlog/details/mpmc_bounded_q.h
@@ -0,0 +1,175 @@
+/*
+A modified version of Bounded MPMC queue by Dmitry Vyukov.
+
+Original code from:
+http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue
+
+licensed by Dmitry Vyukov under the terms below:
+
+Simplified BSD license
+
+Copyright (c) 2010-2011 Dmitry Vyukov. All rights reserved.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+1. Redistributions of source code must retain the above copyright notice, this list of
+conditions and the following disclaimer.
+
+2. 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.
+
+THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "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 DMITRY VYUKOV 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.
+
+The views and conclusions contained in the software and documentation are those of the authors and
+should not be interpreted as representing official policies, either expressed or implied, of Dmitry Vyukov.
+*/
+
+/*
+The code in its current form adds the license below:
+
+spdlog - an extremely fast and easy to use c++11 logging library.
+Copyright (c) 2014 Gabi Melman.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#pragma once
+
+#include <atomic>
+#include "../common.h"
+
+namespace spdlog
+{
+namespace details
+{
+
+template<typename T>
+class mpmc_bounded_queue
+{
+public:
+
+ using item_type = T;
+ mpmc_bounded_queue(size_t buffer_size)
+ : buffer_(new cell_t [buffer_size]),
+ buffer_mask_(buffer_size - 1)
+ {
+ //queue size must be power of two
+ if(!((buffer_size >= 2) && ((buffer_size & (buffer_size - 1)) == 0)))
+ throw spdlog_ex("async logger queue size must be power of two");
+
+ for (size_t i = 0; i != buffer_size; i += 1)
+ buffer_[i].sequence_.store(i, std::memory_order_relaxed);
+ enqueue_pos_.store(0, std::memory_order_relaxed);
+ dequeue_pos_.store(0, std::memory_order_relaxed);
+ }
+
+ ~mpmc_bounded_queue()
+ {
+ delete [] buffer_;
+ }
+
+
+ bool enqueue(T&& data)
+ {
+ cell_t* cell;
+ size_t pos = enqueue_pos_.load(std::memory_order_relaxed);
+ for (;;)
+ {
+ cell = &buffer_[pos & buffer_mask_];
+ size_t seq = cell->sequence_.load(std::memory_order_acquire);
+ intptr_t dif = (intptr_t)seq - (intptr_t)pos;
+ if (dif == 0)
+ {
+ if (enqueue_pos_.compare_exchange_weak(pos, pos + 1, std::memory_order_relaxed))
+ break;
+ }
+ else if (dif < 0)
+ {
+ return false;
+ }
+ else
+ {
+ pos = enqueue_pos_.load(std::memory_order_relaxed);
+ }
+ }
+ cell->data_ = std::move(data);
+ cell->sequence_.store(pos + 1, std::memory_order_release);
+ return true;
+ }
+
+ bool dequeue(T& data)
+ {
+ cell_t* cell;
+ size_t pos = dequeue_pos_.load(std::memory_order_relaxed);
+ for (;;)
+ {
+ cell = &buffer_[pos & buffer_mask_];
+ size_t seq =
+ cell->sequence_.load(std::memory_order_acquire);
+ intptr_t dif = (intptr_t)seq - (intptr_t)(pos + 1);
+ if (dif == 0)
+ {
+ if (dequeue_pos_.compare_exchange_weak(pos, pos + 1, std::memory_order_relaxed))
+ break;
+ }
+ else if (dif < 0)
+ return false;
+ else
+ pos = dequeue_pos_.load(std::memory_order_relaxed);
+ }
+ data = std::move(cell->data_);
+ cell->sequence_.store(pos + buffer_mask_ + 1, std::memory_order_release);
+ return true;
+ }
+
+private:
+ struct cell_t
+ {
+ std::atomic<size_t> sequence_;
+ T data_;
+ };
+
+ static size_t const cacheline_size = 64;
+ typedef char cacheline_pad_t [cacheline_size];
+
+ cacheline_pad_t pad0_;
+ cell_t* const buffer_;
+ size_t const buffer_mask_;
+ cacheline_pad_t pad1_;
+ std::atomic<size_t> enqueue_pos_;
+ cacheline_pad_t pad2_;
+ std::atomic<size_t> dequeue_pos_;
+ cacheline_pad_t pad3_;
+
+ mpmc_bounded_queue(mpmc_bounded_queue const&);
+ void operator = (mpmc_bounded_queue const&);
+};
+
+} // ns details
+} // ns spdlog
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/b02af540/include/spdlog/details/null_mutex.h
----------------------------------------------------------------------
diff --git a/include/spdlog/details/null_mutex.h b/include/spdlog/details/null_mutex.h
new file mode 100644
index 0000000..ebb56a5
--- /dev/null
+++ b/include/spdlog/details/null_mutex.h
@@ -0,0 +1,43 @@
+/*************************************************************************/
+/* spdlog - an extremely fast and easy to use c++11 logging library. */
+/* Copyright (c) 2014 Gabi Melman. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#pragma once
+
+// null, no cost mutex
+
+namespace spdlog
+{
+namespace details
+{
+struct null_mutex
+{
+ void lock() {}
+ void unlock() {}
+ bool try_lock()
+ {
+ return true;
+ }
+};
+}
+}
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/b02af540/include/spdlog/details/os.h
----------------------------------------------------------------------
diff --git a/include/spdlog/details/os.h b/include/spdlog/details/os.h
new file mode 100644
index 0000000..753b6d9
--- /dev/null
+++ b/include/spdlog/details/os.h
@@ -0,0 +1,198 @@
+/*************************************************************************/
+/* spdlog - an extremely fast and easy to use c++11 logging library. */
+/* Copyright (c) 2014 Gabi Melman. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#pragma once
+#include<string>
+#include<cstdio>
+#include<ctime>
+
+#ifdef _WIN32
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
+# include <Windows.h>
+
+#ifdef __MINGW32__
+#include <share.h>
+#endif
+
+#elif __linux__
+#include <sys/syscall.h> //Use gettid() syscall under linux to get thread id
+#include <unistd.h>
+#else
+#include <thread>
+#endif
+
+#include "../common.h"
+
+namespace spdlog
+{
+namespace details
+{
+namespace os
+{
+
+inline spdlog::log_clock::time_point now()
+{
+
+#if defined __linux__ && defined SPDLOG_CLOCK_COARSE
+ timespec ts;
+ ::clock_gettime(CLOCK_REALTIME_COARSE, &ts);
+ return std::chrono::time_point<log_clock, typename log_clock::duration>(
+ std::chrono::duration_cast<typename log_clock::duration>(
+ std::chrono::seconds(ts.tv_sec) + std::chrono::nanoseconds(ts.tv_nsec)));
+
+#else
+ return log_clock::now();
+#endif
+
+}
+inline std::tm localtime(const std::time_t &time_tt)
+{
+
+#ifdef _WIN32
+ std::tm tm;
+ localtime_s(&tm, &time_tt);
+#else
+ std::tm tm;
+ localtime_r(&time_tt, &tm);
+#endif
+ return tm;
+}
+
+inline std::tm localtime()
+{
+ std::time_t now_t = time(nullptr);
+ return localtime(now_t);
+}
+
+
+inline std::tm gmtime(const std::time_t &time_tt)
+{
+
+#ifdef _WIN32
+ std::tm tm;
+ gmtime_s(&tm, &time_tt);
+#else
+ std::tm tm;
+ gmtime_r(&time_tt, &tm);
+#endif
+ return tm;
+}
+
+inline std::tm gmtime()
+{
+ std::time_t now_t = time(nullptr);
+ return gmtime(now_t);
+}
+inline bool operator==(const std::tm& tm1, const std::tm& tm2)
+{
+ return (tm1.tm_sec == tm2.tm_sec &&
+ tm1.tm_min == tm2.tm_min &&
+ tm1.tm_hour == tm2.tm_hour &&
+ tm1.tm_mday == tm2.tm_mday &&
+ tm1.tm_mon == tm2.tm_mon &&
+ tm1.tm_year == tm2.tm_year &&
+ tm1.tm_isdst == tm2.tm_isdst);
+}
+
+inline bool operator!=(const std::tm& tm1, const std::tm& tm2)
+{
+ return !(tm1 == tm2);
+}
+
+#ifdef _WIN32
+inline const char* eol()
+{
+ return "\r\n";
+}
+#else
+constexpr inline const char* eol()
+{
+ return "\n";
+}
+#endif
+
+#ifdef _WIN32
+inline unsigned short eol_size()
+{
+ return 2;
+}
+#else
+constexpr inline unsigned short eol_size()
+{
+ return 1;
+}
+#endif
+
+//fopen_s on non windows for writing
+inline int fopen_s(FILE** fp, const std::string& filename, const char* mode)
+{
+#ifdef _WIN32
+ *fp = _fsopen((filename.c_str()), mode, _SH_DENYWR);
+ return *fp == nullptr;
+#else
+ *fp = fopen((filename.c_str()), mode);
+ return *fp == nullptr;
+#endif
+
+
+}
+
+//Return utc offset in minutes or -1 on failure
+inline int utc_minutes_offset(const std::tm& tm = details::os::localtime())
+{
+
+#ifdef _WIN32
+ (void)tm; // avoid unused param warning
+ DYNAMIC_TIME_ZONE_INFORMATION tzinfo;
+ auto rv = GetDynamicTimeZoneInformation(&tzinfo);
+ if (!rv)
+ return -1;
+ return -1 * (tzinfo.Bias + tzinfo.DaylightBias);
+#else
+ return static_cast<int>(tm.tm_gmtoff / 60);
+#endif
+}
+
+//Return current thread id as size_t
+//It exists because the std::this_thread::get_id() is much slower(espcially under VS 2013)
+inline size_t thread_id()
+{
+#ifdef _WIN32
+ return static_cast<size_t>(::GetCurrentThreadId());
+#elif __linux__
+ return static_cast<size_t>(syscall(SYS_gettid));
+#else //Default to standard C++11 (OSX and other Unix)
+ return static_cast<size_t>(std::hash<std::thread::id>()(std::this_thread::get_id()));
+#endif
+
+}
+
+} //os
+} //details
+} //spdlog
+
+
+
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/b02af540/include/spdlog/details/pattern_formatter_impl.h
----------------------------------------------------------------------
diff --git a/include/spdlog/details/pattern_formatter_impl.h b/include/spdlog/details/pattern_formatter_impl.h
new file mode 100644
index 0000000..a5b2d21
--- /dev/null
+++ b/include/spdlog/details/pattern_formatter_impl.h
@@ -0,0 +1,628 @@
+/*************************************************************************/
+/* spdlog - an extremely fast and easy to use c++11 logging library. */
+/* Copyright (c) 2014 Gabi Melman. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#pragma once
+
+#include <string>
+#include <chrono>
+#include <memory>
+#include <vector>
+#include <thread>
+
+
+#include "../formatter.h"
+#include "./log_msg.h"
+#include "./os.h"
+
+namespace spdlog
+{
+namespace details
+{
+class flag_formatter
+{
+public:
+ virtual ~flag_formatter() {}
+ virtual void format(details::log_msg& msg, const std::tm& tm_time) = 0;
+};
+
+///////////////////////////////////////////////////////////////////////
+// name & level pattern appenders
+///////////////////////////////////////////////////////////////////////
+namespace
+{
+class name_formatter :public flag_formatter
+{
+ void format(details::log_msg& msg, const std::tm&) override
+ {
+ msg.formatted << msg.logger_name;
+ }
+};
+}
+
+// log level appender
+class level_formatter :public flag_formatter
+{
+ void format(details::log_msg& msg, const std::tm&) override
+ {
+ msg.formatted << level::to_str(msg.level);
+ }
+};
+
+// short log level appender
+class short_level_formatter :public flag_formatter
+{
+ void format(details::log_msg& msg, const std::tm&) override
+ {
+ msg.formatted << level::to_short_str(msg.level);
+ }
+};
+
+///////////////////////////////////////////////////////////////////////
+// Date time pattern appenders
+///////////////////////////////////////////////////////////////////////
+
+static const char* ampm(const tm& t)
+{
+ return t.tm_hour >= 12 ? "PM" : "AM";
+}
+
+static int to12h(const tm& t)
+{
+ return t.tm_hour > 12 ? t.tm_hour - 12 : t.tm_hour;
+}
+
+//Abbreviated weekday name
+static const std::string days[] { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
+class a_formatter :public flag_formatter
+{
+ void format(details::log_msg& msg, const std::tm& tm_time) override
+ {
+ msg.formatted << days[tm_time.tm_wday];
+ }
+};
+
+//Full weekday name
+static const std::string full_days[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
+class A_formatter :public flag_formatter
+{
+ void format(details::log_msg& msg, const std::tm& tm_time) override
+ {
+ msg.formatted << full_days[tm_time.tm_wday];
+ }
+};
+
+//Abbreviated month
+static const std::string months[] { "Jan", "Feb", "Mar", "Apr", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec" };
+class b_formatter :public flag_formatter
+{
+ void format(details::log_msg& msg, const std::tm& tm_time) override
+ {
+ msg.formatted<< months[tm_time.tm_mon];
+ }
+};
+
+//Full month name
+static const std::string full_months[] { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" };
+class B_formatter :public flag_formatter
+{
+ void format(details::log_msg& msg, const std::tm& tm_time) override
+ {
+ msg.formatted << full_months[tm_time.tm_mon];
+ }
+};
+
+
+//write 2 ints seperated by sep with padding of 2
+static fmt::MemoryWriter& pad_n_join(fmt::MemoryWriter& w, int v1, int v2, char sep)
+{
+ w << fmt::pad(v1, 2, '0') << sep << fmt::pad(v2, 2, '0');
+ return w;
+}
+
+//write 3 ints seperated by sep with padding of 2
+static fmt::MemoryWriter& pad_n_join(fmt::MemoryWriter& w, int v1, int v2, int v3, char sep)
+{
+ w << fmt::pad(v1, 2, '0') << sep << fmt::pad(v2, 2, '0') << sep << fmt::pad(v3, 2, '0');
+ return w;
+}
+
+
+//Date and time representation (Thu Aug 23 15:35:46 2014)
+class c_formatter :public flag_formatter
+{
+ void format(details::log_msg& msg, const std::tm& tm_time) override
+ {
+ msg.formatted << days[tm_time.tm_wday] << ' ' << months[tm_time.tm_mon] << ' ' << tm_time.tm_mday << ' ';
+ pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, ':') << ' ' << tm_time.tm_year + 1900;
+ }
+};
+
+
+// year - 2 digit
+class C_formatter :public flag_formatter
+{
+ void format(details::log_msg& msg, const std::tm& tm_time) override
+ {
+ msg.formatted << fmt::pad(tm_time.tm_year % 100, 2, '0');
+ }
+};
+
+
+
+// Short MM/DD/YY date, equivalent to %m/%d/%y 08/23/01
+class D_formatter :public flag_formatter
+{
+ void format(details::log_msg& msg, const std::tm& tm_time) override
+ {
+ pad_n_join(msg.formatted, tm_time.tm_mon + 1, tm_time.tm_mday, tm_time.tm_year % 100, '/');
+ }
+};
+
+
+// year - 4 digit
+class Y_formatter :public flag_formatter
+{
+ void format(details::log_msg& msg, const std::tm& tm_time) override
+ {
+ msg.formatted << tm_time.tm_year + 1900;
+ }
+};
+
+// month 1-12
+class m_formatter :public flag_formatter
+{
+ void format(details::log_msg& msg, const std::tm& tm_time) override
+ {
+ msg.formatted << fmt::pad(tm_time.tm_mon + 1, 2, '0');
+ }
+};
+
+// day of month 1-31
+class d_formatter :public flag_formatter
+{
+ void format(details::log_msg& msg, const std::tm& tm_time) override
+ {
+ msg.formatted << fmt::pad(tm_time.tm_mday, 2, '0');
+ }
+};
+
+// hours in 24 format 0-23
+class H_formatter :public flag_formatter
+{
+ void format(details::log_msg& msg, const std::tm& tm_time) override
+ {
+ msg.formatted << fmt::pad(tm_time.tm_hour, 2, '0');
+ }
+};
+
+// hours in 12 format 1-12
+class I_formatter :public flag_formatter
+{
+ void format(details::log_msg& msg, const std::tm& tm_time) override
+ {
+ msg.formatted << fmt::pad(to12h(tm_time), 2, '0');
+ }
+};
+
+// ninutes 0-59
+class M_formatter :public flag_formatter
+{
+ void format(details::log_msg& msg, const std::tm& tm_time) override
+ {
+ msg.formatted << fmt::pad(tm_time.tm_min, 2, '0');
+ }
+};
+
+// seconds 0-59
+class S_formatter :public flag_formatter
+{
+ void format(details::log_msg& msg, const std::tm& tm_time) override
+ {
+ msg.formatted << fmt::pad(tm_time.tm_sec, 2, '0');
+ }
+};
+
+// milliseconds
+class e_formatter :public flag_formatter
+{
+ void format(details::log_msg& msg, const std::tm&) override
+ {
+ auto duration = msg.time.time_since_epoch();
+ auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() % 1000;
+ msg.formatted << fmt::pad(static_cast<int>(millis), 3, '0');
+ }
+};
+
+// microseconds
+class f_formatter :public flag_formatter
+{
+ void format(details::log_msg& msg, const std::tm&) override
+ {
+ auto duration = msg.time.time_since_epoch();
+ auto micros = std::chrono::duration_cast<std::chrono::microseconds>(duration).count() % 1000000;
+ msg.formatted << fmt::pad(static_cast<int>(micros), 6, '0');
+ }
+};
+
+// AM/PM
+class p_formatter :public flag_formatter
+{
+ void format(details::log_msg& msg, const std::tm& tm_time) override
+ {
+ msg.formatted << ampm(tm_time);
+ }
+};
+
+
+// 12 hour clock 02:55:02 pm
+class r_formatter :public flag_formatter
+{
+ void format(details::log_msg& msg, const std::tm& tm_time) override
+ {
+ pad_n_join(msg.formatted, to12h(tm_time), tm_time.tm_min, tm_time.tm_sec, ':') << ' ' << ampm(tm_time);
+ }
+};
+
+// 24-hour HH:MM time, equivalent to %H:%M
+class R_formatter :public flag_formatter
+{
+ void format(details::log_msg& msg, const std::tm& tm_time) override
+ {
+ pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, ':');
+ }
+};
+
+// ISO 8601 time format (HH:MM:SS), equivalent to %H:%M:%S
+class T_formatter :public flag_formatter
+{
+ void format(details::log_msg& msg, const std::tm& tm_time) override
+ {
+ pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, ':');
+ }
+};
+
+
+// ISO 8601 offset from UTC in timezone (+-HH:MM)
+class z_formatter :public flag_formatter
+{
+public:
+ const std::chrono::seconds cache_refresh = std::chrono::seconds(5);
+
+ z_formatter() :_last_update(std::chrono::seconds(0)) {}
+ z_formatter(const z_formatter&) = delete;
+ z_formatter& operator=(const z_formatter&) = delete;
+
+ void format(details::log_msg& msg, const std::tm& tm_time) override
+ {
+#ifdef _WIN32
+ int total_minutes = get_cached_offset(msg, tm_time);
+#else
+ // No need to chache under gcc,
+ // it is very fast (already stored in tm.tm_gmtoff)
+ int total_minutes = os::utc_minutes_offset(tm_time);
+#endif
+
+ int h = total_minutes / 60;
+ int m = total_minutes % 60;
+ char sign = h >= 0 ? '+' : '-';
+ msg.formatted << sign;
+ pad_n_join(msg.formatted, h, m, ':');
+ }
+private:
+ log_clock::time_point _last_update;
+ int _offset_minutes;
+ std::mutex _mutex;
+
+ int get_cached_offset(const log_msg& msg, const std::tm& tm_time)
+ {
+ using namespace std::chrono;
+ std::lock_guard<std::mutex> l(_mutex);
+ if (msg.time - _last_update >= cache_refresh)
+ {
+ _offset_minutes = os::utc_minutes_offset(tm_time);
+ _last_update = msg.time;
+ }
+ return _offset_minutes;
+ }
+};
+
+
+
+//Thread id
+class t_formatter :public flag_formatter
+{
+ void format(details::log_msg& msg, const std::tm&) override
+ {
+ msg.formatted << msg.thread_id;
+ }
+};
+
+
+class v_formatter :public flag_formatter
+{
+ void format(details::log_msg& msg, const std::tm&) override
+ {
+ msg.formatted << fmt::StringRef(msg.raw.data(), msg.raw.size());
+ }
+};
+
+class ch_formatter :public flag_formatter
+{
+public:
+ explicit ch_formatter(char ch) : _ch(ch)
+ {}
+ void format(details::log_msg& msg, const std::tm&) override
+ {
+ msg.formatted << _ch;
+ }
+private:
+ char _ch;
+};
+
+
+//aggregate user chars to display as is
+class aggregate_formatter :public flag_formatter
+{
+public:
+ aggregate_formatter()
+ {}
+ void add_ch(char ch)
+ {
+ _str += ch;
+ }
+ void format(details::log_msg& msg, const std::tm&) override
+ {
+ msg.formatted << _str;
+ }
+private:
+ std::string _str;
+};
+
+// Full info formatter
+// pattern: [%Y-%m-%d %H:%M:%S.%e] [%n] [%l] %v
+class full_formatter :public flag_formatter
+{
+ void format(details::log_msg& msg, const std::tm& tm_time) override
+ {
+#ifndef SPDLOG_NO_DATETIME
+ auto duration = msg.time.time_since_epoch();
+ auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() % 1000;
+
+ /* Slower version(while still very fast - about 3.2 million lines/sec under 10 threads),
+ msg.formatted.write("[{:d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}.{:03d}] [{}] [{}] {} ",
+ tm_time.tm_year + 1900,
+ tm_time.tm_mon + 1,
+ tm_time.tm_mday,
+ tm_time.tm_hour,
+ tm_time.tm_min,
+ tm_time.tm_sec,
+ static_cast<int>(millis),
+ msg.logger_name,
+ level::to_str(msg.level),
+ msg.raw.str());*/
+
+
+ // Faster (albeit uglier) way to format the line (5.6 million lines/sec under 10 threads)
+ msg.formatted << '[' << static_cast<unsigned int>(tm_time.tm_year + 1900) << '-'
+ << fmt::pad(static_cast<unsigned int>(tm_time.tm_mon + 1), 2, '0') << '-'
+ << fmt::pad(static_cast<unsigned int>(tm_time.tm_mday), 2, '0') << ' '
+ << fmt::pad(static_cast<unsigned int>(tm_time.tm_hour), 2, '0') << ':'
+ << fmt::pad(static_cast<unsigned int>(tm_time.tm_min), 2, '0') << ':'
+ << fmt::pad(static_cast<unsigned int>(tm_time.tm_sec), 2, '0') << '.'
+ << fmt::pad(static_cast<unsigned int>(millis), 3, '0') << "] ";
+
+//no datetime needed
+#else
+ (void)tm_time;
+#endif
+
+#ifndef SPDLOG_NO_NAME
+ msg.formatted << '[' << msg.logger_name << "] ";
+#endif
+
+ msg.formatted << '[' << level::to_str(msg.level) << "] ";
+ msg.formatted << fmt::StringRef(msg.raw.data(), msg.raw.size());
+ }
+};
+
+}
+}
+///////////////////////////////////////////////////////////////////////////////
+// pattern_formatter inline impl
+///////////////////////////////////////////////////////////////////////////////
+inline spdlog::pattern_formatter::pattern_formatter(const std::string& pattern)
+{
+ compile_pattern(pattern);
+}
+
+inline void spdlog::pattern_formatter::compile_pattern(const std::string& pattern)
+{
+ auto end = pattern.end();
+ std::unique_ptr<details::aggregate_formatter> user_chars;
+ for (auto it = pattern.begin(); it != end; ++it)
+ {
+ if (*it == '%')
+ {
+ if (user_chars) //append user chars found so far
+ _formatters.push_back(std::move(user_chars));
+
+ if (++it != end)
+ handle_flag(*it);
+ else
+ break;
+ }
+ else // chars not following the % sign should be displayed as is
+ {
+ if (!user_chars)
+ user_chars = std::unique_ptr<details::aggregate_formatter>(new details::aggregate_formatter());
+ user_chars->add_ch(*it);
+ }
+ }
+ if (user_chars) //append raw chars found so far
+ {
+ _formatters.push_back(std::move(user_chars));
+ }
+
+}
+inline void spdlog::pattern_formatter::handle_flag(char flag)
+{
+ switch (flag)
+ {
+ // logger name
+ case 'n':
+ _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::name_formatter()));
+ break;
+
+ case 'l':
+ _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::level_formatter()));
+ break;
+
+ case 'L':
+ _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::short_level_formatter()));
+ break;
+
+ case('t') :
+ _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::t_formatter()));
+ break;
+
+ case('v') :
+ _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::v_formatter()));
+ break;
+
+ case('a') :
+ _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::a_formatter()));
+ break;
+
+ case('A') :
+ _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::A_formatter()));
+ break;
+
+ case('b') :
+ case('h') :
+ _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::b_formatter()));
+ break;
+
+ case('B') :
+ _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::B_formatter()));
+ break;
+ case('c') :
+ _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::c_formatter()));
+ break;
+
+ case('C') :
+ _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::C_formatter()));
+ break;
+
+ case('Y') :
+ _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::Y_formatter()));
+ break;
+
+ case('D') :
+ case('x') :
+
+ _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::D_formatter()));
+ break;
+
+ case('m') :
+ _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::m_formatter()));
+ break;
+
+ case('d') :
+ _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::d_formatter()));
+ break;
+
+ case('H') :
+ _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::H_formatter()));
+ break;
+
+ case('I') :
+ _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::I_formatter()));
+ break;
+
+ case('M') :
+ _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::M_formatter()));
+ break;
+
+ case('S') :
+ _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::S_formatter()));
+ break;
+
+ case('e') :
+ _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::e_formatter()));
+ break;
+
+ case('f') :
+ _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::f_formatter()));
+ break;
+
+ case('p') :
+ _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::p_formatter()));
+ break;
+
+ case('r') :
+ _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::r_formatter()));
+ break;
+
+ case('R') :
+ _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::R_formatter()));
+ break;
+
+ case('T') :
+ case('X') :
+ _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::T_formatter()));
+ break;
+
+ case('z') :
+ _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::z_formatter()));
+ break;
+
+ case ('+'):
+ _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::full_formatter()));
+ break;
+
+ default: //Unkown flag appears as is
+ _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::ch_formatter('%')));
+ _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::ch_formatter(flag)));
+ break;
+ }
+}
+
+
+inline void spdlog::pattern_formatter::format(details::log_msg& msg)
+{
+ try
+ {
+ auto tm_time = details::os::localtime(log_clock::to_time_t(msg.time));
+ for (auto &f : _formatters)
+ {
+ f->format(msg, tm_time);
+ }
+ //write eol
+ msg.formatted << details::os::eol();
+ }
+ catch(const fmt::FormatError& e)
+ {
+ throw spdlog_ex(fmt::format("formatting error while processing format string: {}", e.what()));
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/b02af540/include/spdlog/details/registry.h
----------------------------------------------------------------------
diff --git a/include/spdlog/details/registry.h b/include/spdlog/details/registry.h
new file mode 100644
index 0000000..fd8e4be
--- /dev/null
+++ b/include/spdlog/details/registry.h
@@ -0,0 +1,180 @@
+/*************************************************************************/
+/* spdlog - an extremely fast and easy to use c++11 logging library. */
+/* Copyright (c) 2014 Gabi Melman. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#pragma once
+// Loggers registy of unique name->logger pointer
+// An attempt to create a logger with an alreasy existing name will be ignored
+// If user requests a non existing logger, nullptr will be returned
+// This class is thread safe
+
+#include <string>
+#include <mutex>
+#include <unordered_map>
+#include <functional>
+
+#include "./null_mutex.h"
+#include "../logger.h"
+#include "../async_logger.h"
+#include "../common.h"
+
+namespace spdlog
+{
+namespace details
+{
+template <class Mutex> class registry_t
+{
+public:
+
+ void register_logger(std::shared_ptr<logger> logger)
+ {
+ std::lock_guard<Mutex> lock(_mutex);
+ register_logger_impl(logger);
+ }
+
+
+ std::shared_ptr<logger> get(const std::string& logger_name)
+ {
+ std::lock_guard<Mutex> lock(_mutex);
+ auto found = _loggers.find(logger_name);
+ return found == _loggers.end() ? nullptr : found->second;
+ }
+
+ template<class It>
+ std::shared_ptr<logger> create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end)
+ {
+
+ std::shared_ptr<logger> new_logger;
+
+ std::lock_guard<Mutex> lock(_mutex);
+
+
+ if (_async_mode)
+ new_logger = std::make_shared<async_logger>(logger_name, sinks_begin, sinks_end, _async_q_size, _overflow_policy, _worker_warmup_cb, _flush_interval_ms);
+ else
+ new_logger = std::make_shared<logger>(logger_name, sinks_begin, sinks_end);
+
+ if (_formatter)
+ new_logger->set_formatter(_formatter);
+
+ new_logger->set_level(_level);
+ register_logger_impl(new_logger);
+ return new_logger;
+ }
+
+ void drop(const std::string& logger_name)
+ {
+ std::lock_guard<Mutex> lock(_mutex);
+ _loggers.erase(logger_name);
+ }
+
+ void drop_all()
+ {
+ std::lock_guard<Mutex> lock(_mutex);
+ _loggers.clear();
+ }
+ std::shared_ptr<logger> create(const std::string& logger_name, sinks_init_list sinks)
+ {
+ return create(logger_name, sinks.begin(), sinks.end());
+ }
+
+ std::shared_ptr<logger> create(const std::string& logger_name, sink_ptr sink)
+ {
+ return create(logger_name, { sink });
+ }
+
+
+ void formatter(formatter_ptr f)
+ {
+ std::lock_guard<Mutex> lock(_mutex);
+ _formatter = f;
+ for (auto& l : _loggers)
+ l.second->set_formatter(_formatter);
+ }
+
+ void set_pattern(const std::string& pattern)
+ {
+ std::lock_guard<Mutex> lock(_mutex);
+ _formatter = std::make_shared<pattern_formatter>(pattern);
+ for (auto& l : _loggers)
+ l.second->set_formatter(_formatter);
+ }
+
+ void set_level(level::level_enum log_level)
+ {
+ std::lock_guard<Mutex> lock(_mutex);
+ for (auto& l : _loggers)
+ l.second->set_level(log_level);
+ _level = log_level;
+ }
+
+ void set_async_mode(size_t q_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms)
+ {
+ std::lock_guard<Mutex> lock(_mutex);
+ _async_mode = true;
+ _async_q_size = q_size;
+ _overflow_policy = overflow_policy;
+ _worker_warmup_cb = worker_warmup_cb;
+ _flush_interval_ms = flush_interval_ms;
+ }
+
+ void set_sync_mode()
+ {
+ std::lock_guard<Mutex> lock(_mutex);
+ _async_mode = false;
+ }
+
+ static registry_t<Mutex>& instance()
+ {
+ static registry_t<Mutex> s_instance;
+ return s_instance;
+ }
+
+private:
+ void register_logger_impl(std::shared_ptr<logger> logger)
+ {
+ auto logger_name = logger->name();
+ if (_loggers.find(logger_name) != std::end(_loggers))
+ throw spdlog_ex("logger with name " + logger_name + " already exists");
+ _loggers[logger->name()] = logger;
+ }
+ registry_t<Mutex>(){}
+ registry_t<Mutex>(const registry_t<Mutex>&) = delete;
+ registry_t<Mutex>& operator=(const registry_t<Mutex>&) = delete;
+ Mutex _mutex;
+ std::unordered_map <std::string, std::shared_ptr<logger>> _loggers;
+ formatter_ptr _formatter;
+ level::level_enum _level = level::info;
+ bool _async_mode = false;
+ size_t _async_q_size = 0;
+ async_overflow_policy _overflow_policy = async_overflow_policy::block_retry;
+ std::function<void()> _worker_warmup_cb = nullptr;
+ std::chrono::milliseconds _flush_interval_ms;
+};
+#ifdef SPDLOG_NO_REGISTRY_MUTEX
+typedef registry_t<spdlog::details::null_mutex> registry;
+#else
+typedef registry_t<std::mutex> registry;
+#endif
+}
+}
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/b02af540/include/spdlog/details/spdlog_impl.h
----------------------------------------------------------------------
diff --git a/include/spdlog/details/spdlog_impl.h b/include/spdlog/details/spdlog_impl.h
new file mode 100644
index 0000000..cfd6f82
--- /dev/null
+++ b/include/spdlog/details/spdlog_impl.h
@@ -0,0 +1,154 @@
+/*************************************************************************/
+/* spdlog - an extremely fast and easy to use c++11 logging library. */
+/* Copyright (c) 2014 Gabi Melman. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#pragma once
+
+//
+// Global registry functions
+//
+#include "registry.h"
+#include "../sinks/file_sinks.h"
+#include "../sinks/stdout_sinks.h"
+#include "../sinks/syslog_sink.h"
+
+inline void spdlog::register_logger(std::shared_ptr<logger> logger)
+{
+ return details::registry::instance().register_logger(logger);
+}
+
+inline std::shared_ptr<spdlog::logger> spdlog::get(const std::string& name)
+{
+ return details::registry::instance().get(name);
+}
+
+inline void spdlog::drop(const std::string &name)
+{
+ details::registry::instance().drop(name);
+}
+
+// Create multi/single threaded rotating file logger
+inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_mt(const std::string& logger_name, const std::string& filename, size_t max_file_size, size_t max_files, bool force_flush)
+{
+ return create<spdlog::sinks::rotating_file_sink_mt>(logger_name, filename, "txt", max_file_size, max_files, force_flush);
+}
+
+inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_st(const std::string& logger_name, const std::string& filename, size_t max_file_size, size_t max_files, bool force_flush)
+{
+ return create<spdlog::sinks::rotating_file_sink_st>(logger_name, filename, "txt", max_file_size, max_files, force_flush);
+}
+
+// Create file logger which creates new file at midnight):
+inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_mt(const std::string& logger_name, const std::string& filename, int hour, int minute, bool force_flush)
+{
+ return create<spdlog::sinks::daily_file_sink_mt>(logger_name, filename, "txt", hour, minute, force_flush);
+}
+inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_st(const std::string& logger_name, const std::string& filename, int hour, int minute, bool force_flush)
+{
+ return create<spdlog::sinks::daily_file_sink_st>(logger_name, filename, "txt", hour, minute, force_flush);
+}
+
+
+// Create stdout/stderr loggers
+inline std::shared_ptr<spdlog::logger> spdlog::stdout_logger_mt(const std::string& logger_name)
+{
+ return details::registry::instance().create(logger_name, spdlog::sinks::stdout_sink_mt::instance());
+}
+
+inline std::shared_ptr<spdlog::logger> spdlog::stdout_logger_st(const std::string& logger_name)
+{
+ return details::registry::instance().create(logger_name, spdlog::sinks::stdout_sink_st::instance());
+}
+
+inline std::shared_ptr<spdlog::logger> spdlog::stderr_logger_mt(const std::string& logger_name)
+{
+ return details::registry::instance().create(logger_name, spdlog::sinks::stderr_sink_mt::instance());
+}
+
+inline std::shared_ptr<spdlog::logger> spdlog::stderr_logger_st(const std::string& logger_name)
+{
+ return details::registry::instance().create(logger_name, spdlog::sinks::stderr_sink_st::instance());
+}
+
+#ifdef __linux__
+// Create syslog logger
+inline std::shared_ptr<spdlog::logger> spdlog::syslog_logger(const std::string& logger_name, const std::string& syslog_ident, int syslog_option)
+{
+ return create<spdlog::sinks::syslog_sink>(logger_name, syslog_ident, syslog_option);
+}
+#endif
+
+
+//Create logger with multiple sinks
+
+inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, spdlog::sinks_init_list sinks)
+{
+ return details::registry::instance().create(logger_name, sinks);
+}
+
+
+template <typename Sink, typename... Args>
+inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, const Args&... args)
+{
+ sink_ptr sink = std::make_shared<Sink>(args...);
+ return details::registry::instance().create(logger_name, { sink });
+}
+
+
+template<class It>
+inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end)
+{
+ return details::registry::instance().create(logger_name, sinks_begin, sinks_end);
+}
+
+inline void spdlog::set_formatter(spdlog::formatter_ptr f)
+{
+ details::registry::instance().formatter(f);
+}
+
+inline void spdlog::set_pattern(const std::string& format_string)
+{
+ return details::registry::instance().set_pattern(format_string);
+}
+
+inline void spdlog::set_level(level::level_enum log_level)
+{
+ return details::registry::instance().set_level(log_level);
+}
+
+
+inline void spdlog::set_async_mode(size_t queue_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms)
+{
+ details::registry::instance().set_async_mode(queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms);
+}
+
+inline void spdlog::set_sync_mode()
+{
+ details::registry::instance().set_sync_mode();
+}
+
+inline void spdlog::drop_all()
+{
+ details::registry::instance().drop_all();
+}
+
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/b02af540/include/spdlog/formatter.h
----------------------------------------------------------------------
diff --git a/include/spdlog/formatter.h b/include/spdlog/formatter.h
new file mode 100644
index 0000000..35ea041
--- /dev/null
+++ b/include/spdlog/formatter.h
@@ -0,0 +1,58 @@
+/*************************************************************************/
+/* spdlog - an extremely fast and easy to use c++11 logging library. */
+/* Copyright (c) 2014 Gabi Melman. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#pragma once
+
+#include "details/log_msg.h"
+namespace spdlog
+{
+namespace details
+{
+class flag_formatter;
+}
+
+class formatter
+{
+public:
+ virtual ~formatter() {}
+ virtual void format(details::log_msg& msg) = 0;
+};
+
+class pattern_formatter : public formatter
+{
+
+public:
+ explicit pattern_formatter(const std::string& pattern);
+ pattern_formatter(const pattern_formatter&) = delete;
+ pattern_formatter& operator=(const pattern_formatter&) = delete;
+ void format(details::log_msg& msg) override;
+private:
+ const std::string _pattern;
+ std::vector<std::unique_ptr<details::flag_formatter>> _formatters;
+ void handle_flag(char flag);
+ void compile_pattern(const std::string& pattern);
+};
+}
+
+#include "details/pattern_formatter_impl.h"
+
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/b02af540/include/spdlog/logger.h
----------------------------------------------------------------------
diff --git a/include/spdlog/logger.h b/include/spdlog/logger.h
new file mode 100644
index 0000000..7aefcc7
--- /dev/null
+++ b/include/spdlog/logger.h
@@ -0,0 +1,132 @@
+/*************************************************************************/
+/* spdlog - an extremely fast and easy to use c++11 logging library. */
+/* Copyright (c) 2014 Gabi Melman. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#pragma once
+
+// Thread safe logger
+// Has name, log level, vector of std::shared sink pointers and formatter
+// Upon each log write the logger:
+// 1. Checks if its log level is enough to log the message
+// 2. Format the message using the formatter function
+// 3. Pass the formatted message to its sinks to performa the actual logging
+
+#include<vector>
+#include<memory>
+#include "sinks/base_sink.h"
+#include "common.h"
+
+namespace spdlog
+{
+
+namespace details
+{
+class line_logger;
+}
+
+class logger
+{
+public:
+ logger(const std::string& logger_name, sink_ptr single_sink);
+ logger(const std::string& name, sinks_init_list);
+ template<class It>
+ logger(const std::string& name, const It& begin, const It& end);
+
+ virtual ~logger();
+ logger(const logger&) = delete;
+ logger& operator=(const logger&) = delete;
+
+ void set_level(level::level_enum);
+ level::level_enum level() const;
+
+ const std::string& name() const;
+ bool should_log(level::level_enum) const;
+
+ // logger.info(cppformat_string, arg1, arg2, arg3, ...) call style
+ template <typename... Args> details::line_logger trace(const char* fmt, const Args&... args);
+ template <typename... Args> details::line_logger debug(const char* fmt, const Args&... args);
+ template <typename... Args> details::line_logger info(const char* fmt, const Args&... args);
+ template <typename... Args> details::line_logger notice(const char* fmt, const Args&... args);
+ template <typename... Args> details::line_logger warn(const char* fmt, const Args&... args);
+ template <typename... Args> details::line_logger error(const char* fmt, const Args&... args);
+ template <typename... Args> details::line_logger critical(const char* fmt, const Args&... args);
+ template <typename... Args> details::line_logger alert(const char* fmt, const Args&... args);
+ template <typename... Args> details::line_logger emerg(const char* fmt, const Args&... args);
+
+
+ // logger.info(msg) << ".." call style
+ template <typename T> details::line_logger trace(const T&);
+ template <typename T> details::line_logger debug(const T&);
+ template <typename T> details::line_logger info(const T&);
+ template <typename T> details::line_logger notice(const T&);
+ template <typename T> details::line_logger warn(const T&);
+ template <typename T> details::line_logger error(const T&);
+ template <typename T> details::line_logger critical(const T&);
+ template <typename T> details::line_logger alert(const T&);
+ template <typename T> details::line_logger emerg(const T&);
+
+
+ // logger.info() << ".." call style
+ details::line_logger trace();
+ details::line_logger debug();
+ details::line_logger info();
+ details::line_logger notice();
+ details::line_logger warn();
+ details::line_logger error();
+ details::line_logger critical();
+ details::line_logger alert();
+ details::line_logger emerg();
+
+
+
+ // Create log message with the given level, no matter what is the actual logger's level
+ template <typename... Args>
+ details::line_logger force_log(level::level_enum lvl, const char* fmt, const Args&... args);
+
+ // Set the format of the log messages from this logger
+ void set_pattern(const std::string&);
+ void set_formatter(formatter_ptr);
+
+ void flush();
+
+protected:
+ virtual void _log_msg(details::log_msg&);
+ virtual void _set_pattern(const std::string&);
+ virtual void _set_formatter(formatter_ptr);
+ details::line_logger _log_if_enabled(level::level_enum lvl);
+ template <typename... Args>
+ details::line_logger _log_if_enabled(level::level_enum lvl, const char* fmt, const Args&... args);
+ template<typename T>
+ inline details::line_logger _log_if_enabled(level::level_enum lvl, const T& msg);
+
+
+ friend details::line_logger;
+ std::string _name;
+ std::vector<sink_ptr> _sinks;
+ formatter_ptr _formatter;
+ std::atomic_int _level;
+
+};
+}
+
+#include "details/logger_impl.h"
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/b02af540/include/spdlog/sinks/base_sink.h
----------------------------------------------------------------------
diff --git a/include/spdlog/sinks/base_sink.h b/include/spdlog/sinks/base_sink.h
new file mode 100644
index 0000000..12d63ea
--- /dev/null
+++ b/include/spdlog/sinks/base_sink.h
@@ -0,0 +1,66 @@
+/*************************************************************************/
+/* spdlog - an extremely fast and easy to use c++11 logging library. */
+/* Copyright (c) 2014 Gabi Melman. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#pragma once
+//
+// base sink templated over a mutex (either dummy or realy)
+// concrete implementation should only overrid the _sink_it method.
+// all locking is taken care of here so no locking needed by the implementors..
+//
+
+#include<string>
+#include<mutex>
+#include<atomic>
+#include "./sink.h"
+#include "../formatter.h"
+#include "../common.h"
+#include "../details/log_msg.h"
+
+
+namespace spdlog
+{
+namespace sinks
+{
+template<class Mutex>
+class base_sink:public sink
+{
+public:
+ base_sink():_mutex() {}
+ virtual ~base_sink() = default;
+
+ base_sink(const base_sink&) = delete;
+ base_sink& operator=(const base_sink&) = delete;
+
+ void log(const details::log_msg& msg) override
+ {
+ std::lock_guard<Mutex> lock(_mutex);
+ _sink_it(msg);
+ }
+
+protected:
+ virtual void _sink_it(const details::log_msg& msg) = 0;
+ Mutex _mutex;
+};
+}
+}
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/b02af540/include/spdlog/sinks/file_sinks.h
----------------------------------------------------------------------
diff --git a/include/spdlog/sinks/file_sinks.h b/include/spdlog/sinks/file_sinks.h
new file mode 100644
index 0000000..79cbb4e
--- /dev/null
+++ b/include/spdlog/sinks/file_sinks.h
@@ -0,0 +1,232 @@
+/*************************************************************************/
+/* spdlog - an extremely fast and easy to use c++11 logging library. */
+/* Copyright (c) 2014 Gabi Melman. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#pragma once
+
+#include <mutex>
+#include "base_sink.h"
+#include "../details/null_mutex.h"
+#include "../details/file_helper.h"
+#include "../details/format.h"
+
+namespace spdlog
+{
+namespace sinks
+{
+/*
+* Trivial file sink with single file as target
+*/
+template<class Mutex>
+class simple_file_sink : public base_sink < Mutex >
+{
+public:
+ explicit simple_file_sink(const std::string &filename,
+ bool force_flush = false) :
+ _file_helper(force_flush)
+ {
+ _file_helper.open(filename);
+ }
+ void flush() override
+ {
+ _file_helper.flush();
+ }
+
+protected:
+ void _sink_it(const details::log_msg& msg) override
+ {
+ _file_helper.write(msg);
+ }
+private:
+ details::file_helper _file_helper;
+};
+
+typedef simple_file_sink<std::mutex> simple_file_sink_mt;
+typedef simple_file_sink<details::null_mutex> simple_file_sink_st;
+
+/*
+ * Rotating file sink based on size
+ */
+template<class Mutex>
+class rotating_file_sink : public base_sink < Mutex >
+{
+public:
+ rotating_file_sink(const std::string &base_filename, const std::string &extension,
+ std::size_t max_size, std::size_t max_files,
+ bool force_flush = false) :
+ _base_filename(base_filename),
+ _extension(extension),
+ _max_size(max_size),
+ _max_files(max_files),
+ _current_size(0),
+ _file_helper(force_flush)
+ {
+ _file_helper.open(calc_filename(_base_filename, 0, _extension));
+ }
+
+ void flush() override
+ {
+ _file_helper.flush();
+ }
+
+protected:
+ void _sink_it(const details::log_msg& msg) override
+ {
+ _current_size += msg.formatted.size();
+ if (_current_size > _max_size)
+ {
+ _rotate();
+ _current_size = msg.formatted.size();
+ }
+ _file_helper.write(msg);
+ }
+
+private:
+ static std::string calc_filename(const std::string& filename, std::size_t index, const std::string& extension)
+ {
+ fmt::MemoryWriter w;
+ if (index)
+ w.write("{}.{}.{}", filename, index, extension);
+ else
+ w.write("{}.{}", filename, extension);
+ return w.str();
+ }
+
+ // Rotate files:
+ // log.txt -> log.1.txt
+ // log.1.txt -> log2.txt
+ // log.2.txt -> log3.txt
+ // log.3.txt -> delete
+
+ void _rotate()
+ {
+ _file_helper.close();
+ for (auto i = _max_files; i > 0; --i)
+ {
+ std::string src = calc_filename(_base_filename, i - 1, _extension);
+ std::string target = calc_filename(_base_filename, i, _extension);
+
+ if (details::file_helper::file_exists(target))
+ {
+ if (std::remove(target.c_str()) != 0)
+ {
+ throw spdlog_ex("rotating_file_sink: failed removing " + target);
+ }
+ }
+ if (details::file_helper::file_exists(src) && std::rename(src.c_str(), target.c_str()))
+ {
+ throw spdlog_ex("rotating_file_sink: failed renaming " + src + " to " + target);
+ }
+ }
+ _file_helper.reopen(true);
+ }
+ std::string _base_filename;
+ std::string _extension;
+ std::size_t _max_size;
+ std::size_t _max_files;
+ std::size_t _current_size;
+ details::file_helper _file_helper;
+};
+
+typedef rotating_file_sink<std::mutex> rotating_file_sink_mt;
+typedef rotating_file_sink<details::null_mutex>rotating_file_sink_st;
+
+/*
+ * Rotating file sink based on date. rotates at midnight
+ */
+template<class Mutex>
+class daily_file_sink :public base_sink < Mutex >
+{
+public:
+ //create daily file sink which rotates on given time
+ daily_file_sink(
+ const std::string& base_filename,
+ const std::string& extension,
+ int rotation_hour,
+ int rotation_minute,
+ bool force_flush = false) : _base_filename(base_filename),
+ _extension(extension),
+ _rotation_h(rotation_hour),
+ _rotation_m(rotation_minute),
+ _file_helper(force_flush)
+ {
+ if (rotation_hour < 0 || rotation_hour > 23 || rotation_minute < 0 || rotation_minute > 59)
+ throw spdlog_ex("daily_file_sink: Invalid rotation time in ctor");
+ _rotation_tp = _next_rotation_tp();
+ _file_helper.open(calc_filename(_base_filename, _extension));
+ }
+
+ void flush() override
+ {
+ _file_helper.flush();
+ }
+
+protected:
+ void _sink_it(const details::log_msg& msg) override
+ {
+ if (std::chrono::system_clock::now() >= _rotation_tp)
+ {
+ _file_helper.open(calc_filename(_base_filename, _extension));
+ _rotation_tp = _next_rotation_tp();
+ }
+ _file_helper.write(msg);
+ }
+
+private:
+ std::chrono::system_clock::time_point _next_rotation_tp()
+ {
+ using namespace std::chrono;
+ auto now = system_clock::now();
+ time_t tnow = std::chrono::system_clock::to_time_t(now);
+ tm date = spdlog::details::os::localtime(tnow);
+ date.tm_hour = _rotation_h;
+ date.tm_min = _rotation_m;
+ date.tm_sec = 0;
+ auto rotation_time = std::chrono::system_clock::from_time_t(std::mktime(&date));
+ if (rotation_time > now)
+ return rotation_time;
+ else
+ return system_clock::time_point(rotation_time + hours(24));
+ }
+
+ //Create filename for the form basename.YYYY-MM-DD.extension
+ static std::string calc_filename(const std::string& basename, const std::string& extension)
+ {
+ std::tm tm = spdlog::details::os::localtime();
+ fmt::MemoryWriter w;
+ w.write("{}_{:04d}-{:02d}-{:02d}_{:02d}-{:02d}.{}", basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, extension);
+ return w.str();
+ }
+
+ std::string _base_filename;
+ std::string _extension;
+ int _rotation_h;
+ int _rotation_m;
+ std::chrono::system_clock::time_point _rotation_tp;
+ details::file_helper _file_helper;
+};
+
+typedef daily_file_sink<std::mutex> daily_file_sink_mt;
+typedef daily_file_sink<details::null_mutex> daily_file_sink_st;
+}
+}