diff options
| -rw-r--r-- | project2/Jamfile.jam | 4 | ||||
| -rw-r--r-- | project2/cgi/cgiAppEngine.cpp | 7 | ||||
| -rw-r--r-- | project2/cgi/cgiAppEngine.h | 12 | ||||
| -rw-r--r-- | project2/cgi/cgiCommon.cpp | 59 | ||||
| -rw-r--r-- | project2/cgi/cgiEnvironment.cpp | 14 | ||||
| -rw-r--r-- | project2/cgi/cgiEnvironment.h | 4 | ||||
| -rw-r--r-- | project2/cgi/p2webFCgi.cpp | 9 | ||||
| -rw-r--r-- | project2/console/consoleEnvironment.cpp | 47 | ||||
| -rw-r--r-- | project2/console/consoleEnvironment.h | 12 | ||||
| -rw-r--r-- | project2/console/p2consoleMain.cpp | 13 | ||||
| -rw-r--r-- | project2/environment.cpp | 49 | ||||
| -rw-r--r-- | project2/environment.h | 11 | ||||
| -rw-r--r-- | project2/fsRows.cpp | 4 | ||||
| -rw-r--r-- | project2/iterate.cpp | 1 | ||||
| -rw-r--r-- | project2/logger.cpp | 182 | ||||
| -rw-r--r-- | project2/logger.h | 43 | ||||
| -rw-r--r-- | project2/loggers.h | 55 | ||||
| -rw-r--r-- | project2/rdbmsDataSource.cpp | 14 | ||||
| -rw-r--r-- | project2/rowProcessor.cpp | 1 | ||||
| -rw-r--r-- | project2/rowSet.cpp | 4 | ||||
| -rw-r--r-- | project2/sessionSetTask.cpp | 1 | ||||
| -rw-r--r-- | project2/sqlMergeTask.cpp | 2 | ||||
| -rw-r--r-- | project2/tablepatch.cpp | 1 | ||||
| -rw-r--r-- | project2/variables.cpp | 1 | 
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> | 
