[icinga-checkins] icinga.org: icinga2/feature/pgsql-fixes-5002: Fix IDO PostgreSQL adapter.

git at icinga.org git at icinga.org
Tue Nov 5 12:40:40 CET 2013


Module: icinga2
Branch: feature/pgsql-fixes-5002
Commit: 5f0c02763cc4183ec4a1440dd792596fcdc3a7c5
URL:    https://git.icinga.org/?p=icinga2.git;a=commit;h=5f0c02763cc4183ec4a1440dd792596fcdc3a7c5

Author: Gunnar Beutner <gunnar.beutner at netways.de>
Date:   Tue Nov  5 12:40:25 2013 +0100

Fix IDO PostgreSQL adapter.

---

 components/db_ido_mysql/idomysqlconnection.cpp |   13 ++++++++++--
 components/db_ido_pgsql/idopgsqlconnection.cpp |   16 ++++++++++++--
 lib/base/exception.h                           |    3 +++
 lib/base/workqueue.cpp                         |   27 ++++++++++++++++++------
 lib/base/workqueue.h                           |    7 ++++++
 lib/db_ido/dbconnection.h                      |    5 +++++
 6 files changed, 60 insertions(+), 11 deletions(-)

diff --git a/components/db_ido_mysql/idomysqlconnection.cpp b/components/db_ido_mysql/idomysqlconnection.cpp
index d421f1e..31b80a0 100644
--- a/components/db_ido_mysql/idomysqlconnection.cpp
+++ b/components/db_ido_mysql/idomysqlconnection.cpp
@@ -23,6 +23,7 @@
 #include "base/utility.h"
 #include "base/application.h"
 #include "base/dynamictype.h"
+#include "base/exception.h"
 #include "db_ido/dbtype.h"
 #include "db_ido/dbvalue.h"
 #include "db_ido_mysql/idomysqlconnection.h"
@@ -250,13 +251,21 @@ Array::Ptr IdoMysqlConnection::Query(const String& query)
 	Log(LogDebug, "db_ido_mysql", "Query: " + query);
 
 	if (mysql_query(&m_Connection, query.CStr()) != 0)
-	    BOOST_THROW_EXCEPTION(std::runtime_error(mysql_error(&m_Connection)));
+		BOOST_THROW_EXCEPTION(
+		    database_error()
+		        << errinfo_message(mysql_error(&m_Connection))
+			<< errinfo_database_query(query)
+		);
 
 	MYSQL_RES *result = mysql_store_result(&m_Connection);
 
 	if (!result) {
 		if (mysql_field_count(&m_Connection) > 0)
-			BOOST_THROW_EXCEPTION(std::runtime_error(mysql_error(&m_Connection)));
+			BOOST_THROW_EXCEPTION(
+			    database_error()
+				<< errinfo_message(mysql_error(&m_Connection))
+				<< errinfo_database_query(query)
+			);
 
 		return Array::Ptr();
 	}
diff --git a/components/db_ido_pgsql/idopgsqlconnection.cpp b/components/db_ido_pgsql/idopgsqlconnection.cpp
index 6f318c0..985b8d9 100644
--- a/components/db_ido_pgsql/idopgsqlconnection.cpp
+++ b/components/db_ido_pgsql/idopgsqlconnection.cpp
@@ -23,6 +23,7 @@
 #include "base/utility.h"
 #include "base/application.h"
 #include "base/dynamictype.h"
+#include "base/exception.h"
 #include "db_ido/dbtype.h"
 #include "db_ido/dbvalue.h"
 #include "db_ido_pgsql/idopgsqlconnection.h"
@@ -256,7 +257,10 @@ Array::Ptr IdoPgsqlConnection::Query(const String& query)
 	PGresult *result = PQexec(m_Connection, query.CStr());
 
 	if (!result)
-	    BOOST_THROW_EXCEPTION(std::runtime_error("unknown error during pgSQL query"));
+		BOOST_THROW_EXCEPTION(
+		    database_error()
+		        << errinfo_database_query(query)
+		);
 
 	if (PQresultStatus(result) == PGRES_COMMAND_OK)
 		return Array::Ptr();
@@ -265,7 +269,11 @@ Array::Ptr IdoPgsqlConnection::Query(const String& query)
 		String message = PQresultErrorMessage(result);
 		PQclear(result);
 
-		BOOST_THROW_EXCEPTION(std::runtime_error(message));
+		BOOST_THROW_EXCEPTION(
+		    database_error()
+		        << errinfo_message(message)
+		        << errinfo_database_query(query)
+		);
 	}
 
 	Array::Ptr rows = boost::make_shared<Array>();
@@ -298,6 +306,10 @@ DbReference IdoPgsqlConnection::GetSequenceValue(const String& table, const Stri
 
 	Dictionary::Ptr row = rows->Get(0);
 
+	std::ostringstream msgbuf;
+	msgbuf << "Sequence Value: " << row->Get("id");
+	Log(LogDebug, "db_ido_pgsql", msgbuf.str());
+
 	return DbReference(Convert::ToLong(row->Get("id")));
 }
 
diff --git a/lib/base/exception.h b/lib/base/exception.h
index 156c8f5..365f175 100644
--- a/lib/base/exception.h
+++ b/lib/base/exception.h
@@ -94,6 +94,9 @@ inline std::string to_string(const errinfo_getaddrinfo_error& e)
 	return gai_strerror(e.value());
 }
 
+struct errinfo_message_;
+typedef boost::error_info<struct errinfo_message_, std::string> errinfo_message;
+
 }
 
 #endif /* EXCEPTION_H */
diff --git a/lib/base/workqueue.cpp b/lib/base/workqueue.cpp
index 05de248..c98eed4 100644
--- a/lib/base/workqueue.cpp
+++ b/lib/base/workqueue.cpp
@@ -29,7 +29,8 @@ using namespace icinga;
 int WorkQueue::m_NextID = 1;
 
 WorkQueue::WorkQueue(size_t maxItems)
-	: m_ID(m_NextID++), m_MaxItems(maxItems), m_Joined(false), m_Stopped(false)
+	: m_ID(m_NextID++), m_MaxItems(maxItems), m_Joined(false),
+	  m_Stopped(false), m_ExceptionCallback(WorkQueue::DefaultExceptionCallback)
 {
 	m_Thread = boost::thread(boost::bind(&WorkQueue::WorkerThreadProc, this));
 }
@@ -73,6 +74,18 @@ boost::thread::id WorkQueue::GetThreadId(void) const
 	return m_Thread.get_id();
 }
 
+void WorkQueue::SetExceptionCallback(const ExceptionCallback& callback)
+{
+	boost::mutex::scoped_lock lock(m_Mutex);
+
+	m_ExceptionCallback = callback;
+}
+
+void WorkQueue::DefaultExceptionCallback(boost::exception_ptr exp)
+{
+	throw;
+}
+
 void WorkQueue::WorkerThreadProc(void)
 {
 	boost::mutex::scoped_lock lock(m_Mutex);
@@ -96,13 +109,13 @@ void WorkQueue::WorkerThreadProc(void)
 			lock.unlock();
 			wi();
 		} catch (const std::exception& ex) {
-			std::ostringstream msgbuf;
-			msgbuf << "Exception thrown in workqueue handler: " << std::endl
-			       << boost::diagnostic_information(ex);
+			lock.lock();
+
+			ExceptionCallback callback = m_ExceptionCallback;
+
+			lock.unlock();
 
-			Log(LogCritical, "base", msgbuf.str());
-		} catch (...) {
-			Log(LogCritical, "base", "Exception of unknown type thrown in workqueue handler.");
+			callback(boost::current_exception());
 		}
 
 		lock.lock();
diff --git a/lib/base/workqueue.h b/lib/base/workqueue.h
index 923916d..cd50abf 100644
--- a/lib/base/workqueue.h
+++ b/lib/base/workqueue.h
@@ -26,6 +26,7 @@
 #include <boost/thread/thread.hpp>
 #include <boost/thread/mutex.hpp>
 #include <boost/thread/condition_variable.hpp>
+#include <boost/exception_ptr.hpp>
 
 namespace icinga
 {
@@ -39,6 +40,7 @@ class I2_BASE_API WorkQueue
 {
 public:
 	typedef boost::function<void (void)> WorkCallback;
+	typedef boost::function<void (boost::exception_ptr)> ExceptionCallback;
 
 	WorkQueue(size_t maxItems = 25000);
 	~WorkQueue(void);
@@ -48,6 +50,8 @@ public:
 
 	boost::thread::id GetThreadId(void) const;
 
+	void SetExceptionCallback(const ExceptionCallback& callback);
+
 private:
 	int m_ID;
 	static int m_NextID;
@@ -59,8 +63,11 @@ private:
 	bool m_Joined;
 	bool m_Stopped;
 	std::deque<WorkCallback> m_Items;
+	ExceptionCallback m_ExceptionCallback;
 
 	void WorkerThreadProc(void);
+
+	static void DefaultExceptionCallback(boost::exception_ptr exp);
 };
 
 }
diff --git a/lib/db_ido/dbconnection.h b/lib/db_ido/dbconnection.h
index 2881048..b52b12f 100644
--- a/lib/db_ido/dbconnection.h
+++ b/lib/db_ido/dbconnection.h
@@ -79,6 +79,11 @@ private:
 	static void ProgramStatusHandler(void);
 };
 
+struct database_error : virtual std::exception, virtual boost::exception { };
+
+struct errinfo_database_query_;
+typedef boost::error_info<struct errinfo_database_query_, std::string> errinfo_database_query;
+
 }
 
 #endif /* DBCONNECTION_H */





More information about the icinga-checkins mailing list