summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrandomdan <randomdan@localhost>2011-02-10 10:33:36 +0000
committerrandomdan <randomdan@localhost>2011-02-10 10:33:36 +0000
commitf98bc01af0208321eeb988dd7c708526908f1f36 (patch)
tree705a8548c3df1048e6bcef70f703a01d3867a758
parentMake different DB connectors optional (diff)
downloadproject2-f98bc01af0208321eeb988dd7c708526908f1f36.tar.bz2
project2-f98bc01af0208321eeb988dd7c708526908f1f36.tar.xz
project2-f98bc01af0208321eeb988dd7c708526908f1f36.zip
Fix silly bug loading readonly RDBMS config entries
Add centralised logging system Add code for runtime configuration Add support for configuring logging Move all existing logging to new logging system
-rw-r--r--project2/Jamfile.jam4
-rw-r--r--project2/cgi/cgiAppEngine.cpp7
-rw-r--r--project2/cgi/cgiAppEngine.h12
-rw-r--r--project2/cgi/cgiCommon.cpp59
-rw-r--r--project2/cgi/cgiEnvironment.cpp14
-rw-r--r--project2/cgi/cgiEnvironment.h4
-rw-r--r--project2/cgi/p2webFCgi.cpp9
-rw-r--r--project2/console/consoleEnvironment.cpp47
-rw-r--r--project2/console/consoleEnvironment.h12
-rw-r--r--project2/console/p2consoleMain.cpp13
-rw-r--r--project2/environment.cpp49
-rw-r--r--project2/environment.h11
-rw-r--r--project2/fsRows.cpp4
-rw-r--r--project2/iterate.cpp1
-rw-r--r--project2/logger.cpp182
-rw-r--r--project2/logger.h43
-rw-r--r--project2/loggers.h55
-rw-r--r--project2/rdbmsDataSource.cpp14
-rw-r--r--project2/rowProcessor.cpp1
-rw-r--r--project2/rowSet.cpp4
-rw-r--r--project2/sessionSetTask.cpp1
-rw-r--r--project2/sqlMergeTask.cpp2
-rw-r--r--project2/tablepatch.cpp1
-rw-r--r--project2/variables.cpp1
24 files changed, 487 insertions, 63 deletions
diff --git a/project2/Jamfile.jam b/project2/Jamfile.jam
index 53b530f..040991e 100644
--- a/project2/Jamfile.jam
+++ b/project2/Jamfile.jam
@@ -18,6 +18,7 @@ lib fcgi++ : : <name>fcgi++ ;
lib boost_regex : : <name>boost_regex ;
lib boost_filesystem : : <name>boost_filesystem ;
lib boost_date_time : : <name>boost_date_time ;
+lib boost_program_options : : <name>boost_program_options ;
lib cgicc : : <name>cgicc ;
lib esmtp : : <name>esmtp ;
lib curl : : <name>curl ;
@@ -47,7 +48,7 @@ lib p2uuid :
lib p2common :
appEngine.cpp dataSource.cpp environment.cpp fileStarGlibIoChannel.cpp iHaveParameters.cpp
- iterate.cpp paramChecker.cpp presenter.cpp rawView.cpp dumpTask.cpp
+ iterate.cpp paramChecker.cpp presenter.cpp rawView.cpp dumpTask.cpp logger.cpp
sourceObject.cpp task.cpp variables.cpp view.cpp xmlObjectLoader.cpp exceptions.cpp
sessionClearTask.cpp session.cpp sessionSetTask.cpp commonObjects.cpp xmlPresenter.cpp
rowView.cpp rowSet.cpp rowUser.cpp rowProcessor.cpp config.cpp
@@ -56,6 +57,7 @@ lib p2common :
<library>libxmlpp
<library>boost_filesystem
<library>boost_date_time
+ <library>boost_program_options
;
lib p2xml :
diff --git a/project2/cgi/cgiAppEngine.cpp b/project2/cgi/cgiAppEngine.cpp
index 3a9e362..364d393 100644
--- a/project2/cgi/cgiAppEngine.cpp
+++ b/project2/cgi/cgiAppEngine.cpp
@@ -1,5 +1,4 @@
#include "cgiAppEngine.h"
-#include <syslog.h>
#include <cgicc/Cgicc.h>
#include <cgicc/HTTPContentHeader.h>
#include "cgiEnvironment.h"
@@ -48,6 +47,12 @@ CgiApplicationEngine::env() const
}
void
+CgiApplicationEngine::write(const XmlWriter & w) const
+{
+ w(doc->cobj());
+}
+
+void
CgiApplicationEngine::process() const
{
while (!doc && currentStage) {
diff --git a/project2/cgi/cgiAppEngine.h b/project2/cgi/cgiAppEngine.h
index 5a21e98..25c6537 100644
--- a/project2/cgi/cgiAppEngine.h
+++ b/project2/cgi/cgiAppEngine.h
@@ -8,6 +8,7 @@
#include "../commonObjects.h"
#include "../uuid.h"
#include <boost/intrusive_ptr.hpp>
+#include <boost/function.hpp>
#include <libxml++/document.h>
#include <libxml++/parsers/domparser.h>
@@ -19,16 +20,15 @@ namespace cgicc {
class CgiApplicationEngine : public ApplicationEngine {
public:
+ typedef boost::shared_ptr<xmlpp::Document> XmlDocPtr;
+ typedef boost::function1<void, xmlDocPtr> XmlWriter;
+
CgiApplicationEngine(const CgiEnvironment *);
virtual ~CgiApplicationEngine();
void process() const;
const cgicc::HTTPContentHeader * getHeader() const { return header; }
- template <class Writer>
- void write(const Writer & w) const
- {
- w(doc->cobj());
- }
+ void write(const XmlWriter & w) const;
const Environment * env() const;
SessionPtr session() const;
virtual Glib::ustring resolveCurrentConfig() const;
@@ -45,7 +45,7 @@ class CgiApplicationEngine : public ApplicationEngine {
bool checkDomain(const DomainPlatforms::value_type & i) const;
void loadEngineSection(const xmlpp::Element *) const;
- mutable boost::shared_ptr<xmlpp::Document> doc;
+ mutable XmlDocPtr doc;
class Stage;
typedef boost::intrusive_ptr<Stage> StagePtr;
diff --git a/project2/cgi/cgiCommon.cpp b/project2/cgi/cgiCommon.cpp
index bfbec36..322bdf7 100644
--- a/project2/cgi/cgiCommon.cpp
+++ b/project2/cgi/cgiCommon.cpp
@@ -1,10 +1,10 @@
#include "cgiCommon.h"
+#include "../logger.h"
#include <libxml/tree.h>
#include <glibmm/exception.h>
#include <cgicc/CgiEnvironment.h>
#include <cgicc/HTTPContentHeader.h>
#include <cgicc/HTTPStatusHeader.h>
-#include <fcgi_stdio.h>
#include "cgiEnvironment.h"
#include "cgiAppEngine.h"
#include <boost/bind.hpp>
@@ -19,41 +19,62 @@ xmlWrite(void * _out, const char * buf, int len)
return len;
}
+// These are templates because some people don't inherit their
+// exceptions from std::exception like normal people (Glib)
+const char *
+what(const Glib::Exception & e)
+{
+ return e.what().c_str();
+}
+const char *
+what(const std::exception & e)
+{
+ return e.what();
+}
+template <typename E>
+void
+doExceptionReporting(const E & e, std::ostream & IO)
+{
+ char * buf = __cxxabiv1::__cxa_demangle(typeid(e).name(), NULL, NULL, NULL);
+ Logger()->messagef(LOG_ERR, "%s: Request errored: %s: %s", __FUNCTION__, buf, what(e));
+ cgicc::HTTPStatusHeader header(500, e.what());
+ header.render(IO);
+ IO << "Kaboom!" << std::endl
+ << std::endl
+ << buf << std::endl
+ << e.what() << std::endl;
+ free(buf);
+}
+
void
cgiServe(cgicc::CgiInput * i, std::ostream & IO)
{
+ cgicc::Cgicc cgi(i);
+ CgiEnvironment env(&cgi);
+ env.init();
try {
- cgicc::Cgicc cgi(i);
- CgiEnvironment env(&cgi);
CgiApplicationEngine app(&env);
+
+ Logger()->messagef(LOG_DEBUG, "%s: Processing request", __FUNCTION__);
app.process();
+
+ Logger()->messagef(LOG_DEBUG, "%s: Sending request result", __FUNCTION__);
IO << "Cache-control: no-cache" << std::endl;
app.getHeader()->render(IO);
xmlOutputBufferPtr out = xmlOutputBufferCreateIO(
xmlWrite, NULL, &IO, xmlGetCharEncodingHandler(XML_CHAR_ENCODING_UTF8));
app.write(boost::bind(xmlSaveFileTo, out, _1, "utf-8"));
+
+ Logger()->messagef(LOG_DEBUG, "%s: Completed request", __FUNCTION__);
}
catch (const std::exception & e) {
- cgicc::HTTPStatusHeader header(500, e.what());
- header.render(IO);
- char * buf = __cxxabiv1::__cxa_demangle(typeid(e).name(), NULL, NULL, NULL);
- IO << "Kaboom!" << std::endl
- << std::endl
- << buf << std::endl
- << e.what() << std::endl;
- free(buf);
+ doExceptionReporting(e, IO);
}
catch (const Glib::Exception & e) {
- cgicc::HTTPStatusHeader header(500, e.what());
- header.render(IO);
- char * buf = __cxxabiv1::__cxa_demangle(typeid(e).name(), NULL, NULL, NULL);
- IO << "Kaboom!" << std::endl
- << std::endl
- << buf << std::endl
- << e.what() << std::endl;
- free(buf);
+ doExceptionReporting(e, IO);
}
catch (...) {
+ Logger()->messagef(LOG_ERR, "%s: Request errored: Unknown exception", __FUNCTION__);
cgicc::HTTPStatusHeader header(500, "Unknown exception");
header.render(IO);
IO << "Kaboom!" << std::endl
diff --git a/project2/cgi/cgiEnvironment.cpp b/project2/cgi/cgiEnvironment.cpp
index e541f7f..ae65183 100644
--- a/project2/cgi/cgiEnvironment.cpp
+++ b/project2/cgi/cgiEnvironment.cpp
@@ -2,7 +2,6 @@
#include "../appEngine.h"
#include "../exceptions.h"
#include <map>
-#include <syslog.h>
#include <cgicc/Cgicc.h>
#include <boost/tokenizer.hpp>
@@ -13,6 +12,7 @@ std::vector<X>makeVector(const Y & y)
}
CgiEnvironment::CgiEnvironment(cgicc::Cgicc * c) :
+ Environment(0, NULL),
cgicc::CgiEnvironment(c->getEnvironment()),
elems(makeVector<std::string>(boost::tokenizer<boost::char_separator<char> >(getRedirectURL(), boost::char_separator<char>("/")))),
cgi(c)
@@ -23,6 +23,18 @@ CgiEnvironment::~CgiEnvironment()
{
}
+boost::program_options::options_description
+CgiEnvironment::addOptions(boost::program_options::positional_options_description &)
+{
+ boost::program_options::options_description cgi("Project2 CGI options");
+ return cgi;
+}
+
+void
+CgiEnvironment::postinit(const boost::program_options::options_description &, const boost::program_options::variables_map &)
+{
+}
+
Glib::ustring
CgiEnvironment::getParamUri(unsigned int p) const
{
diff --git a/project2/cgi/cgiEnvironment.h b/project2/cgi/cgiEnvironment.h
index 5c0455c..005a49b 100644
--- a/project2/cgi/cgiEnvironment.h
+++ b/project2/cgi/cgiEnvironment.h
@@ -22,6 +22,10 @@ class CgiEnvironment : public Environment, public cgicc::CgiEnvironment {
std::vector<std::string> elems;
const cgicc::Cgicc * const cgi;
+
+ private:
+ boost::program_options::options_description addOptions(boost::program_options::positional_options_description &);
+ void postinit(const boost::program_options::options_description &, const boost::program_options::variables_map &);
};
#endif
diff --git a/project2/cgi/p2webFCgi.cpp b/project2/cgi/p2webFCgi.cpp
index 620c441..d501787 100644
--- a/project2/cgi/p2webFCgi.cpp
+++ b/project2/cgi/p2webFCgi.cpp
@@ -1,7 +1,7 @@
-#include <syslog.h>
#include "cgiCommon.h"
#include "FCgiIO.h"
#include "../xmlObjectLoader.h"
+#include "../logger.h"
time_t lastPeriodic = 0;
time_t periodicDelay = 600;
@@ -28,7 +28,6 @@ int
main(void)
{
if (!FCGX_IsCGI()) {
- syslog(LOG_NOTICE, "FCGID Startup ($Id$)");
FCGX_Request request;
FCGX_Init();
@@ -38,7 +37,7 @@ main(void)
onAlarm.sa_handler = &p2webGoingIdle;
onAlarm.sa_flags = 0;
if (sigaction(SIGALRM, &onAlarm, NULL)) {
- syslog(LOG_WARNING, "Failed to set signal handler");
+ fprintf(stderr, "Failed to set signal handler\n");
}
alarm(60);
while (FCGX_Accept_r(&request) == 0) {
@@ -51,9 +50,9 @@ main(void)
p2webPeriodic();
}
}
+ return 0;
}
else {
- syslog(LOG_ERR, "FCGID not running as a FastCGI program");
+ return 1;
}
- return 0;
}
diff --git a/project2/console/consoleEnvironment.cpp b/project2/console/consoleEnvironment.cpp
index 0d2f026..1c39dd0 100644
--- a/project2/console/consoleEnvironment.cpp
+++ b/project2/console/consoleEnvironment.cpp
@@ -1,13 +1,17 @@
#include "consoleEnvironment.h"
#include <sys/utsname.h>
-#include <syslog.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
+#include "../logger.h"
+#include <iostream>
+#include <string>
+#include <boost/program_options.hpp>
+
+namespace po = boost::program_options;
ConsoleEnvironment::ConsoleEnvironment(int argc, char ** argv) :
- scriptname(argv[0]),
- todolist(argv + 1, argv + argc)
+ Environment(argc, argv)
{
}
@@ -15,6 +19,33 @@ ConsoleEnvironment::~ConsoleEnvironment()
{
}
+boost::program_options::options_description
+ConsoleEnvironment::addOptions(boost::program_options::positional_options_description & poptions)
+{
+ boost::program_options::options_description console("Project2 Console options");
+ console.add_options()
+ //("version,v", "Print version and exit")
+ ("help,h", "Print usage and exit")
+ ("syslogident,i", po::value<std::string>(&scriptname)->default_value(scriptname), "Log to syslog with ident <arg>")
+ ("file,f", po::value<ToDoList>(&todolist), "File to process")
+ ;
+ poptions.add("file", -1);
+ return console;
+}
+
+void
+ConsoleEnvironment::postinit(const boost::program_options::options_description & options, const boost::program_options::variables_map & settings)
+{
+ if (settings.count("version")) {
+ //show_version(version);
+ exit(1);
+ }
+ if (settings.count("help")) {
+ std::cout << options << std::endl;
+ exit(1);
+ }
+}
+
Glib::ustring
ConsoleEnvironment::getParamUri(unsigned int idx) const
{
@@ -32,8 +63,8 @@ ConsoleEnvironment::getServerName() const
{
struct utsname name;
if (uname(&name)) {
- syslog(LOG_WARNING, "%s: Unable to determine local host name (%d:%s)",
- __FUNCTION__, errno, strerror(errno));
+ Logger()->messagef(LOG_WARNING, "%s: Unable to determine local host name (%d:%s)",
+ __PRETTY_FUNCTION__, errno, strerror(errno));
return "unknown";
}
else {
@@ -47,3 +78,9 @@ ConsoleEnvironment::getScriptName() const
return scriptname;
}
+const ConsoleEnvironment::ToDoList &
+ConsoleEnvironment::todoList() const
+{
+ return todolist;
+}
+
diff --git a/project2/console/consoleEnvironment.h b/project2/console/consoleEnvironment.h
index faa6431..23bbd05 100644
--- a/project2/console/consoleEnvironment.h
+++ b/project2/console/consoleEnvironment.h
@@ -2,22 +2,28 @@
#define ENVPROC_H
#include <string>
-#include <list>
+#include <vector>
#include <boost/filesystem/path.hpp>
#include "../environment.h"
class ConsoleEnvironment : public Environment {
public:
+ typedef std::vector<boost::filesystem::path> ToDoList;
+
ConsoleEnvironment(int argc, char ** argv);
virtual ~ConsoleEnvironment();
+
Glib::ustring getParamUri(unsigned int idx) const;
Glib::ustring getParamQuery(const std::string & idx) const;
std::string getServerName() const;
std::string getScriptName() const;
+ const ToDoList & todoList() const;
- const std::string scriptname;
- typedef std::list<boost::filesystem::path> ToDoList;
+ private:
+ boost::program_options::options_description addOptions(boost::program_options::positional_options_description &);
+ void postinit(const boost::program_options::options_description &, const boost::program_options::variables_map &);
+ std::string scriptname;
ToDoList todolist;
};
diff --git a/project2/console/p2consoleMain.cpp b/project2/console/p2consoleMain.cpp
index eb3ff0d..eee7603 100644
--- a/project2/console/p2consoleMain.cpp
+++ b/project2/console/p2consoleMain.cpp
@@ -1,14 +1,21 @@
#include <libxml/tree.h>
#include "consoleEnvironment.h"
#include "consoleAppEngine.h"
-#include <iostream>
+#include "../logger.h"
-int main(int argc, char ** argv)
+int
+main(int argc, char ** argv)
{
ConsoleEnvironment env(argc, argv);
- BOOST_FOREACH(const boost::filesystem::path & file, env.todolist) {
+ env.init();
+ BOOST_FOREACH(const boost::filesystem::path & file, env.todoList()) {
+ Logger()->messagef(LOG_DEBUG, "%s: Beginning file '%s'", __FUNCTION__, file.string().c_str());
ConsoleApplicationEngine app(&env, file);
+
+ Logger()->messagef(LOG_DEBUG, "%s: Processing file", __FUNCTION__);
app.process();
+
+ Logger()->messagef(LOG_DEBUG, "%s: Complete", __FUNCTION__);
LoaderBase::onIteration();
}
LoaderBase::onPeriodic();
diff --git a/project2/environment.cpp b/project2/environment.cpp
index c0cc0fa..5c50517 100644
--- a/project2/environment.cpp
+++ b/project2/environment.cpp
@@ -1,11 +1,58 @@
#include "environment.h"
+#include "loggers.h"
+#include <stdio.h>
+#include <fstream>
+#include <boost/filesystem/convenience.hpp>
-Environment::Environment()
+namespace po = boost::program_options;
+
+Environment::Environment(int c, char ** v) :
+ argc(c),
+ argv(v)
+{
+}
+
+void
+Environment::init()
{
+ int clLevel = -1;
+ int slLevel = -1;
+
+ po::options_description common("Project2 Common options");
+ po::positional_options_description poptions;
+ common.add_options()
+ ("sysloglevel,s", po::value<int>(&slLevel)->default_value(-1),
+ "Log to syslog with level <arg> (default OFF)")
+ ("consoleloglevel,c", po::value<int>(&clLevel)->default_value(LOG_WARNING),
+ "Log to console with level <arg> (default WARNING)")
+ ;
+ po::options_description all("Project2 options");
+ all.add(common).add(addOptions(poptions));
+
+ po::variables_map settings;
+ if (argc > 0 && argv != NULL) {
+ po::store(po::command_line_parser(argc, argv).options(all).positional(poptions).run(), settings);
+ }
+ po::store(po::parse_environment(all, "P2_"), settings);
+ if (boost::filesystem::exists(".p2config")) {
+ std::ifstream f(".p2config");
+ po::store(po::parse_config_file(f, all), settings);
+ }
+ po::notify(settings);
+
+ postinit(all, settings);
+
+ if (clLevel >= 0) {
+ Logger()->addLogger(new ConsoleLogDriver(stderr, clLevel, false));
+ }
+ if (slLevel >= 0) {
+ Logger()->addLogger(new SyslogLogDriver(getScriptName().c_str(), slLevel));
+ }
}
Environment::~Environment()
{
+ Logger()->clear();
}
Glib::ustring
diff --git a/project2/environment.h b/project2/environment.h
index 97ae4f1..60b5f66 100644
--- a/project2/environment.h
+++ b/project2/environment.h
@@ -3,20 +3,29 @@
#include <string>
#include <glibmm/ustring.h>
+#include <boost/program_options.hpp>
+#include <boost/function.hpp>
class Environment {
public:
class ParameterTypeNotSupported : public std::exception { };
- Environment();
+
+ Environment(int argc, char ** argv);
virtual ~Environment() = 0;
+ void init();
+
virtual Glib::ustring getParamUri(unsigned int idx) const = 0;
virtual Glib::ustring getParamQuery(const std::string & idx) const = 0;
virtual std::string getServerName() const = 0;
virtual std::string getScriptName() const = 0;
private:
+ virtual boost::program_options::options_description addOptions(boost::program_options::positional_options_description &) = 0;
+ virtual void postinit(const boost::program_options::options_description &, const boost::program_options::variables_map &) = 0;
+ int argc;
+ char ** argv;
};
#endif
diff --git a/project2/fsRows.cpp b/project2/fsRows.cpp
index b55e058..1b2d2ce 100644
--- a/project2/fsRows.cpp
+++ b/project2/fsRows.cpp
@@ -1,4 +1,5 @@
#include "fsRows.h"
+#include "logger.h"
#include "xmlObjectLoader.h"
#include "rowProcessor.h"
#include "exceptions.h"
@@ -8,7 +9,6 @@
#include <boost/algorithm/string/split.hpp>
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
-#include <syslog.h>
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
@@ -194,7 +194,7 @@ FsRows::execute(const Path & dir, const RowProcessor * rp) const
}
}
catch (const boost::filesystem::basic_filesystem_error<Path> & e) {
- fprintf(stderr, "err %s\n", e.what());
+ Logger()->messagef(LOG_WARNING, "%s when processing '%s'", e.what(), dir.string().c_str());
}
depth -= 1;
}
diff --git a/project2/iterate.cpp b/project2/iterate.cpp
index f4c8d81..d56fd31 100644
--- a/project2/iterate.cpp
+++ b/project2/iterate.cpp
@@ -1,6 +1,5 @@
#include "iterate.h"
#include <boost/foreach.hpp>
-#include <syslog.h>
#include "xmlObjectLoader.h"
ElementLoaderImpl<Iterate> iterateLoader("iterate");
diff --git a/project2/logger.cpp b/project2/logger.cpp
new file mode 100644
index 0000000..6133ce9
--- /dev/null
+++ b/project2/logger.cpp
@@ -0,0 +1,182 @@
+#define SYSLOG_NAMES 1 // Enables the definition of names in syslog.h
+
+#include "logger.h"
+#include "loggers.h"
+#include <stdio.h>
+#include <boost/foreach.hpp>
+#include <boost/algorithm/string/case_conv.hpp>
+
+const char * const version = "$Id: logger.cpp 8818 2011-01-10 10:09:59Z danielg $";
+
+Log Logger::log;
+
+Log::Log() :
+ lowestLevel(-1)
+{
+}
+
+Log::~Log()
+{
+ logs.clear();
+}
+
+int
+Log::addLogger(LogDriverBasePtr log)
+{
+ logs[++nextId] = log;
+ if (log->level > lowestLevel) {
+ lowestLevel = log->level;
+ }
+ return nextId;
+}
+
+void
+Log::clear()
+{
+ logs.clear();
+}
+
+const char *
+Log::priorityName(int priority)
+{
+ const char * name = NULL;
+ for (CODE * c = prioritynames; c->c_name; c++) {
+ if (c->c_val == priority) {
+ name = c->c_name;
+ }
+ }
+ return name;
+}
+
+
+void
+Log::message(int priority, const char * msg) const
+{
+ if (priority > lowestLevel) return;
+ BOOST_FOREACH(const LogDrivers::value_type & l, logs) {
+ l.second->message(priority, msg);
+ }
+}
+
+void
+Log::messagef(int priority, const char * msgfmt, ...) const
+{
+ if (priority > lowestLevel) return;
+ va_list v;
+ va_start(v, msgfmt);
+ vmessagef(priority, msgfmt, v);
+ va_end(v);
+}
+
+void
+Log::vmessagef(int priority, const char * msgfmt, va_list va) const
+{
+ if (priority > lowestLevel) return;
+ char * msg;
+ int len = vasprintf(&msg, msgfmt, va);
+ if (len > 0) {
+ message(priority, msg);
+ }
+ free(msg);
+}
+
+Log *
+Logger::operator->() const
+{
+ return &log;
+}
+
+LogDriverBase::LogDriverBase(int l) :
+ level(l)
+{
+}
+
+LogDriverBase::~LogDriverBase()
+{
+}
+
+// File based log driver
+//----------------------
+FileBasedLogDriver::FileBasedLogDriver(FILE * f, int l, bool ts) :
+ LogDriverBase(l),
+ file(f),
+ timestamp(ts)
+{
+}
+FileBasedLogDriver::~FileBasedLogDriver()
+{
+}
+void
+FileBasedLogDriver::message(int priority, const char * msg) const
+{
+ if (priority <= level) {
+ writeTimestamp();
+ writeLevel(priority);
+ fprintf(file, "%s\n", msg);
+ fflush(file);
+ }
+}
+const char *
+FileBasedLogDriver::timeStr() const
+{
+ struct tm tm;
+ time_t t = time(NULL);
+ localtime_r(&t, &tm);
+ strftime(tmbuf, sizeof(tmbuf), "%F %T", &tm);
+ return tmbuf;
+}
+void
+FileBasedLogDriver::writeTimestamp() const
+{
+ if (timestamp) {
+ fprintf(file, "%s ", timeStr());
+ }
+}
+void
+FileBasedLogDriver::writeLevel(int level) const
+{
+ if (timestamp) {
+ fprintf(file, "%-6.*s", 5, boost::algorithm::to_upper_copy(std::string(Log::priorityName(level))).c_str());
+ }
+}
+
+// Consol driver
+//-------------------
+ConsoleLogDriver::ConsoleLogDriver(FILE * f, int l, bool ts) :
+ FileBasedLogDriver(f, l, ts)
+{
+}
+ConsoleLogDriver::~ConsoleLogDriver()
+{
+}
+
+// File log driver
+//-------------------
+FileLogDriver::FileLogDriver(const char * path, int l) :
+ FileBasedLogDriver(fopen(path, "a"), l, true)
+{
+}
+FileLogDriver::~FileLogDriver()
+{
+ fclose(file);
+}
+
+// Syslog Log Driver
+//-------------------
+SyslogLogDriver::SyslogLogDriver(const char * ident, int level, int option, int facility) :
+ LogDriverBase(level)
+{
+ openlog(ident, option, facility);
+}
+SyslogLogDriver::~SyslogLogDriver()
+{
+ closelog();
+}
+void
+SyslogLogDriver::message(int priority, const char * msg) const
+{
+ if (priority <= level) {
+ syslog(priority, "%s", msg);
+ }
+}
+
diff --git a/project2/logger.h b/project2/logger.h
new file mode 100644
index 0000000..5d42631
--- /dev/null
+++ b/project2/logger.h
@@ -0,0 +1,43 @@
+#ifndef LOGGER_H
+#define LOGGER_H
+
+#include <map>
+#include <stdarg.h>
+#include <syslog.h> // Pulled in for easy client lookups of LOG_* priorties
+#include <boost/intrusive_ptr.hpp>
+#include "intrusivePtrBase.h"
+
+class LogDriverBase;
+
+class Log {
+ public:
+ typedef boost::intrusive_ptr<LogDriverBase> LogDriverBasePtr;
+ typedef std::map<int, LogDriverBasePtr> LogDrivers;
+
+ Log();
+ ~Log();
+
+ int addLogger(LogDriverBasePtr);
+ void clear();
+
+ void message(int priority, const char * msg) const;
+ void messagef(int priority, const char * msgfmt, ...) const __attribute__ ((format (printf, 3, 4)));
+ void vmessagef(int priority, const char * msgfmt, va_list) const;
+
+ static const char * priorityName(int priority); // Look up the priority as defined in syslog.h
+
+ private:
+ LogDrivers logs;
+ int lowestLevel;
+ int nextId;
+};
+
+class Logger {
+ public:
+ Log * operator->() const;
+ private:
+ static Log log;
+};
+
+#endif
+
diff --git a/project2/loggers.h b/project2/loggers.h
new file mode 100644
index 0000000..7be5280
--- /dev/null
+++ b/project2/loggers.h
@@ -0,0 +1,55 @@
+#ifndef LOGGERS_H
+#define LOGGERS_H
+
+#include "logger.h"
+
+class LogDriverBase : public virtual IntrusivePtrBase {
+ public:
+ LogDriverBase(int level);
+ virtual ~LogDriverBase();
+
+ virtual void message(int priority, const char * msg) const = 0;
+ const int level;
+};
+
+class FileBasedLogDriver : public LogDriverBase {
+ public:
+ FileBasedLogDriver(FILE *, int level, bool timestamp);
+ virtual ~FileBasedLogDriver() = 0;
+
+ virtual void message(int priority, const char * msg) const;
+
+ protected:
+ void writeTimestamp() const;
+ void writeLevel(int level) const;
+ FILE * file;
+ bool timestamp;
+
+ private:
+ const char * timeStr() const;
+ mutable char tmbuf[30];
+};
+
+class ConsoleLogDriver : public FileBasedLogDriver {
+ public:
+ ConsoleLogDriver(FILE *, int level, bool timestamp);
+ ~ConsoleLogDriver();
+
+};
+
+class FileLogDriver : public FileBasedLogDriver {
+ public:
+ FileLogDriver(const char * path, int level);
+ ~FileLogDriver();
+};
+
+class SyslogLogDriver : public LogDriverBase {
+ public:
+ SyslogLogDriver(const char * ident, int level, int option = 0, int facility = LOG_USER);
+ virtual ~SyslogLogDriver();
+
+ virtual void message(int priority, const char * msg) const;
+};
+
+#endif
+
diff --git a/project2/rdbmsDataSource.cpp b/project2/rdbmsDataSource.cpp
index bd3c0b1..6d9e566 100644
--- a/project2/rdbmsDataSource.cpp
+++ b/project2/rdbmsDataSource.cpp
@@ -2,7 +2,7 @@
#include "xmlObjectLoader.h"
#include <libxml++/nodes/textnode.h>
#include <sys/utsname.h>
-#include <syslog.h>
+#include "logger.h"
#include <errno.h>
#include <sqlext.h>
@@ -56,7 +56,7 @@ RdbmsDataSource::RdbmsDataSource(const xmlpp::Element * p) :
BOOST_FOREACH(const xmlpp::Node * node, p->find("readonly/dsn")) {
const xmlpp::Element * elem = dynamic_cast<const xmlpp::Element *>(node);
if (elem) {
- roDSNs.insert(ReadonlyDSNs::value_type(elem->get_attribute_value("host"), p));
+ roDSNs.insert(ReadonlyDSNs::value_type(elem->get_attribute_value("host"), elem));
}
}
}
@@ -90,8 +90,8 @@ RdbmsDataSource::getReadonly() const
if (localhost.length() == 0 && preferLocal) {
struct utsname name;
if (uname(&name)) {
- syslog(LOG_WARNING, "%s: Unable to determine local host name (%d:%s)",
- __FUNCTION__, errno, strerror(errno));
+ Logger()->messagef(LOG_WARNING, "%s: Unable to determine local host name (%d:%s)",
+ __PRETTY_FUNCTION__, errno, strerror(errno));
localhost = "unknown";
}
else {
@@ -102,8 +102,8 @@ RdbmsDataSource::getReadonly() const
ReadonlyDSNs::const_iterator ro = roDSNs.find(localhost);
try {
if (ro == roDSNs.end()) {
- syslog(LOG_WARNING, "%s: No database host matches local host name (%s) Will use master DSN",
- __FUNCTION__, localhost.c_str());
+ Logger()->messagef(LOG_WARNING, "%s: No database host matches local host name (%s) Will use master DSN",
+ __PRETTY_FUNCTION__, localhost.c_str());
return *connectTo(masterDsn)->connection;
}
return *connectTo(ro->second)->connection;
@@ -162,7 +162,7 @@ RdbmsDataSource::connectTo(const ConnectionInfo & dsn)
}
catch (...) {
// Connection in failed state
- syslog(LOG_WARNING, "%s: Cached connection failed", __FUNCTION__);
+ Logger()->messagef(LOG_DEBUG, "%s: Cached connection failed", __PRETTY_FUNCTION__);
}
}
diff --git a/project2/rowProcessor.cpp b/project2/rowProcessor.cpp
index 71d2548..fbb470a 100644
--- a/project2/rowProcessor.cpp
+++ b/project2/rowProcessor.cpp
@@ -2,7 +2,6 @@
#include "commonObjects.h"
#include <cstdlib>
#include <boost/foreach.hpp>
-#include <syslog.h>
RowProcessor::RowProcessor(const xmlpp::Element * p) :
SourceObject(p),
diff --git a/project2/rowSet.cpp b/project2/rowSet.cpp
index 318407a..2e4b3f7 100644
--- a/project2/rowSet.cpp
+++ b/project2/rowSet.cpp
@@ -1,9 +1,9 @@
#include "rowSet.h"
#include "rowUser.h"
#include "commonObjects.h"
+#include "logger.h"
#include <boost/foreach.hpp>
#include <boost/bind.hpp>
-#include <syslog.h>
RowSet::RowValuesStack RowSet::stack;
@@ -39,7 +39,7 @@ void
RowSet::endRow(const RowSet * r)
{
if (stack.back() != r) {
- syslog(LOG_ERR, "RowSet::endRow: stack is corrupted");
+ Logger()->messagef(LOG_CRIT, "%s: stack is corrupted", __PRETTY_FUNCTION__);
std::abort();
}
stack.pop_back();
diff --git a/project2/sessionSetTask.cpp b/project2/sessionSetTask.cpp
index a4b0e44..401604b 100644
--- a/project2/sessionSetTask.cpp
+++ b/project2/sessionSetTask.cpp
@@ -1,4 +1,3 @@
-#include <syslog.h>
#include <boost/foreach.hpp>
#include "xmlObjectLoader.h"
#include "sessionSetTask.h"
diff --git a/project2/sqlMergeTask.cpp b/project2/sqlMergeTask.cpp
index f707a77..f59cc97 100644
--- a/project2/sqlMergeTask.cpp
+++ b/project2/sqlMergeTask.cpp
@@ -1,5 +1,5 @@
#include "sqlMergeTask.h"
-#include "appEngine.h"
+#include "commonObjects.h"
#include "rdbmsDataSource.h"
#include "exceptions.h"
#include "sqlVariableBinder.h"
diff --git a/project2/tablepatch.cpp b/project2/tablepatch.cpp
index 8acc8da..540da5e 100644
--- a/project2/tablepatch.cpp
+++ b/project2/tablepatch.cpp
@@ -1,5 +1,4 @@
#include "tablepatch.h"
-#include <syslog.h>
#include <stdio.h>
#include <misc.h>
#include <selectcommand.h>
diff --git a/project2/variables.cpp b/project2/variables.cpp
index 20b4fa2..32a1a15 100644
--- a/project2/variables.cpp
+++ b/project2/variables.cpp
@@ -6,7 +6,6 @@
#include "genericVisitor.h"
#include <libxml++/nodes/textnode.h>
#include <stdexcept>
-#include <syslog.h>
#include <boost/tokenizer.hpp>
#include <boost/foreach.hpp>
#include <boost/algorithm/string/predicate.hpp>