diff -r 000000000000 -r 08ec8eefde2f loggingservices/eventlogger/LogServ/src/LOGADD.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/loggingservices/eventlogger/LogServ/src/LOGADD.CPP Fri Jan 22 11:06:30 2010 +0200 @@ -0,0 +1,510 @@ +// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#include +#include +#include +#include "LOGADD.H" +#include "logservpanic.h" +#include "LOGDUP.H" +#include "LOGQUERY.H" +#include "LogServRecentList.h" +#include "LogServDatabaseTransactionInterface.h" +#include "LogServResourceInterpreter.h" +#include "LogServCacheConfig.h" +#include "LogServDatabaseChangeInterface.h" +#include +#include +#include "LogServCacheStrings.h" +#include "LogServCacheTypes.h" +#include "LOGREPDEFS.H" + +const TInt KMinimumNumberOfDigitsToMatch = 3; + +//////////////////////////////////////////////////////////////////////////////////////////// +// Local functions + +#ifdef SYSLIBS_TEST + +#pragma BullseyeCoverage off + +static void LogStore32IntL(RFs& aFs, const TDesC& aFilePath, TInt aVal) + { + RFile file; + User::LeaveIfError(file.Replace(aFs, aFilePath, EFileWrite)); + TPtrC8 p((const TUint8*)&aVal, sizeof(aVal)); + TInt err = file.Write(p); + if(err == KErrNone) + { + err = file.Flush(); + } + file.Close(); + User::LeaveIfError(err); + } + +static void LogStoreContactMatchCountAndNameFormatL(TInt aContactMatchCount, TLogContactNameFormat aContactNameFormat) + { + RFs fs; + CleanupClosePushL(fs); + User::LeaveIfError(fs.Connect()); + + _LIT(KTestDir, "c:\\test\\"); + TInt err = fs.MkDir(KTestDir); + if(err != KErrNone && err != KErrAlreadyExists) + { + User::Leave(err); + } + + _LIT(KLogengTestFileNameCount, "c:\\test\\test_logengconfig_count.ini"); + LogStore32IntL(fs, KLogengTestFileNameCount, aContactMatchCount); + + _LIT(KLogengTestFileNameFormat, "c:\\test\\test_logengconfig_format.ini"); + LogStore32IntL(fs, KLogengTestFileNameFormat, (TInt)aContactNameFormat); + + CleanupStack::PopAndDestroy(&fs); + } + +#pragma BullseyeCoverage on + +#endif //SYSLIBS_TEST + +//This function reads logeng repository file and returns the integer value of the given key. +static TInt LogGetRepositoryValueL(CRepository& aRepository, TInt aKey) + { + TInt val = -1; + User::LeaveIfError(aRepository.Get(aKey, val)); + return val; + } + +//This function reads logeng resource file and returns the integer value of the given resource id. +static TInt LogGetResourceValueL(CLogServResourceInterpreter& aResourceInterpreter, TInt aResourceId) + { + TResourceReader reader; + aResourceInterpreter.CreateResourceReaderLC(reader, aResourceId, CLogServResourceInterpreter::ELogServer); + TInt val = reader.ReadInt16(); + CleanupStack::PopAndDestroy(); + return val; + } + +static void LogGetContactmatchCountAndNameFormatL(CLogServResourceInterpreter& aResourceInterpreter, TInt& aContactMatchCount, TLogContactNameFormat& aContactNameFormat) + { + CRepository* repository = NULL; + TRAPD(err, repository = CRepository::NewL(KUidLogengRepository)); + if(err == KErrCorrupt) + { + __ASSERT_DEBUG(!repository, User::Invariant()); + User::Leave(err); + } + else if(err == KErrNone) + { + CleanupStack::PushL(repository); + aContactMatchCount = LogGetRepositoryValueL(*repository, KContactMatchCountRepKey); + aContactNameFormat = static_cast (LogGetRepositoryValueL(*repository, KContactNameFormatRepKey)); + CleanupStack::PopAndDestroy(repository); + } + else + { + __ASSERT_DEBUG(!repository, User::Invariant()); + aContactMatchCount = LogGetResourceValueL(aResourceInterpreter, R_LOG_CONTACT_MATCH_COUNT); + aContactNameFormat = static_cast (LogGetResourceValueL(aResourceInterpreter, R_LOG_CONTACT_NAME_FORMAT)); + } + #ifdef SYSLIBS_TEST + LogStoreContactMatchCountAndNameFormatL(aContactMatchCount, aContactNameFormat); + #endif + } + +//////////////////////////////////////////////////////////////////////////////////////////// +// CLogAddEvent class + +CLogAddEvent::CLogAddEvent(MLogServDatabaseTransactionInterface& aDatabase, TInt aPriority) : + CLogActive(aPriority), + iDatabase(aDatabase) + { + } + +CLogAddEvent::~CLogAddEvent() + { + Cancel(); + + CloseContactsPlugin(); + + delete iDuplicate; + delete iDuplicateFilter; + } + +CLogAddEvent* CLogAddEvent::NewL(MLogServDatabaseTransactionInterface& aDatabase, TInt aPriority) + { + CLogAddEvent* self = new(ELeave) CLogAddEvent(aDatabase, aPriority); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +void CLogAddEvent::ConstructL() + { + iDuplicate = CLogDuplicate::NewL(iDatabase, Priority()); + iDuplicateFilter = CLogFilter::NewL(); + ::LogGetContactmatchCountAndNameFormatL(iDatabase.DTIResourceInterface(), iContactMatchCount, iContactNameFormat); + } + +//This method will open contacts database (if not opened yet), only if the value of +//r_log_contact_match_count resource in logserv.rsg resource file is not 0. +//Se how iContactMatchCount data member is initialised. +TBool CLogAddEvent::PerformContactMatchL() + { + if (iContactMatchCount <= 0 || iEvent->Contact() != KLogNullContactId) + return EFalse; + + if (iContactPlugin) + return ETrue; + + // Attempt to load plugin + TRAPD( err, iContactPlugin=CLogCntModel::NewL()); + + // If plugin doesn't exist this is equivalent to matching being disabled so we don't leave + // for KErrNotFound + if(err==KEComErrNoInterfaceIdentified) + { + // Disable contacts matching so that we don't keep attempting to match + iContactMatchCount = 0; + // Plugin doesn't exist + return EFalse; + } + + User::LeaveIfError(err); + + // Open the DB + OpenContactsL(); + + return ETrue; + } + +void CLogAddEvent::StartL(CLogEvent& aEvent, const CLogServRecentList* aRecentList, TRequestStatus& aStatus, const RMessage2& aMessage) + { + __ASSERT_ALWAYS(!IsActive(), Panic(ELogAlreadyActive1)); + + LOGTEXT("CLogAddEvent::StartL()"); + + // Store event details which were obtained from the client side + iEvent = &aEvent; + iState = ELogAddEvent; + + if (!iDatabase.DTIIsAllowed(EWriteOp, aMessage, iEvent->EventType())) + { + User::Leave(KErrPermissionDenied); + } + + if (PerformContactMatchL()) + iState = ELogSetContactAndRemoteParty; // Go look for a matching contact + + iRecentList = aRecentList; + iEventAdded = EFalse; + + // Setup the event's time (UTC) + TTime time; + time.UniversalTime(); + iEvent->SetTime(time); + + // Save the observer's request status and set it to KRequestPending + Queue(aStatus); + + // Start this objects RunL chain + TRequestStatus* status = &iStatus; + User::RequestComplete(status, KErrNone); + SetActive(); + } + +void CLogAddEvent::SetEventContact() + { + // Start by converting the phone number text into a number + // check we've got a long enough number to be worth checking + if(iEvent->Number().Length() >= KMinimumNumberOfDigitsToMatch) + { + // now search for a contact by looking up the phone number + TLogContactItemId contactId = KLogNullContactId; + TRAPD(err, contactId = iContactPlugin->MatchPhoneNumberL(iEvent->Number(), iContactMatchCount)); + + if(err == KErrNone) + { + // we have at least one match + if(contactId != KLogNullContactId) + { + // we have a match so set the contact id + iEvent->SetContact(contactId); + } + } + } + iEvent->SetFlags(KLogEventContactSearched); + } + +void CLogAddEvent::SetRemoteParty() + { + // Get the contact id + TLogContactItemId contactId = iEvent->Contact(); + if((contactId != KLogNullContactId) && (iEvent->RemoteParty().Length() == 0)) + { + // Look it up and get the remote party info + // Setup buffer to contain concatenated result + TBuf<128> buf; + // Go get the info + TRAPD(err, iContactPlugin->ReadContactNameL(contactId, buf, iContactNameFormat)); + + if(err == KErrNotFound) + { + // Couldn't find the contact with that id so set it to NULL + iEvent->SetContact(KLogNullContactId); + } + else + { + // Found it so fill in remote party + iEvent->SetRemoteParty(buf); + } + } + } + +void CLogAddEvent::GetConfigL() + { + iConfig = iDatabase.DTICacheConfig().Config(); + if(iConfig.iMaxLogSize == 0) + { + LOGTEXT("CLogAddEvent::DoRunL() - logging disabled"); + User::Leave(KErrNotSupported); + } + } + +TLogTypeId CLogAddEvent::SetDescriptionL() + { + const TLogServCacheTypeEntry& entry = iDatabase.DTICacheTypes().FindByUid(iEvent->EventType()); + if(entry.iEventTypeId == KLogNullTypeId) + { + LOGTEXT("CLogAddEvent::DoRunL() - type not found"); + User::Leave(KErrNotFound); + } + if(!entry.iEventType->LoggingEnabled()) + { + LOGTEXT("CLogAddEvent::DoRunL() - type not enabled"); + User::Leave(KErrNotSupported); + } + iEvent->SetDescription(entry.iEventType->Description()); + return entry.iEventTypeId; + } + +TBool CLogAddEvent::DetectDuplicateEventsL() + { + TBool rc = EFalse; + if(iRecentList) + { + iRecentList->GetFilter(*iEvent, *iDuplicateFilter); + rc = iDuplicate->StartL(iEvent->Id(), iRecentList->Id(), *iDuplicateFilter, iStatus); + } + return rc; + } + +void CLogAddEvent::DoRunL() + { + LOGTEXT3("CLogAddEvent::DoRunL(%d), state = %d", iStatus.Int(), iState); + + switch (iState) + { + case ELogSetContactAndRemoteParty: + { + SetEventContact(); + SetRemoteParty(); + TRequestStatus* status = &iStatus; + User::RequestComplete(status, KErrNone); + iState = ELogAddEvent; + SetActive(); + break; + } + case ELogAddEvent: + { + GetConfigL(); + TLogTypeId typeId = SetDescriptionL(); + RLogEventDbTable tbl; + tbl.OpenLC(iDatabase.DTIDatabase()); + ::LogPurgeMainL(iDatabase, tbl, iConfig.iMaxLogSize, 1); + DoAddEventL(tbl, typeId, iDatabase.DTICacheStrings().GetIdL(iEvent->Direction()), iDatabase.DTICacheStrings().GetIdL(iEvent->Status())); + CleanupStack::PopAndDestroy();//tbl + iEventAdded = ETrue; + if(DetectDuplicateEventsL()) + { + iState = ELogPurgeRecent; + SetActive(); + break; + } + iState = ELogPurgeRecent; + TRequestStatus* status = &iStatus; + User::RequestComplete(status, KErrNone); + SetActive(); + break; + } + case ELogPurgeRecent: + { + // Delete old recent events + if (iRecentList) + { + RArray logIds; + ::LogGetRecentEventsLC(iDatabase, iRecentList->Id(), iConfig.iMaxRecentLogSize, logIds); + ::LogPurgeRecentEventsL(iDatabase, logIds); + CleanupStack::PopAndDestroy(&logIds); + } + } + break; + default: + __ASSERT_DEBUG(ETrue, Panic(ELogBadState1)); + break; + } + + LOGTEXT("CLogAddEvent::DoRunL() - end"); + } + +void CLogAddEvent::DoCancel() + { + iDuplicate->Cancel(); + CLogActive::DoCancel(); + } + +void CLogAddEvent::DoAddEventL(RLogEventDbTable& aTbl, TLogTypeId aTypeId, TLogStringId aDirectionId, TLogStringId aStatusId) + { + LOGTEXT("CLogAddEvent::DoAddEventL()"); + + // Insert a new record + aTbl.InsertL(); + + aTbl.SetColL(RLogEventDbTable::iTypeColNo, (TUint32)aTypeId); + + if (iEvent->RemoteParty().Length() > 0) + aTbl.SetColL(RLogEventDbTable::iRemotePartyColNo, iEvent->RemoteParty()); + + if (iEvent->Direction().Length() > 0) + aTbl.SetColL(RLogEventDbTable::iDirectionColNo, (TUint32)aDirectionId); + + aTbl.SetColL(RLogEventDbTable::iTimeColNo, iEvent->Time()); + aTbl.SetColL(RLogEventDbTable::iDurationTypeColNo, (TInt32)iEvent->DurationType()); + + if (iEvent->DurationType() != KLogNullDurationType) + aTbl.SetColL(RLogEventDbTable::iDurationColNo, iEvent->Duration()); + + if (iEvent->Status().Length() > 0) + aTbl.SetColL(RLogEventDbTable::iStatusColNo, (TUint32)aStatusId); + + if (iEvent->Subject().Length() > 0) + aTbl.SetColL(RLogEventDbTable::iSubjectColNo, iEvent->Subject()); + + if (iEvent->Number().Length() > 0) + aTbl.SetColL(RLogEventDbTable::iNumberColNo, iEvent->Number()); + + if (iEvent->Contact() != KLogNullContactId) + aTbl.SetColL(RLogEventDbTable::iContactColNo, iEvent->Contact()); + + if (iEvent->Link() != KLogNullLink) + aTbl.SetColL(RLogEventDbTable::iLinkColNo, iEvent->Link()); + + if (iEvent->Data().Length() > 0) + aTbl.SetColL(RLogEventDbTable::iDataColNo, iEvent->Data()); + + // Set the flags + TInt bit = KLogFlagsCount; + while(bit--) + { + aTbl.SetColL(RLogEventDbTable::iFlagColNo[bit], (TUint32)((iEvent->Flags() & 0x1 << bit) ? 1 : 0)); + } + + if (iRecentList) + { + __ASSERT_DEBUG(iRecentList->Id() != KLogNullRecentList, Panic(ELogNullRecentList)); + aTbl.SetColL(RLogEventDbTable::iRecentColNo, (TInt32)iRecentList->Id()); + } + +#ifdef SYMBIAN_ENABLE_EVENTLOGGER_DUALSIM + if(iEvent->SimId() != KLogNullSimId) + { + aTbl.SetColL(RLogEventDbTable::iSimIdColNo, iEvent->SimId()); + } + else + { + aTbl.SetColNullL(RLogEventDbTable::iSimIdColNo); + } +#endif + + // Assign event id and end the rowset operation + const TLogId newId = aTbl.ColInt32(RLogEventDbTable::iIdColNo); + iEvent->SetId(newId); + aTbl.PutL(); + + // Tell change interface about the addition + iDatabase.DTIChangeInterface().DCISubmitChangedEventContextL(ELogChangeTypeEventAdded, newId); + + LOGTEXT("CLogAddEvent::DoAddEventL() - end"); + } + +void CLogAddEvent::DoComplete(TInt& aStatus) + { + LOGTEXT2("CLogAddEvent::DoComplete(%d)", aStatus); + + if (iDatabase.DTIInTransaction()) + { + LOGTEXT2("CLogAddEvent::DoComplete() - in transaction: %d", aStatus); + if (aStatus == KErrNone) + aStatus = iDatabase.DTICommitAndEnd(); + + LOGTEXT2("CLogAddEvent::DoComplete() - checking for need to rollback: %d", aStatus); + if (aStatus < KErrNone) + iDatabase.DTIRollBack(); + } + else + { + if (iEventAdded) + aStatus = KErrNone; + } + + LOGTEXT2("CLogAddEvent::DoComplete() - final status value is: %d", aStatus); + } + +//Opens the default contacts database. +void CLogAddEvent::OpenContactsL() + { + //Sometimes, after a sequence of OpenContactsL()/CloseContacts() calls the Contacts server crashes + //and OpenContactsL() leaves with error -15. In order to avoid that the following delay has been added. + //(something related to Contacts server state machine) + User::After(100); + // Attempt to open DB + TRAPD(err,iContactPlugin->OpenContactsL()); + if(KErrNone!=err) + { + // If DB doesn't open delete plugin + delete iContactPlugin; + iContactPlugin = NULL; + User::Leave(err); + } + } + +//Closes the default contacts database and deletes the plugin. +void CLogAddEvent::CloseContactsPlugin() + { + if(iContactPlugin) + { + iContactPlugin->CloseContacts(); + delete iContactPlugin; + iContactPlugin = NULL; + //REComSession::FinalClose() call moved here from logcntmodel.cpp. + //The in-source documentation of REComSession::FinalClose() notes that: + //"It must never be called from within a plug-in implementations class + //destructor, especially following a DestroyImplementation() ". + //That was the case before the function call was moved here. + REComSession::FinalClose(); + } + }