|
1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 |
|
17 #include <e32std.h> |
|
18 |
|
19 #include "MSVSTD.H" |
|
20 #include "MSVSTORE.H" |
|
21 #include "MSVIDS.H" |
|
22 |
|
23 #include "MSVENTRY.H" |
|
24 #include "MSVSERV.H" |
|
25 #include "MSVMOVE.H" |
|
26 #include "MSVDELET.H" |
|
27 #include "MSVCOPY.H" |
|
28 |
|
29 #include "MSVPANIC.H" |
|
30 #include "MSVUTILS.H" |
|
31 #include "msvindexadapter.h" |
|
32 const TInt KMsvServerEntryStandardBufLength=64; |
|
33 |
|
34 //********************************** |
|
35 // CMsvServerEntry |
|
36 //********************************** |
|
37 |
|
38 // static |
|
39 /** |
|
40 @internalComponent |
|
41 */ |
|
42 EXPORT_C CMsvServerEntry* CMsvServerEntry::NewL(CMsvServer& aServer, TMsvId aId) |
|
43 // |
|
44 // |
|
45 // |
|
46 { |
|
47 CMsvServerEntry* self = new(ELeave) CMsvServerEntry(aServer); |
|
48 CleanupStack::PushL(self); |
|
49 self->ConstructL(aId); |
|
50 CleanupStack::Pop(); |
|
51 return self; |
|
52 } |
|
53 |
|
54 CMsvServerEntry::CMsvServerEntry(CMsvServer& aServer) |
|
55 : CActive(EPriorityStandard), iLockedStore(EFalse), iServer(aServer) |
|
56 // |
|
57 // |
|
58 // |
|
59 { |
|
60 __DECLARE_NAME(_S("CMsvServerEntry")); |
|
61 } |
|
62 |
|
63 void CMsvServerEntry::ConstructL(TMsvId aId) |
|
64 // |
|
65 // |
|
66 // |
|
67 { |
|
68 iDescription = HBufC::NewL(KMsvServerEntryStandardBufLength); |
|
69 iDetails = HBufC::NewL(KMsvServerEntryStandardBufLength); |
|
70 User::LeaveIfError(SetEntry(aId)); |
|
71 |
|
72 CActiveScheduler::Add(this); |
|
73 } |
|
74 |
|
75 |
|
76 CMsvServerEntry::~CMsvServerEntry() |
|
77 // |
|
78 // |
|
79 // |
|
80 /** Frees resources for the object. It: |
|
81 |
|
82 1. releases the lock on the entry |
|
83 |
|
84 2. releases the lock on the associated message store if has been opened with |
|
85 EditStoreL() |
|
86 |
|
87 3. cancels any outstanding asynchronous MoveEntryL() move operation */ |
|
88 { |
|
89 __ASSERT_DEBUG(iStore==NULL, PanicServer(EMsvStoreLeftOpenOnDestruction)); |
|
90 |
|
91 if (iEntry.Id() != KMsvNullIndexEntryId) |
|
92 { |
|
93 iServer.IndexAdapter().ReleaseEntry(iEntry.Id()); // ignore any error |
|
94 } |
|
95 |
|
96 if (iLockedStore) |
|
97 { |
|
98 iServer.IndexAdapter().ReleaseStore(iEntry.Id()); // ignore any error |
|
99 } |
|
100 |
|
101 delete iDescription; |
|
102 delete iDetails; |
|
103 |
|
104 Cancel(); |
|
105 } |
|
106 |
|
107 |
|
108 |
|
109 EXPORT_C TInt CMsvServerEntry::SetEntry(TMsvId aId) |
|
110 // |
|
111 // Changes the entry used as the context |
|
112 // |
|
113 /** Changes the context of the specified entry. |
|
114 |
|
115 The call locks the entry, preventing it from being accessed by other clients. |
|
116 The lock is released when the object is deleted or the context is changed. |
|
117 |
|
118 Note that you can change the context to KMsvNullIndexEntryId to unlock an |
|
119 entry without locking another. |
|
120 |
|
121 @param aId ID of the entry to access |
|
122 @return KErrNone if successful, KErrNotFound if the entry does not exist, or |
|
123 KErrLocked if the entry is locked. */ |
|
124 { |
|
125 __ASSERT_ALWAYS(iStore==NULL, PanicServer(EMsvEntryStoreLeftOpen)); |
|
126 __ASSERT_ALWAYS(iEntryState==EMsvIdle, PanicServer(EMsvServerEntryNotIdle)); |
|
127 |
|
128 // changing to itself |
|
129 if (iEntry.Id()==aId) |
|
130 return KErrNone; |
|
131 |
|
132 if (aId == KMsvNullIndexEntryId) |
|
133 { |
|
134 // setting the context to NULL |
|
135 iServer.IndexAdapter().ReleaseEntry(iEntry.Id()); // error ignored |
|
136 *iDescription = TPtrC(); |
|
137 *iDetails = TPtrC(); |
|
138 iEntry = TMsvEntry(); |
|
139 return KErrNone; |
|
140 } |
|
141 |
|
142 // lock the new entry |
|
143 TInt error = KErrNone; |
|
144 error = iServer.IndexAdapter().LockEntry(aId); |
|
145 if (error) |
|
146 return error; |
|
147 |
|
148 // get the new entry |
|
149 TMsvEntry* entryPtr; |
|
150 error = iServer.IndexAdapter().GetEntry(aId, entryPtr, iContextOwnerId); |
|
151 if (error==KErrNone) |
|
152 { |
|
153 // check we can copy the strings |
|
154 error = IncreaseBufferSizes(entryPtr->iDescription.Length(), entryPtr->iDetails.Length()); |
|
155 |
|
156 if (error==KErrNone) |
|
157 { |
|
158 // release old entry |
|
159 if (iEntry.Id()!=KMsvNullIndexEntryId) |
|
160 { |
|
161 iServer.IndexAdapter().ReleaseEntry(iEntry.Id()); // error ignored |
|
162 } |
|
163 |
|
164 |
|
165 // switch the context of this object |
|
166 *iDescription = entryPtr->iDescription; |
|
167 *iDetails = entryPtr->iDetails; |
|
168 iEntry = *entryPtr; |
|
169 iEntry.iDescription.Set(*iDescription); |
|
170 iEntry.iDetails.Set(*iDetails); |
|
171 } |
|
172 } |
|
173 |
|
174 // release the lock on the new entry |
|
175 if (error) |
|
176 { |
|
177 iServer.IndexAdapter().ReleaseEntry(aId); // error ignored |
|
178 } |
|
179 |
|
180 |
|
181 return error; |
|
182 } |
|
183 |
|
184 |
|
185 |
|
186 TInt CMsvServerEntry::IncreaseBufferSizes(TInt aNewDescriptionSize, TInt aNewDetailsSize) |
|
187 // |
|
188 // Increase the size of the buffers if needed. The current contents of the buffers is maintained |
|
189 // |
|
190 { |
|
191 if (aNewDescriptionSize > iDescription->Des().MaxLength()) |
|
192 { |
|
193 HBufC* newBuf = iDescription->ReAlloc(aNewDescriptionSize); |
|
194 if (newBuf==NULL) |
|
195 return KErrNoMemory; |
|
196 iDescription=newBuf; |
|
197 } |
|
198 |
|
199 if (aNewDetailsSize > iDetails->Des().MaxLength()) |
|
200 { |
|
201 HBufC* newBuf = iDetails->ReAlloc(aNewDetailsSize); |
|
202 if (newBuf==NULL) |
|
203 return KErrNoMemory; |
|
204 iDetails=newBuf; |
|
205 } |
|
206 return KErrNone; |
|
207 } |
|
208 |
|
209 /** |
|
210 Sets the context's index entry to the specified values. |
|
211 |
|
212 @param aEntry |
|
213 The new details for the entry. |
|
214 |
|
215 @return |
|
216 KErrNone - success; KErrAccessDenied - the entry is read only (deleted |
|
217 entry, standard folder, or locked); KErrNotSupported - aEntry is invalid or the |
|
218 ID specified in aEntry is not the same as the context ID or no context has been |
|
219 set for the object; KErrNoMemory - a memory allocation failed. |
|
220 */ |
|
221 EXPORT_C TInt CMsvServerEntry::ChangeEntry(const TMsvEntry& aEntry) |
|
222 { |
|
223 return DoChangeEntry(aEntry, KMsvServerId, EFalse, EFalse); |
|
224 } |
|
225 |
|
226 /** |
|
227 Sets the context's index entry to the specified values and updates the owner of |
|
228 the entry to that specified by the supplied ID. |
|
229 |
|
230 @param aEntry |
|
231 The new details for the entry. |
|
232 |
|
233 @param aOwnerId |
|
234 The ID of the process that should own the entry. |
|
235 |
|
236 @return |
|
237 KErrNone - success; KErrAccessDenied - the entry is read only (deleted |
|
238 entry, standard folder, or locked); KErrNotSupported - aEntry is invalid or the |
|
239 ID specified in aEntry is not the same as the context ID or no context has been |
|
240 set for the object; KErrNoMemory - a memory allocation failed. |
|
241 */ |
|
242 EXPORT_C TInt CMsvServerEntry::ChangeEntry(const TMsvEntry& aEntry, TSecureId aOwnerId) |
|
243 { |
|
244 return DoChangeEntry(aEntry, aOwnerId, ETrue, EFalse); |
|
245 } |
|
246 /** |
|
247 Sets the context's index entry to the specified values and updates the owner of |
|
248 the entry to that specified by the supplied ID. It does this as part of a bulk |
|
249 operation, so the changes are not immediately committed to file. |
|
250 |
|
251 @param aEntry |
|
252 The new details for the entry. |
|
253 |
|
254 @param aOwnerId |
|
255 The ID of the process that should own the entry. Only commits changes to |
|
256 file at specified bulk commit interval. |
|
257 |
|
258 @return |
|
259 KErrNone - success; KErrAccessDenied - the entry is read only (deleted |
|
260 entry, standard folder, or locked); KErrNotSupported - aEntry is invalid or the |
|
261 ID specified in aEntry is not the same as the context ID or no context has been |
|
262 set for the object; KErrNoMemory - a memory allocation failed. |
|
263 */ |
|
264 EXPORT_C TInt CMsvServerEntry::ChangeEntryBulk(const TMsvEntry& aEntry, TSecureId aOwnerId) |
|
265 { |
|
266 return DoChangeEntry(aEntry, aOwnerId, ETrue, ETrue); |
|
267 } |
|
268 |
|
269 /** |
|
270 Sets the context's index entry to the specified values and updates the owner of |
|
271 the entry to that specified by the supplied ID. It does this as part of a bulk |
|
272 operation, so the changes are not immediately committed to file. |
|
273 |
|
274 @param aEntry |
|
275 The new details for the entry. |
|
276 |
|
277 @return |
|
278 KErrNone - success; KErrAccessDenied - the entry is read only (deleted |
|
279 entry, standard folder, or locked); KErrNotSupported - aEntry is invalid or the |
|
280 ID specified in aEntry is not the same as the context ID or no context has been |
|
281 set for the object; KErrNoMemory - a memory allocation failed. |
|
282 */ |
|
283 EXPORT_C TInt CMsvServerEntry::ChangeEntryBulk(const TMsvEntry& aEntry) |
|
284 { |
|
285 return DoChangeEntry(aEntry, KMsvServerId, EFalse, ETrue); |
|
286 } |
|
287 |
|
288 |
|
289 TInt CMsvServerEntry::DoChangeEntry(const TMsvEntry& aEntry, TSecureId aOwnerId, TBool aForcedUpdate, TBool aBulk) |
|
290 { |
|
291 __ASSERT_DEBUG(iEntry.Id()!=KMsvNullIndexEntryId, PanicServer(EMsvEntryWithNoContext1)); |
|
292 __ASSERT_DEBUG(aEntry.Id()==iEntry.Id(), PanicServer(EMsvNotChangingCurrentContext)); |
|
293 __ASSERT_DEBUG(MsvUtils::ValidEntry(aEntry), PanicServer(EMsvBadEntryContents)); |
|
294 __ASSERT_DEBUG(!iEntry.Deleted(), PanicServer(EMsvChangingDeletedEntry)); |
|
295 |
|
296 // can only change the context, and must be valid |
|
297 if (iEntry.Id()==KMsvNullIndexEntryId || aEntry.Id()!=iEntry.Id() || !MsvUtils::ValidEntry(aEntry)) |
|
298 return KErrNotSupported; |
|
299 |
|
300 if (iEntry.Deleted() || iEntry.StandardFolder()) |
|
301 return KErrAccessDenied; |
|
302 |
|
303 TInt error; |
|
304 |
|
305 TBool permanentDataUnchanged = iEntry.PermanentDataUnchanged(aEntry); |
|
306 if( permanentDataUnchanged && aForcedUpdate ) |
|
307 { |
|
308 // Check to see if the owner ID is being updated - if so then need to |
|
309 // update the permanent data. |
|
310 permanentDataUnchanged = (iContextOwnerId == aOwnerId); |
|
311 } |
|
312 |
|
313 if( permanentDataUnchanged ) |
|
314 { |
|
315 error = iServer.IndexAdapter().ChangeTemporaryData(aEntry); |
|
316 if (error==KErrNone) |
|
317 iEntry.iData = aEntry.iData; |
|
318 } |
|
319 else |
|
320 { |
|
321 error = IncreaseBufferSizes(aEntry.iDescription.Length(), aEntry.iDetails.Length()); |
|
322 |
|
323 if (error==KErrNone) |
|
324 { |
|
325 TMsvEntry entry = aEntry; |
|
326 |
|
327 // check the hidden flags are correct |
|
328 entry.SetOwner(iEntry.Owner()); |
|
329 entry.SetDeleted(iEntry.Deleted()); |
|
330 error = iServer.ChangeEntry(entry, aOwnerId, aForcedUpdate, aBulk); |
|
331 if (error==KErrNone) |
|
332 { |
|
333 // switch the context of this object |
|
334 *iDescription = entry.iDescription; |
|
335 *iDetails = entry.iDetails; |
|
336 iEntry = entry; |
|
337 iEntry.iDescription.Set(*iDescription); |
|
338 iEntry.iDetails.Set(*iDetails); |
|
339 } |
|
340 } |
|
341 } |
|
342 |
|
343 // notify everyone of the change unless this is a bulk change. |
|
344 // for bulk changes (e.g. email synchronize, all notifications get handled elsewhere |
|
345 if ((error == KErrNone) && (!aBulk)) |
|
346 { |
|
347 iServer.NotifyChanged(EMsvEntriesChanged, iEntry.Id(), iEntry.Parent()); |
|
348 } |
|
349 |
|
350 return error; |
|
351 } |
|
352 |
|
353 /** |
|
354 Creates a new entry as a child of the current context. |
|
355 |
|
356 The parent ID and entry ID are set by the Message Server. |
|
357 |
|
358 @param aEntry |
|
359 Index entry value for the new entry |
|
360 |
|
361 @return |
|
362 KErrNone - success; KErrNoMemory - a memory allocation failed; |
|
363 KErrNotSupported - aEntry is invalid |
|
364 */ |
|
365 EXPORT_C TInt CMsvServerEntry::CreateEntry(TMsvEntry& aEntry) |
|
366 { |
|
367 return CreateEntry(aEntry, KMsvServerId); |
|
368 } |
|
369 |
|
370 /** |
|
371 Creates a new entry as a child of the current context. |
|
372 |
|
373 Ownership of the created entry is given to the process with the specified SID. |
|
374 |
|
375 The parent ID and entry ID are set by the Message Server. |
|
376 |
|
377 @param aEntry |
|
378 Index entry value for the new entry |
|
379 |
|
380 @param aOwnerId |
|
381 The SID of the process that will own the create entry. |
|
382 |
|
383 @return |
|
384 KErrNone - success; KErrNoMemory - a memory allocation failed; |
|
385 KErrNotSupported - aEntry is invalid |
|
386 */ |
|
387 EXPORT_C TInt CMsvServerEntry::CreateEntry(TMsvEntry& aEntry, TSecureId aOwnerId) |
|
388 { |
|
389 return CreateEntry(aEntry, aOwnerId, EFalse); |
|
390 } |
|
391 |
|
392 /** |
|
393 Creates a new entry as a child of the current context as part of a |
|
394 bulk creation operation. The entry will not be committed to file immediately. |
|
395 |
|
396 The parent ID and entry ID are set by the Message Server. |
|
397 |
|
398 @param aEntry |
|
399 Index entry value for the new entry |
|
400 |
|
401 @param aOwnerId |
|
402 The SID of the process that will own the create entry. |
|
403 |
|
404 @return |
|
405 KErrNone - success; KErrNoMemory - a memory allocation failed; |
|
406 KErrNotSupported - aEntry is invalid |
|
407 */ |
|
408 EXPORT_C TInt CMsvServerEntry::CreateEntryBulk(TMsvEntry& aEntry, TSecureId aOwnerId) |
|
409 { |
|
410 return CreateEntry(aEntry, aOwnerId, ETrue); |
|
411 } |
|
412 /** |
|
413 Creates a new entry as a child of the current context as part of a |
|
414 bulk creation operation |
|
415 |
|
416 The parent ID and entry ID are set by the Message Server. |
|
417 |
|
418 @param aEntry |
|
419 Index entry value for the new entry |
|
420 |
|
421 @return |
|
422 KErrNone - success; KErrNoMemory - a memory allocation failed; |
|
423 KErrNotSupported - aEntry is invalid |
|
424 */ |
|
425 EXPORT_C TInt CMsvServerEntry::CreateEntryBulk(TMsvEntry& aEntry) |
|
426 { |
|
427 return CreateEntry(aEntry, KMsvServerId, ETrue); |
|
428 } |
|
429 |
|
430 |
|
431 |
|
432 /** |
|
433 Creates a new entry as a child of the current context. |
|
434 |
|
435 Ownership of the created entry is given to the process with the specified SID. |
|
436 |
|
437 The parent ID and entry ID are set by the Message Server. |
|
438 |
|
439 @param aEntry |
|
440 Index entry value for the new entry |
|
441 |
|
442 @param aOwnerId |
|
443 The SID of the process that will own the create entry. |
|
444 |
|
445 @param aBulk |
|
446 A boolean value to indicate whether this is part of a bulk operation. (ETrue = bulk) |
|
447 |
|
448 @return |
|
449 KErrNone - success; KErrNoMemory - a memory allocation failed; |
|
450 KErrNotSupported - aEntry is invalid |
|
451 */ |
|
452 EXPORT_C TInt CMsvServerEntry::CreateEntry(TMsvEntry& aEntry, TSecureId aOwnerId, TBool aBulk) |
|
453 { |
|
454 __ASSERT_DEBUG(iEntry.Id()!=KMsvNullIndexEntryId, PanicServer(EMsvEntryWithNoContext2)); |
|
455 aEntry.SetParent(iEntry.Id()); |
|
456 __ASSERT_DEBUG(MsvUtils::ValidEntry(aEntry, ETrue), PanicServer(EMsvBadEntryContents)); |
|
457 |
|
458 // if valid - try to create the new child |
|
459 TInt error; |
|
460 if (iEntry.Id()==KMsvNullIndexEntryId || !MsvUtils::ValidEntry(aEntry, ETrue)) |
|
461 error = KErrNotSupported; |
|
462 else |
|
463 { |
|
464 error = iServer.AddEntry(aEntry, aOwnerId, ETrue, aBulk); |
|
465 |
|
466 // if the child was created,then notify everyone, otherwise reset the parent |
|
467 if (error) |
|
468 aEntry.SetParent(KMsvNullIndexEntryId); |
|
469 else |
|
470 { |
|
471 if (!aBulk) |
|
472 { |
|
473 iServer.NotifyChanged(EMsvEntriesCreated, aEntry.Id(), aEntry.Parent()); |
|
474 } |
|
475 iEntry.SetOwner(ETrue); |
|
476 } |
|
477 } |
|
478 |
|
479 return error; |
|
480 } |
|
481 |
|
482 EXPORT_C void CMsvServerEntry::CompleteBulk() |
|
483 // |
|
484 /** Completes the current bulk transaction (if any) |
|
485 Requests that the message server commit to the index file on disk |
|
486 any entries which have not been committed and to generate notifications |
|
487 for any entries which require them. |
|
488 @return void */ |
|
489 { |
|
490 iServer.CompleteBulkTransaction(); |
|
491 } |
|
492 |
|
493 |
|
494 |
|
495 TBool CMsvServerEntry::AreChildren(const CMsvEntrySelection& aSelection) const |
|
496 // |
|
497 // Returns true if all the entries are children |
|
498 // |
|
499 { |
|
500 TInt count = aSelection.Count(); |
|
501 while (count--) |
|
502 { |
|
503 if (!IsAChild(aSelection.At(count))) |
|
504 { |
|
505 return EFalse; |
|
506 } |
|
507 } |
|
508 return ETrue; |
|
509 } |
|
510 |
|
511 TBool CMsvServerEntry::IsAChild(TMsvId aId) const |
|
512 // |
|
513 // |
|
514 // |
|
515 { |
|
516 TMsvEntry* entry=NULL; |
|
517 TInt err = KErrNone; |
|
518 err = iServer.IndexAdapter().GetEntry(aId, entry); |
|
519 if (err ==KErrNone && entry->Parent()==iEntry.Id()) |
|
520 return ETrue; |
|
521 return EFalse; |
|
522 } |
|
523 |
|
524 |
|
525 EXPORT_C TInt CMsvServerEntry::DeleteEntry(TMsvId aId) |
|
526 // |
|
527 // Deletes the child of the current context recursively. |
|
528 // |
|
529 /** Deletes a child entry of the context. The delete works recursively through |
|
530 all the descendants. |
|
531 |
|
532 If a child or any descendant is locked by another client, then no entries |
|
533 are deleted. |
|
534 |
|
535 @param aId The ID of the entry to delete |
|
536 @return KErrNone if successful, KErrAccessDenied if the entry or a descendant |
|
537 was locked by another client, KErrInUse if the store or a file associated |
|
538 with the entry is open, or KErrNotFound if the entry is not a child of the |
|
539 context. */ |
|
540 { |
|
541 __ASSERT_DEBUG(iEntry.Id()!=KMsvNullIndexEntryId, PanicServer(EMsvEntryWithNoContext4)); |
|
542 __ASSERT_DEBUG(aId!=iEntry.Id(), PanicServer(EMsvDeletingCurrentContext)); |
|
543 |
|
544 // only delete children |
|
545 if (!IsAChild(aId)) |
|
546 return KErrNotFound; |
|
547 |
|
548 // get the total selection of entries to be deleted |
|
549 CMsvEntrySelection* movedEntries=NULL; |
|
550 CMsvEntrySelection* deletedEntries=NULL; |
|
551 TRAPD(error, DoDeleteEntryL(aId, deletedEntries, movedEntries)); |
|
552 |
|
553 // notify server of the deletions & moves |
|
554 if (deletedEntries && movedEntries && (deletedEntries->Count() || movedEntries->Count())) |
|
555 { |
|
556 if (deletedEntries->Count()) |
|
557 iServer.NotifyChanged(EMsvEntriesDeleted, *deletedEntries, iEntry.Id()); |
|
558 if (movedEntries->Count()) |
|
559 iServer.NotifyChanged(EMsvEntriesMoved, *movedEntries, KMsvDeletedEntryFolderEntryId, iEntry.Id()); |
|
560 |
|
561 // need to remove owner flag if has no children |
|
562 TMsvEntry* pEntry; |
|
563 TInt err = KErrNone; |
|
564 err = iServer.IndexAdapter().GetEntry(iEntry.Id(), pEntry); |
|
565 if (err ==KErrNone) |
|
566 iEntry.SetOwner(pEntry->Owner()); |
|
567 } |
|
568 |
|
569 delete movedEntries; |
|
570 delete deletedEntries; |
|
571 |
|
572 return error; |
|
573 } |
|
574 |
|
575 void CMsvServerEntry::DoDeleteEntryL(TMsvId aId, CMsvEntrySelection*& aDeleted, CMsvEntrySelection*& aMoved) |
|
576 { |
|
577 aDeleted = new(ELeave)CMsvEntrySelection; |
|
578 aMoved = new(ELeave)CMsvEntrySelection; |
|
579 |
|
580 CMsvDelete* del = CMsvDelete::NewL(iServer); |
|
581 CleanupStack::PushL(del); |
|
582 |
|
583 del->StartL(aId, *aDeleted, *aMoved); |
|
584 |
|
585 CleanupStack::PopAndDestroy(); // del |
|
586 } |
|
587 |
|
588 EXPORT_C TInt CMsvServerEntry::DeleteEntries(CMsvEntrySelection& aSelection) |
|
589 // |
|
590 // Deletes the children of the current context in the selection recursively |
|
591 // Returns the children that could not be fully deleted in the selection |
|
592 // |
|
593 /** Deletes a selection of child entries. The delete works recursively through |
|
594 all the descendants. |
|
595 |
|
596 If a child or any descendant is locked by another client, then no entries |
|
597 are deleted. |
|
598 |
|
599 @param aSelection The entries to delete. On return, contains the children |
|
600 that could not be fully deleted |
|
601 @return KErrNone if successful, KErrAccessDenied if the entry or a descendant |
|
602 was locked by another client, KErrInUse if the store or a file associated |
|
603 with the entry is open, or KErrNotFound if the entry is not a child of the |
|
604 context. */ |
|
605 { |
|
606 __ASSERT_DEBUG(iEntry.Id()!=KMsvNullIndexEntryId, PanicServer(EMsvEntryWithNoContext4)); |
|
607 |
|
608 CMsvEntrySelection* deleted = NULL; |
|
609 CMsvEntrySelection* moved = NULL; |
|
610 |
|
611 TRAPD(error, DoDeleteEntriesL(aSelection, deleted, moved)); |
|
612 |
|
613 if (moved && deleted) |
|
614 { |
|
615 // Notify server of the deletions & moves |
|
616 if (deleted->Count()) |
|
617 iServer.NotifyChanged(EMsvEntriesDeleted, *deleted, iEntry.Id()); |
|
618 |
|
619 if (moved->Count()) |
|
620 iServer.NotifyChanged(EMsvEntriesMoved, *moved, KMsvDeletedEntryFolderEntryId, iEntry.Id()); |
|
621 |
|
622 // need to remove owner flag if has no children |
|
623 TMsvEntry* pEntry; |
|
624 TInt err = KErrNone; |
|
625 err = iServer.IndexAdapter().GetEntry(iEntry.Id(), pEntry); |
|
626 if (err ==KErrNone) |
|
627 iEntry.SetOwner(pEntry->Owner()); |
|
628 } |
|
629 |
|
630 delete moved; |
|
631 delete deleted; |
|
632 |
|
633 return error; |
|
634 } |
|
635 |
|
636 void CMsvServerEntry::DoDeleteEntriesL(CMsvEntrySelection& aSelection, CMsvEntrySelection*& aDeleted, CMsvEntrySelection*& aMoved) |
|
637 // |
|
638 // |
|
639 // |
|
640 { |
|
641 __ASSERT_DEBUG(!aDeleted && !aMoved, PanicServer(EMsvDeleteAndMoveSelectionsNotNull)); |
|
642 __ASSERT_DEBUG(aSelection.Count() > 0, PanicServer(EMsvDeletingEmptySelection)); |
|
643 |
|
644 // Total entries deleted and moved |
|
645 aDeleted = new(ELeave)CMsvEntrySelection; |
|
646 aMoved = new(ELeave)CMsvEntrySelection; |
|
647 |
|
648 // Entries deleted when a single item is deleted |
|
649 CMsvEntrySelection* deleted = new(ELeave)CMsvEntrySelection; |
|
650 CleanupStack::PushL(deleted); |
|
651 |
|
652 // Entries moved when a single item is deleted |
|
653 CMsvEntrySelection* moved = new(ELeave)CMsvEntrySelection; |
|
654 CleanupStack::PushL(moved); |
|
655 |
|
656 CMsvEntrySelection* selection = new(ELeave)CMsvEntrySelection; |
|
657 CleanupStack::PushL(selection); |
|
658 |
|
659 CMsvDelete* del = CMsvDelete::NewL(iServer); |
|
660 CleanupStack::PushL(del); |
|
661 |
|
662 TInt firstError = KErrNone; |
|
663 |
|
664 TInt count = aSelection.Count(); |
|
665 while(count--) |
|
666 { |
|
667 TMsvId id = aSelection.At(count); |
|
668 TInt error = KErrNone; |
|
669 |
|
670 // Only delete children |
|
671 if (!IsAChild(id)) |
|
672 error = KErrNotFound; |
|
673 else |
|
674 { |
|
675 // Need to know maximum number of entries that might be deleted |
|
676 selection->AppendL(id); |
|
677 error = iServer.IndexAdapter().ExpandSelectionRecursively(*selection); |
|
678 if (error == KErrNone) |
|
679 { |
|
680 // Reserve space in lists |
|
681 aDeleted->SetReserveL(aDeleted->Count() + selection->Count()); |
|
682 aMoved->SetReserveL(aMoved->Count() + selection->Count()); |
|
683 del->StartL(id, *deleted, *moved); |
|
684 aSelection.Delete(count); |
|
685 |
|
686 if (deleted->Count() > 0) |
|
687 aDeleted->AppendL(deleted->Back(0), deleted->Count()); |
|
688 |
|
689 if (moved->Count() > 0) |
|
690 aMoved->AppendL(moved->Back(0), moved->Count()); |
|
691 } |
|
692 |
|
693 deleted->Reset(); |
|
694 moved->Reset(); |
|
695 selection->Reset(); |
|
696 } |
|
697 |
|
698 // Remember error |
|
699 if (error != KErrNone && firstError == KErrNone) |
|
700 firstError = error; |
|
701 } |
|
702 |
|
703 User::LeaveIfError(firstError); |
|
704 CleanupStack::PopAndDestroy(4); // del, selection, moved, deleted |
|
705 } |
|
706 |
|
707 /** Gets the index entry for a specified entry ID. |
|
708 |
|
709 @param aId ID of the entry to get |
|
710 @param aEntry On return, a pointer to the index entry with ID aId |
|
711 @return KErrNone on success; KErrNotFound if the no entry exists with the specified ID |
|
712 */ |
|
713 EXPORT_C TInt CMsvServerEntry::GetEntryFromId(TMsvId aId,TMsvEntry*& aEntry) |
|
714 // |
|
715 // sets aEntry to the TMsvEntry according to the TMsvId, returns error code |
|
716 // |
|
717 { |
|
718 return iServer.IndexAdapter().GetEntry(aId, aEntry); |
|
719 } |
|
720 |
|
721 |
|
722 EXPORT_C CMsvStore* CMsvServerEntry::ReadStoreL() |
|
723 // |
|
724 // Returns the message store for the current context with read access only |
|
725 // |
|
726 /** Obtains the message store for the current context with read-only access. |
|
727 |
|
728 Multiple clients can read from a store simultaneously. If another client is already |
|
729 writing to the store, the function leaves with KErrAccessDenied. |
|
730 |
|
731 The returned CMsvStore must be deleted when it is no longer required. |
|
732 |
|
733 @leave KErrAccessDenied Store is locked by another process |
|
734 @leave KErrNoMemory Not enough memory to open store |
|
735 @leave KErrNotFound There is no store associated with this entry |
|
736 @return Context's message store open for read-only access */ |
|
737 { |
|
738 // Leave if the message store is not currently available |
|
739 User::LeaveIfError(iServer.IndexAdapter().ErrorState()); |
|
740 __ASSERT_ALWAYS(iStore==NULL, PanicServer(EMsvStoreAlreadyOpen2)); |
|
741 __ASSERT_DEBUG(iEntry.Id()!=KMsvNullIndexEntryId, PanicServer(EMsvEntryWithNoContext6)); |
|
742 |
|
743 // must have a context |
|
744 if (iEntry.Id()==KMsvNullIndexEntryId) |
|
745 User::Leave(KErrNotSupported); |
|
746 |
|
747 TBool locked; |
|
748 User::LeaveIfError(iServer.IndexAdapter().IsStoreLocked(iEntry.Id(), locked)); |
|
749 if (locked) |
|
750 User::Leave(KErrAccessDenied); |
|
751 |
|
752 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB) // open the store |
|
753 { |
|
754 iStore = CMsvStore::OpenForReadL(*this, iServer.FileSession(), iServer.ServerStoreManager(), iEntry.Id(), iEntry.iMtm); |
|
755 } |
|
756 #else |
|
757 iStore = CMsvStore::OpenForReadL(*this, iServer.FileSession(), iServer.ServerStoreManager(), iEntry.Id()); |
|
758 #endif |
|
759 // error ignored as the entry exists, we know this because IsStoreLocked would have returned and error otherwise |
|
760 iServer.IndexAdapter().IncStoreReaderCount(iEntry.Id()); |
|
761 return iStore; |
|
762 } |
|
763 |
|
764 |
|
765 EXPORT_C CMsvStore* CMsvServerEntry::EditStoreL() |
|
766 // |
|
767 // Returns the message store for the current context with write access |
|
768 // |
|
769 /** Obtains the message store for the current context with read-write access. |
|
770 |
|
771 Only one client can edit a message store at one time. If another client is |
|
772 already writing to the store, KErrAccessDenied is returned. However, any number |
|
773 of clients can read from the store simultaneously. |
|
774 |
|
775 If the message store does not exist when EditStore() is called, a new message |
|
776 store is created. |
|
777 |
|
778 The returned CMsvStore must be deleted when it is no longer required. |
|
779 |
|
780 @leave KErrAccessDenied Store is locked by another process or is read-only |
|
781 @leave KErrNoMemory Not enough memory to open store |
|
782 @return Context's message store open for read-write access */ |
|
783 { |
|
784 __ASSERT_ALWAYS(iStore==NULL, PanicServer(EMsvStoreAlreadyOpen1)); |
|
785 __ASSERT_DEBUG(iEntry.Id()!=KMsvNullIndexEntryId, PanicServer(EMsvEntryWithNoContext7)); |
|
786 |
|
787 // Leave if the message store is not currently available |
|
788 User::LeaveIfError(iServer.IndexAdapter().ErrorState()); |
|
789 // must have a context |
|
790 if (iEntry.Id()==KMsvNullIndexEntryId) |
|
791 User::Leave(KErrNotSupported); |
|
792 |
|
793 if (iEntry.ReadOnly()) |
|
794 User::Leave(KErrAccessDenied); |
|
795 User::LeaveIfError(iServer.IndexAdapter().LockStore(iEntry.Id())); |
|
796 // open the store |
|
797 TInt error = 0; |
|
798 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB) |
|
799 { |
|
800 TRAP(error, iStore = CMsvStore::OpenForWriteL(*this, iServer.FileSession(), iServer.ServerStoreManager(), iEntry.Id(), iEntry.iMtm)); |
|
801 } |
|
802 #else |
|
803 TRAP(error, iStore = CMsvStore::OpenForWriteL(*this, iServer.FileSession(), iServer.ServerStoreManager(), iEntry.Id())); |
|
804 #endif |
|
805 if (error) |
|
806 { |
|
807 iServer.IndexAdapter().ReleaseStore(iEntry.Id()); |
|
808 User::Leave(error); |
|
809 } |
|
810 |
|
811 return iStore; |
|
812 } |
|
813 |
|
814 |
|
815 |
|
816 void CMsvServerEntry::HandleStoreEvent(TMsvStoreEvent aEvent, TMsvId aId) |
|
817 // |
|
818 // |
|
819 // |
|
820 { |
|
821 __ASSERT_DEBUG(aId==iEntry.Id(), PanicServer(EMsvUnknownStoreId)); |
|
822 |
|
823 switch (aEvent) |
|
824 { |
|
825 case EMsvEditStoreClosed: |
|
826 iServer.IndexAdapter().ReleaseStore(aId); // error ignored |
|
827 iStore=NULL; |
|
828 break; |
|
829 case EMsvReadStoreClosed: |
|
830 iServer.IndexAdapter().DecStoreReaderCount(aId); // error ignored |
|
831 iStore=NULL; |
|
832 break; |
|
833 default: |
|
834 __ASSERT_DEBUG(EFalse, PanicServer(EMsvUnknownStoreEvent2)); |
|
835 } |
|
836 } |
|
837 |
|
838 EXPORT_C TInt CMsvServerEntry::GetChildren(CMsvEntrySelection& aSelection) |
|
839 // |
|
840 // Returns a the selection of the children of the current context |
|
841 // |
|
842 /** Gets a selection containing the IDs of all the context children. |
|
843 |
|
844 If the entry has no children, the selection is empty. |
|
845 |
|
846 @param aSelection Initially, this must be an empty selection. On return, it |
|
847 lists the children. |
|
848 @return KErrNone - success; |
|
849 KErrMemory - a memory allocation failed */ |
|
850 { |
|
851 return DoGetChildren(KMsvNullIndexEntryId, KNullUid, KNullUid, aSelection); |
|
852 } |
|
853 |
|
854 EXPORT_C TInt CMsvServerEntry::GetChildrenWithService(TMsvId aServiceId, CMsvEntrySelection& aSelection) |
|
855 // |
|
856 // Returns a the selection of the children of the current context with the given service |
|
857 // |
|
858 /** Gets a selection containing the IDs of all the context children with the specified |
|
859 service. |
|
860 |
|
861 If the entry has no children, the selection is empty. |
|
862 |
|
863 @param aServiceId Service by which to filter children |
|
864 @param aSelection Initially, this must be an empty selection. On return, it |
|
865 lists the children. |
|
866 @return KErrNone - success; |
|
867 KErrMemory - a memory allocation failed */ |
|
868 { |
|
869 return DoGetChildren(aServiceId, KNullUid, KNullUid, aSelection); |
|
870 } |
|
871 |
|
872 EXPORT_C TInt CMsvServerEntry::GetChildrenWithMtm(TUid aMtm, CMsvEntrySelection& aSelection) |
|
873 // |
|
874 // Returns a the selection of the children of the current context with the given Mtm |
|
875 // |
|
876 /** Gets a selection containing the IDs of all the context children with the specified |
|
877 MTM. |
|
878 |
|
879 If the entry has no children, the selection is empty. |
|
880 |
|
881 @param aMtm MTM by which to filter children |
|
882 @param aSelection Initially, this must be an empty selection. On return, it |
|
883 lists the children. |
|
884 @return KErrNone - success; |
|
885 KErrMemory - a memory allocation failed */ |
|
886 { |
|
887 return DoGetChildren(KMsvNullIndexEntryId, aMtm, KNullUid, aSelection); |
|
888 } |
|
889 |
|
890 EXPORT_C TInt CMsvServerEntry::GetChildrenWithType(TUid aType, CMsvEntrySelection& aSelection) |
|
891 // |
|
892 // Returns a the selection of the children of the current context with the given type |
|
893 // |
|
894 /** Gets a selection containing the IDs of all the context children with the specified |
|
895 entry type. |
|
896 |
|
897 If the entry has no children, the selection is empty. |
|
898 |
|
899 @param aType Entry type by which to filter children |
|
900 @param aSelection Initially, this must be an empty selection. On return, it |
|
901 lists the children. |
|
902 @return KErrNone - success; |
|
903 KErrMemory - a memory allocation failed */ |
|
904 { |
|
905 return DoGetChildren(KMsvNullIndexEntryId, KNullUid, aType, aSelection); |
|
906 } |
|
907 |
|
908 TInt CMsvServerEntry::DoGetChildren(TMsvId aServiceId, TUid aMtm, TUid aType, CMsvEntrySelection& aSelection) |
|
909 { |
|
910 TRAPD(err, DoGetChildrenL(aServiceId, aMtm, aType, aSelection)); |
|
911 return err; |
|
912 } |
|
913 |
|
914 void CMsvServerEntry::DoGetChildrenL(TMsvId aServiceId, TUid aMtm, TUid aType, CMsvEntrySelection& aSelection) |
|
915 { |
|
916 __ASSERT_DEBUG(iEntry.Id()!=KMsvNullIndexEntryId, PanicServer(EMsvEntryWithNoContext8)); |
|
917 |
|
918 CMsvEntryFilter* filter = CMsvEntryFilter::NewLC(); |
|
919 |
|
920 filter->SetService(aServiceId); |
|
921 filter->SetMtm(aMtm); |
|
922 filter->SetType(aType); |
|
923 filter->SetOrder(iOrdering); |
|
924 filter->SetSortMtm(iMtm); |
|
925 |
|
926 aSelection.Reset(); |
|
927 User::LeaveIfError(iServer.IndexAdapter().GetChildrenId(iEntry.Id(), *filter, aSelection)); |
|
928 CleanupStack::PopAndDestroy(); // filter |
|
929 } |
|
930 |
|
931 EXPORT_C CMsvServerEntry* CMsvServerEntry::NewEntryL(TMsvId aId) |
|
932 // |
|
933 // Creates a new server entry object set with entry aId as context |
|
934 // |
|
935 /** Gets a new CMsvServerEntry object for the specified entry ID. |
|
936 |
|
937 The call locks the entry, preventing it being accessed by other clients. |
|
938 |
|
939 The object must be deleted when it is no longer required. The lock is released |
|
940 when the object is deleted or the context is changed with SetEntry(). |
|
941 |
|
942 @param aId ID of the entry to access |
|
943 @leave KErrLocked Entry is locked |
|
944 @leave KErrNoMemory A memory allocation failed |
|
945 @leave KErrNotFound The entry does not exist |
|
946 @return If the function succeeds, this is a pointer to a newly allocated and |
|
947 initialised object. */ |
|
948 { |
|
949 return CMsvServerEntry::NewL(iServer, aId); |
|
950 } |
|
951 |
|
952 |
|
953 EXPORT_C TInt CMsvServerEntry::MoveEntryWithinService(TMsvId aId, TMsvId aDestination) |
|
954 // |
|
955 // Moves the child of the current context |
|
956 // |
|
957 /** Moves a child of the context to under another entry. All descendants will be |
|
958 moved as well. The destination must belong to the same service as the context. |
|
959 |
|
960 If an error occurs, no changes are made. |
|
961 |
|
962 For pre-Unicode releases see the synchronous overload of MoveEntry(). |
|
963 |
|
964 @param aId The ID of the entry to move |
|
965 @param aDestination The ID of new parent |
|
966 @return KErrNone if successful, KErrArgument if the destination is a child |
|
967 of aId, KErrInUse if the store or a file associated with the entry is open, |
|
968 KErrNotFound if the aId is not a child of the context KErrPathNotFound, if |
|
969 the destination does not exist. */ |
|
970 { |
|
971 __ASSERT_DEBUG(iEntry.Id()!=KMsvNullIndexEntryId, PanicServer(EMsvEntryWithNoContext10)); |
|
972 |
|
973 // only move children |
|
974 if (!IsAChild(aId)) |
|
975 return KErrNotFound; |
|
976 |
|
977 // check for moving into its current parent |
|
978 if (aDestination==iEntry.Id()) |
|
979 return KErrNone; |
|
980 |
|
981 TRAPD(error, DoMoveEntryL(aId, aDestination)); |
|
982 |
|
983 // notify server of the move |
|
984 if (error==KErrNone) |
|
985 { |
|
986 iServer.NotifyChanged(EMsvEntriesMoved, aId, aDestination, iEntry.Id()); |
|
987 // need to remove owner flag if has no children |
|
988 TMsvEntry* pEntry; |
|
989 TInt err = KErrNone; |
|
990 err = iServer.IndexAdapter().GetEntry(iEntry.Id(), pEntry); |
|
991 if (err==KErrNone) |
|
992 iEntry.SetOwner(pEntry->Owner()); |
|
993 } |
|
994 |
|
995 return error; |
|
996 } |
|
997 |
|
998 void CMsvServerEntry::DoMoveEntryL(TMsvId aId, TMsvId aDestination) |
|
999 // |
|
1000 // |
|
1001 // |
|
1002 { |
|
1003 CMsvMove* move = CMsvMove::NewL(iServer); |
|
1004 CleanupStack::PushL(move); |
|
1005 move->StartL(aId, aDestination); |
|
1006 CleanupStack::PopAndDestroy(); // move |
|
1007 } |
|
1008 |
|
1009 EXPORT_C TInt CMsvServerEntry::MoveEntriesWithinService(CMsvEntrySelection& aSelection, TMsvId aDestination) |
|
1010 // |
|
1011 // |
|
1012 // |
|
1013 /** Moves a child of the context to under another entry. All descendants will be |
|
1014 moved as well. The destination must belong to the same service as the context. |
|
1015 |
|
1016 @param aSelection The entries to move. On return, contains the children that |
|
1017 could not be fully moved. |
|
1018 @param aDestination The ID of new parent |
|
1019 @return KErrNone if successful, KErrArgument if the destination is a child |
|
1020 of aSelection entry, KErrInUse if the store or a file associated with an entry |
|
1021 is open, KErrNotFound if an aSelection entry is not a child of the context |
|
1022 the, or KErrPathNotFound if the destination does not exist. */ |
|
1023 { |
|
1024 __ASSERT_DEBUG(iEntry.Id()!=KMsvNullIndexEntryId, PanicServer(EMsvEntryWithNoContext10)); |
|
1025 |
|
1026 CMsvEntrySelection* moved = NULL; |
|
1027 |
|
1028 TRAPD(error, DoMoveEntriesL(aSelection, aDestination, moved)); |
|
1029 |
|
1030 if (moved && moved->Count()) |
|
1031 { |
|
1032 iServer.NotifyChanged(EMsvEntriesMoved, *moved, aDestination, iEntry.Id()); |
|
1033 |
|
1034 // need to remove owner flag if has no children |
|
1035 TMsvEntry* pEntry; |
|
1036 TInt err = KErrNone; |
|
1037 err = iServer.IndexAdapter().GetEntry(iEntry.Id(), pEntry); |
|
1038 if (err==KErrNone) |
|
1039 iEntry.SetOwner(pEntry->Owner()); |
|
1040 } |
|
1041 |
|
1042 delete moved; |
|
1043 return error; |
|
1044 } |
|
1045 |
|
1046 void CMsvServerEntry::DoMoveEntriesL(CMsvEntrySelection& aSelection, TMsvId aDestination, CMsvEntrySelection*& aMoved) |
|
1047 { |
|
1048 __ASSERT_DEBUG(!aMoved, PanicServer(EMsvMoveSelectionNotNull)); |
|
1049 __ASSERT_DEBUG(aSelection.Count() > 0, PanicServer(EMsvMovingEmptySelection)); |
|
1050 |
|
1051 aMoved = new(ELeave)CMsvEntrySelection; |
|
1052 aMoved->SetReserveL(aSelection.Count()); |
|
1053 |
|
1054 CMsvMove* move = CMsvMove::NewL(iServer); |
|
1055 CleanupStack::PushL(move); |
|
1056 |
|
1057 TInt error = KErrNone; |
|
1058 |
|
1059 TInt count = aSelection.Count(); |
|
1060 while(count--) |
|
1061 { |
|
1062 TMsvId id = aSelection.At(count); |
|
1063 if (!IsAChild(id)) |
|
1064 error = KErrNotFound; |
|
1065 else |
|
1066 { |
|
1067 move->StartL(id, aDestination); |
|
1068 aSelection.Delete(count); |
|
1069 aMoved->AppendL(id); |
|
1070 } |
|
1071 } |
|
1072 User::LeaveIfError(error); |
|
1073 CleanupStack::PopAndDestroy(); // move |
|
1074 } |
|
1075 |
|
1076 EXPORT_C void CMsvServerEntry::MoveEntryL(TMsvId aId, TMsvId aDestination, TRequestStatus& aObserverStatus) |
|
1077 // |
|
1078 // |
|
1079 // |
|
1080 /** Moves a child of the context to another entry that belongs to a different service. |
|
1081 All descendants will be moved as well. |
|
1082 |
|
1083 The move is carried out asynchronously. The caller should supply in aObserverStatus |
|
1084 the status word of an active object that it owns. The function will signal |
|
1085 this to be completed when the move is complete. |
|
1086 |
|
1087 If the function leaves, no changes are made. |
|
1088 |
|
1089 In pre-Unicode versions an asynchronous move can be cancelled through CancelMoveEntry(); |
|
1090 in other releases, use Cancel(). |
|
1091 |
|
1092 @param aId The ID of the entry to move |
|
1093 @param aDestination The ID of new parent |
|
1094 @param aObserverStatus The request status to be completed when the operation |
|
1095 has finished |
|
1096 @leave KErrArgument The destination is a child of aId |
|
1097 @leave KErrInUse The store or a file associated with the entry is open |
|
1098 @leave KErrNoMemory A memory allocation failed |
|
1099 @leave KErrNotFound aId is not a child of the context |
|
1100 @leave KErrPathNotFound The destination does not exist */ |
|
1101 { |
|
1102 CMsvEntrySelection* selection = new(ELeave)CMsvEntrySelection; |
|
1103 CleanupStack::PushL(selection); |
|
1104 selection->AppendL(aId); |
|
1105 |
|
1106 MoveEntriesL(*selection, aDestination, aObserverStatus); |
|
1107 |
|
1108 CleanupStack::PopAndDestroy(); // selection |
|
1109 } |
|
1110 |
|
1111 EXPORT_C void CMsvServerEntry::MoveEntriesL(const CMsvEntrySelection& aSelection, TMsvId aDestination, TRequestStatus& aObserverStatus) |
|
1112 // |
|
1113 // |
|
1114 // |
|
1115 /** Moves a selection of children of the context to another entry that belongs |
|
1116 to a different service. All descendants will be moved as well. |
|
1117 |
|
1118 The move is carried out asynchronously. The caller should supply in aObserverStatus |
|
1119 the status word of an active object that it owns. The function will signal |
|
1120 this to be completed when the move is complete. |
|
1121 |
|
1122 @param aSelection The IDs of the entry to move. On return, contains the children |
|
1123 that could not be fully moved. |
|
1124 @param aDestination The ID of new parent |
|
1125 @param aObserverStatus The request status to be completed when the operation |
|
1126 has finished |
|
1127 @leave KErrArgument The destination is a child of an aSelection entry |
|
1128 @leave KErrInUse The store or a file associated with an entry is open |
|
1129 @leave KErrNoMemory A memory allocation failed |
|
1130 @leave KErrNotFound An aSelection entry is not a child of the context |
|
1131 @leave KErrPathNotFound The destination does not exist */ |
|
1132 { |
|
1133 __ASSERT_DEBUG(iEntry.Id()!=KMsvNullIndexEntryId, PanicServer(EMsvEntryWithNoContext10)); |
|
1134 __ASSERT_ALWAYS(aDestination!=iEntry.Id(), PanicServer(EMsvMovingToSamePArent)); |
|
1135 __ASSERT_ALWAYS(iEntryState == EMsvIdle, PanicServer(EMsvServerEntryNotIdle)); |
|
1136 __ASSERT_ALWAYS(aSelection.Count() > 0, PanicServer(EMsvEmptySelection)); |
|
1137 __ASSERT_DEBUG(iCopyMove==NULL, PanicServer(EMsvMoveNotCompleted)); |
|
1138 |
|
1139 // only move children |
|
1140 if (!AreChildren(aSelection)) |
|
1141 User::Leave(KErrNotFound); |
|
1142 |
|
1143 CMsvMoveEntries* move = CMsvMoveEntries::NewL(iServer); |
|
1144 CleanupStack::PushL(move); |
|
1145 |
|
1146 move->StartL(aSelection, aDestination, iStatus); |
|
1147 |
|
1148 CleanupStack::Pop(); // move |
|
1149 |
|
1150 iCopyMove=move; |
|
1151 iEntryState = EMsvMoving; |
|
1152 iObserverStatus = &aObserverStatus; |
|
1153 *iObserverStatus = KRequestPending; |
|
1154 |
|
1155 SetActive(); |
|
1156 } |
|
1157 |
|
1158 EXPORT_C void CMsvServerEntry::CopyEntryL(TMsvId aId, TMsvId aDestination, TRequestStatus& aObserverStatus) |
|
1159 // |
|
1160 // Recursively copies a child of the context to another entry that belongs to a different service. |
|
1161 // |
|
1162 /** Copies a child of the context to another entry. All descendants will be copied |
|
1163 as well. |
|
1164 |
|
1165 The copy is carried out asynchronously. The caller should supply in aObserverStatus |
|
1166 the status word of an active object that it owns. The function will signal |
|
1167 this to be completed when the copy is complete. |
|
1168 |
|
1169 If the function leaves, no changes are made. |
|
1170 |
|
1171 @param aId The ID of the entry to copy |
|
1172 @param aDestination The ID of new parent |
|
1173 @param aObserverStatus The request status to be completed when the operation |
|
1174 has finished |
|
1175 @leave KErrArgument The destination is a child of an aSelection entry |
|
1176 @leave KErrInUse The store or a file associated with an entry is open |
|
1177 @leave KErrNoMemory A memory allocation failed |
|
1178 @leave KErrNotFound An aSelection entry is not a child of the context |
|
1179 @leave KErrPathNotFound The destination does not exist */ |
|
1180 { |
|
1181 CMsvEntrySelection* selection = new(ELeave)CMsvEntrySelection; |
|
1182 CleanupStack::PushL(selection); |
|
1183 selection->AppendL(aId); |
|
1184 iCompletedSelection = NULL; |
|
1185 iCompletedEntryId = NULL; |
|
1186 |
|
1187 DoCopyEntriesL(*selection, aDestination, aObserverStatus); |
|
1188 |
|
1189 CleanupStack::PopAndDestroy(); // selection |
|
1190 } |
|
1191 |
|
1192 EXPORT_C void CMsvServerEntry::CopyEntryL(TMsvId aId, TMsvId aDestination, TMsvId& aCompletedEntry, TRequestStatus& aObserverStatus) |
|
1193 // |
|
1194 // |
|
1195 // |
|
1196 /** Copies a child of the context to another entry. All descendants will be copied |
|
1197 as well. |
|
1198 |
|
1199 This overload returns the ID of the new entry. |
|
1200 |
|
1201 The copy is carried out asynchronously. The caller should supply in aObserverStatus |
|
1202 the status word of an active object that it owns. The function will signal |
|
1203 this to be completed when the copy is complete. |
|
1204 |
|
1205 If the function leaves, no changes are made. |
|
1206 |
|
1207 @param aId The ID of the entry to copy |
|
1208 @param aDestination The ID of new parent |
|
1209 @param aCompletedEntry On return, the ID of the new entry |
|
1210 @param aObserverStatus The request status to be completed when the operation |
|
1211 has finished |
|
1212 @leave KErrArgument The destination is a child of an aSelection entry |
|
1213 @leave KErrInUse The store or a file associated with an entry is open |
|
1214 @leave KErrNoMemory A memory allocation failed |
|
1215 @leave KErrNotFound An aSelection entry is not a child of the context |
|
1216 @leave KErrPathNotFound The destination does not exist */ |
|
1217 { |
|
1218 CMsvEntrySelection* selection = new(ELeave)CMsvEntrySelection; |
|
1219 CleanupStack::PushL(selection); |
|
1220 selection->AppendL(aId); |
|
1221 iCompletedSelection = NULL; |
|
1222 iCompletedEntryId = &aCompletedEntry; |
|
1223 |
|
1224 DoCopyEntriesL(*selection, aDestination, aObserverStatus); |
|
1225 |
|
1226 CleanupStack::PopAndDestroy(); // selection |
|
1227 } |
|
1228 |
|
1229 EXPORT_C void CMsvServerEntry::CopyEntriesL(const CMsvEntrySelection& aSelection, TMsvId aDestination, TRequestStatus& aObserverStatus) |
|
1230 // |
|
1231 // |
|
1232 // |
|
1233 /** Copies a selection of children of the context to another entry that belongs |
|
1234 to a different service. All descendants will be copied as well. |
|
1235 |
|
1236 The copy is carried out asynchronously. The caller should supply in aObserverStatus |
|
1237 the status word of an active object that it owns. The function will signal |
|
1238 this to be completed when the copy is complete. |
|
1239 |
|
1240 @param aSelection The IDs of the entry to copy. On return, contains the children |
|
1241 that could not be fully copied. |
|
1242 @param aDestination The ID of new parent |
|
1243 @param aObserverStatus The request status to be completed when the operation |
|
1244 has finished |
|
1245 @leave KErrArgument The destination is a child of an aSelection entry |
|
1246 @leave KErrInUse The store or a file associated with an entry is open |
|
1247 @leave KErrNoMemory A memory allocation failed |
|
1248 @leave KErrNotFound An aSelection entry is not a child of the context |
|
1249 @leave KErrPathNotFound The destination does not exist */ |
|
1250 { |
|
1251 iCompletedSelection = NULL; |
|
1252 iCompletedEntryId = NULL; |
|
1253 DoCopyEntriesL(aSelection, aDestination, aObserverStatus); |
|
1254 } |
|
1255 |
|
1256 EXPORT_C void CMsvServerEntry::CopyEntriesL(const CMsvEntrySelection& aSelection, TMsvId aDestination, CMsvEntrySelection& aCompletedSelection, TRequestStatus& aObserverStatus) |
|
1257 // |
|
1258 // Recursively copies a selection of children of the context to another entry that belongs to a different service. |
|
1259 // Will return the target entries through the aCompletedSelection parameter. |
|
1260 // |
|
1261 /** Copies a selection of children of the context to another entry that belongs |
|
1262 to a different service. All descendants will be copied as well. |
|
1263 |
|
1264 This overload returns the IDs of the new entries. |
|
1265 |
|
1266 The copy is carried out asynchronously. The caller should supply in aObserverStatus |
|
1267 the status word of an active object that it owns. The function will signal |
|
1268 this to be completed when the copy is complete. |
|
1269 |
|
1270 @param aSelection The IDs of the entry to copy. On return, contains the children |
|
1271 that could not be fully copied. |
|
1272 @param aDestination The ID of new parent |
|
1273 @param aCompletedSelection On return, the IDs of the new entries. |
|
1274 @param aObserverStatus The request status to be completed when the operation |
|
1275 has finished |
|
1276 @leave KErrArgument The destination is a child of an aSelection entry |
|
1277 @leave KErrInUse The store or a file associated with an entry is open |
|
1278 @leave KErrNoMemory A memory allocation failed |
|
1279 @leave KErrNotFound An aSelection entry is not a child of the context |
|
1280 @leave KErrPathNotFound The destination does not exist */ |
|
1281 { |
|
1282 iCompletedSelection = &aCompletedSelection; |
|
1283 iCompletedEntryId = NULL; |
|
1284 DoCopyEntriesL(aSelection, aDestination, aObserverStatus); |
|
1285 } |
|
1286 |
|
1287 void CMsvServerEntry::DoCopyEntriesL(const CMsvEntrySelection& aSelection, TMsvId aDestination, TRequestStatus& aObserverStatus) |
|
1288 // |
|
1289 // |
|
1290 // |
|
1291 { |
|
1292 __ASSERT_DEBUG(iEntry.Id()!=KMsvNullIndexEntryId, PanicServer(EMsvEntryWithNoContext10)); |
|
1293 __ASSERT_ALWAYS(aDestination!=iEntry.Id(), PanicServer(EMsvCopyingToSameParent)); |
|
1294 __ASSERT_ALWAYS(iEntryState == EMsvIdle, PanicServer(EMsvServerEntryNotIdle)); |
|
1295 __ASSERT_ALWAYS(aSelection.Count() > 0, PanicServer(EMsvEmptySelection)); |
|
1296 __ASSERT_DEBUG(iCopyMove==NULL, PanicServer(EMsvCopyNotCompleted)); |
|
1297 |
|
1298 // only copy children |
|
1299 if (!AreChildren(aSelection)) |
|
1300 User::Leave(KErrNotFound); |
|
1301 |
|
1302 CMsvCopyEntries* copy = CMsvCopyEntries::NewL(iServer); |
|
1303 CleanupStack::PushL(copy); |
|
1304 copy->StartL(aSelection, aDestination, iStatus); |
|
1305 CleanupStack::Pop(); // copy |
|
1306 |
|
1307 iCopyMove=copy; |
|
1308 iEntryState = EMsvCopying; |
|
1309 iObserverStatus = &aObserverStatus; |
|
1310 *iObserverStatus = KRequestPending; |
|
1311 |
|
1312 SetActive(); |
|
1313 } |
|
1314 void CMsvServerEntry::RunL() |
|
1315 // |
|
1316 // |
|
1317 // |
|
1318 { |
|
1319 __ASSERT_DEBUG(iEntryState != EMsvIdle, PanicServer(EMsvServerEntryIdle)); |
|
1320 __ASSERT_DEBUG(iCopyMove, PanicServer(EMsvCopyMoveCompletionMissing)); |
|
1321 |
|
1322 if (iCopyMove->CompletedIds().Count() > 0) |
|
1323 { |
|
1324 switch (iEntryState) |
|
1325 { |
|
1326 case EMsvMoving: |
|
1327 { |
|
1328 iServer.NotifyChanged(EMsvEntriesMoved, iCopyMove->CompletedIds(), iCopyMove->TargetId(), iEntry.Id()); |
|
1329 |
|
1330 TMsvEntry* pEntry; |
|
1331 TInt err = KErrNone; |
|
1332 err = iServer.IndexAdapter().GetEntry(iEntry.Id(), pEntry); |
|
1333 if (err ==KErrNone) |
|
1334 iEntry.SetOwner(pEntry->Owner()); |
|
1335 break; |
|
1336 } |
|
1337 |
|
1338 case EMsvCopying: |
|
1339 { |
|
1340 const CMsvEntrySelection& newEntries = static_cast<CMsvCopyEntries*>(iCopyMove)->NewEntryIds(); |
|
1341 iServer.NotifyChanged(EMsvEntriesCreated, newEntries, iCopyMove->TargetId()); |
|
1342 |
|
1343 if (iCompletedSelection) |
|
1344 { |
|
1345 iCompletedSelection->Reset(); |
|
1346 TInt count = newEntries.Count(); |
|
1347 |
|
1348 while (count--) |
|
1349 iCompletedSelection->AppendL(newEntries[count]); |
|
1350 } |
|
1351 else if (iCompletedEntryId) |
|
1352 *iCompletedEntryId = newEntries[0]; |
|
1353 |
|
1354 break; |
|
1355 } |
|
1356 |
|
1357 default: |
|
1358 break; |
|
1359 } |
|
1360 } |
|
1361 |
|
1362 delete iCopyMove; |
|
1363 iCopyMove = NULL; |
|
1364 iEntryState = EMsvIdle; |
|
1365 |
|
1366 User::RequestComplete(iObserverStatus, iStatus.Int()); |
|
1367 } |
|
1368 |
|
1369 |
|
1370 void CMsvServerEntry::DoCancel() |
|
1371 // |
|
1372 // |
|
1373 // |
|
1374 { |
|
1375 __ASSERT_DEBUG(iEntryState != EMsvIdle, PanicServer(EMsvServerEntryIdle)); |
|
1376 __ASSERT_DEBUG(iCopyMove, PanicServer(EMsvCopyMoveCancelMissing)); |
|
1377 |
|
1378 iCopyMove->Cancel(); |
|
1379 |
|
1380 delete iCopyMove; |
|
1381 iCopyMove=NULL; |
|
1382 iEntryState = EMsvIdle; |
|
1383 |
|
1384 User::RequestComplete(iObserverStatus, KErrCancel); |
|
1385 } |
|
1386 |
|
1387 |
|
1388 EXPORT_C TMsvId CMsvServerEntry::OwningService() const |
|
1389 // |
|
1390 // |
|
1391 // |
|
1392 /** Gets the ID of the service that owns the context. |
|
1393 |
|
1394 Local entries are considered as being members of the local service. |
|
1395 |
|
1396 If the entry is the root, then the root ID (KMsvRootIndexEntryId) is returned. |
|
1397 |
|
1398 @return ID of the service that owns this entry */ |
|
1399 { |
|
1400 if (iEntry.Id()==KMsvRootIndexEntryId) |
|
1401 return KMsvRootIndexEntryId; |
|
1402 TMsvId owningService; |
|
1403 iServer.IndexAdapter().OwningService(iEntry.Id(), owningService); // error ignored as entry obviously exists |
|
1404 return owningService; |
|
1405 } |
|
1406 |
|
1407 |
|
1408 EXPORT_C TInt CMsvServerEntry::ChangeAttributes(const CMsvEntrySelection& aSelection, TUint aSetAttributes, TUint aClearAttributes) |
|
1409 // |
|
1410 // |
|
1411 // |
|
1412 /** Provides a quick way to set or clear multiple fields in a selection of entries. |
|
1413 |
|
1414 Fields to change are specified using a bitmask of TMsvAttribute values. Possible |
|
1415 fields that can be changed using this function are: |
|
1416 |
|
1417 1. PC synchronisation |
|
1418 |
|
1419 2. Visibility flag |
|
1420 |
|
1421 3. Read flag |
|
1422 |
|
1423 4. In-preparation flag |
|
1424 |
|
1425 5. Connected flag |
|
1426 |
|
1427 6. New flag |
|
1428 |
|
1429 @param aSelection The entries to change |
|
1430 @param aSetAttributes A bitmask of the fields to set |
|
1431 @param aClearAttributes A bitmask of the fields to clear |
|
1432 @return KErrNone if successful, otherwise one of the system-wide error codes. |
|
1433 KErrNotFound if a specified entry does not exist. |
|
1434 @see TMsvAttribute */ |
|
1435 { |
|
1436 __ASSERT_DEBUG(iEntry.Id()!=KMsvNullIndexEntryId, PanicServer(EMsvEntryWithNoContext11)); |
|
1437 |
|
1438 // only change children |
|
1439 if (!AreChildren(aSelection)) |
|
1440 return KErrNotFound; |
|
1441 |
|
1442 // get a copy of the selection |
|
1443 CMsvEntrySelection* changedEntries=NULL; |
|
1444 TRAPD(error, changedEntries = aSelection.CopyL()); |
|
1445 if (error) |
|
1446 return error; |
|
1447 |
|
1448 // lock all the selection |
|
1449 TInt count1=aSelection.Count(); |
|
1450 while (count1--) |
|
1451 { |
|
1452 error = iServer.IndexAdapter().LockEntry(aSelection.At(count1)); |
|
1453 if (error) |
|
1454 break; |
|
1455 } |
|
1456 |
|
1457 // change the attributes if all were locked |
|
1458 if (error==KErrNone) |
|
1459 { |
|
1460 error = iServer.IndexAdapter().ChangeAttributes(*changedEntries, aSetAttributes, aClearAttributes); |
|
1461 } |
|
1462 |
|
1463 // release all that were locked |
|
1464 TInt count2=aSelection.Count(); |
|
1465 while (--count2>count1) |
|
1466 { |
|
1467 iServer.IndexAdapter().ReleaseEntry(aSelection.At(count2)); |
|
1468 } |
|
1469 |
|
1470 |
|
1471 // notify server if any have been changed |
|
1472 if (error==KErrNone && changedEntries->Count()) |
|
1473 iServer.NotifyChanged(EMsvEntriesChanged, *changedEntries, iEntry.Id()); |
|
1474 |
|
1475 delete changedEntries; |
|
1476 |
|
1477 return error; |
|
1478 } |
|
1479 |
|
1480 |
|
1481 EXPORT_C TBool CMsvServerEntry::HasStoreL() const |
|
1482 /** Tests if the context has an associated message store. |
|
1483 |
|
1484 @return ETrue: entry has a message store EFalse: entry does not have a message |
|
1485 store */ |
|
1486 { |
|
1487 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB) |
|
1488 if(iServer.ServerStoreManager().DoesAnyStoreExists(iEntry.Id(), iEntry.iMtm)) |
|
1489 return ETrue; |
|
1490 else |
|
1491 return iServer.ServerStoreManager().FileStoreExistsL(iEntry.Id()); |
|
1492 #else |
|
1493 return iServer.ServerStoreManager().FileStoreExistsL(iEntry.Id()); |
|
1494 #endif |
|
1495 } |
|
1496 |
|
1497 |
|
1498 EXPORT_C RFs& CMsvServerEntry::FileSession() |
|
1499 /** Allows a Server-side MTM to access the file session handle created by the Message |
|
1500 Server. This is preferable, as more efficient, to creating another handle. |
|
1501 |
|
1502 @return File session handle */ |
|
1503 { |
|
1504 return iServer.FileSession(); |
|
1505 } |
|
1506 |
|
1507 |