office-gobmx/ucb/source/ucp/webdav/NeonLockStore.cxx
2011-03-29 21:40:28 +01:00

248 lines
7.2 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2000, 2010 Oracle and/or its affiliates.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* This file is part of OpenOffice.org.
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenOffice.org is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
*
************************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_ucb.hxx"
#include <ne_locks.h>
#include <ne_uri.h>
#include "rtl/ustring.hxx"
#include "osl/time.h"
#include "osl/thread.hxx"
#include "NeonSession.hxx"
#include "NeonLockStore.hxx"
using namespace webdav_ucp;
namespace webdav_ucp {
class TickerThread : public osl::Thread
{
bool m_bFinish;
NeonLockStore & m_rLockStore;
public:
TickerThread( NeonLockStore & rLockStore )
: osl::Thread(), m_bFinish( false ), m_rLockStore( rLockStore ) {}
void finish() { m_bFinish = true; }
protected:
virtual void SAL_CALL run();
};
} // namespace webdav_ucp
// -------------------------------------------------------------------
void TickerThread::run()
{
OSL_TRACE( "TickerThread: 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." );
}
// -------------------------------------------------------------------
NeonLockStore::NeonLockStore()
: m_pNeonLockStore( ne_lockstore_create() ),
m_pTickerThread( 0 )
{
OSL_ENSURE( m_pNeonLockStore, "Unable to create neon lock store!" );
}
// -------------------------------------------------------------------
NeonLockStore::~NeonLockStore()
{
stopTicker();
// release active locks, if any.
OSL_ENSURE( m_aLockInfoMap.size() == 0,
"NeonLockStore::~NeonLockStore - Releasing active locks!" );
LockInfoMap::const_iterator it( m_aLockInfoMap.begin() );
const LockInfoMap::const_iterator end( m_aLockInfoMap.end() );
while ( it != end )
{
NeonLock * pLock = (*it).first;
(*it).second.xSession->UNLOCK( pLock );
ne_lockstore_remove( m_pNeonLockStore, pLock );
ne_lock_destroy( pLock );
++it;
}
ne_lockstore_destroy( m_pNeonLockStore );
}
// -------------------------------------------------------------------
void NeonLockStore::startTicker()
{
osl::MutexGuard aGuard( m_aMutex );
if ( !m_pTickerThread )
{
m_pTickerThread = new TickerThread( *this );
m_pTickerThread->create();
}
}
// -------------------------------------------------------------------
void NeonLockStore::stopTicker()
{
osl::MutexGuard aGuard( m_aMutex );
if ( m_pTickerThread )
{
m_pTickerThread->finish();
m_pTickerThread->join();
delete m_pTickerThread;
m_pTickerThread = 0;
}
}
// -------------------------------------------------------------------
void NeonLockStore::registerSession( HttpSession * pHttpSession )
{
osl::MutexGuard aGuard( m_aMutex );
ne_lockstore_register( m_pNeonLockStore, pHttpSession );
}
// -------------------------------------------------------------------
NeonLock * NeonLockStore::findByUri( rtl::OUString const & rUri )
{
osl::MutexGuard aGuard( m_aMutex );
ne_uri aUri;
ne_uri_parse( rtl::OUStringToOString(
rUri, RTL_TEXTENCODING_UTF8 ).getStr(), &aUri );
return ne_lockstore_findbyuri( m_pNeonLockStore, &aUri );
}
// -------------------------------------------------------------------
void NeonLockStore::addLock( NeonLock * pLock,
rtl::Reference< NeonSession > const & xSession,
sal_Int32 nLastChanceToSendRefreshRequest )
{
osl::MutexGuard aGuard( m_aMutex );
ne_lockstore_add( m_pNeonLockStore, pLock );
m_aLockInfoMap[ pLock ]
= LockInfo( xSession, nLastChanceToSendRefreshRequest );
startTicker();
}
// -------------------------------------------------------------------
void NeonLockStore::updateLock( NeonLock * pLock,
sal_Int32 nLastChanceToSendRefreshRequest )
{
osl::MutexGuard aGuard( m_aMutex );
LockInfoMap::iterator it( m_aLockInfoMap.find( pLock ) );
OSL_ENSURE( it != m_aLockInfoMap.end(),
"NeonLockStore::updateLock: lock not found!" );
if ( it != m_aLockInfoMap.end() )
{
(*it).second.nLastChanceToSendRefreshRequest
= nLastChanceToSendRefreshRequest;
}
}
// -------------------------------------------------------------------
void NeonLockStore::removeLock( NeonLock * pLock )
{
osl::MutexGuard aGuard( m_aMutex );
m_aLockInfoMap.erase( pLock );
ne_lockstore_remove( m_pNeonLockStore, pLock );
if ( m_aLockInfoMap.size() == 0 )
stopTicker();
}
// -------------------------------------------------------------------
void NeonLockStore::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.
sal_Int32 nlastChanceToSendRefreshRequest = -1;
if ( rInfo.xSession->LOCK(
(*it).first,
/* out param */ nlastChanceToSendRefreshRequest ) )
{
rInfo.nLastChanceToSendRefreshRequest
= nlastChanceToSendRefreshRequest;
}
else
{
// refresh failed. stop auto-refresh.
rInfo.nLastChanceToSendRefreshRequest = -1;
}
}
}
++it;
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */