--- a/cbs/CbsServer/ServerSrc/CCbsDbImpTopicList.cpp Mon Aug 23 15:50:31 2010 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2757 +0,0 @@
-/*
-* Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies).
-* All rights reserved.
-* This component and the accompanying materials are made available
-* under the terms of "Eclipse Public License v1.0"
-* which accompanies this distribution, and is available
-* at the URL "http://www.eclipse.org/legal/epl-v10.html".
-*
-* Initial Contributors:
-* Nokia Corporation - initial contribution.
-*
-* Contributors:
-*
-* Description: This file contains the implementation of the CCbsDbImpTopicList class
-* member functions.
-*
-* This class represents the topic list contained in the database.
-*
-*/
-
-
-
-// INCLUDE FILES
-#include <e32base.h>
-#include <e32svr.h>
-#include <f32file.h>
-
-#include <shareddataclient.h> // RequestFreeDiskSpaceLC
-
-#include <barsc.h> // Resource access
-#include <barsread.h> // Resource access
-
-#include <CbsServer.rsg>
-
-#include "CbsServerPanic.h"
-#include "CbsStreamHelper.h"
-#include "CbsDbConstants.h"
-#include "CbsUtils.h"
-#include "CCbsDbImpTopicList.h"
-#include "MCbsDbTopicListObserver.H"
-#include "CCbsDbImpTopicMessages.h"
-
-#include "CbsLogger.h"
-
-#include <centralrepository.h> // for local variation
-#include "cbsinternalcrkeys.h" // for local variation
-#include "cbsvariant.hrh" // for local variation
-
-// CONSTANTS
-
-// Initial size for topic cache array
-const TInt KDefaultTopicListSize = 10;
-
-// Size of the topic stream, used in checking against FFS free space limit
-const TInt KTopicStreamSize = 92;
-
-// Size of the topic messages stream, FFS critical level check
-const TInt KEmptyTopicMessagesStreamSize = 4;
-
-// Size of topic list stream, FFS critical level check
-const TInt KTopicListStreamSize = 85;
-
-// Size of topic list stream (root), FFS critical level check
-const TInt KTopicListRootStreamSize = 2;
-
-// Time in microseconds to wait after a critical store exception
-// before a recovery attempt is made.
-const TInt KWaitAfterCriticalStoreException = 2000000;
-
-// Used when unsaved message stream ids are deleted from topic messages
-// stream
-const TInt KTypicalNumberOfTopicMessages = 6;
-
-// Minimum interval between compacting the stores in minutes
-const TInt KMinimumCompactInterval = 30;
-
-// Number of the index topic
-const TInt KIndexTopicNumber = 0;
-
-// Space for reading messages
-const TInt KReadMessageSize = 92;
-
-const TInt KTopicsGranularity = 1;
-
-const TInt KTopicListsGranularity = 1;
-
-const TInt KTopicIdsGranularity = 5;
-
-// ================= MEMBER FUNCTIONS =======================
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::CCbsDbImpTopicList
-// C++ default constructor can NOT contain any code, that
-// might leave.
-// -----------------------------------------------------------------------------
-//
-CCbsDbImpTopicList::CCbsDbImpTopicList(
- RFs& aFs,
- CCbsDbImp& aDatabase )
- : iDatabase( aDatabase ),
- iFs( aFs ),
- iTopicCount( 0 ),
- iInitializing( EFalse ),
- iDeleteAllTopics( EFalse )
- {
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::ConstructL
-// Symbian 2nd phase constructor can leave.
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::ConstructL(
- const TDesC& aTopicsFile,
- const TDesC& aUnsavedMessagesFile )
- {
- CBSLOGSTRING("CBSSERVER: >>> CCbsDbImpTopicList::ConstructL()");
-
- // Create observer array
- iObservers = new ( ELeave ) CArrayFixFlat< MCbsDbTopicListObserver* >(
- KCbsDbObserverArraySize );
-
- // Create topic array, additional memory size in new alloc, 1*192 B = 192 B
- iTopics = new ( ELeave ) CArrayFixFlat< TCbsDbImpTopic >( KTopicsGranularity );
-
- // Create the root item table, additional memory size in new alloc, 1*184 B = 184 B
- iTopicLists = new ( ELeave ) CArrayFixFlat< TCbsDbImpTopicList >( KTopicListsGranularity );
-
- // Create topic ID array, additional memory size in new alloc, 5*4 B = 20 B
- iTopicIds = new ( ELeave ) CArrayFixFlat< TStreamId >( KTopicIdsGranularity );
-
- // Initialize iPreviousCompact to now
- iPreviousCompact.UniversalTime();
-
- // Copy datafile names from parameters
- iTopicsFilename = aTopicsFile.AllocL();
- iUnsavedMessagesFilename = aUnsavedMessagesFile.AllocL();
-
- // Fetch local variation bits from CenRep
- CRepository* repository = CRepository::NewL( KCRUidCbsVariation );
- TInt err = repository->Get( KCbsVariationFlags, iLVBits );
- CBSLOGSTRING2("CBSSERVER: CCbsRecEtel::ConstructL(): CenRep error: %d", err );
- if ( err )
- {
- iLVBits = 0;
- }
- delete repository;
-
- // If aLoadFactorySettings, then the files are recreated and initialized.
- // If not, then the nonexisting files are created, files opened and
- // data internalized.
-
- TBool unsavedMsgFileExists( CbsUtils::ExistsL( iFs, *iUnsavedMessagesFilename ) );
-
- TBool loadFactorySettings( !CbsUtils::ExistsL( iFs, aTopicsFile ) );
- TRAPD( error, OpenFilesL( loadFactorySettings, EFalse ) );
-
- CBSLOGSTRING2("CBSSERVER: CCbsDbImpTopicList::ConstructL(): OpenFilesL() error: %d", error );
-
- if ( error == KErrDiskFull )
- {
- // Delete the store and open is again
- CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicList::ConstructL(): About to delete iTopicStore..." );
-
- delete iTopicStore;
- iTopicStore = NULL;
-
- CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicList::ConstructL(): iTopicStore deletion finished." );
-
- // Try to open the store again
- TRAPD( error, iTopicStore = CFileStore::OpenL( iFs, *iTopicsFilename, EFileRead | EFileWrite ) );
- CBSLOGSTRING2("CBSSERVER: CCbsDbImpTopicList::ConstructL(); iTopicStore OpenL() error: %d", error );
- if ( error )
- {
- InitializeListL( ETrue );
- }
- }
- else
- {
- if ( loadFactorySettings )
- {
- // Create a topic list for standard topics
- if ( iTopicLists->Count() == 0 )
- {
- CreateStandardTopicListL();
- }
- }
-
- // Only load the topics, if not already loaded when opening the files
- if ( loadFactorySettings || unsavedMsgFileExists )
- {
- // Load the topics
- LoadDefaultTopicStreamL();
- }
-
- // Compact the topic store
- TopicStoreL()->CompactL();
- TopicStoreL()->CommitL();
- }
-
- // Reset the unread message count to be sure that UI client gets the correct information,
- // at this point count is always zero.
- for ( TInt i( 0 ); i < iTopics->Count(); ++i )
- {
- iTopics->At( i ).iTopicData.iUnreadMessages = 0;
- }
-
- __TEST_INVARIANT;
-
- CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicList::ConstructL()");
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::NewL
-// Two-phased constructor.
-// -----------------------------------------------------------------------------
-//
-CCbsDbImpTopicList* CCbsDbImpTopicList::NewL(
- RFs& aFs,
- const TDesC& aTopicsFile,
- const TDesC& aUnsavedMessagesFile,
- CCbsDbImp& aDatabase )
- {
- CCbsDbImpTopicList* self =
- new ( ELeave ) CCbsDbImpTopicList( aFs, aDatabase );
- CleanupStack::PushL( self );
- self->ConstructL( aTopicsFile, aUnsavedMessagesFile );
- CleanupStack::Pop();
- return self;
- }
-
-// Destructor
-CCbsDbImpTopicList::~CCbsDbImpTopicList()
- {
- CBSLOGSTRING("CBSSERVER: >>> CCbsDbImpTopicList::~CCbsDbImpTopicList()");
- delete iTopics;
- delete iTopicStore;
- delete iTopicLists;
- delete iTopicIds;
- delete iUnsavedMessageStore;
- delete iObservers;
- delete iUnsavedMessagesFilename;
- if ( iTopicsFilename )
- {
- delete iTopicsFilename;
- }
- CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicList::~CCbsDbImpTopicList()");
- }
-
-#ifndef __SECURE_BACKUP__
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::ChangeFileLockL
-// Closes or reopens the settings file if requested by a backup.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::ChangeFileLockL(
- const TDesC& aFileName,
- TFileLockFlags aFlags )
- {
- CBSLOGSTRING2("CBSSERVER: >>> CCbsDbImpTopicList::ChangeFileLockL() (1): flag: %d", aFlags );
-
- if ( aFlags == ETakeLock && iTopicStore == NULL )
- {
- CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicList::ChangeFileLockL() (1): Try to open store...");
-
- // Try to open the store.
- iTopicStore = CPermanentFileStore::OpenL( iFs,
- aFileName, EFileRead | EFileWrite );
-
- CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicList::ChangeFileLockL() (1): Store opened.");
- }
- else if ( aFlags != ETakeLock )
- {
- CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicList::ChangeFileLockL() (1): Deleting iTopicStore...");
-
- delete iTopicStore;
- iTopicStore = NULL;
-
- CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicList::ChangeFileLockL() (1): iTopicStore deleted.");
- }
- CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicList::ChangeFileLockL() (1)");
- }
-#else
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpSettings::ChangeFileLockL
-// Closes or reopens the settings file if requested by backup.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::ChangeFileLockL( const TCbsBackupRequest& aRequest )
- {
- CBSLOGSTRING2("CBSSERVER: >>> CCbsDbImpTopicList::ChangeFileLockL() (2): aRequest: %d", aRequest );
-
- // If backing up or restoring, release locks
- if ( ( aRequest == ECbsBackup ||
- aRequest == ECbsRestore ) )
- {
- delete iTopicStore;
- iTopicStore = NULL;
-
- CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicList::ChangeFileLockL() (2): iTopicStore deleted.");
- }
- // Else take files into use again
- else if ( ( aRequest == ECbsNoBackup ||
- aRequest == ECbsBackupNotDefined ) &&
- iTopicStore == NULL)
- {
- CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicList::ChangeFileLockL() (2): Calling CPermanentFileStore::OpenL()...");
- // Try to open the store.
- iTopicStore = CPermanentFileStore::OpenL( iFs,
- iTopicsFilename->Des(), EFileRead | EFileWrite );
- CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicList::ChangeFileLockL() (2): CPermanentFileStore::OpenL() finished.");
- }
- CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicList::ChangeFileLockL() (2)");
- }
-
-#endif
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::CheckFileLockL
-// Check if the server has a file lock.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::CheckFileLockL() const
- {
- CBSLOGSTRING("CBSSERVER: >>> CCbsDbImpTopicList::CheckFileLockL()");
- if ( iTopicStore == NULL )
- {
- CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicList::CheckFileLockL(): iTopicStore == NULL, leaving with KErrLocked...");
- User::Leave( KErrLocked );
- }
- CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicList::CheckFileLockL()");
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::CreateNewTopicListL
-// Creates a new topic list.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::CreateNewTopicListL( const TDesC& aTopicListName )
- {
- // FFS critical level check
- CbsUtils::FFSCriticalLevelCheckL( KTopicListStreamSize +
- KCbsDbTopicArraySize, iFs );
-
- TInt topicListCount = iTopicLists->Count();
-
- // Check if there already is 10 topic lists
- if ( topicListCount < KCbsRootItemsSize )
- {
- // Create the stream for this topic list entry
- RStoreWriteStream outstream;
- TStreamId topicListStreamId(
- outstream.CreateLC( *TopicStoreL() ) ); // on CS
-
- // Set the values for this new topic list and set it as "current".
- // Reset the topic count of this topic list.
- iCurrentTopicList.iTopicCount = 0;
-
- // Topic list stream id for this list
- iCurrentTopicList.iTopicListId = topicListStreamId;
-
- // List name
- iCurrentTopicList.iTopicListName = aTopicListName;
-
- // Is this the default list
- iCurrentTopicList.iIsDefaultTopicList = ETrue;
-
- // Number of this list, which is a int value between 0...9
- iCurrentTopicList.iNumber = iTopicLists->Count();
-
- // Add this list to the list array
- TKeyArrayFix key( _FOFF( TCbsDbImpTopicList, iNumber ), ECmpTUint16 );
- iTopicLists->InsertIsqL( iCurrentTopicList, key );
-
- // Write the values to this topic list's stream
- outstream << iCurrentTopicList.iTopicListName;
- CbsStreamHelper::WriteBoolL( outstream, iCurrentTopicList.iIsDefaultTopicList );
- outstream.WriteInt16L( iCurrentTopicList.iNumber );
- outstream.WriteInt16L( iCurrentTopicList.iTopicCount );
-
- // Write space for topic stream IDs
- for ( TInt i( 0 ); i < KCbsDbTopicArraySize; i++ )
- {
- outstream << TStreamId( 0 );
- }
-
- outstream.CommitL();
- CleanupStack::PopAndDestroy(); // outstream
-
- // Reset the topic array and add an index topic to this
- // topic list
- iTopics->Reset();
- AddIndexTopicL();
-
- // Update the root stream
- UpdateRootStreamL( EFalse );
-
- // Commit file changes
- CommitFilesL();
-
- // Load the topics (count = 1, Index topic only),
- // so that the array is up to date
- LoadTopicsL( iCurrentTopicList.iTopicListId );
- }
- else
- {
- User::Leave( KErrGeneral );
- }
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::SetTopicMessages
-// Sets the topic messages db object for this topic list.
-// Note that this function does not transfer ownership
-// of aMessages.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::SetTopicMessages(
- CCbsDbImpTopicMessages* aMessages )
- {
- __ASSERT_ALWAYS( aMessages != NULL,
- CbsServerPanic( ECbsTopicMessagesNull ) );
- iMessages = aMessages;
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::TopicCount
-// Returns the total amount of topics the list contains.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-TInt CCbsDbImpTopicList::TopicCount() const
- {
- return iTopics->Count();
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::TopicListCount
-// Get topic list count.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-TInt CCbsDbImpTopicList::TopicListCount() const
- {
- return iTopicLists->Count();
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::TopicStoreL
-// Returns pointer to the current store which contains topics
-// of the server (i.e., Topics-file) and saved messages.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-CFileStore* CCbsDbImpTopicList::TopicStoreL() const
- {
- CheckFileLockL();
- return iTopicStore;
- }
-
-// ---------------------------------------------------------
-// TopicFilename()
-//
-// ---------------------------------------------------------
-const TDesC& CCbsDbImpTopicList::TopicFilename() const
- {
- return *iTopicsFilename;
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::UnsavedMessagesStore
-// Returns a pointer to the store, which contains unsaved
-// messages of the server (Unsaved Messages-file, "cbs4.dat").
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-CFileStore* CCbsDbImpTopicList::UnsavedMessagesStore() const
- {
- return iUnsavedMessageStore;
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::UnsavedMessagesFilename
-// Returns a reference to the name of the file, which contains unsaved
-// messages of the server (Unsaved Messages-file, "cbs4.dat").
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-const TDesC& CCbsDbImpTopicList::UnsavedMessagesFilename() const
- {
- return *iUnsavedMessagesFilename;
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::ExtractTopicNumber
-// Extracts topic handle from message handle.
-// Note that the method does not check that the message exists.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-TCbsDbTopicNumber CCbsDbImpTopicList::ExtractTopicNumber(
- const TCbsDbMessageHandle& aHandle ) const
- {
- return TCbsDbTopicNumber( aHandle >> 16 );
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::GetTopicMessagesIdL
-// Returns the topic messages stream id by topic handle.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::GetTopicMessagesIdL(
- TCbsDbTopicNumber aNumber, TStreamId& aId ) const
- {
- CBSLOGSTRING("CBSSERVER: >>> CCbsDbImpTopicList::GetTopicMessagesIdL()");
-
- // Find the topic.
- TInt index( TopicIndexInList( aNumber ) );
- CBSLOGSTRING2("CBSSERVER: CCbsDbImpTopicList::GetTopicMessagesIdL(): Leaving if index != 0. Index: %d.", index );
- User::LeaveIfError( index );
-
- // Return the topic message stream id.
- aId = iTopics->At( index ).iTopicMessagesId;
-
- CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicList::GetTopicMessagesIdL()");
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::UpdateTopicMessagesIdL
-// Updates the topic messages stream id by topic handle.
-// The new identifier is expected not to be a null id.
-// Note that the method will not commit changes to the store.
-// It also changes the internal state and thus if the method leaves,
-// it is good to reload the whole root stream.
-// The method will delete the old topic messages stream.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::UpdateTopicMessagesIdL(
- TCbsDbTopicNumber aNumber,
- const TStreamId& aNewId )
- {
- __TEST_INVARIANT;
- // Find position.
- TInt index( TopicIndexInList( aNumber ) );
- User::LeaveIfError( index );
-
- // Get the old id.
- TStreamId oldId( iTopics->At( index ).iTopicMessagesId );
-
- // Get the topic information.
- TCbsDbTopic topic;
- GetTopicL( index, topic );
-
- // Write information to the stream.
- RStoreWriteStream outstream;
- outstream.OpenLC( *TopicStoreL(), iTopics->At( index ).iTopicId ); // on CS
- WriteTopicInformationL( outstream, topic, aNewId );
- outstream.CommitL();
- CleanupStack::PopAndDestroy();
-
- // Delete the old stream.
- TopicStoreL()->DeleteL( oldId );
-
- // Update the topic messages id.
- iTopics->At( index ).iTopicMessagesId = aNewId;
- __TEST_INVARIANT;
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::GenerateMessageHandle
-// Generates a new message handle using the topic
-// handle of the message and a given random value.
-// Note that it must be checked that the message handle is unique
-// in that topic.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-TCbsDbMessageHandle CCbsDbImpTopicList::GenerateMessageHandle(
- const TCbsDbTopicNumber aNumber,
- TUint16 aRandom ) const
- {
- return ( aNumber << 16 ) + aRandom;
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::ReloadRootStreamL
-// Reloads the root stream to the memory.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::ReloadRootStreamL()
- {
- LoadRootStreamL();
- __TEST_INVARIANT;
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::InformNewMessageReceivedL
-// Informs that a new message has been received in a topic.
-// This method is called by CCbsDbImpTopicMessages. After internal
-// records are changed, the observers are informed of this event.
-// Note: leaves changes in stores uncommited.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::InformNewMessageReceivedL(
- const TCbsDbMessageHandle& aMessageHandle )
- {
- __TEST_INVARIANT;
- // Find topic by handle.
- TCbsDbTopicNumber number( ExtractTopicNumber( aMessageHandle ) );
-
- TCbsDbTopic topic;
- FindTopicByNumberL( number, topic );
-
- topic.iUnreadMessages++;
-
- // Increase the counter in cache
- TInt position = TopicIndexInList( topic.iNumber );
- iTopics->At( position ).iTopicData.iUnreadMessages++;
-
- // Write topic information to topic stream but leave changes uncommited.
- UpdateTopicCountersL( topic, EFalse );
-
- if ( topic.iHotmarked )
- {
- SetHotmarkedMessage( aMessageHandle );
- }
-
- __TEST_INVARIANT;
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::InformMessageSavedL
-// Informs that a message has been set as saved.
-// Updates the saved messages counters
-// for the topic of the message and the whole system.
-// Called by CCbsDbTopicMessages.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::InformMessageSavedL(
- const TCbsDbMessageHandle& aMessageHandle )
- {
- __TEST_INVARIANT;
- // Find topic by handle.
- TCbsDbTopicNumber number( ExtractTopicNumber( aMessageHandle ) );
-
- TCbsDbTopic topic;
- FindTopicByNumberL( number, topic );
-
- topic.iSavedMessages++;
-
- // Increase the counter in cache
- TInt position = TopicIndexInList( topic.iNumber );
- iTopics->At( position ).iTopicData.iSavedMessages++;
-
- // Write topic information to topic stream but leave changes uncommited.
- UpdateTopicCountersL( topic, EFalse );
-
- __TEST_INVARIANT;
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::InformUnreadMessageReadL
-// Informs that an unread message has been read.
-// Updates the counters when a message is read by the client.
-// Note: leaves changes in stores uncommited.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::InformUnreadMessageReadL(
- const TCbsDbMessageHandle& aMessageHandle )
- {
- CBSLOGSTRING("CBSSERVER: >>> CCbsDbImpTopicList::InformUnreadMessageReadL()");
-
- __TEST_INVARIANT;
-
- // Check for file lock
- CheckFileLockL();
-
- // Check disk space
- TRAPD( error, CbsUtils::FFSCriticalLevelCheckL( KReadMessageSize, iFs ) );
- CBSLOGSTRING2("CBSSERVER: CCbsDbImpTopicList::InformUnreadMessageReadL(): FFSCriticalLevelCheckL returned: %d", error );
- if ( error == KErrDiskFull )
- {
- return;
- }
-
- // Find topic by number.
- TCbsDbTopicNumber number( ExtractTopicNumber( aMessageHandle ) );
-
- TCbsDbTopic topic;
- FindTopicByNumberL( number, topic );
-
- // Decrease the counter
- topic.iUnreadMessages--;
-
- // Decrease the counter in cache
- TInt position = TopicIndexInList( topic.iNumber );
- iTopics->At( position ).iTopicData.iUnreadMessages--;
-
- // Write topic information to topic stream but leave changes uncommited.
- UpdateTopicCountersL( topic, EFalse );
-
- __TEST_INVARIANT;
-
- CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicList::InformUnreadMessageReadL()");
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::InformMessageDeletedL
-// Informs that an unread message has been deleted.
-// Updates the counters when a message is deleted.
-// Note: leaves changes in stores uncommited.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::InformMessageDeletedL(
- const TCbsDbMessageHandle& aMessageHandle,
- TBool aPermanent,
- TBool aRead )
- {
- // Find topic by handle.
- TCbsDbTopicNumber number( ExtractTopicNumber( aMessageHandle ) );
-
- TCbsDbTopic topic;
- FindTopicByNumberL( number, topic );
-
- TInt position = TopicIndexInList( topic.iNumber );
-
- if ( aPermanent )
- {
- topic.iSavedMessages--;
- iTopics->At( position ).iTopicData.iSavedMessages--;
- }
-
- if ( !aRead )
- {
- topic.iUnreadMessages--;
- iTopics->At( position ).iTopicData.iUnreadMessages--;
- }
-
- // Write topic information to topic stream but leave changes uncommited.
- UpdateTopicCountersL( topic, ETrue );
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::TotalSavedMessages
-// Returns the number of saved messages in the current topic list.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-TInt CCbsDbImpTopicList::TotalSavedMessages() const
- {
- // Return the total amount of saved messages.
- TInt count( 0 );
- for ( TInt i( 0 ); i < iTopics->Count(); i++ )
- {
- count += iTopics->At( i ).iTopicData.iSavedMessages;
- }
-
- return count;
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::GetTopicCount
-// Returns the number of topic stored in this topic list.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::GetTopicCount(
- TInt& aCount ) const
- {
- // Return the total amount of topics.
- aCount = TopicCount();
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::InitializeListL
-// Initializes the whole topic list.
-// Creates and opens the topic list file,
-// invalidates the cache and informs the observers.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::InitializeListL( const TBool aFileOpenFailed )
- {
- __TEST_INVARIANT;
-
- if ( !aFileOpenFailed )
- {
- // Check for file lock
- CheckFileLockL();
- }
-
- // About to write to FFS: make critical level check
- CbsUtils::FFSCriticalLevelCheckL( 0, iFs );
-
- if ( iMessages != NULL && iMessages->IsLockedMessages() )
- {
- User::Leave( KErrAccessDenied );
- }
-
- // If only one topic list exists, just delete and recreate the whole file
- if ( iTopicLists->Count() == 1 || aFileOpenFailed == 1 )
- {
- delete iTopicStore;
- iTopicStore = NULL;
- delete iUnsavedMessageStore;
- iUnsavedMessageStore = NULL;
- CbsUtils::DeleteFileL( iFs, *iTopicsFilename );
- CbsUtils::DeleteFileL( iFs, *iUnsavedMessagesFilename );
-
- iTopicLists->Reset();
-
- // Create new files.
- OpenFilesL( EFalse, ETrue );
- }
-
- iIsHotmarkedMessage = EFalse;
- iLastTopicNumber = 0;
- iMessageHandle = 0;
-
- // Inform the message manager.
- if ( iMessages )
- {
- iMessages->InvalidateCache();
- }
-
- // Notify everyone.
- NotifyTopicListInitializedL();
-
- __TEST_INVARIANT;
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::GetTopicL
-// Returns a topic matching the given index.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::GetTopicL(
- TInt aIndex,
- TCbsDbTopic& aTopic )
- {
- CBSLOGSTRING("CBSSERVER: >>> CCbsDbImpTopicList::GetTopicL()");
-
- __TEST_INVARIANT;
-
- // Check that aIndex is in proper range.
- if ( ( aIndex < 0 ) || ( aIndex >= iTopics->Count() ) )
- {
- CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicList::GetTopicL(): Leaving with KErrArgument...");
- User::Leave( KErrArgument );
- }
-
- // And then get the information from the array.
- aTopic = iTopics->At( aIndex ).iTopicData;
-
- CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicList::GetTopicL()");
-
- __TEST_INVARIANT;
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::FindTopicByNumberL
-// Returns a topic matching the given topic number
-// (in GSM Specs this is called the Message Identifier)
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::FindTopicByNumberL(
- TCbsDbTopicNumber aNumber,
- TCbsDbTopic& aTopic )
- {
- CBSLOGSTRING("CBSSERVER: >>> CCbsDbImpTopicList::FindTopicByNumberL()");
-
- __TEST_INVARIANT;
-
- TInt topicIndex( TopicIndexInList( aNumber ) );
- CBSLOGSTRING2("CBSSERVER: CCbsDbImpTopicList::FindTopicByNumberL(): Leaving if topicIndex < 0: topicIndex: %d.", topicIndex );
- User::LeaveIfError( topicIndex );
-
- GetTopicL( topicIndex, aTopic );
-
- CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicList::FindTopicByNumberL()");
-
- __TEST_INVARIANT;
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::AddTopicL
-// Adds a new topic to the list.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::AddTopicL(
- TCbsDbTopic& aTopic, const TBool aDetected )
- {
- __TEST_INVARIANT;
-
- // Check for file lock
- CheckFileLockL();
-
- // Check that topic number is in proper range
- if ( !CheckTopicNumber( aTopic.iNumber ) )
- {
- User::Leave( KErrArgument );
- }
-
- // Check if there is a topic with the
- // same topic number in current topic list.
- if ( TopicIndexInList( aTopic.iNumber ) != KErrNotFound )
- {
- User::Leave( KErrAlreadyExists );
- }
-
- // There should not be any saved or unread messages
- aTopic.iSavedMessages = 0;
- aTopic.iUnreadMessages = 0;
-
- // Variated feature. Also, only topics that were not detected automatically
- // are subscribed by default.
- if ( iLVBits & KCbsLVFlagTopicSubscription && !aDetected )
- {
- aTopic.iSubscribed = ETrue;
- }
- else
- {
- aTopic.iSubscribed = EFalse;
- }
-
- // Now we have the handle, so let's add the topic.
- TRAPD( error, DoAddTopicL( aTopic ) );
- if ( error != KErrNone )
- {
- RevertFilesL();
- __TEST_INVARIANT;
- User::Leave( error );
- }
- else
- {
- iLastTopicNumber = aTopic.iNumber;
- NotifyTopicAddedL( aTopic.iNumber );
- }
-
- __TEST_INVARIANT;
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::UpdateTopicNameAndNumberL
-// Updates the name and the topic number of a topic
-// matching the given handle to the database.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::UpdateTopicNameAndNumberL(
- TCbsDbTopicNumber aOldNumber,
- TCbsDbTopicNumber aNewNumber,
- const TCbsDbTopicName& aName )
- {
- // Check for file lock
- CheckFileLockL();
-
- // First, check that the new number is ok.
- if ( !CheckTopicNumber( aNewNumber ) )
- {
- User::Leave( KErrArgument );
- }
-
- // First find and then update.
- TCbsDbTopic topic;
- FindTopicByNumberL( aOldNumber, topic );
-
- // If no changes to topic, no need to update
- if ( !( aOldNumber == aNewNumber && topic.iName == aName ) )
- {
- if ( topic.iProtected )
- {
- User::Leave( KErrAccessDenied );
- }
-
- topic.iName = aName;
- topic.iNumber = aNewNumber;
-
- UpdateTopicL( aOldNumber, topic );
- }
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::UpdateTopicSubscriptionStatusL
-// Updates the new topic subscription status to the database.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::UpdateTopicSubscriptionStatusL(
- TCbsDbTopicNumber aNumber,
- TBool aStatus )
- {
- __TEST_INVARIANT;
-
- // Update topic subsciption status.
- TCbsDbTopic topic;
- FindTopicByNumberL( aNumber, topic );
-
- topic.iSubscribed = aStatus;
- UpdateTopicL( aNumber, topic );
- __TEST_INVARIANT;
-
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::UpdateTopicHotmarkStatusL
-// Updates the new topic hotmarking status to the database.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::UpdateTopicHotmarkStatusL(
- TCbsDbTopicNumber aNumber,
- TBool aStatus )
- {
- __TEST_INVARIANT;
-
- // Check for file lock
- CheckFileLockL();
-
- // Update topic hotmark status.
- TCbsDbTopic topic;
- FindTopicByNumberL( aNumber, topic );
-
- topic.iHotmarked = aStatus;
- UpdateTopicL( aNumber, topic );
- __TEST_INVARIANT;
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::DeleteTopicL
-// Deletes an existing topic and all its messages.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::DeleteTopicL(
- TCbsDbTopicNumber aNumber )
- {
- __TEST_INVARIANT;
-
- // Try to find the position. If it is not found, leave.
- TInt position( TopicIndexInList( aNumber ) );
- User::LeaveIfError( position );
-
- // Check that there are no locked messages in the topic.
- if ( iMessages->IsLockedMessagesInTopic( aNumber ) )
- {
- User::Leave( KErrAccessDenied );
- }
-
- // Topic only in one topic list, not an index topic, so delete the topic.
- if ( aNumber != 0 )
- {
- // Just try to delete
- TRAPD( error, DoDeleteTopicL( position ) );
- if ( error != KErrNone )
- {
- // It failed, so we must revert.
- RevertFilesL();
-
- // Inform the topic messages.
- iMessages->InvalidateCacheIfTopic( aNumber );
-
- __TEST_INVARIANT;
- User::Leave( error );
- }
- else
- {
- // Notify the observers
- NotifyTopicDeletedL( aNumber );
- }
- }
- __TEST_INVARIANT;
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::GetUnreadMessageCount
-// Gets the total amount of unread messages.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::GetUnreadMessageCount(
- TInt& aCount ) const
- {
- CBSLOGSTRING("CBSSERVER: >>> CCbsDbImpTopicList::GetUnreadMessageCount()");
- CBSLOGSTRING2("CBSSERVER: CCbsDbImpTopicList::GetUnreadMessageCount(): Topic count: %d", iTopics->Count() );
-
- // Return the total amount of unread messages.
- TInt count( 0 );
- for ( TInt i( 0 ); i < iTopics->Count(); i++ )
- {
- count += iTopics->At( i ).iTopicData.iUnreadMessages;
- }
-
- aCount = count;
-
- CBSLOGSTRING2("CBSSERVER: CCbsDbImpTopicList::GetUnreadMessageCount(): Unread msgs found: %d", count );
- CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicList::GetUnreadMessageCount()");
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::GetHotmarkedMessageHandleL
-// Returns the handle to the latest hotmarked message.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::GetHotmarkedMessageHandleL(
- TCbsDbMessageHandle& aMessage )
- {
- __TEST_INVARIANT;
-
- // Check if there is a hotmarked message.
- if ( iIsHotmarkedMessage )
- {
- // If there is, then return it.
- aMessage = iMessageHandle;
- iIsHotmarkedMessage = EFalse;
- }
- else
- {
- // Otherwise leave.
- __TEST_INVARIANT;
- User::Leave( KErrNotFound );
- }
- __TEST_INVARIANT;
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::UnreadHotmarkedMessageCount
-// Returns the handle to the latest hotmarked message.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-TInt CCbsDbImpTopicList::UnreadHotmarkedMessageCount() const
- {
- // Return the total amount of unread messages in hotmarked topics.
- TInt count( 0 );
- for ( TInt i( 0 ); i < iTopics->Count(); i++ )
- {
- TCbsDbTopic& topic = iTopics->At( i ).iTopicData;
- if ( topic.iHotmarked )
- {
- count += topic.iUnreadMessages;
- }
- }
- return count;
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::AddObserverL
-// Adds a topic list observer.
-// After an observer is added to the topic list,
-// it will be notified whenever an event occurs.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::AddObserverL(
- MCbsDbTopicListObserver* aObserver )
- {
- __ASSERT_DEBUG( aObserver != 0, CbsServerPanic( ECbsObserverNull ) );
- iObservers->AppendL( aObserver );
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::RemoveObserver
-// Removes a topic list observer.
-// If aObserver is not in the list, the method will panic.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::RemoveObserver(
- const MCbsDbTopicListObserver* aObserver )
- {
- __TEST_INVARIANT;
- __ASSERT_DEBUG( aObserver != 0, CbsServerPanic( ECbsObserverNull ) );
-
- TBool observerFound( EFalse );
- TInt amountOfObservers( iObservers->Count() );
-
- // Check if the observer exists and
- // find its possible location index in the array.
- for ( TInt index( 0 ); ( index < amountOfObservers ) && !observerFound; index++ )
- {
- if ( aObserver == iObservers->At( index ) )
- {
- iObservers->Delete( index );
- observerFound = ETrue;
- }
- }
-
- __TEST_INVARIANT;
-
-#ifdef _DEBUG
- if ( !observerFound )
- {
- CbsServerPanic( ECbsObserverNotFound );
- }
-#endif
-
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::TopicIndexInList
-// Finds the index of the topic matching the given topic number
-// in the topic list.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-TInt CCbsDbImpTopicList::TopicIndexInList(
- TCbsDbTopicNumber aNumber ) const
- {
- // Create a TCbsDbImpTopic to compare against and use a binary search.
- TKeyArrayFix key( _FOFF( TCbsDbImpTopic, iTopicData.iNumber ), ECmpTUint16 );
- TCbsDbImpTopic dummy;
- TInt position;
-
- dummy.iTopicData.iNumber = aNumber;
- TInt result( iTopics->FindIsq( dummy, key, position ) );
-
- if ( result != KErrNone )
- {
- position = KErrNotFound;
- }
-
- return position;
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::GetNextAndPrevTopicNumberL
-// Retrieves numbers of topics that precede and succeed the topic
-// with number aCurrentTopic.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::GetNextAndPrevTopicNumberL(
- const TCbsTopicNumber& aCurrentTopic,
- TCbsTopicNumber& aNextTopic,
- TCbsTopicNumber& aPrevTopic,
- TInt& aPosition )
- {
- // Determine position of requested topic in topic list.
- TInt index( TopicIndexInList( aCurrentTopic ) );
- User::LeaveIfError( index ); // if KErrNotFound
-
- // Determine position indications
- aPosition = 0;
- if ( index == 0 )
- {
- aPosition |= ECbsHead;
- }
- else
- {
- aPrevTopic = iTopics->At( index-1 ).iTopicData.iNumber;
- }
-
- if ( index == iTopics->Count()-1 )
- {
- aPosition |= ECbsTail;
- }
- else
- {
- aNextTopic = iTopics->At( index+1 ).iTopicData.iNumber;
- }
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::NotifyNewMessageArrivedL
-// Notifies each observer that a new message has arrived to a topic.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::NotifyNewMessageArrivedL(
- const TCbsDbMessageHandle& aHandle )
- {
- // Notify each observer.
- TInt count( iObservers->Count() );
- for ( TInt index( 0 ); index < count; index++ )
- {
- iObservers->At( index )->TopicNewMessageReceivedIndL( aHandle );
- }
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::AppendSubscribedTopicsL
-// Adds numbers of subscribed topics to the given array.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::AppendSubscribedTopicsL(
- CArrayFixFlat<TUint16>& aSubscriptions ) const
- {
- TInt count( iTopics->Count() );
- for ( TInt i( 0 ); i < count; i++ )
- {
- TCbsDbImpTopic& topic = iTopics->At( i );
- if ( topic.iTopicData.iSubscribed )
- {
- aSubscriptions.AppendL( topic.iTopicData.iNumber );
- }
- }
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::LoadRootStreamL
-// Loads the root stream to the memory.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::LoadRootStreamL()
- {
- __ASSERT_DEBUG( iTopicLists != NULL,
- CbsServerPanic( ECbsTopicListArrayNull ) );
-
- // Get the root stream and open it.
- TStreamId id( TopicStoreL()->Root() );
- RStoreReadStream instream;
- instream.OpenLC( *TopicStoreL(), id ); // on CS
-
- // Load the topic list count
- TInt topicListCount( instream.ReadInt16L() );
-
- // Sanity check
- if ( topicListCount < 0 )
- {
- User::Leave( KErrCorrupt );
- }
-
- // Reset the topic list array
- iTopicLists->Reset();
-
- // Load the topic list information
- TCbsDbImpTopicList item;
- instream >> item.iTopicListId;
- ReadTopicListInformationL( item.iTopicListId, item );
- iTopicLists->AppendL( item );
-
- // Destroy the stream.
- CleanupStack::PopAndDestroy(); // instream
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::LoadDefaultTopicStreamL
-// Loads the default topic list to the memory.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::LoadDefaultTopicStreamL()
- {
- __ASSERT_DEBUG( iTopics != NULL,
- CbsServerPanic( ECbsTopicListArrayNull ) );
-
- // Read root item count
- TInt topicListCount = iTopicLists->Count();
-
- // If there isn't any, create a topic list for standard topics here
- if ( topicListCount == 0 )
- {
- CreateStandardTopicListL();
- topicListCount = iTopicLists->Count();
- }
-
- TStreamId defaultTopicListId( 0 );
- TBool quitSearch( EFalse );
-
- TInt i;
- // Find the default topic list
- for ( i = 0; ( i < topicListCount ) && !quitSearch; ++i )
- {
- if ( iTopicLists->At( i ).iIsDefaultTopicList )
- {
- defaultTopicListId = iTopicLists->At( i ).iTopicListId;
- quitSearch = ETrue;
- }
- }
-
- CArrayFixFlat< TStreamId >* topicIds =
- new ( ELeave ) CArrayFixFlat< TStreamId >( KTopicIdsGranularity );
-
- // Open the default topic list stream
- RStoreReadStream instream;
- instream.OpenLC( *TopicStoreL(), defaultTopicListId ); // on CS
-
- // Set the ID
- iCurrentTopicList.iTopicListId = defaultTopicListId;
-
- // Set the name
- HBufC* topicListName = HBufC::NewL( instream, KCbsDbTopicNameLength );
- iCurrentTopicList.iTopicListName.Copy( topicListName->Des() );
- delete topicListName;
- topicListName = NULL;
-
- // Skip default list status, since it is always true in default topic list
- CbsStreamHelper::ReadBoolL( instream );
- iCurrentTopicList.iIsDefaultTopicList = ETrue;
-
- // Set the topic list number
- iCurrentTopicList.iNumber = instream.ReadInt16L();
-
- // Read the amount of topics
- TInt topicCount = instream.ReadInt16L();
- iCurrentTopicList.iTopicCount = topicCount;
-
- // Clear the topic array.
- iTopics->ResizeL( 0 );
-
- TStreamId id( 0 );
-
- // Load the topic IDs
- for ( i = 0; i < topicCount; i++ )
- {
- instream >> id;
- topicIds->AppendL( id );
- }
-
- // Destroy the stream.
- CleanupStack::PopAndDestroy();
-
- // Load necessary information for each topic
- TInt count = topicIds->Count();
- TCbsDbImpTopic topic;
- for ( i = 0; i < count; i++ )
- {
- ReadTopicInformationL( topicIds->At( i ), topic );
-
- if ( topic.iTopicData.iNumber == KIndexTopicNumber )
- {
- HBufC* indexName = ReadIndexTopicNameLC(); // on CS
- topic.iTopicData.iName.Copy( *indexName );
- CleanupStack::PopAndDestroy(); // indexName
- }
-
- iTopics->AppendL( topic );
- }
- delete topicIds;
- topicIds = NULL;
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::ReadTopicListInformationL
-// Reads topic list information from stream.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::ReadTopicListInformationL(
- const TStreamId& aId,
- TCbsDbImpTopicList& aTopicList ) const
- {
- RStoreReadStream instream;
- instream.OpenLC( *TopicStoreL(), aId ); // on CS
-
- // Topic List name
- HBufC* topicListName = HBufC::NewL( instream, KCbsDbTopicNameLength );
- aTopicList.iTopicListName.Copy( topicListName->Des() );
- delete topicListName;
- topicListName = NULL;
-
- // Default list status
- aTopicList.iIsDefaultTopicList = CbsStreamHelper::ReadBoolL( instream );
-
- // Topic List number
- aTopicList.iNumber = instream.ReadInt16L();
-
- // Topic count of this topic list
- aTopicList.iTopicCount = instream.ReadInt16L();
-
- CleanupStack::PopAndDestroy(); // instream
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::ReadTopicInformationL
-// Reads all information on topic found in stream aId
-// into aTopic.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::ReadTopicInformationL(
- const TStreamId& aId,
- TCbsDbImpTopic& aTopic ) const
- {
- RStoreReadStream instream;
- instream.OpenLC( *TopicStoreL(), aId ); // on CS
-
- // Topic ID
- aTopic.iTopicId = aId;
-
- // Read saved messages.
- aTopic.iTopicData.iSavedMessages = instream.ReadInt16L();
-
- // Read name.
- instream >> aTopic.iTopicData.iName;
-
- // Read topic number (message identifier)
- aTopic.iTopicData.iNumber = instream.ReadInt16L();
-
- // Read statuses
- aTopic.iTopicData.iProtected = CbsStreamHelper::ReadBoolL( instream ); // Protected
- aTopic.iTopicData.iSubscribed = CbsStreamHelper::ReadBoolL( instream );// Subscribed
- aTopic.iTopicData.iHotmarked = CbsStreamHelper::ReadBoolL( instream ); // Hotmarked
-
- // Read unread messages count
- aTopic.iTopicData.iUnreadMessages = instream.ReadInt16L();
-
- // Topic messages' stream ID
- instream >> aTopic.iTopicMessagesId;
-
- // Sanity check
- if ( aTopic.iTopicData.iSavedMessages > KCbsDbMaxSavedMessages
- || aTopic.iTopicData.iNumber > KCbsMaxValidTopicNumber
- || aTopic.iTopicData.iUnreadMessages > KCbsDbMaxReceivedMessages )
- {
- User::Leave( KErrCorrupt );
- }
-
- CleanupStack::PopAndDestroy(); // instream
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::DoAddTopicL
-// Adds a topic into the database.
-// Assumes aTopic is not a duplicate.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::DoAddTopicL(
- const TCbsDbTopic& aTopic )
- {
- // About to write to FFS: make critical level check
- CbsUtils::FFSCriticalLevelCheckL( KTopicStreamSize +
- KEmptyTopicMessagesStreamSize, iFs );
-
- // Generate general information about topic.
- TCbsDbImpTopic topic;
- topic.iTopicData = aTopic;
-
- // Write stream for messages.
- topic.iTopicMessagesId =
- CCbsDbImpTopicMessages::CreateDefaultTopicMessagesStreamL(
- *TopicStoreL() );
-
- // Create stream for topic information.
- RStoreWriteStream outstream;
- topic.iTopicId = outstream.CreateLC( *TopicStoreL() ); // on CS
-
- WriteTopicInformationL( outstream, aTopic, topic.iTopicMessagesId );
-
- outstream.CommitL();
- CleanupStack::PopAndDestroy(); // outstream
-
- // Now, insert the new topic information to the array
- TKeyArrayFix key( _FOFF( TCbsDbImpTopic, iTopicData.iNumber ), ECmpTUint16 );
- iTopics->InsertIsqL( topic, key );
-
- // Update the topic list stream
- UpdateTopicListStreamL( iCurrentTopicList, EFalse );
-
- // We have modified only iTopicStore, so if CommitFilesL() leaves,
- // we either get all committed or nothing committed.
- CommitFilesL();
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::DoUpdateTopicL
-// Updates the data for a topic into the database.
-// The position of the topic in the list is
-// changed if necessary.
-// If the position has to be changed, the handles of messages
-// contained in the topic have to be changed as well because
-// the high word of the handle identifies the topic by it's
-// number.
-// Please note that standard EPOC DoSomethingL protocol
-// is not followed here as this function does NOT commit
-// changes made to the store. Instead, the caller must ensure
-// use of proper commit/revert operations.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::DoUpdateTopicL(
- const TCbsDbTopic& aTopic,
- TBool aNeedToChange,
- TInt aOldPosition,
- TBool aDeleting )
- {
- CBSLOGSTRING("CBSSERVER: >>> CCbsDbImpTopicList::DoUpdateTopicL()");
-
- RSharedDataClient sharedData;
- // About to write to FFS: make critical level check
- if ( aDeleting )
- {
- User::LeaveIfError( sharedData.Connect() );
- sharedData.RequestFreeDiskSpaceLC( KTopicStreamSize ); // on CS
- }
- else
- {
- CbsUtils::FFSCriticalLevelCheckL( KTopicStreamSize, iFs );
- }
-
- TInt newPosition( aOldPosition );
-
- // If there is need to change position, change it.
- if ( aNeedToChange )
- {
- TCbsDbImpTopic topic( iTopics->At( aOldPosition ) );
-
- // Adjust handles of topic messages to match the changed topic number.
- iMessages->UpdateHandlesOfTopicMessagesL(
- topic.iTopicData.iNumber, aTopic.iNumber );
-
- // Delete topic from the array.
- iTopics->Delete( aOldPosition );
-
- // Set the number and reinsert into array
- topic.iTopicData.iNumber = aTopic.iNumber;
- TKeyArrayFix key( _FOFF( TCbsDbImpTopic, iTopicData.iNumber ), ECmpTUint16 );
- newPosition = iTopics->InsertIsqL( topic, key );
- }
-
- iTopics->At( newPosition ).iTopicData.iSubscribed = aTopic.iSubscribed;
- iTopics->At( newPosition ).iTopicData.iHotmarked = aTopic.iHotmarked;
- iTopics->At( newPosition ).iTopicData.iName = aTopic.iName;
- iTopics->At( newPosition ).iTopicData.iSavedMessages = aTopic.iSavedMessages;
- iTopics->At( newPosition ).iTopicData.iUnreadMessages = aTopic.iUnreadMessages;
-
- // Replace existing stream.
- RStoreWriteStream outstream;
- outstream.ReplaceLC( *TopicStoreL(),
- iTopics->At( newPosition ).iTopicId ); // on CS
- WriteTopicInformationL( outstream, aTopic,
- iTopics->At( newPosition ).iTopicMessagesId );
-
- outstream.CommitL();
- CleanupStack::PopAndDestroy(); // outstream
-
- // Free the reserved space
- if ( aDeleting )
- {
- CleanupStack::PopAndDestroy(); // disk space
- sharedData.Close();
- }
-
- // Update topic list stream, if necessary.
- if ( aNeedToChange )
- {
- UpdateTopicListStreamL( iCurrentTopicList, EFalse );
- }
-
- CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicList::DoUpdateTopicL()");
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::DoDeleteTopicL
-// Deletes a topic from the given position in the database.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::DoDeleteTopicL(
- TInt aPosition )
- {
- // Check that the topic is not protected.
- TCbsDbTopic topic;
- GetTopicL( aPosition, topic );
-
- // It is not allowed to delete a topic that is protected. It must
- // first be updated to be not protected.
- if ( topic.iProtected )
- {
- User::Leave( KErrAccessDenied );
- }
-
- // First delete all messages the topic contains.
- RStoreReadStream instream;
- instream.OpenLC( *TopicStoreL(),
- iTopics->At( aPosition ).iTopicMessagesId ); // on CS
- CCbsDbImpTopicMessages::DeleteAllTopicMessagesL( *TopicStoreL(),
- *iUnsavedMessageStore, instream );
- iMessages->InvalidateCache();
- CleanupStack::PopAndDestroy(); // instream
-
- // Delete topic and topic messages streams.
- TopicStoreL()->DeleteL( iTopics->At( aPosition ).iTopicMessagesId );
- TopicStoreL()->DeleteL( iTopics->At( aPosition ).iTopicId );
-
- // Remove from the internal cache.
- iTopics->Delete( aPosition );
-
- iCurrentTopicList.iTopicCount--;
- UpdateTopicListStreamL( iCurrentTopicList, ETrue );
- CommitFilesL();
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::UpdateRootStreamL
-// Updates the root stream.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::UpdateRootStreamL(
- TBool aDeleting )
- {
- // Check the free space
- TInt neededSpace( KTopicListRootStreamSize + iTopicLists->Count() * 2 );
-
- RSharedDataClient sharedData;
- // About to write to FFS: make critical level check
- if ( aDeleting )
- {
- User::LeaveIfError( sharedData.Connect() );
- sharedData.RequestFreeDiskSpaceLC( neededSpace ); // on CS
- }
- else
- {
- CbsUtils::FFSCriticalLevelCheckL( neededSpace, iFs );
- }
-
- // Now there is room for all topics. So we can just replace.
- RStoreWriteStream outstream;
- outstream.ReplaceLC( *TopicStoreL(), TopicStoreL()->Root() ); // on CS
-
- // Write root stream
- WriteRootStreamL( outstream );
- CleanupStack::PopAndDestroy(); // outstream
-
- // Free the reserved space
- if ( aDeleting )
- {
- CleanupStack::PopAndDestroy(); // disk space
- sharedData.Close();
- }
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::UpdateTopicListStreamL
-// Updates topic list stream.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::UpdateTopicListStreamL(
- TCbsDbImpTopicList& aTopicList,
- TBool aDeleting )
- {
- TInt neededSpace( KTopicListStreamSize + iTopics->Count() * 2 );
-
- RSharedDataClient sharedData;
- // About to write to FFS: make critical level check
- if ( aDeleting )
- {
- User::LeaveIfError( sharedData.Connect() );
- sharedData.RequestFreeDiskSpaceLC( neededSpace ); // on CS
- }
- else
- {
- CbsUtils::FFSCriticalLevelCheckL( neededSpace, iFs );
- }
-
- // Replace the stream
- RStoreWriteStream outstream;
- outstream.ReplaceLC( *TopicStoreL(), aTopicList.iTopicListId ); // on CS
-
- // Write root stream
- WriteTopicListStreamL( outstream, aTopicList );
- CleanupStack::PopAndDestroy(); // outstream
-
- // Free the reserved space
- if ( aDeleting )
- {
- CleanupStack::PopAndDestroy(); // disk space
- sharedData.Close();
- }
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::UpdateTopicL
-// Updates the information for a topic already existing
-// in the database.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::UpdateTopicL(
- TCbsDbTopicNumber aTopicNumber,
- TCbsDbTopic& aTopic )
- {
- // Check that the new topic number is unique.
- TBool needToChangePosition( ETrue );
-
- // Try to find the topic and leave if it was not found.
- TInt oldPosition( TopicIndexInList( aTopicNumber ) );
- User::LeaveIfError( oldPosition );
-
- // Check if we have to change the position of the topic in the
- // internal array
- if ( aTopic.iNumber == aTopicNumber )
- {
- needToChangePosition = EFalse;
- }
- else
- {
- TInt topicWithTheNewNumber( TopicIndexInList( aTopic.iNumber ) );
- if ( topicWithTheNewNumber != KErrNotFound &&
- topicWithTheNewNumber != oldPosition )
- {
- User::Leave( KErrAlreadyExists );
- }
- }
-
- // Write data to store.
- // Deviation from EPOC standards: DoUpdateTopicL does NOT commit
- // the store.
- TRAPD( result, DoUpdateTopicL( aTopic, needToChangePosition,
- oldPosition, EFalse ) );
-
- // Commit both topic and unsaved msgs store
- if ( result == KErrNone )
- {
- TRAP( result, CommitFilesL() );
- }
-
- // If either DoUpdateTopicL or CommitFilesL fails => revert.
- if ( result != KErrNone )
- {
- TopicStoreL()->Revert();
- ReloadRootStreamL();
- User::Leave( result );
- }
- else
- {
- // Notify the observers.
- NotifyTopicModifiedL( aTopicNumber );
- }
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::CheckTopicNumber
-// Checks if a topic number is valid.
-// The valid topic number range in this implementation is
-// 000..999, with 000 indicating an index message.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-TBool CCbsDbImpTopicList::CheckTopicNumber(
- TCbsDbTopicNumber aNumber ) const
- {
- // Check that the number is in proper range
- return aNumber <= KCbsMaxValidTopicNumber;
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::WriteRootStreamL
-// Write the root stream.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::WriteRootStreamL(
- RWriteStream& aOut ) const
- {
- // Write the total amount of topic lists
- TInt topicListCount( iTopicLists->Count() );
- aOut.WriteInt16L( topicListCount );
-
- // Write space for topic list stream ids
- TInt index;
- for ( index = 0; index < topicListCount; index++ )
- {
- aOut << iTopicLists->At( index ).iTopicListId;
- }
-
- // Write null stream ids
- for ( ; index < KCbsRootItemsSize; index++ )
- {
- aOut << TStreamId( 0 );
- }
-
- aOut.CommitL();
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::WriteTopicListStreamL
-// Writes topic list information to specified stream.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::WriteTopicListStreamL(
- RWriteStream& aOut,
- TCbsDbImpTopicList& aTopicList ) const
- {
- // Write the values to this topic list's stream
-
- // Topic List name
- aOut << aTopicList.iTopicListName;
-
- // Is this the default list
- CbsStreamHelper::WriteBoolL( aOut, aTopicList.iIsDefaultTopicList );
-
- // Topic List number
- aOut.WriteInt16L( aTopicList.iNumber );
-
- // NUmber of topics in this list
- aOut.WriteInt16L( iTopics->Count() );
-
- // Write the stream IDs of the topics belonging to this list
- TInt i;
- for ( i = 0; i < iTopics->Count(); i++ )
- {
- aOut << iTopics->At( i ).iTopicId;
- }
-
- // Write space for the rest topic stream IDs
- for ( ; i < KCbsDbTopicArraySize; i++ )
- {
- aOut << TStreamId( 0 );
- }
-
- aOut.CommitL();
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::NotifyTopicListInitializedL
-// Notifies each observer that the topic list has been initialized.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::NotifyTopicListInitializedL()
- {
- // Notify each observer.
- TInt count( iObservers->Count() );
- for( TInt index( 0 ); index < count; index++ )
- {
- iObservers->At( index )->TopicListInitializedIndL();
- }
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::NotifyTopicAddedL
-// Notifies each observer that a topic has been added.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::NotifyTopicAddedL(
- TCbsDbTopicNumber aNumber )
- {
- // Notify each observer.
- TInt count( iObservers->Count() );
- for ( TInt index( 0 ); index < count; index++ )
- {
- iObservers->At( index )->TopicAddedIndL( aNumber );
- }
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::NotifyTopicModifiedL
-// Notifies each observer that a topic has been modified.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::NotifyTopicModifiedL(
- TCbsDbTopicNumber aNumber )
- {
- // Notify each observer.
- TInt count( iObservers->Count() );
- for( TInt index( 0 ); index < count; index++ )
- {
- iObservers->At( index )->TopicModifiedIndL( aNumber );
- }
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::NotifyTopicDeletedL
-// Notifies each observer that a topic has been deleted.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::NotifyTopicDeletedL(
- TCbsDbTopicNumber aNumber )
- {
- // Notify each observer.
- TInt count( iObservers->Count() );
- for( TInt index( 0 ); index < count; index++ )
- {
- iObservers->At( index )->TopicDeletedIndL( aNumber );
- }
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::SetHotmarkedMessage
-// Sets the hotmarked message handle.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::SetHotmarkedMessage(
- const TCbsDbMessageHandle& aMessageHandle )
- {
- // Set the hotmarked message.
- iIsHotmarkedMessage = ETrue;
- iMessageHandle = aMessageHandle;
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::CreateDefaultRootStreamL
-// Creates a root stream and writes default values into it.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-TStreamId CCbsDbImpTopicList::CreateDefaultRootStreamL(
- CStreamStore& aStore ) const
- {
- // Create the stream
- RStoreWriteStream outstream;
- TStreamId id( outstream.CreateLC( aStore ) ); // on CS
-
- // Write the amount of topic lists
- outstream.WriteInt16L( 0 );
-
- // Write space for topic list stream ids
- for ( TInt index( 0 ); index < KCbsRootItemsSize; index++ )
- {
- outstream << TStreamId( 0 );
- }
-
- outstream.CommitL();
- CleanupStack::PopAndDestroy(); // aStore
-
- // Return the stream id.
- return id;
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::WriteTopicInformationL
-// Writes topic data into a stream.
-// This includes number of saved messages,
-// number of unread messages, topic handle,
-// topic name, topic number, protection status,
-// subscription status and hotmark status.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::WriteTopicInformationL(
- RWriteStream& aOut,
- const TCbsDbTopic& aTopic,
- const TStreamId& aTopicMessagesId ) const
- {
- // Write saved messages.
- aOut.WriteInt16L( aTopic.iSavedMessages );
-
- // Write name.
- aOut << aTopic.iName;
-
- // Write topic number (message identifier)
- aOut.WriteInt16L( aTopic.iNumber );
-
- // Write statuses
- CbsStreamHelper::WriteBoolL( aOut, aTopic.iProtected ); // Protected
- CbsStreamHelper::WriteBoolL( aOut, aTopic.iSubscribed ); // Subscribed
- CbsStreamHelper::WriteBoolL( aOut, aTopic.iHotmarked ); // Hotmarked
-
- // Write unread messages count
- aOut.WriteInt16L( aTopic.iUnreadMessages );
-
- // And then write the topic messages stream id.
- aOut << aTopicMessagesId;
- }
-
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::RevertFilesL
-// Reverts all changes made to three datafiles handled by this class.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::RevertFilesL()
- {
-
- // Check for file lock
- CheckFileLockL();
-
- iTopicStore->Revert();
- iUnsavedMessageStore->Revert();
- ReloadRootStreamL();
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::CommitFilesL
-// Commits all changes made to two datafiles handled by this class.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::CommitFilesL()
- {
- TopicStoreL()->CommitL();
- TInt errorCode( iUnsavedMessageStore->Commit() );
-
- // If committing of the unsaved msg store fails, remove all
- // messages in the store and rebuild the topic list
- if ( errorCode != KErrNone )
- {
- TRAPD( errorCode2, RebuildUnsavedMessageStoreL() );
- if ( errorCode2 != KErrNone )
- {
- CActiveScheduler::Stop();
- User::Leave( KErrServerTerminated );
- }
-
- // Tell the caller that something went wrong
- User::Leave( errorCode );
- }
-
- // Check if we should compact
- TTime now;
- TTimeIntervalMinutes interval;
- now.UniversalTime();
- now.MinutesFrom( iPreviousCompact, interval );
- if ( interval.Int() >= KMinimumCompactInterval )
- {
- TopicStoreL()->CompactL();
- iUnsavedMessageStore->CompactL();
- iPreviousCompact = now;
- }
-
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::RebuildUnsavedMessageStoreL
-// Deletes the unsaved messages' store and rebuilds it.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::RebuildUnsavedMessageStoreL()
- {
- // Close the stores and delete the unsaved store
- delete iUnsavedMessageStore; iUnsavedMessageStore = NULL;
- delete iTopicStore; iTopicStore = NULL;
- CbsUtils::DeleteFileL( iFs, *iUnsavedMessagesFilename );
-
- // Re-create the store
- DoCreateStoreL( *iUnsavedMessagesFilename );
- TryToOpenFilesL( ETrue, EFalse );
-
- // Remove the stream ids to unsaved messages, because
- // they were all just deleted.
- HandleDeletionOfUnsavedMessagesFileL();
-
- // Compact the topic list
- TopicStoreL()->CommitL();
- TopicStoreL()->CompactL();
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::RebuildTopicAndUnsavedStoresL
-// Deletes and rebuilds topic/topic list and unsaved message stores.
-// Loads Standard Topic List into memory.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::RebuildTopicAndUnsavedStoresL()
- {
- __TEST_INVARIANT;
-
- // Check for file lock
- CheckFileLockL();
-
- // About to write to FFS: make critical level check
- CbsUtils::FFSCriticalLevelCheckL( KTopicListRootStreamSize +
- KDefaultTopicListSize * 2, iFs );
-
- if ( iMessages != NULL && iMessages->IsLockedMessages() )
- {
- User::Leave( KErrAccessDenied );
- }
-
- delete iTopicStore;
- iTopicStore = NULL;
- delete iUnsavedMessageStore;
- iUnsavedMessageStore = NULL;
- CbsUtils::DeleteFileL( iFs, *iTopicsFilename );
- CbsUtils::DeleteFileL( iFs, *iUnsavedMessagesFilename );
-
- // Create new files.
- OpenFilesL( ETrue, EFalse );
-
- // Add standard index topic.
- AddIndexTopicL();
-
- // Load the Standard Topic list
- LoadDefaultTopicStreamL();
-
- iIsHotmarkedMessage = EFalse;
- iLastTopicNumber = 0;
- iMessageHandle = 0;
-
- // Inform the message manager.
- if ( iMessages )
- {
- iMessages->InvalidateCache();
- }
-
- // Notify everyone.
- NotifyTopicListInitializedL();
-
- __TEST_INVARIANT;
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::GetLatestTopicNumber
-// Returns the number of the topic that was added last
-// to the database by topic detection feature.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-TInt CCbsDbImpTopicList::GetLatestTopicNumber(
- TCbsTopicNumber& aNumber ) const
- {
- TInt result( KErrNone );
- if ( iLastTopicNumber == 0 )
- {
- result = KErrNotFound;
- }
- aNumber = iLastTopicNumber;
- return result;
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::OpenFilesL
-// After a call to this function, the file stores can be assumed
-// to be open and initialized.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::OpenFilesL(
- TBool aDeleteExistingFiles,
- TBool aCreateNewTopicList )
- {
- __ASSERT_DEBUG( iTopicsFilename->Length() > 0,
- CbsServerPanic( ECbsInvalidFilenameDescriptor ) );
- __ASSERT_DEBUG( iUnsavedMessagesFilename->Length() > 0,
- CbsServerPanic( ECbsInvalidFilenameDescriptor ) );
-
- // if LFS, delete files, create files, open files, write root stream
- // if not LFS, create file if it doesn't exist, open files
-
- // Close file stores.
- delete iTopicStore;
- iTopicStore = NULL;
- delete iUnsavedMessageStore;
- iUnsavedMessageStore = NULL;
-
- // If any of files doesn't exist, create the file. Also writes the root
- // stream of the topic file, if necessary.
- // It is possible that this operation fails because FFS is full.
- // In this case the server will take a break and retry. If the second
- // attempt fails, the server is shut down.
- TBool unsavedMsgFileExists( EFalse );
- TRAPD( result, CreateFilesIfNecessaryL( unsavedMsgFileExists ) );
- if ( result != KErrNone )
- {
- // Critical exception: wait for a while and retry.
- User::After( KWaitAfterCriticalStoreException );
- TBool ignoreThis( EFalse ); // value of unsavedMsgFileExists preserved
- TRAP( result, CreateFilesIfNecessaryL( ignoreThis ) );
- if ( result != KErrNone )
- {
- __DEBUGGER();
- // Recovery is not possible: shut the server down.
- CActiveScheduler::Stop();
- User::Leave( KErrServerTerminated );
- }
- }
-
- // Open the files for use. Also reads the topic file root stream.
- TryToOpenFilesL( unsavedMsgFileExists == EFalse &&
- aDeleteExistingFiles == EFalse,
- aCreateNewTopicList );
-
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::CreateFilesIfNecessaryL
-// Creates CBS files, if appropriate.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::CreateFilesIfNecessaryL(
- TBool& aUnsavedMsgFileExisted )
- {
- if ( CbsUtils::ExistsL( iFs, *iTopicsFilename ) == EFalse )
- {
- CbsUtils::FFSCriticalLevelCheckL( KTopicListRootStreamSize +
- KDefaultTopicListSize * 2, iFs );
-
- CPermanentFileStore* store = CPermanentFileStore::CreateLC( iFs,
- *iTopicsFilename, EFileWrite ); // on CS
-
- store->SetTypeL( store->Layout() );
- TStreamId id( CreateDefaultRootStreamL( *store ) );
- store->SetRootL( id );
- store->CommitL();
- CleanupStack::PopAndDestroy(); // store
- }
-
- aUnsavedMsgFileExisted = CbsUtils::ExistsL( iFs,
- *iUnsavedMessagesFilename );
- if ( aUnsavedMsgFileExisted == EFalse )
- {
- // No critical level check, because unsaved msgs reside on ramdisk
- DoCreateStoreL( *iUnsavedMessagesFilename );
- }
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::DoCreateStoreL
-// Creates an empty file store with the given filename.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::DoCreateStoreL(
- const TDesC& aFilename )
- {
- CFileStore* store = CPermanentFileStore::CreateLC( iFs,
- aFilename, EFileWrite ); // on CS
- store->SetTypeL( store->Layout() );
- store->CommitL();
- CleanupStack::PopAndDestroy();
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::TryToOpenFilesL
-// Tries to open topic and unsaved messages files.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::TryToOpenFilesL(
- TBool aDeleteUnsavedMsgStreamIds,
- TBool aCreateNewTopicList )
- {
- CBSLOGSTRING("CBSSERVER: >>> CCbsDbImpTopicList::TryToOpenFilesL()" );
-
- if ( !iTopicStore )
- {
- CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicList::TryToOpenFilesL(): *** NO iTopicStore (1) ***" );
- }
-
- // Try to open the store
- TRAPD( error, iTopicStore = CFileStore::OpenL( iFs, *iTopicsFilename, EFileRead | EFileWrite ) );
- CBSLOGSTRING2("CBSSERVER: CCbsDbImpTopicList::TryToOpenFilesL(); iTopicStore OpenL() error: %d", error );
-
- TRAPD( error2, iUnsavedMessageStore = CFileStore::OpenL( iFs, *iUnsavedMessagesFilename, EFileRead | EFileWrite ) );
- CBSLOGSTRING2("CBSSERVER: CCbsDbImpTopicList::TryToOpenFilesL(); iUnsavedMessageStore OpenL() error: %d", error2 );
-
- if ( error || error2 )
- {
- CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicList::TryToOpenFilesL(): Calling InitializeListL( ETrue )..." );
-
- InitializeListL( ETrue );
-
- CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicList::TryToOpenFilesL(): Calling InitializeListL( ETrue ) finished." );
- }
- else
- {
- if ( iTopicLists->Count() == 0 &&
- aDeleteUnsavedMsgStreamIds &&
- aCreateNewTopicList )
- {
- // Create first topic list, since it was deleted with the file
- CreateStandardTopicListL();
- }
-
- // Load the root stream for topic store.
- LoadRootStreamL();
-
- if ( aDeleteUnsavedMsgStreamIds )
- {
- // Load the topics and repair the topic file
- // since unsaved msg file has been deleted
- LoadDefaultTopicStreamL();
- HandleDeletionOfUnsavedMessagesFileL();
- }
- }
- CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicList::TryToOpenFilesL()" );
- }
-
-// ---------------------------------------------------------
-// CCbsDbImpTopicList::ReadIndexTopicNameLC()
-// Reads the localized index topic name
-// (other items were commented in a header).
-// ---------------------------------------------------------
-HBufC* CCbsDbImpTopicList::ReadIndexTopicNameLC()
- {
- // Open localized resource file.
- RResourceFile resourceFile;
-
- CbsUtils::FindAndOpenDefaultResourceFileLC( iFs, resourceFile ); // on CS
- // Read "Index"-string.
- TResourceReader reader;
- reader.SetBuffer( resourceFile.AllocReadLC( R_TEXT_INDEX_TOPIC ) );//on CS
- HBufC* text = reader.ReadHBufCL();
- CleanupStack::PopAndDestroy(2); // readerBuf, resourceFile
- CleanupStack::PushL( text );
-
- return text;
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::AddIndexTopicL
-// Adds index topic to topic list.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::AddIndexTopicL()
- {
- // Open localized resource file.
- HBufC* text = ReadIndexTopicNameLC();
-
- TCbsDbTopic topic;
- topic.iName.Copy( *text );
- topic.iNumber = 0;
- topic.iHotmarked = EFalse;
- topic.iProtected = ETrue;
- topic.iSubscribed = ETrue;
- topic.iSavedMessages = 0;
- topic.iUnreadMessages = 0;
-
- // Add the topic without notifying anybody.
- TRAPD( error, DoAddTopicL( topic ) );
- if ( error != KErrNone )
- {
- RevertFilesL();
- __TEST_INVARIANT;
- User::Leave( error );
- }
-
- CleanupStack::PopAndDestroy(); // text
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::HandleDeletionOfUnsavedMessagesFileL
-// Called to repair the database when Unsaved messages -file
-// has been deleted, but Topics-file still contains information
-// on unsaved messages.
-//
-// Things to do here:
-// - Reset unread message counters, because a saved message
-// is always also read.
-// - Remove stream ids to unsaved messages from
-// Topic messages -streams.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::HandleDeletionOfUnsavedMessagesFileL()
- {
- TRAPD( result, DoHandleDeletionOfUnsavedMessagesFileL() );
- if ( result != KErrNone )
- {
- // Recovery impossible -> reset the database.
- // Note that this function is not called when the database
- // is initialized.
- RebuildTopicAndUnsavedStoresL();
- }
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::DoHandleDeletionOfUnsavedMessagesFileL
-// Does the work for HandleDeletionOfUnsavedMessagesFileL().
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::DoHandleDeletionOfUnsavedMessagesFileL()
- {
- // Reset the unread counter of each topic and delete stream ids of
- // unsaved messages.
- TInt numberOfTopics( iTopics->Count() );
- for ( TInt i( 0 ); i < numberOfTopics; i++ )
- {
- TCbsDbTopic topic;
- FindTopicByNumberL( iTopics->At( i ).iTopicData.iNumber, topic );
- topic.iUnreadMessages = 0;
- DoUpdateTopicL( topic, EFalse, i, EFalse );
- DeleteUnsavedMessageStreamIdsL( iTopics->At( i ).iTopicMessagesId );
- }
-
- UpdateTopicListStreamL( iCurrentTopicList, ETrue );
- TopicStoreL()->CommitL();
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::DeleteUnsavedMessageStreamIdsL
-// This function is called when the unsaved messages file has
-// been deleted but the Topic messages -stream still contains
-// stream ids to deleted message streams.
-// All stream ids found in the given topic messages -stream
-// pointing to the unsaved messages file are removed.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::DeleteUnsavedMessageStreamIdsL(
- const TStreamId& aMsgStreamId ) const
- {
- CArrayFixFlat< TStreamId >* streamIds =
- new ( ELeave ) CArrayFixFlat< TStreamId >( KTypicalNumberOfTopicMessages );
- CleanupStack::PushL( streamIds );
-
- RStoreReadStream instream;
- instream.OpenLC( *TopicStoreL(), aMsgStreamId ); // on CS
-
- // Read msg count
- TInt numberOfMsgs( instream.ReadInt16L() );
-
- // Read max msg count
- TInt maxNumberOfMsgs( instream.ReadInt16L() );
-
- TInt index( 0 );
-
- for ( ; index < numberOfMsgs; index++ )
- {
- TBool saved( CbsStreamHelper::ReadBoolL( instream ) );
- TStreamId id( 0 );
- instream >> id;
- if ( saved )
- {
- streamIds->AppendL( id );
- }
- }
-
- CleanupStack::PopAndDestroy(); // instream
-
- // Write stream ids of saved messages into the new topic message stream
- // which replaces the stream identified with aMsgStreamId.
- RStoreWriteStream outstream;
- outstream.ReplaceLC( *TopicStoreL(), aMsgStreamId ); // on CS
-
- TInt numberOfSavedmessages( streamIds->Count() );
-
- // Number of messages = number of saved messages
- outstream.WriteInt16L( numberOfSavedmessages );
-
- // Number of saved messages <= number of messages <= maxNumberOfMsgs
- outstream.WriteInt16L( maxNumberOfMsgs );
-
- for ( index = 0; index < numberOfSavedmessages; index++ )
- {
- // All messages are saved (i.e., permanent)
- CbsStreamHelper::WriteBoolL( outstream, ETrue );
- outstream << streamIds->At( index );
- }
-
- for ( ; index < maxNumberOfMsgs; index ++ )
- {
- CbsStreamHelper::WriteBoolL( outstream, EFalse );
- outstream << TStreamId( 0 );
- }
-
- outstream.CommitL();
- CleanupStack::PopAndDestroy(2); // outstream, streamIds
-
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::UpdateTopicCountersL
-// Resolves the topic position in topic list and uses this information
-// to call DoUpdateTopicL.
-// Changes to stores are NOT commited.
-// Call to DoUpdateTopicL is not trapped.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::UpdateTopicCountersL(
- const TCbsDbTopic& aTopic,
- const TBool aDeleting )
- {
- CBSLOGSTRING("CBSSERVER: >>> CCbsDbImpTopicList::UpdateTopicCountersL()");
-
- // Find out the position of the topic in topic list.
- TInt index( TopicIndexInList( aTopic.iNumber ) );
- if ( index == KErrNotFound )
- {
- User::Leave( KErrNotFound );
- }
-
- // DoUpdateTopicL leaves changes uncommited. EFalse for not having to
- // change topic position in topic list.
- DoUpdateTopicL( aTopic, EFalse, index, aDeleting );
-
- CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicList::UpdateTopicCountersL()");
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::CreateStandardTopicListL
-// Creates the Standard topic list (topic list no. 0)
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::CreateStandardTopicListL()
- {
- // Read standard topic list name from the resource file
- RResourceFile resourceFile;
- CbsUtils::FindAndOpenDefaultResourceFileLC( iFs, resourceFile ); // on CS
-
- TResourceReader reader;
- reader.SetBuffer( resourceFile.AllocReadLC( R_TEXT_STANDARD_TOPIC_LIST ) ); // on CS
- HBufC* standardTopicListName = reader.ReadHBufCL();
- CleanupStack::PushL( standardTopicListName );
-
- // Create a new topic list
- CreateNewTopicListL( standardTopicListName->Des() );
-
- CleanupStack::PopAndDestroy( 3 ); // resourceFile, reader, standardTopicListName
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::LoadTopicsIdsL
-// Reads topic IDs of a topic list from the stream.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::LoadTopicsIdsL(
- const TStreamId& aTopicListStreamId )
- {
- // Open the topic list stream
- RStoreReadStream instream;
- instream.OpenLC( *TopicStoreL(), aTopicListStreamId ); // on CS
-
- // Skip topic list name
- delete HBufC::NewL( instream, KCbsDbTopicNameLength );
-
- // Skip default list status
- CbsStreamHelper::ReadBoolL( instream );
-
- // Skip Topic List number
- instream.ReadInt16L();
-
- // Skip the amount of topics
- TInt topicCount = instream.ReadInt16L();
-
- // Clear the array
- iTopicIds->ResizeL( 0 );
-
- TStreamId id( 0 );
-
- // Load the topic IDs
- for ( TInt i = 0; i < topicCount; i++ )
- {
- instream >> id;
- iTopicIds->AppendL( id );
- }
-
- CleanupStack::PopAndDestroy(); // instream
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::LoadTopicsL
-// Loads topics of a specified topic list.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::LoadTopicsL(
- const TStreamId& aTopicListStreamId )
- {
- // Open the topic list stream
- RStoreReadStream instream;
- instream.OpenLC( *TopicStoreL(), aTopicListStreamId ); // on CS
-
- // Skip topic list name
- delete HBufC::NewL( instream, KCbsDbTopicNameLength );
-
- // Skip default list status
- CbsStreamHelper::ReadBoolL( instream );
-
- // Skip Topic List number
- instream.ReadInt16L();
-
- // Skip the amount of topics
- TInt topicCount = instream.ReadInt16L();
-
- // Clear the arrays
- iTopics->ResizeL( 0 );
- iTopicIds->ResizeL( 0 );
-
- TStreamId id( 0 );
-
- // Load the topic IDs
- TInt i;
- for ( i = 0; i < topicCount; i++ )
- {
- instream >> id;
- iTopicIds->AppendL( id );
- }
-
- CleanupStack::PopAndDestroy(); // instream
-
- // Load necessary information for each topic
- TInt count = iTopicIds->Count();
- TCbsDbImpTopic topic;
- for ( i = 0; i < count; i++ )
- {
- ReadTopicInformationL( iTopicIds->At( i ), topic );
-
- if ( topic.iTopicData.iNumber == KIndexTopicNumber )
- {
- HBufC* indexName = ReadIndexTopicNameLC(); // on CS
- topic.iTopicData.iName.Copy( *indexName );
- CleanupStack::PopAndDestroy(); // indexName
- }
- iTopics->AppendL( topic );
- }
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::UpdateTopicStreamIdsL
-// Updates the topic stream IDs.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::UpdateTopicStreamIdsL(
- const TCbsDbTopicNumber aTopicNumber )
- {
- // Try to find the topic from current topic list
- TInt position( TopicIndexInList( aTopicNumber ) );
- if ( position >= 0 )
- {
- // Remove from the internal cache of this topic list
- iTopics->Delete( position );
-
- iCurrentTopicList.iTopicCount--;
-
- // Update the stream
- UpdateTopicListStreamL( iCurrentTopicList, EFalse );
- CommitFilesL();
- }
- }
-
-// -----------------------------------------------------------------------------
-// CCbsDbImpTopicList::__DbgTestInvariant
-// Checks that the object is in a valid state, and panics if it is not.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsDbImpTopicList::__DbgTestInvariant() const
- {
- /*
-#if defined(_DEBUG)
-#endif
- */
- }
-
-// ========================== OTHER EXPORTED FUNCTIONS =========================
-
-// End of File