diff options
| author | Carl Hetherington <cth@carlh.net> | 2018-09-07 13:01:36 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2019-12-03 17:01:32 +0100 |
| commit | 867eb568ba00a4a36c971822596f39fd482744f2 (patch) | |
| tree | 7591dc989137889737fbd9aef819d4dbf0a249fd /src/asdcp | |
| parent | a7e1d778842dd4a5dc79fdbcf57eff175f50dafe (diff) | |
Install KM_log.h
Diffstat (limited to 'src/asdcp')
| -rwxr-xr-x | src/asdcp/KM_log.h | 328 | ||||
| -rwxr-xr-x | src/asdcp/KM_mutex.h | 89 |
2 files changed, 417 insertions, 0 deletions
diff --git a/src/asdcp/KM_log.h b/src/asdcp/KM_log.h new file mode 100755 index 0000000..c15608a --- /dev/null +++ b/src/asdcp/KM_log.h @@ -0,0 +1,328 @@ +/* +Copyright (c) 2004-2009, John Hurst +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. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR 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. +*/ + /*! \file KM_log.h + \version $Id$ + \brief message logging API + */ + + +#ifndef _KM_LOG_H_ +#define _KM_LOG_H_ + +#include <asdcp/KM_platform.h> +#include <asdcp/KM_mutex.h> +#include <asdcp/KM_util.h> +#include <stdarg.h> +#include <errno.h> +#include <iosfwd> +#include <set> + +#define LOG_MSG_IMPL(t) \ + va_list args; \ + va_start(args, fmt); \ + vLogf((t), fmt, &args); \ + va_end(args) + +// Returns RESULT_PTR if the given argument is NULL. +# define KM_TEST_NULL_L(p) \ + if ( (p) == 0 ) { \ + DefaultLogSink().Error("NULL pointer in file %s, line %d\n", __FILE__, __LINE__); \ + return Kumu::RESULT_PTR; \ + } + +// Returns RESULT_PTR if the given argument is NULL. It then +// assumes that the argument is a pointer to a string and returns +// RESULT_NULL_STR if the first character is '\0'. +// +# define KM_TEST_NULL_STR_L(p) \ + KM_TEST_NULL_L(p); \ + if ( (p)[0] == '\0' ) { \ + DefaultLogSink().Error("Empty string in file %s, line %d\n", __FILE__, __LINE__); \ + return Kumu::RESULT_NULL_STR; \ + } + + +namespace Kumu +{ + // no log message will exceed this length + const ui32_t MaxLogLength = 512; + + //--------------------------------------------------------------------------------- + // message logging + + // Log messages are recorded by objects which implement the interface given + // in the class ILogSink below. The library maintains a pointer to a default + // log sink which is used by the library to report messages. + // + + // types of log messages + enum LogType_t { + LOG_DEBUG, // detailed developer info + LOG_INFO, // developer info + LOG_WARN, // library non-fatal or near-miss error + LOG_ERROR, // library fatal error + LOG_NOTICE, // application user info + LOG_ALERT, // application non-fatal or near-miss error + LOG_CRIT, // application fatal error + LOG_MAX + }; + + + // OR these values together to come up with sink filter flags. + // The default mask is LOG_ALLOW_ALL (all messages). + const i32_t LOG_ALLOW_DEBUG = 0x00000001; + const i32_t LOG_ALLOW_INFO = 0x00000002; + const i32_t LOG_ALLOW_WARN = 0x00000004; + const i32_t LOG_ALLOW_ERROR = 0x00000008; + const i32_t LOG_ALLOW_NOTICE = 0x00000010; + const i32_t LOG_ALLOW_ALERT = 0x00000020; + const i32_t LOG_ALLOW_CRIT = 0x00000040; + const i32_t LOG_ALLOW_NONE = 0x00000000; + const i32_t LOG_ALLOW_ALL = 0x000fffff; + + // options are used to control display format default is 0. + const i32_t LOG_OPTION_TYPE = 0x01000000; + const i32_t LOG_OPTION_TIMESTAMP = 0x02000000; + const i32_t LOG_OPTION_PID = 0x04000000; + const i32_t LOG_OPTION_NONE = 0x00000000; + const i32_t LOG_OPTION_ALL = 0xfff00000; + + // A log message with environmental metadata + class LogEntry : public IArchive + { + public: + ui32_t PID; + Timestamp EventTime; + LogType_t Type; + std::string Msg; + + LogEntry() {} + LogEntry(ui32_t pid, LogType_t t, const char* m) : PID(pid), Type(t), Msg(m) { assert(m); } + virtual ~LogEntry() {} + + // returns true if the message Type is present in the mask + bool TestFilter(i32_t mask_value) const; + + // renders the message into outstr using the given dispaly options + // returns outstr& + std::string& CreateStringWithOptions(std::string& outstr, i32_t mask_value) const; + + // IArchive + bool HasValue() const { return ! Msg.empty(); } + ui32_t ArchiveLength() const; + bool Archive(MemIOWriter* Writer) const; + bool Unarchive(MemIOReader* Reader); + }; + + // + std::basic_ostream<char, std::char_traits<char> >& + operator<<(std::basic_ostream<char, std::char_traits<char> >& strm, LogEntry const& Entry); + + + typedef ArchivableList<LogEntry> LogEntryList; + + // + class ILogSink + { + protected: + i32_t m_filter; + i32_t m_options; + Mutex m_lock; + std::set<ILogSink*> m_listeners; + + // you must obtain m_lock BEFORE calling this from your own WriteEntry + void WriteEntryToListeners(const LogEntry& entry) + { + std::set<ILogSink*>::iterator i; + for ( i = m_listeners.begin(); i != m_listeners.end(); ++i ) + (*i)->WriteEntry(entry); + } + + KM_NO_COPY_CONSTRUCT(ILogSink); + + public: + ILogSink() : m_filter(LOG_ALLOW_ALL), m_options(LOG_OPTION_NONE) {} + virtual ~ILogSink() {} + + void SetFilterFlag(i32_t f) { m_filter |= f; } + void UnsetFilterFlag(i32_t f) { m_filter &= ~f; } + bool TestFilterFlag(i32_t f) const { return ((m_filter & f) == f); } + + void SetOptionFlag(i32_t o) { m_options |= o; } + void UnsetOptionFlag(i32_t o) { m_options &= ~o; } + bool TestOptionFlag(i32_t o) const { return ((m_options & o) == o); } + + void AddListener(ILogSink& s) { + if ( &s != this ) + { + AutoMutex l(m_lock); + m_listeners.insert(&s); + } + } + + void DelListener(ILogSink& s) { + AutoMutex l(m_lock); + m_listeners.erase(&s); + } + + // library messages + void Error(const char* fmt, ...) { LOG_MSG_IMPL(LOG_ERROR); } + void Warn(const char* fmt, ...) { LOG_MSG_IMPL(LOG_WARN); } + void Info(const char* fmt, ...) { LOG_MSG_IMPL(LOG_INFO); } + void Debug(const char* fmt, ...) { LOG_MSG_IMPL(LOG_DEBUG); } + + // application messages + void Critical(const char* fmt, ...) { LOG_MSG_IMPL(LOG_CRIT); } + void Alert(const char* fmt, ...) { LOG_MSG_IMPL(LOG_ALERT); } + void Notice(const char* fmt, ...) { LOG_MSG_IMPL(LOG_NOTICE); } + + // message with type + void Logf(LogType_t type, const char* fmt, ...) { LOG_MSG_IMPL(type); } + + // actual log sink input + virtual void vLogf(LogType_t, const char*, va_list*); + virtual void WriteEntry(const LogEntry&) = 0; + }; + + + // Sets the internal default sink to the given receiver. If the given value + // is zero, sets the default sink to the internally allocated stderr sink. + void SetDefaultLogSink(ILogSink* = 0); + + // Returns the internal default sink. + ILogSink& DefaultLogSink(); + + + // attach a log sink as a listener until deleted + class LogSinkListenContext + { + ILogSink* m_log_source; + ILogSink* m_sink; + KM_NO_COPY_CONSTRUCT(LogSinkListenContext); + LogSinkListenContext(); + + public: + LogSinkListenContext(ILogSink& source, ILogSink& sink) + { + m_log_source = &source; + m_sink = &sink; + m_log_source->AddListener(*m_sink); + } + + ~LogSinkListenContext() + { + m_log_source->DelListener(*m_sink); + } + }; + + + //------------------------------------------------------------------------------------------ + // + + // collect log messages into the given list, does not test filter + class EntryListLogSink : public ILogSink + { + LogEntryList& m_Target; + KM_NO_COPY_CONSTRUCT(EntryListLogSink); + EntryListLogSink(); + + public: + EntryListLogSink(LogEntryList& target) : m_Target(target) {} + virtual ~EntryListLogSink() {} + + void WriteEntry(const LogEntry& Entry); + }; + + + // write messages to a POSIX stdio stream + class StdioLogSink : public ILogSink + { + FILE* m_stream; + KM_NO_COPY_CONSTRUCT(StdioLogSink); + + public: + StdioLogSink() : m_stream(stderr) {} + StdioLogSink(FILE* stream) : m_stream(stream) {} + virtual ~StdioLogSink() {} + + void WriteEntry(const LogEntry&); + }; + +#ifdef KM_WIN32 + // write messages to the Win32 debug stream + class WinDbgLogSink : public ILogSink + { + KM_NO_COPY_CONSTRUCT(WinDbgLogSink); + + public: + WinDbgLogSink() {} + virtual ~WinDbgLogSink() {} + + void WriteEntry(const LogEntry&); + }; +#endif + +#ifndef KM_WIN32 + // write messages to a POSIX file descriptor + class StreamLogSink : public ILogSink + { + int m_fd; + KM_NO_COPY_CONSTRUCT(StreamLogSink); + StreamLogSink(); + + public: + StreamLogSink(int fd) : m_fd(fd) {} + virtual ~StreamLogSink() {} + + void WriteEntry(const LogEntry&); + }; + + // write messages to the syslog facility + class SyslogLogSink : public ILogSink + { + KM_NO_COPY_CONSTRUCT(SyslogLogSink); + SyslogLogSink(); + + public: + SyslogLogSink(const std::string& source_name, int facility); + virtual ~SyslogLogSink(); + void WriteEntry(const LogEntry&); + }; + + // convert a string into the appropriate syslog facility id + int SyslogNameToFacility(const std::string& facility_name); + +#endif + + +} // namespace Kumu + +#endif // _KM_LOG_H_ + +// +// end KM_log.h +// diff --git a/src/asdcp/KM_mutex.h b/src/asdcp/KM_mutex.h new file mode 100755 index 0000000..b44c4f2 --- /dev/null +++ b/src/asdcp/KM_mutex.h @@ -0,0 +1,89 @@ +/* +Copyright (c) 2004-2009, John Hurst +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. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR 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. +*/ + /*! \file KM_mutex.h + \version $Id$ + \brief platform portability + */ + +#ifndef _KM_MUTEX_H_ +#define _KM_MUTEX_H_ + +#include <asdcp/KM_platform.h> + +#ifndef KM_WIN32 +# include <pthread.h> +#endif + +namespace Kumu +{ +#ifdef KM_WIN32 + class Mutex + { + CRITICAL_SECTION m_Mutex; + KM_NO_COPY_CONSTRUCT(Mutex); + + public: + inline Mutex() { ::InitializeCriticalSection(&m_Mutex); } + inline ~Mutex() { ::DeleteCriticalSection(&m_Mutex); } + inline void Lock() { ::EnterCriticalSection(&m_Mutex); } + inline void Unlock() { ::LeaveCriticalSection(&m_Mutex); } + }; +#else // KM_WIN32 + class Mutex + { + pthread_mutex_t m_Mutex; + KM_NO_COPY_CONSTRUCT(Mutex); + + public: + inline Mutex() { pthread_mutex_init(&m_Mutex, 0); } + inline ~Mutex() { pthread_mutex_destroy(&m_Mutex); } + inline void Lock() { pthread_mutex_lock(&m_Mutex); } + inline void Unlock() { pthread_mutex_unlock(&m_Mutex); } + }; +#endif // KM_WIN32 + + // automatic Mutex management within a block - + // the mutex is created by the constructor and + // released by the destructor + class AutoMutex + { + Mutex& m_Mutex; + AutoMutex(); + KM_NO_COPY_CONSTRUCT(AutoMutex); + + public: + AutoMutex(Mutex& Mtx) : m_Mutex(Mtx) { m_Mutex.Lock(); } + ~AutoMutex() { m_Mutex.Unlock(); } + }; + +} // namespace Kumu + +#endif // _KM_MUTEX_H_ + +// +// end KM_mutex.h +// |
