1*9646dec5SDamjan Jovanovic /**************************************************************
2*9646dec5SDamjan Jovanovic *
3*9646dec5SDamjan Jovanovic * Licensed to the Apache Software Foundation (ASF) under one
4*9646dec5SDamjan Jovanovic * or more contributor license agreements. See the NOTICE file
5*9646dec5SDamjan Jovanovic * distributed with this work for additional information
6*9646dec5SDamjan Jovanovic * regarding copyright ownership. The ASF licenses this file
7*9646dec5SDamjan Jovanovic * to you under the Apache License, Version 2.0 (the
8*9646dec5SDamjan Jovanovic * "License"); you may not use this file except in compliance
9*9646dec5SDamjan Jovanovic * with the License. You may obtain a copy of the License at
10*9646dec5SDamjan Jovanovic *
11*9646dec5SDamjan Jovanovic * http://www.apache.org/licenses/LICENSE-2.0
12*9646dec5SDamjan Jovanovic *
13*9646dec5SDamjan Jovanovic * Unless required by applicable law or agreed to in writing,
14*9646dec5SDamjan Jovanovic * software distributed under the License is distributed on an
15*9646dec5SDamjan Jovanovic * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*9646dec5SDamjan Jovanovic * KIND, either express or implied. See the License for the
17*9646dec5SDamjan Jovanovic * specific language governing permissions and limitations
18*9646dec5SDamjan Jovanovic * under the License.
19*9646dec5SDamjan Jovanovic *
20*9646dec5SDamjan Jovanovic *************************************************************/
21*9646dec5SDamjan Jovanovic
22*9646dec5SDamjan Jovanovic
23*9646dec5SDamjan Jovanovic
24*9646dec5SDamjan Jovanovic // MARKER(update_precomp.py): autogen include statement, do not remove
25*9646dec5SDamjan Jovanovic #include "precompiled_webdav.hxx"
26*9646dec5SDamjan Jovanovic
27*9646dec5SDamjan Jovanovic #include <rtl/ustring.hxx>
28*9646dec5SDamjan Jovanovic #include <osl/time.h>
29*9646dec5SDamjan Jovanovic #include <osl/thread.hxx>
30*9646dec5SDamjan Jovanovic #include "CurlTypes.hxx"
31*9646dec5SDamjan Jovanovic #include "CurlSession.hxx"
32*9646dec5SDamjan Jovanovic #include "CurlLockStore.hxx"
33*9646dec5SDamjan Jovanovic
34*9646dec5SDamjan Jovanovic using namespace http_dav_ucp;
35*9646dec5SDamjan Jovanovic
36*9646dec5SDamjan Jovanovic namespace http_dav_ucp {
37*9646dec5SDamjan Jovanovic
38*9646dec5SDamjan Jovanovic class TickerThread : public osl::Thread
39*9646dec5SDamjan Jovanovic {
40*9646dec5SDamjan Jovanovic bool m_bFinish;
41*9646dec5SDamjan Jovanovic CurlLockStore & m_rLockStore;
42*9646dec5SDamjan Jovanovic
43*9646dec5SDamjan Jovanovic public:
44*9646dec5SDamjan Jovanovic
TickerThread(CurlLockStore & rLockStore)45*9646dec5SDamjan Jovanovic TickerThread( CurlLockStore & rLockStore )
46*9646dec5SDamjan Jovanovic : osl::Thread(), m_bFinish( false ), m_rLockStore( rLockStore ) {}
47*9646dec5SDamjan Jovanovic
finish()48*9646dec5SDamjan Jovanovic void finish() { m_bFinish = true; }
49*9646dec5SDamjan Jovanovic
50*9646dec5SDamjan Jovanovic protected:
51*9646dec5SDamjan Jovanovic
52*9646dec5SDamjan Jovanovic virtual void SAL_CALL run();
53*9646dec5SDamjan Jovanovic };
54*9646dec5SDamjan Jovanovic
55*9646dec5SDamjan Jovanovic } // namespace http_dav_ucp
56*9646dec5SDamjan Jovanovic
57*9646dec5SDamjan Jovanovic // -------------------------------------------------------------------
run()58*9646dec5SDamjan Jovanovic void TickerThread::run()
59*9646dec5SDamjan Jovanovic {
60*9646dec5SDamjan Jovanovic OSL_TRACE( "TickerThread::run: start." );
61*9646dec5SDamjan Jovanovic
62*9646dec5SDamjan Jovanovic // we have to go through the loop more often to be able to finish ~quickly
63*9646dec5SDamjan Jovanovic const int nNth = 25;
64*9646dec5SDamjan Jovanovic
65*9646dec5SDamjan Jovanovic int nCount = nNth;
66*9646dec5SDamjan Jovanovic while ( !m_bFinish )
67*9646dec5SDamjan Jovanovic {
68*9646dec5SDamjan Jovanovic if ( nCount-- <= 0 )
69*9646dec5SDamjan Jovanovic {
70*9646dec5SDamjan Jovanovic m_rLockStore.refreshLocks();
71*9646dec5SDamjan Jovanovic nCount = nNth;
72*9646dec5SDamjan Jovanovic }
73*9646dec5SDamjan Jovanovic
74*9646dec5SDamjan Jovanovic TimeValue aTV;
75*9646dec5SDamjan Jovanovic aTV.Seconds = 0;
76*9646dec5SDamjan Jovanovic aTV.Nanosec = 1000000000 / nNth;
77*9646dec5SDamjan Jovanovic wait( aTV );
78*9646dec5SDamjan Jovanovic }
79*9646dec5SDamjan Jovanovic
80*9646dec5SDamjan Jovanovic OSL_TRACE( "TickerThread: stop." );
81*9646dec5SDamjan Jovanovic }
82*9646dec5SDamjan Jovanovic
83*9646dec5SDamjan Jovanovic // -------------------------------------------------------------------
CurlLockStore()84*9646dec5SDamjan Jovanovic CurlLockStore::CurlLockStore()
85*9646dec5SDamjan Jovanovic : m_pTickerThread( 0 )
86*9646dec5SDamjan Jovanovic {
87*9646dec5SDamjan Jovanovic }
88*9646dec5SDamjan Jovanovic
89*9646dec5SDamjan Jovanovic // -------------------------------------------------------------------
~CurlLockStore()90*9646dec5SDamjan Jovanovic CurlLockStore::~CurlLockStore()
91*9646dec5SDamjan Jovanovic {
92*9646dec5SDamjan Jovanovic stopTicker();
93*9646dec5SDamjan Jovanovic
94*9646dec5SDamjan Jovanovic // release active locks, if any.
95*9646dec5SDamjan Jovanovic OSL_ENSURE( m_aLockInfoMap.size() == 0,
96*9646dec5SDamjan Jovanovic "CurlLockStore::~CurlLockStore - Releasing active locks!" );
97*9646dec5SDamjan Jovanovic
98*9646dec5SDamjan Jovanovic LockInfoMap::const_iterator it( m_aLockInfoMap.begin() );
99*9646dec5SDamjan Jovanovic const LockInfoMap::const_iterator end( m_aLockInfoMap.end() );
100*9646dec5SDamjan Jovanovic while ( it != end )
101*9646dec5SDamjan Jovanovic {
102*9646dec5SDamjan Jovanovic CurlLock * pLock = (*it).first;
103*9646dec5SDamjan Jovanovic try
104*9646dec5SDamjan Jovanovic {
105*9646dec5SDamjan Jovanovic (*it).second.xSession->UNLOCK( pLock );
106*9646dec5SDamjan Jovanovic (*it).second.xSession->release();
107*9646dec5SDamjan Jovanovic }
108*9646dec5SDamjan Jovanovic catch (DAVException & )
109*9646dec5SDamjan Jovanovic {}
110*9646dec5SDamjan Jovanovic ++it;
111*9646dec5SDamjan Jovanovic }
112*9646dec5SDamjan Jovanovic }
113*9646dec5SDamjan Jovanovic
114*9646dec5SDamjan Jovanovic // -------------------------------------------------------------------
startTicker()115*9646dec5SDamjan Jovanovic void CurlLockStore::startTicker()
116*9646dec5SDamjan Jovanovic {
117*9646dec5SDamjan Jovanovic osl::MutexGuard aGuard( m_aMutex );
118*9646dec5SDamjan Jovanovic
119*9646dec5SDamjan Jovanovic if ( !m_pTickerThread )
120*9646dec5SDamjan Jovanovic {
121*9646dec5SDamjan Jovanovic m_pTickerThread = new TickerThread( *this );
122*9646dec5SDamjan Jovanovic m_pTickerThread->create();
123*9646dec5SDamjan Jovanovic }
124*9646dec5SDamjan Jovanovic }
125*9646dec5SDamjan Jovanovic
126*9646dec5SDamjan Jovanovic // -------------------------------------------------------------------
stopTicker()127*9646dec5SDamjan Jovanovic void CurlLockStore::stopTicker()
128*9646dec5SDamjan Jovanovic {
129*9646dec5SDamjan Jovanovic osl::MutexGuard aGuard( m_aMutex );
130*9646dec5SDamjan Jovanovic
131*9646dec5SDamjan Jovanovic if ( m_pTickerThread )
132*9646dec5SDamjan Jovanovic {
133*9646dec5SDamjan Jovanovic m_pTickerThread->finish();
134*9646dec5SDamjan Jovanovic m_pTickerThread->join();
135*9646dec5SDamjan Jovanovic delete m_pTickerThread;
136*9646dec5SDamjan Jovanovic m_pTickerThread = 0;
137*9646dec5SDamjan Jovanovic }
138*9646dec5SDamjan Jovanovic }
139*9646dec5SDamjan Jovanovic
140*9646dec5SDamjan Jovanovic #if 0 //not currently used
141*9646dec5SDamjan Jovanovic // -------------------------------------------------------------------
142*9646dec5SDamjan Jovanovic void CurlLockStore::registerSession( CurlSession /* aSession */ )
143*9646dec5SDamjan Jovanovic {
144*9646dec5SDamjan Jovanovic osl::MutexGuard aGuard( m_aMutex );
145*9646dec5SDamjan Jovanovic
146*9646dec5SDamjan Jovanovic }
147*9646dec5SDamjan Jovanovic #endif
148*9646dec5SDamjan Jovanovic
149*9646dec5SDamjan Jovanovic // -------------------------------------------------------------------
findByUri(rtl::OUString const & rUri)150*9646dec5SDamjan Jovanovic CurlLock * CurlLockStore::findByUri( rtl::OUString const & rUri)
151*9646dec5SDamjan Jovanovic {
152*9646dec5SDamjan Jovanovic osl::MutexGuard aGuard( m_aMutex );
153*9646dec5SDamjan Jovanovic
154*9646dec5SDamjan Jovanovic LockInfoMap::const_iterator it( m_aLockInfoMap.begin() );
155*9646dec5SDamjan Jovanovic const LockInfoMap::const_iterator end( m_aLockInfoMap.end() );
156*9646dec5SDamjan Jovanovic
157*9646dec5SDamjan Jovanovic while ( it != end )
158*9646dec5SDamjan Jovanovic {
159*9646dec5SDamjan Jovanovic CurlLock * pLock = (*it).first;
160*9646dec5SDamjan Jovanovic if( pLock->getResourceUri().equals( rUri ) )
161*9646dec5SDamjan Jovanovic {
162*9646dec5SDamjan Jovanovic return pLock;
163*9646dec5SDamjan Jovanovic }
164*9646dec5SDamjan Jovanovic ++it;
165*9646dec5SDamjan Jovanovic }
166*9646dec5SDamjan Jovanovic
167*9646dec5SDamjan Jovanovic return static_cast<CurlLock*>(0);
168*9646dec5SDamjan Jovanovic }
169*9646dec5SDamjan Jovanovic
170*9646dec5SDamjan Jovanovic // -------------------------------------------------------------------
addLock(CurlLock * pLock,rtl::Reference<CurlSession> const & xSession,sal_Int32 nLastChanceToSendRefreshRequest)171*9646dec5SDamjan Jovanovic void CurlLockStore::addLock( CurlLock * pLock,
172*9646dec5SDamjan Jovanovic rtl::Reference< CurlSession > const & xSession,
173*9646dec5SDamjan Jovanovic sal_Int32 nLastChanceToSendRefreshRequest )
174*9646dec5SDamjan Jovanovic {
175*9646dec5SDamjan Jovanovic osl::MutexGuard aGuard( m_aMutex );
176*9646dec5SDamjan Jovanovic
177*9646dec5SDamjan Jovanovic m_aLockInfoMap[ pLock ]
178*9646dec5SDamjan Jovanovic = LockInfo( xSession, nLastChanceToSendRefreshRequest );
179*9646dec5SDamjan Jovanovic //acquire this session, needed to manage the lock refresh
180*9646dec5SDamjan Jovanovic xSession->acquire();
181*9646dec5SDamjan Jovanovic
182*9646dec5SDamjan Jovanovic #if OSL_DEBUG_LEVEL > 0
183*9646dec5SDamjan Jovanovic rtl::OUString aOwner;
184*9646dec5SDamjan Jovanovic pLock->getLock().Owner >>= aOwner;
185*9646dec5SDamjan Jovanovic rtl::OUString aToken;
186*9646dec5SDamjan Jovanovic aToken = pLock->getLock().LockTokens[0];
187*9646dec5SDamjan Jovanovic OSL_TRACE("CurlLockStore::addLock: new lock added aOwner '%s', token '%s'",
188*9646dec5SDamjan Jovanovic rtl::OUStringToOString(aOwner, RTL_TEXTENCODING_UTF8).getStr(),
189*9646dec5SDamjan Jovanovic rtl::OUStringToOString(aToken, RTL_TEXTENCODING_UTF8).getStr() );
190*9646dec5SDamjan Jovanovic #endif
191*9646dec5SDamjan Jovanovic startTicker();
192*9646dec5SDamjan Jovanovic }
193*9646dec5SDamjan Jovanovic
194*9646dec5SDamjan Jovanovic #if 0 //not currently used
195*9646dec5SDamjan Jovanovic // -------------------------------------------------------------------
196*9646dec5SDamjan Jovanovic void CurlLockStore::updateLock( CurlLock * pLock,
197*9646dec5SDamjan Jovanovic sal_Int32 nLastChanceToSendRefreshRequest )
198*9646dec5SDamjan Jovanovic {
199*9646dec5SDamjan Jovanovic osl::MutexGuard aGuard( m_aMutex );
200*9646dec5SDamjan Jovanovic
201*9646dec5SDamjan Jovanovic LockInfoMap::iterator it( m_aLockInfoMap.find( pLock ) );
202*9646dec5SDamjan Jovanovic OSL_ENSURE( it != m_aLockInfoMap.end(),
203*9646dec5SDamjan Jovanovic "CurlLockStore::updateLock: lock not found!" );
204*9646dec5SDamjan Jovanovic
205*9646dec5SDamjan Jovanovic if ( it != m_aLockInfoMap.end() )
206*9646dec5SDamjan Jovanovic {
207*9646dec5SDamjan Jovanovic (*it).second.nLastChanceToSendRefreshRequest
208*9646dec5SDamjan Jovanovic = nLastChanceToSendRefreshRequest;
209*9646dec5SDamjan Jovanovic }
210*9646dec5SDamjan Jovanovic }
211*9646dec5SDamjan Jovanovic #endif
212*9646dec5SDamjan Jovanovic
213*9646dec5SDamjan Jovanovic // -------------------------------------------------------------------
removeLock(CurlLock * pLock)214*9646dec5SDamjan Jovanovic void CurlLockStore::removeLock( CurlLock * pLock )
215*9646dec5SDamjan Jovanovic {
216*9646dec5SDamjan Jovanovic osl::MutexGuard aGuard( m_aMutex );
217*9646dec5SDamjan Jovanovic
218*9646dec5SDamjan Jovanovic LockInfoMap::iterator it( m_aLockInfoMap.find( pLock ) );
219*9646dec5SDamjan Jovanovic if(it != m_aLockInfoMap.end())
220*9646dec5SDamjan Jovanovic {
221*9646dec5SDamjan Jovanovic LockInfo & rInfo = (*it).second;
222*9646dec5SDamjan Jovanovic rInfo.xSession->release();
223*9646dec5SDamjan Jovanovic m_aLockInfoMap.erase( pLock );
224*9646dec5SDamjan Jovanovic //the caller should deallocate CurlLock class after the call!
225*9646dec5SDamjan Jovanovic if ( m_aLockInfoMap.size() == 0 )
226*9646dec5SDamjan Jovanovic stopTicker();
227*9646dec5SDamjan Jovanovic }
228*9646dec5SDamjan Jovanovic }
229*9646dec5SDamjan Jovanovic
230*9646dec5SDamjan Jovanovic // -------------------------------------------------------------------
refreshLocks()231*9646dec5SDamjan Jovanovic void CurlLockStore::refreshLocks()
232*9646dec5SDamjan Jovanovic {
233*9646dec5SDamjan Jovanovic osl::MutexGuard aGuard( m_aMutex );
234*9646dec5SDamjan Jovanovic
235*9646dec5SDamjan Jovanovic LockInfoMap::iterator it( m_aLockInfoMap.begin() );
236*9646dec5SDamjan Jovanovic const LockInfoMap::const_iterator end( m_aLockInfoMap.end() );
237*9646dec5SDamjan Jovanovic while ( it != end )
238*9646dec5SDamjan Jovanovic {
239*9646dec5SDamjan Jovanovic LockInfo & rInfo = (*it).second;
240*9646dec5SDamjan Jovanovic if ( rInfo.nLastChanceToSendRefreshRequest != -1 )
241*9646dec5SDamjan Jovanovic {
242*9646dec5SDamjan Jovanovic // 30 seconds or less remaining until lock expires?
243*9646dec5SDamjan Jovanovic TimeValue t1;
244*9646dec5SDamjan Jovanovic osl_getSystemTime( &t1 );
245*9646dec5SDamjan Jovanovic if ( rInfo.nLastChanceToSendRefreshRequest - 30
246*9646dec5SDamjan Jovanovic <= sal_Int32( t1.Seconds ) )
247*9646dec5SDamjan Jovanovic {
248*9646dec5SDamjan Jovanovic // refresh the lock.
249*9646dec5SDamjan Jovanovic #if OSL_DEBUG_LEVEL > 0
250*9646dec5SDamjan Jovanovic ucb::Lock aLock = (*it).first->getLock();
251*9646dec5SDamjan Jovanovic rtl::OUString aOwner;
252*9646dec5SDamjan Jovanovic aLock.Owner >>= aOwner;
253*9646dec5SDamjan Jovanovic rtl::OUString aToken;
254*9646dec5SDamjan Jovanovic aToken = aLock.LockTokens[0];
255*9646dec5SDamjan Jovanovic OSL_TRACE( "CurlLockStore::refreshLocks: refresh started for lock: aOwner '%s', token '%s'",
256*9646dec5SDamjan Jovanovic rtl::OUStringToOString(aOwner, RTL_TEXTENCODING_UTF8).getStr(),
257*9646dec5SDamjan Jovanovic rtl::OUStringToOString(aToken, RTL_TEXTENCODING_UTF8).getStr() );
258*9646dec5SDamjan Jovanovic #endif
259*9646dec5SDamjan Jovanovic sal_Int32 nlastChanceToSendRefreshRequest = -1;
260*9646dec5SDamjan Jovanovic try
261*9646dec5SDamjan Jovanovic {
262*9646dec5SDamjan Jovanovic rInfo.xSession->LOCK( (*it).first,
263*9646dec5SDamjan Jovanovic /* out param */ nlastChanceToSendRefreshRequest );
264*9646dec5SDamjan Jovanovic rInfo.nLastChanceToSendRefreshRequest
265*9646dec5SDamjan Jovanovic = nlastChanceToSendRefreshRequest;
266*9646dec5SDamjan Jovanovic #if OSL_DEBUG_LEVEL > 0
267*9646dec5SDamjan Jovanovic OSL_TRACE( "Lock '%s' successfully refreshed." ,
268*9646dec5SDamjan Jovanovic rtl::OUStringToOString(aToken, RTL_TEXTENCODING_UTF8).getStr() );
269*9646dec5SDamjan Jovanovic #endif
270*9646dec5SDamjan Jovanovic }
271*9646dec5SDamjan Jovanovic catch ( DAVException & e )
272*9646dec5SDamjan Jovanovic {
273*9646dec5SDamjan Jovanovic // refresh failed. stop auto-refresh.
274*9646dec5SDamjan Jovanovic // TODO i126305 discuss:
275*9646dec5SDamjan Jovanovic // probably not a good idea to stop the refresh?
276*9646dec5SDamjan Jovanovic // may be just ignore and go on, it's possible the net is temporary down?
277*9646dec5SDamjan Jovanovic rInfo.nLastChanceToSendRefreshRequest = -1;
278*9646dec5SDamjan Jovanovic #if OSL_DEBUG_LEVEL > 0
279*9646dec5SDamjan Jovanovic OSL_TRACE( "CurlLockStore::refreshLocks: Lock '%s' not refreshed! (error: DAVException.mStatusCode %d)",
280*9646dec5SDamjan Jovanovic rtl::OUStringToOString(aToken, RTL_TEXTENCODING_UTF8).getStr(), e.getStatus() );
281*9646dec5SDamjan Jovanovic #endif
282*9646dec5SDamjan Jovanovic }
283*9646dec5SDamjan Jovanovic }
284*9646dec5SDamjan Jovanovic }
285*9646dec5SDamjan Jovanovic ++it;
286*9646dec5SDamjan Jovanovic }
287*9646dec5SDamjan Jovanovic }
288