diff --git a/Data/include/Poco/Data/SessionPool.h b/Data/include/Poco/Data/SessionPool.h index 30f77a75e..47e6d6bae 100644 --- a/Data/include/Poco/Data/SessionPool.h +++ b/Data/include/Poco/Data/SessionPool.h @@ -114,7 +114,28 @@ public: /// If the maximum number of sessions for this pool has /// already been created, a SessionPoolExhaustedException /// is thrown. - + + template + Session get(const std::string& name, const T& value) + /// Returns a Session with requested property set. + /// The property can be diferent from the default pool + /// value, in which case it is reset back to the pool + /// value when the session is reclaimed by the pool. + { + Session& s = get(); + _addPropertyMap.insert(AddPropertyMap::value_type(s.impl(), + std::make_pair(name, s.getProperty(name)))); + s.setProperty(name, value); + + return s; + } + + Session get(const std::string& name, bool value); + /// Returns a Session with requested feature set. + /// The feature can be diferent from the default pool + /// value, in which case it is reset back to the pool + /// value when the session is reclaimed by the pool. + int capacity() const; /// Returns the maximum number of sessions the SessionPool will manage. @@ -163,27 +184,35 @@ protected: void purgeDeadSessions(); int deadImpl(SessionList& rSessions); + void applySettings(SessionImpl* pImpl); void putBack(PooledSessionHolderPtr pHolder); void onJanitorTimer(Poco::Timer&); private: + typedef std::pair PropertyPair; + typedef std::pair FeaturePair; + typedef std::map AddPropertyMap; + typedef std::map AddFeatureMap; + SessionPool(const SessionPool&); SessionPool& operator = (const SessionPool&); void closeAll(SessionList& sessionList); - std::string _connector; - std::string _connectionString; - int _minSessions; - int _maxSessions; - int _idleTime; - int _nSessions; - SessionList _idleSessions; - SessionList _activeSessions; - Poco::Timer _janitorTimer; - FeatureMap _featureMap; - PropertyMap _propertyMap; - bool _shutdown; + std::string _connector; + std::string _connectionString; + int _minSessions; + int _maxSessions; + int _idleTime; + int _nSessions; + SessionList _idleSessions; + SessionList _activeSessions; + Poco::Timer _janitorTimer; + FeatureMap _featureMap; + PropertyMap _propertyMap; + bool _shutdown; + AddPropertyMap _addPropertyMap; + AddFeatureMap _addFeatureMap; mutable Poco::Mutex _mutex; diff --git a/Data/src/SessionPool.cpp b/Data/src/SessionPool.cpp index dda09819f..1ea64e912 100644 --- a/Data/src/SessionPool.cpp +++ b/Data/src/SessionPool.cpp @@ -65,6 +65,17 @@ SessionPool::~SessionPool() } +Session SessionPool::get(const std::string& name, bool value) +{ + Session& s = get(); + _addFeatureMap.insert(AddFeatureMap::value_type(s.impl(), + std::make_pair(name, s.getFeature(name)))); + s.setFeature(name, value); + + return s; +} + + Session SessionPool::get() { Poco::Mutex::ScopedLock lock(_mutex); @@ -77,14 +88,7 @@ Session SessionPool::get() if (_nSessions < _maxSessions) { Session newSession(SessionFactory::instance().create(_connector, _connectionString)); - - FeatureMap::Iterator fmIt = _featureMap.begin(); - FeatureMap::Iterator fmEnd = _featureMap.end(); - for (; fmIt != fmEnd; ++fmIt) newSession.setFeature(fmIt->first, fmIt->second); - - PropertyMap::Iterator pmIt = _propertyMap.begin(); - PropertyMap::Iterator pmEnd = _propertyMap.end(); - for (; pmIt != pmEnd; ++pmIt) newSession.setProperty(pmIt->first, pmIt->second); + applySettings(newSession.impl()); PooledSessionHolderPtr pHolder(new PooledSessionHolder(*this, newSession.impl())); _idleSessions.push_front(pHolder); @@ -218,16 +222,40 @@ Poco::Any SessionPool::getProperty(const std::string& name) } +void SessionPool::applySettings(SessionImpl* pImpl) +{ + FeatureMap::Iterator fmIt = _featureMap.begin(); + FeatureMap::Iterator fmEnd = _featureMap.end(); + for (; fmIt != fmEnd; ++fmIt) pImpl->setFeature(fmIt->first, fmIt->second); + + PropertyMap::Iterator pmIt = _propertyMap.begin(); + PropertyMap::Iterator pmEnd = _propertyMap.end(); + for (; pmIt != pmEnd; ++pmIt) pImpl->setProperty(pmIt->first, pmIt->second); +} + + void SessionPool::putBack(PooledSessionHolderPtr pHolder) { Poco::Mutex::ScopedLock lock(_mutex); if (_shutdown) return; - + SessionList::iterator it = std::find(_activeSessions.begin(), _activeSessions.end(), pHolder); if (it != _activeSessions.end()) { if (pHolder->session()->isConnected()) { + // reverse settings applied at acquisition time, if any + AddPropertyMap::iterator pIt = _addPropertyMap.find(pHolder->session()); + if (pIt != _addPropertyMap.end()) + pHolder->session()->setProperty(pIt->second.first, pIt->second.second); + + AddFeatureMap::iterator fIt = _addFeatureMap.find(pHolder->session()); + if (fIt != _addFeatureMap.end()) + pHolder->session()->setFeature(fIt->second.first, fIt->second.second); + + // re-apply the default pool settings + applySettings(pHolder->session()); + pHolder->access(); _idleSessions.push_front(pHolder); } diff --git a/Data/testsuite/src/SessionPoolTest.cpp b/Data/testsuite/src/SessionPoolTest.cpp index 8d26b4ada..f7fc66ce6 100644 --- a/Data/testsuite/src/SessionPoolTest.cpp +++ b/Data/testsuite/src/SessionPoolTest.cpp @@ -88,6 +88,9 @@ void SessionPoolTest::testSessionPool() assert (pool.allocated() == pool.used() + pool.idle()); Session s1(pool.get()); + assert (s1.getFeature("f1")); + assert (1 == Poco::AnyCast(s1.getProperty("p1"))); + try { pool.setFeature("f1", true); fail ("must fail"); } catch ( Poco::InvalidAccessException& ) { } @@ -101,7 +104,9 @@ void SessionPoolTest::testSessionPool() assert (pool.dead() == 0); assert (pool.allocated() == pool.used() + pool.idle()); - Session s2(pool.get()); + Session s2(pool.get("f1", false)); + assert (!s2.getFeature("f1")); + assert (1 == Poco::AnyCast(s2.getProperty("p1"))); assert (pool.capacity() == 4); assert (pool.allocated() == 2); @@ -111,7 +116,9 @@ void SessionPoolTest::testSessionPool() assert (pool.allocated() == pool.used() + pool.idle()); { - Session s3(pool.get()); + Session s3(pool.get("p1", 2)); + assert (s3.getFeature("f1")); + assert (2 == Poco::AnyCast(s3.getProperty("p1"))); assert (pool.capacity() == 4); assert (pool.allocated() == 3); @@ -129,6 +136,8 @@ void SessionPoolTest::testSessionPool() assert (pool.allocated() == pool.used() + pool.idle()); Session s4(pool.get()); + assert (s4.getFeature("f1")); + assert (1 == Poco::AnyCast(s4.getProperty("p1"))); assert (pool.capacity() == 4); assert (pool.allocated() == 3);