// // SessionPool.cpp // // $Id: //poco/Main/Data/src/SessionPool.cpp#3 $ // // Library: Data // Package: SessionPooling // Module: SessionPool // // Copyright (c) 2006, Applied Informatics Software Engineering GmbH. // and Contributors. // // Permission is hereby granted, free of charge, to any person or organization // obtaining a copy of the software and accompanying documentation covered by // this license (the "Software") to use, reproduce, display, distribute, // execute, and transmit the Software, and to prepare derivative works of the // Software, and to permit third-parties to whom the Software is furnished to // do so, all subject to the following: // // The copyright notices in the Software and this entire statement, including // the above license grant, this restriction and the following disclaimer, // must be included in all copies of the Software, in whole or in part, and // all derivative works of the Software, unless such copies or derivative // works are solely in the form of machine-executable object code generated by // a source language processor. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. // #include "Poco/Data/SessionPool.h" #include "Poco/Data/SessionFactory.h" #include "Poco/Data/DataException.h" #include namespace Poco { namespace Data { SessionPool::SessionPool(const std::string& sessionKey, const std::string& connectionString, int minSessions, int maxSessions, int idleTime): _sessionKey(sessionKey), _connectionString(connectionString), _minSessions(minSessions), _maxSessions(maxSessions), _idleTime(idleTime), _nSessions(0), _janitorTimer(1000*idleTime, 1000*idleTime/4) { Poco::TimerCallback callback(*this, &SessionPool::onJanitorTimer); _janitorTimer.start(callback); } SessionPool::~SessionPool() { _janitorTimer.stop(); } Session SessionPool::get() { Poco::FastMutex::ScopedLock lock(_mutex); purgeDeadSessions(); if (_idleSessions.empty()) { if (_nSessions < _maxSessions) { Session newSession(SessionFactory::instance().create(_sessionKey, _connectionString)); PooledSessionHolderPtr pHolder(new PooledSessionHolder(*this, newSession.impl())); _idleSessions.push_front(pHolder); ++_nSessions; } else throw SessionPoolExhaustedException(_sessionKey, _connectionString); } PooledSessionHolderPtr pHolder(_idleSessions.front()); PooledSessionImplPtr pPSI(new PooledSessionImpl(pHolder)); _activeSessions.push_front(pHolder); _idleSessions.pop_front(); return Session(pPSI); } void SessionPool::purgeDeadSessions() { SessionList::iterator it = _idleSessions.begin(); for (; it != _idleSessions.end(); ) { if (!(*it)->session()->isConnected()) { it = _idleSessions.erase(it); --_nSessions; } else ++it; } } int SessionPool::capacity() const { return _maxSessions; } int SessionPool::used() const { Poco::FastMutex::ScopedLock lock(_mutex); return (int) _activeSessions.size(); } int SessionPool::idle() const { Poco::FastMutex::ScopedLock lock(_mutex); return (int) _idleSessions.size(); } int SessionPool::dead() { Poco::FastMutex::ScopedLock lock(_mutex); int count = 0; SessionList::iterator it = _activeSessions.begin(); SessionList::iterator itEnd = _activeSessions.end(); for (; it != itEnd; ++it) { if (!(*it)->session()->isConnected()) ++count; } return count; } int SessionPool::allocated() const { Poco::FastMutex::ScopedLock lock(_mutex); return _nSessions; } int SessionPool::available() const { return _maxSessions - used(); } void SessionPool::putBack(PooledSessionHolderPtr pHolder) { Poco::FastMutex::ScopedLock lock(_mutex); SessionList::iterator it = std::find(_activeSessions.begin(), _activeSessions.end(), pHolder); if (it != _activeSessions.end()) { if (pHolder->session()->isConnected()) { pHolder->access(); _idleSessions.push_front(pHolder); } else --_nSessions; _activeSessions.erase(it); } else { poco_bugcheck_msg("Unknown session passed to SessionPool::putBack()"); } } void SessionPool::onJanitorTimer(Poco::Timer&) { Poco::FastMutex::ScopedLock lock(_mutex); SessionList::iterator it = _idleSessions.begin(); while (_nSessions > _minSessions && it != _idleSessions.end()) { if ((*it)->idle() > _idleTime || !(*it)->session()->isConnected()) { try { (*it)->session()->close(); } catch (...) { } it = _idleSessions.erase(it); --_nSessions; } else ++it; } } } } // namespace Poco::Data