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