mmsengine/mmsserver/src/mmslog.cpp
changeset 31 ebfee66fde93
child 47 5b14749788d7
equal deleted inserted replaced
30:6a20128ce557 31:ebfee66fde93
       
     1 /*
       
     2 * Copyright (c) 2002-2006 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  
       
    15 *     State machine for handling MMS log entries
       
    16 *     (sent messages and delivery reports)
       
    17 *
       
    18 */
       
    19 
       
    20 
       
    21 
       
    22 // INCLUDE FILES
       
    23 #include    <badesca.h>
       
    24 #include    <msvids.h>
       
    25 #include    <logcli.h>
       
    26 #include    <logview.h>
       
    27 // common component
       
    28 #include    <sysutil.h>
       
    29 #include    "LogsApiConsts.h"
       
    30 
       
    31 // MMS specific
       
    32 #include    "mmsconst.h"
       
    33 #include    "mmslog.h"
       
    34 #include    "mmsgenutils.h"
       
    35 #include    "mmsservercommon.h" // needed for logging
       
    36 
       
    37 // EXTERNAL DATA STRUCTURES
       
    38 
       
    39 // EXTERNAL FUNCTION PROTOTYPES  
       
    40 extern void gPanic(TMmsPanic aPanic);
       
    41 
       
    42 // CONSTANTS
       
    43 _LIT(KMmsLogEventTypeName, "MMS");
       
    44 
       
    45 // MACROS
       
    46 
       
    47 // LOCAL CONSTANTS AND MACROS
       
    48 
       
    49 // MODULE DATA STRUCTURES
       
    50 
       
    51 // LOCAL FUNCTION PROTOTYPES
       
    52 
       
    53 // ==================== LOCAL FUNCTIONS ====================
       
    54 
       
    55 // ================= MEMBER FUNCTIONS =======================
       
    56 
       
    57 // C++ default constructor can NOT contain any code, that
       
    58 // might leave.
       
    59 //
       
    60 CMmsLog::CMmsLog( CLogClient& aLogClient, CLogViewEvent& aLogViewEvent )
       
    61     :CMsgActive( EPriorityStandard ),
       
    62     iState( EMmsLogIdle ),
       
    63     iError( KErrNone ),
       
    64     iLogClient( aLogClient ),
       
    65     iLogViewEvent( aLogViewEvent ),
       
    66     iLastMatchedLink( KLogNullLink )
       
    67     {
       
    68     }
       
    69 
       
    70 // Symbian OS default constructor can leave.
       
    71 void CMmsLog::ConstructL( RFs& aFs )
       
    72     {
       
    73     
       
    74     iFs = aFs;
       
    75     iEntryId = KMsvNullIndexEntryId;
       
    76     iLogUpdatedEvent = CLogEvent::NewL();
       
    77     iFilterList = new ( ELeave ) CLogFilterList;
       
    78 
       
    79     CActiveScheduler::Add(this);
       
    80 
       
    81     }
       
    82 
       
    83 // Two-phased constructor.
       
    84 CMmsLog* CMmsLog::NewL( CLogClient& aLogClient, CLogViewEvent& aLogViewEvent, RFs& aFs )
       
    85     {
       
    86     CMmsLog* self = new (ELeave) CMmsLog( aLogClient, aLogViewEvent );
       
    87     
       
    88     CleanupStack::PushL( self );
       
    89     self->ConstructL( aFs );
       
    90     CleanupStack::Pop( self );
       
    91 
       
    92     return self;
       
    93     }
       
    94 
       
    95     
       
    96 // Destructor
       
    97 CMmsLog::~CMmsLog()
       
    98     {
       
    99     Cancel();
       
   100     // we don't delete those pointers that the caller owns.
       
   101     if( iFilterList )
       
   102         {
       
   103         iFilterList->ResetAndDestroy();
       
   104         delete iFilterList;
       
   105         }
       
   106     delete iLogUpdatedEvent;
       
   107     delete iLogEventType;
       
   108     }
       
   109 
       
   110 // ---------------------------------------------------------
       
   111 // CMmsLog::StartL
       
   112 //
       
   113 // ---------------------------------------------------------
       
   114 //
       
   115 void CMmsLog::StartL(
       
   116     CLogEvent& aLogEvent,
       
   117     CDesCArray& aRemoteParties,
       
   118     TRequestStatus& aStatus)
       
   119     {
       
   120     __ASSERT_DEBUG(iState==EMmsLogIdle,gPanic(EMmsAlreadyBusy));
       
   121 
       
   122     // We must save this because we are a state machine,
       
   123     // and we keep running around in circles ...
       
   124     iLastMatchedLink = KLogNullLink; 
       
   125     iLogEvent = &aLogEvent;
       
   126     iRemoteParties = &aRemoteParties;
       
   127     iCurrentRemoteParty = iRemoteParties->MdcaCount() - 1;
       
   128     if ( iCurrentRemoteParty < 0 )
       
   129         {
       
   130         // if no entries nothing to do
       
   131         TRequestStatus* status = &aStatus;
       
   132         aStatus = KRequestPending;
       
   133         User::RequestComplete( status, KErrNone );
       
   134         return;
       
   135         }
       
   136         
       
   137     TTime now;
       
   138     // the dates in log must be in universal time, not local time
       
   139     now.UniversalTime();
       
   140     if ( iLogEvent->Time().Int64() == 0 )
       
   141         {
       
   142         iLogEvent->SetTime( now );
       
   143         }
       
   144         
       
   145     iFilterList->ResetAndDestroy(); // Clear old filters - just in case
       
   146 
       
   147     // try adding event type only once
       
   148     iEventTypeAdded = EFalse;
       
   149 
       
   150     // Unfortunately neither Link nor Data (message id) can be used
       
   151     // in the filter.
       
   152     // We must filter for each remote party and match the id's separately
       
   153 
       
   154     Queue( aStatus );
       
   155     iStatus=KRequestPending;
       
   156 
       
   157     SetActive();
       
   158 
       
   159     // Pretend that we called an asynchronous service
       
   160     // in order to get into the state machine loop
       
   161     TRequestStatus* status = &iStatus;
       
   162     User::RequestComplete( status, KErrNone );
       
   163 
       
   164     }
       
   165     
       
   166 
       
   167 // ---------------------------------------------------------
       
   168 // CMmsLog::GetLink()
       
   169 // Returns the link id which is the same as TMsvId of the 
       
   170 // related message
       
   171 // ---------------------------------------------------------
       
   172 //
       
   173 TLogLink CMmsLog::GetLink()
       
   174 {
       
   175     return iLastMatchedLink;	
       
   176 }
       
   177 
       
   178 // ---------------------------------------------------------
       
   179 // CMmsLog::RunL()
       
   180 //
       
   181 // ---------------------------------------------------------
       
   182 //
       
   183 void CMmsLog::RunL()
       
   184 //
       
   185 // When the AO is state driven, this form of Run() is very effective
       
   186 // DoRunL() takes the AO through the states, queuing another asynch step as required
       
   187 // if DoRunL() detects the end of the cycle it returns without queuing another cycle.
       
   188 //
       
   189 // If Run() would exit without queuing another cycle it reports completion to the client.
       
   190 // This is true if the asynch step or DoRunL() fails, or the state cycle is complete
       
   191 //
       
   192     {
       
   193     iError = iStatus.Int();
       
   194     
       
   195 #ifndef _NO_MMSS_LOGGING_
       
   196     if ( iError != KErrNone )
       
   197         {
       
   198         TMmsLogger::Log( _L("CMmsLog RunL iError = %d"), iError);
       
   199         }
       
   200 #endif
       
   201     
       
   202     if ( iError >= KErrNone ||
       
   203         ( iError == KErrNotFound && iState == EMmsLogCreatingEntry ) )
       
   204         {
       
   205         TRAPD( error,DoRunL() );      // continue operations, may re-queue
       
   206         __ASSERT_DEBUG( error==KErrNone || !IsActive(),User::Invariant() );   // must not requeue in error situations
       
   207         if ( IsActive() )             // requeued
       
   208             return;
       
   209         iError = error;
       
   210         }
       
   211     Complete( iError );
       
   212     }
       
   213 
       
   214 // ---------------------------------------------------------
       
   215 // CMmsLog::DoRunL()
       
   216 //
       
   217 // ---------------------------------------------------------
       
   218 //
       
   219 void CMmsLog::DoRunL()
       
   220     {
       
   221 
       
   222     // This routine takes the state machine through the states
       
   223     // until an error is encountered or the cycle completes.
       
   224 
       
   225     if ( iError != KErrNone &&
       
   226         !( iState == EMmsLogCreatingEntry && iError == KErrNotFound 
       
   227            && iEventTypeAdded == EFalse ) )
       
   228         {
       
   229         // We encountered an error, and cannot continue
       
   230         iStatus = iError;
       
   231         iState = EMmsLogIdle;
       
   232         // If we return from DoRunL without becoming active again,
       
   233         // RunL completes.
       
   234         return;
       
   235         }
       
   236 
       
   237     if ( iError == KErrNotFound && iState == EMmsLogCreatingEntry )
       
   238         {
       
   239         iState = EMmsLogAddingEventType;
       
   240         iError = KErrNone;
       
   241         iEventTypeAdded = ETrue;
       
   242         // CreateEntryL decrements remote party
       
   243         // We get here only if we have tried creating entry and failed
       
   244         // after we have tried adding the event type, we retry
       
   245         // creating log entry
       
   246         iCurrentRemoteParty++;
       
   247         }
       
   248     else
       
   249         {
       
   250         SelectNextState();
       
   251         }
       
   252 
       
   253     if ( iState != EMmsLogFinal )
       
   254         {
       
   255         // If appropriate, ChangeState makes us active again
       
   256         ChangeStateL();
       
   257         // If we return from DoRunL without becoming active again,
       
   258         // RunL completes.
       
   259         }
       
   260     else
       
   261         {
       
   262         iState = EMmsLogIdle;
       
   263         // If we return from DoRunL without becoming active again,
       
   264         // RunL completes.
       
   265         }
       
   266 
       
   267     }
       
   268 
       
   269 // ---------------------------------------------------------
       
   270 // CMmsLog::DoComplete
       
   271 //
       
   272 // ---------------------------------------------------------
       
   273 //
       
   274 void CMmsLog::DoComplete( TInt& /* aStatus */ )
       
   275     {
       
   276     // We are exiting the loop - we say we are idle now
       
   277     // This is needed when the mms event type does not exist
       
   278     // in the log database.
       
   279     // In that case the entries cannot be logged, and the
       
   280     // state machine exits before reaching the final state.
       
   281     iState = EMmsLogIdle;
       
   282     }
       
   283 
       
   284 // ---------------------------------------------------------
       
   285 // CMmsLog::SelectNextState
       
   286 //
       
   287 // ---------------------------------------------------------
       
   288 //
       
   289 void CMmsLog::SelectNextState()
       
   290    {
       
   291 
       
   292     // If appropriate, the functions called within the switch statement
       
   293     // will make us active again. If all is done, the asynchronous request
       
   294     // will complete
       
   295 
       
   296     switch ( iState )
       
   297         {
       
   298         case EMmsLogIdle:
       
   299             iState = EMmsLogFiltering;
       
   300             break;
       
   301         case EMmsLogFiltering:
       
   302             if ( iEvents )
       
   303                 {
       
   304                 // Check if any of found entries matches our criteria
       
   305                 iState = EMmsLogMatchingEntry;
       
   306 #ifndef _NO_MMSS_LOGGING_
       
   307                 TMmsLogger::Log( _L("CMmsLog matching log entry"));
       
   308 #endif
       
   309                 }
       
   310             else
       
   311                 {
       
   312                 iState = EMmsLogCreatingEntry;
       
   313                 }
       
   314             break;
       
   315         case EMmsLogMatchingEntry:
       
   316             if ( iEventMatched )
       
   317                 {
       
   318                 iState = EMmsLogUpdatingEntry;
       
   319                 }
       
   320             else if ( iEvents )
       
   321                 {
       
   322                 // Something found from the database
       
   323                 // Check if any of found entries matches our criteria
       
   324                 iState = EMmsLogMatchingEntry;
       
   325                 }
       
   326             else
       
   327                 {
       
   328                 // no match, create new entry
       
   329                 iState = EMmsLogCreatingEntry;
       
   330                 }
       
   331             break;
       
   332         case EMmsLogUpdatingEntry:
       
   333             if ( iCurrentRemoteParty >= 0 )
       
   334                 {
       
   335                 iState = EMmsLogFiltering;
       
   336                 }
       
   337             else
       
   338                 {
       
   339                 // done
       
   340                 iState = EMmsLogFinal;
       
   341                 }
       
   342             break;
       
   343         case EMmsLogCreatingEntry:
       
   344             if ( iCurrentRemoteParty >= 0 )
       
   345                 {
       
   346                 iState = EMmsLogFiltering;
       
   347                 }
       
   348             else
       
   349                 {
       
   350                 // done
       
   351                 iState = EMmsLogFinal;
       
   352                 }
       
   353             break;
       
   354         case EMmsLogAddingEventType:
       
   355             iState = EMmsLogCreatingEntry;
       
   356             break;
       
   357         case EMmsLogFinal:
       
   358             break;
       
   359         default:
       
   360             break;
       
   361         }
       
   362 
       
   363    }
       
   364 
       
   365 // ---------------------------------------------------------
       
   366 // CMmsLog::ChangeState
       
   367 //
       
   368 // ---------------------------------------------------------
       
   369 //
       
   370 void CMmsLog::ChangeStateL()
       
   371     {
       
   372 
       
   373     switch ( iState )
       
   374         {
       
   375         case EMmsLogIdle:
       
   376             break;
       
   377         case EMmsLogFiltering:
       
   378             FilterL();
       
   379             break;
       
   380         case EMmsLogMatchingEntry:
       
   381             MatchEntryL();
       
   382             break;
       
   383         case EMmsLogUpdatingEntry:
       
   384             UpdateEntryL();
       
   385             break;
       
   386         case EMmsLogCreatingEntry:
       
   387             CreateEntryL();
       
   388             break;
       
   389         case EMmsLogAddingEventType:
       
   390             AddEventTypeL();
       
   391             break;
       
   392         case EMmsLogFinal:
       
   393             break;
       
   394         default:
       
   395             break;
       
   396         }
       
   397 
       
   398     }
       
   399 
       
   400 // ---------------------------------------------------------
       
   401 // CMmsLog::Filter
       
   402 //
       
   403 // ---------------------------------------------------------
       
   404 //
       
   405 void CMmsLog::FilterL()
       
   406     {
       
   407 
       
   408     iEvents = EFalse;
       
   409     iEventMatched = EFalse;
       
   410     
       
   411     // Try filtering by status
       
   412     // We cannot filter by remote party as it may be either a phone number
       
   413     // or an email address.
       
   414     // The best filter would be message id but it is stored in data field
       
   415     // and events cannot be filtered by data field.
       
   416     
       
   417     // We need to use several statuses depending on what we are doing
       
   418     // - If we are adding an entry in pending state, we only search pending entries
       
   419     // - If we are handling a delivery or read report, we must use all states
       
   420         
       
   421     TLogString logString;
       
   422     iLogClient.GetString( logString, R_LOG_DEL_PENDING );
       
   423     
       
   424     iFilterList->ResetAndDestroy(); // Clear old filters - just in case
       
   425     
       
   426     CLogFilter* filter = CLogFilter::NewL();
       
   427     CleanupStack::PushL( filter );
       
   428     filter->SetEventType( iLogEvent->EventType() );
       
   429     // We always filter with pending entries
       
   430     iLogClient.GetString( logString, R_LOG_DEL_PENDING );
       
   431     filter->SetStatus( logString );
       
   432     iFilterList->AppendL(filter);
       
   433     // Filter is now in the list - popped from cleanup stack		
       
   434     CleanupStack::Pop( filter );
       
   435 #ifndef _NO_MMSS_LOGGING_
       
   436     TMmsLogger::Log( _L("CMmsLog Filtering with status %S"), &filter->Status() );
       
   437 #endif
       
   438     filter = NULL; // this is out of our hands now
       
   439 
       
   440     // If we are handling reports, we must filter other statuses, too
       
   441     // logstring was set to pending, and that is the state when
       
   442     // creating new entries after sending.
       
   443     // If we are handling a delivery report or a read report, the status is
       
   444     // R_LOG_DEL_DONE, R_LOG_DEL_FAILED, or KLogsMsgReadText
       
   445     // We don't care about the failed ones.
       
   446     // If the entry has gone into failed state, we create a new one.
       
   447     // That should never happen - no new reports should arrive once something has
       
   448     // been put into failed state.
       
   449     
       
   450     if ( iLogEvent->Status().CompareF( logString ) != 0 )
       
   451         {
       
   452         // Filter entries that are already in delivered state
       
   453         filter = CLogFilter::NewL();
       
   454         CleanupStack::PushL( filter );
       
   455         filter->SetEventType( iLogEvent->EventType() );
       
   456         iLogClient.GetString( logString, R_LOG_DEL_DONE );
       
   457         filter->SetStatus( logString );
       
   458         iFilterList->AppendL(filter);
       
   459         // Filter is now in the list - popped from cleanup stack		
       
   460         CleanupStack::Pop( filter );
       
   461 #ifndef _NO_MMSS_LOGGING_
       
   462         TMmsLogger::Log( _L("CMmsLog Filtering with status %S"), &filter->Status() );
       
   463 #endif
       
   464         filter = NULL; // this is out of our hands now
       
   465         
       
   466         // Filter entries in "read" state just to prevent creation of a new one
       
   467         filter = CLogFilter::NewL();
       
   468         CleanupStack::PushL( filter );
       
   469         filter->SetEventType( iLogEvent->EventType() );
       
   470         logString.Copy( KLogsMsgReadText );
       
   471         filter->SetStatus( logString );
       
   472         iFilterList->AppendL(filter);
       
   473         // Filter is now in the list - popped from cleanup stack		
       
   474         CleanupStack::Pop( filter );
       
   475 #ifndef _NO_MMSS_LOGGING_
       
   476         TMmsLogger::Log( _L("CMmsLog Filtering with status %S"), &filter->Status() );
       
   477 #endif
       
   478         filter = NULL; // this is out of our hands now
       
   479         }
       
   480     
       
   481 #ifndef _NO_MMSS_LOGGING_
       
   482     if ( iLogEvent->EventType() == KLogMmsEventTypeUid )
       
   483         {
       
   484         TMmsLogger::Log( _L(" - and event type MMS") );
       
   485         }
       
   486     else
       
   487         {
       
   488         TMmsLogger::Log( _L("wrong event type %d"), iLogEvent->EventType() );
       
   489         }
       
   490 #endif
       
   491     
       
   492     iEvents = iLogViewEvent.SetFilterL( *iFilterList, iStatus );
       
   493 
       
   494     if ( iEvents )
       
   495         {
       
   496         SetActive();
       
   497         }
       
   498     else
       
   499         {
       
   500         // If there are no events, CLogViewEvent will not issue an asynchronous request
       
   501         // In that case we must complete ourselves
       
   502 #ifndef _NO_MMSS_LOGGING_
       
   503         TMmsLogger::Log( _L("CMmsLog found no MMS events in any state searched") );
       
   504 #endif
       
   505         iStatus = KRequestPending;
       
   506         SetActive();
       
   507         TRequestStatus* status = &iStatus;
       
   508         User::RequestComplete( status, KErrNone );
       
   509         }
       
   510     }
       
   511 
       
   512 // ---------------------------------------------------------
       
   513 // CMmsLog::MatchEntryL
       
   514 //
       
   515 // ---------------------------------------------------------
       
   516 //
       
   517 void CMmsLog::MatchEntryL()
       
   518     {
       
   519 
       
   520     iEventMatched = EFalse;
       
   521     // When a view is created, it is positioned on the first event
       
   522     // If we know our message entry id, we try to match it
       
   523     if ( iLogEvent->Link() != KLogNullLink )
       
   524         {
       
   525         if ( iLogEvent->Link() == iLogViewEvent.Event().Link() )
       
   526             {
       
   527             iEventMatched = ETrue;
       
   528             }
       
   529         }
       
   530     else
       
   531         {
       
   532         // Our message id (returned by MMSC) is stored to Data field.
       
   533         if ( iLogEvent->Data().Compare( iLogViewEvent.Event().Data() ) == 0 )
       
   534             {
       
   535             iEventMatched = ETrue;
       
   536             }
       
   537         }
       
   538 
       
   539     TPtrC dummy;
       
   540     TPtrC remoteParty;
       
   541     dummy.Set( iRemoteParties->MdcaPoint( iCurrentRemoteParty ) );
       
   542     if ( TMmsGenUtils::IsValidMMSPhoneAddress( dummy, ETrue ) )
       
   543         {
       
   544         dummy.Set( dummy.Right( Min( KMmsNumberOfDigitsToMatch, dummy.Length() ) ) );
       
   545         remoteParty.Set( iLogViewEvent.Event().Number().Right(
       
   546             Min ( dummy.Length(), iLogViewEvent.Event().Number().Length() ) ) );
       
   547         }
       
   548     else
       
   549         {
       
   550         dummy.Set( dummy.Right( Min( KLogMaxRemotePartyLength, dummy.Length() ) ) );
       
   551         remoteParty.Set( iLogViewEvent.Event().RemoteParty() );
       
   552         }
       
   553 
       
   554     if ( dummy.Compare( remoteParty ) != 0 )
       
   555         {
       
   556         iEventMatched = EFalse;
       
   557         }
       
   558         
       
   559     iStatus = KRequestPending;
       
   560     if ( iEventMatched )
       
   561         {
       
   562         iLastMatchedLink = iLogViewEvent.Event().Link();
       
   563         
       
   564         // found matching event, switch state to updating
       
   565         iLogUpdatedEvent->CopyL( iLogViewEvent.Event() );
       
   566         SetActive();
       
   567         TRequestStatus* status = &iStatus;
       
   568         User::RequestComplete( status, KErrNone );
       
   569         }
       
   570     else
       
   571         {
       
   572         // get next entry
       
   573         iEvents = iLogViewEvent.NextL( iStatus );
       
   574         SetActive();
       
   575         if ( iEvents == EFalse )
       
   576             {
       
   577             // If the LogViewEvent did not issue an asynchronous
       
   578             // request, we must complete ourselves
       
   579             TRequestStatus* status = &iStatus;
       
   580             User::RequestComplete( status, KErrNone );
       
   581             }
       
   582         }
       
   583     }
       
   584 
       
   585 // ---------------------------------------------------------
       
   586 // CMmsLog::UpdateEntryL
       
   587 //
       
   588 // ---------------------------------------------------------
       
   589 //
       
   590 void CMmsLog::UpdateEntryL()
       
   591     {
       
   592 
       
   593     // Update status and message id
       
   594     // If contact database id is not defined, try to update it too
       
   595     
       
   596     // We update the date only if it is later than what is already in the log
       
   597     // Otherwise we take the date that is already in the log
       
   598     if ( iLogUpdatedEvent->Time() < iLogEvent->Time() )
       
   599         {
       
   600         iLogUpdatedEvent->SetTime( iLogEvent->Time() );
       
   601         }
       
   602         
       
   603 #ifndef _NO_MMSS_LOGGING_
       
   604     TMmsLogger::Log( _L("CMmsLog updating log"));
       
   605     TTime time = iLogUpdatedEvent->Time(); 
       
   606     TBuf<KMmsDateBufferLength> dateString;
       
   607     time.FormatL(dateString,(_L("%*E%*D%X%*N%*Y %1 %2 '%3")));
       
   608     TMmsLogger::Log( _L(" - event date %S"), &dateString );
       
   609     time.FormatL(dateString,(_L("%-B%:0%J%:1%T%:2%S%:3%+B")));
       
   610     TMmsLogger::Log( _L(" - event time %S"), &dateString );
       
   611 #endif
       
   612 
       
   613     // This will mark the entry as "sent" or "delivered" or "failed"
       
   614     // or something similar...
       
   615     TBool doNotUpdate = EFalse;
       
   616      if ( iLogUpdatedEvent->Status().CompareF( KLogsMsgReadText ) == 0 )
       
   617          {
       
   618          // If the status is already "read" we don't change it
       
   619          // This is a case where a delivery report arrives after a read report.
       
   620          // Highly unlikely, but possible
       
   621          doNotUpdate = ETrue;
       
   622  #ifndef _NO_MMSS_LOGGING_
       
   623          TMmsLogger::Log( _L("Status already updated to read - do not update again"));
       
   624  #endif
       
   625          }
       
   626      else
       
   627          {
       
   628          iLogUpdatedEvent->SetStatus( iLogEvent->Status() );
       
   629          // Clear the event read flag in case the user has cleared the log view
       
   630          // We want this to become visible again.
       
   631          iLogUpdatedEvent->ClearFlags( KLogEventRead );
       
   632          }
       
   633     // if we have a message id, store it
       
   634     if ( ( iLogUpdatedEvent->Data().Length() <= 0 ) &&
       
   635         ( iLogEvent->Data().Length() > 0 ) )
       
   636         {
       
   637         iLogUpdatedEvent->SetDataL( iLogEvent->Data() );
       
   638         }
       
   639 
       
   640     // done with this remote party
       
   641     iCurrentRemoteParty--;
       
   642     
       
   643     if ( !doNotUpdate )
       
   644         {
       
   645         // update the entry
       
   646         iLogClient.ChangeEvent( *iLogUpdatedEvent, iStatus );
       
   647         SetActive();
       
   648         }
       
   649     else
       
   650         {
       
   651         // backward change - do not touch
       
   652         iStatus = KRequestPending;
       
   653         TRequestStatus* status = &iStatus;
       
   654         SetActive();
       
   655         User::RequestComplete( status, KErrNone );
       
   656         }
       
   657 
       
   658     }
       
   659 
       
   660 // ---------------------------------------------------------
       
   661 // CMmsLog::CreateEntry
       
   662 //
       
   663 // ---------------------------------------------------------
       
   664 //
       
   665 void CMmsLog::CreateEntryL()
       
   666     {
       
   667 
       
   668     TPtrC dummy;
       
   669     iLogUpdatedEvent->CopyL( *iLogEvent );
       
   670     dummy.Set( iRemoteParties->MdcaPoint( iCurrentRemoteParty ) );
       
   671     iLogUpdatedEvent->SetRemoteParty( dummy.Left(
       
   672         Min( dummy.Length(), KLogMaxRemotePartyLength ) ) );
       
   673         
       
   674 #ifndef _NO_MMSS_LOGGING_
       
   675     TMmsLogger::Log( _L("CMmsLog creating log entry"));
       
   676 #endif
       
   677 
       
   678     TInt error = KErrNone;
       
   679 
       
   680     // search contact database only if remote party is phone number
       
   681     // we don't log email recipients when sending.
       
   682     // However, if we get a delivery report from an email address, we log it.
       
   683 
       
   684     if ( TMmsGenUtils::IsValidMMSPhoneAddress( dummy, ETrue ) )
       
   685         {
       
   686         iLogUpdatedEvent->SetNumber( dummy.Right(
       
   687             Min( dummy.Length(), KLogMaxRemotePartyLength ) ) );
       
   688         error = TMmsGenUtils::GetAlias(
       
   689             iRemoteParties->MdcaPoint( iCurrentRemoteParty ),
       
   690             iAlias,
       
   691             KLogMaxRemotePartyLength,
       
   692             iFs );
       
   693             
       
   694         if ( error == KErrNone )
       
   695             {
       
   696             if ( iAlias.Length() > 0 )
       
   697                 {
       
   698                 iLogUpdatedEvent->SetRemoteParty( iAlias );
       
   699                 }
       
   700             }
       
   701         }
       
   702 
       
   703     // done with this remote party
       
   704     TInt size = KMmsIntegerSize; // room for integer types - estimate - 32 bytes
       
   705     size += iLogUpdatedEvent->RemoteParty().Size();
       
   706     size += iLogUpdatedEvent->Direction().Size();
       
   707     size += iLogUpdatedEvent->Status().Size();
       
   708     size += iLogUpdatedEvent->Number().Size();
       
   709     size += iLogUpdatedEvent->Description().Size();
       
   710     size += iLogUpdatedEvent->Data().Size();
       
   711     iCurrentRemoteParty--;
       
   712 
       
   713     // Query about disk space.
       
   714     if ( TMmsGenUtils::DiskSpaceBelowCriticalLevelL( &iFs, size, EDriveC ) )
       
   715         {
       
   716         // we use standard error code here
       
   717         iError = KErrDiskFull;
       
   718         }
       
   719     if ( iError != KErrDiskFull )
       
   720         {
       
   721         iLogClient.AddEvent( *iLogUpdatedEvent, iStatus );
       
   722         SetActive();
       
   723         }
       
   724     else
       
   725         {
       
   726         User::Leave( iError );
       
   727         }
       
   728     }
       
   729 
       
   730 // ---------------------------------------------------------
       
   731 // CMmsLog::AddEventTypeL
       
   732 //
       
   733 // ---------------------------------------------------------
       
   734 //
       
   735 void CMmsLog::AddEventTypeL()
       
   736     {
       
   737     // Event type is added if create event returns KErrNotFound
       
   738     iLogEventType = CLogEventType::NewL();
       
   739     iLogEventType->SetUid( KLogMmsEventTypeUid );
       
   740     iLogEventType->SetDescription( KMmsLogEventTypeName );
       
   741     iLogEventType->SetLoggingEnabled( ETrue );
       
   742     iLogClient.AddEventType( *iLogEventType, iStatus );
       
   743     SetActive();
       
   744     }
       
   745 
       
   746 // ================= OTHER EXPORTED FUNCTIONS ==============
       
   747 
       
   748 //  End of File  
       
   749