1 /* |
|
2 * Copyright (c) 2004-2006 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Lock manager for locked remote files |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include "rsfwfileentry.h" |
|
20 #include "rsfwrfestatemachine.h" |
|
21 #include "rsfwlockmanager.h" |
|
22 #include "rsfwfileentry.h" |
|
23 #include "rsfwconfig.h" |
|
24 #include "mdebug.h" |
|
25 |
|
26 // ---------------------------------------------------------------------------- |
|
27 |
|
28 // ============================ MEMBER FUNCTIONS ============================== |
|
29 |
|
30 // ---------------------------------------------------------------------------- |
|
31 // CRsfwLockManager::NewL |
|
32 // ---------------------------------------------------------------------------- |
|
33 // |
|
34 CRsfwLockManager* CRsfwLockManager::NewL(CRsfwRemoteAccess* aRemoteAccess) |
|
35 { |
|
36 CRsfwLockManager* self = CRsfwLockManager::NewLC(aRemoteAccess); |
|
37 CleanupStack::Pop(self); |
|
38 return self; |
|
39 } |
|
40 |
|
41 // ---------------------------------------------------------------------------- |
|
42 // CRsfwLockManager::NewLC |
|
43 // ---------------------------------------------------------------------------- |
|
44 // |
|
45 CRsfwLockManager* CRsfwLockManager::NewLC(CRsfwRemoteAccess* aRemoteAccess) |
|
46 { |
|
47 DEBUGSTRING(("CRsfwLockManager::NewLC")); |
|
48 CRsfwLockManager* self = new (ELeave) CRsfwLockManager(); |
|
49 CleanupStack::PushL(self); |
|
50 self->ConstructL(aRemoteAccess); |
|
51 return self; |
|
52 } |
|
53 |
|
54 // ---------------------------------------------------------------------------- |
|
55 // CRsfwLockManager::ConstructL |
|
56 // ---------------------------------------------------------------------------- |
|
57 // |
|
58 void CRsfwLockManager::ConstructL(CRsfwRemoteAccess* aRemoteAccess) |
|
59 { |
|
60 iRemoteAccess = aRemoteAccess; |
|
61 } |
|
62 |
|
63 // ---------------------------------------------------------------------------- |
|
64 // CRsfwLockManager::~CRsfwLockManager |
|
65 // ---------------------------------------------------------------------------- |
|
66 // |
|
67 CRsfwLockManager::~CRsfwLockManager() |
|
68 { |
|
69 iLockRefreshContexts.Close(); |
|
70 |
|
71 // set unlock flag for all the entries locked |
|
72 while (iLockedEntries.Count() > 0) |
|
73 { |
|
74 CRsfwFileEntry* entry = iLockedEntries[0]; |
|
75 iLockedEntries.Remove(0); |
|
76 // note that RemoveLocked will call CRsfwLockManager::RemoveLockedEntry |
|
77 entry->RemoveLocked(); |
|
78 } |
|
79 iLockedEntries.Close(); |
|
80 } |
|
81 |
|
82 |
|
83 // ---------------------------------------------------------------------------- |
|
84 // CRsfwLockManager::HandleRemoteAccessResponse |
|
85 // For handling the response from RefreshLockL(). |
|
86 // If the lock refresh is successful we restart the timer |
|
87 // as the server may have changed the timeout. |
|
88 // If the refresh request returns an error we remove the lock |
|
89 // We assume that server does not hold the lock anymore, |
|
90 // so we cannot re-acquire it simply by trying to refresh it again. |
|
91 // Instead, we should do a fresh lock operation |
|
92 // ---------------------------------------------------------------------------- |
|
93 // |
|
94 void CRsfwLockManager::HandleRemoteAccessResponse(TUint aId, |
|
95 TInt aStatus) |
|
96 { |
|
97 DEBUGSTRING(("CRsfwLockManager::HandleRemoteAccessResponse id: %d, status: %d", aId, aStatus)); |
|
98 TPendingLockRefreshContext lockRefresh; |
|
99 lockRefresh.iId = aId; |
|
100 TInt index = iLockRefreshContexts.Find(lockRefresh); |
|
101 if (index != KErrNotFound) |
|
102 { |
|
103 lockRefresh = iLockRefreshContexts[index]; |
|
104 if (aStatus == KErrNone) |
|
105 { |
|
106 // Note that this can leave only when creating the timer |
|
107 // so it shouldn't really leave anymore at this point. |
|
108 // Also resetting the timer and calling Start() do not even |
|
109 // return an error, so there is no need to examine err or ret value |
|
110 TRAP_IGNORE(lockRefresh.iFileEntry->SetLockedL(this, NULL)); |
|
111 } |
|
112 else |
|
113 { |
|
114 lockRefresh.iFileEntry->RemoveLocked(); |
|
115 } |
|
116 iLockRefreshContexts.Remove(index); |
|
117 } |
|
118 } |
|
119 |
|
120 // ---------------------------------------------------------------------------- |
|
121 // CRsfwLockManager::ObtainLockL |
|
122 // ---------------------------------------------------------------------------- |
|
123 // |
|
124 void CRsfwLockManager::ObtainLockL(CRsfwFileEntry *aFileEntry, |
|
125 TUint aLockFlags, |
|
126 TDesC8*& aLockToken, |
|
127 CRsfwRfeStateMachine* aOperation) |
|
128 { |
|
129 DEBUGSTRING(("CRsfwLockManager::ObtainLockL")); |
|
130 if (aFileEntry->iLockTimeout == 0) |
|
131 { |
|
132 // No locking wanted, |
|
133 // we use notsupported as a return code in this case too.... |
|
134 DEBUGSTRING(("lock timeout in CFileEntry is 0, no locking")); |
|
135 aOperation->HandleRemoteAccessResponse(0, KErrNotSupported); |
|
136 } |
|
137 else |
|
138 { |
|
139 HBufC* fullName = aFileEntry->FullNameLC(); |
|
140 if (!iRemoteAccess) |
|
141 { |
|
142 DEBUGSTRING(("iRemoteAccess NULL")); |
|
143 User::Leave(KErrNotReady); |
|
144 } |
|
145 else |
|
146 { |
|
147 DEBUGSTRING(("calling iRemoteAccess::ObtainLockL()")); |
|
148 iRemoteAccess->ObtainLockL(*fullName, |
|
149 aLockFlags, |
|
150 aFileEntry->iLockTimeout, |
|
151 aLockToken, |
|
152 aOperation); |
|
153 } |
|
154 |
|
155 CleanupStack::PopAndDestroy(fullName); // fullname |
|
156 } |
|
157 |
|
158 } |
|
159 |
|
160 // ---------------------------------------------------------------------------- |
|
161 // CRsfwLockManager::ReleaseLockL |
|
162 // ---------------------------------------------------------------------------- |
|
163 // |
|
164 void CRsfwLockManager::ReleaseLockL(CRsfwFileEntry* aFileEntry, |
|
165 CRsfwRfeStateMachine* aOperation) |
|
166 { |
|
167 DEBUGSTRING(("CRsfwLockManager::ReleaseLockL")); |
|
168 if (aFileEntry->iLockTimeout == 0) |
|
169 { |
|
170 // No locking |
|
171 User::Leave(KErrNotFound); |
|
172 } |
|
173 |
|
174 |
|
175 if (!iRemoteAccess) |
|
176 { |
|
177 User::Leave(KErrNotReady); |
|
178 } |
|
179 else |
|
180 { |
|
181 HBufC* fullName = aFileEntry->FullNameLC(); |
|
182 #ifdef _DEBUG |
|
183 TInt err; |
|
184 err = iRemoteAccess->ReleaseLockL(*fullName, aOperation); |
|
185 TPtrC p = fullName->Des(); |
|
186 DEBUGSTRING16(("ReleaseLockL(): returned %d for file '%S'", err, &p)); |
|
187 |
|
188 |
|
189 |
|
190 #else |
|
191 iRemoteAccess->ReleaseLockL(*fullName, aOperation); |
|
192 #endif |
|
193 CleanupStack::PopAndDestroy(fullName); // fullname |
|
194 } |
|
195 |
|
196 } |
|
197 |
|
198 // ---------------------------------------------------------------------------- |
|
199 // CRsfwLockManager::RefreshLockL |
|
200 // ---------------------------------------------------------------------------- |
|
201 // |
|
202 void CRsfwLockManager::RefreshLockL(CRsfwFileEntry* aFileEntry) |
|
203 { |
|
204 DEBUGSTRING(("CRsfwLockManager::RefreshLockL")); |
|
205 TInt id = 0; |
|
206 if (aFileEntry->iLockTimeout > 0) // timeout = 0 indicates no locking |
|
207 { |
|
208 aFileEntry->iLockTimer->Cancel(); // cancel the old timer |
|
209 HBufC* fullName = aFileEntry->FullNameLC(); |
|
210 TRAPD(err, id = iRemoteAccess->RefreshLockL(*fullName, |
|
211 aFileEntry->iLockTimeout, |
|
212 this)); |
|
213 if (err == KErrNone) |
|
214 { |
|
215 TPendingLockRefreshContext lockRefresh; |
|
216 lockRefresh.iId = id; |
|
217 lockRefresh.iFileEntry = aFileEntry; |
|
218 iLockRefreshContexts.AppendL(lockRefresh); |
|
219 } |
|
220 else |
|
221 { |
|
222 // This error would come from the lower layers of the communication |
|
223 // stack, not from the server. |
|
224 // We use the timer mechanism to try again |
|
225 // but set the timeout to smaller. |
|
226 // Note that we don't touch aFileEntry->iLockTimer, |
|
227 // which will be used to set the timeout requested from the server |
|
228 TInt lockTimeout = |
|
229 Min((aFileEntry->iLockTimeout / KLockRefreshAdjustment) / 2, |
|
230 KMinLockRefreshAttempt); |
|
231 TCallBack callBack(CRsfwFileEntry::LockTimerExpiredL, this); |
|
232 aFileEntry->iLockTimer->Start(1000000 * lockTimeout, |
|
233 1000000 * lockTimeout, |
|
234 callBack); |
|
235 } |
|
236 CleanupStack::PopAndDestroy(fullName); // fullname |
|
237 } |
|
238 } |
|
239 |
|
240 // ---------------------------------------------------------------------------- |
|
241 // CRsfwLockManager::LockedCount |
|
242 // ---------------------------------------------------------------------------- |
|
243 // |
|
244 TInt CRsfwLockManager::LockedCount() |
|
245 { |
|
246 return iLockedEntries.Count(); |
|
247 } |
|
248 |
|
249 // ---------------------------------------------------------------------------- |
|
250 // CRsfwLockManager::AddLockedEntryL |
|
251 // ---------------------------------------------------------------------------- |
|
252 // |
|
253 void CRsfwLockManager::AddLockedEntryL(CRsfwFileEntry* aEntry) |
|
254 { |
|
255 // prevent from adding the same item twice |
|
256 if (iLockedEntries.Find(aEntry) != KErrNotFound) |
|
257 { |
|
258 return; |
|
259 } |
|
260 |
|
261 iLockedEntries.AppendL(aEntry); |
|
262 DEBUGSTRING(("Update locked count %d -> %d", |
|
263 iLockedEntries.Count() - 1, |
|
264 iLockedEntries.Count())); |
|
265 } |
|
266 |
|
267 // ---------------------------------------------------------------------------- |
|
268 // CRsfwLockManager::RemoveLockedEntry |
|
269 // ---------------------------------------------------------------------------- |
|
270 // |
|
271 void CRsfwLockManager::RemoveLockedEntry(CRsfwFileEntry* aEntry) |
|
272 { |
|
273 TInt index = iLockedEntries.Find(aEntry); |
|
274 if (index != KErrNotFound) |
|
275 { |
|
276 iLockedEntries.Remove(index); |
|
277 DEBUGSTRING(("Update locked count %d -> %d", |
|
278 iLockedEntries.Count() + 1, |
|
279 iLockedEntries.Count())); |
|
280 |
|
281 } |
|
282 } |
|
283 |
|
284 // ---------------------------------------------------------------------------- |
|
285 // CRsfwLockManager::PopulateExternalLockTokenCacheL |
|
286 // ---------------------------------------------------------------------------- |
|
287 // |
|
288 void CRsfwLockManager::PopulateExternalLockTokenCacheL(CRsfwFileEntry* aRoot) |
|
289 { |
|
290 if (aRoot) |
|
291 { |
|
292 const TDesC8* lockToken = aRoot->LockToken(); |
|
293 if (lockToken) |
|
294 { |
|
295 HBufC* path = aRoot->FullNameLC(); |
|
296 TPtr pathPtr = path->Des(); |
|
297 if (aRoot->Type() == KNodeTypeDir) |
|
298 { |
|
299 // the MaxLength() of path is KMaxPath, so we can append |
|
300 if (pathPtr.Length() && (pathPtr[pathPtr.Length() - 1] != '/')) |
|
301 { |
|
302 pathPtr.Append('/'); |
|
303 } |
|
304 } |
|
305 iRemoteAccess->SetLockToken(pathPtr, *lockToken); |
|
306 CleanupStack::PopAndDestroy(path); |
|
307 } |
|
308 |
|
309 RPointerArray<CRsfwFileEntry>* kids = aRoot->Kids(); |
|
310 TInt i; |
|
311 for (i = 0; i < kids->Count(); i++) |
|
312 { |
|
313 PopulateExternalLockTokenCacheL((*kids)[i]); |
|
314 } |
|
315 } |
|
316 } |
|
317 |
|
318 // End of File |
|