Some work toward Issue 27 and Issue 319

This commit is contained in:
Nick Bolton
2010-05-31 21:30:29 +00:00
parent fea12827d4
commit f974d8d680
74 changed files with 4057 additions and 3756 deletions

View File

@@ -1,319 +1,300 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2002 Chris Schoeneman
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file COPYING that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "CLog.h"
#include "CString.h"
#include "CStringUtil.h"
#include "LogOutputters.h"
#include "CArch.h"
#include "Version.h"
#include <cstdio>
#include <cstring>
#include <iostream>
#include <ctime>
// names of priorities
static const char* g_priority[] = {
"FATAL",
"ERROR",
"WARNING",
"NOTE",
"INFO",
"DEBUG",
"DEBUG1",
"DEBUG2"
};
// number of priorities
static const int g_numPriority = (int)(sizeof(g_priority) /
sizeof(g_priority[0]));
// the default priority
#if defined(NDEBUG)
static const int g_defaultMaxPriority = 4;
#else
static const int g_defaultMaxPriority = 5;
#endif
// length of longest string in g_priority
static const int g_maxPriorityLength = 7;
// length of suffix string (": ")
static const int g_prioritySuffixLength = 2;
// amount of padded required to fill in the priority prefix
static const int g_priorityPad = g_maxPriorityLength +
g_prioritySuffixLength;
//
// CLog
//
CLog* CLog::s_log = NULL;
CLog::CLog()
{
assert(s_log == NULL);
// create mutex for multithread safe operation
m_mutex = ARCH->newMutex();
// other initalization
m_maxPriority = g_defaultMaxPriority;
m_maxNewlineLength = 0;
insert(new CConsoleLogOutputter);
}
CLog::~CLog()
{
// clean up
for (COutputterList::iterator index = m_outputters.begin();
index != m_outputters.end(); ++index) {
delete *index;
}
for (COutputterList::iterator index = m_alwaysOutputters.begin();
index != m_alwaysOutputters.end(); ++index) {
delete *index;
}
ARCH->closeMutex(m_mutex);
s_log = NULL;
}
CLog*
CLog::getInstance()
{
// note -- not thread safe; client must initialize log safely
if (s_log == NULL) {
s_log = new CLog;
}
return s_log;
}
void
CLog::print(const char* file, int line, const char* fmt, ...) const
{
// check if fmt begins with a priority argument
int priority = 4;
if (fmt[0] == '%' && fmt[1] == 'z') {
priority = fmt[2] - '\060';
fmt += 3;
}
// done if below priority threshold
if (priority > getFilter()) {
return;
}
// compute prefix padding length
char stack[1024];
// compute suffix padding length
int sPad = m_maxNewlineLength;
// print to buffer, leaving space for a newline at the end and prefix
// at the beginning.
char* buffer = stack;
int len = (int)(sizeof(stack) / sizeof(stack[0]));
while (true) {
// try printing into the buffer
va_list args;
va_start(args, fmt);
int n = ARCH->vsnprintf(buffer, len - sPad, fmt, args);
va_end(args);
// if the buffer wasn't big enough then make it bigger and try again
if (n < 0 || n > (int)len) {
if (buffer != stack) {
delete[] buffer;
}
len *= 2;
buffer = new char[len];
}
// if the buffer was big enough then continue
else {
break;
}
}
// print the prefix to the buffer. leave space for priority label.
if (file != NULL) {
char message[2048];
struct tm *tm;
char tmp[220];
time_t t;
time(&t);
tm = localtime(&t);
sprintf(tmp, "%04i-%02i-%02iT%02i:%02i:%02i", tm->tm_year + 1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
//strcpy(msg, tmp);
sprintf(message, "%s %s: %s\n\t%s,%d", tmp, g_priority[priority], buffer, file, line);
// buffer[pPad - 1] = ' ';
// discard file and line if priority < 0
/*if (priority < 0) {
message += pPad - g_priorityPad;
}
*/
// output buffer
output(priority, message);
} else {
output(priority, buffer);
}
// clean up
if (buffer != stack) {
delete[] buffer;
}
}
void
CLog::insert(ILogOutputter* outputter, bool alwaysAtHead)
{
assert(outputter != NULL);
assert(outputter->getNewline() != NULL);
CArchMutexLock lock(m_mutex);
if (alwaysAtHead) {
m_alwaysOutputters.push_front(outputter);
}
else {
m_outputters.push_front(outputter);
}
int newlineLength = (int)strlen(outputter->getNewline());
if (newlineLength > m_maxNewlineLength) {
m_maxNewlineLength = newlineLength;
}
outputter->open(kAppVersion);
// Issue 41
// don't show log unless user requests it, as some users find this
// feature irritating (i.e. when they lose network connectivity).
// in windows the log window can be displayed by selecting "show log"
// from the synergy system tray icon.
// if this causes problems for other architectures, then a different
// work around should be attempted.
//outputter->show(false);
}
void
CLog::remove(ILogOutputter* outputter)
{
CArchMutexLock lock(m_mutex);
m_outputters.remove(outputter);
m_alwaysOutputters.remove(outputter);
}
void
CLog::pop_front(bool alwaysAtHead)
{
CArchMutexLock lock(m_mutex);
COutputterList* list = alwaysAtHead ? &m_alwaysOutputters : &m_outputters;
if (!list->empty()) {
delete list->front();
list->pop_front();
}
}
bool
CLog::setFilter(const char* maxPriority)
{
if (maxPriority != NULL) {
for (int i = 0; i < g_numPriority; ++i) {
if (strcmp(maxPriority, g_priority[i]) == 0) {
setFilter(i);
return true;
}
}
return false;
}
return true;
}
void
CLog::setFilter(int maxPriority)
{
CArchMutexLock lock(m_mutex);
m_maxPriority = maxPriority;
}
int
CLog::getFilter() const
{
CArchMutexLock lock(m_mutex);
return m_maxPriority;
}
void
CLog::output(int priority, char* msg) const
{
assert(priority >= -1 && priority < g_numPriority);
assert(msg != NULL);
// insert priority label
//int n = -g_prioritySuffixLength;
/*
if (priority >= 0) {
n = strlen(g_priority[priority]);
strcpy(msg + g_maxPriorityLength - n, g_priority[priority]);
msg[g_maxPriorityLength + 0] = ':';
msg[g_maxPriorityLength + 1] = ' ';
msg[g_maxPriorityLength + 1] = ' ';
}
*/
// find end of message
//char* end = msg + g_priorityPad + strlen(msg + g_priorityPad);
int len = (int)strlen(msg);
char* tmp = new char[len+m_maxNewlineLength+1];
char* end = tmp + len;
strcpy(tmp, msg);
// write to each outputter
CArchMutexLock lock(m_mutex);
for (COutputterList::const_iterator index = m_alwaysOutputters.begin();
index != m_alwaysOutputters.end();
++index) {
// get outputter
ILogOutputter* outputter = *index;
// put an appropriate newline at the end
strcpy(end, outputter->getNewline());
// write message
outputter->write(static_cast<ILogOutputter::ELevel>(priority),
tmp /*+ g_maxPriorityLength - n*/);
}
for (COutputterList::const_iterator index = m_outputters.begin();
index != m_outputters.end(); ++index) {
// get outputter
ILogOutputter* outputter = *index;
// put an appropriate newline at the end
strcpy(end, outputter->getNewline());
// write message and break out of loop if it returns false
if (!outputter->write(static_cast<ILogOutputter::ELevel>(priority),
tmp /*+ g_maxPriorityLength - n*/)) {
break;
}
}
delete[] tmp;
}
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2002 Chris Schoeneman
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file COPYING that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "CLog.h"
#include "CString.h"
#include "CStringUtil.h"
#include "LogOutputters.h"
#include "CArch.h"
#include "Version.h"
#include <cstdio>
#include <cstring>
#include <iostream>
#include <ctime>
// names of priorities
static const char* g_priority[] = {
"FATAL",
"ERROR",
"WARNING",
"NOTE",
"INFO",
"DEBUG",
"DEBUG1",
"DEBUG2",
"DEBUG3",
"DEBUG4",
"DEBUG5"
};
// number of priorities
static const int g_numPriority = (int)(sizeof(g_priority) / sizeof(g_priority[0]));
// the default priority
#if defined(NDEBUG)
static const int g_defaultMaxPriority = 4;
#else
static const int g_defaultMaxPriority = 5;
#endif
// length of longest string in g_priority
static const int g_maxPriorityLength = 7;
// length of suffix string (": ")
static const int g_prioritySuffixLength = 2;
// amount of padded required to fill in the priority prefix
static const int g_priorityPad = g_maxPriorityLength +
g_prioritySuffixLength;
//
// CLog
//
CLog* CLog::s_log = NULL;
CLog::CLog()
{
assert(s_log == NULL);
// create mutex for multithread safe operation
m_mutex = ARCH->newMutex();
// other initalization
m_maxPriority = g_defaultMaxPriority;
m_maxNewlineLength = 0;
insert(new CConsoleLogOutputter);
}
CLog::~CLog()
{
// clean up
for (COutputterList::iterator index = m_outputters.begin();
index != m_outputters.end(); ++index) {
delete *index;
}
for (COutputterList::iterator index = m_alwaysOutputters.begin();
index != m_alwaysOutputters.end(); ++index) {
delete *index;
}
ARCH->closeMutex(m_mutex);
s_log = NULL;
}
CLog*
CLog::getInstance()
{
// note -- not thread safe; client must initialize log safely
if (s_log == NULL) {
s_log = new CLog;
}
return s_log;
}
const char*
CLog::getFilterName() const
{
return getFilterName(getFilter());
}
const char*
CLog::getFilterName(int level) const
{
return g_priority[level];
}
void
CLog::print(const char* file, int line, const char* fmt, ...)
{
// check if fmt begins with a priority argument
ELevel priority = kINFO;
if (fmt[0] == '%' && fmt[1] == 'z') {
// 060 in octal is 0 (48 in decimal), so subtracting this converts ascii
// number it a true number. we could use atoi instead, but this is how
// it was done originally.
priority = (ELevel)(fmt[2] - '\060'); // TODO: fix this shit
// move the pointer on past the debug priority char
fmt += 3;
}
// done if below priority threshold
if (priority > getFilter()) {
return;
}
// compute prefix padding length
char stack[1024];
// compute suffix padding length
int sPad = m_maxNewlineLength;
// print to buffer, leaving space for a newline at the end and prefix
// at the beginning.
char* buffer = stack;
int len = (int)(sizeof(stack) / sizeof(stack[0]));
while (true) {
// try printing into the buffer
va_list args;
va_start(args, fmt);
int n = ARCH->vsnprintf(buffer, len - sPad, fmt, args);
va_end(args);
// if the buffer wasn't big enough then make it bigger and try again
if (n < 0 || n > (int)len) {
if (buffer != stack) {
delete[] buffer;
}
len *= 2;
buffer = new char[len];
}
// if the buffer was big enough then continue
else {
break;
}
}
// print the prefix to the buffer. leave space for priority label.
if (file != NULL) {
char message[2048];
struct tm *tm;
char tmp[220];
time_t t;
time(&t);
tm = localtime(&t);
sprintf(tmp, "%04i-%02i-%02iT%02i:%02i:%02i", tm->tm_year + 1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
//strcpy(msg, tmp);
sprintf(message, "%s %s: %s\n\t%s,%d", tmp, g_priority[priority], buffer, file, line);
// buffer[pPad - 1] = ' ';
// discard file and line if priority < 0
/*if (priority < 0) {
message += pPad - g_priorityPad;
}
*/
// output buffer
output(priority, message);
} else {
output(priority, buffer);
}
// clean up
if (buffer != stack) {
delete[] buffer;
}
}
void
CLog::insert(ILogOutputter* outputter, bool alwaysAtHead)
{
assert(outputter != NULL);
CArchMutexLock lock(m_mutex);
if (alwaysAtHead) {
m_alwaysOutputters.push_front(outputter);
}
else {
m_outputters.push_front(outputter);
}
outputter->open(kAppVersion);
// Issue 41
// don't show log unless user requests it, as some users find this
// feature irritating (i.e. when they lose network connectivity).
// in windows the log window can be displayed by selecting "show log"
// from the synergy system tray icon.
// if this causes problems for other architectures, then a different
// work around should be attempted.
//outputter->show(false);
}
void
CLog::remove(ILogOutputter* outputter)
{
CArchMutexLock lock(m_mutex);
m_outputters.remove(outputter);
m_alwaysOutputters.remove(outputter);
}
void
CLog::pop_front(bool alwaysAtHead)
{
CArchMutexLock lock(m_mutex);
COutputterList* list = alwaysAtHead ? &m_alwaysOutputters : &m_outputters;
if (!list->empty()) {
delete list->front();
list->pop_front();
}
}
bool
CLog::setFilter(const char* maxPriority)
{
if (maxPriority != NULL) {
for (int i = 0; i < g_numPriority; ++i) {
if (strcmp(maxPriority, g_priority[i]) == 0) {
setFilter(i);
return true;
}
}
return false;
}
return true;
}
void
CLog::setFilter(int maxPriority)
{
CArchMutexLock lock(m_mutex);
m_maxPriority = maxPriority;
}
int
CLog::getFilter() const
{
CArchMutexLock lock(m_mutex);
return m_maxPriority;
}
void
CLog::output(ELevel priority, char* msg)
{
assert(priority >= -1 && priority < g_numPriority);
assert(msg != NULL);
if (!msg) return;
CArchMutexLock lock(m_mutex);
COutputterList::const_iterator i;
for (i = m_alwaysOutputters.begin(); i != m_alwaysOutputters.end(); ++i) {
// write to outputter
(*i)->write(priority, msg);
}
for (i = m_outputters.begin(); i != m_outputters.end(); ++i) {
// write to outputter and break out of loop if it returns false
if (!(*i)->write(priority, msg)) {
break;
}
}
}

View File

@@ -19,10 +19,12 @@
#include "IArchMultithread.h"
#include "stdlist.h"
#include <stdarg.h>
#include "CArch.h"
#define CLOG (CLog::getInstance())
class ILogOutputter;
class CThread;
//! Logging facility
/*!
@@ -44,8 +46,11 @@ public:
kNOTE, //!< For messages about notable events
kINFO, //!< For informational messages
kDEBUG, //!< For important debugging messages
kDEBUG1, //!< For more detailed debugging messages
kDEBUG2 //!< For even more detailed debugging messages
kDEBUG1, //!< For verbosity +1 debugging messages
kDEBUG2, //!< For verbosity +2 debugging messages
kDEBUG3, //!< For verbosity +3 debugging messages
kDEBUG4, //!< For verbosity +4 debugging messages
kDEBUG5 //!< For verbosity +5 debugging messages
};
~CLog();
@@ -109,20 +114,28 @@ public:
neither the file nor the line are printed.
*/
void print(const char* file, int line,
const char* format, ...) const;
const char* format, ...);
//! Get the minimum priority level.
int getFilter() const;
//! Get the filter name of the current filter level.
const char* getFilterName() const;
//! Get the filter name of a specified filter level.
const char* getFilterName(int level) const;
//! Get the singleton instance of the log
static CLog* getInstance();
//! Get the console filter level (messages above this are not sent to console).
int getConsoleMaxLevel() const { return kDEBUG1; }
//@}
private:
CLog();
void output(int priority, char* msg) const;
void output(ELevel priority, char* msg);
private:
typedef std::list<ILogOutputter*> COutputterList;
@@ -189,8 +202,13 @@ otherwise it expands to a call that doesn't.
#define CLOG_TRACE __FILE__, __LINE__,
#endif
#define CLOG_PRINT CLOG_TRACE "%z\057"
#define CLOG_CRIT CLOG_TRACE "%z\060"
// the CLOG_* defines are line and file plus %z and an octal number (060=0,
// 071=9), but the limitation is that once we run out of numbers at either
// end, then we resort to using non-numerical chars. this still works (since
// to deduce the number we subtract octal \060, so '/' is -1, and ':' is 10
#define CLOG_PRINT CLOG_TRACE "%z\057" // char is '/'
#define CLOG_CRIT CLOG_TRACE "%z\060" // char is '0'
#define CLOG_ERR CLOG_TRACE "%z\061"
#define CLOG_WARN CLOG_TRACE "%z\062"
#define CLOG_NOTE CLOG_TRACE "%z\063"
@@ -198,5 +216,8 @@ otherwise it expands to a call that doesn't.
#define CLOG_DEBUG CLOG_TRACE "%z\065"
#define CLOG_DEBUG1 CLOG_TRACE "%z\066"
#define CLOG_DEBUG2 CLOG_TRACE "%z\067"
#define CLOG_DEBUG3 CLOG_TRACE "%z\070"
#define CLOG_DEBUG4 CLOG_TRACE "%z\071" // char is '9'
#define CLOG_DEBUG5 CLOG_TRACE "%z\072" // char is ':'
#endif

View File

@@ -63,18 +63,6 @@ public:
*/
virtual bool write(ELevel level, const char* message) = 0;
//@}
//! @name accessors
//@{
//! Returns the newline sequence for the outputter
/*!
Different outputters use different character sequences for newlines.
This method returns the appropriate newline sequence for this
outputter.
*/
virtual const char* getNewline() const = 0;
//@}
};

View File

@@ -14,6 +14,7 @@
#include "LogOutputters.h"
#include "CArch.h"
#include "TMethodJob.h"
#include <fstream>
//
@@ -54,12 +55,6 @@ CStopLogOutputter::write(ELevel, const char*)
return false;
}
const char*
CStopLogOutputter::getNewline() const
{
return "";
}
//
// CConsoleLogOutputter
@@ -67,12 +62,10 @@ CStopLogOutputter::getNewline() const
CConsoleLogOutputter::CConsoleLogOutputter()
{
// do nothing
}
CConsoleLogOutputter::~CConsoleLogOutputter()
{
// do nothing
}
void
@@ -94,16 +87,16 @@ CConsoleLogOutputter::show(bool showIfEmpty)
}
bool
CConsoleLogOutputter::write(ELevel, const char* msg)
CConsoleLogOutputter::write(ELevel level, const char* msg)
{
ARCH->writeConsole(msg);
return true;
return true; // wtf?
}
const char*
CConsoleLogOutputter::getNewline() const
void
CConsoleLogOutputter::flush()
{
return ARCH->getNewlineForConsole();
}
@@ -170,13 +163,6 @@ CSystemLogOutputter::write(ELevel level, const char* msg)
return true;
}
const char*
CSystemLogOutputter::getNewline() const
{
return "";
}
//
// CSystemLogger
//
@@ -261,12 +247,6 @@ CBufferedLogOutputter::write(ELevel, const char* message)
return true;
}
const char*
CBufferedLogOutputter::getNewline() const
{
return "";
}
//
// CFileLogOutputter
@@ -287,17 +267,11 @@ CFileLogOutputter::~CFileLogOutputter()
m_handle.close();
}
const char*
CFileLogOutputter::getNewline() const
{
return "\n";
}
bool
CFileLogOutputter::write(ILogOutputter::ELevel level, const char *message)
{
if (m_handle.is_open() && m_handle.fail() != true) {
m_handle << message;
m_handle << message << std::endl;
// write buffer to file
m_handle.flush();

View File

@@ -19,8 +19,11 @@
#include "ILogOutputter.h"
#include "CString.h"
#include "stddeque.h"
#include "CThread.h"
#include <list>
#include <fstream>
//! Stop traversing log chain outputter
/*!
This outputter performs no output and returns false from \c write(),
@@ -37,7 +40,6 @@ public:
virtual void close();
virtual void show(bool showIfEmpty);
virtual bool write(ELevel level, const char* message);
virtual const char* getNewline() const;
};
//! Write log to console
@@ -55,7 +57,7 @@ public:
virtual void close();
virtual void show(bool showIfEmpty);
virtual bool write(ELevel level, const char* message);
virtual const char* getNewline() const;
virtual void flush();
};
//! Write log to file
@@ -74,7 +76,6 @@ public:
virtual void close();
virtual void show(bool showIfEmpty);
virtual bool write(ELevel level, const char* message);
virtual const char* getNewline() const;
private:
std::ofstream m_handle;
};
@@ -93,7 +94,6 @@ public:
virtual void close();
virtual void show(bool showIfEmpty);
virtual bool write(ELevel level, const char* message);
virtual const char* getNewline() const;
};
//! Write log to system log only
@@ -144,8 +144,6 @@ public:
virtual void close();
virtual void show(bool showIfEmpty);
virtual bool write(ELevel level, const char* message);
virtual const char* getNewline() const;
private:
UInt32 m_maxBufferSize;
CBuffer m_buffer;