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