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 45*51ba086bSDamjan Jovanovic TickerThread( CurlLockStore & rLockStore ) 46*51ba086bSDamjan Jovanovic : osl::Thread(), m_bFinish( false ), m_rLockStore( rLockStore ) {} 47*51ba086bSDamjan Jovanovic 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 // ------------------------------------------------------------------- 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 // ------------------------------------------------------------------- 84*51ba086bSDamjan Jovanovic CurlLockStore::CurlLockStore() 85*51ba086bSDamjan Jovanovic : m_pTickerThread( 0 ) 86*51ba086bSDamjan Jovanovic { 87*51ba086bSDamjan Jovanovic } 88*51ba086bSDamjan Jovanovic 89*51ba086bSDamjan Jovanovic // ------------------------------------------------------------------- 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 // ------------------------------------------------------------------- 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 // ------------------------------------------------------------------- 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 // ------------------------------------------------------------------- 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 // ------------------------------------------------------------------- 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 // ------------------------------------------------------------------- 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 // ------------------------------------------------------------------- 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