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 <ne_locks.h> 28 #include <ne_uri.h> 29 #include "rtl/ustring.hxx" 30 #include "osl/time.h" 31 #include "osl/thread.hxx" 32 #include "SerfSession.hxx" 33 #include "SerfLockStore.hxx" 34 35 using namespace http_dav_ucp; 36 37 namespace http_dav_ucp { 38 39 class TickerThread : public osl::Thread 40 { 41 bool m_bFinish; 42 SerfLockStore & m_rLockStore; 43 44 public: 45 46 TickerThread( SerfLockStore & rLockStore ) 47 : osl::Thread(), m_bFinish( false ), m_rLockStore( rLockStore ) {} 48 49 void finish() { m_bFinish = true; } 50 51 protected: 52 53 virtual void SAL_CALL run(); 54 }; 55 56 } // namespace http_dav_ucp 57 58 // ------------------------------------------------------------------- 59 void TickerThread::run() 60 { 61 OSL_TRACE( "TickerThread: start." ); 62 63 // we have to go through the loop more often to be able to finish ~quickly 64 const int nNth = 25; 65 66 int nCount = nNth; 67 while ( !m_bFinish ) 68 { 69 if ( nCount-- <= 0 ) 70 { 71 m_rLockStore.refreshLocks(); 72 nCount = nNth; 73 } 74 75 TimeValue aTV; 76 aTV.Seconds = 0; 77 aTV.Nanosec = 1000000000 / nNth; 78 wait( aTV ); 79 } 80 81 OSL_TRACE( "TickerThread: stop." ); 82 } 83 84 // ------------------------------------------------------------------- 85 SerfLockStore::SerfLockStore() 86 : m_pSerfLockStore( ne_lockstore_create() ), 87 m_pTickerThread( 0 ) 88 { 89 OSL_ENSURE( m_pSerfLockStore, "Unable to create neon lock store!" ); 90 } 91 92 // ------------------------------------------------------------------- 93 SerfLockStore::~SerfLockStore() 94 { 95 stopTicker(); 96 97 // release active locks, if any. 98 OSL_ENSURE( m_aLockInfoMap.size() == 0, 99 "SerfLockStore::~SerfLockStore - Releasing active locks!" ); 100 101 LockInfoMap::const_iterator it( m_aLockInfoMap.begin() ); 102 const LockInfoMap::const_iterator end( m_aLockInfoMap.end() ); 103 while ( it != end ) 104 { 105 SerfLock * pLock = (*it).first; 106 (*it).second.xSession->UNLOCK( pLock ); 107 108 ne_lockstore_remove( m_pSerfLockStore, pLock ); 109 ne_lock_destroy( pLock ); 110 111 ++it; 112 } 113 114 ne_lockstore_destroy( m_pSerfLockStore ); 115 } 116 117 // ------------------------------------------------------------------- 118 void SerfLockStore::startTicker() 119 { 120 osl::MutexGuard aGuard( m_aMutex ); 121 122 if ( !m_pTickerThread ) 123 { 124 m_pTickerThread = new TickerThread( *this ); 125 m_pTickerThread->create(); 126 } 127 } 128 129 // ------------------------------------------------------------------- 130 void SerfLockStore::stopTicker() 131 { 132 osl::MutexGuard aGuard( m_aMutex ); 133 134 if ( m_pTickerThread ) 135 { 136 m_pTickerThread->finish(); 137 m_pTickerThread->join(); 138 delete m_pTickerThread; 139 m_pTickerThread = 0; 140 } 141 } 142 143 // ------------------------------------------------------------------- 144 void SerfLockStore::registerSession( HttpSession * pHttpSession ) 145 { 146 osl::MutexGuard aGuard( m_aMutex ); 147 148 ne_lockstore_register( m_pSerfLockStore, pHttpSession ); 149 } 150 151 // ------------------------------------------------------------------- 152 SerfLock * SerfLockStore::findByUri( rtl::OUString const & rUri ) 153 { 154 osl::MutexGuard aGuard( m_aMutex ); 155 156 ne_uri aUri; 157 ne_uri_parse( rtl::OUStringToOString( 158 rUri, RTL_TEXTENCODING_UTF8 ).getStr(), &aUri ); 159 return ne_lockstore_findbyuri( m_pSerfLockStore, &aUri ); 160 } 161 162 // ------------------------------------------------------------------- 163 void SerfLockStore::addLock( SerfLock * pLock, 164 rtl::Reference< SerfSession > const & xSession, 165 sal_Int32 nLastChanceToSendRefreshRequest ) 166 { 167 osl::MutexGuard aGuard( m_aMutex ); 168 169 ne_lockstore_add( m_pSerfLockStore, pLock ); 170 m_aLockInfoMap[ pLock ] 171 = LockInfo( xSession, nLastChanceToSendRefreshRequest ); 172 173 startTicker(); 174 } 175 176 // ------------------------------------------------------------------- 177 void SerfLockStore::updateLock( SerfLock * pLock, 178 sal_Int32 nLastChanceToSendRefreshRequest ) 179 { 180 osl::MutexGuard aGuard( m_aMutex ); 181 182 LockInfoMap::iterator it( m_aLockInfoMap.find( pLock ) ); 183 OSL_ENSURE( it != m_aLockInfoMap.end(), 184 "SerfLockStore::updateLock: lock not found!" ); 185 186 if ( it != m_aLockInfoMap.end() ) 187 { 188 (*it).second.nLastChanceToSendRefreshRequest 189 = nLastChanceToSendRefreshRequest; 190 } 191 } 192 193 // ------------------------------------------------------------------- 194 void SerfLockStore::removeLock( SerfLock * pLock ) 195 { 196 osl::MutexGuard aGuard( m_aMutex ); 197 198 m_aLockInfoMap.erase( pLock ); 199 ne_lockstore_remove( m_pSerfLockStore, pLock ); 200 201 if ( m_aLockInfoMap.size() == 0 ) 202 stopTicker(); 203 } 204 205 // ------------------------------------------------------------------- 206 void SerfLockStore::refreshLocks() 207 { 208 osl::MutexGuard aGuard( m_aMutex ); 209 210 LockInfoMap::iterator it( m_aLockInfoMap.begin() ); 211 const LockInfoMap::const_iterator end( m_aLockInfoMap.end() ); 212 while ( it != end ) 213 { 214 LockInfo & rInfo = (*it).second; 215 if ( rInfo.nLastChanceToSendRefreshRequest != -1 ) 216 { 217 // 30 seconds or less remaining until lock expires? 218 TimeValue t1; 219 osl_getSystemTime( &t1 ); 220 if ( rInfo.nLastChanceToSendRefreshRequest - 30 221 <= sal_Int32( t1.Seconds ) ) 222 { 223 // refresh the lock. 224 sal_Int32 nlastChanceToSendRefreshRequest = -1; 225 if ( rInfo.xSession->LOCK( 226 (*it).first, 227 /* out param */ nlastChanceToSendRefreshRequest ) ) 228 { 229 rInfo.nLastChanceToSendRefreshRequest 230 = nlastChanceToSendRefreshRequest; 231 } 232 else 233 { 234 // refresh failed. stop auto-refresh. 235 rInfo.nLastChanceToSendRefreshRequest = -1; 236 } 237 } 238 } 239 ++it; 240 } 241 } 242