bump product version to 5.0.4.1
[LibreOffice.git] / ucb / source / ucp / webdav-neon / NeonLockStore.cxx
blob5d7d35f904f6fea2e6cfa8b0523fbbca83452d8e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include <ne_uri.h>
31 #include "rtl/ustring.hxx"
32 #include "osl/time.h"
33 #include "osl/thread.hxx"
34 #include <osl/diagnose.h>
35 #include "salhelper/thread.hxx"
36 #include "NeonSession.hxx"
37 #include "NeonLockStore.hxx"
39 using namespace webdav_ucp;
41 namespace webdav_ucp {
43 class TickerThread : public salhelper::Thread
45 bool m_bFinish;
46 NeonLockStore & m_rLockStore;
48 public:
50 TickerThread( NeonLockStore & rLockStore )
51 : Thread( "NeonTickerThread" ), m_bFinish( false ),
52 m_rLockStore( rLockStore ) {}
54 void finish() { m_bFinish = true; }
56 private:
58 virtual void execute() SAL_OVERRIDE;
61 } // namespace webdav_ucp
63 void TickerThread::execute()
65 OSL_TRACE( "TickerThread: start." );
67 // we have to go through the loop more often to be able to finish ~quickly
68 const int nNth = 25;
70 int nCount = nNth;
71 while ( !m_bFinish )
73 if ( nCount-- <= 0 )
75 m_rLockStore.refreshLocks();
76 nCount = nNth;
79 TimeValue aTV;
80 aTV.Seconds = 0;
81 aTV.Nanosec = 1000000000 / nNth;
82 salhelper::Thread::wait( aTV );
85 OSL_TRACE( "TickerThread: stop." );
88 NeonLockStore::NeonLockStore()
89 : m_pNeonLockStore( ne_lockstore_create() )
91 OSL_ENSURE( m_pNeonLockStore, "Unable to create neon lock store!" );
94 NeonLockStore::~NeonLockStore()
96 osl::ResettableMutexGuard aGuard(m_aMutex);
97 stopTicker(aGuard);
98 aGuard.reset(); // actually no threads should even try to access members now
100 // release active locks, if any.
101 OSL_ENSURE( m_aLockInfoMap.empty(),
102 "NeonLockStore::~NeonLockStore - Releasing active locks!" );
104 LockInfoMap::const_iterator it( m_aLockInfoMap.begin() );
105 const LockInfoMap::const_iterator end( m_aLockInfoMap.end() );
106 while ( it != end )
108 NeonLock * pLock = (*it).first;
109 (*it).second.xSession->UNLOCK( pLock );
111 ne_lockstore_remove( m_pNeonLockStore, pLock );
112 ne_lock_destroy( pLock );
114 ++it;
117 ne_lockstore_destroy( m_pNeonLockStore );
120 void NeonLockStore::startTicker()
122 osl::MutexGuard aGuard( m_aMutex );
124 if ( !m_pTickerThread.is() )
126 m_pTickerThread = new TickerThread( *this );
127 m_pTickerThread->launch();
131 void NeonLockStore::stopTicker(osl::ClearableMutexGuard & rGuard)
133 rtl::Reference<TickerThread> pTickerThread;
135 if (m_pTickerThread.is())
137 m_pTickerThread->finish(); // needs mutex
138 // the TickerThread may run refreshLocks() at most once after this
139 pTickerThread = m_pTickerThread;
140 m_pTickerThread.clear();
143 rGuard.clear();
145 if (pTickerThread.is())
146 pTickerThread->join(); // without m_aMutex locked (to prevent deadlock)
149 void NeonLockStore::registerSession( HttpSession * pHttpSession )
151 osl::MutexGuard aGuard( m_aMutex );
153 ne_lockstore_register( m_pNeonLockStore, pHttpSession );
156 NeonLock * NeonLockStore::findByUri( OUString const & rUri )
158 osl::MutexGuard aGuard( m_aMutex );
160 ne_uri aUri;
161 ne_uri_parse( OUStringToOString(
162 rUri, RTL_TEXTENCODING_UTF8 ).getStr(), &aUri );
163 return ne_lockstore_findbyuri( m_pNeonLockStore, &aUri );
166 void NeonLockStore::addLock( NeonLock * pLock,
167 rtl::Reference< NeonSession > const & xSession,
168 sal_Int32 nLastChanceToSendRefreshRequest )
170 osl::MutexGuard aGuard( m_aMutex );
172 ne_lockstore_add( m_pNeonLockStore, pLock );
173 m_aLockInfoMap[ pLock ]
174 = LockInfo( xSession, nLastChanceToSendRefreshRequest );
176 startTicker();
179 void NeonLockStore::updateLock( NeonLock * pLock,
180 sal_Int32 nLastChanceToSendRefreshRequest )
182 osl::MutexGuard aGuard( m_aMutex );
184 LockInfoMap::iterator it( m_aLockInfoMap.find( pLock ) );
185 OSL_ENSURE( it != m_aLockInfoMap.end(),
186 "NeonLockStore::updateLock: lock not found!" );
188 if ( it != m_aLockInfoMap.end() )
190 (*it).second.nLastChanceToSendRefreshRequest
191 = nLastChanceToSendRefreshRequest;
195 void NeonLockStore::removeLock( NeonLock * pLock )
197 osl::ClearableMutexGuard aGuard( m_aMutex );
199 m_aLockInfoMap.erase( pLock );
200 ne_lockstore_remove( m_pNeonLockStore, pLock );
202 if ( m_aLockInfoMap.empty() )
203 stopTicker(aGuard);
206 void NeonLockStore::refreshLocks()
208 osl::MutexGuard aGuard( m_aMutex );
210 LockInfoMap::iterator it( m_aLockInfoMap.begin() );
211 const LockInfoMap::const_iterator end( m_aLockInfoMap.end() );
212 while ( it != end )
214 LockInfo & rInfo = (*it).second;
215 if ( rInfo.nLastChanceToSendRefreshRequest != -1 )
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 ) )
223 // refresh the lock.
224 sal_Int32 nlastChanceToSendRefreshRequest = -1;
225 if ( rInfo.xSession->LOCK(
226 (*it).first,
227 /* out param */ nlastChanceToSendRefreshRequest ) )
229 rInfo.nLastChanceToSendRefreshRequest
230 = nlastChanceToSendRefreshRequest;
232 else
234 // refresh failed. stop auto-refresh.
235 rInfo.nLastChanceToSendRefreshRequest = -1;
239 ++it;
243 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */