Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*************************************************************************
3 : *
4 : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : *
6 : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : *
8 : * OpenOffice.org - a multi-platform office productivity suite
9 : *
10 : * This file is part of OpenOffice.org.
11 : *
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.
15 : *
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).
21 : *
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.
26 : *
27 : ************************************************************************/
28 :
29 :
30 : #include <ne_uri.h>
31 : #include "rtl/ustring.hxx"
32 : #include "osl/time.h"
33 : #include "osl/thread.hxx"
34 : #include "salhelper/thread.hxx"
35 : #include "NeonSession.hxx"
36 : #include "NeonLockStore.hxx"
37 :
38 : using namespace webdav_ucp;
39 :
40 : namespace webdav_ucp {
41 :
42 0 : class TickerThread : public salhelper::Thread
43 : {
44 : bool m_bFinish;
45 : NeonLockStore & m_rLockStore;
46 :
47 : public:
48 :
49 0 : TickerThread( NeonLockStore & rLockStore )
50 : : Thread( "NeonTickerThread" ), m_bFinish( false ),
51 0 : m_rLockStore( rLockStore ) {}
52 :
53 0 : void finish() { m_bFinish = true; }
54 :
55 : private:
56 :
57 : virtual void execute() SAL_OVERRIDE;
58 : };
59 :
60 : } // namespace webdav_ucp
61 :
62 0 : void TickerThread::execute()
63 : {
64 : OSL_TRACE( "TickerThread: start." );
65 :
66 : // we have to go through the loop more often to be able to finish ~quickly
67 0 : const int nNth = 25;
68 :
69 0 : int nCount = nNth;
70 0 : while ( !m_bFinish )
71 : {
72 0 : if ( nCount-- <= 0 )
73 : {
74 0 : m_rLockStore.refreshLocks();
75 0 : nCount = nNth;
76 : }
77 :
78 : TimeValue aTV;
79 0 : aTV.Seconds = 0;
80 0 : aTV.Nanosec = 1000000000 / nNth;
81 0 : salhelper::Thread::wait( aTV );
82 : }
83 :
84 : OSL_TRACE( "TickerThread: stop." );
85 0 : }
86 :
87 2 : NeonLockStore::NeonLockStore()
88 2 : : m_pNeonLockStore( ne_lockstore_create() )
89 : {
90 : OSL_ENSURE( m_pNeonLockStore, "Unable to create neon lock store!" );
91 2 : }
92 :
93 4 : NeonLockStore::~NeonLockStore()
94 : {
95 2 : osl::ResettableMutexGuard aGuard(m_aMutex);
96 2 : stopTicker(aGuard);
97 2 : aGuard.reset(); // actually no threads should even try to access members now
98 :
99 : // release active locks, if any.
100 : OSL_ENSURE( m_aLockInfoMap.empty(),
101 : "NeonLockStore::~NeonLockStore - Releasing active locks!" );
102 :
103 2 : LockInfoMap::const_iterator it( m_aLockInfoMap.begin() );
104 2 : const LockInfoMap::const_iterator end( m_aLockInfoMap.end() );
105 4 : while ( it != end )
106 : {
107 0 : NeonLock * pLock = (*it).first;
108 0 : (*it).second.xSession->UNLOCK( pLock );
109 :
110 0 : ne_lockstore_remove( m_pNeonLockStore, pLock );
111 0 : ne_lock_destroy( pLock );
112 :
113 0 : ++it;
114 : }
115 :
116 2 : ne_lockstore_destroy( m_pNeonLockStore );
117 2 : }
118 :
119 0 : void NeonLockStore::startTicker()
120 : {
121 0 : osl::MutexGuard aGuard( m_aMutex );
122 :
123 0 : if ( !m_pTickerThread.is() )
124 : {
125 0 : m_pTickerThread = new TickerThread( *this );
126 0 : m_pTickerThread->launch();
127 0 : }
128 0 : }
129 :
130 2 : void NeonLockStore::stopTicker(osl::ClearableMutexGuard & rGuard)
131 : {
132 2 : rtl::Reference<TickerThread> pTickerThread;
133 :
134 2 : if (m_pTickerThread.is())
135 : {
136 0 : m_pTickerThread->finish(); // needs mutex
137 : // the TickerThread may run refreshLocks() at most once after this
138 0 : pTickerThread = m_pTickerThread;
139 0 : m_pTickerThread.clear();
140 : }
141 :
142 2 : rGuard.clear();
143 :
144 2 : if (pTickerThread.is())
145 0 : pTickerThread->join(); // without m_aMutex locked (to prevent deadlock)
146 2 : }
147 :
148 0 : void NeonLockStore::registerSession( HttpSession * pHttpSession )
149 : {
150 0 : osl::MutexGuard aGuard( m_aMutex );
151 :
152 0 : ne_lockstore_register( m_pNeonLockStore, pHttpSession );
153 0 : }
154 :
155 0 : NeonLock * NeonLockStore::findByUri( OUString const & rUri )
156 : {
157 0 : osl::MutexGuard aGuard( m_aMutex );
158 :
159 : ne_uri aUri;
160 : ne_uri_parse( OUStringToOString(
161 0 : rUri, RTL_TEXTENCODING_UTF8 ).getStr(), &aUri );
162 0 : return ne_lockstore_findbyuri( m_pNeonLockStore, &aUri );
163 : }
164 :
165 0 : void NeonLockStore::addLock( NeonLock * pLock,
166 : rtl::Reference< NeonSession > const & xSession,
167 : sal_Int32 nLastChanceToSendRefreshRequest )
168 : {
169 0 : osl::MutexGuard aGuard( m_aMutex );
170 :
171 0 : ne_lockstore_add( m_pNeonLockStore, pLock );
172 0 : m_aLockInfoMap[ pLock ]
173 0 : = LockInfo( xSession, nLastChanceToSendRefreshRequest );
174 :
175 0 : startTicker();
176 0 : }
177 :
178 0 : void NeonLockStore::updateLock( NeonLock * pLock,
179 : sal_Int32 nLastChanceToSendRefreshRequest )
180 : {
181 0 : osl::MutexGuard aGuard( m_aMutex );
182 :
183 0 : LockInfoMap::iterator it( m_aLockInfoMap.find( pLock ) );
184 : OSL_ENSURE( it != m_aLockInfoMap.end(),
185 : "NeonLockStore::updateLock: lock not found!" );
186 :
187 0 : if ( it != m_aLockInfoMap.end() )
188 : {
189 0 : (*it).second.nLastChanceToSendRefreshRequest
190 0 : = nLastChanceToSendRefreshRequest;
191 0 : }
192 0 : }
193 :
194 0 : void NeonLockStore::removeLock( NeonLock * pLock )
195 : {
196 0 : osl::ClearableMutexGuard aGuard( m_aMutex );
197 :
198 0 : m_aLockInfoMap.erase( pLock );
199 0 : ne_lockstore_remove( m_pNeonLockStore, pLock );
200 :
201 0 : if ( m_aLockInfoMap.empty() )
202 0 : stopTicker(aGuard);
203 0 : }
204 :
205 0 : void NeonLockStore::refreshLocks()
206 : {
207 0 : osl::MutexGuard aGuard( m_aMutex );
208 :
209 0 : LockInfoMap::iterator it( m_aLockInfoMap.begin() );
210 0 : const LockInfoMap::const_iterator end( m_aLockInfoMap.end() );
211 0 : while ( it != end )
212 : {
213 0 : LockInfo & rInfo = (*it).second;
214 0 : if ( rInfo.nLastChanceToSendRefreshRequest != -1 )
215 : {
216 : // 30 seconds or less remaining until lock expires?
217 : TimeValue t1;
218 0 : osl_getSystemTime( &t1 );
219 0 : if ( rInfo.nLastChanceToSendRefreshRequest - 30
220 0 : <= sal_Int32( t1.Seconds ) )
221 : {
222 : // refresh the lock.
223 0 : sal_Int32 nlastChanceToSendRefreshRequest = -1;
224 0 : if ( rInfo.xSession->LOCK(
225 0 : (*it).first,
226 0 : /* out param */ nlastChanceToSendRefreshRequest ) )
227 : {
228 : rInfo.nLastChanceToSendRefreshRequest
229 0 : = nlastChanceToSendRefreshRequest;
230 : }
231 : else
232 : {
233 : // refresh failed. stop auto-refresh.
234 0 : rInfo.nLastChanceToSendRefreshRequest = -1;
235 : }
236 : }
237 : }
238 0 : ++it;
239 0 : }
240 0 : }
241 :
242 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|