cbs/CbsServer/ServerSrc/CCbsDbImpTopicMessages.cpp
changeset 46 2fa1fa551b0b
parent 42 35488577e233
child 48 78df25012fda
equal deleted inserted replaced
42:35488577e233 46:2fa1fa551b0b
     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 module contains the implementation of CCbsDbImpTopicMessages class 
       
    15 *                member functions. 
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 
       
    21 // INCLUDE FILES
       
    22 
       
    23 #include <e32svr.h>
       
    24 
       
    25 #include <shareddataclient.h>
       
    26 
       
    27 #include "CbsServerPanic.h"
       
    28 #include "CbsStreamHelper.h"
       
    29 #include "CbsUtils.h"
       
    30 #include "CbsDbConstants.h"
       
    31 #include "CCbsDbImpTopicList.h"
       
    32 #include "CCbsDbImpTopicMessages.h"
       
    33 #include "CCbsRecEtel.h"
       
    34 #include "CCbsReceiverHelper.h"
       
    35 
       
    36 #include "CbsLogger.h"
       
    37 
       
    38 // CONSTANTS
       
    39 
       
    40 // Expected maximum number of locked messages at once. 
       
    41 const TInt KDefaultSpaceForLockedMessages = 1;
       
    42 
       
    43 // CB message header size in bytes.
       
    44 const TInt KCbMessageHeaderSize = 16;
       
    45 
       
    46 // The space used for the header of messages stream
       
    47 const TInt KMessageRootStreamSize = 6;
       
    48 
       
    49 /// The space used by one message in the messages stream
       
    50 const TInt KMessageEntrySize = 3;
       
    51 
       
    52 // Default space reserved for topic messages in message stream
       
    53 const TInt KDefaultSpaceForMessages = 6;
       
    54 
       
    55 // Space for reading messages
       
    56 const TInt KReadMessageSize = 92;
       
    57 
       
    58 
       
    59 // ================= MEMBER FUNCTIONS =======================
       
    60 
       
    61 // -----------------------------------------------------------------------------
       
    62 // CCbsDbImpTopicMessages::CCbsDbImpTopicMessages
       
    63 // C++ default constructor can NOT contain any code, that
       
    64 // might leave.
       
    65 // -----------------------------------------------------------------------------
       
    66 //
       
    67 CCbsDbImpTopicMessages::CCbsDbImpTopicMessages( 
       
    68     CCbsDbImpTopicList& aTopicList, 
       
    69     RFs& aFs )
       
    70     :iTopicList( aTopicList ), 
       
    71     iCacheValid( EFalse ), 
       
    72     iCachedTopicNumber( 0 ), 
       
    73     iFs( aFs )
       
    74     {
       
    75     }
       
    76 
       
    77 // -----------------------------------------------------------------------------
       
    78 // CCbsDbImpTopicMessages::ConstructL
       
    79 // Symbian 2nd phase constructor can leave.
       
    80 // -----------------------------------------------------------------------------
       
    81 //
       
    82 void CCbsDbImpTopicMessages::ConstructL()
       
    83     {
       
    84     // Allocate the default size for the message list.
       
    85     iMessageList = 
       
    86         new ( ELeave ) CArrayFixFlat< TCbsDbImpTopicMessagesCacheItem > 
       
    87             ( KCbsDbMaxReceivedMessages + KCbsDbMaxSavedMessages );
       
    88 
       
    89     // Allocate the array for locked messages.
       
    90     iLockedMessages = new ( ELeave ) CArrayFixFlat< TCbsDbMessageHandle >
       
    91         ( KDefaultSpaceForLockedMessages );
       
    92     }
       
    93 
       
    94 // -----------------------------------------------------------------------------
       
    95 // CCbsDbImpTopicMessages::NewL
       
    96 // Two-phased constructor.
       
    97 // -----------------------------------------------------------------------------
       
    98 //
       
    99 CCbsDbImpTopicMessages* CCbsDbImpTopicMessages::NewL( 
       
   100     CCbsDbImpTopicList& aTopicList, RFs& aFs )
       
   101     {
       
   102     CCbsDbImpTopicMessages* self = 
       
   103         new ( ELeave ) CCbsDbImpTopicMessages( aTopicList, aFs );
       
   104     CleanupStack::PushL( self );
       
   105     self->ConstructL();
       
   106     CleanupStack::Pop();
       
   107     return self;
       
   108     }
       
   109 
       
   110     
       
   111 // Destructor
       
   112 CCbsDbImpTopicMessages::~CCbsDbImpTopicMessages()
       
   113     {
       
   114     CBSLOGSTRING("CBSSERVER: >>> CCbsDbImpTopicMessages::~CCbsDbImpTopicMessages()");
       
   115     // Invalidate cache.
       
   116     InvalidateCache();
       
   117 
       
   118     // And then delete the message list.
       
   119     delete iMessageList;
       
   120     
       
   121     // Delete locked messages.
       
   122     delete iLockedMessages; 
       
   123     CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicMessages::~CCbsDbImpTopicMessages()");   
       
   124     }
       
   125 
       
   126 // -----------------------------------------------------------------------------
       
   127 // CCbsDbImpTopicMessages::InvalidateCache
       
   128 // Resets the cache to default values.
       
   129 // (other items were commented in a header).
       
   130 // -----------------------------------------------------------------------------
       
   131 //
       
   132 void CCbsDbImpTopicMessages::InvalidateCache()
       
   133     {    
       
   134     // Initialize members back to default.
       
   135     iCacheValid = EFalse;
       
   136     iCachedTopicNumber = 0;
       
   137         
       
   138     // Resize the message list. After the call is made, the
       
   139     // array is empty.
       
   140     if ( iMessageList )
       
   141         {
       
   142         iMessageList->Reset();
       
   143         }
       
   144     }
       
   145 
       
   146 // -----------------------------------------------------------------------------
       
   147 // CCbsDbImpTopicMessages::InvalidateCacheIfTopic
       
   148 // Resets the cache to default values.
       
   149 // (other items were commented in a header).
       
   150 // -----------------------------------------------------------------------------
       
   151 //
       
   152 void CCbsDbImpTopicMessages::InvalidateCacheIfTopic( 
       
   153     const TCbsDbTopicNumber& aNumber )
       
   154     {
       
   155     // Check the handle and then invalidate
       
   156     if ( iCachedTopicNumber == aNumber )
       
   157         {
       
   158         InvalidateCache();
       
   159         }
       
   160     }
       
   161 
       
   162 // -----------------------------------------------------------------------------
       
   163 // CCbsDbImpTopicMessages::CreateDefaultTopicMessagesStreamL
       
   164 // Creates a default topic messages stream.
       
   165 // (other items were commented in a header).
       
   166 // -----------------------------------------------------------------------------
       
   167 //
       
   168 TStreamId CCbsDbImpTopicMessages::CreateDefaultTopicMessagesStreamL(
       
   169     CStreamStore& aStore )
       
   170     {
       
   171     // Create the stream.
       
   172     RStoreWriteStream outstream;
       
   173     TStreamId id = outstream.CreateLC( aStore ); // on CS
       
   174 
       
   175     // Write total amount of messages.
       
   176     outstream.WriteInt16L( 0 );
       
   177 
       
   178     // Write total amount of space for messages.
       
   179     outstream.WriteInt16L( KDefaultSpaceForMessages );
       
   180 
       
   181     for ( TInt index( 0 ); index < KDefaultSpaceForMessages; index++ )
       
   182         {
       
   183         // "Saved"-flag
       
   184         CbsStreamHelper::WriteBoolL( outstream, EFalse );
       
   185         // Write message stream id.
       
   186         outstream << TStreamId( 0 );
       
   187         }
       
   188 
       
   189     outstream.CommitL();
       
   190     CleanupStack::PopAndDestroy();  // outstream
       
   191 
       
   192     return id;
       
   193     }
       
   194 
       
   195 // -----------------------------------------------------------------------------
       
   196 // CCbsDbImpTopicMessages::CreateDefaultTopicMessagesStreamL
       
   197 // Delete all topics messages.
       
   198 // (other items were commented in a header).
       
   199 // -----------------------------------------------------------------------------
       
   200 //
       
   201 void CCbsDbImpTopicMessages::DeleteAllTopicMessagesL( 
       
   202     CStreamStore& aSavedStore,
       
   203     CStreamStore& aUnsavedStore,
       
   204     RReadStream& aIn )
       
   205     {
       
   206     // Read total amount of messages.
       
   207     TInt total( aIn.ReadInt16L() );
       
   208     
       
   209     // Skip space for messages.
       
   210     aIn.ReadInt16L();
       
   211 
       
   212     // Now, delete all streams..
       
   213     for ( TInt index( 0 ); index < total; index++ )
       
   214         {
       
   215 
       
   216         TBool isSaved( CbsStreamHelper::ReadBoolL( aIn ) );
       
   217         TStreamId id;
       
   218 
       
   219         // Read stream id.
       
   220         aIn >> id;
       
   221         CStreamStore& store = isSaved ? aSavedStore : aUnsavedStore;
       
   222         store.DeleteL( id );
       
   223         }
       
   224     }
       
   225 
       
   226 // -----------------------------------------------------------------------------
       
   227 // CCbsDbImpTopicMessages::IsLockedMessagesInTopic
       
   228 // Determines whether or not there are any locked messages in 
       
   229 // the topic.
       
   230 // (other items were commented in a header).
       
   231 // -----------------------------------------------------------------------------
       
   232 //
       
   233 TBool CCbsDbImpTopicMessages::IsLockedMessagesInTopic( 
       
   234     const TCbsDbTopicNumber& aNumber ) const
       
   235     {
       
   236     TBool result( EFalse );
       
   237 
       
   238     // Checks whether or not there is a locked message in the topic.
       
   239     TInt count( iLockedMessages->Count() );
       
   240     for ( TInt index( 0 ); index < count; index++ )
       
   241         {
       
   242         if ( iTopicList.ExtractTopicNumber( 
       
   243             iLockedMessages->At( index ) ) == aNumber )
       
   244             {
       
   245             result = ETrue;
       
   246             }
       
   247         }    
       
   248     return result;
       
   249     }
       
   250 
       
   251 // -----------------------------------------------------------------------------
       
   252 // CCbsDbImpTopicMessages::IsLockedMessages
       
   253 // Determines whether there is at least one locked message.
       
   254 // Returns ETrue, if there are any locked messages in the 
       
   255 // database.
       
   256 // (other items were commented in a header).
       
   257 // -----------------------------------------------------------------------------
       
   258 //
       
   259 TBool CCbsDbImpTopicMessages::IsLockedMessages() const
       
   260     {
       
   261     return ( iLockedMessages->Count() > 0 );
       
   262     }
       
   263 
       
   264 // -----------------------------------------------------------------------------
       
   265 // CCbsDbImpTopicMessages::GetMessageCountL
       
   266 // Returns the total amount of messages the topic contains.
       
   267 // (other items were commented in a header).
       
   268 // -----------------------------------------------------------------------------
       
   269 //
       
   270 void CCbsDbImpTopicMessages::GetMessageCountL( 
       
   271     const TCbsDbTopicNumber& aNumber, 
       
   272     TInt& aCount )
       
   273     {
       
   274     // Load cache.
       
   275     LoadCacheL( aNumber );
       
   276 
       
   277     // and then get the message count.
       
   278     aCount = iMessageList->Count();
       
   279     }
       
   280 
       
   281 // -----------------------------------------------------------------------------
       
   282 // CCbsDbImpTopicMessages::GetMessageL
       
   283 // Returns message information.
       
   284 // Returns the message matching the given
       
   285 // index value. Leaves if the index is not valid.
       
   286 // (other items were commented in a header).
       
   287 // -----------------------------------------------------------------------------
       
   288 //
       
   289 void CCbsDbImpTopicMessages::GetMessageL( 
       
   290     const TCbsDbTopicNumber& aNumber, 
       
   291     TInt aIndex, 
       
   292     TCbsDbMessage& aMessage )
       
   293     {
       
   294     // Load the cache.
       
   295     LoadCacheL( aNumber );
       
   296 
       
   297     // Check if the index is not valid.
       
   298     if ( ( aIndex < 0 ) || ( aIndex >= iMessageList->Count() ) )
       
   299         {
       
   300         User::Leave( KErrNotFound );
       
   301         }
       
   302 
       
   303     // Load the message.
       
   304     LoadMessageL( aIndex, aMessage );
       
   305     }
       
   306 
       
   307 // -----------------------------------------------------------------------------
       
   308 // CCbsDbImpTopicMessages::FindMessageByHandleL
       
   309 // Finds the message for given handle and returns it.
       
   310 // Returns the message matching the given
       
   311 // index value.
       
   312 // (other items were commented in a header).
       
   313 // -----------------------------------------------------------------------------
       
   314 //
       
   315 void CCbsDbImpTopicMessages::FindMessageByHandleL( 
       
   316     const TCbsDbMessageHandle& aHandle, 
       
   317     TCbsDbMessage& aMessage )
       
   318     {
       
   319     // Load cache
       
   320     LoadCacheL( iTopicList.ExtractTopicNumber( aHandle ) );
       
   321 
       
   322     // Load message
       
   323     LoadMessageL( FindMessagePositionByHandleL( aHandle ), aMessage );
       
   324     }
       
   325 
       
   326 // -----------------------------------------------------------------------------
       
   327 // CCbsDbImpTopicMessages::GetMessageContentsL
       
   328 // Returns the contents of a message.
       
   329 // Stores the contents of the message to the buffer aContents. 
       
   330 // If aContents is too small to contain the whole message
       
   331 // body, the message body is truncated.
       
   332 // (other items were commented in a header).
       
   333 // -----------------------------------------------------------------------------
       
   334 //
       
   335 void CCbsDbImpTopicMessages::GetMessageContentsL( 
       
   336     const TCbsDbMessageHandle& aHandle, 
       
   337     TPtr& aContents,
       
   338     TUint aSize )
       
   339     {
       
   340     LoadCacheL( iTopicList.ExtractTopicNumber( aHandle ) );
       
   341 
       
   342     TInt position( FindMessagePositionByHandleL( aHandle ) );
       
   343 
       
   344     TCbsDbMessage message;
       
   345     LoadMessageL( position, message );
       
   346 
       
   347     LoadMessageContentsL( iMessageList->At( position ).iContentsId, 
       
   348                           aContents, message.iPermanent, aSize );
       
   349     }
       
   350 
       
   351 // -----------------------------------------------------------------------------
       
   352 // CCbsDbImpTopicMessages::DeleteMessageL
       
   353 // Deletes a message. Leaves if the message is protected
       
   354 // (other items were commented in a header).
       
   355 // -----------------------------------------------------------------------------
       
   356 //
       
   357 void CCbsDbImpTopicMessages::DeleteMessageL( 
       
   358     const TCbsDbMessageHandle& aHandle,
       
   359     const CCbsRecEtel& aReceiver )
       
   360     {
       
   361     // Get the topic handle.
       
   362     LoadCacheL( iTopicList.ExtractTopicNumber( aHandle ) );
       
   363 
       
   364     // Check if the message is locked.
       
   365     if ( IsMessageLocked( aHandle ) )
       
   366         {
       
   367         // Yes, leave.
       
   368         User::Leave( KErrAccessDenied );
       
   369         }
       
   370     else
       
   371         {
       
   372         // Otherwise, delete.
       
   373         TRAPD( error, DoDeleteMessageL( 
       
   374             FindMessagePositionByHandleL( aHandle ) ) );
       
   375 
       
   376         if ( error != KErrNone )
       
   377             {
       
   378             // Failed.
       
   379             RevertFileOperationL( error );
       
   380             }
       
   381         else
       
   382             {
       
   383             // Update the soft notification dialog, if topic is hotmarked
       
   384             UpdateSoftNotificationL( aHandle, aReceiver );
       
   385             }
       
   386         }
       
   387 
       
   388     iTopicList.NotifyTopicModifiedL( 
       
   389         iTopicList.ExtractTopicNumber( aHandle ) );
       
   390     }
       
   391 
       
   392 // -----------------------------------------------------------------------------
       
   393 // CCbsDbImpTopicMessages::AddMessageL
       
   394 // Creates a new message to the topic.
       
   395 // Stores a handle to the message in aHandle.
       
   396 // FFS critical level check is made prior to operation.
       
   397 // (other items were commented in a header).
       
   398 // -----------------------------------------------------------------------------
       
   399 //
       
   400 void CCbsDbImpTopicMessages::AddMessageL( 
       
   401     const TCbsDbTopicNumber& aNumber, 
       
   402     TCbsDbMessage& aMessage, 
       
   403     const TPtrC& aContents )
       
   404     {
       
   405     CBSLOGSTRING("CBSSERVER: >>> CCbsDbImpTopicMessages::AddMessageL()");
       
   406     
       
   407     LoadCacheL( aNumber );
       
   408 
       
   409     aMessage.iLength = aContents.Length();
       
   410     CBSLOGSTRING2("CBSSERVER: CCbsDbImpTopicMessages::AddMessageL(): Content length: %d.", aMessage.iLength );
       
   411 
       
   412     // Generate a new message handle.
       
   413     aMessage.iHandle = GenerateNewMessageHandle( aNumber );    
       
   414     
       
   415     // Make sure that the message is not inserted as permanent
       
   416     aMessage.iPermanent = EFalse;
       
   417 
       
   418     TRAPD( error, DoAddMessageL( aMessage, aContents ) );
       
   419     if ( error != KErrNone )
       
   420         {
       
   421         CBSLOGSTRING2("CBSSERVER: CCbsDbImpTopicMessages::AddMessageL(): DoAddMessageL() failed, error: %d.", error );
       
   422         
       
   423         // Failed.
       
   424         RevertFileOperationL( error );
       
   425         
       
   426         CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicMessages::AddMessageL(): RevertFileOperationL() finished OK." );
       
   427         }
       
   428         
       
   429     CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicMessages::AddMessageL()");
       
   430     }
       
   431 
       
   432 // -----------------------------------------------------------------------------
       
   433 // CCbsDbImpTopicMessages::SaveMessageL
       
   434 // Saves a message. 
       
   435 // This operation is called "keeping" in the UI. 
       
   436 // The CBS server has a global limit for saved 
       
   437 // messages. The function leaves, if this is exceeded. 
       
   438 // A saved message has it's permanent-flag raised.
       
   439 // FFS critical level check is made prior to the operation.
       
   440 // (other items were commented in a header).
       
   441 // -----------------------------------------------------------------------------
       
   442 //
       
   443 void CCbsDbImpTopicMessages::SaveMessageL( 
       
   444     const TCbsDbMessageHandle& aHandle,
       
   445     const CCbsRecEtel& aReceiver )
       
   446     {
       
   447     // Load cache.
       
   448     TCbsTopicNumber topicNumber( iTopicList.ExtractTopicNumber( aHandle ) );
       
   449     LoadCacheL( topicNumber );
       
   450 
       
   451     // Now find message by handle.
       
   452     TInt position( FindMessagePositionByHandleL( aHandle ) );
       
   453 
       
   454     TCbsDbMessage message;
       
   455     LoadMessageL( position, message );
       
   456     TStreamId contentsId( iMessageList->At( position ).iContentsId );
       
   457 
       
   458     // This function should not be called if the message is already permanent.
       
   459     if ( message.iPermanent )
       
   460         {
       
   461         User::Leave( KErrAlreadyExists );
       
   462         }
       
   463 
       
   464     // Check that the limit for maximum saved messages/topic is not exceeded.
       
   465     TCbsDbTopic topic;
       
   466     iTopicList.FindTopicByNumberL( topicNumber, topic );
       
   467     if ( iTopicList.TotalSavedMessages() >= KCbsDbMaxSavedMessages )
       
   468         {
       
   469         User::Leave( KErrOverflow );
       
   470         }
       
   471 
       
   472     // FFS critical level check (header is 16 bytes, message coded in Unicode)
       
   473     CbsUtils::FFSCriticalLevelCheckL( KCbMessageHeaderSize + 
       
   474         2 * message.iLength, iFs );
       
   475 
       
   476     // Create a temporary buffer for message body and load the contents into
       
   477     // the buffer.
       
   478     HBufC* buffer = HBufC::NewLC( message.iLength ); // on CS
       
   479     TPtr contentPtr( buffer->Des() );
       
   480     LoadMessageContentsL( contentsId, contentPtr, EFalse, message.iLength );
       
   481 
       
   482     // Delete message's previous header and body streams.
       
   483     TCbsDbImpTopicMessagesCacheItem item( iMessageList->At( position ) );    
       
   484 
       
   485     TRAPD( result, DoSaveMessageL( message, item, contentPtr, position ) );
       
   486     CleanupStack::PopAndDestroy( buffer );
       
   487     if ( result != KErrNone )
       
   488         {
       
   489         RevertFileOperationL( result );
       
   490         }
       
   491     else
       
   492         {
       
   493         iTopicList.NotifyTopicModifiedL( 
       
   494             iTopicList.ExtractTopicNumber( aHandle ) );
       
   495             
       
   496         // Update the soft notification dialog, if topic is hotmarked
       
   497         UpdateSoftNotificationL( aHandle, aReceiver );
       
   498         }
       
   499     }
       
   500 
       
   501 // -----------------------------------------------------------------------------
       
   502 // CCbsDbImpTopicMessages::DoSaveMessageL
       
   503 // Saves a message.
       
   504 // (other items were commented in a header).
       
   505 // -----------------------------------------------------------------------------
       
   506 //
       
   507 void CCbsDbImpTopicMessages::DoSaveMessageL( 
       
   508     TCbsDbMessage& aMessage,
       
   509     const TCbsDbImpTopicMessagesCacheItem& aItem,
       
   510     const TDesC& aContentPtr,
       
   511     TInt aPosition )
       
   512     {
       
   513     CFileStore* store = iTopicList.UnsavedMessagesStore();
       
   514     store->Delete( aItem.iId );
       
   515     store->Delete( aItem.iContentsId );
       
   516 
       
   517     TBool needToUpdateReadCounter( EFalse );
       
   518     aMessage.iPermanent = ETrue;
       
   519     if ( !aMessage.iRead ) 
       
   520         {
       
   521         needToUpdateReadCounter = ETrue;
       
   522         aMessage.iRead = ETrue;
       
   523         }
       
   524 
       
   525     // Create new streams for message header and body.
       
   526     TStreamId contentsStream( CreateMessageContentsStreamL( 
       
   527         *iTopicList.TopicStoreL(), aContentPtr ) );
       
   528     TStreamId messageStream( CreateMessageStreamL( 
       
   529         *iTopicList.TopicStoreL(), aMessage, contentsStream ) );
       
   530 
       
   531     // Update message's cache item information.
       
   532 	TCbsDbImpTopicMessagesCacheItem& item = iMessageList->At( aPosition );
       
   533     item.iContentsId = contentsStream;
       
   534     item.iId = messageStream;
       
   535     item.iIsSaved = ETrue;
       
   536     item.iMessage = aMessage;
       
   537 
       
   538     // Update topic messages stream; the cache item is saved into the stream.
       
   539     UpdateTopicMessagesStreamL( EFalse );
       
   540 
       
   541     iTopicList.InformMessageSavedL( aMessage.iHandle );
       
   542     if ( needToUpdateReadCounter )
       
   543         {
       
   544         iTopicList.InformUnreadMessageReadL( aMessage.iHandle );
       
   545         }
       
   546 
       
   547     // Commit changes to both files.
       
   548     iTopicList.CommitFilesL();
       
   549     }
       
   550 
       
   551 // -----------------------------------------------------------------------------
       
   552 // CCbsDbImpTopicMessages::ReadMessageL
       
   553 // Marks the message read
       
   554 // (other items were commented in a header).
       
   555 // -----------------------------------------------------------------------------
       
   556 //
       
   557 void CCbsDbImpTopicMessages::ReadMessageL(
       
   558     const TCbsDbMessageHandle& aHandle,
       
   559     const CCbsRecEtel& aReceiver )
       
   560     {
       
   561     //Checked that there is space for writing data on FFS.
       
   562     CbsUtils::FFSCriticalLevelCheckL( KReadMessageSize, iFs );
       
   563 
       
   564     // Load cache.
       
   565     TCbsDbTopicNumber topicNum( iTopicList.ExtractTopicNumber( aHandle ) );
       
   566     LoadCacheL( topicNum );
       
   567 
       
   568     // Now find message by handle.
       
   569     TInt position( FindMessagePositionByHandleL( aHandle ) );
       
   570 
       
   571     TCbsDbMessage message;
       
   572     LoadMessageL( position, message );
       
   573     TStreamId contentsId( iMessageList->At( position ).iContentsId );
       
   574     TStreamId id( iMessageList->At( position ).iId );
       
   575 
       
   576     // Check if the message is already read, then there is nothing more to do.
       
   577     if ( !message.iRead )
       
   578         {
       
   579         message.iRead = ETrue;
       
   580 
       
   581         TRAPD( error, DoReadMessageL( id, message, contentsId ) );
       
   582         if ( error == KErrNone )
       
   583             {
       
   584             iMessageList->At( position ).iMessage = message;
       
   585             
       
   586             iTopicList.NotifyTopicModifiedL( 
       
   587                 iTopicList.ExtractTopicNumber( aHandle ) );
       
   588         
       
   589             // Update the soft notification dialog, if topic is hotmarked
       
   590             UpdateSoftNotificationL( aHandle, aReceiver );
       
   591             }
       
   592         else
       
   593             {
       
   594             RevertFileOperationL( error );
       
   595             }
       
   596         }
       
   597     }
       
   598 
       
   599 // -----------------------------------------------------------------------------
       
   600 // CCbsDbImpTopicMessages::UpdateHandlesOfTopicMessagesL
       
   601 // Updates handles of messages in the topic with the number given in
       
   602 // aOldTopicNumber to match new topic number. 
       
   603 // Traverses through the given topic processing
       
   604 // each message stream encountered. Since the topic number is
       
   605 // the primary key and previous message handles can be assumed
       
   606 // to be unique, updating the high word of the handle to
       
   607 // match the new topic number is adequate.
       
   608 // (other items were commented in a header).
       
   609 // -----------------------------------------------------------------------------
       
   610 //
       
   611 void CCbsDbImpTopicMessages::UpdateHandlesOfTopicMessagesL(
       
   612     const TCbsDbTopicNumber& aOldTopicNumber, 
       
   613     const TCbsDbTopicNumber& aNewTopicNumber )
       
   614     {
       
   615     LoadCacheL( aOldTopicNumber );
       
   616 
       
   617     TInt msgs( iMessageList->Count() );
       
   618 
       
   619     for ( TInt i( 0 ); i < msgs; i++ )
       
   620         {
       
   621         // Fetch message at this position
       
   622         TCbsDbMessage message;
       
   623         LoadMessageL( i, message );
       
   624         TStreamId contentsStreamId( iMessageList->At( i ).iContentsId );
       
   625         TStreamId messageStreamId( iMessageList->At( i ).iId );
       
   626 
       
   627         // Insert new topic number as the high word of the handle
       
   628         message.iHandle = ( aNewTopicNumber << 16 ) |
       
   629             ( message.iHandle & 0xFFFF );
       
   630         DoUpdateMessageL( messageStreamId, message, contentsStreamId );
       
   631         }
       
   632     }
       
   633 
       
   634 // -----------------------------------------------------------------------------
       
   635 // CCbsDbImpTopicMessages::LockMessageL
       
   636 // Unlocks one message and then locks another message.
       
   637 // Message that is locked can not be removed. Topic that 
       
   638 // contains a locked message can not be removed.
       
   639 // Note that locking status is not persistent in the sense that 
       
   640 // when the power is switched off and turned on, no messages 
       
   641 // are automatically locked.
       
   642 // (other items were commented in a header).
       
   643 // -----------------------------------------------------------------------------
       
   644 //
       
   645 void CCbsDbImpTopicMessages::LockMessageL( 
       
   646     const TCbsDbMessageHandle& aUnlock, 
       
   647     const TCbsDbMessageHandle& aLock )
       
   648     {
       
   649     // Check if the message exists: leave if not found, ignore return value
       
   650     if ( aLock != 0 )
       
   651         {
       
   652         TCbsDbMessage message;
       
   653         TInt position( FindMessagePositionByHandleL( aLock ) );
       
   654         LoadMessageL( position, message );
       
   655         }
       
   656 
       
   657     TBool unlockNull( ETrue );
       
   658 
       
   659     if ( aUnlock != 0 )
       
   660         {
       
   661         DeleteFromLocked( aUnlock );
       
   662         unlockNull = EFalse;
       
   663         }
       
   664 
       
   665     if ( aLock != 0 )
       
   666         {
       
   667         InsertToLockedL( aLock ) ;
       
   668         }
       
   669 
       
   670     if ( unlockNull == EFalse )
       
   671         {
       
   672         LoadCacheL( iTopicList.ExtractTopicNumber( aUnlock ) );
       
   673         }
       
   674     }
       
   675 
       
   676 // -----------------------------------------------------------------------------
       
   677 // CCbsDbImpTopicMessages::GetNextAndPrevMsgHandleL
       
   678 // Returns the handles of the next and previous message
       
   679 // when given a current message. 
       
   680 // (other items were commented in a header).
       
   681 // -----------------------------------------------------------------------------
       
   682 //
       
   683 void CCbsDbImpTopicMessages::GetNextAndPrevMsgHandleL(
       
   684     const TCbsDbMessageHandle& aCurrentMsg,
       
   685     TCbsDbMessageHandle& aNextMsg, 
       
   686     TCbsDbMessageHandle& aPrevMsg, 
       
   687     TInt& aPosition)
       
   688     {
       
   689     LoadCacheL( iTopicList.ExtractTopicNumber( aCurrentMsg ) );
       
   690 
       
   691     // Load the current message
       
   692     TInt index( FindMessagePositionByHandleL( aCurrentMsg ) );
       
   693 
       
   694     // Reset position indications
       
   695     aPosition = 0;
       
   696 
       
   697     // Retrieve position indications and message handles
       
   698     if ( index == 0 )
       
   699         {
       
   700         aPosition |= ECbsHead;
       
   701         }
       
   702     else
       
   703         {
       
   704         TCbsDbMessage prevMessage;
       
   705         LoadMessageL( index - 1, prevMessage );
       
   706         aPrevMsg = prevMessage.iHandle;
       
   707         }
       
   708 
       
   709     // If index points to the last element of iMessageList,
       
   710     // raise flag ECbsTail.
       
   711     if ( index == iMessageList->Count()-1 )
       
   712         {
       
   713         aPosition |= ECbsTail;
       
   714         }
       
   715     else
       
   716         {
       
   717         TCbsDbMessage nextMessage;
       
   718         LoadMessageL( index+1, nextMessage );
       
   719         aNextMsg = nextMessage.iHandle;
       
   720         }
       
   721     }
       
   722 
       
   723 // -----------------------------------------------------------------------------
       
   724 // CCbsDbImpTopicMessages::DoAddMessageL
       
   725 // Inserts a message into the database.
       
   726 // (other items were commented in a header).
       
   727 // -----------------------------------------------------------------------------
       
   728 //
       
   729 void CCbsDbImpTopicMessages::DoAddMessageL(
       
   730     TCbsDbMessage& aMessage, 
       
   731     const TDesC& aContents )
       
   732     {
       
   733     // Cache is assumed to be loaded. Message is assumed not to
       
   734     // already exist in the DB.
       
   735     CFileStore* store = aMessage.iPermanent ? 
       
   736         iTopicList.TopicStoreL() : iTopicList.UnsavedMessagesStore();
       
   737 
       
   738     if ( aMessage.iPermanent )
       
   739         {
       
   740         // About to write to FFS: make critical level check.
       
   741         // Message is in Unicode characters, so its size
       
   742         // is double the length.
       
   743         CbsUtils::FFSCriticalLevelCheckL( KCbMessageHeaderSize + 
       
   744             2 * aMessage.iLength, iFs );
       
   745         }
       
   746     else
       
   747         {
       
   748         CbsUtils::VolumeCriticalLevelCheckL(
       
   749             iTopicList.UnsavedMessagesFilename(),
       
   750             KCbMessageHeaderSize + 2 * aMessage.iLength, iFs );
       
   751         }
       
   752 
       
   753     // Create stream for contents.
       
   754     TStreamId contentsStream( CreateMessageContentsStreamL( 
       
   755         *store, aContents ) );
       
   756 
       
   757     // Now we have to find the position to which the message should be
       
   758     // inserted.         
       
   759     TInt positionToBeInserted( -1 );
       
   760 
       
   761     TTime messageTime( aMessage.iDateTime );
       
   762     TInt index( 0 );
       
   763 
       
   764     // Go through all messages in topic and find the position.
       
   765     TInt count( iMessageList->Count() );
       
   766     for ( ; index < count && positionToBeInserted == -1; index++ )
       
   767         {
       
   768         TCbsDbMessage message;
       
   769         LoadMessageL( index, message );
       
   770 
       
   771         TTime tmp( message.iDateTime );
       
   772 
       
   773         if ( tmp <= messageTime )
       
   774             {
       
   775             positionToBeInserted = index;
       
   776             }
       
   777         }
       
   778 
       
   779     // If we looped through, append
       
   780     if ( positionToBeInserted == -1 )
       
   781         {
       
   782         positionToBeInserted = index;
       
   783         }
       
   784 
       
   785     // Create message stream.
       
   786     TStreamId messageStream( CreateMessageStreamL( *store, 
       
   787         aMessage, contentsStream ) );
       
   788 
       
   789     // Add to internal cache.
       
   790     TCbsDbImpTopicMessagesCacheItem item;
       
   791     
       
   792     item.iId = messageStream;
       
   793     item.iIsMessage = EFalse;
       
   794     item.iIsSaved = aMessage.iPermanent;
       
   795 
       
   796     iMessageList->InsertL( positionToBeInserted, item );
       
   797 
       
   798     // Check if message should be deleted.
       
   799     DeleteReceivedIfNecessaryL();
       
   800 
       
   801     // Update topic messages stream.
       
   802     UpdateTopicMessagesStreamL( EFalse );
       
   803 
       
   804     // Update counters.
       
   805     iTopicList.InformNewMessageReceivedL( aMessage.iHandle );
       
   806 
       
   807     // Commit changes to both stores.
       
   808     iTopicList.CommitFilesL();
       
   809 
       
   810     // Inform observers. Done after commit to make sure there's
       
   811     // a message to inform of.
       
   812     iTopicList.NotifyNewMessageArrivedL( aMessage.iHandle );
       
   813     }
       
   814 
       
   815 // -----------------------------------------------------------------------------
       
   816 // CCbsDbImpTopicMessages::DoDeleteMessageL
       
   817 // Deletes a message from the database.
       
   818 // (other items were commented in a header).
       
   819 // -----------------------------------------------------------------------------
       
   820 //
       
   821 void CCbsDbImpTopicMessages::DoDeleteMessageL( 
       
   822     TInt aPosition )
       
   823     {    
       
   824     TCbsDbMessage message;
       
   825     LoadMessageL( aPosition, message );
       
   826 
       
   827     // Delete the message, if it is possible.
       
   828     DeleteMessageByPositionL( aPosition );
       
   829     DeleteReceivedIfNecessaryL();
       
   830     UpdateTopicMessagesStreamL( ETrue );
       
   831 
       
   832     // Inform the topic list about deletion.
       
   833     iTopicList.InformMessageDeletedL( message.iHandle, 
       
   834         message.iPermanent, message.iRead );
       
   835 
       
   836     iTopicList.CommitFilesL();
       
   837     }
       
   838 
       
   839 // -----------------------------------------------------------------------------
       
   840 // CCbsDbImpTopicMessages::DoUpdateMessageL
       
   841 // Updates the information for a message.
       
   842 // (other items were commented in a header).
       
   843 // -----------------------------------------------------------------------------
       
   844 //
       
   845 void CCbsDbImpTopicMessages::DoUpdateMessageL( 
       
   846     const TStreamId& aId, 
       
   847     const TCbsDbMessage& aMessage, 
       
   848     const TStreamId& aContentsId ) const
       
   849     {
       
   850     // Update the stream contents.
       
   851     CFileStore* store = aMessage.iPermanent ? 
       
   852         iTopicList.TopicStoreL() : iTopicList.UnsavedMessagesStore();
       
   853 
       
   854     RStoreWriteStream outstream;
       
   855     outstream.ReplaceLC( *store, aId ); // on CS
       
   856 
       
   857     WriteMessageInformationL( outstream, aMessage, aContentsId );
       
   858 
       
   859     outstream.CommitL();
       
   860     CleanupStack::PopAndDestroy(); // outstream
       
   861     }
       
   862 
       
   863 // -----------------------------------------------------------------------------
       
   864 // CCbsDbImpTopicMessages::DoReadMessageL
       
   865 // Marks a message read by updating it in the database.
       
   866 // (other items were commented in a header).
       
   867 // -----------------------------------------------------------------------------
       
   868 //
       
   869 void CCbsDbImpTopicMessages::DoReadMessageL( 
       
   870     const TStreamId& aId, 
       
   871     const TCbsDbMessage& aMessage, 
       
   872     const TStreamId& aContentsId )
       
   873     {
       
   874     DoUpdateMessageL( aId, aMessage, aContentsId );
       
   875     iTopicList.InformUnreadMessageReadL( aMessage.iHandle );
       
   876     iTopicList.CommitFilesL();
       
   877     }
       
   878 
       
   879 // -----------------------------------------------------------------------------
       
   880 // CCbsDbImpTopicMessages::DoDeleteL
       
   881 // Deletes messages that are not supposed to be in the topic.
       
   882 // Because of message locking it is possible that there are more 
       
   883 // received messages than there should be. This method tries to 
       
   884 // delete this kind of message.
       
   885 // (other items were commented in a header).
       
   886 // -----------------------------------------------------------------------------
       
   887 //
       
   888 void CCbsDbImpTopicMessages::DoDeleteL()
       
   889     {
       
   890     CBSLOGSTRING("CBSSERVER: >>> CCbsDbImpTopicMessages::DoDeleteL()");
       
   891 
       
   892     // Delete temporary messages and update topic messages stream.
       
   893     if ( DeleteReceivedIfNecessaryL() )
       
   894         {
       
   895         UpdateTopicMessagesStreamL( ETrue );    
       
   896         }
       
   897     iTopicList.CommitFilesL();
       
   898     
       
   899     CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicMessages::DoDeleteL()");
       
   900     }
       
   901 
       
   902 // -----------------------------------------------------------------------------
       
   903 // CCbsDbImpTopicMessages::FindMessageByKeyL
       
   904 // Returns a handle to a message with the given key.
       
   905 // (other items were commented in a header).
       
   906 // -----------------------------------------------------------------------------
       
   907 //
       
   908 TInt CCbsDbImpTopicMessages::FindMessageByKeyL( 
       
   909     TCbsDbTopicNumber aNumber, 
       
   910     TCbsDbMessageKey aKey,
       
   911     TCbsDbMessage& aMessage )
       
   912     {
       
   913     TCbsDbMessage message;
       
   914     TInt count;
       
   915     TBool result( KErrNotFound );
       
   916 
       
   917     // Find a message even if the update numbers don't match
       
   918     aKey &= 0xfff0;
       
   919 
       
   920     // Try to find a message with the same key in the topic.
       
   921     LoadCacheL( aNumber );
       
   922     GetMessageCountL( aNumber, count );
       
   923 
       
   924     for ( TInt index( 0 ); ( index < count ) && ( result != KErrNone ); index++ )
       
   925         {
       
   926         LoadMessageL( index, message );
       
   927 
       
   928         if ( (message.iKey & 0xfff0) == aKey )
       
   929             {
       
   930             aMessage = message;
       
   931             result = KErrNone; // message was found
       
   932             }
       
   933         }
       
   934     return result;
       
   935     }
       
   936 
       
   937 // -----------------------------------------------------------------------------
       
   938 // CCbsDbImpTopicMessages::FindMessagePositionByHandleL
       
   939 // Returns the position of a message with the given handle.
       
   940 // (other items were commented in a header).
       
   941 // -----------------------------------------------------------------------------
       
   942 //
       
   943 TInt CCbsDbImpTopicMessages::FindMessagePositionByHandleL( 
       
   944     const TCbsDbMessageHandle& aHandle )
       
   945     {
       
   946     // Load the cache.
       
   947     LoadCacheL( iTopicList.ExtractTopicNumber( aHandle ) );
       
   948 
       
   949     // Now, find the message
       
   950     TInt count( iMessageList->Count() );
       
   951 
       
   952     TCbsDbMessage message;
       
   953     TBool found( EFalse );
       
   954 
       
   955     // Go through messages.
       
   956     TInt index( 0 );
       
   957     for ( ; ( index < count ) && !found; )
       
   958         {
       
   959         // Load the message.
       
   960         LoadMessageL( index, message );
       
   961         
       
   962         // Check if it is this one.
       
   963         if ( message.iHandle == aHandle )
       
   964             {
       
   965             found = ETrue;
       
   966             }
       
   967         else
       
   968             {
       
   969             index++;
       
   970             }        
       
   971         }
       
   972 
       
   973     if ( !found )
       
   974         {
       
   975         User::Leave( KErrNotFound );
       
   976         }
       
   977      
       
   978     return index;        
       
   979     }
       
   980 
       
   981 // -----------------------------------------------------------------------------
       
   982 // CCbsDbImpTopicMessages::LoadCacheL
       
   983 // Loads the cache, if it is not already loaded with this topic information.
       
   984 // The method does not load any message information to the cache 
       
   985 // - only what is really necessary.
       
   986 // (other items were commented in a header).
       
   987 // -----------------------------------------------------------------------------
       
   988 //
       
   989 void CCbsDbImpTopicMessages::LoadCacheL( 
       
   990     const TCbsDbTopicNumber& aNumber )
       
   991     {
       
   992     CBSLOGSTRING2("CBSSERVER: >>> CCbsDbImpTopicMessages::LoadCacheL(), topic number: %d.", aNumber );
       
   993     
       
   994     // Check if the cache is valid. If not, load it.
       
   995     if ( !( iCacheValid && ( iCachedTopicNumber == aNumber ) ) ) 
       
   996         {        
       
   997         CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicMessages::LoadCacheL(): Calling InvalidateCache()...");        
       
   998         // Invalidate the old cache, if it is necessary.
       
   999         InvalidateCache();        
       
  1000         CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicMessages::LoadCacheL(): InvalidateCache() called OK.");
       
  1001 
       
  1002         // Load message queue ids.
       
  1003         TStreamId id;
       
  1004         iTopicList.GetTopicMessagesIdL( aNumber, id );
       
  1005 
       
  1006         ReadTopicMessagesCacheItemsL( *iTopicList.TopicStoreL(), 
       
  1007             id, *iMessageList, iSpaceForMessages );
       
  1008     
       
  1009         // Cache is valid.
       
  1010         iCachedTopicNumber = aNumber;
       
  1011         iCacheValid = ETrue;
       
  1012 
       
  1013         // Check if it there are more topics than there should be.
       
  1014         TCbsDbTopic topic;
       
  1015         iTopicList.FindTopicByNumberL( aNumber, topic );
       
  1016         if ( ( iMessageList->Count() - topic.iSavedMessages ) > 
       
  1017              KCbsDbMaxReceivedMessages ) 
       
  1018             {
       
  1019             TRAPD( error, DoDeleteL() );
       
  1020             CBSLOGSTRING2("CBSSERVER: CCbsDbImpTopicMessages::LoadCacheL(): DoDeleteL() finished with %d.", error );        
       
  1021             
       
  1022             if ( error != KErrNone )
       
  1023                 {
       
  1024                 RevertFileOperationL( error );
       
  1025                 }
       
  1026             }
       
  1027         }
       
  1028     CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicMessages::LoadCacheL()");
       
  1029     }
       
  1030 
       
  1031 // -----------------------------------------------------------------------------
       
  1032 // CCbsDbImpTopicMessages::LoadMessageL
       
  1033 // Loads the message header to the cache.
       
  1034 // Note that it is assumed that the index is in proper range and 
       
  1035 // the cache is already loaded.
       
  1036 // (other items were commented in a header).
       
  1037 // -----------------------------------------------------------------------------
       
  1038 //
       
  1039 void CCbsDbImpTopicMessages::LoadMessageL( 
       
  1040     TInt aIndex, 
       
  1041     TCbsDbMessage& aMessage )
       
  1042     {
       
  1043     CBSLOGSTRING("CBSSERVER: >>> CCbsDbImpTopicMessages::LoadMessageL()");
       
  1044 
       
  1045     // Check that the aIndex is in proper range and.
       
  1046     // that the cache is valid (just for sure).
       
  1047     if ( aIndex < 0 || aIndex >= iMessageList->Count() ||
       
  1048          !iCacheValid )
       
  1049         {
       
  1050         CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicMessages::LoadMessageL(): Leaving with KErrNotFound...");
       
  1051         User::Leave( KErrNotFound );
       
  1052         }
       
  1053 
       
  1054     // Check if the message information is already loaded.
       
  1055     if ( iMessageList->At( aIndex ).iIsMessage )
       
  1056         {       
       
  1057         // Yes, just make a fast copy.
       
  1058         aMessage = iMessageList->At( aIndex ).iMessage;
       
  1059         CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicMessages::LoadMessageL(): Msg already loaded, fast copy made.");
       
  1060         }
       
  1061     else
       
  1062         {
       
  1063         TStreamId id( TStreamId( 0 ) );
       
  1064         // Choose the file store: saved messages are stored elsewhere
       
  1065         // than other messages.
       
  1066         CFileStore* store = iMessageList->At( aIndex ).iIsSaved ?
       
  1067             iTopicList.TopicStoreL() : 
       
  1068             iTopicList.UnsavedMessagesStore();
       
  1069         CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicMessages::LoadMessageL(): Store created.");
       
  1070 
       
  1071         // Then read the message. If the message stream cannot be
       
  1072         // found, delete the reference to the message
       
  1073         TRAPD( error, ReadMessageInformationL( *store, 
       
  1074             iMessageList->At( aIndex ).iId, aMessage, id ) );
       
  1075             
       
  1076         CBSLOGSTRING2("CBSSERVER: CCbsDbImpTopicMessages::LoadMessageL(): ReadMessageInformationL() finished with %d.", error );
       
  1077         
       
  1078         if( error == KErrNotFound )
       
  1079             {
       
  1080             DeleteMessageByPositionL( aIndex );
       
  1081             UpdateTopicMessagesStreamL( ETrue );
       
  1082             iTopicList.CommitFilesL();    
       
  1083             }
       
  1084         
       
  1085         CBSLOGSTRING2("CBSSERVER: CCbsDbImpTopicMessages::LoadMessageL(): Leaving if error code < 0: error %d...", error );
       
  1086         User::LeaveIfError( error );
       
  1087 
       
  1088         // And copy to the internal cache.
       
  1089         iMessageList->At( aIndex ).iIsMessage = ETrue;
       
  1090         iMessageList->At( aIndex ).iContentsId = id;
       
  1091         iMessageList->At( aIndex ).iMessage = aMessage;
       
  1092         }
       
  1093     CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicMessages::LoadMessageL()");
       
  1094     }
       
  1095 
       
  1096 // -----------------------------------------------------------------------------
       
  1097 // CCbsDbImpTopicMessages::LoadMessageContentsL
       
  1098 // Loads message contents (as much as it fits).
       
  1099 // Restores the contents of a message
       
  1100 // by reading a stream specified in parameter aContentsId.
       
  1101 // Save status of message is required because saved and unsaved
       
  1102 // messages are stored on separate files.
       
  1103 // (other items were commented in a header).
       
  1104 // -----------------------------------------------------------------------------
       
  1105 //
       
  1106 void CCbsDbImpTopicMessages::LoadMessageContentsL( 
       
  1107     const TStreamId& aContentsId, 
       
  1108     TPtr& aContents,
       
  1109     TBool aIsSaved,
       
  1110     TUint aSize ) const
       
  1111     {
       
  1112     CFileStore* store = aIsSaved ? 
       
  1113         iTopicList.TopicStoreL() :
       
  1114         iTopicList.UnsavedMessagesStore();
       
  1115 
       
  1116     // Read data to the buffer.
       
  1117     RStoreReadStream instream;
       
  1118     instream.OpenLC( *store, aContentsId ); // on CS
       
  1119 
       
  1120     // Read the data into a temporary buffer first.
       
  1121 	// Then copy to the aContents descriptor only
       
  1122 	// as much as it can take.
       
  1123     TUint length( instream.ReadInt16L() );
       
  1124     if ( length > KCbsMaxCharsInMessage )
       
  1125         {
       
  1126         User::Leave( KErrCorrupt );
       
  1127         }
       
  1128 
       
  1129 	HBufC* buf = HBufC::NewL( instream, length );    
       
  1130 	if ( length > aSize )
       
  1131 		{
       
  1132 		length = aSize;
       
  1133 		}
       
  1134 
       
  1135 	aContents.Copy( buf->Ptr(), length );
       
  1136 	delete buf;
       
  1137 
       
  1138     CleanupStack::PopAndDestroy(); // instream
       
  1139     }
       
  1140 
       
  1141 // -----------------------------------------------------------------------------
       
  1142 // CCbsDbImpTopicMessages::GenerateNewMessageHandle
       
  1143 // Generates a new, unique handle for a message.
       
  1144 // The generation uses topic number as 
       
  1145 // basis and then increments the handle value until an unique
       
  1146 // handle is found.
       
  1147 // (other items were commented in a header).
       
  1148 // -----------------------------------------------------------------------------
       
  1149 //
       
  1150 TCbsDbMessageHandle CCbsDbImpTopicMessages::GenerateNewMessageHandle( 
       
  1151     const TCbsDbTopicNumber& aNumber )
       
  1152     {
       
  1153     // Start with a reasonable seed. We'll try the number
       
  1154     // of messages in topic, plus one.
       
  1155     TUint16 handleLow( TUint16( iMessageList->Count() + 1 ) );
       
  1156     TCbsDbMessageHandle handle( 1 );
       
  1157     TInt error( KErrNone );
       
  1158 
       
  1159     while ( error == KErrNone )
       
  1160         {
       
  1161         handleLow++;
       
  1162         if ( handleLow == 0 ) 
       
  1163             {
       
  1164             handleLow++;
       
  1165             }
       
  1166 
       
  1167         // Generate a new message handle.
       
  1168         handle = iTopicList.GenerateMessageHandle( aNumber, 
       
  1169             handleLow );
       
  1170 
       
  1171         TRAP( error, ( FindMessagePositionByHandleL( handle ) ) );
       
  1172         }
       
  1173     return handle;
       
  1174     }
       
  1175 
       
  1176 // -----------------------------------------------------------------------------
       
  1177 // CCbsDbImpTopicMessages::DeleteReceivedIfNecessaryL
       
  1178 // Checks that if there are too many received messages in the internal cache, 
       
  1179 // then they will be deleted if they are not locked.  
       
  1180 // Note: Count() is changed in for-loop.
       
  1181 // (other items were commented in a header).
       
  1182 // -----------------------------------------------------------------------------
       
  1183 //
       
  1184 TBool CCbsDbImpTopicMessages::DeleteReceivedIfNecessaryL()
       
  1185     {
       
  1186     CBSLOGSTRING("CBSSERVER: >>> CCbsDbImpTopicMessages::DeleteReceivedIfNecessaryL()");
       
  1187     
       
  1188     // So check if there are too many received messages in the topic. 
       
  1189     // Thus delete if message is not locked.
       
  1190 
       
  1191     __ASSERT_DEBUG( iCacheValid, CbsServerPanic( ECbsCacheNotValid ) );
       
  1192 
       
  1193     TInt totalReceived( 0 );
       
  1194     TCbsDbMessage message;
       
  1195     TBool result( EFalse );
       
  1196     TInt index( 0 );
       
  1197 
       
  1198     for ( index = 0; index < iMessageList->Count(); index++ ) 
       
  1199         {
       
  1200         LoadMessageL( index, message );
       
  1201 
       
  1202         // Count the amount of received messages
       
  1203         if ( !message.iPermanent )
       
  1204             {
       
  1205             totalReceived++;
       
  1206             
       
  1207             // If there are too many, then check that it can be deleted.
       
  1208             if ( totalReceived > KCbsDbMaxReceivedMessages && 
       
  1209                 !IsMessageLocked( message.iHandle ) )
       
  1210                 {
       
  1211                 // Delete the message.
       
  1212                 DeleteMessageByPositionL( index );
       
  1213                 iTopicList.InformMessageDeletedL
       
  1214                                     ( message.iHandle, 
       
  1215                                       message.iPermanent, 
       
  1216                                       message.iRead );
       
  1217                 result = ETrue;
       
  1218                 
       
  1219                 // They are always deleted from internal cache
       
  1220                 index--;
       
  1221                 totalReceived--;
       
  1222                 }
       
  1223             }
       
  1224         }
       
  1225 
       
  1226     CBSLOGSTRING2("CBSSERVER: <<< CCbsDbImpTopicMessages::DeleteReceivedIfNecessaryL(), returning %d.", result );
       
  1227     return result;
       
  1228     }
       
  1229 
       
  1230 // -----------------------------------------------------------------------------
       
  1231 // CCbsDbImpTopicMessages::DeleteMessageByPositionL
       
  1232 // Deletes message by its position in the internal cache.
       
  1233 // Note that after the call the internal cache won't contain 
       
  1234 // the item.
       
  1235 // (other items were commented in a header).
       
  1236 // -----------------------------------------------------------------------------
       
  1237 //
       
  1238 void CCbsDbImpTopicMessages::DeleteMessageByPositionL( 
       
  1239     TInt aIndex )
       
  1240     {
       
  1241     CBSLOGSTRING("CBSSERVER: >>> CCbsDbImpTopicMessages::DeleteMessageByPositionL()");
       
  1242     
       
  1243     // Delete from cache and from file.
       
  1244     __ASSERT_DEBUG( iCacheValid, CbsServerPanic( ECbsCacheNotValid ) );
       
  1245 
       
  1246     TCbsDbImpTopicMessagesCacheItem item( iMessageList->At( aIndex ) );
       
  1247 
       
  1248     // Determine the file where the message is stored.
       
  1249     CFileStore* store = item.iIsSaved ? iTopicList.TopicStoreL() :
       
  1250         iTopicList.UnsavedMessagesStore();
       
  1251 
       
  1252     iMessageList->Delete( aIndex );
       
  1253 
       
  1254     store->Delete( item.iId );
       
  1255     store->Delete( item.iContentsId );
       
  1256     
       
  1257     CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicMessages::DeleteMessageByPositionL()");
       
  1258     }
       
  1259 
       
  1260 // -----------------------------------------------------------------------------
       
  1261 // CCbsDbImpTopicMessages::IsMessageLocked
       
  1262 // Determines whether or not the message is locked.
       
  1263 // (other items were commented in a header).
       
  1264 // -----------------------------------------------------------------------------
       
  1265 //
       
  1266 TBool CCbsDbImpTopicMessages::IsMessageLocked( 
       
  1267     const TCbsDbMessageHandle& aHandle ) const
       
  1268     {
       
  1269     // Find out if the message is locked.
       
  1270     TBool found( EFalse );
       
  1271     TInt count( iLockedMessages->Count() );
       
  1272     for ( TInt index( 0 ); ( index < count ) && !found; index++ )
       
  1273         {
       
  1274         if ( iLockedMessages->At( index ) == aHandle )
       
  1275             {
       
  1276             found = ETrue;            
       
  1277             }
       
  1278         }
       
  1279 
       
  1280     return found;    
       
  1281     }
       
  1282 
       
  1283 // -----------------------------------------------------------------------------
       
  1284 // CCbsDbImpTopicMessages::DeleteFromLocked
       
  1285 // Deletes from the locked messages.
       
  1286 // (other items were commented in a header).
       
  1287 // -----------------------------------------------------------------------------
       
  1288 //
       
  1289 void CCbsDbImpTopicMessages::DeleteFromLocked( 
       
  1290     const TCbsDbMessageHandle& aHandle )
       
  1291     {
       
  1292     TBool deleted( EFalse );
       
  1293     TInt count( iLockedMessages->Count() );
       
  1294 
       
  1295     for ( TInt index( 0 ); ( index < count ) && !deleted; index++ )
       
  1296         {
       
  1297         if ( iLockedMessages->At( index ) == aHandle )
       
  1298             {
       
  1299             iLockedMessages->Delete( index );
       
  1300             deleted = ETrue;            
       
  1301             }
       
  1302         }
       
  1303     }
       
  1304 
       
  1305 // -----------------------------------------------------------------------------
       
  1306 // CCbsDbImpTopicMessages::InsertToLockedL
       
  1307 // Adds a handle to the locked messages.
       
  1308 // (other items were commented in a header).
       
  1309 // -----------------------------------------------------------------------------
       
  1310 //
       
  1311 void CCbsDbImpTopicMessages::InsertToLockedL( 
       
  1312     const TCbsDbMessageHandle& aHandle )
       
  1313     {
       
  1314     // Just append to the end. 
       
  1315     iLockedMessages->AppendL( aHandle );
       
  1316     }
       
  1317 
       
  1318 // -----------------------------------------------------------------------------
       
  1319 // CCbsDbImpTopicMessages::UpdateTopicMessagesStreamL
       
  1320 // Updates topic messages stream from the internal cache.
       
  1321 // (other items were commented in a header).
       
  1322 // -----------------------------------------------------------------------------
       
  1323 //
       
  1324 void CCbsDbImpTopicMessages::UpdateTopicMessagesStreamL(
       
  1325     TBool aDeleting )
       
  1326     {
       
  1327     CBSLOGSTRING("CBSSERVER: >>> CCbsDbImpTopicMessages::UpdateTopicMessagesStreamL()");
       
  1328     
       
  1329     __ASSERT_DEBUG( iCacheValid, CbsServerPanic( ECbsCacheNotValid ) );
       
  1330 
       
  1331     TInt neededSpace( KMessageRootStreamSize + 
       
  1332         iMessageList->Count() * KMessageEntrySize );
       
  1333 
       
  1334     RSharedDataClient sharedData;
       
  1335     // About to write to FFS: make critical level check
       
  1336     if ( aDeleting )
       
  1337         {
       
  1338         User::LeaveIfError( sharedData.Connect() );
       
  1339         sharedData.RequestFreeDiskSpaceLC( neededSpace ); // on CS
       
  1340         }
       
  1341     else
       
  1342         {
       
  1343         CbsUtils::FFSCriticalLevelCheckL( neededSpace, iFs );
       
  1344         }
       
  1345 
       
  1346     // Now, first check if the information fits well to the current stream.
       
  1347     if ( iSpaceForMessages >= iMessageList->Count() )
       
  1348         {
       
  1349         CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicMessages::UpdateTopicMessagesStreamL(): (3)");
       
  1350         
       
  1351         // Write data to the old stream.
       
  1352         TStreamId id;
       
  1353         iTopicList.GetTopicMessagesIdL( iCachedTopicNumber, id );
       
  1354         CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicMessages::UpdateTopicMessagesStreamL(): (4)");
       
  1355         
       
  1356         // Replace the existing stream.
       
  1357         RStoreWriteStream outstream;
       
  1358         outstream.ReplaceLC( *iTopicList.TopicStoreL(), id ); // on CS
       
  1359         CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicMessages::UpdateTopicMessagesStreamL(): (5)");
       
  1360     
       
  1361         WriteTopicMessagesStreamL( outstream );
       
  1362         CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicMessages::UpdateTopicMessagesStreamL(): (6)");
       
  1363 
       
  1364         outstream.CommitL();
       
  1365         CleanupStack::PopAndDestroy(); // outstream
       
  1366         }
       
  1367     else
       
  1368         {
       
  1369         CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicMessages::UpdateTopicMessagesStreamL(): (7)");
       
  1370         // Calculate the amount of space for messages.
       
  1371         if ( iSpaceForMessages == 0 )
       
  1372             {
       
  1373             // Zero is not very good, lets put it greater.
       
  1374             iSpaceForMessages = KDefaultSpaceForMessages;
       
  1375             }
       
  1376 
       
  1377         // But no need for extra messages.
       
  1378         iSpaceForMessages = 2 * iSpaceForMessages;
       
  1379         if ( iSpaceForMessages > 
       
  1380              ( KCbsDbMaxReceivedMessages + KCbsDbMaxSavedMessages ) )
       
  1381             {
       
  1382             iSpaceForMessages = 
       
  1383                 KCbsDbMaxReceivedMessages + KCbsDbMaxSavedMessages;
       
  1384             }
       
  1385         if ( iMessageList->Count() > iSpaceForMessages )
       
  1386             {
       
  1387             iSpaceForMessages = iMessageList->Count();
       
  1388             }
       
  1389 
       
  1390         // And finally write the data to stream.
       
  1391         RStoreWriteStream outstream;
       
  1392         TStreamId id = outstream.CreateLC( *iTopicList.TopicStoreL() );// on CS
       
  1393         CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicMessages::UpdateTopicMessagesStreamL(): (8)");
       
  1394 
       
  1395         WriteTopicMessagesStreamL( outstream );
       
  1396         CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicMessages::UpdateTopicMessagesStreamL(): (9)");
       
  1397 
       
  1398         outstream.CommitL();
       
  1399         CleanupStack::PopAndDestroy(); // outstream
       
  1400 
       
  1401         // And then update topic messages stream. It will also delete 
       
  1402         // the old stream.
       
  1403         iTopicList.UpdateTopicMessagesIdL( iCachedTopicNumber, id );
       
  1404         CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicMessages::UpdateTopicMessagesStreamL(): (10)");
       
  1405         }
       
  1406 
       
  1407     // Free the reserved space
       
  1408     if ( aDeleting )
       
  1409         {
       
  1410         CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicMessages::UpdateTopicMessagesStreamL(): (11)");
       
  1411         CleanupStack::PopAndDestroy(); // disk space
       
  1412         sharedData.Close();
       
  1413         }
       
  1414 
       
  1415     CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicMessages::UpdateTopicMessagesStreamL()"); 
       
  1416     }
       
  1417 
       
  1418 // -----------------------------------------------------------------------------
       
  1419 // CCbsDbImpTopicMessages::WriteTopicMessagesStreamL
       
  1420 // Writes topic messages stream from the internal cache.
       
  1421 // (other items were commented in a header).
       
  1422 // -----------------------------------------------------------------------------
       
  1423 //
       
  1424 void CCbsDbImpTopicMessages::WriteTopicMessagesStreamL( 
       
  1425     RWriteStream& aOut )
       
  1426     {
       
  1427     // Write total amount of messages.
       
  1428     TInt count( iMessageList->Count() );
       
  1429     aOut.WriteInt16L( count );
       
  1430 
       
  1431     // Write total amount of space for messages.
       
  1432     aOut.WriteInt16L( iSpaceForMessages );
       
  1433 
       
  1434     TInt index( 0 );
       
  1435 
       
  1436     for ( ; index < count; index++ )
       
  1437         {
       
  1438         CbsStreamHelper::WriteBoolL( aOut,
       
  1439             iMessageList->At( index ).iIsSaved );
       
  1440 
       
  1441         // Write message stream id.
       
  1442         aOut << iMessageList->At( index ).iId;
       
  1443         }
       
  1444 
       
  1445     for ( ; index < iSpaceForMessages; index++ )
       
  1446         {
       
  1447         CbsStreamHelper::WriteBoolL( aOut, EFalse );
       
  1448 
       
  1449         // Write null message stream id.
       
  1450         aOut << TStreamId( 0 );
       
  1451         }
       
  1452     }
       
  1453 
       
  1454 // -----------------------------------------------------------------------------
       
  1455 // CCbsDbImpTopicMessages::CreateMessageContentsStreamL
       
  1456 // Creates a new message content stream and writes 
       
  1457 // the given contents into this stream.
       
  1458 // (other items were commented in a header).
       
  1459 // -----------------------------------------------------------------------------
       
  1460 //
       
  1461 TStreamId CCbsDbImpTopicMessages::CreateMessageContentsStreamL(
       
  1462     CStreamStore&  aStore, 
       
  1463     const TDesC& aContents )
       
  1464     {
       
  1465     // Create stream and write data to it.
       
  1466     RStoreWriteStream outstream;
       
  1467     TStreamId id( outstream.CreateLC( aStore ) ); // on CS
       
  1468 
       
  1469     // Just write the contents..
       
  1470     TInt count( aContents.Length() );
       
  1471     outstream.WriteInt16L( count );
       
  1472 	outstream << aContents;
       
  1473 
       
  1474     outstream.CommitL();
       
  1475     CleanupStack::PopAndDestroy(); // outstream
       
  1476 
       
  1477     return id;
       
  1478     }
       
  1479 
       
  1480 // -----------------------------------------------------------------------------
       
  1481 // CCbsDbImpTopicMessages::CreateMessageStreamL
       
  1482 // Creates a message stream and
       
  1483 // writes the message into that stream. 
       
  1484 // (other items were commented in a header).
       
  1485 // -----------------------------------------------------------------------------
       
  1486 //
       
  1487 TStreamId CCbsDbImpTopicMessages::CreateMessageStreamL( 
       
  1488     CStreamStore& aStore, 
       
  1489     TCbsDbMessage& aMessage, 
       
  1490     const TStreamId& aContents )
       
  1491     {
       
  1492     // Create stream and write data to it.
       
  1493     RStoreWriteStream outstream;
       
  1494     TStreamId id = outstream.CreateLC( aStore ); // on CS
       
  1495 
       
  1496     // Write the handle.
       
  1497     outstream.WriteInt32L( aMessage.iHandle );
       
  1498 
       
  1499     // Write the message key.
       
  1500     outstream.WriteInt16L( aMessage.iKey );
       
  1501     
       
  1502     // Write the language.
       
  1503     outstream.WriteInt16L( aMessage.iLanguage );
       
  1504 
       
  1505     // Write the date and time.
       
  1506     outstream << aMessage.iDateTime;
       
  1507     
       
  1508     // Write the permanent status.
       
  1509     CbsStreamHelper::WriteBoolL( outstream, aMessage.iPermanent );
       
  1510     
       
  1511     // Write the read status.
       
  1512     CbsStreamHelper::WriteBoolL( outstream, aMessage.iRead );
       
  1513     
       
  1514     // Write the stream identifier to the contents.
       
  1515     outstream << aContents;
       
  1516 
       
  1517     outstream.CommitL();
       
  1518     CleanupStack::PopAndDestroy(); // outstream
       
  1519 
       
  1520     return id;
       
  1521     }
       
  1522 
       
  1523 // -----------------------------------------------------------------------------
       
  1524 // CCbsDbImpTopicMessages::ReadTopicMessagesCacheItemsL
       
  1525 // Reads all cache items for a topic.
       
  1526 // Restores topic message cache from a stream.
       
  1527 // (other items were commented in a header).
       
  1528 // -----------------------------------------------------------------------------
       
  1529 //
       
  1530 void CCbsDbImpTopicMessages::ReadTopicMessagesCacheItemsL( 
       
  1531     const CStreamStore& aStore, 
       
  1532     const TStreamId& aId, 
       
  1533     TCbsDbImpTopicMessagesCache& aCache, 
       
  1534     TInt& aSpace )
       
  1535     {
       
  1536     CBSLOGSTRING("CBSSERVER: >>> CCbsDbImpTopicMessages::ReadTopicMessagesCacheItemsL()");
       
  1537     
       
  1538     RStoreReadStream instream;
       
  1539     instream.OpenLC( aStore, aId ); // on CS
       
  1540     CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicMessages::ReadTopicMessagesCacheItemsL(): instream.OpenLC() OK.");
       
  1541 
       
  1542     // Read total amount of messages.
       
  1543     TInt totalMessages( instream.ReadInt16L() );
       
  1544     CBSLOGSTRING2("CBSSERVER: CCbsDbImpTopicMessages::ReadTopicMessagesCacheItemsL(): totalMessages: %d.", totalMessages );
       
  1545 
       
  1546     // Read total amount of space for messages.
       
  1547     aSpace = instream.ReadInt16L();
       
  1548     CBSLOGSTRING2("CBSSERVER: CCbsDbImpTopicMessages::ReadTopicMessagesCacheItemsL(): aSpace: %d.", aSpace );
       
  1549 
       
  1550     // Sanity check: if the number of messages exceeds
       
  1551     // the worst case, leave. If the space for messages
       
  1552     // is smaller than number of messages, leave.
       
  1553     if ( totalMessages > KCbsDbMaxSavedMessages + KCbsDbMaxReceivedMessages 
       
  1554         || aSpace < totalMessages )
       
  1555         {
       
  1556         CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicMessages::ReadTopicMessagesCacheItemsL(): Stream corrupt, leaving with KErrCorrupt...");
       
  1557         User::Leave( KErrCorrupt );
       
  1558         }
       
  1559 
       
  1560     TCbsDbImpTopicMessagesCacheItem item;
       
  1561 
       
  1562     aCache.Reset();
       
  1563 
       
  1564     for ( TInt index( 0 ); index < totalMessages; index++ )
       
  1565         {
       
  1566         CBSLOGSTRING2("CBSSERVER: CCbsDbImpTopicMessages::ReadTopicMessagesCacheItemsL(): Looping msgs, i: %d.", index );
       
  1567         item.iIsSaved = CbsStreamHelper::ReadBoolL( instream );
       
  1568 
       
  1569         // Read topic message stream id.
       
  1570         instream >> item.iId;
       
  1571 
       
  1572         // Initialize other fields.
       
  1573         item.iIsMessage = EFalse;
       
  1574 
       
  1575         // And finally, append the item to the array
       
  1576         aCache.AppendL( item );
       
  1577         
       
  1578         CBSLOGSTRING("CBSSERVER: CCbsDbImpTopicMessages::ReadTopicMessagesCacheItemsL(): Msg appended to array.");
       
  1579         }
       
  1580 
       
  1581     CleanupStack::PopAndDestroy(); // instream
       
  1582     
       
  1583     CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicMessages::ReadTopicMessagesCacheItemsL()");
       
  1584     }
       
  1585 
       
  1586 // -----------------------------------------------------------------------------
       
  1587 // CCbsDbImpTopicMessages::ReadMessageInformationL
       
  1588 // Restore a message from a stream.
       
  1589 // (other items were commented in a header).
       
  1590 // -----------------------------------------------------------------------------
       
  1591 //
       
  1592 void CCbsDbImpTopicMessages::ReadMessageInformationL( 
       
  1593     const CStreamStore& aStore, 
       
  1594     const TStreamId& aId, 
       
  1595     TCbsDbMessage& aMessage, 
       
  1596     TStreamId& aContentsId )
       
  1597     {
       
  1598     CBSLOGSTRING("CBSSERVER: >>> CCbsDbImpTopicMessages::ReadMessageInformationL()");
       
  1599     
       
  1600     // Open the message information stream.
       
  1601     RStoreReadStream instream;
       
  1602     instream.OpenLC( aStore, aId ); // on CS
       
  1603 
       
  1604     // Read the handle.
       
  1605     aMessage.iHandle = instream.ReadInt32L();
       
  1606 
       
  1607     // Read the message key.
       
  1608     aMessage.iKey = instream.ReadInt16L();
       
  1609     
       
  1610     // Read the language.
       
  1611     aMessage.iLanguage = instream.ReadInt16L();    
       
  1612     
       
  1613     // Read the date and time.
       
  1614     TInt64 time;
       
  1615     instream >> time;
       
  1616     aMessage.iDateTime = time;
       
  1617     
       
  1618     // Read the permanent status.
       
  1619     aMessage.iPermanent = CbsStreamHelper::ReadBoolL( instream );
       
  1620 
       
  1621     // Read the read status.
       
  1622     aMessage.iRead = CbsStreamHelper::ReadBoolL( instream );
       
  1623     
       
  1624     // Read the stream identifier to the contents.
       
  1625     instream >> aContentsId;
       
  1626 
       
  1627     CleanupStack::PopAndDestroy(); // instream
       
  1628 
       
  1629     if ( aContentsId == TStreamId( 0 ) )
       
  1630         {
       
  1631         aMessage.iLength = 0;
       
  1632         }
       
  1633     else
       
  1634         {
       
  1635         // Open message contents stream.
       
  1636         RStoreReadStream instreamContents;
       
  1637 
       
  1638         instreamContents.OpenLC( aStore, aContentsId ); // on CS
       
  1639 
       
  1640         // Read the length of the message.
       
  1641         aMessage.iLength = instreamContents.ReadInt16L();
       
  1642 
       
  1643         CleanupStack::PopAndDestroy(); // instreamContents
       
  1644         }
       
  1645     CBSLOGSTRING("CBSSERVER: <<< CCbsDbImpTopicMessages::ReadMessageInformationL()");
       
  1646     }
       
  1647 
       
  1648 // -----------------------------------------------------------------------------
       
  1649 // CCbsDbImpTopicMessages::WriteMessageInformationL
       
  1650 // Writes message information into a stream. 
       
  1651 // (other items were commented in a header).
       
  1652 // -----------------------------------------------------------------------------
       
  1653 //
       
  1654 void CCbsDbImpTopicMessages::WriteMessageInformationL( 
       
  1655     RWriteStream& aOut, 
       
  1656     const TCbsDbMessage& aMessage, 
       
  1657     const TStreamId& aContentsId )
       
  1658     {    
       
  1659     // Write the handle.
       
  1660     aOut.WriteInt32L( aMessage.iHandle );
       
  1661     
       
  1662     // Write the message key.
       
  1663     aOut.WriteInt16L( aMessage.iKey );
       
  1664     
       
  1665     // Write the language.
       
  1666     aOut.WriteInt16L( aMessage.iLanguage );
       
  1667         
       
  1668     // Write the date and time.
       
  1669     aOut << aMessage.iDateTime;
       
  1670     
       
  1671     // Write the permanent status.
       
  1672     CbsStreamHelper::WriteBoolL( aOut, aMessage.iPermanent );
       
  1673     
       
  1674     // Write the read status.
       
  1675     CbsStreamHelper::WriteBoolL( aOut, aMessage.iRead );
       
  1676     
       
  1677     // Write the stream identifier to the contents.
       
  1678     aOut << aContentsId;
       
  1679     }
       
  1680 
       
  1681 // -----------------------------------------------------------------------------
       
  1682 // CCbsDbImpTopicMessages::UpdateSoftNotificationL
       
  1683 // Updates the soft notification (dialog) when unread message count changes.           
       
  1684 // (other items were commented in a header).
       
  1685 // -----------------------------------------------------------------------------
       
  1686 //
       
  1687 void CCbsDbImpTopicMessages::UpdateSoftNotificationL( 
       
  1688     const TCbsDbMessageHandle& aHandle,
       
  1689     const CCbsRecEtel& aReceiver )
       
  1690     {
       
  1691     TCbsDbTopic topic;
       
  1692     TCbsDbTopicNumber topicNum( iTopicList.ExtractTopicNumber( aHandle ) );
       
  1693     iTopicList.FindTopicByNumberL( topicNum, topic ); 
       
  1694     
       
  1695     // If topic is hotmarked, update the soft notification (dialog) ,
       
  1696     // since number of read messages was changed
       
  1697     if ( topic.iHotmarked )
       
  1698         {            
       
  1699         aReceiver.Interface().LaunchMessageSoftNotificationL( EFalse );
       
  1700         } 
       
  1701     }
       
  1702     
       
  1703 // -----------------------------------------------------------------------------
       
  1704 // CCbsDbImpTopicMessages::RevertFileOperationL
       
  1705 // Reverts any not commited file operation in data files,
       
  1706 // reloads cache and then leaves with aReason.
       
  1707 // (other items were commented in a header).
       
  1708 // -----------------------------------------------------------------------------
       
  1709 //
       
  1710 void CCbsDbImpTopicMessages::RevertFileOperationL( 
       
  1711     TInt aReason )
       
  1712     {
       
  1713     iTopicList.RevertFilesL();
       
  1714     InvalidateCache();
       
  1715     User::Leave( aReason );
       
  1716     }
       
  1717 
       
  1718 // ========================== OTHER EXPORTED FUNCTIONS =========================
       
  1719 
       
  1720 //  End of File