find_package(Termcap)
set(HAVE_TERMCAP "${TERMCAP_FOUND}")
-find_package(PostgreSQL)
-
-if(PostgreSQL_FOUND)
- link_directories(${PostgreSQL_LIBRARY_DIRS})
- include_directories(${PostgreSQL_INCLUDE_DIRS})
-endif()
-
include_directories(
${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/lib
${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/lib
endif()
if(ICINGA2_WITH_MYSQL)
- add_subdirectory(db_ido_mysql)
+ find_package(MySQL)
+
+ if(MYSQL_FOUND)
+ add_subdirectory(db_ido_mysql)
+ add_subdirectory(mysql_shim)
+ else()
+ message(FATAL_ERROR "You have selected MySQL support, but MySQL could not be found. You can disable the MySQL IDO module using -DICINGA2_WITH_MYSQL=OFF.")
+ endif()
endif()
if(ICINGA2_WITH_PGSQL)
- add_subdirectory(db_ido_pgsql)
+ find_package(PostgreSQL)
+
+ if(PostgreSQL_FOUND)
+ add_subdirectory(db_ido_pgsql)
+ add_subdirectory(pgsql_shim)
+ else()
+ message(FATAL_ERROR "You have selected PostgreSQL support, but PostgreSQL could not be found. You can disable the PostgreSQL IDO module using -DICINGA2_WITH_PGSQL=OFF.")
+ endif()
endif()
if(ICINGA2_WITH_DEMO)
convert.cpp datetime.cpp datetime.thpp datetime-script.cpp debuginfo.cpp dictionary.cpp dictionary-script.cpp
configobject.cpp configobject.thpp configobject-script.cpp configtype.cpp configwriter.cpp dependencygraph.cpp
exception.cpp fifo.cpp filelogger.cpp filelogger.thpp initialize.cpp json.cpp
- json-script.cpp loader.cpp logger.cpp logger.thpp math-script.cpp
+ json-script.cpp library.cpp loader.cpp logger.cpp logger.thpp math-script.cpp
netstring.cpp networkstream.cpp number.cpp number-script.cpp object.cpp
object-script.cpp objecttype.cpp primitivetype.cpp process.cpp ringbuffer.cpp scriptframe.cpp
function.cpp function.thpp function-script.cpp
--- /dev/null
+/******************************************************************************
+ * Icinga 2 *
+ * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 2 *
+ * of the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software Foundation *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ******************************************************************************/
+
+#include "base/library.hpp"
+#include "base/loader.hpp"
+#include "base/logger.hpp"
+#include "base/exception.hpp"
+#include "base/application.hpp"
+
+using namespace icinga;
+
+/**
+ * Loads the specified library.
+ *
+ * @param name The name of the library.
+ */
+Library::Library(const String& name)
+{
+ String path;
+#if defined(_WIN32)
+ path = name + ".dll";
+#elif defined(__APPLE__)
+ path = "lib" + name + "." + Application::GetAppSpecVersion() + ".dylib";
+#else /* __APPLE__ */
+ path = "lib" + name + ".so." + Application::GetAppSpecVersion();
+#endif /* _WIN32 */
+
+ Log(LogNotice, "Library")
+ << "Loading library '" << path << "'";
+
+#ifdef _WIN32
+ HMODULE hModule = LoadLibrary(path.CStr());
+
+ if (!hModule) {
+ BOOST_THROW_EXCEPTION(win32_error()
+ << boost::errinfo_api_function("LoadLibrary")
+ << errinfo_win32_error(GetLastError())
+ << boost::errinfo_file_name(path));
+ }
+#else /* _WIN32 */
+ void *hModule = dlopen(path.CStr(), RTLD_NOW | RTLD_GLOBAL);
+
+ if (!hModule) {
+ BOOST_THROW_EXCEPTION(std::runtime_error("Could not load library '" + path + "': " + dlerror()));
+ }
+#endif /* _WIN32 */
+
+ Loader::ExecuteDeferredInitializers();
+
+ m_Handle.reset(new LibraryHandle(hModule), [](LibraryHandle *handle) {
+#ifdef _WIN32
+ FreeLibrary(*handle);
+#else /* _WIN32 */
+ dlclose(*handle);
+#endif /* _WIN32 */
+ });
+}
+
+void *Library::GetSymbolAddress(const String& name) const
+{
+ if (!m_Handle)
+ BOOST_THROW_EXCEPTION(std::runtime_error("Invalid library handle"));
+
+#ifdef _WIN32
+ return GetProcAddress(*m_Handle.get(), name.CStr());
+#else /* _WIN32 */
+ return dlsym(*m_Handle.get(), name.CStr());
+#endif /* _WIN32 */
+}
--- /dev/null
+/******************************************************************************
+ * Icinga 2 *
+ * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 2 *
+ * of the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software Foundation *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ******************************************************************************/
+
+#ifndef LIBRARY_H
+#define LIBRARY_H
+
+#include "base/i2-base.hpp"
+#include "base/string.hpp"
+#include <memory>
+
+namespace icinga
+{
+
+#ifndef _WIN32
+typedef void *LibraryHandle;
+#else /* _WIN32 */
+typedef HMODULE LibraryHandle;
+#endif /* _WIN32 */
+
+class Library
+{
+public:
+ Library(void) = default;
+ Library(const String& name);
+
+ void *GetSymbolAddress(const String& name) const;
+
+ template<typename T>
+ T GetSymbolAddress(const String& name) const
+ {
+ static_assert(!std::is_same<T, void *>::value, "T must not be void *");
+
+ return reinterpret_cast<T>(GetSymbolAddress(name));
+ }
+
+private:
+ std::shared_ptr<LibraryHandle> m_Handle;
+};
+
+}
+
+#endif /* LIBRARY_H */
******************************************************************************/
#include "base/loader.hpp"
+#include "base/logger.hpp"
+#include "base/exception.hpp"
+#include "base/application.hpp"
using namespace icinga;
Log(LogNotice, "config")
<< "Ignoring explicit load request for library \"" << libres << "\".";
- //Loader::LoadExtensionLibrary(libres.GetValue());
return Empty;
}
# along with this program; if not, write to the Free Software Foundation
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
-find_package(MySQL)
+mkclass_target(idomysqlconnection.ti idomysqlconnection.tcpp idomysqlconnection.thpp)
-if(MYSQL_FOUND)
- mkclass_target(idomysqlconnection.ti idomysqlconnection.tcpp idomysqlconnection.thpp)
+set(db_ido_mysql_SOURCES
+ idomysqlconnection.cpp idomysqlconnection.thpp
+)
- set(db_ido_mysql_SOURCES
- idomysqlconnection.cpp idomysqlconnection.thpp
- )
+if(ICINGA2_UNITY_BUILD)
+ mkunity_target(db_ido_mysql db_ido_mysql db_ido_mysql_SOURCES)
+endif()
- if(ICINGA2_UNITY_BUILD)
- mkunity_target(db_ido_mysql db_ido_mysql db_ido_mysql_SOURCES)
- endif()
+add_library(db_ido_mysql STATIC ${db_ido_mysql_SOURCES})
- add_library(db_ido_mysql STATIC ${db_ido_mysql_SOURCES})
+include_directories(${MYSQL_INCLUDE_DIR})
- include_directories(${MYSQL_INCLUDE_DIR})
- target_link_libraries(db_ido_mysql ${Boost_LIBRARIES} ${MYSQL_LIB} base config icinga db_ido)
+target_link_libraries(db_ido_mysql ${Boost_LIBRARIES} base config icinga db_ido)
- set_target_properties (
- db_ido_mysql PROPERTIES
- FOLDER Components
- )
+set_target_properties (
+ db_ido_mysql PROPERTIES
+ FOLDER Components
+)
- install_if_not_exists(
- ${PROJECT_SOURCE_DIR}/etc/icinga2/features-available/ido-mysql.conf
- ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/features-available
- )
+install_if_not_exists(
+ ${PROJECT_SOURCE_DIR}/etc/icinga2/features-available/ido-mysql.conf
+ ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/features-available
+)
- install(
- DIRECTORY schema
- DESTINATION ${CMAKE_INSTALL_DATADIR}/icinga2-ido-mysql
- FILES_MATCHING PATTERN "*.sql"
- )
+install(
+ DIRECTORY schema
+ DESTINATION ${CMAKE_INSTALL_DATADIR}/icinga2-ido-mysql
+ FILES_MATCHING PATTERN "*.sql"
+)
- install(
- DIRECTORY schema/upgrade
- DESTINATION ${CMAKE_INSTALL_DATADIR}/icinga2-ido-mysql/schema
- FILES_MATCHING PATTERN "*.sql"
- )
+install(
+ DIRECTORY schema/upgrade
+ DESTINATION ${CMAKE_INSTALL_DATADIR}/icinga2-ido-mysql/schema
+ FILES_MATCHING PATTERN "*.sql"
+)
- set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "${CPACK_NSIS_EXTRA_INSTALL_COMMANDS}" PARENT_SCOPE)
-else()
- message(FATAL_ERROR "You have selected MySQL support, but MySQL could not be found. You can disable the MySQL IDO module using -DICINGA2_WITH_MYSQL=OFF.")
-endif()
+set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "${CPACK_NSIS_EXTRA_INSTALL_COMMANDS}" PARENT_SCOPE)
ObjectImpl<IdoMysqlConnection>::OnConfigLoaded();
m_QueryQueue.SetName("IdoMysqlConnection, " + GetName());
+
+ Library shimLibrary{"mysql_shim"};
+
+ auto create_mysql_shim = shimLibrary.GetSymbolAddress<create_mysql_shim_ptr>("create_mysql_shim");
+
+ m_Mysql.reset(create_mysql_shim());
+
+ std::swap(m_Library, shimLibrary);
}
void IdoMysqlConnection::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata)
m_ReconnectTimer->Start();
m_ReconnectTimer->Reschedule(0);
- ASSERT(mysql_thread_safe());
+ ASSERT(m_Mysql->thread_safe());
}
void IdoMysqlConnection::Pause(void)
<< "Exception during database operation: " << DiagnosticInformation(exp);
if (GetConnected()) {
- mysql_close(&m_Connection);
+ m_Mysql->close(&m_Connection);
SetConnected(false);
}
return;
Query("COMMIT");
- mysql_close(&m_Connection);
+ m_Mysql->close(&m_Connection);
SetConnected(false);
}
if (GetConnected()) {
/* Check if we're really still connected */
- if (mysql_ping(&m_Connection) == 0)
+ if (m_Mysql->ping(&m_Connection) == 0)
return;
- mysql_close(&m_Connection);
+ m_Mysql->close(&m_Connection);
SetConnected(false);
reconnect = true;
}
sslCipher = (!isslCipher.IsEmpty()) ? isslCipher.CStr() : nullptr;
/* connection */
- if (!mysql_init(&m_Connection)) {
+ if (!m_Mysql->init(&m_Connection)) {
Log(LogCritical, "IdoMysqlConnection")
<< "mysql_init() failed: out of memory";
}
if (enableSsl)
- mysql_ssl_set(&m_Connection, sslKey, sslCert, sslCa, sslCaPath, sslCipher);
+ m_Mysql->ssl_set(&m_Connection, sslKey, sslCert, sslCa, sslCaPath, sslCipher);
- if (!mysql_real_connect(&m_Connection, host, user, passwd, db, port, socket_path, CLIENT_FOUND_ROWS | CLIENT_MULTI_STATEMENTS)) {
+ if (!m_Mysql->real_connect(&m_Connection, host, user, passwd, db, port, socket_path, CLIENT_FOUND_ROWS | CLIENT_MULTI_STATEMENTS)) {
Log(LogCritical, "IdoMysqlConnection")
<< "Connection to database '" << db << "' with user '" << user << "' on '" << host << ":" << port
- << "' " << (enableSsl ? "(SSL enabled) " : "") << "failed: \"" << mysql_error(&m_Connection) << "\"";
+ << "' " << (enableSsl ? "(SSL enabled) " : "") << "failed: \"" << m_Mysql->error(&m_Connection) << "\"";
- BOOST_THROW_EXCEPTION(std::runtime_error(mysql_error(&m_Connection)));
+ BOOST_THROW_EXCEPTION(std::runtime_error(m_Mysql->error(&m_Connection)));
}
SetConnected(true);
row = FetchRow(result);
if (!row) {
- mysql_close(&m_Connection);
+ m_Mysql->close(&m_Connection);
SetConnected(false);
Log(LogCritical, "IdoMysqlConnection", "Schema does not provide any valid version! Verify your schema installation.");
SetSchemaVersion(version);
if (Utility::CompareVersion(IDO_COMPAT_SCHEMA_VERSION, version) < 0) {
- mysql_close(&m_Connection);
+ m_Mysql->close(&m_Connection);
SetConnected(false);
Log(LogCritical, "IdoMysqlConnection")
<< "Last update by '" << endpoint_name << "' was " << status_update_age << "s ago.";
if (status_update_age < GetFailoverTimeout()) {
- mysql_close(&m_Connection);
+ m_Mysql->close(&m_Connection);
SetConnected(false);
SetShouldConnect(false);
Log(LogNotice, "IdoMysqlConnection")
<< "Local endpoint '" << my_endpoint->GetName() << "' is not authoritative, bailing out.";
- mysql_close(&m_Connection);
+ m_Mysql->close(&m_Connection);
SetConnected(false);
return;
String query = querybuf.str();
- if (mysql_query(&m_Connection, query.CStr()) != 0) {
+ if (m_Mysql->query(&m_Connection, query.CStr()) != 0) {
std::ostringstream msgbuf;
- String message = mysql_error(&m_Connection);
+ String message = m_Mysql->error(&m_Connection);
msgbuf << "Error \"" << message << "\" when executing query \"" << query << "\"";
Log(LogCritical, "IdoMysqlConnection", msgbuf.str());
BOOST_THROW_EXCEPTION(
database_error()
- << errinfo_message(mysql_error(&m_Connection))
+ << errinfo_message(m_Mysql->error(&m_Connection))
<< errinfo_database_query(query)
);
}
for (std::vector<IdoAsyncQuery>::size_type i = offset; i < offset + count; i++) {
const IdoAsyncQuery& aq = queries[i];
- MYSQL_RES *result = mysql_store_result(&m_Connection);
+ MYSQL_RES *result = m_Mysql->store_result(&m_Connection);
- m_AffectedRows = mysql_affected_rows(&m_Connection);
+ m_AffectedRows = m_Mysql->affected_rows(&m_Connection);
IdoMysqlResult iresult;
if (!result) {
- if (mysql_field_count(&m_Connection) > 0) {
+ if (m_Mysql->field_count(&m_Connection) > 0) {
std::ostringstream msgbuf;
- String message = mysql_error(&m_Connection);
+ String message = m_Mysql->error(&m_Connection);
msgbuf << "Error \"" << message << "\" when executing query \"" << aq.Query << "\"";
Log(LogCritical, "IdoMysqlConnection", msgbuf.str());
BOOST_THROW_EXCEPTION(
database_error()
- << errinfo_message(mysql_error(&m_Connection))
+ << errinfo_message(m_Mysql->error(&m_Connection))
<< errinfo_database_query(query)
);
}
} else
- iresult = IdoMysqlResult(result, std::ptr_fun(mysql_free_result));
+ iresult = IdoMysqlResult(result, std::bind(&MysqlInterface::free_result, std::cref(m_Mysql), _1));
if (aq.Callback)
aq.Callback(iresult);
- if (mysql_next_result(&m_Connection) > 0) {
+ if (m_Mysql->next_result(&m_Connection) > 0) {
std::ostringstream msgbuf;
- String message = mysql_error(&m_Connection);
+ String message = m_Mysql->error(&m_Connection);
msgbuf << "Error \"" << message << "\" when executing query \"" << query << "\"";
Log(LogCritical, "IdoMysqlConnection", msgbuf.str());
BOOST_THROW_EXCEPTION(
database_error()
- << errinfo_message(mysql_error(&m_Connection))
+ << errinfo_message(m_Mysql->error(&m_Connection))
<< errinfo_database_query(query)
);
}
IncreaseQueryCount();
- if (mysql_query(&m_Connection, query.CStr()) != 0) {
+ if (m_Mysql->query(&m_Connection, query.CStr()) != 0) {
std::ostringstream msgbuf;
- String message = mysql_error(&m_Connection);
+ String message = m_Mysql->error(&m_Connection);
msgbuf << "Error \"" << message << "\" when executing query \"" << query << "\"";
Log(LogCritical, "IdoMysqlConnection", msgbuf.str());
BOOST_THROW_EXCEPTION(
database_error()
- << errinfo_message(mysql_error(&m_Connection))
+ << errinfo_message(m_Mysql->error(&m_Connection))
<< errinfo_database_query(query)
);
}
- MYSQL_RES *result = mysql_store_result(&m_Connection);
+ MYSQL_RES *result = m_Mysql->store_result(&m_Connection);
- m_AffectedRows = mysql_affected_rows(&m_Connection);
+ m_AffectedRows = m_Mysql->affected_rows(&m_Connection);
if (!result) {
- if (mysql_field_count(&m_Connection) > 0) {
+ if (m_Mysql->field_count(&m_Connection) > 0) {
std::ostringstream msgbuf;
- String message = mysql_error(&m_Connection);
+ String message = m_Mysql->error(&m_Connection);
msgbuf << "Error \"" << message << "\" when executing query \"" << query << "\"";
Log(LogCritical, "IdoMysqlConnection", msgbuf.str());
BOOST_THROW_EXCEPTION(
database_error()
- << errinfo_message(mysql_error(&m_Connection))
+ << errinfo_message(m_Mysql->error(&m_Connection))
<< errinfo_database_query(query)
);
}
return IdoMysqlResult();
}
- return IdoMysqlResult(result, std::ptr_fun(mysql_free_result));
+ return IdoMysqlResult(result, std::bind(&MysqlInterface::free_result, std::cref(m_Mysql), _1));
}
DbReference IdoMysqlConnection::GetLastInsertID(void)
{
AssertOnWorkQueue();
- return DbReference(mysql_insert_id(&m_Connection));
+ return DbReference(m_Mysql->insert_id(&m_Connection));
}
int IdoMysqlConnection::GetAffectedRows(void)
size_t length = utf8s.GetLength();
char *to = new char[utf8s.GetLength() * 2 + 1];
- mysql_real_escape_string(&m_Connection, to, utf8s.CStr(), length);
+ m_Mysql->real_escape_string(&m_Connection, to, utf8s.CStr(), length);
String result = String(to);
MYSQL_FIELD *field;
unsigned long *lengths, i;
- row = mysql_fetch_row(result.get());
+ row = m_Mysql->fetch_row(result.get());
if (!row)
return nullptr;
- lengths = mysql_fetch_lengths(result.get());
+ lengths = m_Mysql->fetch_lengths(result.get());
if (!lengths)
return nullptr;
Dictionary::Ptr dict = new Dictionary();
- mysql_field_seek(result.get(), 0);
- for (field = mysql_fetch_field(result.get()), i = 0; field; field = mysql_fetch_field(result.get()), i++)
+ m_Mysql->field_seek(result.get(), 0);
+ for (field = m_Mysql->fetch_field(result.get()), i = 0; field; field = m_Mysql->fetch_field(result.get()), i++)
dict->Set(field->name, String(row[i], row[i] + lengths[i]));
return dict;
#define IDOMYSQLCONNECTION_H
#include "db_ido_mysql/idomysqlconnection.thpp"
+#include "mysql_shim/mysqlinterface.hpp"
#include "base/array.hpp"
#include "base/timer.hpp"
#include "base/workqueue.hpp"
-#include <mysql.h>
+#include "base/library.hpp"
namespace icinga
{
WorkQueue m_QueryQueue;
+ Library m_Library;
+ std::unique_ptr<MysqlInterface, MysqlInterfaceDeleter> m_Mysql;
+
MYSQL m_Connection;
int m_AffectedRows;
unsigned int m_MaxPacketSize;
# along with this program; if not, write to the Free Software Foundation
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
-if(PostgreSQL_FOUND)
- mkclass_target(idopgsqlconnection.ti idopgsqlconnection.tcpp idopgsqlconnection.thpp)
-
- set(db_ido_pgsql_SOURCES
- idopgsqlconnection.cpp idopgsqlconnection.thpp
- )
-
- if(ICINGA2_UNITY_BUILD)
- mkunity_target(db_ido_pgsql db_ido_pgsql db_ido_pgsql_SOURCES)
- endif()
-
- add_library(db_ido_pgsql STATIC ${db_ido_pgsql_SOURCES})
-
- target_link_libraries(db_ido_pgsql ${Boost_LIBRARIES} ${PostgreSQL_LIBRARIES} base config icinga db_ido)
-
- set_target_properties (
- db_ido_pgsql PROPERTIES
- FOLDER Components
- )
-
- install_if_not_exists(
- ${PROJECT_SOURCE_DIR}/etc/icinga2/features-available/ido-pgsql.conf
- ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/features-available
- )
-
- install(
- DIRECTORY schema
- DESTINATION ${CMAKE_INSTALL_DATADIR}/icinga2-ido-pgsql
- FILES_MATCHING PATTERN "*.sql"
- )
-
- install(
- DIRECTORY schema/upgrade
- DESTINATION ${CMAKE_INSTALL_DATADIR}/icinga2-ido-pgsql/schema
- FILES_MATCHING PATTERN "*.sql"
- )
-
- set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "${CPACK_NSIS_EXTRA_INSTALL_COMMANDS}" PARENT_SCOPE)
-else()
- message(FATAL_ERROR "You have selected PostgreSQL support, but PostgreSQL could not be found. You can disable the PostgreSQL IDO module using -DICINGA2_WITH_PGSQL=OFF.")
+mkclass_target(idopgsqlconnection.ti idopgsqlconnection.tcpp idopgsqlconnection.thpp)
+
+set(db_ido_pgsql_SOURCES
+ idopgsqlconnection.cpp idopgsqlconnection.thpp
+)
+
+if(ICINGA2_UNITY_BUILD)
+ mkunity_target(db_ido_pgsql db_ido_pgsql db_ido_pgsql_SOURCES)
endif()
+
+add_library(db_ido_pgsql STATIC ${db_ido_pgsql_SOURCES})
+
+include_directories(${PostgreSQL_INCLUDE_DIRS})
+
+target_link_libraries(db_ido_pgsql ${Boost_LIBRARIES} base config icinga db_ido)
+
+set_target_properties (
+ db_ido_pgsql PROPERTIES
+ FOLDER Components
+)
+
+install_if_not_exists(
+ ${PROJECT_SOURCE_DIR}/etc/icinga2/features-available/ido-pgsql.conf
+ ${CMAKE_INSTALL_SYSCONFDIR}/icinga2/features-available
+)
+
+install(
+ DIRECTORY schema
+ DESTINATION ${CMAKE_INSTALL_DATADIR}/icinga2-ido-pgsql
+ FILES_MATCHING PATTERN "*.sql"
+)
+
+install(
+ DIRECTORY schema/upgrade
+ DESTINATION ${CMAKE_INSTALL_DATADIR}/icinga2-ido-pgsql/schema
+ FILES_MATCHING PATTERN "*.sql"
+)
+
+set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "${CPACK_NSIS_EXTRA_INSTALL_COMMANDS}" PARENT_SCOPE)
ObjectImpl<IdoPgsqlConnection>::OnConfigLoaded();
m_QueryQueue.SetName("IdoPgsqlConnection, " + GetName());
+
+ Library shimLibrary{"pgsql_shim"};
+
+ auto create_pgsql_shim = shimLibrary.GetSymbolAddress<create_pgsql_shim_ptr>("create_pgsql_shim");
+
+ m_Pgsql.reset(create_pgsql_shim());
+
+ std::swap(m_Library, shimLibrary);
}
void IdoPgsqlConnection::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata)
m_ReconnectTimer->Start();
m_ReconnectTimer->Reschedule(0);
- ASSERT(PQisthreadsafe());
+ ASSERT(m_Pgsql->isthreadsafe());
}
void IdoPgsqlConnection::Pause(void)
<< "Exception during database operation: " << DiagnosticInformation(exp);
if (GetConnected()) {
- PQfinish(m_Connection);
+ m_Pgsql->finish(m_Connection);
SetConnected(false);
}
}
Query("COMMIT");
- PQfinish(m_Connection);
+ m_Pgsql->finish(m_Connection);
SetConnected(false);
}
Query("SELECT 1");
return;
} catch (const std::exception&) {
- PQfinish(m_Connection);
+ m_Pgsql->finish(m_Connection);
SetConnected(false);
reconnect = true;
}
passwd = (!ipasswd.IsEmpty()) ? ipasswd.CStr() : nullptr;
db = (!idb.IsEmpty()) ? idb.CStr() : nullptr;
- m_Connection = PQsetdbLogin(host, port, nullptr, nullptr, db, user, passwd);
+ m_Connection = m_Pgsql->setdbLogin(host, port, nullptr, nullptr, db, user, passwd);
if (!m_Connection)
return;
- if (PQstatus(m_Connection) != CONNECTION_OK) {
- String message = PQerrorMessage(m_Connection);
- PQfinish(m_Connection);
+ if (m_Pgsql->status(m_Connection) != CONNECTION_OK) {
+ String message = m_Pgsql->errorMessage(m_Connection);
+ m_Pgsql->finish(m_Connection);
SetConnected(false);
Log(LogCritical, "IdoPgsqlConnection")
/* explicitely require legacy mode for string escaping in PostgreSQL >= 9.1
* changing standard_conforming_strings to on by default
*/
- if (PQserverVersion(m_Connection) >= 90100)
+ if (m_Pgsql->serverVersion(m_Connection) >= 90100)
result = Query("SET standard_conforming_strings TO off");
String dbVersionName = "idoutils";
Dictionary::Ptr row = FetchRow(result, 0);
if (!row) {
- PQfinish(m_Connection);
+ m_Pgsql->finish(m_Connection);
SetConnected(false);
Log(LogCritical, "IdoPgsqlConnection", "Schema does not provide any valid version! Verify your schema installation.");
SetSchemaVersion(version);
if (Utility::CompareVersion(IDO_COMPAT_SCHEMA_VERSION, version) < 0) {
- PQfinish(m_Connection);
+ m_Pgsql->finish(m_Connection);
SetConnected(false);
Log(LogCritical, "IdoPgsqlConnection")
<< "Last update by '" << endpoint_name << "' was " << status_update_age << "s ago.";
if (status_update_age < GetFailoverTimeout()) {
- PQfinish(m_Connection);
+ m_Pgsql->finish(m_Connection);
SetConnected(false);
SetShouldConnect(false);
Log(LogNotice, "IdoPgsqlConnection")
<< "Local endpoint '" << my_endpoint->GetName() << "' is not authoritative, bailing out.";
- PQfinish(m_Connection);
+ m_Pgsql->finish(m_Connection);
SetConnected(false);
return;
IncreaseQueryCount();
- PGresult *result = PQexec(m_Connection, query.CStr());
+ PGresult *result = m_Pgsql->exec(m_Connection, query.CStr());
if (!result) {
- String message = PQerrorMessage(m_Connection);
+ String message = m_Pgsql->errorMessage(m_Connection);
Log(LogCritical, "IdoPgsqlConnection")
<< "Error \"" << message << "\" when executing query \"" << query << "\"";
);
}
- char *rowCount = PQcmdTuples(result);
+ char *rowCount = m_Pgsql->cmdTuples(result);
m_AffectedRows = atoi(rowCount);
- if (PQresultStatus(result) == PGRES_COMMAND_OK) {
- PQclear(result);
+ if (m_Pgsql->resultStatus(result) == PGRES_COMMAND_OK) {
+ m_Pgsql->clear(result);
return IdoPgsqlResult();
}
- if (PQresultStatus(result) != PGRES_TUPLES_OK) {
- String message = PQresultErrorMessage(result);
- PQclear(result);
+ if (m_Pgsql->resultStatus(result) != PGRES_TUPLES_OK) {
+ String message = m_Pgsql->resultErrorMessage(result);
+ m_Pgsql->clear(result);
Log(LogCritical, "IdoPgsqlConnection")
<< "Error \"" << message << "\" when executing query \"" << query << "\"";
);
}
- return IdoPgsqlResult(result, std::ptr_fun(PQclear));
+ return IdoPgsqlResult(result, std::bind(&PgsqlInterface::clear, std::cref(m_Pgsql), _1));
}
DbReference IdoPgsqlConnection::GetSequenceValue(const String& table, const String& column)
size_t length = utf8s.GetLength();
char *to = new char[utf8s.GetLength() * 2 + 1];
- PQescapeStringConn(m_Connection, to, utf8s.CStr(), length, nullptr);
+ m_Pgsql->escapeStringConn(m_Connection, to, utf8s.CStr(), length, nullptr);
String result = String(to);
{
AssertOnWorkQueue();
- if (row >= PQntuples(result.get()))
+ if (row >= m_Pgsql->ntuples(result.get()))
return nullptr;
- int columns = PQnfields(result.get());
+ int columns = m_Pgsql->nfields(result.get());
Dictionary::Ptr dict = new Dictionary();
for (int column = 0; column < columns; column++) {
Value value;
- if (!PQgetisnull(result.get(), row, column))
- value = PQgetvalue(result.get(), row, column);
+ if (!m_Pgsql->getisnull(result.get(), row, column))
+ value = m_Pgsql->getvalue(result.get(), row, column);
- dict->Set(PQfname(result.get(), column), value);
+ dict->Set(m_Pgsql->fname(result.get(), column), value);
}
return dict;
#define IDOPGSQLCONNECTION_H
#include "db_ido_pgsql/idopgsqlconnection.thpp"
+#include "pgsql_shim/pgsqlinterface.hpp"
#include "base/array.hpp"
#include "base/timer.hpp"
#include "base/workqueue.hpp"
-#include <libpq-fe.h>
+#include "base/library.hpp"
namespace icinga
{
WorkQueue m_QueryQueue;
+ Library m_Library;
+ std::unique_ptr<PgsqlInterface, PgsqlInterfaceDeleter> m_Pgsql;
+
PGconn *m_Connection;
int m_AffectedRows;
--- /dev/null
+# Icinga 2
+# Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+
+include_directories(${MYSQL_INCLUDE_DIR})
+
+set(mysql_shim_SOURCES
+ mysql_shim.def
+ mysqlinterface.cpp
+)
+
+if(ICINGA2_UNITY_BUILD)
+ mkunity_target(mysql_shim mysql_shim mysql_shim_SOURCES)
+endif()
+
+add_library(mysql_shim SHARED ${mysql_shim_SOURCES})
+
+include(GenerateExportHeader)
+generate_export_header(mysql_shim)
+
+target_link_libraries(mysql_shim ${MYSQL_LIB})
+
+set_target_properties (
+ mysql_shim PROPERTIES
+ FOLDER Lib
+ VERSION ${SPEC_VERSION}
+)
+
+install(
+ TARGETS mysql_shim
+ RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}/icinga2
+)
--- /dev/null
+LIBRARY mysql_shim
+EXPORTS
+ create_mysql_shim
--- /dev/null
+/******************************************************************************
+ * Icinga 2 *
+ * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 2 *
+ * of the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software Foundation *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ******************************************************************************/
+
+#include "mysql_shim/mysqlinterface.hpp"
+
+using namespace icinga;
+
+struct MysqlInterfaceImpl : public MysqlInterface
+{
+ void Destroy(void) override
+ {
+ delete this;
+ }
+
+ my_ulonglong affected_rows(MYSQL *mysql) const override
+ {
+ return mysql_affected_rows(mysql);
+ }
+
+ void close(MYSQL *sock) const override
+ {
+ return mysql_close(sock);
+ }
+
+ const char *error(MYSQL *mysql) const override
+ {
+ return mysql_error(mysql);
+ }
+
+ MYSQL_FIELD *fetch_field(MYSQL_RES *result) const override
+ {
+ return mysql_fetch_field(result);
+ }
+
+ unsigned long *fetch_lengths(MYSQL_RES *result) const override
+ {
+ return mysql_fetch_lengths(result);
+ }
+
+ MYSQL_ROW fetch_row(MYSQL_RES *result) const override
+ {
+ return mysql_fetch_row(result);
+ }
+
+ unsigned int field_count(MYSQL *mysql) const override
+ {
+ return mysql_field_count(mysql);
+ }
+
+ MYSQL_FIELD_OFFSET field_seek(MYSQL_RES *result, MYSQL_FIELD_OFFSET offset) const override
+ {
+ return mysql_field_seek(result, offset);
+ }
+
+ void free_result(MYSQL_RES *result) const override
+ {
+ mysql_free_result(result);
+ }
+
+ MYSQL *init(MYSQL *mysql) const override
+ {
+ return mysql_init(mysql);
+ }
+
+ my_ulonglong insert_id(MYSQL *mysql) const override
+ {
+ return mysql_insert_id(mysql);
+ }
+
+ int next_result(MYSQL *mysql) const override
+ {
+ return mysql_next_result(mysql);
+ }
+
+ int ping(MYSQL *mysql) const override
+ {
+ return mysql_ping(mysql);
+ }
+
+ int query(MYSQL *mysql, const char *q) const override
+ {
+ return mysql_query(mysql, q);
+ }
+
+ MYSQL *real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd,
+ const char *db, unsigned int port, const char *unix_socket, unsigned long clientflag) const override
+ {
+ return mysql_real_connect(mysql, host, user, passwd, db, port, unix_socket, clientflag);
+ }
+
+ unsigned long real_escape_string(MYSQL *mysql, char *to, const char *from, unsigned long length) const override
+ {
+ return mysql_real_escape_string(mysql, to, from, length);
+ }
+
+ my_bool ssl_set(MYSQL *mysql, const char *key, const char *cert, const char *ca, const char *capath, const char *cipher) const override
+ {
+ return mysql_ssl_set(mysql, key, cert, ca, capath, cipher);
+ }
+
+ MYSQL_RES *store_result(MYSQL *mysql) const override
+ {
+ return mysql_store_result(mysql);
+ }
+
+ unsigned int thread_safe(void) const override
+ {
+ return mysql_thread_safe();
+ }
+};
+
+MysqlInterface *create_mysql_shim(void)
+{
+ return new MysqlInterfaceImpl();
+}
--- /dev/null
+/******************************************************************************
+ * Icinga 2 *
+ * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 2 *
+ * of the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software Foundation *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ******************************************************************************/
+
+#ifndef MYSQLINTERFACE_H
+#define MYSQLINTERFACE_H
+
+#include "mysql_shim/mysql_shim_export.h"
+#include <memory>
+#include <mysql.h>
+
+namespace icinga
+{
+
+struct MysqlInterface
+{
+ MysqlInterface(const MysqlInterface&) = delete;
+ MysqlInterface& operator=(MysqlInterface&) = delete;
+
+ virtual void Destroy(void) = 0;
+
+ virtual my_ulonglong affected_rows(MYSQL *mysql) const = 0;
+ virtual void close(MYSQL *sock) const = 0;
+ virtual const char *error(MYSQL *mysql) const = 0;
+ virtual MYSQL_FIELD *fetch_field(MYSQL_RES *result) const = 0;
+ virtual unsigned long *fetch_lengths(MYSQL_RES *result) const = 0;
+ virtual MYSQL_ROW fetch_row(MYSQL_RES *result) const = 0;
+ virtual unsigned int field_count(MYSQL *mysql) const = 0;
+ virtual MYSQL_FIELD_OFFSET field_seek(MYSQL_RES *result,
+ MYSQL_FIELD_OFFSET offset) const = 0;
+ virtual void free_result(MYSQL_RES *result) const = 0;
+ virtual MYSQL *init(MYSQL *mysql) const = 0;
+ virtual my_ulonglong insert_id(MYSQL *mysql) const = 0;
+ virtual int next_result(MYSQL *mysql) const = 0;
+ virtual int ping(MYSQL *mysql) const = 0;
+ virtual int query(MYSQL *mysql, const char *q) const = 0;
+ virtual MYSQL *real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd,
+ const char *db, unsigned int port, const char *unix_socket, unsigned long clientflag) const = 0;
+ virtual unsigned long real_escape_string(MYSQL *mysql, char *to, const char *from, unsigned long length) const = 0;
+ virtual my_bool ssl_set(MYSQL *mysql, const char *key, const char *cert, const char *ca, const char *capath, const char *cipher) const = 0;
+ virtual MYSQL_RES *store_result(MYSQL *mysql) const = 0;
+ virtual unsigned int thread_safe(void) const = 0;
+
+protected:
+ MysqlInterface(void) = default;
+ ~MysqlInterface(void) = default;
+};
+
+struct MysqlInterfaceDeleter
+{
+ void operator()(MysqlInterface *ifc) const
+ {
+ ifc->Destroy();
+ }
+};
+
+}
+
+extern "C"
+{
+ MYSQL_SHIM_EXPORT icinga::MysqlInterface *create_mysql_shim(void);
+}
+
+typedef icinga::MysqlInterface *(*create_mysql_shim_ptr)(void);
+
+#endif /* MYSQLINTERFACE_H */
--- /dev/null
+# Icinga 2
+# Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+
+link_directories(${PostgreSQL_LIBRARY_DIRS})
+include_directories(${PostgreSQL_INCLUDE_DIRS})
+
+set(pgsql_shim_SOURCES
+ pgsql_shim.def
+ pgsqlinterface.cpp
+)
+
+if(ICINGA2_UNITY_BUILD)
+ mkunity_target(pgsql_shim pgsql_shim pgsql_shim_SOURCES)
+endif()
+
+add_library(pgsql_shim SHARED ${pgsql_shim_SOURCES})
+
+include(GenerateExportHeader)
+generate_export_header(pgsql_shim)
+
+target_link_libraries(pgsql_shim ${PostgreSQL_LIBRARIES})
+
+set_target_properties (
+ pgsql_shim PROPERTIES
+ FOLDER Lib
+ VERSION ${SPEC_VERSION}
+)
+
+install(
+ TARGETS pgsql_shim
+ RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}/icinga2
+)
--- /dev/null
+LIBRARY pgsql_shim
+EXPORTS
+ create_pgsql_shim
--- /dev/null
+/******************************************************************************
+ * Icinga 2 *
+ * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 2 *
+ * of the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software Foundation *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ******************************************************************************/
+
+#include "pgsql_shim/pgsqlinterface.hpp"
+
+using namespace icinga;
+
+struct PgsqlInterfaceImpl : public PgsqlInterface
+{
+ void Destroy(void) override
+ {
+ delete this;
+ }
+
+ void clear(PGresult *res) const override
+ {
+ PQclear(res);
+ }
+
+ char *cmdTuples(PGresult *res) const override
+ {
+ return PQcmdTuples(res);
+ }
+
+ char *errorMessage(const PGconn *conn) const override
+ {
+ return PQerrorMessage(conn);
+ }
+
+ size_t escapeStringConn(PGconn *conn, char *to, const char *from, size_t length, int *error) const override
+ {
+ return PQescapeStringConn(conn, to, from, length, error);
+ }
+
+ PGresult *exec(PGconn *conn, const char *query) const override
+ {
+ return PQexec(conn, query);
+ }
+
+ void finish(PGconn *conn) const override
+ {
+ PQfinish(conn);
+ }
+
+ char *fname(const PGresult *res, int field_num) const override
+ {
+ return PQfname(res, field_num);
+ }
+
+ int getisnull(const PGresult *res, int tup_num, int field_num) const override
+ {
+ return PQgetisnull(res, tup_num, field_num);
+ }
+
+ char *getvalue(const PGresult *res, int tup_num, int field_num) const override
+ {
+ return PQgetvalue(res, tup_num, field_num);
+ }
+
+ int isthreadsafe(void) const override
+ {
+ return PQisthreadsafe();
+ }
+
+ int nfields(const PGresult *res) const override
+ {
+ return PQnfields(res);
+ }
+
+ int ntuples(const PGresult *res) const override
+ {
+ return PQntuples(res);
+ }
+
+ char *resultErrorMessage(const PGresult *res) const override
+ {
+ return PQresultErrorMessage(res);
+ }
+
+ ExecStatusType resultStatus(const PGresult *res) const override
+ {
+ return PQresultStatus(res);
+ }
+
+ int serverVersion(const PGconn *conn) const override
+ {
+ return PQserverVersion(conn);
+ }
+
+ PGconn *setdbLogin(const char *pghost, const char *pgport, const char *pgoptions, const char *pgtty, const char *dbName, const char *login, const char *pwd) const override
+ {
+ return PQsetdbLogin(pghost, pgport, pgoptions, pgtty, dbName, login, pwd);
+ }
+
+ ConnStatusType status(const PGconn *conn) const override
+ {
+ return PQstatus(conn);
+ }
+};
+
+PgsqlInterface *create_pgsql_shim(void)
+{
+ return new PgsqlInterfaceImpl();
+}
--- /dev/null
+/******************************************************************************
+ * Icinga 2 *
+ * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 2 *
+ * of the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software Foundation *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ******************************************************************************/
+
+#ifndef PGSQLINTERFACE_H
+#define PGSQLINTERFACE_H
+
+#include "pgsql_shim/pgsql_shim_export.h"
+#include <memory>
+#include <libpq-fe.h>
+
+namespace icinga
+{
+
+struct PgsqlInterface
+{
+ PgsqlInterface(const PgsqlInterface&) = delete;
+ PgsqlInterface& operator=(PgsqlInterface&) = delete;
+
+ virtual void Destroy(void) = 0;
+
+ virtual void clear(PGresult *res) const = 0;
+ virtual char *cmdTuples(PGresult *res) const = 0;
+ virtual char *errorMessage(const PGconn *conn) const = 0;
+ virtual size_t escapeStringConn(PGconn *conn, char *to, const char *from, size_t length, int *error) const = 0;
+ virtual PGresult *exec(PGconn *conn, const char *query) const = 0;
+ virtual void finish(PGconn *conn) const = 0;
+ virtual char *fname(const PGresult *res, int field_num) const = 0;
+ virtual int getisnull(const PGresult *res, int tup_num, int field_num) const = 0;
+ virtual char *getvalue(const PGresult *res, int tup_num, int field_num) const = 0;
+ virtual int isthreadsafe(void) const = 0;
+ virtual int nfields(const PGresult *res) const = 0;
+ virtual int ntuples(const PGresult *res) const = 0;
+ virtual char *resultErrorMessage(const PGresult *res) const = 0;
+ virtual ExecStatusType resultStatus(const PGresult *res) const = 0;
+ virtual int serverVersion(const PGconn *conn) const = 0;
+ virtual PGconn *setdbLogin(const char *pghost, const char *pgport, const char *pgoptions, const char *pgtty, const char *dbName, const char *login, const char *pwd) const = 0;
+ virtual ConnStatusType status(const PGconn *conn) const = 0;
+
+protected:
+ PgsqlInterface(void) = default;
+ ~PgsqlInterface(void) = default;
+};
+
+struct PgsqlInterfaceDeleter
+{
+ void operator()(PgsqlInterface *ifc) const
+ {
+ ifc->Destroy();
+ }
+};
+
+}
+
+extern "C"
+{
+ PGSQL_SHIM_EXPORT icinga::PgsqlInterface *create_pgsql_shim(void);
+}
+
+typedef icinga::PgsqlInterface *(*create_pgsql_shim_ptr)(void);
+
+#endif /* PGSQLINTERFACE_H */