blob: d62eb55c17f82933c57c91486da6a1e133892b89 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_ucb.hxx"
#include <rtl/ustring.hxx>
#include <osl/time.h>
#include <osl/thread.hxx>
#include "SerfTypes.hxx"
#include "SerfSession.hxx"
#include "SerfLockStore.hxx"
using namespace http_dav_ucp;
namespace http_dav_ucp {
class TickerThread : public osl::Thread
{
bool m_bFinish;
SerfLockStore & m_rLockStore;
public:
TickerThread( SerfLockStore & rLockStore )
: osl::Thread(), m_bFinish( false ), m_rLockStore( rLockStore ) {}
void finish() { m_bFinish = true; }
protected:
virtual void SAL_CALL run();
};
} // namespace http_dav_ucp
// -------------------------------------------------------------------
void TickerThread::run()
{
OSL_TRACE( "TickerThread::run: start." );
// we have to go through the loop more often to be able to finish ~quickly
const int nNth = 25;
int nCount = nNth;
while ( !m_bFinish )
{
if ( nCount-- <= 0 )
{
m_rLockStore.refreshLocks();
nCount = nNth;
}
TimeValue aTV;
aTV.Seconds = 0;
aTV.Nanosec = 1000000000 / nNth;
wait( aTV );
}
OSL_TRACE( "TickerThread: stop." );
}
// -------------------------------------------------------------------
SerfLockStore::SerfLockStore()
: m_pTickerThread( 0 )
{
}
// -------------------------------------------------------------------
SerfLockStore::~SerfLockStore()
{
stopTicker();
// release active locks, if any.
OSL_ENSURE( m_aLockInfoMap.size() == 0,
"SerfLockStore::~SerfLockStore - Releasing active locks!" );
LockInfoMap::const_iterator it( m_aLockInfoMap.begin() );
const LockInfoMap::const_iterator end( m_aLockInfoMap.end() );
while ( it != end )
{
SerfLock * pLock = (*it).first;
try
{
(*it).second.xSession->UNLOCK( pLock );
(*it).second.xSession->release();
}
catch (DAVException & )
{}
++it;
}
}
// -------------------------------------------------------------------
void SerfLockStore::startTicker()
{
osl::MutexGuard aGuard( m_aMutex );
if ( !m_pTickerThread )
{
m_pTickerThread = new TickerThread( *this );
m_pTickerThread->create();
}
}
// -------------------------------------------------------------------
void SerfLockStore::stopTicker()
{
osl::MutexGuard aGuard( m_aMutex );
if ( m_pTickerThread )
{
m_pTickerThread->finish();
m_pTickerThread->join();
delete m_pTickerThread;
m_pTickerThread = 0;
}
}
#if 0 //not currently used
// -------------------------------------------------------------------
void SerfLockStore::registerSession( SerfSession /* aSession */ )
{
osl::MutexGuard aGuard( m_aMutex );
}
#endif
// -------------------------------------------------------------------
SerfLock * SerfLockStore::findByUri( rtl::OUString const & rUri)
{
osl::MutexGuard aGuard( m_aMutex );
LockInfoMap::const_iterator it( m_aLockInfoMap.begin() );
const LockInfoMap::const_iterator end( m_aLockInfoMap.end() );
while ( it != end )
{
SerfLock * pLock = (*it).first;
if( pLock->getResourceUri().equals( rUri ) )
{
return pLock;
}
++it;
}
return static_cast<SerfLock*>(0);
}
// -------------------------------------------------------------------
void SerfLockStore::addLock( SerfLock * pLock,
rtl::Reference< SerfSession > const & xSession,
sal_Int32 nLastChanceToSendRefreshRequest )
{
osl::MutexGuard aGuard( m_aMutex );
m_aLockInfoMap[ pLock ]
= LockInfo( xSession, nLastChanceToSendRefreshRequest );
//acquire this session, needed to manage the lock refresh
xSession->acquire();
#if OSL_DEBUG_LEVEL > 0
rtl::OUString aOwner;
pLock->getLock().Owner >>= aOwner;
rtl::OUString aToken;
aToken = pLock->getLock().LockTokens[0];
OSL_TRACE("SerfLockStore::addLock: new lock added aOwner '%s', token '%s'",
rtl::OUStringToOString(aOwner, RTL_TEXTENCODING_UTF8).getStr(),
rtl::OUStringToOString(aToken, RTL_TEXTENCODING_UTF8).getStr() );
#endif
startTicker();
}
#if 0 //not currently used
// -------------------------------------------------------------------
void SerfLockStore::updateLock( SerfLock * pLock,
sal_Int32 nLastChanceToSendRefreshRequest )
{
osl::MutexGuard aGuard( m_aMutex );
LockInfoMap::iterator it( m_aLockInfoMap.find( pLock ) );
OSL_ENSURE( it != m_aLockInfoMap.end(),
"SerfLockStore::updateLock: lock not found!" );
if ( it != m_aLockInfoMap.end() )
{
(*it).second.nLastChanceToSendRefreshRequest
= nLastChanceToSendRefreshRequest;
}
}
#endif
// -------------------------------------------------------------------
void SerfLockStore::removeLock( SerfLock * pLock )
{
osl::MutexGuard aGuard( m_aMutex );
LockInfoMap::iterator it( m_aLockInfoMap.find( pLock ) );
if(it != m_aLockInfoMap.end())
{
LockInfo & rInfo = (*it).second;
rInfo.xSession->release();
m_aLockInfoMap.erase( pLock );
//the caller should deallocate SerfLock class after the call!
if ( m_aLockInfoMap.size() == 0 )
stopTicker();
}
}
// -------------------------------------------------------------------
void SerfLockStore::refreshLocks()
{
osl::MutexGuard aGuard( m_aMutex );
LockInfoMap::iterator it( m_aLockInfoMap.begin() );
const LockInfoMap::const_iterator end( m_aLockInfoMap.end() );
while ( it != end )
{
LockInfo & rInfo = (*it).second;
if ( rInfo.nLastChanceToSendRefreshRequest != -1 )
{
// 30 seconds or less remaining until lock expires?
TimeValue t1;
osl_getSystemTime( &t1 );
if ( rInfo.nLastChanceToSendRefreshRequest - 30
<= sal_Int32( t1.Seconds ) )
{
// refresh the lock.
#if OSL_DEBUG_LEVEL > 0
ucb::Lock aLock = (*it).first->getLock();
rtl::OUString aOwner;
aLock.Owner >>= aOwner;
rtl::OUString aToken;
aToken = aLock.LockTokens[0];
OSL_TRACE( "SerfLockStore::refreshLocks: refresh started for lock: aOwner '%s', token '%s'",
rtl::OUStringToOString(aOwner, RTL_TEXTENCODING_UTF8).getStr(),
rtl::OUStringToOString(aToken, RTL_TEXTENCODING_UTF8).getStr() );
#endif
sal_Int32 nlastChanceToSendRefreshRequest = -1;
try
{
rInfo.xSession->LOCK( (*it).first,
/* out param */ nlastChanceToSendRefreshRequest );
rInfo.nLastChanceToSendRefreshRequest
= nlastChanceToSendRefreshRequest;
#if OSL_DEBUG_LEVEL > 0
OSL_TRACE( "Lock '%s' successfully refreshed." ,
rtl::OUStringToOString(aToken, RTL_TEXTENCODING_UTF8).getStr() );
#endif
}
catch ( DAVException & e )
{
// refresh failed. stop auto-refresh.
// TODO i126305 discuss:
// probably not a good idea to stop the refresh?
// may be just ignore and go on, it's possible the net is temporary down?
rInfo.nLastChanceToSendRefreshRequest = -1;
#if OSL_DEBUG_LEVEL > 0
OSL_TRACE( "SerfLockStore::refreshLocks: Lock '%s' not refreshed! (error: DAVException.mStatusCode %d)",
rtl::OUStringToOString(aToken, RTL_TEXTENCODING_UTF8).getStr(), e.getStatus() );
#endif
}
}
}
++it;
}
}