merge the formfield patch from ooo-build
[ooovba.git] / connectivity / source / cpool / ZConnectionPool.cxx
blobd40aeccda0ff42782a594e86b372498745f23da7
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ZConnectionPool.cxx,v $
10 * $Revision: 1.19 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_connectivity.hxx"
34 #include <stdio.h>
35 #include "ZConnectionPool.hxx"
36 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
37 #include <com/sun/star/container/ElementExistException.hpp>
38 #include <comphelper/extract.hxx>
39 #include <comphelper/types.hxx>
40 #include <com/sun/star/lang/XComponent.hpp>
41 #include "ZPooledConnection.hxx"
42 #include "ZPoolCollection.hxx"
43 #ifndef _CONNECTIVITY_CONNECTIONWRAPPER_HXX_
44 #include "connectivity/ConnectionWrapper.hxx"
45 #endif
46 #include <com/sun/star/beans/XPropertySet.hpp>
47 #ifndef _CONNECTIVITY_CONNECTIONWRAPPER_HXX_
48 #include "connectivity/ConnectionWrapper.hxx"
49 #endif
52 using namespace ::com::sun::star::uno;
53 using namespace ::com::sun::star::lang;
54 using namespace ::com::sun::star::sdbc;
55 using namespace ::com::sun::star::beans;
56 using namespace ::com::sun::star::container;
57 using namespace ::osl;
58 using namespace connectivity;
60 #include <algorithm>
62 //==========================================================================
63 //= OPoolTimer
64 //==========================================================================
65 void SAL_CALL OPoolTimer::onShot()
67 m_pPool->invalidatePooledConnections();
69 namespace
71 //--------------------------------------------------------------------
72 static const ::rtl::OUString& getTimeoutNodeName()
74 static ::rtl::OUString s_sNodeName = ::rtl::OUString::createFromAscii("Timeout");
75 return s_sNodeName;
79 //==========================================================================
80 //= OConnectionPool
81 //==========================================================================
82 //--------------------------------------------------------------------------
83 OConnectionPool::OConnectionPool(const Reference< XDriver >& _xDriver,
84 const Reference< XInterface >& _xDriverNode,
85 const Reference< ::com::sun::star::reflection::XProxyFactory >& _rxProxyFactory)
86 :m_xDriver(_xDriver)
87 ,m_xDriverNode(_xDriverNode)
88 ,m_xProxyFactory(_rxProxyFactory)
89 ,m_nTimeOut(10)
90 ,m_nALiveCount(10)
92 OSL_ENSURE(m_xDriverNode.is(),"NO valid Driver node set!");
93 Reference< XComponent > xComponent(m_xDriverNode, UNO_QUERY);
94 if (xComponent.is())
95 xComponent->addEventListener(this);
97 Reference<XPropertySet> xProp(m_xDriverNode,UNO_QUERY);
98 if(xProp.is())
99 xProp->addPropertyChangeListener(getTimeoutNodeName(),this);
101 OPoolCollection::getNodeValue(getTimeoutNodeName(),m_xDriverNode) >>= m_nALiveCount;
102 calculateTimeOuts();
104 m_xInvalidator = new OPoolTimer(this,::vos::TTimeValue(m_nTimeOut,0));
105 m_xInvalidator->start();
107 // -----------------------------------------------------------------------------
108 OConnectionPool::~OConnectionPool()
110 clear(sal_False);
112 // -----------------------------------------------------------------------------
113 struct TRemoveEventListenerFunctor : ::std::unary_function<TPooledConnections::value_type,void>
114 ,::std::unary_function<TActiveConnectionMap::value_type,void>
116 OConnectionPool* m_pConnectionPool;
117 sal_Bool m_bDispose;
119 TRemoveEventListenerFunctor(OConnectionPool* _pConnectionPool,sal_Bool _bDispose = sal_False)
120 : m_pConnectionPool(_pConnectionPool)
121 ,m_bDispose(_bDispose)
123 OSL_ENSURE(m_pConnectionPool,"No connection pool!");
125 // -----------------------------------------------------------------------------
126 void dispose(const Reference<XInterface>& _xComponent)
128 Reference< XComponent > xComponent(_xComponent, UNO_QUERY);
130 if ( xComponent.is() )
132 xComponent->removeEventListener(m_pConnectionPool);
133 if ( m_bDispose )
134 xComponent->dispose();
137 // -----------------------------------------------------------------------------
138 void operator()(const TPooledConnections::value_type& _aValue)
140 dispose(_aValue);
142 // -----------------------------------------------------------------------------
143 void operator()(const TActiveConnectionMap::value_type& _aValue)
145 dispose(_aValue.first);
148 // -----------------------------------------------------------------------------
149 struct TConnectionPoolFunctor : ::std::unary_function<TConnectionMap::value_type,void>
151 OConnectionPool* m_pConnectionPool;
153 TConnectionPoolFunctor(OConnectionPool* _pConnectionPool)
154 : m_pConnectionPool(_pConnectionPool)
156 OSL_ENSURE(m_pConnectionPool,"No connection pool!");
158 void operator()(const TConnectionMap::value_type& _aValue)
160 ::std::for_each(_aValue.second.aConnections.begin(),_aValue.second.aConnections.end(),TRemoveEventListenerFunctor(m_pConnectionPool,sal_True));
163 // -----------------------------------------------------------------------------
164 void OConnectionPool::clear(sal_Bool _bDispose)
166 MutexGuard aGuard(m_aMutex);
168 if(m_xInvalidator->isTicking())
169 m_xInvalidator->stop();
171 ::std::for_each(m_aPool.begin(),m_aPool.end(),TConnectionPoolFunctor(this));
172 m_aPool.clear();
174 ::std::for_each(m_aActiveConnections.begin(),m_aActiveConnections.end(),TRemoveEventListenerFunctor(this,_bDispose));
175 m_aActiveConnections.clear();
177 Reference< XComponent > xComponent(m_xDriverNode, UNO_QUERY);
178 if (xComponent.is())
179 xComponent->removeEventListener(this);
180 Reference< XPropertySet > xProp(m_xDriverNode, UNO_QUERY);
181 if (xProp.is())
182 xProp->removePropertyChangeListener(getTimeoutNodeName(),this);
184 m_xDriverNode.clear();
185 m_xDriver.clear();
187 //--------------------------------------------------------------------------
188 Reference< XConnection > SAL_CALL OConnectionPool::getConnectionWithInfo( const ::rtl::OUString& _rURL, const Sequence< PropertyValue >& _rInfo ) throw(SQLException, RuntimeException)
190 MutexGuard aGuard(m_aMutex);
192 Reference<XConnection> xConnection;
194 // create a unique id and look for it in our map
195 Sequence< PropertyValue > aInfo(_rInfo);
196 TConnectionMap::key_type nId;
197 OConnectionWrapper::createUniqueId(_rURL,aInfo,nId.m_pBuffer);
198 TConnectionMap::iterator aIter = m_aPool.find(nId);
200 if ( m_aPool.end() != aIter )
201 xConnection = getPooledConnection(aIter);
203 if ( !xConnection.is() )
204 xConnection = createNewConnection(_rURL,_rInfo);
206 return xConnection;
208 //--------------------------------------------------------------------------
209 void SAL_CALL OConnectionPool::disposing( const ::com::sun::star::lang::EventObject& Source ) throw (RuntimeException)
211 Reference<XConnection> xConnection(Source.Source,UNO_QUERY);
212 if(xConnection.is())
214 MutexGuard aGuard(m_aMutex);
215 TActiveConnectionMap::iterator aIter = m_aActiveConnections.find(xConnection);
216 OSL_ENSURE(aIter != m_aActiveConnections.end(),"OConnectionPool::disposing: Conenction wasn't in pool");
217 if(aIter != m_aActiveConnections.end())
218 { // move the pooled connection back to the pool
219 aIter->second.aPos->second.nALiveCount = m_nALiveCount;
220 aIter->second.aPos->second.aConnections.push_back(aIter->second.xPooledConnection);
221 m_aActiveConnections.erase(aIter);
224 else
226 m_xDriverNode.clear();
229 // -----------------------------------------------------------------------------
230 Reference< XConnection> OConnectionPool::createNewConnection(const ::rtl::OUString& _rURL,const Sequence< PropertyValue >& _rInfo)
232 // create new pooled conenction
233 Reference< XPooledConnection > xPooledConnection = new ::connectivity::OPooledConnection(m_xDriver->connect(_rURL,_rInfo),m_xProxyFactory);
234 // get the new connection from the pooled connection
235 Reference<XConnection> xConnection = xPooledConnection->getConnection();
236 if(xConnection.is())
238 // add our own as dispose listener to know when we should put the connection back to the pool
239 Reference< XComponent > xComponent(xConnection, UNO_QUERY);
240 if (xComponent.is())
241 xComponent->addEventListener(this);
243 // save some information to find the right pool later on
244 Sequence< PropertyValue > aInfo(_rInfo);
245 TConnectionMap::key_type nId;
246 OConnectionWrapper::createUniqueId(_rURL,aInfo,nId.m_pBuffer);
247 TConnectionPool aPack;
249 // insert the new connection and struct into the active connection map
250 aPack.nALiveCount = m_nALiveCount;
251 TActiveConnectionInfo aActiveInfo;
252 aActiveInfo.aPos = m_aPool.insert(TConnectionMap::value_type(nId,aPack)).first;
253 aActiveInfo.xPooledConnection = xPooledConnection;
254 m_aActiveConnections.insert(TActiveConnectionMap::value_type(xConnection,aActiveInfo));
256 if(m_xInvalidator->isExpired())
257 m_xInvalidator->start();
260 return xConnection;
262 // -----------------------------------------------------------------------------
263 void OConnectionPool::invalidatePooledConnections()
265 MutexGuard aGuard(m_aMutex);
266 TConnectionMap::iterator aIter = m_aPool.begin();
267 for (; aIter != m_aPool.end(); )
269 if(!(--(aIter->second.nALiveCount))) // connections are invalid
271 ::std::for_each(aIter->second.aConnections.begin(),aIter->second.aConnections.end(),TRemoveEventListenerFunctor(this,sal_True));
273 aIter->second.aConnections.clear();
275 // look if the iterator aIter is still present in the active connection map
276 TActiveConnectionMap::iterator aActIter = m_aActiveConnections.begin();
277 for (; aActIter != m_aActiveConnections.end(); ++aActIter)
279 if(aIter == aActIter->second.aPos)
280 break;
282 if(aActIter == m_aActiveConnections.end())
283 {// he isn't so we can delete him
284 TConnectionMap::iterator aDeleteIter = aIter;
285 ++aIter;
286 m_aPool.erase(aDeleteIter);
288 else
289 ++aIter;
291 else
292 ++aIter;
294 if(!m_aPool.empty())
295 m_xInvalidator->start();
297 // -----------------------------------------------------------------------------
298 Reference< XConnection> OConnectionPool::getPooledConnection(TConnectionMap::iterator& _rIter)
300 Reference<XConnection> xConnection;
302 if(!_rIter->second.aConnections.empty())
304 Reference< XPooledConnection > xPooledConnection = _rIter->second.aConnections.back();
305 _rIter->second.aConnections.pop_back();
307 OSL_ENSURE(xPooledConnection.is(),"Can not be null here!");
308 xConnection = xPooledConnection->getConnection();
309 Reference< XComponent > xComponent(xConnection, UNO_QUERY);
310 if (xComponent.is())
311 xComponent->addEventListener(this);
313 TActiveConnectionInfo aActiveInfo;
314 aActiveInfo.aPos = _rIter;
315 aActiveInfo.xPooledConnection = xPooledConnection;
316 m_aActiveConnections[xConnection] = aActiveInfo;
318 return xConnection;
320 // -----------------------------------------------------------------------------
321 void SAL_CALL OConnectionPool::propertyChange( const PropertyChangeEvent& evt ) throw (::com::sun::star::uno::RuntimeException)
323 if(getTimeoutNodeName() == evt.PropertyName)
325 evt.NewValue >>= m_nALiveCount;
326 calculateTimeOuts();
329 // -----------------------------------------------------------------------------
330 void OConnectionPool::calculateTimeOuts()
332 sal_Int32 nTimeOutCorrection = 10;
333 if(m_nALiveCount < 100)
334 nTimeOutCorrection = 20;
336 m_nTimeOut = m_nALiveCount / nTimeOutCorrection;
337 m_nALiveCount = m_nALiveCount / m_nTimeOut;
339 // -----------------------------------------------------------------------------