Commit 0a1bf83a authored by Marco De Marco's avatar Marco De Marco
Browse files

Connection manager refactored to Tango

parent 3274ba01
Loading
Loading
Loading
Loading
+124 −0
Original line number Diff line number Diff line
#include <ConnectionManager.h>
#include <Destination.h>

#include <sstream>

#include <logging.h>

#include <soci/mysql/soci-mysql.h>

//=============================================================================
//	ConnectionManager::ConnectionManager()
//=============================================================================
ConnectionManager::ConnectionManager(Tango::DeviceImpl* device_impl_p, 
	Configuration::SP configuration_sp, Instrument::SPVector instrument_spvector)
	throw(std::runtime_error) : Tango::LogAdapter(device_impl_p)
{
    DEBUG_STREAM << "ConnectionManager::ConnectionManager()" << endl;

	int connectionNumber = configuration_sp->getConnectionNumber();

	if(connectionNumber < 1)
		throw std::runtime_error("Connection number property must be greater than 0");

	Instrument::SPVector::iterator it;
	for(it=instrument_spvector.begin(); it!=instrument_spvector.end(); it++)
	{
        DEBUG_STREAM << "ConnectionManager::ConnectionManager() instrument " 
            << (*it)->getName().c_str() << endl;

		Destination::SP destination_sp = (*it)->getDestination();

		std::string host = destination_sp->getHost();
		int port = destination_sp->getPort();
		std::string user = destination_sp->getUser();
		std::string password = destination_sp->getPassword();
		std::string schema = destination_sp->getSchema();

		PoolID poolID(host, port, user);

		if(m_pool.find(poolID) == m_pool.end())
		{
			PoolSP pool_sp( new soci::connection_pool(connectionNumber) );

			for(int i=0; i<connectionNumber; i++)
			{
				std::stringstream connection;
				connection << " host=" << host;
				connection << " port=" << port;
				connection << " user=" << user;
				connection << " password=" << password;
				connection << " dbname=" << schema;

                #ifdef VERBOSE_DEBUG
                    INFO_STREAM << "Connection: " << connection.str() << endl;
                #endif                
                
				pool_sp->at(i).open(soci::mysql, connection.str());
			}

			m_pool.insert( std::pair<PoolID, PoolSP>(poolID, pool_sp) ); 

            DEBUG_STREAM << "ConnectionManager::ConnectionManager() connection" 
                << " host: " << host.c_str() << " port: " << port 
                << " user: " << user.c_str() << " added" << endl;
		}
		else
		{
            DEBUG_STREAM << "ConnectionManager::ConnectionManager() connection" 
                << " host: " << host.c_str() << " port: " << port 
                << " user: " << user.c_str() << " skipped" << endl;
		}
	}
}

//=============================================================================
//	ConnectionManager::ConnectionManager()
//=============================================================================
ConnectionManager::~ConnectionManager()
{
	DEBUG_STREAM << "ConnectionManager::~ConnectionManager()" << endl;
}

//=============================================================================
//	ConnectionManager::create()
//=============================================================================
ConnectionManager::SP ConnectionManager::create(Tango::DeviceImpl* device_impl_p,
	Configuration::SP configuration_sp, Instrument::SPVector instrument_spvector)
	throw(std::runtime_error)
{
	ConnectionManager::SP c_sp(new ConnectionManager(device_impl_p,
		configuration_sp, instrument_spvector), ConnectionManager::Deleter());

	return c_sp;
}

//=============================================================================
//	ConnectionManager::getSession()
//=============================================================================
ConnectionManager::SessionSP ConnectionManager::getSession(
	Destination::SP destination_sp) throw(std::runtime_error)
{
	DEBUG_STREAM << "ConnectionManager::getSession()" << endl;

	std::string host = destination_sp->getHost();
	int port = destination_sp->getPort();
	std::string user = destination_sp->getUser();

	PoolID poolID(host, port, user); 

	std::map<PoolID, PoolSP>::iterator it;
	if((it = m_pool.find( poolID )) == m_pool.end())
	{
		std::stringstream error_str;
		error_str << "Connection not found for host " << host 
			<< ":" << port << " user: " << user;
		throw std::runtime_error(error_str.str());
	}

	SessionSP session_sp( new soci::session( *(it->second) ) );

	return session_sp;
}

/*___oOo___*/
+93 −0
Original line number Diff line number Diff line
#ifndef CONNECTION_MANAGER_H
#define CONNECTION_MANAGER_H

#include <Instrument.h>
#include <Configuration.h>

#include <tango.h>

#include <map>
#include <sstream>
#include <stdexcept>

#include <boost/shared_ptr.hpp>
#include <boost/scoped_ptr.hpp>

#include <soci/connection-pool.h>
#include <soci/session.h>

class ConnectionManager : public Tango::LogAdapter
{
public:
//------------------------------------------------------------------------------
//	[Public] shared pointer typedef	
//------------------------------------------------------------------------------
	typedef boost::shared_ptr<ConnectionManager> SP;
	typedef boost::shared_ptr<soci::session> SessionSP;

protected:
//------------------------------------------------------------------------------
//	[Protected] constructor destructor deleter
//------------------------------------------------------------------------------
	ConnectionManager(Tango::DeviceImpl*, Configuration::SP, Instrument::SPVector)
		throw(std::runtime_error);
	virtual ~ConnectionManager();

	class Deleter;
	friend class Deleter;
	class Deleter
	{
	public:
		void operator()(ConnectionManager* c) { delete c; }
	};

public:
//------------------------------------------------------------------------------
//	[Public] Users methods
//------------------------------------------------------------------------------
	static ConnectionManager::SP create(Tango::DeviceImpl*, Configuration::SP,
        Instrument::SPVector) throw(std::runtime_error);

	SessionSP getSession(Destination::SP) throw(std::runtime_error);

protected:
//------------------------------------------------------------------------------
//	[Protected] Connection pool class
//------------------------------------------------------------------------------
	class PoolID
	{
	public:
		PoolID(std::string host, int port, std::string user) :
			m_host(host), m_port(port), m_user(user) {}

		std::string getHost() const { return m_host; }
		int getPort() const { return m_port; }
		std::string getUser()const { return m_user; }

	bool operator<(const PoolID& id) const
	{
		std::stringstream str_1;
		str_1 << m_host << m_port << m_user;

		std::stringstream str_2;
		str_2 << id.getHost() << id.getPort() << id.getUser();

		return str_1.str().compare( str_2.str() );
	}

	private:
		std::string m_host;
		int m_port;	
		std::string m_user;	
	};

	typedef boost::shared_ptr< soci::connection_pool > PoolSP;
    
//------------------------------------------------------------------------------
//	[Protected] Class variables
//------------------------------------------------------------------------------
	//Connection pool map
	std::map<PoolID, PoolSP> m_pool;
};

#endif /*!CONNECTION_MANAGER_H*/