loggingservices/eventlogger/LogServ/src/LOGADD.CPP
changeset 0 08ec8eefde2f
child 6 5ffdb8f2067f
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <s32file.h>
       
    17 #include <logcntmodel.h>
       
    18 #include <logengevents.h>
       
    19 #include "LOGADD.H"
       
    20 #include "logservpanic.h"
       
    21 #include "LOGDUP.H"
       
    22 #include "LOGQUERY.H"
       
    23 #include "LogServRecentList.h"
       
    24 #include "LogServDatabaseTransactionInterface.h"
       
    25 #include "LogServResourceInterpreter.h"
       
    26 #include "LogServCacheConfig.h"
       
    27 #include "LogServDatabaseChangeInterface.h"
       
    28 #include <logserv.rsg>
       
    29 #include <centralrepository.h>
       
    30 #include "LogServCacheStrings.h"
       
    31 #include "LogServCacheTypes.h"
       
    32 #include "LOGREPDEFS.H"
       
    33 
       
    34 const TInt KMinimumNumberOfDigitsToMatch = 3;
       
    35 
       
    36 ////////////////////////////////////////////////////////////////////////////////////////////
       
    37 // Local functions
       
    38 
       
    39 #ifdef SYSLIBS_TEST
       
    40 
       
    41 #pragma BullseyeCoverage off
       
    42 
       
    43 static void LogStore32IntL(RFs& aFs, const TDesC& aFilePath, TInt aVal)
       
    44 	{
       
    45 	RFile file;
       
    46 	User::LeaveIfError(file.Replace(aFs, aFilePath, EFileWrite));
       
    47 	TPtrC8 p((const TUint8*)&aVal, sizeof(aVal));
       
    48 	TInt err = file.Write(p);
       
    49 	if(err == KErrNone)
       
    50 		{
       
    51 		err = file.Flush();
       
    52 		}
       
    53 	file.Close();
       
    54 	User::LeaveIfError(err);
       
    55 	}
       
    56 
       
    57 static void LogStoreContactMatchCountAndNameFormatL(TInt aContactMatchCount, TLogContactNameFormat aContactNameFormat)
       
    58 	{
       
    59 	RFs fs;
       
    60 	CleanupClosePushL(fs);
       
    61 	User::LeaveIfError(fs.Connect());
       
    62 
       
    63 	_LIT(KTestDir, "c:\\test\\");
       
    64 	TInt err = fs.MkDir(KTestDir);
       
    65 	if(err != KErrNone && err != KErrAlreadyExists)
       
    66 		{
       
    67 		User::Leave(err);
       
    68 		}
       
    69 	
       
    70 	_LIT(KLogengTestFileNameCount, "c:\\test\\test_logengconfig_count.ini");
       
    71 	LogStore32IntL(fs, KLogengTestFileNameCount, aContactMatchCount);
       
    72 	
       
    73 	_LIT(KLogengTestFileNameFormat, "c:\\test\\test_logengconfig_format.ini");
       
    74 	LogStore32IntL(fs, KLogengTestFileNameFormat, (TInt)aContactNameFormat);
       
    75 	
       
    76 	CleanupStack::PopAndDestroy(&fs);
       
    77 	}
       
    78 
       
    79 #pragma BullseyeCoverage on
       
    80 
       
    81 #endif //SYSLIBS_TEST
       
    82 
       
    83 //This function reads logeng repository file and returns the integer value of the given key. 
       
    84 static TInt LogGetRepositoryValueL(CRepository& aRepository, TInt aKey)
       
    85 	{		
       
    86 	TInt val = -1;		
       
    87 	User::LeaveIfError(aRepository.Get(aKey, val));
       
    88 	return val;
       
    89 	}
       
    90 
       
    91 //This function reads logeng resource file and returns the integer value of the given resource id. 
       
    92 static TInt LogGetResourceValueL(CLogServResourceInterpreter& aResourceInterpreter, TInt aResourceId)
       
    93 	{		
       
    94 	TResourceReader reader;
       
    95 	aResourceInterpreter.CreateResourceReaderLC(reader, aResourceId, CLogServResourceInterpreter::ELogServer);
       
    96 	TInt val = reader.ReadInt16();
       
    97 	CleanupStack::PopAndDestroy();
       
    98 	return val;
       
    99 	}
       
   100 
       
   101 static void LogGetContactmatchCountAndNameFormatL(CLogServResourceInterpreter& aResourceInterpreter, TInt& aContactMatchCount, TLogContactNameFormat& aContactNameFormat)
       
   102 	{
       
   103 	CRepository* repository = NULL;
       
   104 	TRAPD(err, repository = CRepository::NewL(KUidLogengRepository));		
       
   105 	if(err == KErrCorrupt)
       
   106 		{
       
   107 		__ASSERT_DEBUG(!repository, User::Invariant());
       
   108 		User::Leave(err);
       
   109 		}
       
   110 	else if(err == KErrNone)
       
   111 		{
       
   112 		CleanupStack::PushL(repository);
       
   113 		aContactMatchCount = LogGetRepositoryValueL(*repository, KContactMatchCountRepKey);
       
   114 		aContactNameFormat = static_cast <TLogContactNameFormat> (LogGetRepositoryValueL(*repository, KContactNameFormatRepKey));
       
   115 		CleanupStack::PopAndDestroy(repository);
       
   116 		}
       
   117 	else
       
   118 		{
       
   119 		__ASSERT_DEBUG(!repository, User::Invariant());
       
   120 		aContactMatchCount = LogGetResourceValueL(aResourceInterpreter, R_LOG_CONTACT_MATCH_COUNT);
       
   121 		aContactNameFormat = static_cast <TLogContactNameFormat> (LogGetResourceValueL(aResourceInterpreter, R_LOG_CONTACT_NAME_FORMAT));
       
   122 		}
       
   123 	#ifdef SYSLIBS_TEST
       
   124 	LogStoreContactMatchCountAndNameFormatL(aContactMatchCount, aContactNameFormat);
       
   125 	#endif	
       
   126 	}
       
   127 
       
   128 ////////////////////////////////////////////////////////////////////////////////////////////
       
   129 // CLogAddEvent class
       
   130 
       
   131 CLogAddEvent::CLogAddEvent(MLogServDatabaseTransactionInterface& aDatabase, TInt aPriority) :
       
   132 	CLogActive(aPriority), 
       
   133 	iDatabase(aDatabase)
       
   134 	{
       
   135 	}
       
   136 
       
   137 CLogAddEvent::~CLogAddEvent()
       
   138 	{
       
   139 	Cancel();
       
   140 	
       
   141 	CloseContactsPlugin();
       
   142 
       
   143 	delete iDuplicate;
       
   144 	delete iDuplicateFilter;
       
   145 	}
       
   146 
       
   147 CLogAddEvent* CLogAddEvent::NewL(MLogServDatabaseTransactionInterface& aDatabase, TInt aPriority)
       
   148 	{
       
   149 	CLogAddEvent* self = new(ELeave) CLogAddEvent(aDatabase, aPriority);
       
   150 	CleanupStack::PushL(self);
       
   151 	self->ConstructL();
       
   152 	CleanupStack::Pop(self);
       
   153 	return self;
       
   154 	}
       
   155 
       
   156 void CLogAddEvent::ConstructL()
       
   157 	{
       
   158 	iDuplicate = CLogDuplicate::NewL(iDatabase, Priority());
       
   159 	iDuplicateFilter = CLogFilter::NewL();
       
   160 	::LogGetContactmatchCountAndNameFormatL(iDatabase.DTIResourceInterface(), iContactMatchCount, iContactNameFormat);
       
   161 	}
       
   162 
       
   163 //This method will open contacts database (if not opened yet), only if the value of 
       
   164 //r_log_contact_match_count resource in logserv.rsg resource file is not 0.
       
   165 //Se how iContactMatchCount data member is initialised.
       
   166 TBool CLogAddEvent::PerformContactMatchL()
       
   167 	{
       
   168 	if (iContactMatchCount <= 0 || iEvent->Contact() != KLogNullContactId)
       
   169 		return EFalse;
       
   170 	
       
   171 	if (iContactPlugin)
       
   172 		return ETrue;
       
   173 	
       
   174 	// Attempt to load plugin
       
   175 	TRAPD( err, iContactPlugin=CLogCntModel::NewL());
       
   176 
       
   177 	// If plugin doesn't exist this is equivalent to matching being disabled so we don't leave
       
   178 	// for KErrNotFound
       
   179 	if(err==KEComErrNoInterfaceIdentified)
       
   180 		{
       
   181 		// Disable contacts matching so that we don't keep attempting to match
       
   182 		iContactMatchCount = 0;
       
   183 		// Plugin doesn't exist
       
   184 		return EFalse;
       
   185 		}
       
   186 
       
   187 	User::LeaveIfError(err);
       
   188 	
       
   189 	// Open the DB
       
   190 	OpenContactsL();
       
   191 	
       
   192 	return ETrue;
       
   193 	}
       
   194 
       
   195 void CLogAddEvent::StartL(CLogEvent& aEvent, const CLogServRecentList* aRecentList, TRequestStatus& aStatus, const RMessage2& aMessage)
       
   196 	{
       
   197 	__ASSERT_ALWAYS(!IsActive(), Panic(ELogAlreadyActive1));
       
   198 
       
   199 	LOGTEXT("CLogAddEvent::StartL()");
       
   200 
       
   201 	// Store event details which were obtained from the client side
       
   202 	iEvent = &aEvent;
       
   203 	iState = ELogAddEvent;
       
   204 	
       
   205 	if (!iDatabase.DTIIsAllowed(EWriteOp, aMessage, iEvent->EventType()))
       
   206 		{
       
   207 		User::Leave(KErrPermissionDenied);
       
   208 		}
       
   209 
       
   210 	if (PerformContactMatchL())
       
   211 		iState = ELogSetContactAndRemoteParty; // Go look for a matching contact
       
   212 
       
   213 	iRecentList = aRecentList;
       
   214 	iEventAdded = EFalse;
       
   215 
       
   216 	// Setup the event's time (UTC)
       
   217 	TTime time;
       
   218 	time.UniversalTime();
       
   219 	iEvent->SetTime(time);
       
   220 
       
   221 	// Save the observer's request status and set it to KRequestPending
       
   222 	Queue(aStatus);
       
   223 
       
   224 	// Start this objects RunL chain
       
   225 	TRequestStatus* status = &iStatus;
       
   226 	User::RequestComplete(status, KErrNone);
       
   227 	SetActive();
       
   228 	}
       
   229 	
       
   230 void CLogAddEvent::SetEventContact()
       
   231     {
       
   232     // Start by converting the phone number text into a number
       
   233     // check we've got a long enough number to be worth checking
       
   234     if(iEvent->Number().Length() >= KMinimumNumberOfDigitsToMatch)
       
   235         {
       
   236         // now search for a contact by looking up the phone number
       
   237         TLogContactItemId contactId = KLogNullContactId;
       
   238         TRAPD(err, contactId = iContactPlugin->MatchPhoneNumberL(iEvent->Number(), iContactMatchCount));
       
   239         
       
   240         if(err == KErrNone)
       
   241             {
       
   242             // we have at least one match
       
   243             if(contactId != KLogNullContactId)
       
   244                 {
       
   245                 // we have a match so set the contact id
       
   246                 iEvent->SetContact(contactId);
       
   247                 }
       
   248             }
       
   249         }
       
   250     iEvent->SetFlags(KLogEventContactSearched);
       
   251     }
       
   252 
       
   253 void CLogAddEvent::SetRemoteParty()
       
   254     {
       
   255     // Get the contact id
       
   256     TLogContactItemId  contactId = iEvent->Contact();
       
   257     if((contactId != KLogNullContactId) && (iEvent->RemoteParty().Length() == 0))
       
   258         {
       
   259         // Look it up and get the remote party info
       
   260         // Setup buffer to contain concatenated result
       
   261         TBuf<128> buf;
       
   262         // Go get the info
       
   263         TRAPD(err, iContactPlugin->ReadContactNameL(contactId, buf, iContactNameFormat));
       
   264 
       
   265         if(err == KErrNotFound)
       
   266             {
       
   267             // Couldn't find the contact with that id so set it to NULL
       
   268             iEvent->SetContact(KLogNullContactId);
       
   269             }
       
   270         else
       
   271             {
       
   272             // Found it so fill in remote party
       
   273             iEvent->SetRemoteParty(buf);
       
   274             }
       
   275         }
       
   276     }
       
   277 
       
   278 void CLogAddEvent::GetConfigL()
       
   279     {
       
   280     iConfig = iDatabase.DTICacheConfig().Config();
       
   281     if(iConfig.iMaxLogSize == 0)
       
   282       {
       
   283       LOGTEXT("CLogAddEvent::DoRunL() - logging disabled");
       
   284       User::Leave(KErrNotSupported);
       
   285       }
       
   286     }
       
   287 
       
   288 TLogTypeId CLogAddEvent::SetDescriptionL()
       
   289     {
       
   290     const TLogServCacheTypeEntry& entry = iDatabase.DTICacheTypes().FindByUid(iEvent->EventType());
       
   291     if(entry.iEventTypeId == KLogNullTypeId)
       
   292         {
       
   293         LOGTEXT("CLogAddEvent::DoRunL() - type not found");
       
   294         User::Leave(KErrNotFound);
       
   295         }
       
   296     if(!entry.iEventType->LoggingEnabled())
       
   297         {
       
   298         LOGTEXT("CLogAddEvent::DoRunL() - type not enabled");
       
   299         User::Leave(KErrNotSupported);
       
   300         }
       
   301     iEvent->SetDescription(entry.iEventType->Description());
       
   302     return entry.iEventTypeId;
       
   303     }
       
   304     
       
   305 TBool CLogAddEvent::DetectDuplicateEventsL()
       
   306     {
       
   307     TBool rc = EFalse;
       
   308     if(iRecentList)
       
   309         {
       
   310         iRecentList->GetFilter(*iEvent, *iDuplicateFilter);
       
   311         rc = iDuplicate->StartL(iEvent->Id(), iRecentList->Id(), *iDuplicateFilter, iStatus);
       
   312         }
       
   313     return rc;
       
   314     }
       
   315 
       
   316 void CLogAddEvent::DoRunL()
       
   317 	{
       
   318 	LOGTEXT3("CLogAddEvent::DoRunL(%d), state = %d", iStatus.Int(), iState);
       
   319 
       
   320 	switch (iState)
       
   321 		{
       
   322 		case ELogSetContactAndRemoteParty:
       
   323 			{
       
   324 			SetEventContact();
       
   325 			SetRemoteParty();
       
   326 			TRequestStatus* status = &iStatus;
       
   327 			User::RequestComplete(status, KErrNone);
       
   328 			iState = ELogAddEvent;
       
   329 			SetActive();
       
   330 			break;
       
   331 			}
       
   332 		case ELogAddEvent:
       
   333 			{
       
   334 			GetConfigL();
       
   335 			TLogTypeId typeId = SetDescriptionL();
       
   336 			RLogEventDbTable tbl;
       
   337 			tbl.OpenLC(iDatabase.DTIDatabase());
       
   338 			::LogPurgeMainL(iDatabase, tbl, iConfig.iMaxLogSize, 1);
       
   339 			DoAddEventL(tbl, typeId, iDatabase.DTICacheStrings().GetIdL(iEvent->Direction()), iDatabase.DTICacheStrings().GetIdL(iEvent->Status()));
       
   340             CleanupStack::PopAndDestroy();//tbl
       
   341 			iEventAdded = ETrue;
       
   342 			if(DetectDuplicateEventsL())
       
   343 			    {
       
   344                 iState = ELogPurgeRecent;
       
   345                 SetActive();
       
   346                 break;
       
   347 			    }
       
   348 			iState = ELogPurgeRecent;
       
   349 			TRequestStatus* status = &iStatus;
       
   350 			User::RequestComplete(status, KErrNone);
       
   351 			SetActive();
       
   352 			break;
       
   353 			}
       
   354 		case ELogPurgeRecent:
       
   355 			{
       
   356 			// Delete old recent events
       
   357 			if (iRecentList)
       
   358 				{
       
   359 				RArray<TLogId> logIds;
       
   360 				::LogGetRecentEventsLC(iDatabase, iRecentList->Id(), iConfig.iMaxRecentLogSize, logIds); 
       
   361 				::LogPurgeRecentEventsL(iDatabase, logIds);
       
   362 				CleanupStack::PopAndDestroy(&logIds);
       
   363 				}
       
   364 			}
       
   365 			break;
       
   366 		default:
       
   367 			__ASSERT_DEBUG(ETrue, Panic(ELogBadState1));
       
   368             break;
       
   369 		}
       
   370 
       
   371 	LOGTEXT("CLogAddEvent::DoRunL() - end");
       
   372 	}
       
   373 
       
   374 void CLogAddEvent::DoCancel()
       
   375 	{
       
   376 	iDuplicate->Cancel();
       
   377 	CLogActive::DoCancel();
       
   378 	}
       
   379 
       
   380 void CLogAddEvent::DoAddEventL(RLogEventDbTable& aTbl, TLogTypeId aTypeId, TLogStringId aDirectionId, TLogStringId aStatusId)
       
   381 	{
       
   382 	LOGTEXT("CLogAddEvent::DoAddEventL()");
       
   383 
       
   384 	// Insert a new record
       
   385 	aTbl.InsertL();
       
   386 
       
   387 	aTbl.SetColL(RLogEventDbTable::iTypeColNo, (TUint32)aTypeId);
       
   388 
       
   389 	if (iEvent->RemoteParty().Length() > 0)
       
   390 		aTbl.SetColL(RLogEventDbTable::iRemotePartyColNo, iEvent->RemoteParty());
       
   391 
       
   392 	if (iEvent->Direction().Length() > 0)
       
   393 		aTbl.SetColL(RLogEventDbTable::iDirectionColNo, (TUint32)aDirectionId);
       
   394 
       
   395 	aTbl.SetColL(RLogEventDbTable::iTimeColNo, iEvent->Time());
       
   396 	aTbl.SetColL(RLogEventDbTable::iDurationTypeColNo, (TInt32)iEvent->DurationType());
       
   397 
       
   398 	if (iEvent->DurationType() != KLogNullDurationType)
       
   399 		aTbl.SetColL(RLogEventDbTable::iDurationColNo, iEvent->Duration());
       
   400 
       
   401 	if (iEvent->Status().Length() > 0)
       
   402 		aTbl.SetColL(RLogEventDbTable::iStatusColNo, (TUint32)aStatusId);
       
   403 
       
   404 	if (iEvent->Subject().Length() > 0)
       
   405 		aTbl.SetColL(RLogEventDbTable::iSubjectColNo, iEvent->Subject());
       
   406 
       
   407 	if (iEvent->Number().Length() > 0)
       
   408 		aTbl.SetColL(RLogEventDbTable::iNumberColNo, iEvent->Number());
       
   409 
       
   410 	if (iEvent->Contact() != KLogNullContactId)
       
   411 		aTbl.SetColL(RLogEventDbTable::iContactColNo, iEvent->Contact());
       
   412 
       
   413 	if (iEvent->Link() != KLogNullLink)
       
   414 		aTbl.SetColL(RLogEventDbTable::iLinkColNo, iEvent->Link());
       
   415 
       
   416 	if (iEvent->Data().Length() > 0)
       
   417 		aTbl.SetColL(RLogEventDbTable::iDataColNo, iEvent->Data());
       
   418 
       
   419 	// Set the flags
       
   420 	TInt bit = KLogFlagsCount;
       
   421 	while(bit--)
       
   422 		{
       
   423 		aTbl.SetColL(RLogEventDbTable::iFlagColNo[bit], (TUint32)((iEvent->Flags() & 0x1 << bit) ? 1 : 0));
       
   424 		}
       
   425 
       
   426 	if (iRecentList)
       
   427 		{
       
   428 		__ASSERT_DEBUG(iRecentList->Id() != KLogNullRecentList, Panic(ELogNullRecentList));
       
   429 		aTbl.SetColL(RLogEventDbTable::iRecentColNo, (TInt32)iRecentList->Id());
       
   430 		}
       
   431 
       
   432 #ifdef SYMBIAN_ENABLE_EVENTLOGGER_DUALSIM	
       
   433 	if(iEvent->SimId() != KLogNullSimId)
       
   434 		{
       
   435 		aTbl.SetColL(RLogEventDbTable::iSimIdColNo, iEvent->SimId());
       
   436 		}
       
   437 	else
       
   438 		{
       
   439 		aTbl.SetColNullL(RLogEventDbTable::iSimIdColNo);
       
   440 		}
       
   441 #endif
       
   442 	
       
   443 	// Assign event id and end the rowset operation
       
   444 	const TLogId newId = aTbl.ColInt32(RLogEventDbTable::iIdColNo);
       
   445 	iEvent->SetId(newId);
       
   446 	aTbl.PutL();
       
   447 
       
   448 	// Tell change interface about the addition
       
   449 	iDatabase.DTIChangeInterface().DCISubmitChangedEventContextL(ELogChangeTypeEventAdded, newId);
       
   450 
       
   451 	LOGTEXT("CLogAddEvent::DoAddEventL() - end");
       
   452 	}
       
   453 
       
   454 void CLogAddEvent::DoComplete(TInt& aStatus)
       
   455 	{
       
   456 	LOGTEXT2("CLogAddEvent::DoComplete(%d)", aStatus);
       
   457 
       
   458 	if	(iDatabase.DTIInTransaction())
       
   459 		{
       
   460 		LOGTEXT2("CLogAddEvent::DoComplete() - in transaction: %d", aStatus);
       
   461 		if (aStatus == KErrNone)
       
   462 			aStatus = iDatabase.DTICommitAndEnd();
       
   463 
       
   464 		LOGTEXT2("CLogAddEvent::DoComplete() - checking for need to rollback: %d", aStatus);
       
   465 		if (aStatus < KErrNone)
       
   466 			iDatabase.DTIRollBack();
       
   467 		}
       
   468 	else
       
   469 		{
       
   470 		if	(iEventAdded)
       
   471 			aStatus = KErrNone;
       
   472 		}
       
   473 
       
   474 	LOGTEXT2("CLogAddEvent::DoComplete() - final status value is: %d", aStatus);
       
   475 	}
       
   476 
       
   477 //Opens the default contacts database.
       
   478 void CLogAddEvent::OpenContactsL()
       
   479 	{
       
   480 	//Sometimes, after a sequence of OpenContactsL()/CloseContacts() calls the Contacts server crashes
       
   481 	//and OpenContactsL() leaves with error -15. In order to avoid that the following delay has been added.
       
   482 	//(something related to Contacts server state machine)
       
   483     User::After(100);
       
   484 	// Attempt to open DB
       
   485 	TRAPD(err,iContactPlugin->OpenContactsL());
       
   486 	if(KErrNone!=err)
       
   487 		{
       
   488 		// If DB doesn't open delete plugin
       
   489 		delete iContactPlugin;
       
   490 		iContactPlugin = NULL;
       
   491 		User::Leave(err);
       
   492 		}
       
   493 	}
       
   494 
       
   495 //Closes the default contacts database and deletes the plugin.
       
   496 void CLogAddEvent::CloseContactsPlugin()
       
   497 	{
       
   498 	if(iContactPlugin)
       
   499 		{
       
   500 		iContactPlugin->CloseContacts();
       
   501 		delete iContactPlugin;
       
   502 		iContactPlugin = NULL;
       
   503 		//REComSession::FinalClose() call moved here from logcntmodel.cpp.
       
   504 		//The in-source documentation of REComSession::FinalClose() notes that: 
       
   505 		//"It must never be called from within a plug-in implementations class 
       
   506 		//destructor, especially following a DestroyImplementation() ". 
       
   507 		//That was the case before the function call was moved here.
       
   508 	    REComSession::FinalClose();
       
   509 		}
       
   510 	}