xref: /AOO42X/main/ucb/source/ucp/webdav/CurlLockStore.cxx (revision b1c5455db1639c48e26c568e4fa7ee78ca5d60ee)
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