/* * This file is a part of Winix * and is distributed under the 2-Clause BSD licence. * Author: Tomasz Sowa */ /* * Copyright (c) 2010-2014, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #include #include "dbconn.h" #include "core/log.h" #include "core/error.h" namespace Winix { DbConn::DbConn() { pg_conn = 0; } DbConn::~DbConn() { Close(); } PGconn * DbConn::GetPgConn() { return pg_conn; } void DbConn::SetConnParam(const std::wstring & conn_string) { db_conn_string = conn_string; db_host.clear(); db_port.clear(); db_database.clear(); db_user.clear(); db_pass.clear(); } void DbConn::SetConnParam(const std::wstring & host, const std::wstring & port, const std::wstring & d, const std::wstring & u, const std::wstring & p) { db_conn_string.clear(); db_host = host; db_port = port; db_database = d; db_user = u; db_pass = p; } void DbConn::Connect() { Close(); conn_info.Clear(); conn_info.SetExtented(false); if( !db_conn_string.empty() ) { conn_info << R(db_conn_string); } else { conn_info << R("dbname=") << db_database << R(" user=") << db_user << R(" password=") << db_pass; if( !db_host.empty() ) { conn_info << R(L"hostaddr=") << db_host; } if( !db_port.empty() ) { conn_info << R(L"port=") << db_port; } } pg_conn = PQconnectdb(conn_info.CStr()); // warning! pg_conn can be not null but there cannnot be a connection established // use PQstatus(pg_conn) to check whether the connection works fine } void DbConn::LogConnectionSocket() { log << log2 << "Db: connection to the database works fine" << logend; log << log3 << "Db: connection socket: " << PQsocket(pg_conn) << logend; } void DbConn::WaitForConnection() { if( !pg_conn || PQstatus(pg_conn) != CONNECTION_OK ) { log << log3 << "Db: waiting for the db to be ready...." << logend << logsave; while( !AssertConnection(false, false) ) sleep(5); LogConnectionSocket(); } } void DbConn::Close() { if( pg_conn ) { PQfinish(pg_conn); pg_conn = 0; } } bool DbConn::AssertConnection(bool put_log, bool throw_if_no_connection) { bool was_connection = true; if( !pg_conn ) { was_connection = false; Connect(); } else if( PQstatus(pg_conn) != CONNECTION_OK ) { if( put_log ) log << log2 << "Db: connection to the database is lost, trying to recover" << logend; was_connection = false; PQreset(pg_conn); } if( pg_conn && PQstatus(pg_conn) == CONNECTION_OK ) { if( !was_connection ) { if( put_log ) LogConnectionSocket(); SetDbParameters(); } return true; } else { if( put_log ) log << log1 << "Db: connection to db server cannot be established" << logend; if( throw_if_no_connection ) throw Error(WINIX_ERR_DB_FATAL_ERROR_DURING_CONNECTING); return false; } } void DbConn::SetDbParameters() { if( PQsetClientEncoding(pg_conn, "UTF8") == -1 ) log << log1 << "Db: Can't set the proper client encoding" << logend; } } // namespace Winix