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