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