summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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>