1 /* |
|
2 * Copyright (c) 2005-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: State machine for creating files |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include "rsfwcreatefilestatemachine.h" |
|
20 #include "rsfwfileentry.h" |
|
21 #include "rsfwfiletable.h" |
|
22 #include "rsfwinterface.h" |
|
23 #include "rsfwfileengine.h" |
|
24 #include "rsfwlockmanager.h" |
|
25 #include "mdebug.h" |
|
26 #include "rsfwdirentattr.h" |
|
27 #include "rsfwvolumetable.h" |
|
28 |
|
29 |
|
30 // ---------------------------------------------------------------------------- |
|
31 // CRsfwCreateFileStateMachine::CRsfwCreateFileStateMachine |
|
32 // ---------------------------------------------------------------------------- |
|
33 // |
|
34 CRsfwCreateFileStateMachine::CRsfwCreateFileStateMachine() |
|
35 { |
|
36 } |
|
37 |
|
38 // ---------------------------------------------------------------------------- |
|
39 // CRsfwCreateFileStateMachine::~CRsfwCreateFileStateMachine |
|
40 // ---------------------------------------------------------------------------- |
|
41 // |
|
42 CRsfwCreateFileStateMachine::~CRsfwCreateFileStateMachine() |
|
43 { |
|
44 delete iDirEntAttr; |
|
45 delete iLockToken; |
|
46 } |
|
47 |
|
48 // ---------------------------------------------------------------------------- |
|
49 // CRsfwCreateFileStateMachine::CompleteRequestL |
|
50 // ---------------------------------------------------------------------------- |
|
51 // |
|
52 CRsfwRfeStateMachine::TState* |
|
53 CRsfwCreateFileStateMachine::CompleteRequestL(TInt aError) |
|
54 { |
|
55 TRfeCreateOutArgs* outArgs = |
|
56 static_cast<TRfeCreateOutArgs*>(iOutArgs); |
|
57 if (!aError) |
|
58 { |
|
59 // Set the return values for the create call |
|
60 TFid* kidFidp = &(outArgs->iFid); |
|
61 TDirEntAttr* oAttrp = &(outArgs->iAttr); |
|
62 *kidFidp = iKidFep->Fid(); |
|
63 iKidFep->GetAttributes(*oAttrp); |
|
64 } |
|
65 |
|
66 if (iKidCreated && aError) |
|
67 { |
|
68 delete iKidFep; |
|
69 iKidFep = NULL; |
|
70 } |
|
71 |
|
72 // it may happen by chance that the new name is equal to iLastFailedLookup value |
|
73 FileEngine()->ResetFailedLookup(); |
|
74 |
|
75 CompleteAndDestroyState()->SetErrorCode(aError); |
|
76 return CompleteAndDestroyState(); |
|
77 } |
|
78 |
|
79 // Check if exists |
|
80 |
|
81 // ---------------------------------------------------------------------------- |
|
82 // CRsfwCreateFileStateMachine::TCheckIfExistsState::TCheckIfExistsState |
|
83 // ---------------------------------------------------------------------------- |
|
84 // |
|
85 CRsfwCreateFileStateMachine:: |
|
86 TCheckIfExistsState::TCheckIfExistsState(CRsfwCreateFileStateMachine* aParent) |
|
87 : iOperation(aParent) |
|
88 { |
|
89 } |
|
90 |
|
91 // ---------------------------------------------------------------------------- |
|
92 // CRsfwCreateFileStateMachine::TCheckIfExistsState::EnterL |
|
93 // ---------------------------------------------------------------------------- |
|
94 // |
|
95 void CRsfwCreateFileStateMachine::TCheckIfExistsState::EnterL() |
|
96 { |
|
97 DEBUGSTRING(("CRsfwCreateFileStateMachine::TCheckIfExistsState::EnterL()")); |
|
98 TRfeCreateInArgs* inArgs = |
|
99 static_cast<TRfeCreateInArgs*>(iOperation->iInArgs); |
|
100 TPtrC kidName(inArgs->iEntry.iName); |
|
101 iExclp = inArgs->iExcl; |
|
102 |
|
103 // used to pass the file open mode |
|
104 // could be something simpler, e.g. only one int |
|
105 iOperation->iFlags = inArgs->iEntry.iAttr.iAtt; |
|
106 |
|
107 // Get the parent to which we are creating this |
|
108 if (!iOperation->Node()) |
|
109 { |
|
110 User::Leave(KErrNotFound); |
|
111 } |
|
112 |
|
113 |
|
114 DEBUGSTRING16(("creating file '%S' in fid %d", |
|
115 &kidName, |
|
116 iOperation->Node()->Fid().iNodeId)); |
|
117 |
|
118 // Do we know about the kid yet? |
|
119 iOperation->iKidFep = iOperation->Node()->FindKidByName(kidName); |
|
120 if (!iOperation->iKidFep) |
|
121 { |
|
122 // This is either a completely new file, or a file that we |
|
123 // have not yet created a file entry for. |
|
124 |
|
125 if (! iOperation->Volumes()->EnsureMetadataCanBeAddedL(iOperation->Node())) |
|
126 { |
|
127 User::Leave(KErrNoMemory); |
|
128 } |
|
129 iOperation->iKidFep = CRsfwFileEntry::NewL(kidName, iOperation->Node()); |
|
130 iOperation->iKidCreated = ETrue; |
|
131 iOperation->iKidFep->SetNewlyCreated(); |
|
132 } |
|
133 |
|
134 if (iOperation->FileEngine()->Disconnected()) |
|
135 { |
|
136 if (iOperation->iKidFep->Type() != KNodeTypeUnknown) |
|
137 { |
|
138 // "file exists" |
|
139 iOperation->HandleRemoteAccessResponse(0, KErrNone); |
|
140 } |
|
141 else |
|
142 { |
|
143 iOperation->HandleRemoteAccessResponse(0, KErrNotFound); |
|
144 } |
|
145 } |
|
146 else |
|
147 { |
|
148 iOperation->FileEngine()->GetAttributesL(*iOperation->iKidFep, |
|
149 iOperation->iDirEntAttr, |
|
150 KNodeTypeFile, |
|
151 iOperation); |
|
152 } |
|
153 } |
|
154 |
|
155 |
|
156 // ---------------------------------------------------------------------------- |
|
157 // CRsfwCreateFileStateMachine::TCheckIfExistsState::CompleteL |
|
158 // ---------------------------------------------------------------------------- |
|
159 // |
|
160 CRsfwCreateFileStateMachine::TState* |
|
161 CRsfwCreateFileStateMachine::TCheckIfExistsState::CompleteL() |
|
162 { |
|
163 DEBUGSTRING(("CRsfwCreateFileStateMachine::TCheckIfExistsState::CompleteL()")); |
|
164 if (iExclp) |
|
165 { |
|
166 DEBUGSTRING(("kid exists!")); |
|
167 return iOperation->CompleteRequestL(KErrAlreadyExists); |
|
168 } |
|
169 else |
|
170 { // file with the same name exists, but exclusive is false |
|
171 return new CRsfwCreateFileStateMachine::TCreateNodeState(iOperation); |
|
172 } |
|
173 } |
|
174 |
|
175 // ---------------------------------------------------------------------------- |
|
176 // CRsfwCreateFileStateMachine::TCheckIfExistsState::ErrorL |
|
177 // ---------------------------------------------------------------------------- |
|
178 // |
|
179 CRsfwCreateFileStateMachine::TState* |
|
180 CRsfwCreateFileStateMachine::TCheckIfExistsState::ErrorL(TInt aCode) |
|
181 { |
|
182 DEBUGSTRING16(("CRsfwCreateFileStateMachine::TCheckIfExistsState::ErrorL error=%d", aCode)); |
|
183 return new CRsfwCreateFileStateMachine::TCreateNodeState(iOperation); |
|
184 } |
|
185 |
|
186 // create node |
|
187 |
|
188 // ---------------------------------------------------------------------------- |
|
189 // CRsfwCreateFileStateMachine::TCreateNodeState::TCreateNodeState |
|
190 // ---------------------------------------------------------------------------- |
|
191 // |
|
192 CRsfwCreateFileStateMachine:: |
|
193 TCreateNodeState::TCreateNodeState(CRsfwCreateFileStateMachine* aParent) |
|
194 : iOperation(aParent) |
|
195 { |
|
196 } |
|
197 |
|
198 // ---------------------------------------------------------------------------- |
|
199 // CRsfwCreateFileStateMachine::TCreateNodeState::EnterL |
|
200 // ---------------------------------------------------------------------------- |
|
201 // |
|
202 void CRsfwCreateFileStateMachine::TCreateNodeState::EnterL() |
|
203 { |
|
204 DEBUGSTRING(("CRsfwCreateFileStateMachine::TCreateNodeState::EnterL()")); |
|
205 if (iOperation->iKidCreated) |
|
206 { |
|
207 iOperation->iKidFep->SetType(KNodeTypeFile); |
|
208 } |
|
209 |
|
210 if (!iOperation->FileEngine()->WriteDisconnected()) |
|
211 { |
|
212 // Create the file |
|
213 HBufC16* kidPath = |
|
214 iOperation->FileEngine()->FullNameLC(*iOperation->iKidFep); |
|
215 // iDirEntAttr exists, we know we are overwriting |
|
216 // pass this info to the access module (needed e.g. by UPnP) |
|
217 iOperation-> |
|
218 FileEngine()-> |
|
219 RemoteAccessL()->CreateFileL(*kidPath, |
|
220 (iOperation->iDirEntAttr != NULL), |
|
221 iOperation); |
|
222 CleanupStack::PopAndDestroy(kidPath); |
|
223 } |
|
224 } |
|
225 |
|
226 // ---------------------------------------------------------------------------- |
|
227 // CRsfwCreateFileStateMachine::TCreateNodeState::CompleteL |
|
228 // ---------------------------------------------------------------------------- |
|
229 // |
|
230 CRsfwCreateFileStateMachine::TState* |
|
231 CRsfwCreateFileStateMachine::TCreateNodeState::CompleteL() |
|
232 { |
|
233 DEBUGSTRING(("CRsfwCreateFileStateMachine::TCreateNodeState::CompleteL()")); |
|
234 return new CRsfwCreateFileStateMachine::TAcquireLockState(iOperation); |
|
235 } |
|
236 |
|
237 // ---------------------------------------------------------------------------- |
|
238 // CRsfwCreateFileStateMachine::TCreateNodeState::ErrorL |
|
239 // ---------------------------------------------------------------------------- |
|
240 // |
|
241 CRsfwCreateFileStateMachine::TState* |
|
242 CRsfwCreateFileStateMachine::TCreateNodeState::ErrorL(TInt aCode) |
|
243 { |
|
244 DEBUGSTRING16(("CRsfwCreateFileStateMachine::TCreateNodeState::ErrorL error=%d", aCode)); |
|
245 DEBUGSTRING(("remote create failed!")); |
|
246 return iOperation->CompleteRequestL(aCode); |
|
247 } |
|
248 |
|
249 // Acquire lock |
|
250 |
|
251 // ---------------------------------------------------------------------------- |
|
252 // CRsfwCreateFileStateMachine::TAcquireLockState::TAcquireLockState |
|
253 // ---------------------------------------------------------------------------- |
|
254 // |
|
255 CRsfwCreateFileStateMachine:: |
|
256 TAcquireLockState::TAcquireLockState(CRsfwCreateFileStateMachine* aParent) |
|
257 { |
|
258 iOperation = aParent; |
|
259 iRequestedLock = EFalse; |
|
260 } |
|
261 |
|
262 // ---------------------------------------------------------------------------- |
|
263 // CRsfwCreateFileStateMachine::TAcquireLockState::EnterL |
|
264 // ---------------------------------------------------------------------------- |
|
265 // |
|
266 void CRsfwCreateFileStateMachine::TAcquireLockState::EnterL() |
|
267 { |
|
268 DEBUGSTRING(("CRsfwCreateFileStateMachine::TAcquireLockState::EnterL()")); |
|
269 if (!iOperation->FileEngine()->WriteDisconnected()) |
|
270 { |
|
271 // There are two state machines currently, |
|
272 // which may take a lock for a file based on the mode, |
|
273 // OpenByPath and this. |
|
274 // Currently the mode check is different which is not a good |
|
275 // thing, there is a clear risk of an error where they |
|
276 // acquire a lock in different situations. |
|
277 if (!iOperation->iKidFep->IsLocked() |
|
278 && iOperation->iFlags != KEntryAttReadOnly) |
|
279 { |
|
280 iOperation->FileEngine()->LockManager()-> |
|
281 ObtainLockL(iOperation->iKidFep, |
|
282 EFileWrite, |
|
283 iOperation->iLockToken, |
|
284 iOperation); |
|
285 iRequestedLock = ETrue; |
|
286 } |
|
287 else |
|
288 { |
|
289 iOperation->HandleRemoteAccessResponse(0, KErrNone); |
|
290 } |
|
291 } |
|
292 else |
|
293 { |
|
294 iOperation->HandleRemoteAccessResponse(0, KErrNone); |
|
295 } |
|
296 } |
|
297 |
|
298 // ---------------------------------------------------------------------------- |
|
299 // CRsfwCreateFileStateMachine::TAcquireLockState::CompleteL |
|
300 // ---------------------------------------------------------------------------- |
|
301 // |
|
302 CRsfwCreateFileStateMachine::TState* |
|
303 CRsfwCreateFileStateMachine::TAcquireLockState::CompleteL() |
|
304 { |
|
305 DEBUGSTRING(("CRsfwCreateFileStateMachine::TAcquireLockState::CompleteL()")); |
|
306 if (iRequestedLock) |
|
307 { |
|
308 iOperation->iKidFep-> |
|
309 SetLockedL(iOperation->FileEngine()->LockManager(), |
|
310 iOperation->iLockToken); |
|
311 iOperation->iLockToken = NULL; |
|
312 } |
|
313 |
|
314 // Note that the kid has to be attached to the file table |
|
315 // to get a NodeId before the cache file is created. |
|
316 if (iOperation->iKidCreated) |
|
317 { |
|
318 // Attach a new kid to its parent |
|
319 iOperation->FileEngine()->iFileTable->AddL(iOperation->iKidFep); |
|
320 iOperation->Node()->AddKid(*iOperation->iKidFep); |
|
321 } |
|
322 |
|
323 // Create an empty container file locally |
|
324 iOperation->FileEngine()->CreateContainerFileL(*iOperation->iKidFep); |
|
325 |
|
326 iOperation->iKidFep->SetSize(0); |
|
327 iOperation->iKidFep->SetCachedSize(0); |
|
328 iOperation->iKidFep->SetCached(ETrue); |
|
329 iOperation->iKidFep->SetAttribValidationTime(); |
|
330 |
|
331 iOperation->FileEngine()->SetupAttributes(*iOperation->iKidFep); |
|
332 |
|
333 iOperation->Node()->SetLocallyDirty(); |
|
334 |
|
335 return iOperation->CompleteRequestL(KErrNone); |
|
336 } |
|
337 |
|
338 // ---------------------------------------------------------------------------- |
|
339 // CRsfwCreateFileStateMachine::TAcquireLockState::ErrorL |
|
340 // ---------------------------------------------------------------------------- |
|
341 // |
|
342 CRsfwCreateFileStateMachine::TState* |
|
343 CRsfwCreateFileStateMachine::TAcquireLockState::ErrorL(TInt aCode) |
|
344 { |
|
345 DEBUGSTRING16(("CRsfwCreateFileStateMachine::TAcquireLockState::ErrorL error=%d", aCode)); |
|
346 if (aCode == KErrNotSupported) |
|
347 { |
|
348 iRequestedLock = EFalse; |
|
349 return this->CompleteL(); |
|
350 } |
|
351 else |
|
352 { |
|
353 return iOperation->CompleteRequestL(aCode); |
|
354 } |
|
355 } |
|
356 |
|
357 |
|
358 |
|