|
1 /* |
|
2 * Copyright (c) 2003 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: This file contains the implementation of the CCbsDbImpTopicList class |
|
15 * member functions. |
|
16 * |
|
17 * This class represents the topic list contained in the database. |
|
18 * |
|
19 */ |
|
20 |
|
21 |
|
22 |
|
23 // INCLUDE FILES |
|
24 #include <e32base.h> |
|
25 #include <e32svr.h> |
|
26 #include <f32file.h> |
|
27 |
|
28 #include <shareddataclient.h> // RequestFreeDiskSpaceLC |
|
29 |
|
30 #include <barsc.h> // Resource access |
|
31 #include <barsread.h> // Resource access |
|
32 |
|
33 #include <CbsServer.rsg> |
|
34 |
|
35 #include "CbsServerPanic.h" |
|
36 #include "CbsStreamHelper.h" |
|
37 #include "CbsDbConstants.h" |
|
38 #include "CbsUtils.h" |
|
39 #include "CCbsDbImpTopicList.h" |
|
40 #include "MCbsDbTopicListObserver.H" |
|
41 #include "CCbsDbImpTopicMessages.h" |
|
42 |
|
43 #include "CbsLogger.h" |
|
44 |
|
45 #include <centralrepository.h> // for local variation |
|
46 #include "cbsinternalcrkeys.h" // for local variation |
|
47 #include "cbsvariant.hrh" // for local variation |
|
48 |
|
49 // CONSTANTS |
|
50 |
|
51 // Initial size for topic cache array |
|
52 const TInt KDefaultTopicListSize = 10; |
|
53 |
|
54 // Size of the topic stream, used in checking against FFS free space limit |
|
55 const TInt KTopicStreamSize = 92; |
|
56 |
|
57 // Size of the topic messages stream, FFS critical level check |
|
58 const TInt KEmptyTopicMessagesStreamSize = 4; |
|
59 |
|
60 // Size of topic list stream, FFS critical level check |
|
61 const TInt KTopicListStreamSize = 85; |
|
62 |
|
63 // Size of topic list stream (root), FFS critical level check |
|
64 const TInt KTopicListRootStreamSize = 2; |
|
65 |
|
66 // Time in microseconds to wait after a critical store exception |
|
67 // before a recovery attempt is made. |
|
68 const TInt KWaitAfterCriticalStoreException = 2000000; |
|
69 |
|
70 // Used when unsaved message stream ids are deleted from topic messages |
|
71 // stream |
|
72 const TInt KTypicalNumberOfTopicMessages = 6; |
|
73 |
|
74 // Minimum interval between compacting the stores in minutes |
|
75 const TInt KMinimumCompactInterval = 30; |
|
76 |
|
77 // Number of the index topic |
|
78 const TInt KIndexTopicNumber = 0; |
|
79 |
|
80 // Space for reading messages |
|
81 const TInt KReadMessageSize = 92; |
|
82 |
|
83 const TInt KTopicsGranularity = 1; |
|
84 |
|
85 const TInt KTopicListsGranularity = 1; |
|
86 |
|
87 const TInt KTopicIdsGranularity = 5; |
|
88 |
|
89 // ================= MEMBER FUNCTIONS ======================= |
|
90 |
|
91 // ----------------------------------------------------------------------------- |
|
92 // CCbsDbImpTopicList::CCbsDbImpTopicList |
|
93 // C++ default constructor can NOT contain any code, that |
|
94 // might leave. |
|
95 // ----------------------------------------------------------------------------- |
|
96 // |
|
97 CCbsDbImpTopicList::CCbsDbImpTopicList( |
|
98 RFs& aFs, |
|
99 CCbsDbImp& aDatabase ) |
|
100 : iDatabase( aDatabase ), |
|
101 iFs( aFs ), |
|
102 iTopicCount( 0 ), |
|
103 iInitializing( EFalse ), |
|
104 iDeleteAllTopics( EFalse ) |
|
105 { |
|
106 } |
|
107 |
|
108 // ----------------------------------------------------------------------------- |
|
109 // CCbsDbImpTopicList::ConstructL |
|
110 // Symbian 2nd phase constructor can leave. |
|
111 // ----------------------------------------------------------------------------- |
|
112 // |
|
113 void CCbsDbImpTopicList::ConstructL( |
|
114 const TDesC& aTopicsFile, |
|
115 const TDesC& aUnsavedMessagesFile ) |
|
116 { |
|
117 CBSLOGSTRING("CBSSERVER: >>> CCbsDbImpTopicList::ConstructL()"); |
|
118 |
|
119 // Create observer array |
|
120 iObservers = new ( ELeave ) CArrayFixFlat< MCbsDbTopicListObserver* >( |
|
121 KCbsDbObserverArraySize ); |
|
122 |
|
123 // Create topic array, additional memory size in new alloc, 1*192 B = 192 B |
|
124 iTopics = new ( ELeave ) CArrayFixFlat< TCbsDbImpTopic >( KTopicsGranularity ); |
|
125 |
|
126 // Create the root item table, additional memory size in new alloc, 1*184 B = 184 B |
|
127 iTopicLists = new ( ELeave ) CArrayFixFlat< TCbsDbImpTopicList >( KTopicListsGranularity ); |
|
128 |
|
129 // Create topic ID array, additional memory size in new alloc, 5*4 B = 20 B |
|
130 iTopicIds = new ( ELeave ) CArrayFixFlat< TStreamId >( KTopicIdsGranularity ); |
|
131 |
|
132 // Initialize iPreviousCompact to now |
|
133 iPreviousCompact.UniversalTime(); |
|
134 |
|
135 // Copy datafile names from parameters |
|
136 iTopicsFilename = aTopicsFile.AllocL(); |
|
137 iUnsavedMessagesFilename = aUnsavedMessagesFile.AllocL(); |
|
138 |
|
139 // Fetch local variation bits from CenRep |
|
140 CRepository* repository = CRepository::NewL( KCRUidCbsVariation ); |
|
141 TInt err = repository->Get( KCbsVariationFlags, iLVBits ); |
|
142 CBSLOGSTRING2("CBSSERVER: CCbsRecEtel::ConstructL(): CenRep error: %d", err ); |
|
143 if ( err ) |
|
144 { |
|
145 iLVBits = 0; |
|
146 } |
|
147 delete repository; |
|
148 |
|
149 // If aLoadFactorySettings, then the files are recreated and initialized. |
|
150 // If not, then the nonexisting files are created, files opened and |
|
151 // data internalized. |
|
152 |
|
153 TBool unsavedMsgFileExists( CbsUtils::ExistsL( iFs, *iUnsavedMessagesFilename ) ); |
|
154 |
|
155 TBool loadFactorySettings( !CbsUtils::ExistsL( iFs, aTopicsFile ) ); |
|
156 TRAPD( error, OpenFilesL( loadFactorySettings, EFalse ) ); |
|
157 |
|
158 CBSLOGSTRING2("CBSSERVER: CCbsDbImpTopicList::ConstructL(): OpenFilesL() error: %d", error ); |
|
159 |
|
160 if ( error == KErrDiskFull ) |
|
161 { |
|
162 // Delete the store and open is again |
|
163 CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicList::ConstructL(): About to delete iTopicStore..." ); |
|
164 |
|
165 delete iTopicStore; |
|
166 iTopicStore = NULL; |
|
167 |
|
168 CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicList::ConstructL(): iTopicStore deletion finished." ); |
|
169 |
|
170 // Try to open the store again |
|
171 TRAPD( error, iTopicStore = CFileStore::OpenL( iFs, *iTopicsFilename, EFileRead | EFileWrite ) ); |
|
172 CBSLOGSTRING2("CBSSERVER: CCbsDbImpTopicList::ConstructL(); iTopicStore OpenL() error: %d", error ); |
|
173 if ( error ) |
|
174 { |
|
175 InitializeListL( ETrue ); |
|
176 } |
|
177 } |
|
178 else |
|
179 { |
|
180 if ( loadFactorySettings ) |
|
181 { |
|
182 // Create a topic list for standard topics |
|
183 if ( iTopicLists->Count() == 0 ) |
|
184 { |
|
185 CreateStandardTopicListL(); |
|
186 } |
|
187 } |
|
188 |
|
189 // Only load the topics, if not already loaded when opening the files |
|
190 if ( loadFactorySettings || unsavedMsgFileExists ) |
|
191 { |
|
192 // Load the topics |
|
193 LoadDefaultTopicStreamL(); |
|
194 } |
|
195 |
|
196 // Compact the topic store |
|
197 TopicStoreL()->CompactL(); |
|
198 TopicStoreL()->CommitL(); |
|
199 } |
|
200 |
|
201 // Reset the unread message count to be sure that UI client gets the correct information, |
|
202 // at this point count is always zero. |
|
203 for ( TInt i( 0 ); i < iTopics->Count(); ++i ) |
|
204 { |
|
205 iTopics->At( i ).iTopicData.iUnreadMessages = 0; |
|
206 } |
|
207 |
|
208 __TEST_INVARIANT; |
|
209 |
|
210 CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicList::ConstructL()"); |
|
211 } |
|
212 |
|
213 // ----------------------------------------------------------------------------- |
|
214 // CCbsDbImpTopicList::NewL |
|
215 // Two-phased constructor. |
|
216 // ----------------------------------------------------------------------------- |
|
217 // |
|
218 CCbsDbImpTopicList* CCbsDbImpTopicList::NewL( |
|
219 RFs& aFs, |
|
220 const TDesC& aTopicsFile, |
|
221 const TDesC& aUnsavedMessagesFile, |
|
222 CCbsDbImp& aDatabase ) |
|
223 { |
|
224 CCbsDbImpTopicList* self = |
|
225 new ( ELeave ) CCbsDbImpTopicList( aFs, aDatabase ); |
|
226 CleanupStack::PushL( self ); |
|
227 self->ConstructL( aTopicsFile, aUnsavedMessagesFile ); |
|
228 CleanupStack::Pop(); |
|
229 return self; |
|
230 } |
|
231 |
|
232 // Destructor |
|
233 CCbsDbImpTopicList::~CCbsDbImpTopicList() |
|
234 { |
|
235 CBSLOGSTRING("CBSSERVER: >>> CCbsDbImpTopicList::~CCbsDbImpTopicList()"); |
|
236 delete iTopics; |
|
237 delete iTopicStore; |
|
238 delete iTopicLists; |
|
239 delete iTopicIds; |
|
240 delete iUnsavedMessageStore; |
|
241 delete iObservers; |
|
242 delete iUnsavedMessagesFilename; |
|
243 if ( iTopicsFilename ) |
|
244 { |
|
245 delete iTopicsFilename; |
|
246 } |
|
247 CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicList::~CCbsDbImpTopicList()"); |
|
248 } |
|
249 |
|
250 #ifndef __SECURE_BACKUP__ |
|
251 // ----------------------------------------------------------------------------- |
|
252 // CCbsDbImpTopicList::ChangeFileLockL |
|
253 // Closes or reopens the settings file if requested by a backup. |
|
254 // (other items were commented in a header). |
|
255 // ----------------------------------------------------------------------------- |
|
256 // |
|
257 void CCbsDbImpTopicList::ChangeFileLockL( |
|
258 const TDesC& aFileName, |
|
259 TFileLockFlags aFlags ) |
|
260 { |
|
261 CBSLOGSTRING2("CBSSERVER: >>> CCbsDbImpTopicList::ChangeFileLockL() (1): flag: %d", aFlags ); |
|
262 |
|
263 if ( aFlags == ETakeLock && iTopicStore == NULL ) |
|
264 { |
|
265 CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicList::ChangeFileLockL() (1): Try to open store..."); |
|
266 |
|
267 // Try to open the store. |
|
268 iTopicStore = CPermanentFileStore::OpenL( iFs, |
|
269 aFileName, EFileRead | EFileWrite ); |
|
270 |
|
271 CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicList::ChangeFileLockL() (1): Store opened."); |
|
272 } |
|
273 else if ( aFlags != ETakeLock ) |
|
274 { |
|
275 CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicList::ChangeFileLockL() (1): Deleting iTopicStore..."); |
|
276 |
|
277 delete iTopicStore; |
|
278 iTopicStore = NULL; |
|
279 |
|
280 CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicList::ChangeFileLockL() (1): iTopicStore deleted."); |
|
281 } |
|
282 CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicList::ChangeFileLockL() (1)"); |
|
283 } |
|
284 #else |
|
285 |
|
286 // ----------------------------------------------------------------------------- |
|
287 // CCbsDbImpSettings::ChangeFileLockL |
|
288 // Closes or reopens the settings file if requested by backup. |
|
289 // (other items were commented in a header). |
|
290 // ----------------------------------------------------------------------------- |
|
291 // |
|
292 void CCbsDbImpTopicList::ChangeFileLockL( const TCbsBackupRequest& aRequest ) |
|
293 { |
|
294 CBSLOGSTRING2("CBSSERVER: >>> CCbsDbImpTopicList::ChangeFileLockL() (2): aRequest: %d", aRequest ); |
|
295 |
|
296 // If backing up or restoring, release locks |
|
297 if ( ( aRequest == ECbsBackup || |
|
298 aRequest == ECbsRestore ) ) |
|
299 { |
|
300 delete iTopicStore; |
|
301 iTopicStore = NULL; |
|
302 |
|
303 CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicList::ChangeFileLockL() (2): iTopicStore deleted."); |
|
304 } |
|
305 // Else take files into use again |
|
306 else if ( ( aRequest == ECbsNoBackup || |
|
307 aRequest == ECbsBackupNotDefined ) && |
|
308 iTopicStore == NULL) |
|
309 { |
|
310 CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicList::ChangeFileLockL() (2): Calling CPermanentFileStore::OpenL()..."); |
|
311 // Try to open the store. |
|
312 iTopicStore = CPermanentFileStore::OpenL( iFs, |
|
313 iTopicsFilename->Des(), EFileRead | EFileWrite ); |
|
314 CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicList::ChangeFileLockL() (2): CPermanentFileStore::OpenL() finished."); |
|
315 } |
|
316 CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicList::ChangeFileLockL() (2)"); |
|
317 } |
|
318 |
|
319 #endif |
|
320 |
|
321 // ----------------------------------------------------------------------------- |
|
322 // CCbsDbImpTopicList::CheckFileLockL |
|
323 // Check if the server has a file lock. |
|
324 // (other items were commented in a header). |
|
325 // ----------------------------------------------------------------------------- |
|
326 // |
|
327 void CCbsDbImpTopicList::CheckFileLockL() const |
|
328 { |
|
329 CBSLOGSTRING("CBSSERVER: >>> CCbsDbImpTopicList::CheckFileLockL()"); |
|
330 if ( iTopicStore == NULL ) |
|
331 { |
|
332 CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicList::CheckFileLockL(): iTopicStore == NULL, leaving with KErrLocked..."); |
|
333 User::Leave( KErrLocked ); |
|
334 } |
|
335 CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicList::CheckFileLockL()"); |
|
336 } |
|
337 |
|
338 // ----------------------------------------------------------------------------- |
|
339 // CCbsDbImpTopicList::CreateNewTopicListL |
|
340 // Creates a new topic list. |
|
341 // (other items were commented in a header). |
|
342 // ----------------------------------------------------------------------------- |
|
343 // |
|
344 void CCbsDbImpTopicList::CreateNewTopicListL( const TDesC& aTopicListName ) |
|
345 { |
|
346 // FFS critical level check |
|
347 CbsUtils::FFSCriticalLevelCheckL( KTopicListStreamSize + |
|
348 KCbsDbTopicArraySize, iFs ); |
|
349 |
|
350 TInt topicListCount = iTopicLists->Count(); |
|
351 |
|
352 // Check if there already is 10 topic lists |
|
353 if ( topicListCount < KCbsRootItemsSize ) |
|
354 { |
|
355 // Create the stream for this topic list entry |
|
356 RStoreWriteStream outstream; |
|
357 TStreamId topicListStreamId( |
|
358 outstream.CreateLC( *TopicStoreL() ) ); // on CS |
|
359 |
|
360 // Set the values for this new topic list and set it as "current". |
|
361 // Reset the topic count of this topic list. |
|
362 iCurrentTopicList.iTopicCount = 0; |
|
363 |
|
364 // Topic list stream id for this list |
|
365 iCurrentTopicList.iTopicListId = topicListStreamId; |
|
366 |
|
367 // List name |
|
368 iCurrentTopicList.iTopicListName = aTopicListName; |
|
369 |
|
370 // Is this the default list |
|
371 iCurrentTopicList.iIsDefaultTopicList = ETrue; |
|
372 |
|
373 // Number of this list, which is a int value between 0...9 |
|
374 iCurrentTopicList.iNumber = iTopicLists->Count(); |
|
375 |
|
376 // Add this list to the list array |
|
377 TKeyArrayFix key( _FOFF( TCbsDbImpTopicList, iNumber ), ECmpTUint16 ); |
|
378 iTopicLists->InsertIsqL( iCurrentTopicList, key ); |
|
379 |
|
380 // Write the values to this topic list's stream |
|
381 outstream << iCurrentTopicList.iTopicListName; |
|
382 CbsStreamHelper::WriteBoolL( outstream, iCurrentTopicList.iIsDefaultTopicList ); |
|
383 outstream.WriteInt16L( iCurrentTopicList.iNumber ); |
|
384 outstream.WriteInt16L( iCurrentTopicList.iTopicCount ); |
|
385 |
|
386 // Write space for topic stream IDs |
|
387 for ( TInt i( 0 ); i < KCbsDbTopicArraySize; i++ ) |
|
388 { |
|
389 outstream << TStreamId( 0 ); |
|
390 } |
|
391 |
|
392 outstream.CommitL(); |
|
393 CleanupStack::PopAndDestroy(); // outstream |
|
394 |
|
395 // Reset the topic array and add an index topic to this |
|
396 // topic list |
|
397 iTopics->Reset(); |
|
398 AddIndexTopicL(); |
|
399 |
|
400 // Update the root stream |
|
401 UpdateRootStreamL( EFalse ); |
|
402 |
|
403 // Commit file changes |
|
404 CommitFilesL(); |
|
405 |
|
406 // Load the topics (count = 1, Index topic only), |
|
407 // so that the array is up to date |
|
408 LoadTopicsL( iCurrentTopicList.iTopicListId ); |
|
409 } |
|
410 else |
|
411 { |
|
412 User::Leave( KErrGeneral ); |
|
413 } |
|
414 } |
|
415 |
|
416 // ----------------------------------------------------------------------------- |
|
417 // CCbsDbImpTopicList::SetTopicMessages |
|
418 // Sets the topic messages db object for this topic list. |
|
419 // Note that this function does not transfer ownership |
|
420 // of aMessages. |
|
421 // (other items were commented in a header). |
|
422 // ----------------------------------------------------------------------------- |
|
423 // |
|
424 void CCbsDbImpTopicList::SetTopicMessages( |
|
425 CCbsDbImpTopicMessages* aMessages ) |
|
426 { |
|
427 __ASSERT_ALWAYS( aMessages != NULL, |
|
428 CbsServerPanic( ECbsTopicMessagesNull ) ); |
|
429 iMessages = aMessages; |
|
430 } |
|
431 |
|
432 // ----------------------------------------------------------------------------- |
|
433 // CCbsDbImpTopicList::TopicCount |
|
434 // Returns the total amount of topics the list contains. |
|
435 // (other items were commented in a header). |
|
436 // ----------------------------------------------------------------------------- |
|
437 // |
|
438 TInt CCbsDbImpTopicList::TopicCount() const |
|
439 { |
|
440 return iTopics->Count(); |
|
441 } |
|
442 |
|
443 // ----------------------------------------------------------------------------- |
|
444 // CCbsDbImpTopicList::TopicListCount |
|
445 // Get topic list count. |
|
446 // (other items were commented in a header). |
|
447 // ----------------------------------------------------------------------------- |
|
448 // |
|
449 TInt CCbsDbImpTopicList::TopicListCount() const |
|
450 { |
|
451 return iTopicLists->Count(); |
|
452 } |
|
453 |
|
454 // ----------------------------------------------------------------------------- |
|
455 // CCbsDbImpTopicList::TopicStoreL |
|
456 // Returns pointer to the current store which contains topics |
|
457 // of the server (i.e., Topics-file) and saved messages. |
|
458 // (other items were commented in a header). |
|
459 // ----------------------------------------------------------------------------- |
|
460 // |
|
461 CFileStore* CCbsDbImpTopicList::TopicStoreL() const |
|
462 { |
|
463 CheckFileLockL(); |
|
464 return iTopicStore; |
|
465 } |
|
466 |
|
467 // --------------------------------------------------------- |
|
468 // TopicFilename() |
|
469 // |
|
470 // --------------------------------------------------------- |
|
471 const TDesC& CCbsDbImpTopicList::TopicFilename() const |
|
472 { |
|
473 return *iTopicsFilename; |
|
474 } |
|
475 |
|
476 // ----------------------------------------------------------------------------- |
|
477 // CCbsDbImpTopicList::UnsavedMessagesStore |
|
478 // Returns a pointer to the store, which contains unsaved |
|
479 // messages of the server (Unsaved Messages-file, "cbs4.dat"). |
|
480 // (other items were commented in a header). |
|
481 // ----------------------------------------------------------------------------- |
|
482 // |
|
483 CFileStore* CCbsDbImpTopicList::UnsavedMessagesStore() const |
|
484 { |
|
485 return iUnsavedMessageStore; |
|
486 } |
|
487 |
|
488 // ----------------------------------------------------------------------------- |
|
489 // CCbsDbImpTopicList::UnsavedMessagesFilename |
|
490 // Returns a reference to the name of the file, which contains unsaved |
|
491 // messages of the server (Unsaved Messages-file, "cbs4.dat"). |
|
492 // (other items were commented in a header). |
|
493 // ----------------------------------------------------------------------------- |
|
494 // |
|
495 const TDesC& CCbsDbImpTopicList::UnsavedMessagesFilename() const |
|
496 { |
|
497 return *iUnsavedMessagesFilename; |
|
498 } |
|
499 |
|
500 // ----------------------------------------------------------------------------- |
|
501 // CCbsDbImpTopicList::ExtractTopicNumber |
|
502 // Extracts topic handle from message handle. |
|
503 // Note that the method does not check that the message exists. |
|
504 // (other items were commented in a header). |
|
505 // ----------------------------------------------------------------------------- |
|
506 // |
|
507 TCbsDbTopicNumber CCbsDbImpTopicList::ExtractTopicNumber( |
|
508 const TCbsDbMessageHandle& aHandle ) const |
|
509 { |
|
510 return TCbsDbTopicNumber( aHandle >> 16 ); |
|
511 } |
|
512 |
|
513 // ----------------------------------------------------------------------------- |
|
514 // CCbsDbImpTopicList::GetTopicMessagesIdL |
|
515 // Returns the topic messages stream id by topic handle. |
|
516 // (other items were commented in a header). |
|
517 // ----------------------------------------------------------------------------- |
|
518 // |
|
519 void CCbsDbImpTopicList::GetTopicMessagesIdL( |
|
520 TCbsDbTopicNumber aNumber, TStreamId& aId ) const |
|
521 { |
|
522 CBSLOGSTRING("CBSSERVER: >>> CCbsDbImpTopicList::GetTopicMessagesIdL()"); |
|
523 |
|
524 // Find the topic. |
|
525 TInt index( TopicIndexInList( aNumber ) ); |
|
526 CBSLOGSTRING2("CBSSERVER: CCbsDbImpTopicList::GetTopicMessagesIdL(): Leaving if index != 0. Index: %d.", index ); |
|
527 User::LeaveIfError( index ); |
|
528 |
|
529 // Return the topic message stream id. |
|
530 aId = iTopics->At( index ).iTopicMessagesId; |
|
531 |
|
532 CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicList::GetTopicMessagesIdL()"); |
|
533 } |
|
534 |
|
535 // ----------------------------------------------------------------------------- |
|
536 // CCbsDbImpTopicList::UpdateTopicMessagesIdL |
|
537 // Updates the topic messages stream id by topic handle. |
|
538 // The new identifier is expected not to be a null id. |
|
539 // Note that the method will not commit changes to the store. |
|
540 // It also changes the internal state and thus if the method leaves, |
|
541 // it is good to reload the whole root stream. |
|
542 // The method will delete the old topic messages stream. |
|
543 // (other items were commented in a header). |
|
544 // ----------------------------------------------------------------------------- |
|
545 // |
|
546 void CCbsDbImpTopicList::UpdateTopicMessagesIdL( |
|
547 TCbsDbTopicNumber aNumber, |
|
548 const TStreamId& aNewId ) |
|
549 { |
|
550 __TEST_INVARIANT; |
|
551 // Find position. |
|
552 TInt index( TopicIndexInList( aNumber ) ); |
|
553 User::LeaveIfError( index ); |
|
554 |
|
555 // Get the old id. |
|
556 TStreamId oldId( iTopics->At( index ).iTopicMessagesId ); |
|
557 |
|
558 // Get the topic information. |
|
559 TCbsDbTopic topic; |
|
560 GetTopicL( index, topic ); |
|
561 |
|
562 // Write information to the stream. |
|
563 RStoreWriteStream outstream; |
|
564 outstream.OpenLC( *TopicStoreL(), iTopics->At( index ).iTopicId ); // on CS |
|
565 WriteTopicInformationL( outstream, topic, aNewId ); |
|
566 outstream.CommitL(); |
|
567 CleanupStack::PopAndDestroy(); |
|
568 |
|
569 // Delete the old stream. |
|
570 TopicStoreL()->DeleteL( oldId ); |
|
571 |
|
572 // Update the topic messages id. |
|
573 iTopics->At( index ).iTopicMessagesId = aNewId; |
|
574 __TEST_INVARIANT; |
|
575 } |
|
576 |
|
577 // ----------------------------------------------------------------------------- |
|
578 // CCbsDbImpTopicList::GenerateMessageHandle |
|
579 // Generates a new message handle using the topic |
|
580 // handle of the message and a given random value. |
|
581 // Note that it must be checked that the message handle is unique |
|
582 // in that topic. |
|
583 // (other items were commented in a header). |
|
584 // ----------------------------------------------------------------------------- |
|
585 // |
|
586 TCbsDbMessageHandle CCbsDbImpTopicList::GenerateMessageHandle( |
|
587 const TCbsDbTopicNumber aNumber, |
|
588 TUint16 aRandom ) const |
|
589 { |
|
590 return ( aNumber << 16 ) + aRandom; |
|
591 } |
|
592 |
|
593 // ----------------------------------------------------------------------------- |
|
594 // CCbsDbImpTopicList::ReloadRootStreamL |
|
595 // Reloads the root stream to the memory. |
|
596 // (other items were commented in a header). |
|
597 // ----------------------------------------------------------------------------- |
|
598 // |
|
599 void CCbsDbImpTopicList::ReloadRootStreamL() |
|
600 { |
|
601 LoadRootStreamL(); |
|
602 __TEST_INVARIANT; |
|
603 } |
|
604 |
|
605 // ----------------------------------------------------------------------------- |
|
606 // CCbsDbImpTopicList::InformNewMessageReceivedL |
|
607 // Informs that a new message has been received in a topic. |
|
608 // This method is called by CCbsDbImpTopicMessages. After internal |
|
609 // records are changed, the observers are informed of this event. |
|
610 // Note: leaves changes in stores uncommited. |
|
611 // (other items were commented in a header). |
|
612 // ----------------------------------------------------------------------------- |
|
613 // |
|
614 void CCbsDbImpTopicList::InformNewMessageReceivedL( |
|
615 const TCbsDbMessageHandle& aMessageHandle ) |
|
616 { |
|
617 __TEST_INVARIANT; |
|
618 // Find topic by handle. |
|
619 TCbsDbTopicNumber number( ExtractTopicNumber( aMessageHandle ) ); |
|
620 |
|
621 TCbsDbTopic topic; |
|
622 FindTopicByNumberL( number, topic ); |
|
623 |
|
624 topic.iUnreadMessages++; |
|
625 |
|
626 // Increase the counter in cache |
|
627 TInt position = TopicIndexInList( topic.iNumber ); |
|
628 iTopics->At( position ).iTopicData.iUnreadMessages++; |
|
629 |
|
630 // Write topic information to topic stream but leave changes uncommited. |
|
631 UpdateTopicCountersL( topic, EFalse ); |
|
632 |
|
633 if ( topic.iHotmarked ) |
|
634 { |
|
635 SetHotmarkedMessage( aMessageHandle ); |
|
636 } |
|
637 |
|
638 __TEST_INVARIANT; |
|
639 } |
|
640 |
|
641 // ----------------------------------------------------------------------------- |
|
642 // CCbsDbImpTopicList::InformMessageSavedL |
|
643 // Informs that a message has been set as saved. |
|
644 // Updates the saved messages counters |
|
645 // for the topic of the message and the whole system. |
|
646 // Called by CCbsDbTopicMessages. |
|
647 // (other items were commented in a header). |
|
648 // ----------------------------------------------------------------------------- |
|
649 // |
|
650 void CCbsDbImpTopicList::InformMessageSavedL( |
|
651 const TCbsDbMessageHandle& aMessageHandle ) |
|
652 { |
|
653 __TEST_INVARIANT; |
|
654 // Find topic by handle. |
|
655 TCbsDbTopicNumber number( ExtractTopicNumber( aMessageHandle ) ); |
|
656 |
|
657 TCbsDbTopic topic; |
|
658 FindTopicByNumberL( number, topic ); |
|
659 |
|
660 topic.iSavedMessages++; |
|
661 |
|
662 // Increase the counter in cache |
|
663 TInt position = TopicIndexInList( topic.iNumber ); |
|
664 iTopics->At( position ).iTopicData.iSavedMessages++; |
|
665 |
|
666 // Write topic information to topic stream but leave changes uncommited. |
|
667 UpdateTopicCountersL( topic, EFalse ); |
|
668 |
|
669 __TEST_INVARIANT; |
|
670 } |
|
671 |
|
672 // ----------------------------------------------------------------------------- |
|
673 // CCbsDbImpTopicList::InformUnreadMessageReadL |
|
674 // Informs that an unread message has been read. |
|
675 // Updates the counters when a message is read by the client. |
|
676 // Note: leaves changes in stores uncommited. |
|
677 // (other items were commented in a header). |
|
678 // ----------------------------------------------------------------------------- |
|
679 // |
|
680 void CCbsDbImpTopicList::InformUnreadMessageReadL( |
|
681 const TCbsDbMessageHandle& aMessageHandle ) |
|
682 { |
|
683 CBSLOGSTRING("CBSSERVER: >>> CCbsDbImpTopicList::InformUnreadMessageReadL()"); |
|
684 |
|
685 __TEST_INVARIANT; |
|
686 |
|
687 // Check for file lock |
|
688 CheckFileLockL(); |
|
689 |
|
690 // Check disk space |
|
691 TRAPD( error, CbsUtils::FFSCriticalLevelCheckL( KReadMessageSize, iFs ) ); |
|
692 CBSLOGSTRING2("CBSSERVER: CCbsDbImpTopicList::InformUnreadMessageReadL(): FFSCriticalLevelCheckL returned: %d", error ); |
|
693 if ( error == KErrDiskFull ) |
|
694 { |
|
695 return; |
|
696 } |
|
697 |
|
698 // Find topic by number. |
|
699 TCbsDbTopicNumber number( ExtractTopicNumber( aMessageHandle ) ); |
|
700 |
|
701 TCbsDbTopic topic; |
|
702 FindTopicByNumberL( number, topic ); |
|
703 |
|
704 // Decrease the counter |
|
705 topic.iUnreadMessages--; |
|
706 |
|
707 // Decrease the counter in cache |
|
708 TInt position = TopicIndexInList( topic.iNumber ); |
|
709 iTopics->At( position ).iTopicData.iUnreadMessages--; |
|
710 |
|
711 // Write topic information to topic stream but leave changes uncommited. |
|
712 UpdateTopicCountersL( topic, EFalse ); |
|
713 |
|
714 __TEST_INVARIANT; |
|
715 |
|
716 CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicList::InformUnreadMessageReadL()"); |
|
717 } |
|
718 |
|
719 // ----------------------------------------------------------------------------- |
|
720 // CCbsDbImpTopicList::InformMessageDeletedL |
|
721 // Informs that an unread message has been deleted. |
|
722 // Updates the counters when a message is deleted. |
|
723 // Note: leaves changes in stores uncommited. |
|
724 // (other items were commented in a header). |
|
725 // ----------------------------------------------------------------------------- |
|
726 // |
|
727 void CCbsDbImpTopicList::InformMessageDeletedL( |
|
728 const TCbsDbMessageHandle& aMessageHandle, |
|
729 TBool aPermanent, |
|
730 TBool aRead ) |
|
731 { |
|
732 // Find topic by handle. |
|
733 TCbsDbTopicNumber number( ExtractTopicNumber( aMessageHandle ) ); |
|
734 |
|
735 TCbsDbTopic topic; |
|
736 FindTopicByNumberL( number, topic ); |
|
737 |
|
738 TInt position = TopicIndexInList( topic.iNumber ); |
|
739 |
|
740 if ( aPermanent ) |
|
741 { |
|
742 topic.iSavedMessages--; |
|
743 iTopics->At( position ).iTopicData.iSavedMessages--; |
|
744 } |
|
745 |
|
746 if ( !aRead ) |
|
747 { |
|
748 topic.iUnreadMessages--; |
|
749 iTopics->At( position ).iTopicData.iUnreadMessages--; |
|
750 } |
|
751 |
|
752 // Write topic information to topic stream but leave changes uncommited. |
|
753 UpdateTopicCountersL( topic, ETrue ); |
|
754 } |
|
755 |
|
756 // ----------------------------------------------------------------------------- |
|
757 // CCbsDbImpTopicList::TotalSavedMessages |
|
758 // Returns the number of saved messages in the current topic list. |
|
759 // (other items were commented in a header). |
|
760 // ----------------------------------------------------------------------------- |
|
761 // |
|
762 TInt CCbsDbImpTopicList::TotalSavedMessages() const |
|
763 { |
|
764 // Return the total amount of saved messages. |
|
765 TInt count( 0 ); |
|
766 for ( TInt i( 0 ); i < iTopics->Count(); i++ ) |
|
767 { |
|
768 count += iTopics->At( i ).iTopicData.iSavedMessages; |
|
769 } |
|
770 |
|
771 return count; |
|
772 } |
|
773 |
|
774 // ----------------------------------------------------------------------------- |
|
775 // CCbsDbImpTopicList::GetTopicCount |
|
776 // Returns the number of topic stored in this topic list. |
|
777 // (other items were commented in a header). |
|
778 // ----------------------------------------------------------------------------- |
|
779 // |
|
780 void CCbsDbImpTopicList::GetTopicCount( |
|
781 TInt& aCount ) const |
|
782 { |
|
783 // Return the total amount of topics. |
|
784 aCount = TopicCount(); |
|
785 } |
|
786 |
|
787 // ----------------------------------------------------------------------------- |
|
788 // CCbsDbImpTopicList::InitializeListL |
|
789 // Initializes the whole topic list. |
|
790 // Creates and opens the topic list file, |
|
791 // invalidates the cache and informs the observers. |
|
792 // (other items were commented in a header). |
|
793 // ----------------------------------------------------------------------------- |
|
794 // |
|
795 void CCbsDbImpTopicList::InitializeListL( const TBool aFileOpenFailed ) |
|
796 { |
|
797 __TEST_INVARIANT; |
|
798 |
|
799 if ( !aFileOpenFailed ) |
|
800 { |
|
801 // Check for file lock |
|
802 CheckFileLockL(); |
|
803 } |
|
804 |
|
805 // About to write to FFS: make critical level check |
|
806 CbsUtils::FFSCriticalLevelCheckL( 0, iFs ); |
|
807 |
|
808 if ( iMessages != NULL && iMessages->IsLockedMessages() ) |
|
809 { |
|
810 User::Leave( KErrAccessDenied ); |
|
811 } |
|
812 |
|
813 // If only one topic list exists, just delete and recreate the whole file |
|
814 if ( iTopicLists->Count() == 1 || aFileOpenFailed == 1 ) |
|
815 { |
|
816 delete iTopicStore; |
|
817 iTopicStore = NULL; |
|
818 delete iUnsavedMessageStore; |
|
819 iUnsavedMessageStore = NULL; |
|
820 CbsUtils::DeleteFileL( iFs, *iTopicsFilename ); |
|
821 CbsUtils::DeleteFileL( iFs, *iUnsavedMessagesFilename ); |
|
822 |
|
823 iTopicLists->Reset(); |
|
824 |
|
825 // Create new files. |
|
826 OpenFilesL( EFalse, ETrue ); |
|
827 } |
|
828 |
|
829 iIsHotmarkedMessage = EFalse; |
|
830 iLastTopicNumber = 0; |
|
831 iMessageHandle = 0; |
|
832 |
|
833 // Inform the message manager. |
|
834 if ( iMessages ) |
|
835 { |
|
836 iMessages->InvalidateCache(); |
|
837 } |
|
838 |
|
839 // Notify everyone. |
|
840 NotifyTopicListInitializedL(); |
|
841 |
|
842 __TEST_INVARIANT; |
|
843 } |
|
844 |
|
845 // ----------------------------------------------------------------------------- |
|
846 // CCbsDbImpTopicList::GetTopicL |
|
847 // Returns a topic matching the given index. |
|
848 // (other items were commented in a header). |
|
849 // ----------------------------------------------------------------------------- |
|
850 // |
|
851 void CCbsDbImpTopicList::GetTopicL( |
|
852 TInt aIndex, |
|
853 TCbsDbTopic& aTopic ) |
|
854 { |
|
855 CBSLOGSTRING("CBSSERVER: >>> CCbsDbImpTopicList::GetTopicL()"); |
|
856 |
|
857 __TEST_INVARIANT; |
|
858 |
|
859 // Check that aIndex is in proper range. |
|
860 if ( ( aIndex < 0 ) || ( aIndex >= iTopics->Count() ) ) |
|
861 { |
|
862 CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicList::GetTopicL(): Leaving with KErrArgument..."); |
|
863 User::Leave( KErrArgument ); |
|
864 } |
|
865 |
|
866 // And then get the information from the array. |
|
867 aTopic = iTopics->At( aIndex ).iTopicData; |
|
868 |
|
869 CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicList::GetTopicL()"); |
|
870 |
|
871 __TEST_INVARIANT; |
|
872 } |
|
873 |
|
874 // ----------------------------------------------------------------------------- |
|
875 // CCbsDbImpTopicList::FindTopicByNumberL |
|
876 // Returns a topic matching the given topic number |
|
877 // (in GSM Specs this is called the Message Identifier) |
|
878 // (other items were commented in a header). |
|
879 // ----------------------------------------------------------------------------- |
|
880 // |
|
881 void CCbsDbImpTopicList::FindTopicByNumberL( |
|
882 TCbsDbTopicNumber aNumber, |
|
883 TCbsDbTopic& aTopic ) |
|
884 { |
|
885 CBSLOGSTRING("CBSSERVER: >>> CCbsDbImpTopicList::FindTopicByNumberL()"); |
|
886 |
|
887 __TEST_INVARIANT; |
|
888 |
|
889 TInt topicIndex( TopicIndexInList( aNumber ) ); |
|
890 CBSLOGSTRING2("CBSSERVER: CCbsDbImpTopicList::FindTopicByNumberL(): Leaving if topicIndex < 0: topicIndex: %d.", topicIndex ); |
|
891 User::LeaveIfError( topicIndex ); |
|
892 |
|
893 GetTopicL( topicIndex, aTopic ); |
|
894 |
|
895 CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicList::FindTopicByNumberL()"); |
|
896 |
|
897 __TEST_INVARIANT; |
|
898 } |
|
899 |
|
900 // ----------------------------------------------------------------------------- |
|
901 // CCbsDbImpTopicList::AddTopicL |
|
902 // Adds a new topic to the list. |
|
903 // (other items were commented in a header). |
|
904 // ----------------------------------------------------------------------------- |
|
905 // |
|
906 void CCbsDbImpTopicList::AddTopicL( |
|
907 TCbsDbTopic& aTopic, const TBool aDetected ) |
|
908 { |
|
909 __TEST_INVARIANT; |
|
910 |
|
911 // Check for file lock |
|
912 CheckFileLockL(); |
|
913 |
|
914 // Check that topic number is in proper range |
|
915 if ( !CheckTopicNumber( aTopic.iNumber ) ) |
|
916 { |
|
917 User::Leave( KErrArgument ); |
|
918 } |
|
919 |
|
920 // Check if there is a topic with the |
|
921 // same topic number in current topic list. |
|
922 if ( TopicIndexInList( aTopic.iNumber ) != KErrNotFound ) |
|
923 { |
|
924 User::Leave( KErrAlreadyExists ); |
|
925 } |
|
926 |
|
927 // There should not be any saved or unread messages |
|
928 aTopic.iSavedMessages = 0; |
|
929 aTopic.iUnreadMessages = 0; |
|
930 |
|
931 // Variated feature. Also, only topics that were not detected automatically |
|
932 // are subscribed by default. |
|
933 if ( iLVBits & KCbsLVFlagTopicSubscription && !aDetected ) |
|
934 { |
|
935 aTopic.iSubscribed = ETrue; |
|
936 } |
|
937 else |
|
938 { |
|
939 aTopic.iSubscribed = EFalse; |
|
940 } |
|
941 |
|
942 // Now we have the handle, so let's add the topic. |
|
943 TRAPD( error, DoAddTopicL( aTopic ) ); |
|
944 if ( error != KErrNone ) |
|
945 { |
|
946 RevertFilesL(); |
|
947 __TEST_INVARIANT; |
|
948 User::Leave( error ); |
|
949 } |
|
950 else |
|
951 { |
|
952 iLastTopicNumber = aTopic.iNumber; |
|
953 NotifyTopicAddedL( aTopic.iNumber ); |
|
954 } |
|
955 |
|
956 __TEST_INVARIANT; |
|
957 } |
|
958 |
|
959 // ----------------------------------------------------------------------------- |
|
960 // CCbsDbImpTopicList::UpdateTopicNameAndNumberL |
|
961 // Updates the name and the topic number of a topic |
|
962 // matching the given handle to the database. |
|
963 // (other items were commented in a header). |
|
964 // ----------------------------------------------------------------------------- |
|
965 // |
|
966 void CCbsDbImpTopicList::UpdateTopicNameAndNumberL( |
|
967 TCbsDbTopicNumber aOldNumber, |
|
968 TCbsDbTopicNumber aNewNumber, |
|
969 const TCbsDbTopicName& aName ) |
|
970 { |
|
971 // Check for file lock |
|
972 CheckFileLockL(); |
|
973 |
|
974 // First, check that the new number is ok. |
|
975 if ( !CheckTopicNumber( aNewNumber ) ) |
|
976 { |
|
977 User::Leave( KErrArgument ); |
|
978 } |
|
979 |
|
980 // First find and then update. |
|
981 TCbsDbTopic topic; |
|
982 FindTopicByNumberL( aOldNumber, topic ); |
|
983 |
|
984 // If no changes to topic, no need to update |
|
985 if ( !( aOldNumber == aNewNumber && topic.iName == aName ) ) |
|
986 { |
|
987 if ( topic.iProtected ) |
|
988 { |
|
989 User::Leave( KErrAccessDenied ); |
|
990 } |
|
991 |
|
992 topic.iName = aName; |
|
993 topic.iNumber = aNewNumber; |
|
994 |
|
995 UpdateTopicL( aOldNumber, topic ); |
|
996 } |
|
997 } |
|
998 |
|
999 // ----------------------------------------------------------------------------- |
|
1000 // CCbsDbImpTopicList::UpdateTopicSubscriptionStatusL |
|
1001 // Updates the new topic subscription status to the database. |
|
1002 // (other items were commented in a header). |
|
1003 // ----------------------------------------------------------------------------- |
|
1004 // |
|
1005 void CCbsDbImpTopicList::UpdateTopicSubscriptionStatusL( |
|
1006 TCbsDbTopicNumber aNumber, |
|
1007 TBool aStatus ) |
|
1008 { |
|
1009 __TEST_INVARIANT; |
|
1010 |
|
1011 // Update topic subsciption status. |
|
1012 TCbsDbTopic topic; |
|
1013 FindTopicByNumberL( aNumber, topic ); |
|
1014 |
|
1015 topic.iSubscribed = aStatus; |
|
1016 UpdateTopicL( aNumber, topic ); |
|
1017 __TEST_INVARIANT; |
|
1018 |
|
1019 } |
|
1020 |
|
1021 // ----------------------------------------------------------------------------- |
|
1022 // CCbsDbImpTopicList::UpdateTopicHotmarkStatusL |
|
1023 // Updates the new topic hotmarking status to the database. |
|
1024 // (other items were commented in a header). |
|
1025 // ----------------------------------------------------------------------------- |
|
1026 // |
|
1027 void CCbsDbImpTopicList::UpdateTopicHotmarkStatusL( |
|
1028 TCbsDbTopicNumber aNumber, |
|
1029 TBool aStatus ) |
|
1030 { |
|
1031 __TEST_INVARIANT; |
|
1032 |
|
1033 // Check for file lock |
|
1034 CheckFileLockL(); |
|
1035 |
|
1036 // Update topic hotmark status. |
|
1037 TCbsDbTopic topic; |
|
1038 FindTopicByNumberL( aNumber, topic ); |
|
1039 |
|
1040 topic.iHotmarked = aStatus; |
|
1041 UpdateTopicL( aNumber, topic ); |
|
1042 __TEST_INVARIANT; |
|
1043 } |
|
1044 |
|
1045 // ----------------------------------------------------------------------------- |
|
1046 // CCbsDbImpTopicList::DeleteTopicL |
|
1047 // Deletes an existing topic and all its messages. |
|
1048 // (other items were commented in a header). |
|
1049 // ----------------------------------------------------------------------------- |
|
1050 // |
|
1051 void CCbsDbImpTopicList::DeleteTopicL( |
|
1052 TCbsDbTopicNumber aNumber ) |
|
1053 { |
|
1054 __TEST_INVARIANT; |
|
1055 |
|
1056 // Try to find the position. If it is not found, leave. |
|
1057 TInt position( TopicIndexInList( aNumber ) ); |
|
1058 User::LeaveIfError( position ); |
|
1059 |
|
1060 // Check that there are no locked messages in the topic. |
|
1061 if ( iMessages->IsLockedMessagesInTopic( aNumber ) ) |
|
1062 { |
|
1063 User::Leave( KErrAccessDenied ); |
|
1064 } |
|
1065 |
|
1066 // Topic only in one topic list, not an index topic, so delete the topic. |
|
1067 if ( aNumber != 0 ) |
|
1068 { |
|
1069 // Just try to delete |
|
1070 TRAPD( error, DoDeleteTopicL( position ) ); |
|
1071 if ( error != KErrNone ) |
|
1072 { |
|
1073 // It failed, so we must revert. |
|
1074 RevertFilesL(); |
|
1075 |
|
1076 // Inform the topic messages. |
|
1077 iMessages->InvalidateCacheIfTopic( aNumber ); |
|
1078 |
|
1079 __TEST_INVARIANT; |
|
1080 User::Leave( error ); |
|
1081 } |
|
1082 else |
|
1083 { |
|
1084 // Notify the observers |
|
1085 NotifyTopicDeletedL( aNumber ); |
|
1086 } |
|
1087 } |
|
1088 __TEST_INVARIANT; |
|
1089 } |
|
1090 |
|
1091 // ----------------------------------------------------------------------------- |
|
1092 // CCbsDbImpTopicList::GetUnreadMessageCount |
|
1093 // Gets the total amount of unread messages. |
|
1094 // (other items were commented in a header). |
|
1095 // ----------------------------------------------------------------------------- |
|
1096 // |
|
1097 void CCbsDbImpTopicList::GetUnreadMessageCount( |
|
1098 TInt& aCount ) const |
|
1099 { |
|
1100 CBSLOGSTRING("CBSSERVER: >>> CCbsDbImpTopicList::GetUnreadMessageCount()"); |
|
1101 CBSLOGSTRING2("CBSSERVER: CCbsDbImpTopicList::GetUnreadMessageCount(): Topic count: %d", iTopics->Count() ); |
|
1102 |
|
1103 // Return the total amount of unread messages. |
|
1104 TInt count( 0 ); |
|
1105 for ( TInt i( 0 ); i < iTopics->Count(); i++ ) |
|
1106 { |
|
1107 count += iTopics->At( i ).iTopicData.iUnreadMessages; |
|
1108 } |
|
1109 |
|
1110 aCount = count; |
|
1111 |
|
1112 CBSLOGSTRING2("CBSSERVER: CCbsDbImpTopicList::GetUnreadMessageCount(): Unread msgs found: %d", count ); |
|
1113 CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicList::GetUnreadMessageCount()"); |
|
1114 } |
|
1115 |
|
1116 // ----------------------------------------------------------------------------- |
|
1117 // CCbsDbImpTopicList::GetHotmarkedMessageHandleL |
|
1118 // Returns the handle to the latest hotmarked message. |
|
1119 // (other items were commented in a header). |
|
1120 // ----------------------------------------------------------------------------- |
|
1121 // |
|
1122 void CCbsDbImpTopicList::GetHotmarkedMessageHandleL( |
|
1123 TCbsDbMessageHandle& aMessage ) |
|
1124 { |
|
1125 __TEST_INVARIANT; |
|
1126 |
|
1127 // Check if there is a hotmarked message. |
|
1128 if ( iIsHotmarkedMessage ) |
|
1129 { |
|
1130 // If there is, then return it. |
|
1131 aMessage = iMessageHandle; |
|
1132 iIsHotmarkedMessage = EFalse; |
|
1133 } |
|
1134 else |
|
1135 { |
|
1136 // Otherwise leave. |
|
1137 __TEST_INVARIANT; |
|
1138 User::Leave( KErrNotFound ); |
|
1139 } |
|
1140 __TEST_INVARIANT; |
|
1141 } |
|
1142 |
|
1143 // ----------------------------------------------------------------------------- |
|
1144 // CCbsDbImpTopicList::UnreadHotmarkedMessageCount |
|
1145 // Returns the handle to the latest hotmarked message. |
|
1146 // (other items were commented in a header). |
|
1147 // ----------------------------------------------------------------------------- |
|
1148 // |
|
1149 TInt CCbsDbImpTopicList::UnreadHotmarkedMessageCount() const |
|
1150 { |
|
1151 // Return the total amount of unread messages in hotmarked topics. |
|
1152 TInt count( 0 ); |
|
1153 for ( TInt i( 0 ); i < iTopics->Count(); i++ ) |
|
1154 { |
|
1155 TCbsDbTopic& topic = iTopics->At( i ).iTopicData; |
|
1156 if ( topic.iHotmarked ) |
|
1157 { |
|
1158 count += topic.iUnreadMessages; |
|
1159 } |
|
1160 } |
|
1161 return count; |
|
1162 } |
|
1163 |
|
1164 // ----------------------------------------------------------------------------- |
|
1165 // CCbsDbImpTopicList::AddObserverL |
|
1166 // Adds a topic list observer. |
|
1167 // After an observer is added to the topic list, |
|
1168 // it will be notified whenever an event occurs. |
|
1169 // (other items were commented in a header). |
|
1170 // ----------------------------------------------------------------------------- |
|
1171 // |
|
1172 void CCbsDbImpTopicList::AddObserverL( |
|
1173 MCbsDbTopicListObserver* aObserver ) |
|
1174 { |
|
1175 __ASSERT_DEBUG( aObserver != 0, CbsServerPanic( ECbsObserverNull ) ); |
|
1176 iObservers->AppendL( aObserver ); |
|
1177 } |
|
1178 |
|
1179 // ----------------------------------------------------------------------------- |
|
1180 // CCbsDbImpTopicList::RemoveObserver |
|
1181 // Removes a topic list observer. |
|
1182 // If aObserver is not in the list, the method will panic. |
|
1183 // (other items were commented in a header). |
|
1184 // ----------------------------------------------------------------------------- |
|
1185 // |
|
1186 void CCbsDbImpTopicList::RemoveObserver( |
|
1187 const MCbsDbTopicListObserver* aObserver ) |
|
1188 { |
|
1189 __TEST_INVARIANT; |
|
1190 __ASSERT_DEBUG( aObserver != 0, CbsServerPanic( ECbsObserverNull ) ); |
|
1191 |
|
1192 TBool observerFound( EFalse ); |
|
1193 TInt amountOfObservers( iObservers->Count() ); |
|
1194 |
|
1195 // Check if the observer exists and |
|
1196 // find its possible location index in the array. |
|
1197 for ( TInt index( 0 ); ( index < amountOfObservers ) && !observerFound; index++ ) |
|
1198 { |
|
1199 if ( aObserver == iObservers->At( index ) ) |
|
1200 { |
|
1201 iObservers->Delete( index ); |
|
1202 observerFound = ETrue; |
|
1203 } |
|
1204 } |
|
1205 |
|
1206 __TEST_INVARIANT; |
|
1207 |
|
1208 #ifdef _DEBUG |
|
1209 if ( !observerFound ) |
|
1210 { |
|
1211 CbsServerPanic( ECbsObserverNotFound ); |
|
1212 } |
|
1213 #endif |
|
1214 |
|
1215 } |
|
1216 |
|
1217 // ----------------------------------------------------------------------------- |
|
1218 // CCbsDbImpTopicList::TopicIndexInList |
|
1219 // Finds the index of the topic matching the given topic number |
|
1220 // in the topic list. |
|
1221 // (other items were commented in a header). |
|
1222 // ----------------------------------------------------------------------------- |
|
1223 // |
|
1224 TInt CCbsDbImpTopicList::TopicIndexInList( |
|
1225 TCbsDbTopicNumber aNumber ) const |
|
1226 { |
|
1227 // Create a TCbsDbImpTopic to compare against and use a binary search. |
|
1228 TKeyArrayFix key( _FOFF( TCbsDbImpTopic, iTopicData.iNumber ), ECmpTUint16 ); |
|
1229 TCbsDbImpTopic dummy; |
|
1230 TInt position; |
|
1231 |
|
1232 dummy.iTopicData.iNumber = aNumber; |
|
1233 TInt result( iTopics->FindIsq( dummy, key, position ) ); |
|
1234 |
|
1235 if ( result != KErrNone ) |
|
1236 { |
|
1237 position = KErrNotFound; |
|
1238 } |
|
1239 |
|
1240 return position; |
|
1241 } |
|
1242 |
|
1243 // ----------------------------------------------------------------------------- |
|
1244 // CCbsDbImpTopicList::GetNextAndPrevTopicNumberL |
|
1245 // Retrieves numbers of topics that precede and succeed the topic |
|
1246 // with number aCurrentTopic. |
|
1247 // (other items were commented in a header). |
|
1248 // ----------------------------------------------------------------------------- |
|
1249 // |
|
1250 void CCbsDbImpTopicList::GetNextAndPrevTopicNumberL( |
|
1251 const TCbsTopicNumber& aCurrentTopic, |
|
1252 TCbsTopicNumber& aNextTopic, |
|
1253 TCbsTopicNumber& aPrevTopic, |
|
1254 TInt& aPosition ) |
|
1255 { |
|
1256 // Determine position of requested topic in topic list. |
|
1257 TInt index( TopicIndexInList( aCurrentTopic ) ); |
|
1258 User::LeaveIfError( index ); // if KErrNotFound |
|
1259 |
|
1260 // Determine position indications |
|
1261 aPosition = 0; |
|
1262 if ( index == 0 ) |
|
1263 { |
|
1264 aPosition |= ECbsHead; |
|
1265 } |
|
1266 else |
|
1267 { |
|
1268 aPrevTopic = iTopics->At( index-1 ).iTopicData.iNumber; |
|
1269 } |
|
1270 |
|
1271 if ( index == iTopics->Count()-1 ) |
|
1272 { |
|
1273 aPosition |= ECbsTail; |
|
1274 } |
|
1275 else |
|
1276 { |
|
1277 aNextTopic = iTopics->At( index+1 ).iTopicData.iNumber; |
|
1278 } |
|
1279 } |
|
1280 |
|
1281 // ----------------------------------------------------------------------------- |
|
1282 // CCbsDbImpTopicList::NotifyNewMessageArrivedL |
|
1283 // Notifies each observer that a new message has arrived to a topic. |
|
1284 // (other items were commented in a header). |
|
1285 // ----------------------------------------------------------------------------- |
|
1286 // |
|
1287 void CCbsDbImpTopicList::NotifyNewMessageArrivedL( |
|
1288 const TCbsDbMessageHandle& aHandle ) |
|
1289 { |
|
1290 // Notify each observer. |
|
1291 TInt count( iObservers->Count() ); |
|
1292 for ( TInt index( 0 ); index < count; index++ ) |
|
1293 { |
|
1294 iObservers->At( index )->TopicNewMessageReceivedIndL( aHandle ); |
|
1295 } |
|
1296 } |
|
1297 |
|
1298 // ----------------------------------------------------------------------------- |
|
1299 // CCbsDbImpTopicList::AppendSubscribedTopicsL |
|
1300 // Adds numbers of subscribed topics to the given array. |
|
1301 // (other items were commented in a header). |
|
1302 // ----------------------------------------------------------------------------- |
|
1303 // |
|
1304 void CCbsDbImpTopicList::AppendSubscribedTopicsL( |
|
1305 CArrayFixFlat<TUint16>& aSubscriptions ) const |
|
1306 { |
|
1307 TInt count( iTopics->Count() ); |
|
1308 for ( TInt i( 0 ); i < count; i++ ) |
|
1309 { |
|
1310 TCbsDbImpTopic& topic = iTopics->At( i ); |
|
1311 if ( topic.iTopicData.iSubscribed ) |
|
1312 { |
|
1313 aSubscriptions.AppendL( topic.iTopicData.iNumber ); |
|
1314 } |
|
1315 } |
|
1316 } |
|
1317 |
|
1318 // ----------------------------------------------------------------------------- |
|
1319 // CCbsDbImpTopicList::LoadRootStreamL |
|
1320 // Loads the root stream to the memory. |
|
1321 // (other items were commented in a header). |
|
1322 // ----------------------------------------------------------------------------- |
|
1323 // |
|
1324 void CCbsDbImpTopicList::LoadRootStreamL() |
|
1325 { |
|
1326 __ASSERT_DEBUG( iTopicLists != NULL, |
|
1327 CbsServerPanic( ECbsTopicListArrayNull ) ); |
|
1328 |
|
1329 // Get the root stream and open it. |
|
1330 TStreamId id( TopicStoreL()->Root() ); |
|
1331 RStoreReadStream instream; |
|
1332 instream.OpenLC( *TopicStoreL(), id ); // on CS |
|
1333 |
|
1334 // Load the topic list count |
|
1335 TInt topicListCount( instream.ReadInt16L() ); |
|
1336 |
|
1337 // Sanity check |
|
1338 if ( topicListCount < 0 ) |
|
1339 { |
|
1340 User::Leave( KErrCorrupt ); |
|
1341 } |
|
1342 |
|
1343 // Reset the topic list array |
|
1344 iTopicLists->Reset(); |
|
1345 |
|
1346 // Load the topic list information |
|
1347 TCbsDbImpTopicList item; |
|
1348 instream >> item.iTopicListId; |
|
1349 ReadTopicListInformationL( item.iTopicListId, item ); |
|
1350 iTopicLists->AppendL( item ); |
|
1351 |
|
1352 // Destroy the stream. |
|
1353 CleanupStack::PopAndDestroy(); // instream |
|
1354 } |
|
1355 |
|
1356 // ----------------------------------------------------------------------------- |
|
1357 // CCbsDbImpTopicList::LoadDefaultTopicStreamL |
|
1358 // Loads the default topic list to the memory. |
|
1359 // (other items were commented in a header). |
|
1360 // ----------------------------------------------------------------------------- |
|
1361 // |
|
1362 void CCbsDbImpTopicList::LoadDefaultTopicStreamL() |
|
1363 { |
|
1364 __ASSERT_DEBUG( iTopics != NULL, |
|
1365 CbsServerPanic( ECbsTopicListArrayNull ) ); |
|
1366 |
|
1367 // Read root item count |
|
1368 TInt topicListCount = iTopicLists->Count(); |
|
1369 |
|
1370 // If there isn't any, create a topic list for standard topics here |
|
1371 if ( topicListCount == 0 ) |
|
1372 { |
|
1373 CreateStandardTopicListL(); |
|
1374 topicListCount = iTopicLists->Count(); |
|
1375 } |
|
1376 |
|
1377 TStreamId defaultTopicListId( 0 ); |
|
1378 TBool quitSearch( EFalse ); |
|
1379 |
|
1380 TInt i; |
|
1381 // Find the default topic list |
|
1382 for ( i = 0; ( i < topicListCount ) && !quitSearch; ++i ) |
|
1383 { |
|
1384 if ( iTopicLists->At( i ).iIsDefaultTopicList ) |
|
1385 { |
|
1386 defaultTopicListId = iTopicLists->At( i ).iTopicListId; |
|
1387 quitSearch = ETrue; |
|
1388 } |
|
1389 } |
|
1390 |
|
1391 CArrayFixFlat< TStreamId >* topicIds = |
|
1392 new ( ELeave ) CArrayFixFlat< TStreamId >( KTopicIdsGranularity ); |
|
1393 |
|
1394 // Open the default topic list stream |
|
1395 RStoreReadStream instream; |
|
1396 instream.OpenLC( *TopicStoreL(), defaultTopicListId ); // on CS |
|
1397 |
|
1398 // Set the ID |
|
1399 iCurrentTopicList.iTopicListId = defaultTopicListId; |
|
1400 |
|
1401 // Set the name |
|
1402 HBufC* topicListName = HBufC::NewL( instream, KCbsDbTopicNameLength ); |
|
1403 iCurrentTopicList.iTopicListName.Copy( topicListName->Des() ); |
|
1404 delete topicListName; |
|
1405 topicListName = NULL; |
|
1406 |
|
1407 // Skip default list status, since it is always true in default topic list |
|
1408 CbsStreamHelper::ReadBoolL( instream ); |
|
1409 iCurrentTopicList.iIsDefaultTopicList = ETrue; |
|
1410 |
|
1411 // Set the topic list number |
|
1412 iCurrentTopicList.iNumber = instream.ReadInt16L(); |
|
1413 |
|
1414 // Read the amount of topics |
|
1415 TInt topicCount = instream.ReadInt16L(); |
|
1416 iCurrentTopicList.iTopicCount = topicCount; |
|
1417 |
|
1418 // Clear the topic array. |
|
1419 iTopics->ResizeL( 0 ); |
|
1420 |
|
1421 TStreamId id( 0 ); |
|
1422 |
|
1423 // Load the topic IDs |
|
1424 for ( i = 0; i < topicCount; i++ ) |
|
1425 { |
|
1426 instream >> id; |
|
1427 topicIds->AppendL( id ); |
|
1428 } |
|
1429 |
|
1430 // Destroy the stream. |
|
1431 CleanupStack::PopAndDestroy(); |
|
1432 |
|
1433 // Load necessary information for each topic |
|
1434 TInt count = topicIds->Count(); |
|
1435 TCbsDbImpTopic topic; |
|
1436 for ( i = 0; i < count; i++ ) |
|
1437 { |
|
1438 ReadTopicInformationL( topicIds->At( i ), topic ); |
|
1439 |
|
1440 if ( topic.iTopicData.iNumber == KIndexTopicNumber ) |
|
1441 { |
|
1442 HBufC* indexName = ReadIndexTopicNameLC(); // on CS |
|
1443 topic.iTopicData.iName.Copy( *indexName ); |
|
1444 CleanupStack::PopAndDestroy(); // indexName |
|
1445 } |
|
1446 |
|
1447 iTopics->AppendL( topic ); |
|
1448 } |
|
1449 delete topicIds; |
|
1450 topicIds = NULL; |
|
1451 } |
|
1452 |
|
1453 // ----------------------------------------------------------------------------- |
|
1454 // CCbsDbImpTopicList::ReadTopicListInformationL |
|
1455 // Reads topic list information from stream. |
|
1456 // (other items were commented in a header). |
|
1457 // ----------------------------------------------------------------------------- |
|
1458 // |
|
1459 void CCbsDbImpTopicList::ReadTopicListInformationL( |
|
1460 const TStreamId& aId, |
|
1461 TCbsDbImpTopicList& aTopicList ) const |
|
1462 { |
|
1463 RStoreReadStream instream; |
|
1464 instream.OpenLC( *TopicStoreL(), aId ); // on CS |
|
1465 |
|
1466 // Topic List name |
|
1467 HBufC* topicListName = HBufC::NewL( instream, KCbsDbTopicNameLength ); |
|
1468 aTopicList.iTopicListName.Copy( topicListName->Des() ); |
|
1469 delete topicListName; |
|
1470 topicListName = NULL; |
|
1471 |
|
1472 // Default list status |
|
1473 aTopicList.iIsDefaultTopicList = CbsStreamHelper::ReadBoolL( instream ); |
|
1474 |
|
1475 // Topic List number |
|
1476 aTopicList.iNumber = instream.ReadInt16L(); |
|
1477 |
|
1478 // Topic count of this topic list |
|
1479 aTopicList.iTopicCount = instream.ReadInt16L(); |
|
1480 |
|
1481 CleanupStack::PopAndDestroy(); // instream |
|
1482 } |
|
1483 |
|
1484 // ----------------------------------------------------------------------------- |
|
1485 // CCbsDbImpTopicList::ReadTopicInformationL |
|
1486 // Reads all information on topic found in stream aId |
|
1487 // into aTopic. |
|
1488 // (other items were commented in a header). |
|
1489 // ----------------------------------------------------------------------------- |
|
1490 // |
|
1491 void CCbsDbImpTopicList::ReadTopicInformationL( |
|
1492 const TStreamId& aId, |
|
1493 TCbsDbImpTopic& aTopic ) const |
|
1494 { |
|
1495 RStoreReadStream instream; |
|
1496 instream.OpenLC( *TopicStoreL(), aId ); // on CS |
|
1497 |
|
1498 // Topic ID |
|
1499 aTopic.iTopicId = aId; |
|
1500 |
|
1501 // Read saved messages. |
|
1502 aTopic.iTopicData.iSavedMessages = instream.ReadInt16L(); |
|
1503 |
|
1504 // Read name. |
|
1505 instream >> aTopic.iTopicData.iName; |
|
1506 |
|
1507 // Read topic number (message identifier) |
|
1508 aTopic.iTopicData.iNumber = instream.ReadInt16L(); |
|
1509 |
|
1510 // Read statuses |
|
1511 aTopic.iTopicData.iProtected = CbsStreamHelper::ReadBoolL( instream ); // Protected |
|
1512 aTopic.iTopicData.iSubscribed = CbsStreamHelper::ReadBoolL( instream );// Subscribed |
|
1513 aTopic.iTopicData.iHotmarked = CbsStreamHelper::ReadBoolL( instream ); // Hotmarked |
|
1514 |
|
1515 // Read unread messages count |
|
1516 aTopic.iTopicData.iUnreadMessages = instream.ReadInt16L(); |
|
1517 |
|
1518 // Topic messages' stream ID |
|
1519 instream >> aTopic.iTopicMessagesId; |
|
1520 |
|
1521 // Sanity check |
|
1522 if ( aTopic.iTopicData.iSavedMessages > KCbsDbMaxSavedMessages |
|
1523 || aTopic.iTopicData.iNumber > KCbsMaxValidTopicNumber |
|
1524 || aTopic.iTopicData.iUnreadMessages > KCbsDbMaxReceivedMessages ) |
|
1525 { |
|
1526 User::Leave( KErrCorrupt ); |
|
1527 } |
|
1528 |
|
1529 CleanupStack::PopAndDestroy(); // instream |
|
1530 } |
|
1531 |
|
1532 // ----------------------------------------------------------------------------- |
|
1533 // CCbsDbImpTopicList::DoAddTopicL |
|
1534 // Adds a topic into the database. |
|
1535 // Assumes aTopic is not a duplicate. |
|
1536 // (other items were commented in a header). |
|
1537 // ----------------------------------------------------------------------------- |
|
1538 // |
|
1539 void CCbsDbImpTopicList::DoAddTopicL( |
|
1540 const TCbsDbTopic& aTopic ) |
|
1541 { |
|
1542 // About to write to FFS: make critical level check |
|
1543 CbsUtils::FFSCriticalLevelCheckL( KTopicStreamSize + |
|
1544 KEmptyTopicMessagesStreamSize, iFs ); |
|
1545 |
|
1546 // Generate general information about topic. |
|
1547 TCbsDbImpTopic topic; |
|
1548 topic.iTopicData = aTopic; |
|
1549 |
|
1550 // Write stream for messages. |
|
1551 topic.iTopicMessagesId = |
|
1552 CCbsDbImpTopicMessages::CreateDefaultTopicMessagesStreamL( |
|
1553 *TopicStoreL() ); |
|
1554 |
|
1555 // Create stream for topic information. |
|
1556 RStoreWriteStream outstream; |
|
1557 topic.iTopicId = outstream.CreateLC( *TopicStoreL() ); // on CS |
|
1558 |
|
1559 WriteTopicInformationL( outstream, aTopic, topic.iTopicMessagesId ); |
|
1560 |
|
1561 outstream.CommitL(); |
|
1562 CleanupStack::PopAndDestroy(); // outstream |
|
1563 |
|
1564 // Now, insert the new topic information to the array |
|
1565 TKeyArrayFix key( _FOFF( TCbsDbImpTopic, iTopicData.iNumber ), ECmpTUint16 ); |
|
1566 iTopics->InsertIsqL( topic, key ); |
|
1567 |
|
1568 // Update the topic list stream |
|
1569 UpdateTopicListStreamL( iCurrentTopicList, EFalse ); |
|
1570 |
|
1571 // We have modified only iTopicStore, so if CommitFilesL() leaves, |
|
1572 // we either get all committed or nothing committed. |
|
1573 CommitFilesL(); |
|
1574 } |
|
1575 |
|
1576 // ----------------------------------------------------------------------------- |
|
1577 // CCbsDbImpTopicList::DoUpdateTopicL |
|
1578 // Updates the data for a topic into the database. |
|
1579 // The position of the topic in the list is |
|
1580 // changed if necessary. |
|
1581 // If the position has to be changed, the handles of messages |
|
1582 // contained in the topic have to be changed as well because |
|
1583 // the high word of the handle identifies the topic by it's |
|
1584 // number. |
|
1585 // Please note that standard EPOC DoSomethingL protocol |
|
1586 // is not followed here as this function does NOT commit |
|
1587 // changes made to the store. Instead, the caller must ensure |
|
1588 // use of proper commit/revert operations. |
|
1589 // (other items were commented in a header). |
|
1590 // ----------------------------------------------------------------------------- |
|
1591 // |
|
1592 void CCbsDbImpTopicList::DoUpdateTopicL( |
|
1593 const TCbsDbTopic& aTopic, |
|
1594 TBool aNeedToChange, |
|
1595 TInt aOldPosition, |
|
1596 TBool aDeleting ) |
|
1597 { |
|
1598 CBSLOGSTRING("CBSSERVER: >>> CCbsDbImpTopicList::DoUpdateTopicL()"); |
|
1599 |
|
1600 RSharedDataClient sharedData; |
|
1601 // About to write to FFS: make critical level check |
|
1602 if ( aDeleting ) |
|
1603 { |
|
1604 User::LeaveIfError( sharedData.Connect() ); |
|
1605 sharedData.RequestFreeDiskSpaceLC( KTopicStreamSize ); // on CS |
|
1606 } |
|
1607 else |
|
1608 { |
|
1609 CbsUtils::FFSCriticalLevelCheckL( KTopicStreamSize, iFs ); |
|
1610 } |
|
1611 |
|
1612 TInt newPosition( aOldPosition ); |
|
1613 |
|
1614 // If there is need to change position, change it. |
|
1615 if ( aNeedToChange ) |
|
1616 { |
|
1617 TCbsDbImpTopic topic( iTopics->At( aOldPosition ) ); |
|
1618 |
|
1619 // Adjust handles of topic messages to match the changed topic number. |
|
1620 iMessages->UpdateHandlesOfTopicMessagesL( |
|
1621 topic.iTopicData.iNumber, aTopic.iNumber ); |
|
1622 |
|
1623 // Delete topic from the array. |
|
1624 iTopics->Delete( aOldPosition ); |
|
1625 |
|
1626 // Set the number and reinsert into array |
|
1627 topic.iTopicData.iNumber = aTopic.iNumber; |
|
1628 TKeyArrayFix key( _FOFF( TCbsDbImpTopic, iTopicData.iNumber ), ECmpTUint16 ); |
|
1629 newPosition = iTopics->InsertIsqL( topic, key ); |
|
1630 } |
|
1631 |
|
1632 iTopics->At( newPosition ).iTopicData.iSubscribed = aTopic.iSubscribed; |
|
1633 iTopics->At( newPosition ).iTopicData.iHotmarked = aTopic.iHotmarked; |
|
1634 iTopics->At( newPosition ).iTopicData.iName = aTopic.iName; |
|
1635 iTopics->At( newPosition ).iTopicData.iSavedMessages = aTopic.iSavedMessages; |
|
1636 iTopics->At( newPosition ).iTopicData.iUnreadMessages = aTopic.iUnreadMessages; |
|
1637 |
|
1638 // Replace existing stream. |
|
1639 RStoreWriteStream outstream; |
|
1640 outstream.ReplaceLC( *TopicStoreL(), |
|
1641 iTopics->At( newPosition ).iTopicId ); // on CS |
|
1642 WriteTopicInformationL( outstream, aTopic, |
|
1643 iTopics->At( newPosition ).iTopicMessagesId ); |
|
1644 |
|
1645 outstream.CommitL(); |
|
1646 CleanupStack::PopAndDestroy(); // outstream |
|
1647 |
|
1648 // Free the reserved space |
|
1649 if ( aDeleting ) |
|
1650 { |
|
1651 CleanupStack::PopAndDestroy(); // disk space |
|
1652 sharedData.Close(); |
|
1653 } |
|
1654 |
|
1655 // Update topic list stream, if necessary. |
|
1656 if ( aNeedToChange ) |
|
1657 { |
|
1658 UpdateTopicListStreamL( iCurrentTopicList, EFalse ); |
|
1659 } |
|
1660 |
|
1661 CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicList::DoUpdateTopicL()"); |
|
1662 } |
|
1663 |
|
1664 // ----------------------------------------------------------------------------- |
|
1665 // CCbsDbImpTopicList::DoDeleteTopicL |
|
1666 // Deletes a topic from the given position in the database. |
|
1667 // (other items were commented in a header). |
|
1668 // ----------------------------------------------------------------------------- |
|
1669 // |
|
1670 void CCbsDbImpTopicList::DoDeleteTopicL( |
|
1671 TInt aPosition ) |
|
1672 { |
|
1673 // Check that the topic is not protected. |
|
1674 TCbsDbTopic topic; |
|
1675 GetTopicL( aPosition, topic ); |
|
1676 |
|
1677 // It is not allowed to delete a topic that is protected. It must |
|
1678 // first be updated to be not protected. |
|
1679 if ( topic.iProtected ) |
|
1680 { |
|
1681 User::Leave( KErrAccessDenied ); |
|
1682 } |
|
1683 |
|
1684 // First delete all messages the topic contains. |
|
1685 RStoreReadStream instream; |
|
1686 instream.OpenLC( *TopicStoreL(), |
|
1687 iTopics->At( aPosition ).iTopicMessagesId ); // on CS |
|
1688 CCbsDbImpTopicMessages::DeleteAllTopicMessagesL( *TopicStoreL(), |
|
1689 *iUnsavedMessageStore, instream ); |
|
1690 iMessages->InvalidateCache(); |
|
1691 CleanupStack::PopAndDestroy(); // instream |
|
1692 |
|
1693 // Delete topic and topic messages streams. |
|
1694 TopicStoreL()->DeleteL( iTopics->At( aPosition ).iTopicMessagesId ); |
|
1695 TopicStoreL()->DeleteL( iTopics->At( aPosition ).iTopicId ); |
|
1696 |
|
1697 // Remove from the internal cache. |
|
1698 iTopics->Delete( aPosition ); |
|
1699 |
|
1700 iCurrentTopicList.iTopicCount--; |
|
1701 UpdateTopicListStreamL( iCurrentTopicList, ETrue ); |
|
1702 CommitFilesL(); |
|
1703 } |
|
1704 |
|
1705 // ----------------------------------------------------------------------------- |
|
1706 // CCbsDbImpTopicList::UpdateRootStreamL |
|
1707 // Updates the root stream. |
|
1708 // (other items were commented in a header). |
|
1709 // ----------------------------------------------------------------------------- |
|
1710 // |
|
1711 void CCbsDbImpTopicList::UpdateRootStreamL( |
|
1712 TBool aDeleting ) |
|
1713 { |
|
1714 // Check the free space |
|
1715 TInt neededSpace( KTopicListRootStreamSize + iTopicLists->Count() * 2 ); |
|
1716 |
|
1717 RSharedDataClient sharedData; |
|
1718 // About to write to FFS: make critical level check |
|
1719 if ( aDeleting ) |
|
1720 { |
|
1721 User::LeaveIfError( sharedData.Connect() ); |
|
1722 sharedData.RequestFreeDiskSpaceLC( neededSpace ); // on CS |
|
1723 } |
|
1724 else |
|
1725 { |
|
1726 CbsUtils::FFSCriticalLevelCheckL( neededSpace, iFs ); |
|
1727 } |
|
1728 |
|
1729 // Now there is room for all topics. So we can just replace. |
|
1730 RStoreWriteStream outstream; |
|
1731 outstream.ReplaceLC( *TopicStoreL(), TopicStoreL()->Root() ); // on CS |
|
1732 |
|
1733 // Write root stream |
|
1734 WriteRootStreamL( outstream ); |
|
1735 CleanupStack::PopAndDestroy(); // outstream |
|
1736 |
|
1737 // Free the reserved space |
|
1738 if ( aDeleting ) |
|
1739 { |
|
1740 CleanupStack::PopAndDestroy(); // disk space |
|
1741 sharedData.Close(); |
|
1742 } |
|
1743 } |
|
1744 |
|
1745 // ----------------------------------------------------------------------------- |
|
1746 // CCbsDbImpTopicList::UpdateTopicListStreamL |
|
1747 // Updates topic list stream. |
|
1748 // (other items were commented in a header). |
|
1749 // ----------------------------------------------------------------------------- |
|
1750 // |
|
1751 void CCbsDbImpTopicList::UpdateTopicListStreamL( |
|
1752 TCbsDbImpTopicList& aTopicList, |
|
1753 TBool aDeleting ) |
|
1754 { |
|
1755 TInt neededSpace( KTopicListStreamSize + iTopics->Count() * 2 ); |
|
1756 |
|
1757 RSharedDataClient sharedData; |
|
1758 // About to write to FFS: make critical level check |
|
1759 if ( aDeleting ) |
|
1760 { |
|
1761 User::LeaveIfError( sharedData.Connect() ); |
|
1762 sharedData.RequestFreeDiskSpaceLC( neededSpace ); // on CS |
|
1763 } |
|
1764 else |
|
1765 { |
|
1766 CbsUtils::FFSCriticalLevelCheckL( neededSpace, iFs ); |
|
1767 } |
|
1768 |
|
1769 // Replace the stream |
|
1770 RStoreWriteStream outstream; |
|
1771 outstream.ReplaceLC( *TopicStoreL(), aTopicList.iTopicListId ); // on CS |
|
1772 |
|
1773 // Write root stream |
|
1774 WriteTopicListStreamL( outstream, aTopicList ); |
|
1775 CleanupStack::PopAndDestroy(); // outstream |
|
1776 |
|
1777 // Free the reserved space |
|
1778 if ( aDeleting ) |
|
1779 { |
|
1780 CleanupStack::PopAndDestroy(); // disk space |
|
1781 sharedData.Close(); |
|
1782 } |
|
1783 } |
|
1784 |
|
1785 // ----------------------------------------------------------------------------- |
|
1786 // CCbsDbImpTopicList::UpdateTopicL |
|
1787 // Updates the information for a topic already existing |
|
1788 // in the database. |
|
1789 // (other items were commented in a header). |
|
1790 // ----------------------------------------------------------------------------- |
|
1791 // |
|
1792 void CCbsDbImpTopicList::UpdateTopicL( |
|
1793 TCbsDbTopicNumber aTopicNumber, |
|
1794 TCbsDbTopic& aTopic ) |
|
1795 { |
|
1796 // Check that the new topic number is unique. |
|
1797 TBool needToChangePosition( ETrue ); |
|
1798 |
|
1799 // Try to find the topic and leave if it was not found. |
|
1800 TInt oldPosition( TopicIndexInList( aTopicNumber ) ); |
|
1801 User::LeaveIfError( oldPosition ); |
|
1802 |
|
1803 // Check if we have to change the position of the topic in the |
|
1804 // internal array |
|
1805 if ( aTopic.iNumber == aTopicNumber ) |
|
1806 { |
|
1807 needToChangePosition = EFalse; |
|
1808 } |
|
1809 else |
|
1810 { |
|
1811 TInt topicWithTheNewNumber( TopicIndexInList( aTopic.iNumber ) ); |
|
1812 if ( topicWithTheNewNumber != KErrNotFound && |
|
1813 topicWithTheNewNumber != oldPosition ) |
|
1814 { |
|
1815 User::Leave( KErrAlreadyExists ); |
|
1816 } |
|
1817 } |
|
1818 |
|
1819 // Write data to store. |
|
1820 // Deviation from EPOC standards: DoUpdateTopicL does NOT commit |
|
1821 // the store. |
|
1822 TRAPD( result, DoUpdateTopicL( aTopic, needToChangePosition, |
|
1823 oldPosition, EFalse ) ); |
|
1824 |
|
1825 // Commit both topic and unsaved msgs store |
|
1826 if ( result == KErrNone ) |
|
1827 { |
|
1828 TRAP( result, CommitFilesL() ); |
|
1829 } |
|
1830 |
|
1831 // If either DoUpdateTopicL or CommitFilesL fails => revert. |
|
1832 if ( result != KErrNone ) |
|
1833 { |
|
1834 TopicStoreL()->Revert(); |
|
1835 ReloadRootStreamL(); |
|
1836 User::Leave( result ); |
|
1837 } |
|
1838 else |
|
1839 { |
|
1840 // Notify the observers. |
|
1841 NotifyTopicModifiedL( aTopicNumber ); |
|
1842 } |
|
1843 } |
|
1844 |
|
1845 // ----------------------------------------------------------------------------- |
|
1846 // CCbsDbImpTopicList::CheckTopicNumber |
|
1847 // Checks if a topic number is valid. |
|
1848 // The valid topic number range in this implementation is |
|
1849 // 000..999, with 000 indicating an index message. |
|
1850 // (other items were commented in a header). |
|
1851 // ----------------------------------------------------------------------------- |
|
1852 // |
|
1853 TBool CCbsDbImpTopicList::CheckTopicNumber( |
|
1854 TCbsDbTopicNumber aNumber ) const |
|
1855 { |
|
1856 // Check that the number is in proper range |
|
1857 return aNumber <= KCbsMaxValidTopicNumber; |
|
1858 } |
|
1859 |
|
1860 // ----------------------------------------------------------------------------- |
|
1861 // CCbsDbImpTopicList::WriteRootStreamL |
|
1862 // Write the root stream. |
|
1863 // (other items were commented in a header). |
|
1864 // ----------------------------------------------------------------------------- |
|
1865 // |
|
1866 void CCbsDbImpTopicList::WriteRootStreamL( |
|
1867 RWriteStream& aOut ) const |
|
1868 { |
|
1869 // Write the total amount of topic lists |
|
1870 TInt topicListCount( iTopicLists->Count() ); |
|
1871 aOut.WriteInt16L( topicListCount ); |
|
1872 |
|
1873 // Write space for topic list stream ids |
|
1874 TInt index; |
|
1875 for ( index = 0; index < topicListCount; index++ ) |
|
1876 { |
|
1877 aOut << iTopicLists->At( index ).iTopicListId; |
|
1878 } |
|
1879 |
|
1880 // Write null stream ids |
|
1881 for ( ; index < KCbsRootItemsSize; index++ ) |
|
1882 { |
|
1883 aOut << TStreamId( 0 ); |
|
1884 } |
|
1885 |
|
1886 aOut.CommitL(); |
|
1887 } |
|
1888 |
|
1889 // ----------------------------------------------------------------------------- |
|
1890 // CCbsDbImpTopicList::WriteTopicListStreamL |
|
1891 // Writes topic list information to specified stream. |
|
1892 // (other items were commented in a header). |
|
1893 // ----------------------------------------------------------------------------- |
|
1894 // |
|
1895 void CCbsDbImpTopicList::WriteTopicListStreamL( |
|
1896 RWriteStream& aOut, |
|
1897 TCbsDbImpTopicList& aTopicList ) const |
|
1898 { |
|
1899 // Write the values to this topic list's stream |
|
1900 |
|
1901 // Topic List name |
|
1902 aOut << aTopicList.iTopicListName; |
|
1903 |
|
1904 // Is this the default list |
|
1905 CbsStreamHelper::WriteBoolL( aOut, aTopicList.iIsDefaultTopicList ); |
|
1906 |
|
1907 // Topic List number |
|
1908 aOut.WriteInt16L( aTopicList.iNumber ); |
|
1909 |
|
1910 // NUmber of topics in this list |
|
1911 aOut.WriteInt16L( iTopics->Count() ); |
|
1912 |
|
1913 // Write the stream IDs of the topics belonging to this list |
|
1914 TInt i; |
|
1915 for ( i = 0; i < iTopics->Count(); i++ ) |
|
1916 { |
|
1917 aOut << iTopics->At( i ).iTopicId; |
|
1918 } |
|
1919 |
|
1920 // Write space for the rest topic stream IDs |
|
1921 for ( ; i < KCbsDbTopicArraySize; i++ ) |
|
1922 { |
|
1923 aOut << TStreamId( 0 ); |
|
1924 } |
|
1925 |
|
1926 aOut.CommitL(); |
|
1927 } |
|
1928 |
|
1929 // ----------------------------------------------------------------------------- |
|
1930 // CCbsDbImpTopicList::NotifyTopicListInitializedL |
|
1931 // Notifies each observer that the topic list has been initialized. |
|
1932 // (other items were commented in a header). |
|
1933 // ----------------------------------------------------------------------------- |
|
1934 // |
|
1935 void CCbsDbImpTopicList::NotifyTopicListInitializedL() |
|
1936 { |
|
1937 // Notify each observer. |
|
1938 TInt count( iObservers->Count() ); |
|
1939 for( TInt index( 0 ); index < count; index++ ) |
|
1940 { |
|
1941 iObservers->At( index )->TopicListInitializedIndL(); |
|
1942 } |
|
1943 } |
|
1944 |
|
1945 // ----------------------------------------------------------------------------- |
|
1946 // CCbsDbImpTopicList::NotifyTopicAddedL |
|
1947 // Notifies each observer that a topic has been added. |
|
1948 // (other items were commented in a header). |
|
1949 // ----------------------------------------------------------------------------- |
|
1950 // |
|
1951 void CCbsDbImpTopicList::NotifyTopicAddedL( |
|
1952 TCbsDbTopicNumber aNumber ) |
|
1953 { |
|
1954 // Notify each observer. |
|
1955 TInt count( iObservers->Count() ); |
|
1956 for ( TInt index( 0 ); index < count; index++ ) |
|
1957 { |
|
1958 iObservers->At( index )->TopicAddedIndL( aNumber ); |
|
1959 } |
|
1960 } |
|
1961 |
|
1962 // ----------------------------------------------------------------------------- |
|
1963 // CCbsDbImpTopicList::NotifyTopicModifiedL |
|
1964 // Notifies each observer that a topic has been modified. |
|
1965 // (other items were commented in a header). |
|
1966 // ----------------------------------------------------------------------------- |
|
1967 // |
|
1968 void CCbsDbImpTopicList::NotifyTopicModifiedL( |
|
1969 TCbsDbTopicNumber aNumber ) |
|
1970 { |
|
1971 // Notify each observer. |
|
1972 TInt count( iObservers->Count() ); |
|
1973 for( TInt index( 0 ); index < count; index++ ) |
|
1974 { |
|
1975 iObservers->At( index )->TopicModifiedIndL( aNumber ); |
|
1976 } |
|
1977 } |
|
1978 |
|
1979 // ----------------------------------------------------------------------------- |
|
1980 // CCbsDbImpTopicList::NotifyTopicDeletedL |
|
1981 // Notifies each observer that a topic has been deleted. |
|
1982 // (other items were commented in a header). |
|
1983 // ----------------------------------------------------------------------------- |
|
1984 // |
|
1985 void CCbsDbImpTopicList::NotifyTopicDeletedL( |
|
1986 TCbsDbTopicNumber aNumber ) |
|
1987 { |
|
1988 // Notify each observer. |
|
1989 TInt count( iObservers->Count() ); |
|
1990 for( TInt index( 0 ); index < count; index++ ) |
|
1991 { |
|
1992 iObservers->At( index )->TopicDeletedIndL( aNumber ); |
|
1993 } |
|
1994 } |
|
1995 |
|
1996 // ----------------------------------------------------------------------------- |
|
1997 // CCbsDbImpTopicList::SetHotmarkedMessage |
|
1998 // Sets the hotmarked message handle. |
|
1999 // (other items were commented in a header). |
|
2000 // ----------------------------------------------------------------------------- |
|
2001 // |
|
2002 void CCbsDbImpTopicList::SetHotmarkedMessage( |
|
2003 const TCbsDbMessageHandle& aMessageHandle ) |
|
2004 { |
|
2005 // Set the hotmarked message. |
|
2006 iIsHotmarkedMessage = ETrue; |
|
2007 iMessageHandle = aMessageHandle; |
|
2008 } |
|
2009 |
|
2010 // ----------------------------------------------------------------------------- |
|
2011 // CCbsDbImpTopicList::CreateDefaultRootStreamL |
|
2012 // Creates a root stream and writes default values into it. |
|
2013 // (other items were commented in a header). |
|
2014 // ----------------------------------------------------------------------------- |
|
2015 // |
|
2016 TStreamId CCbsDbImpTopicList::CreateDefaultRootStreamL( |
|
2017 CStreamStore& aStore ) const |
|
2018 { |
|
2019 // Create the stream |
|
2020 RStoreWriteStream outstream; |
|
2021 TStreamId id( outstream.CreateLC( aStore ) ); // on CS |
|
2022 |
|
2023 // Write the amount of topic lists |
|
2024 outstream.WriteInt16L( 0 ); |
|
2025 |
|
2026 // Write space for topic list stream ids |
|
2027 for ( TInt index( 0 ); index < KCbsRootItemsSize; index++ ) |
|
2028 { |
|
2029 outstream << TStreamId( 0 ); |
|
2030 } |
|
2031 |
|
2032 outstream.CommitL(); |
|
2033 CleanupStack::PopAndDestroy(); // aStore |
|
2034 |
|
2035 // Return the stream id. |
|
2036 return id; |
|
2037 } |
|
2038 |
|
2039 // ----------------------------------------------------------------------------- |
|
2040 // CCbsDbImpTopicList::WriteTopicInformationL |
|
2041 // Writes topic data into a stream. |
|
2042 // This includes number of saved messages, |
|
2043 // number of unread messages, topic handle, |
|
2044 // topic name, topic number, protection status, |
|
2045 // subscription status and hotmark status. |
|
2046 // (other items were commented in a header). |
|
2047 // ----------------------------------------------------------------------------- |
|
2048 // |
|
2049 void CCbsDbImpTopicList::WriteTopicInformationL( |
|
2050 RWriteStream& aOut, |
|
2051 const TCbsDbTopic& aTopic, |
|
2052 const TStreamId& aTopicMessagesId ) const |
|
2053 { |
|
2054 // Write saved messages. |
|
2055 aOut.WriteInt16L( aTopic.iSavedMessages ); |
|
2056 |
|
2057 // Write name. |
|
2058 aOut << aTopic.iName; |
|
2059 |
|
2060 // Write topic number (message identifier) |
|
2061 aOut.WriteInt16L( aTopic.iNumber ); |
|
2062 |
|
2063 // Write statuses |
|
2064 CbsStreamHelper::WriteBoolL( aOut, aTopic.iProtected ); // Protected |
|
2065 CbsStreamHelper::WriteBoolL( aOut, aTopic.iSubscribed ); // Subscribed |
|
2066 CbsStreamHelper::WriteBoolL( aOut, aTopic.iHotmarked ); // Hotmarked |
|
2067 |
|
2068 // Write unread messages count |
|
2069 aOut.WriteInt16L( aTopic.iUnreadMessages ); |
|
2070 |
|
2071 // And then write the topic messages stream id. |
|
2072 aOut << aTopicMessagesId; |
|
2073 } |
|
2074 |
|
2075 |
|
2076 // ----------------------------------------------------------------------------- |
|
2077 // CCbsDbImpTopicList::RevertFilesL |
|
2078 // Reverts all changes made to three datafiles handled by this class. |
|
2079 // (other items were commented in a header). |
|
2080 // ----------------------------------------------------------------------------- |
|
2081 // |
|
2082 void CCbsDbImpTopicList::RevertFilesL() |
|
2083 { |
|
2084 |
|
2085 // Check for file lock |
|
2086 CheckFileLockL(); |
|
2087 |
|
2088 iTopicStore->Revert(); |
|
2089 iUnsavedMessageStore->Revert(); |
|
2090 ReloadRootStreamL(); |
|
2091 } |
|
2092 |
|
2093 // ----------------------------------------------------------------------------- |
|
2094 // CCbsDbImpTopicList::CommitFilesL |
|
2095 // Commits all changes made to two datafiles handled by this class. |
|
2096 // (other items were commented in a header). |
|
2097 // ----------------------------------------------------------------------------- |
|
2098 // |
|
2099 void CCbsDbImpTopicList::CommitFilesL() |
|
2100 { |
|
2101 TopicStoreL()->CommitL(); |
|
2102 TInt errorCode( iUnsavedMessageStore->Commit() ); |
|
2103 |
|
2104 // If committing of the unsaved msg store fails, remove all |
|
2105 // messages in the store and rebuild the topic list |
|
2106 if ( errorCode != KErrNone ) |
|
2107 { |
|
2108 TRAPD( errorCode2, RebuildUnsavedMessageStoreL() ); |
|
2109 if ( errorCode2 != KErrNone ) |
|
2110 { |
|
2111 CActiveScheduler::Stop(); |
|
2112 User::Leave( KErrServerTerminated ); |
|
2113 } |
|
2114 |
|
2115 // Tell the caller that something went wrong |
|
2116 User::Leave( errorCode ); |
|
2117 } |
|
2118 |
|
2119 // Check if we should compact |
|
2120 TTime now; |
|
2121 TTimeIntervalMinutes interval; |
|
2122 now.UniversalTime(); |
|
2123 now.MinutesFrom( iPreviousCompact, interval ); |
|
2124 if ( interval.Int() >= KMinimumCompactInterval ) |
|
2125 { |
|
2126 TopicStoreL()->CompactL(); |
|
2127 iUnsavedMessageStore->CompactL(); |
|
2128 iPreviousCompact = now; |
|
2129 } |
|
2130 |
|
2131 } |
|
2132 |
|
2133 // ----------------------------------------------------------------------------- |
|
2134 // CCbsDbImpTopicList::RebuildUnsavedMessageStoreL |
|
2135 // Deletes the unsaved messages' store and rebuilds it. |
|
2136 // (other items were commented in a header). |
|
2137 // ----------------------------------------------------------------------------- |
|
2138 // |
|
2139 void CCbsDbImpTopicList::RebuildUnsavedMessageStoreL() |
|
2140 { |
|
2141 // Close the stores and delete the unsaved store |
|
2142 delete iUnsavedMessageStore; iUnsavedMessageStore = NULL; |
|
2143 delete iTopicStore; iTopicStore = NULL; |
|
2144 CbsUtils::DeleteFileL( iFs, *iUnsavedMessagesFilename ); |
|
2145 |
|
2146 // Re-create the store |
|
2147 DoCreateStoreL( *iUnsavedMessagesFilename ); |
|
2148 TryToOpenFilesL( ETrue, EFalse ); |
|
2149 |
|
2150 // Remove the stream ids to unsaved messages, because |
|
2151 // they were all just deleted. |
|
2152 HandleDeletionOfUnsavedMessagesFileL(); |
|
2153 |
|
2154 // Compact the topic list |
|
2155 TopicStoreL()->CommitL(); |
|
2156 TopicStoreL()->CompactL(); |
|
2157 } |
|
2158 |
|
2159 // ----------------------------------------------------------------------------- |
|
2160 // CCbsDbImpTopicList::RebuildTopicAndUnsavedStoresL |
|
2161 // Deletes and rebuilds topic/topic list and unsaved message stores. |
|
2162 // Loads Standard Topic List into memory. |
|
2163 // (other items were commented in a header). |
|
2164 // ----------------------------------------------------------------------------- |
|
2165 // |
|
2166 void CCbsDbImpTopicList::RebuildTopicAndUnsavedStoresL() |
|
2167 { |
|
2168 __TEST_INVARIANT; |
|
2169 |
|
2170 // Check for file lock |
|
2171 CheckFileLockL(); |
|
2172 |
|
2173 // About to write to FFS: make critical level check |
|
2174 CbsUtils::FFSCriticalLevelCheckL( KTopicListRootStreamSize + |
|
2175 KDefaultTopicListSize * 2, iFs ); |
|
2176 |
|
2177 if ( iMessages != NULL && iMessages->IsLockedMessages() ) |
|
2178 { |
|
2179 User::Leave( KErrAccessDenied ); |
|
2180 } |
|
2181 |
|
2182 delete iTopicStore; |
|
2183 iTopicStore = NULL; |
|
2184 delete iUnsavedMessageStore; |
|
2185 iUnsavedMessageStore = NULL; |
|
2186 CbsUtils::DeleteFileL( iFs, *iTopicsFilename ); |
|
2187 CbsUtils::DeleteFileL( iFs, *iUnsavedMessagesFilename ); |
|
2188 |
|
2189 // Create new files. |
|
2190 OpenFilesL( ETrue, EFalse ); |
|
2191 |
|
2192 // Add standard index topic. |
|
2193 AddIndexTopicL(); |
|
2194 |
|
2195 // Load the Standard Topic list |
|
2196 LoadDefaultTopicStreamL(); |
|
2197 |
|
2198 iIsHotmarkedMessage = EFalse; |
|
2199 iLastTopicNumber = 0; |
|
2200 iMessageHandle = 0; |
|
2201 |
|
2202 // Inform the message manager. |
|
2203 if ( iMessages ) |
|
2204 { |
|
2205 iMessages->InvalidateCache(); |
|
2206 } |
|
2207 |
|
2208 // Notify everyone. |
|
2209 NotifyTopicListInitializedL(); |
|
2210 |
|
2211 __TEST_INVARIANT; |
|
2212 } |
|
2213 |
|
2214 // ----------------------------------------------------------------------------- |
|
2215 // CCbsDbImpTopicList::GetLatestTopicNumber |
|
2216 // Returns the number of the topic that was added last |
|
2217 // to the database by topic detection feature. |
|
2218 // (other items were commented in a header). |
|
2219 // ----------------------------------------------------------------------------- |
|
2220 // |
|
2221 TInt CCbsDbImpTopicList::GetLatestTopicNumber( |
|
2222 TCbsTopicNumber& aNumber ) const |
|
2223 { |
|
2224 TInt result( KErrNone ); |
|
2225 if ( iLastTopicNumber == 0 ) |
|
2226 { |
|
2227 result = KErrNotFound; |
|
2228 } |
|
2229 aNumber = iLastTopicNumber; |
|
2230 return result; |
|
2231 } |
|
2232 |
|
2233 // ----------------------------------------------------------------------------- |
|
2234 // CCbsDbImpTopicList::OpenFilesL |
|
2235 // After a call to this function, the file stores can be assumed |
|
2236 // to be open and initialized. |
|
2237 // (other items were commented in a header). |
|
2238 // ----------------------------------------------------------------------------- |
|
2239 // |
|
2240 void CCbsDbImpTopicList::OpenFilesL( |
|
2241 TBool aDeleteExistingFiles, |
|
2242 TBool aCreateNewTopicList ) |
|
2243 { |
|
2244 __ASSERT_DEBUG( iTopicsFilename->Length() > 0, |
|
2245 CbsServerPanic( ECbsInvalidFilenameDescriptor ) ); |
|
2246 __ASSERT_DEBUG( iUnsavedMessagesFilename->Length() > 0, |
|
2247 CbsServerPanic( ECbsInvalidFilenameDescriptor ) ); |
|
2248 |
|
2249 // if LFS, delete files, create files, open files, write root stream |
|
2250 // if not LFS, create file if it doesn't exist, open files |
|
2251 |
|
2252 // Close file stores. |
|
2253 delete iTopicStore; |
|
2254 iTopicStore = NULL; |
|
2255 delete iUnsavedMessageStore; |
|
2256 iUnsavedMessageStore = NULL; |
|
2257 |
|
2258 // If any of files doesn't exist, create the file. Also writes the root |
|
2259 // stream of the topic file, if necessary. |
|
2260 // It is possible that this operation fails because FFS is full. |
|
2261 // In this case the server will take a break and retry. If the second |
|
2262 // attempt fails, the server is shut down. |
|
2263 TBool unsavedMsgFileExists( EFalse ); |
|
2264 TRAPD( result, CreateFilesIfNecessaryL( unsavedMsgFileExists ) ); |
|
2265 if ( result != KErrNone ) |
|
2266 { |
|
2267 // Critical exception: wait for a while and retry. |
|
2268 User::After( KWaitAfterCriticalStoreException ); |
|
2269 TBool ignoreThis( EFalse ); // value of unsavedMsgFileExists preserved |
|
2270 TRAP( result, CreateFilesIfNecessaryL( ignoreThis ) ); |
|
2271 if ( result != KErrNone ) |
|
2272 { |
|
2273 __DEBUGGER(); |
|
2274 // Recovery is not possible: shut the server down. |
|
2275 CActiveScheduler::Stop(); |
|
2276 User::Leave( KErrServerTerminated ); |
|
2277 } |
|
2278 } |
|
2279 |
|
2280 // Open the files for use. Also reads the topic file root stream. |
|
2281 TryToOpenFilesL( unsavedMsgFileExists == EFalse && |
|
2282 aDeleteExistingFiles == EFalse, |
|
2283 aCreateNewTopicList ); |
|
2284 |
|
2285 } |
|
2286 |
|
2287 // ----------------------------------------------------------------------------- |
|
2288 // CCbsDbImpTopicList::CreateFilesIfNecessaryL |
|
2289 // Creates CBS files, if appropriate. |
|
2290 // (other items were commented in a header). |
|
2291 // ----------------------------------------------------------------------------- |
|
2292 // |
|
2293 void CCbsDbImpTopicList::CreateFilesIfNecessaryL( |
|
2294 TBool& aUnsavedMsgFileExisted ) |
|
2295 { |
|
2296 if ( CbsUtils::ExistsL( iFs, *iTopicsFilename ) == EFalse ) |
|
2297 { |
|
2298 CbsUtils::FFSCriticalLevelCheckL( KTopicListRootStreamSize + |
|
2299 KDefaultTopicListSize * 2, iFs ); |
|
2300 |
|
2301 CPermanentFileStore* store = CPermanentFileStore::CreateLC( iFs, |
|
2302 *iTopicsFilename, EFileWrite ); // on CS |
|
2303 |
|
2304 store->SetTypeL( store->Layout() ); |
|
2305 TStreamId id( CreateDefaultRootStreamL( *store ) ); |
|
2306 store->SetRootL( id ); |
|
2307 store->CommitL(); |
|
2308 CleanupStack::PopAndDestroy(); // store |
|
2309 } |
|
2310 |
|
2311 aUnsavedMsgFileExisted = CbsUtils::ExistsL( iFs, |
|
2312 *iUnsavedMessagesFilename ); |
|
2313 if ( aUnsavedMsgFileExisted == EFalse ) |
|
2314 { |
|
2315 // No critical level check, because unsaved msgs reside on ramdisk |
|
2316 DoCreateStoreL( *iUnsavedMessagesFilename ); |
|
2317 } |
|
2318 } |
|
2319 |
|
2320 // ----------------------------------------------------------------------------- |
|
2321 // CCbsDbImpTopicList::DoCreateStoreL |
|
2322 // Creates an empty file store with the given filename. |
|
2323 // (other items were commented in a header). |
|
2324 // ----------------------------------------------------------------------------- |
|
2325 // |
|
2326 void CCbsDbImpTopicList::DoCreateStoreL( |
|
2327 const TDesC& aFilename ) |
|
2328 { |
|
2329 CFileStore* store = CPermanentFileStore::CreateLC( iFs, |
|
2330 aFilename, EFileWrite ); // on CS |
|
2331 store->SetTypeL( store->Layout() ); |
|
2332 store->CommitL(); |
|
2333 CleanupStack::PopAndDestroy(); |
|
2334 } |
|
2335 |
|
2336 // ----------------------------------------------------------------------------- |
|
2337 // CCbsDbImpTopicList::TryToOpenFilesL |
|
2338 // Tries to open topic and unsaved messages files. |
|
2339 // (other items were commented in a header). |
|
2340 // ----------------------------------------------------------------------------- |
|
2341 // |
|
2342 void CCbsDbImpTopicList::TryToOpenFilesL( |
|
2343 TBool aDeleteUnsavedMsgStreamIds, |
|
2344 TBool aCreateNewTopicList ) |
|
2345 { |
|
2346 CBSLOGSTRING("CBSSERVER: >>> CCbsDbImpTopicList::TryToOpenFilesL()" ); |
|
2347 |
|
2348 if ( !iTopicStore ) |
|
2349 { |
|
2350 CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicList::TryToOpenFilesL(): *** NO iTopicStore (1) ***" ); |
|
2351 } |
|
2352 |
|
2353 // Try to open the store |
|
2354 TRAPD( error, iTopicStore = CFileStore::OpenL( iFs, *iTopicsFilename, EFileRead | EFileWrite ) ); |
|
2355 CBSLOGSTRING2("CBSSERVER: CCbsDbImpTopicList::TryToOpenFilesL(); iTopicStore OpenL() error: %d", error ); |
|
2356 |
|
2357 TRAPD( error2, iUnsavedMessageStore = CFileStore::OpenL( iFs, *iUnsavedMessagesFilename, EFileRead | EFileWrite ) ); |
|
2358 CBSLOGSTRING2("CBSSERVER: CCbsDbImpTopicList::TryToOpenFilesL(); iUnsavedMessageStore OpenL() error: %d", error2 ); |
|
2359 |
|
2360 if ( error || error2 ) |
|
2361 { |
|
2362 CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicList::TryToOpenFilesL(): Calling InitializeListL( ETrue )..." ); |
|
2363 |
|
2364 InitializeListL( ETrue ); |
|
2365 |
|
2366 CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicList::TryToOpenFilesL(): Calling InitializeListL( ETrue ) finished." ); |
|
2367 } |
|
2368 else |
|
2369 { |
|
2370 if ( iTopicLists->Count() == 0 && |
|
2371 aDeleteUnsavedMsgStreamIds && |
|
2372 aCreateNewTopicList ) |
|
2373 { |
|
2374 // Create first topic list, since it was deleted with the file |
|
2375 CreateStandardTopicListL(); |
|
2376 } |
|
2377 |
|
2378 // Load the root stream for topic store. |
|
2379 LoadRootStreamL(); |
|
2380 |
|
2381 if ( aDeleteUnsavedMsgStreamIds ) |
|
2382 { |
|
2383 // Load the topics and repair the topic file |
|
2384 // since unsaved msg file has been deleted |
|
2385 LoadDefaultTopicStreamL(); |
|
2386 HandleDeletionOfUnsavedMessagesFileL(); |
|
2387 } |
|
2388 } |
|
2389 CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicList::TryToOpenFilesL()" ); |
|
2390 } |
|
2391 |
|
2392 // --------------------------------------------------------- |
|
2393 // CCbsDbImpTopicList::ReadIndexTopicNameLC() |
|
2394 // Reads the localized index topic name |
|
2395 // (other items were commented in a header). |
|
2396 // --------------------------------------------------------- |
|
2397 HBufC* CCbsDbImpTopicList::ReadIndexTopicNameLC() |
|
2398 { |
|
2399 // Open localized resource file. |
|
2400 RResourceFile resourceFile; |
|
2401 |
|
2402 CbsUtils::FindAndOpenDefaultResourceFileLC( iFs, resourceFile ); // on CS |
|
2403 // Read "Index"-string. |
|
2404 TResourceReader reader; |
|
2405 reader.SetBuffer( resourceFile.AllocReadLC( R_TEXT_INDEX_TOPIC ) );//on CS |
|
2406 HBufC* text = reader.ReadHBufCL(); |
|
2407 CleanupStack::PopAndDestroy(2); // readerBuf, resourceFile |
|
2408 CleanupStack::PushL( text ); |
|
2409 |
|
2410 return text; |
|
2411 } |
|
2412 |
|
2413 // ----------------------------------------------------------------------------- |
|
2414 // CCbsDbImpTopicList::AddIndexTopicL |
|
2415 // Adds index topic to topic list. |
|
2416 // (other items were commented in a header). |
|
2417 // ----------------------------------------------------------------------------- |
|
2418 // |
|
2419 void CCbsDbImpTopicList::AddIndexTopicL() |
|
2420 { |
|
2421 // Open localized resource file. |
|
2422 HBufC* text = ReadIndexTopicNameLC(); |
|
2423 |
|
2424 TCbsDbTopic topic; |
|
2425 topic.iName.Copy( *text ); |
|
2426 topic.iNumber = 0; |
|
2427 topic.iHotmarked = EFalse; |
|
2428 topic.iProtected = ETrue; |
|
2429 topic.iSubscribed = ETrue; |
|
2430 topic.iSavedMessages = 0; |
|
2431 topic.iUnreadMessages = 0; |
|
2432 |
|
2433 // Add the topic without notifying anybody. |
|
2434 TRAPD( error, DoAddTopicL( topic ) ); |
|
2435 if ( error != KErrNone ) |
|
2436 { |
|
2437 RevertFilesL(); |
|
2438 __TEST_INVARIANT; |
|
2439 User::Leave( error ); |
|
2440 } |
|
2441 |
|
2442 CleanupStack::PopAndDestroy(); // text |
|
2443 } |
|
2444 |
|
2445 // ----------------------------------------------------------------------------- |
|
2446 // CCbsDbImpTopicList::HandleDeletionOfUnsavedMessagesFileL |
|
2447 // Called to repair the database when Unsaved messages -file |
|
2448 // has been deleted, but Topics-file still contains information |
|
2449 // on unsaved messages. |
|
2450 // |
|
2451 // Things to do here: |
|
2452 // - Reset unread message counters, because a saved message |
|
2453 // is always also read. |
|
2454 // - Remove stream ids to unsaved messages from |
|
2455 // Topic messages -streams. |
|
2456 // (other items were commented in a header). |
|
2457 // ----------------------------------------------------------------------------- |
|
2458 // |
|
2459 void CCbsDbImpTopicList::HandleDeletionOfUnsavedMessagesFileL() |
|
2460 { |
|
2461 TRAPD( result, DoHandleDeletionOfUnsavedMessagesFileL() ); |
|
2462 if ( result != KErrNone ) |
|
2463 { |
|
2464 // Recovery impossible -> reset the database. |
|
2465 // Note that this function is not called when the database |
|
2466 // is initialized. |
|
2467 RebuildTopicAndUnsavedStoresL(); |
|
2468 } |
|
2469 } |
|
2470 |
|
2471 // ----------------------------------------------------------------------------- |
|
2472 // CCbsDbImpTopicList::DoHandleDeletionOfUnsavedMessagesFileL |
|
2473 // Does the work for HandleDeletionOfUnsavedMessagesFileL(). |
|
2474 // (other items were commented in a header). |
|
2475 // ----------------------------------------------------------------------------- |
|
2476 // |
|
2477 void CCbsDbImpTopicList::DoHandleDeletionOfUnsavedMessagesFileL() |
|
2478 { |
|
2479 // Reset the unread counter of each topic and delete stream ids of |
|
2480 // unsaved messages. |
|
2481 TInt numberOfTopics( iTopics->Count() ); |
|
2482 for ( TInt i( 0 ); i < numberOfTopics; i++ ) |
|
2483 { |
|
2484 TCbsDbTopic topic; |
|
2485 FindTopicByNumberL( iTopics->At( i ).iTopicData.iNumber, topic ); |
|
2486 topic.iUnreadMessages = 0; |
|
2487 DoUpdateTopicL( topic, EFalse, i, EFalse ); |
|
2488 DeleteUnsavedMessageStreamIdsL( iTopics->At( i ).iTopicMessagesId ); |
|
2489 } |
|
2490 |
|
2491 UpdateTopicListStreamL( iCurrentTopicList, ETrue ); |
|
2492 TopicStoreL()->CommitL(); |
|
2493 } |
|
2494 |
|
2495 // ----------------------------------------------------------------------------- |
|
2496 // CCbsDbImpTopicList::DeleteUnsavedMessageStreamIdsL |
|
2497 // This function is called when the unsaved messages file has |
|
2498 // been deleted but the Topic messages -stream still contains |
|
2499 // stream ids to deleted message streams. |
|
2500 // All stream ids found in the given topic messages -stream |
|
2501 // pointing to the unsaved messages file are removed. |
|
2502 // (other items were commented in a header). |
|
2503 // ----------------------------------------------------------------------------- |
|
2504 // |
|
2505 void CCbsDbImpTopicList::DeleteUnsavedMessageStreamIdsL( |
|
2506 const TStreamId& aMsgStreamId ) const |
|
2507 { |
|
2508 CArrayFixFlat< TStreamId >* streamIds = |
|
2509 new ( ELeave ) CArrayFixFlat< TStreamId >( KTypicalNumberOfTopicMessages ); |
|
2510 CleanupStack::PushL( streamIds ); |
|
2511 |
|
2512 RStoreReadStream instream; |
|
2513 instream.OpenLC( *TopicStoreL(), aMsgStreamId ); // on CS |
|
2514 |
|
2515 // Read msg count |
|
2516 TInt numberOfMsgs( instream.ReadInt16L() ); |
|
2517 |
|
2518 // Read max msg count |
|
2519 TInt maxNumberOfMsgs( instream.ReadInt16L() ); |
|
2520 |
|
2521 TInt index( 0 ); |
|
2522 |
|
2523 for ( ; index < numberOfMsgs; index++ ) |
|
2524 { |
|
2525 TBool saved( CbsStreamHelper::ReadBoolL( instream ) ); |
|
2526 TStreamId id( 0 ); |
|
2527 instream >> id; |
|
2528 if ( saved ) |
|
2529 { |
|
2530 streamIds->AppendL( id ); |
|
2531 } |
|
2532 } |
|
2533 |
|
2534 CleanupStack::PopAndDestroy(); // instream |
|
2535 |
|
2536 // Write stream ids of saved messages into the new topic message stream |
|
2537 // which replaces the stream identified with aMsgStreamId. |
|
2538 RStoreWriteStream outstream; |
|
2539 outstream.ReplaceLC( *TopicStoreL(), aMsgStreamId ); // on CS |
|
2540 |
|
2541 TInt numberOfSavedmessages( streamIds->Count() ); |
|
2542 |
|
2543 // Number of messages = number of saved messages |
|
2544 outstream.WriteInt16L( numberOfSavedmessages ); |
|
2545 |
|
2546 // Number of saved messages <= number of messages <= maxNumberOfMsgs |
|
2547 outstream.WriteInt16L( maxNumberOfMsgs ); |
|
2548 |
|
2549 for ( index = 0; index < numberOfSavedmessages; index++ ) |
|
2550 { |
|
2551 // All messages are saved (i.e., permanent) |
|
2552 CbsStreamHelper::WriteBoolL( outstream, ETrue ); |
|
2553 outstream << streamIds->At( index ); |
|
2554 } |
|
2555 |
|
2556 for ( ; index < maxNumberOfMsgs; index ++ ) |
|
2557 { |
|
2558 CbsStreamHelper::WriteBoolL( outstream, EFalse ); |
|
2559 outstream << TStreamId( 0 ); |
|
2560 } |
|
2561 |
|
2562 outstream.CommitL(); |
|
2563 CleanupStack::PopAndDestroy(2); // outstream, streamIds |
|
2564 |
|
2565 } |
|
2566 |
|
2567 // ----------------------------------------------------------------------------- |
|
2568 // CCbsDbImpTopicList::UpdateTopicCountersL |
|
2569 // Resolves the topic position in topic list and uses this information |
|
2570 // to call DoUpdateTopicL. |
|
2571 // Changes to stores are NOT commited. |
|
2572 // Call to DoUpdateTopicL is not trapped. |
|
2573 // (other items were commented in a header). |
|
2574 // ----------------------------------------------------------------------------- |
|
2575 // |
|
2576 void CCbsDbImpTopicList::UpdateTopicCountersL( |
|
2577 const TCbsDbTopic& aTopic, |
|
2578 const TBool aDeleting ) |
|
2579 { |
|
2580 CBSLOGSTRING("CBSSERVER: >>> CCbsDbImpTopicList::UpdateTopicCountersL()"); |
|
2581 |
|
2582 // Find out the position of the topic in topic list. |
|
2583 TInt index( TopicIndexInList( aTopic.iNumber ) ); |
|
2584 if ( index == KErrNotFound ) |
|
2585 { |
|
2586 User::Leave( KErrNotFound ); |
|
2587 } |
|
2588 |
|
2589 // DoUpdateTopicL leaves changes uncommited. EFalse for not having to |
|
2590 // change topic position in topic list. |
|
2591 DoUpdateTopicL( aTopic, EFalse, index, aDeleting ); |
|
2592 |
|
2593 CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicList::UpdateTopicCountersL()"); |
|
2594 } |
|
2595 |
|
2596 // ----------------------------------------------------------------------------- |
|
2597 // CCbsDbImpTopicList::CreateStandardTopicListL |
|
2598 // Creates the Standard topic list (topic list no. 0) |
|
2599 // (other items were commented in a header). |
|
2600 // ----------------------------------------------------------------------------- |
|
2601 // |
|
2602 void CCbsDbImpTopicList::CreateStandardTopicListL() |
|
2603 { |
|
2604 // Read standard topic list name from the resource file |
|
2605 RResourceFile resourceFile; |
|
2606 CbsUtils::FindAndOpenDefaultResourceFileLC( iFs, resourceFile ); // on CS |
|
2607 |
|
2608 TResourceReader reader; |
|
2609 reader.SetBuffer( resourceFile.AllocReadLC( R_TEXT_STANDARD_TOPIC_LIST ) ); // on CS |
|
2610 HBufC* standardTopicListName = reader.ReadHBufCL(); |
|
2611 CleanupStack::PushL( standardTopicListName ); |
|
2612 |
|
2613 // Create a new topic list |
|
2614 CreateNewTopicListL( standardTopicListName->Des() ); |
|
2615 |
|
2616 CleanupStack::PopAndDestroy( 3 ); // resourceFile, reader, standardTopicListName |
|
2617 } |
|
2618 |
|
2619 // ----------------------------------------------------------------------------- |
|
2620 // CCbsDbImpTopicList::LoadTopicsIdsL |
|
2621 // Reads topic IDs of a topic list from the stream. |
|
2622 // (other items were commented in a header). |
|
2623 // ----------------------------------------------------------------------------- |
|
2624 // |
|
2625 void CCbsDbImpTopicList::LoadTopicsIdsL( |
|
2626 const TStreamId& aTopicListStreamId ) |
|
2627 { |
|
2628 // Open the topic list stream |
|
2629 RStoreReadStream instream; |
|
2630 instream.OpenLC( *TopicStoreL(), aTopicListStreamId ); // on CS |
|
2631 |
|
2632 // Skip topic list name |
|
2633 delete HBufC::NewL( instream, KCbsDbTopicNameLength ); |
|
2634 |
|
2635 // Skip default list status |
|
2636 CbsStreamHelper::ReadBoolL( instream ); |
|
2637 |
|
2638 // Skip Topic List number |
|
2639 instream.ReadInt16L(); |
|
2640 |
|
2641 // Skip the amount of topics |
|
2642 TInt topicCount = instream.ReadInt16L(); |
|
2643 |
|
2644 // Clear the array |
|
2645 iTopicIds->ResizeL( 0 ); |
|
2646 |
|
2647 TStreamId id( 0 ); |
|
2648 |
|
2649 // Load the topic IDs |
|
2650 for ( TInt i = 0; i < topicCount; i++ ) |
|
2651 { |
|
2652 instream >> id; |
|
2653 iTopicIds->AppendL( id ); |
|
2654 } |
|
2655 |
|
2656 CleanupStack::PopAndDestroy(); // instream |
|
2657 } |
|
2658 |
|
2659 // ----------------------------------------------------------------------------- |
|
2660 // CCbsDbImpTopicList::LoadTopicsL |
|
2661 // Loads topics of a specified topic list. |
|
2662 // (other items were commented in a header). |
|
2663 // ----------------------------------------------------------------------------- |
|
2664 // |
|
2665 void CCbsDbImpTopicList::LoadTopicsL( |
|
2666 const TStreamId& aTopicListStreamId ) |
|
2667 { |
|
2668 // Open the topic list stream |
|
2669 RStoreReadStream instream; |
|
2670 instream.OpenLC( *TopicStoreL(), aTopicListStreamId ); // on CS |
|
2671 |
|
2672 // Skip topic list name |
|
2673 delete HBufC::NewL( instream, KCbsDbTopicNameLength ); |
|
2674 |
|
2675 // Skip default list status |
|
2676 CbsStreamHelper::ReadBoolL( instream ); |
|
2677 |
|
2678 // Skip Topic List number |
|
2679 instream.ReadInt16L(); |
|
2680 |
|
2681 // Skip the amount of topics |
|
2682 TInt topicCount = instream.ReadInt16L(); |
|
2683 |
|
2684 // Clear the arrays |
|
2685 iTopics->ResizeL( 0 ); |
|
2686 iTopicIds->ResizeL( 0 ); |
|
2687 |
|
2688 TStreamId id( 0 ); |
|
2689 |
|
2690 // Load the topic IDs |
|
2691 TInt i; |
|
2692 for ( i = 0; i < topicCount; i++ ) |
|
2693 { |
|
2694 instream >> id; |
|
2695 iTopicIds->AppendL( id ); |
|
2696 } |
|
2697 |
|
2698 CleanupStack::PopAndDestroy(); // instream |
|
2699 |
|
2700 // Load necessary information for each topic |
|
2701 TInt count = iTopicIds->Count(); |
|
2702 TCbsDbImpTopic topic; |
|
2703 for ( i = 0; i < count; i++ ) |
|
2704 { |
|
2705 ReadTopicInformationL( iTopicIds->At( i ), topic ); |
|
2706 |
|
2707 if ( topic.iTopicData.iNumber == KIndexTopicNumber ) |
|
2708 { |
|
2709 HBufC* indexName = ReadIndexTopicNameLC(); // on CS |
|
2710 topic.iTopicData.iName.Copy( *indexName ); |
|
2711 CleanupStack::PopAndDestroy(); // indexName |
|
2712 } |
|
2713 iTopics->AppendL( topic ); |
|
2714 } |
|
2715 } |
|
2716 |
|
2717 // ----------------------------------------------------------------------------- |
|
2718 // CCbsDbImpTopicList::UpdateTopicStreamIdsL |
|
2719 // Updates the topic stream IDs. |
|
2720 // (other items were commented in a header). |
|
2721 // ----------------------------------------------------------------------------- |
|
2722 // |
|
2723 void CCbsDbImpTopicList::UpdateTopicStreamIdsL( |
|
2724 const TCbsDbTopicNumber aTopicNumber ) |
|
2725 { |
|
2726 // Try to find the topic from current topic list |
|
2727 TInt position( TopicIndexInList( aTopicNumber ) ); |
|
2728 if ( position >= 0 ) |
|
2729 { |
|
2730 // Remove from the internal cache of this topic list |
|
2731 iTopics->Delete( position ); |
|
2732 |
|
2733 iCurrentTopicList.iTopicCount--; |
|
2734 |
|
2735 // Update the stream |
|
2736 UpdateTopicListStreamL( iCurrentTopicList, EFalse ); |
|
2737 CommitFilesL(); |
|
2738 } |
|
2739 } |
|
2740 |
|
2741 // ----------------------------------------------------------------------------- |
|
2742 // CCbsDbImpTopicList::__DbgTestInvariant |
|
2743 // Checks that the object is in a valid state, and panics if it is not. |
|
2744 // (other items were commented in a header). |
|
2745 // ----------------------------------------------------------------------------- |
|
2746 // |
|
2747 void CCbsDbImpTopicList::__DbgTestInvariant() const |
|
2748 { |
|
2749 /* |
|
2750 #if defined(_DEBUG) |
|
2751 #endif |
|
2752 */ |
|
2753 } |
|
2754 |
|
2755 // ========================== OTHER EXPORTED FUNCTIONS ========================= |
|
2756 |
|
2757 // End of File |