File: | home/maarten/src/libreoffice/core/connectivity/source/cpool/ZConnectionPool.cxx |
Warning: | line 297, column 37 Division by zero |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ | |||
2 | /* | |||
3 | * This file is part of the LibreOffice project. | |||
4 | * | |||
5 | * This Source Code Form is subject to the terms of the Mozilla Public | |||
6 | * License, v. 2.0. If a copy of the MPL was not distributed with this | |||
7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. | |||
8 | * | |||
9 | * This file incorporates work covered by the following license notice: | |||
10 | * | |||
11 | * Licensed to the Apache Software Foundation (ASF) under one or more | |||
12 | * contributor license agreements. See the NOTICE file distributed | |||
13 | * with this work for additional information regarding copyright | |||
14 | * ownership. The ASF licenses this file to you under the Apache | |||
15 | * License, Version 2.0 (the "License"); you may not use this file | |||
16 | * except in compliance with the License. You may obtain a copy of | |||
17 | * the License at http://www.apache.org/licenses/LICENSE-2.0 . | |||
18 | */ | |||
19 | ||||
20 | ||||
21 | #include "ZConnectionPool.hxx" | |||
22 | #include <com/sun/star/lang/XComponent.hpp> | |||
23 | #include "ZPooledConnection.hxx" | |||
24 | #include "ZPoolCollection.hxx" | |||
25 | #include <connectivity/ConnectionWrapper.hxx> | |||
26 | #include <com/sun/star/beans/XPropertySet.hpp> | |||
27 | ||||
28 | ||||
29 | using namespace ::com::sun::star::uno; | |||
30 | using namespace ::com::sun::star::lang; | |||
31 | using namespace ::com::sun::star::sdbc; | |||
32 | using namespace ::com::sun::star::beans; | |||
33 | using namespace ::com::sun::star::container; | |||
34 | using namespace ::osl; | |||
35 | using namespace connectivity; | |||
36 | ||||
37 | #include <algorithm> | |||
38 | ||||
39 | void SAL_CALL OPoolTimer::onShot() | |||
40 | { | |||
41 | m_pPool->invalidatePooledConnections(); | |||
42 | } | |||
43 | ||||
44 | const char TIMEOUT_NODENAME[] = "Timeout"; | |||
45 | ||||
46 | OConnectionPool::OConnectionPool(const Reference< XDriver >& _xDriver, | |||
47 | const Reference< XInterface >& _xDriverNode, | |||
48 | const Reference< css::reflection::XProxyFactory >& _rxProxyFactory) | |||
49 | :m_xDriver(_xDriver) | |||
50 | ,m_xDriverNode(_xDriverNode) | |||
51 | ,m_xProxyFactory(_rxProxyFactory) | |||
52 | ,m_nTimeOut(10) | |||
53 | ,m_nALiveCount(10) | |||
54 | { | |||
55 | OSL_ENSURE(m_xDriverNode.is(),"NO valid Driver node set!")do { if (true && (!(m_xDriverNode.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/cpool/ZConnectionPool.cxx" ":" "55" ": "), "%s", "NO valid Driver node set!"); } } while (false); | |||
| ||||
56 | Reference< XComponent > xComponent(m_xDriverNode, UNO_QUERY); | |||
57 | if (xComponent.is()) | |||
58 | xComponent->addEventListener(this); | |||
59 | ||||
60 | Reference<XPropertySet> xProp(m_xDriverNode,UNO_QUERY); | |||
61 | if(xProp.is()) | |||
62 | xProp->addPropertyChangeListener(TIMEOUT_NODENAME,this); | |||
63 | ||||
64 | OPoolCollection::getNodeValue(TIMEOUT_NODENAME, m_xDriverNode) >>= m_nALiveCount; | |||
65 | calculateTimeOuts(); | |||
66 | ||||
67 | m_xInvalidator = new OPoolTimer(this,::salhelper::TTimeValue(m_nTimeOut,0)); | |||
68 | m_xInvalidator->start(); | |||
69 | } | |||
70 | ||||
71 | OConnectionPool::~OConnectionPool() | |||
72 | { | |||
73 | clear(false); | |||
74 | } | |||
75 | ||||
76 | namespace { | |||
77 | ||||
78 | struct TRemoveEventListenerFunctor | |||
79 | { | |||
80 | OConnectionPool* m_pConnectionPool; | |||
81 | bool m_bDispose; | |||
82 | ||||
83 | TRemoveEventListenerFunctor(OConnectionPool* _pConnectionPool, bool _bDispose) | |||
84 | : m_pConnectionPool(_pConnectionPool) | |||
85 | ,m_bDispose(_bDispose) | |||
86 | { | |||
87 | OSL_ENSURE(m_pConnectionPool,"No connection pool!")do { if (true && (!(m_pConnectionPool))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/cpool/ZConnectionPool.cxx" ":" "87" ": "), "%s", "No connection pool!"); } } while (false ); | |||
88 | } | |||
89 | ||||
90 | void dispose(const Reference<XInterface>& _xComponent) | |||
91 | { | |||
92 | Reference< XComponent > xComponent(_xComponent, UNO_QUERY); | |||
93 | ||||
94 | if ( xComponent.is() ) | |||
95 | { | |||
96 | xComponent->removeEventListener(m_pConnectionPool); | |||
97 | if ( m_bDispose ) | |||
98 | xComponent->dispose(); | |||
99 | } | |||
100 | } | |||
101 | ||||
102 | void operator()(const TPooledConnections::value_type& _aValue) | |||
103 | { | |||
104 | dispose(_aValue); | |||
105 | } | |||
106 | ||||
107 | void operator()(const TActiveConnectionMap::value_type& _aValue) | |||
108 | { | |||
109 | dispose(_aValue.first); | |||
110 | } | |||
111 | }; | |||
112 | ||||
113 | struct TConnectionPoolFunctor | |||
114 | { | |||
115 | OConnectionPool* m_pConnectionPool; | |||
116 | ||||
117 | explicit TConnectionPoolFunctor(OConnectionPool* _pConnectionPool) | |||
118 | : m_pConnectionPool(_pConnectionPool) | |||
119 | { | |||
120 | OSL_ENSURE(m_pConnectionPool,"No connection pool!")do { if (true && (!(m_pConnectionPool))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/cpool/ZConnectionPool.cxx" ":" "120" ": "), "%s", "No connection pool!"); } } while (false ); | |||
121 | } | |||
122 | void operator()(const TConnectionMap::value_type& _aValue) | |||
123 | { | |||
124 | std::for_each(_aValue.second.aConnections.begin(),_aValue.second.aConnections.end(),TRemoveEventListenerFunctor(m_pConnectionPool,true)); | |||
125 | } | |||
126 | }; | |||
127 | ||||
128 | } | |||
129 | ||||
130 | void OConnectionPool::clear(bool _bDispose) | |||
131 | { | |||
132 | MutexGuard aGuard(m_aMutex); | |||
133 | ||||
134 | if(m_xInvalidator->isTicking()) | |||
135 | m_xInvalidator->stop(); | |||
136 | ||||
137 | std::for_each(m_aPool.begin(),m_aPool.end(),TConnectionPoolFunctor(this)); | |||
138 | m_aPool.clear(); | |||
139 | ||||
140 | std::for_each(m_aActiveConnections.begin(),m_aActiveConnections.end(),TRemoveEventListenerFunctor(this,_bDispose)); | |||
141 | m_aActiveConnections.clear(); | |||
142 | ||||
143 | Reference< XComponent > xComponent(m_xDriverNode, UNO_QUERY); | |||
144 | if (xComponent.is()) | |||
145 | xComponent->removeEventListener(this); | |||
146 | Reference< XPropertySet > xProp(m_xDriverNode, UNO_QUERY); | |||
147 | if (xProp.is()) | |||
148 | xProp->removePropertyChangeListener(TIMEOUT_NODENAME, this); | |||
149 | ||||
150 | m_xDriverNode.clear(); | |||
151 | m_xDriver.clear(); | |||
152 | } | |||
153 | ||||
154 | Reference< XConnection > OConnectionPool::getConnectionWithInfo( const OUString& _rURL, const Sequence< PropertyValue >& _rInfo ) | |||
155 | { | |||
156 | MutexGuard aGuard(m_aMutex); | |||
157 | ||||
158 | Reference<XConnection> xConnection; | |||
159 | ||||
160 | // create a unique id and look for it in our map | |||
161 | Sequence< PropertyValue > aInfo(_rInfo); | |||
162 | TConnectionMap::key_type nId; | |||
163 | OConnectionWrapper::createUniqueId(_rURL,aInfo,nId.m_pBuffer); | |||
164 | TConnectionMap::iterator aIter = m_aPool.find(nId); | |||
165 | ||||
166 | if ( m_aPool.end() != aIter ) | |||
167 | xConnection = getPooledConnection(aIter); | |||
168 | ||||
169 | if ( !xConnection.is() ) | |||
170 | xConnection = createNewConnection(_rURL,_rInfo); | |||
171 | ||||
172 | return xConnection; | |||
173 | } | |||
174 | ||||
175 | void SAL_CALL OConnectionPool::disposing( const css::lang::EventObject& Source ) | |||
176 | { | |||
177 | Reference<XConnection> xConnection(Source.Source,UNO_QUERY); | |||
178 | if(xConnection.is()) | |||
179 | { | |||
180 | MutexGuard aGuard(m_aMutex); | |||
181 | TActiveConnectionMap::iterator aIter = m_aActiveConnections.find(xConnection); | |||
182 | OSL_ENSURE(aIter != m_aActiveConnections.end(),"OConnectionPool::disposing: Connection wasn't in pool")do { if (true && (!(aIter != m_aActiveConnections.end ()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/connectivity/source/cpool/ZConnectionPool.cxx" ":" "182" ": "), "%s", "OConnectionPool::disposing: Connection wasn't in pool" ); } } while (false); | |||
183 | if(aIter != m_aActiveConnections.end()) | |||
184 | { // move the pooled connection back to the pool | |||
185 | aIter->second.aPos->second.nALiveCount = m_nALiveCount; | |||
186 | aIter->second.aPos->second.aConnections.push_back(aIter->second.xPooledConnection); | |||
187 | m_aActiveConnections.erase(aIter); | |||
188 | } | |||
189 | } | |||
190 | else | |||
191 | { | |||
192 | m_xDriverNode.clear(); | |||
193 | } | |||
194 | } | |||
195 | ||||
196 | Reference< XConnection> OConnectionPool::createNewConnection(const OUString& _rURL,const Sequence< PropertyValue >& _rInfo) | |||
197 | { | |||
198 | // create new pooled connection | |||
199 | Reference< XPooledConnection > xPooledConnection = new ::connectivity::OPooledConnection(m_xDriver->connect(_rURL,_rInfo),m_xProxyFactory); | |||
200 | // get the new connection from the pooled connection | |||
201 | Reference<XConnection> xConnection = xPooledConnection->getConnection(); | |||
202 | if(xConnection.is()) | |||
203 | { | |||
204 | // add our own as dispose listener to know when we should put the connection back to the pool | |||
205 | Reference< XComponent > xComponent(xConnection, UNO_QUERY); | |||
206 | if (xComponent.is()) | |||
207 | xComponent->addEventListener(this); | |||
208 | ||||
209 | // save some information to find the right pool later on | |||
210 | Sequence< PropertyValue > aInfo(_rInfo); | |||
211 | TConnectionMap::key_type nId; | |||
212 | OConnectionWrapper::createUniqueId(_rURL,aInfo,nId.m_pBuffer); | |||
213 | TConnectionPool aPack; | |||
214 | ||||
215 | // insert the new connection and struct into the active connection map | |||
216 | aPack.nALiveCount = m_nALiveCount; | |||
217 | TActiveConnectionInfo aActiveInfo; | |||
218 | aActiveInfo.aPos = m_aPool.emplace(nId,aPack).first; | |||
219 | aActiveInfo.xPooledConnection = xPooledConnection; | |||
220 | m_aActiveConnections.emplace(xConnection,aActiveInfo); | |||
221 | ||||
222 | if(m_xInvalidator->isExpired()) | |||
223 | m_xInvalidator->start(); | |||
224 | } | |||
225 | ||||
226 | return xConnection; | |||
227 | } | |||
228 | ||||
229 | void OConnectionPool::invalidatePooledConnections() | |||
230 | { | |||
231 | MutexGuard aGuard(m_aMutex); | |||
232 | TConnectionMap::iterator aIter = m_aPool.begin(); | |||
233 | for (; aIter != m_aPool.end(); ) | |||
234 | { | |||
235 | if(!(--(aIter->second.nALiveCount))) // connections are invalid | |||
236 | { | |||
237 | std::for_each(aIter->second.aConnections.begin(),aIter->second.aConnections.end(),TRemoveEventListenerFunctor(this,true)); | |||
238 | ||||
239 | aIter->second.aConnections.clear(); | |||
240 | ||||
241 | // look if the iterator aIter is still present in the active connection map | |||
242 | bool isPresent = std::any_of(m_aActiveConnections.begin(), m_aActiveConnections.end(), | |||
243 | [&aIter](const TActiveConnectionMap::value_type& rEntry) { return rEntry.second.aPos == aIter; }); | |||
244 | if(!isPresent) | |||
245 | {// he isn't so we can delete him | |||
246 | aIter = m_aPool.erase(aIter); | |||
247 | } | |||
248 | else | |||
249 | ++aIter; | |||
250 | } | |||
251 | else | |||
252 | ++aIter; | |||
253 | } | |||
254 | if(!m_aPool.empty()) | |||
255 | m_xInvalidator->start(); | |||
256 | } | |||
257 | ||||
258 | Reference< XConnection> OConnectionPool::getPooledConnection(TConnectionMap::iterator const & _rIter) | |||
259 | { | |||
260 | Reference<XConnection> xConnection; | |||
261 | ||||
262 | if(!_rIter->second.aConnections.empty()) | |||
263 | { | |||
264 | Reference< XPooledConnection > xPooledConnection = _rIter->second.aConnections.back(); | |||
265 | _rIter->second.aConnections.pop_back(); | |||
266 | ||||
267 | OSL_ENSURE(xPooledConnection.is(),"Can not be null here!")do { if (true && (!(xPooledConnection.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/cpool/ZConnectionPool.cxx" ":" "267" ": "), "%s", "Can not be null here!"); } } while ( false); | |||
268 | xConnection = xPooledConnection->getConnection(); | |||
269 | Reference< XComponent > xComponent(xConnection, UNO_QUERY); | |||
270 | if (xComponent.is()) | |||
271 | xComponent->addEventListener(this); | |||
272 | ||||
273 | TActiveConnectionInfo aActiveInfo; | |||
274 | aActiveInfo.aPos = _rIter; | |||
275 | aActiveInfo.xPooledConnection = xPooledConnection; | |||
276 | m_aActiveConnections[xConnection] = aActiveInfo; | |||
277 | } | |||
278 | return xConnection; | |||
279 | } | |||
280 | ||||
281 | void SAL_CALL OConnectionPool::propertyChange( const PropertyChangeEvent& evt ) | |||
282 | { | |||
283 | if(TIMEOUT_NODENAME == evt.PropertyName) | |||
284 | { | |||
285 | evt.NewValue >>= m_nALiveCount; | |||
286 | calculateTimeOuts(); | |||
287 | } | |||
288 | } | |||
289 | ||||
290 | void OConnectionPool::calculateTimeOuts() | |||
291 | { | |||
292 | sal_Int32 nTimeOutCorrection = 10; | |||
293 | if(m_nALiveCount
| |||
294 | nTimeOutCorrection = 20; | |||
295 | ||||
296 | m_nTimeOut = m_nALiveCount / nTimeOutCorrection; | |||
297 | m_nALiveCount = m_nALiveCount / m_nTimeOut; | |||
| ||||
298 | } | |||
299 | ||||
300 | ||||
301 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |