19b5730f6SAndrew Rist /**************************************************************
2*1636bfc2Smseidel *
39b5730f6SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
49b5730f6SAndrew Rist * or more contributor license agreements. See the NOTICE file
59b5730f6SAndrew Rist * distributed with this work for additional information
69b5730f6SAndrew Rist * regarding copyright ownership. The ASF licenses this file
79b5730f6SAndrew Rist * to you under the Apache License, Version 2.0 (the
89b5730f6SAndrew Rist * "License"); you may not use this file except in compliance
99b5730f6SAndrew Rist * with the License. You may obtain a copy of the License at
10*1636bfc2Smseidel *
119b5730f6SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12*1636bfc2Smseidel *
139b5730f6SAndrew Rist * Unless required by applicable law or agreed to in writing,
149b5730f6SAndrew Rist * software distributed under the License is distributed on an
159b5730f6SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
169b5730f6SAndrew Rist * KIND, either express or implied. See the License for the
179b5730f6SAndrew Rist * specific language governing permissions and limitations
189b5730f6SAndrew Rist * under the License.
19*1636bfc2Smseidel *
209b5730f6SAndrew Rist *************************************************************/
219b5730f6SAndrew Rist
229b5730f6SAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_connectivity.hxx"
26cdf0e10cSrcweir
27cdf0e10cSrcweir #include <stdio.h>
28cdf0e10cSrcweir #include "ZConnectionPool.hxx"
29cdf0e10cSrcweir #include <com/sun/star/lang/XSingleServiceFactory.hpp>
30cdf0e10cSrcweir #include <com/sun/star/container/ElementExistException.hpp>
31cdf0e10cSrcweir #include <comphelper/extract.hxx>
32cdf0e10cSrcweir #include <comphelper/types.hxx>
33cdf0e10cSrcweir #include <com/sun/star/lang/XComponent.hpp>
34cdf0e10cSrcweir #include "ZPooledConnection.hxx"
35cdf0e10cSrcweir #include "ZPoolCollection.hxx"
36cdf0e10cSrcweir #ifndef _CONNECTIVITY_CONNECTIONWRAPPER_HXX_
37cdf0e10cSrcweir #include "connectivity/ConnectionWrapper.hxx"
38cdf0e10cSrcweir #endif
39cdf0e10cSrcweir #include <com/sun/star/beans/XPropertySet.hpp>
40cdf0e10cSrcweir #ifndef _CONNECTIVITY_CONNECTIONWRAPPER_HXX_
41cdf0e10cSrcweir #include "connectivity/ConnectionWrapper.hxx"
42cdf0e10cSrcweir #endif
43cdf0e10cSrcweir
44cdf0e10cSrcweir
45cdf0e10cSrcweir using namespace ::com::sun::star::uno;
46cdf0e10cSrcweir using namespace ::com::sun::star::lang;
47cdf0e10cSrcweir using namespace ::com::sun::star::sdbc;
48cdf0e10cSrcweir using namespace ::com::sun::star::beans;
49cdf0e10cSrcweir using namespace ::com::sun::star::container;
50cdf0e10cSrcweir using namespace ::osl;
51cdf0e10cSrcweir using namespace connectivity;
52cdf0e10cSrcweir
53cdf0e10cSrcweir #include <algorithm>
54cdf0e10cSrcweir
55cdf0e10cSrcweir //==========================================================================
56cdf0e10cSrcweir //= OPoolTimer
57cdf0e10cSrcweir //==========================================================================
onShot()58cdf0e10cSrcweir void SAL_CALL OPoolTimer::onShot()
59cdf0e10cSrcweir {
60cdf0e10cSrcweir m_pPool->invalidatePooledConnections();
61cdf0e10cSrcweir }
62cdf0e10cSrcweir namespace
63cdf0e10cSrcweir {
64cdf0e10cSrcweir //--------------------------------------------------------------------
getTimeoutNodeName()65cdf0e10cSrcweir static const ::rtl::OUString& getTimeoutNodeName()
66cdf0e10cSrcweir {
67cdf0e10cSrcweir static ::rtl::OUString s_sNodeName = ::rtl::OUString::createFromAscii("Timeout");
68cdf0e10cSrcweir return s_sNodeName;
69cdf0e10cSrcweir }
70*1636bfc2Smseidel
71cdf0e10cSrcweir }
72cdf0e10cSrcweir //==========================================================================
73cdf0e10cSrcweir //= OConnectionPool
74cdf0e10cSrcweir //==========================================================================
75cdf0e10cSrcweir //--------------------------------------------------------------------------
OConnectionPool(const Reference<XDriver> & _xDriver,const Reference<XInterface> & _xDriverNode,const Reference<::com::sun::star::reflection::XProxyFactory> & _rxProxyFactory)76cdf0e10cSrcweir OConnectionPool::OConnectionPool(const Reference< XDriver >& _xDriver,
77cdf0e10cSrcweir const Reference< XInterface >& _xDriverNode,
78cdf0e10cSrcweir const Reference< ::com::sun::star::reflection::XProxyFactory >& _rxProxyFactory)
79cdf0e10cSrcweir :m_xDriver(_xDriver)
80cdf0e10cSrcweir ,m_xDriverNode(_xDriverNode)
81cdf0e10cSrcweir ,m_xProxyFactory(_rxProxyFactory)
82cdf0e10cSrcweir ,m_nTimeOut(10)
83cdf0e10cSrcweir ,m_nALiveCount(10)
84cdf0e10cSrcweir {
85cdf0e10cSrcweir OSL_ENSURE(m_xDriverNode.is(),"NO valid Driver node set!");
86cdf0e10cSrcweir Reference< XComponent > xComponent(m_xDriverNode, UNO_QUERY);
87cdf0e10cSrcweir if (xComponent.is())
88cdf0e10cSrcweir xComponent->addEventListener(this);
89cdf0e10cSrcweir
90cdf0e10cSrcweir Reference<XPropertySet> xProp(m_xDriverNode,UNO_QUERY);
91cdf0e10cSrcweir if(xProp.is())
92cdf0e10cSrcweir xProp->addPropertyChangeListener(getTimeoutNodeName(),this);
93cdf0e10cSrcweir
94cdf0e10cSrcweir OPoolCollection::getNodeValue(getTimeoutNodeName(),m_xDriverNode) >>= m_nALiveCount;
95cdf0e10cSrcweir calculateTimeOuts();
96*1636bfc2Smseidel
97cdf0e10cSrcweir m_xInvalidator = new OPoolTimer(this,::vos::TTimeValue(m_nTimeOut,0));
98cdf0e10cSrcweir m_xInvalidator->start();
99cdf0e10cSrcweir }
100cdf0e10cSrcweir // -----------------------------------------------------------------------------
~OConnectionPool()101cdf0e10cSrcweir OConnectionPool::~OConnectionPool()
102cdf0e10cSrcweir {
103cdf0e10cSrcweir clear(sal_False);
104cdf0e10cSrcweir }
105cdf0e10cSrcweir // -----------------------------------------------------------------------------
106cdf0e10cSrcweir struct TRemoveEventListenerFunctor : ::std::unary_function<TPooledConnections::value_type,void>
107cdf0e10cSrcweir ,::std::unary_function<TActiveConnectionMap::value_type,void>
108cdf0e10cSrcweir {
109cdf0e10cSrcweir OConnectionPool* m_pConnectionPool;
110cdf0e10cSrcweir sal_Bool m_bDispose;
111cdf0e10cSrcweir
TRemoveEventListenerFunctorTRemoveEventListenerFunctor112*1636bfc2Smseidel TRemoveEventListenerFunctor(OConnectionPool* _pConnectionPool,sal_Bool _bDispose = sal_False)
113cdf0e10cSrcweir : m_pConnectionPool(_pConnectionPool)
114cdf0e10cSrcweir ,m_bDispose(_bDispose)
115cdf0e10cSrcweir {
116cdf0e10cSrcweir OSL_ENSURE(m_pConnectionPool,"No connection pool!");
117cdf0e10cSrcweir }
118cdf0e10cSrcweir // -----------------------------------------------------------------------------
disposeTRemoveEventListenerFunctor119cdf0e10cSrcweir void dispose(const Reference<XInterface>& _xComponent)
120cdf0e10cSrcweir {
121cdf0e10cSrcweir Reference< XComponent > xComponent(_xComponent, UNO_QUERY);
122cdf0e10cSrcweir
123cdf0e10cSrcweir if ( xComponent.is() )
124cdf0e10cSrcweir {
125cdf0e10cSrcweir xComponent->removeEventListener(m_pConnectionPool);
126cdf0e10cSrcweir if ( m_bDispose )
127cdf0e10cSrcweir xComponent->dispose();
128cdf0e10cSrcweir }
129cdf0e10cSrcweir }
130cdf0e10cSrcweir // -----------------------------------------------------------------------------
operator ()TRemoveEventListenerFunctor131cdf0e10cSrcweir void operator()(const TPooledConnections::value_type& _aValue)
132cdf0e10cSrcweir {
133cdf0e10cSrcweir dispose(_aValue);
134cdf0e10cSrcweir }
135cdf0e10cSrcweir // -----------------------------------------------------------------------------
operator ()TRemoveEventListenerFunctor136cdf0e10cSrcweir void operator()(const TActiveConnectionMap::value_type& _aValue)
137cdf0e10cSrcweir {
138cdf0e10cSrcweir dispose(_aValue.first);
139cdf0e10cSrcweir }
140cdf0e10cSrcweir };
141cdf0e10cSrcweir // -----------------------------------------------------------------------------
142cdf0e10cSrcweir struct TConnectionPoolFunctor : ::std::unary_function<TConnectionMap::value_type,void>
143cdf0e10cSrcweir {
144cdf0e10cSrcweir OConnectionPool* m_pConnectionPool;
145cdf0e10cSrcweir
TConnectionPoolFunctorTConnectionPoolFunctor146*1636bfc2Smseidel TConnectionPoolFunctor(OConnectionPool* _pConnectionPool)
147cdf0e10cSrcweir : m_pConnectionPool(_pConnectionPool)
148cdf0e10cSrcweir {
149cdf0e10cSrcweir OSL_ENSURE(m_pConnectionPool,"No connection pool!");
150cdf0e10cSrcweir }
operator ()TConnectionPoolFunctor151cdf0e10cSrcweir void operator()(const TConnectionMap::value_type& _aValue)
152cdf0e10cSrcweir {
153cdf0e10cSrcweir ::std::for_each(_aValue.second.aConnections.begin(),_aValue.second.aConnections.end(),TRemoveEventListenerFunctor(m_pConnectionPool,sal_True));
154cdf0e10cSrcweir }
155cdf0e10cSrcweir };
156cdf0e10cSrcweir // -----------------------------------------------------------------------------
clear(sal_Bool _bDispose)157cdf0e10cSrcweir void OConnectionPool::clear(sal_Bool _bDispose)
158cdf0e10cSrcweir {
159cdf0e10cSrcweir MutexGuard aGuard(m_aMutex);
160cdf0e10cSrcweir
161cdf0e10cSrcweir if(m_xInvalidator->isTicking())
162cdf0e10cSrcweir m_xInvalidator->stop();
163cdf0e10cSrcweir
164cdf0e10cSrcweir ::std::for_each(m_aPool.begin(),m_aPool.end(),TConnectionPoolFunctor(this));
165cdf0e10cSrcweir m_aPool.clear();
166cdf0e10cSrcweir
167cdf0e10cSrcweir ::std::for_each(m_aActiveConnections.begin(),m_aActiveConnections.end(),TRemoveEventListenerFunctor(this,_bDispose));
168cdf0e10cSrcweir m_aActiveConnections.clear();
169cdf0e10cSrcweir
170cdf0e10cSrcweir Reference< XComponent > xComponent(m_xDriverNode, UNO_QUERY);
171cdf0e10cSrcweir if (xComponent.is())
172cdf0e10cSrcweir xComponent->removeEventListener(this);
173cdf0e10cSrcweir Reference< XPropertySet > xProp(m_xDriverNode, UNO_QUERY);
174cdf0e10cSrcweir if (xProp.is())
175cdf0e10cSrcweir xProp->removePropertyChangeListener(getTimeoutNodeName(),this);
176cdf0e10cSrcweir
177cdf0e10cSrcweir m_xDriverNode.clear();
178cdf0e10cSrcweir m_xDriver.clear();
179cdf0e10cSrcweir }
180cdf0e10cSrcweir //--------------------------------------------------------------------------
getConnectionWithInfo(const::rtl::OUString & _rURL,const Sequence<PropertyValue> & _rInfo)181cdf0e10cSrcweir Reference< XConnection > SAL_CALL OConnectionPool::getConnectionWithInfo( const ::rtl::OUString& _rURL, const Sequence< PropertyValue >& _rInfo ) throw(SQLException, RuntimeException)
182cdf0e10cSrcweir {
183cdf0e10cSrcweir MutexGuard aGuard(m_aMutex);
184cdf0e10cSrcweir
185cdf0e10cSrcweir Reference<XConnection> xConnection;
186cdf0e10cSrcweir
187cdf0e10cSrcweir // create a unique id and look for it in our map
188cdf0e10cSrcweir Sequence< PropertyValue > aInfo(_rInfo);
189cdf0e10cSrcweir TConnectionMap::key_type nId;
190cdf0e10cSrcweir OConnectionWrapper::createUniqueId(_rURL,aInfo,nId.m_pBuffer);
191cdf0e10cSrcweir TConnectionMap::iterator aIter = m_aPool.find(nId);
192cdf0e10cSrcweir
193cdf0e10cSrcweir if ( m_aPool.end() != aIter )
194cdf0e10cSrcweir xConnection = getPooledConnection(aIter);
195cdf0e10cSrcweir
196cdf0e10cSrcweir if ( !xConnection.is() )
197cdf0e10cSrcweir xConnection = createNewConnection(_rURL,_rInfo);
198*1636bfc2Smseidel
199cdf0e10cSrcweir return xConnection;
200cdf0e10cSrcweir }
201cdf0e10cSrcweir //--------------------------------------------------------------------------
disposing(const::com::sun::star::lang::EventObject & Source)202cdf0e10cSrcweir void SAL_CALL OConnectionPool::disposing( const ::com::sun::star::lang::EventObject& Source ) throw (RuntimeException)
203cdf0e10cSrcweir {
204cdf0e10cSrcweir Reference<XConnection> xConnection(Source.Source,UNO_QUERY);
205cdf0e10cSrcweir if(xConnection.is())
206cdf0e10cSrcweir {
207cdf0e10cSrcweir MutexGuard aGuard(m_aMutex);
208cdf0e10cSrcweir TActiveConnectionMap::iterator aIter = m_aActiveConnections.find(xConnection);
209*1636bfc2Smseidel OSL_ENSURE(aIter != m_aActiveConnections.end(),"OConnectionPool::disposing: Connection wasn't in pool");
210cdf0e10cSrcweir if(aIter != m_aActiveConnections.end())
211cdf0e10cSrcweir { // move the pooled connection back to the pool
212cdf0e10cSrcweir aIter->second.aPos->second.nALiveCount = m_nALiveCount;
213cdf0e10cSrcweir aIter->second.aPos->second.aConnections.push_back(aIter->second.xPooledConnection);
214cdf0e10cSrcweir m_aActiveConnections.erase(aIter);
215cdf0e10cSrcweir }
216cdf0e10cSrcweir }
217cdf0e10cSrcweir else
218cdf0e10cSrcweir {
219cdf0e10cSrcweir m_xDriverNode.clear();
220cdf0e10cSrcweir }
221cdf0e10cSrcweir }
222cdf0e10cSrcweir // -----------------------------------------------------------------------------
createNewConnection(const::rtl::OUString & _rURL,const Sequence<PropertyValue> & _rInfo)223cdf0e10cSrcweir Reference< XConnection> OConnectionPool::createNewConnection(const ::rtl::OUString& _rURL,const Sequence< PropertyValue >& _rInfo)
224cdf0e10cSrcweir {
225*1636bfc2Smseidel // create new pooled connection
226cdf0e10cSrcweir Reference< XPooledConnection > xPooledConnection = new ::connectivity::OPooledConnection(m_xDriver->connect(_rURL,_rInfo),m_xProxyFactory);
227cdf0e10cSrcweir // get the new connection from the pooled connection
228cdf0e10cSrcweir Reference<XConnection> xConnection = xPooledConnection->getConnection();
229cdf0e10cSrcweir if(xConnection.is())
230cdf0e10cSrcweir {
231cdf0e10cSrcweir // add our own as dispose listener to know when we should put the connection back to the pool
232cdf0e10cSrcweir Reference< XComponent > xComponent(xConnection, UNO_QUERY);
233cdf0e10cSrcweir if (xComponent.is())
234cdf0e10cSrcweir xComponent->addEventListener(this);
235cdf0e10cSrcweir
236cdf0e10cSrcweir // save some information to find the right pool later on
237cdf0e10cSrcweir Sequence< PropertyValue > aInfo(_rInfo);
238cdf0e10cSrcweir TConnectionMap::key_type nId;
239cdf0e10cSrcweir OConnectionWrapper::createUniqueId(_rURL,aInfo,nId.m_pBuffer);
240cdf0e10cSrcweir TConnectionPool aPack;
241*1636bfc2Smseidel
242cdf0e10cSrcweir // insert the new connection and struct into the active connection map
243cdf0e10cSrcweir aPack.nALiveCount = m_nALiveCount;
244cdf0e10cSrcweir TActiveConnectionInfo aActiveInfo;
245cdf0e10cSrcweir aActiveInfo.aPos = m_aPool.insert(TConnectionMap::value_type(nId,aPack)).first;
246cdf0e10cSrcweir aActiveInfo.xPooledConnection = xPooledConnection;
247cdf0e10cSrcweir m_aActiveConnections.insert(TActiveConnectionMap::value_type(xConnection,aActiveInfo));
248cdf0e10cSrcweir
249cdf0e10cSrcweir if(m_xInvalidator->isExpired())
250cdf0e10cSrcweir m_xInvalidator->start();
251cdf0e10cSrcweir }
252cdf0e10cSrcweir
253cdf0e10cSrcweir return xConnection;
254cdf0e10cSrcweir }
255cdf0e10cSrcweir // -----------------------------------------------------------------------------
invalidatePooledConnections()256cdf0e10cSrcweir void OConnectionPool::invalidatePooledConnections()
257cdf0e10cSrcweir {
258cdf0e10cSrcweir MutexGuard aGuard(m_aMutex);
259cdf0e10cSrcweir TConnectionMap::iterator aIter = m_aPool.begin();
260cdf0e10cSrcweir for (; aIter != m_aPool.end(); )
261cdf0e10cSrcweir {
262*1636bfc2Smseidel if(!(--(aIter->second.nALiveCount))) // connections are invalid
263cdf0e10cSrcweir {
264cdf0e10cSrcweir ::std::for_each(aIter->second.aConnections.begin(),aIter->second.aConnections.end(),TRemoveEventListenerFunctor(this,sal_True));
265cdf0e10cSrcweir
266cdf0e10cSrcweir aIter->second.aConnections.clear();
267cdf0e10cSrcweir
268cdf0e10cSrcweir // look if the iterator aIter is still present in the active connection map
269cdf0e10cSrcweir TActiveConnectionMap::iterator aActIter = m_aActiveConnections.begin();
270cdf0e10cSrcweir for (; aActIter != m_aActiveConnections.end(); ++aActIter)
271cdf0e10cSrcweir {
272cdf0e10cSrcweir if(aIter == aActIter->second.aPos)
273cdf0e10cSrcweir break;
274cdf0e10cSrcweir }
275cdf0e10cSrcweir if(aActIter == m_aActiveConnections.end())
276cdf0e10cSrcweir {// he isn't so we can delete him
277cdf0e10cSrcweir TConnectionMap::iterator aDeleteIter = aIter;
278cdf0e10cSrcweir ++aIter;
279cdf0e10cSrcweir m_aPool.erase(aDeleteIter);
280cdf0e10cSrcweir }
281cdf0e10cSrcweir else
282cdf0e10cSrcweir ++aIter;
283cdf0e10cSrcweir }
284cdf0e10cSrcweir else
285cdf0e10cSrcweir ++aIter;
286cdf0e10cSrcweir }
287cdf0e10cSrcweir if(!m_aPool.empty())
288cdf0e10cSrcweir m_xInvalidator->start();
289cdf0e10cSrcweir }
290cdf0e10cSrcweir // -----------------------------------------------------------------------------
getPooledConnection(TConnectionMap::iterator & _rIter)291cdf0e10cSrcweir Reference< XConnection> OConnectionPool::getPooledConnection(TConnectionMap::iterator& _rIter)
292cdf0e10cSrcweir {
293cdf0e10cSrcweir Reference<XConnection> xConnection;
294cdf0e10cSrcweir
295cdf0e10cSrcweir if(!_rIter->second.aConnections.empty())
296cdf0e10cSrcweir {
297cdf0e10cSrcweir Reference< XPooledConnection > xPooledConnection = _rIter->second.aConnections.back();
298cdf0e10cSrcweir _rIter->second.aConnections.pop_back();
299cdf0e10cSrcweir
300cdf0e10cSrcweir OSL_ENSURE(xPooledConnection.is(),"Can not be null here!");
301cdf0e10cSrcweir xConnection = xPooledConnection->getConnection();
302cdf0e10cSrcweir Reference< XComponent > xComponent(xConnection, UNO_QUERY);
303cdf0e10cSrcweir if (xComponent.is())
304cdf0e10cSrcweir xComponent->addEventListener(this);
305*1636bfc2Smseidel
306cdf0e10cSrcweir TActiveConnectionInfo aActiveInfo;
307cdf0e10cSrcweir aActiveInfo.aPos = _rIter;
308cdf0e10cSrcweir aActiveInfo.xPooledConnection = xPooledConnection;
309cdf0e10cSrcweir m_aActiveConnections[xConnection] = aActiveInfo;
310cdf0e10cSrcweir }
311cdf0e10cSrcweir return xConnection;
312cdf0e10cSrcweir }
313cdf0e10cSrcweir // -----------------------------------------------------------------------------
propertyChange(const PropertyChangeEvent & evt)314cdf0e10cSrcweir void SAL_CALL OConnectionPool::propertyChange( const PropertyChangeEvent& evt ) throw (::com::sun::star::uno::RuntimeException)
315cdf0e10cSrcweir {
316cdf0e10cSrcweir if(getTimeoutNodeName() == evt.PropertyName)
317cdf0e10cSrcweir {
318cdf0e10cSrcweir evt.NewValue >>= m_nALiveCount;
319cdf0e10cSrcweir calculateTimeOuts();
320cdf0e10cSrcweir }
321cdf0e10cSrcweir }
322cdf0e10cSrcweir // -----------------------------------------------------------------------------
calculateTimeOuts()323cdf0e10cSrcweir void OConnectionPool::calculateTimeOuts()
324cdf0e10cSrcweir {
325cdf0e10cSrcweir sal_Int32 nTimeOutCorrection = 10;
326cdf0e10cSrcweir if(m_nALiveCount < 100)
327cdf0e10cSrcweir nTimeOutCorrection = 20;
328cdf0e10cSrcweir
329cdf0e10cSrcweir m_nTimeOut = m_nALiveCount / nTimeOutCorrection;
330cdf0e10cSrcweir m_nALiveCount = m_nALiveCount / m_nTimeOut;
331cdf0e10cSrcweir }
332cdf0e10cSrcweir // -----------------------------------------------------------------------------
333*1636bfc2Smseidel
334*1636bfc2Smseidel /* vim: set noet sw=4 ts=4: */
335