1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/persistentdata/loggingservices/eventlogger/LogServ/src/LOGADD.CPP Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,503 @@
1.4 +// Copyright (c) 2004-2010 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +#include <s32file.h>
1.20 +#include <logcntmodel.h>
1.21 +#include <logengevents.h>
1.22 +#include "LOGADD.H"
1.23 +#include "logservpanic.h"
1.24 +#include "LOGDUP.H"
1.25 +#include "LOGQUERY.H"
1.26 +#include "LogServRecentList.h"
1.27 +#include "LogServDatabaseTransactionInterface.h"
1.28 +#include "LogServResourceInterpreter.h"
1.29 +#include "LogServCacheConfig.h"
1.30 +#include "LogServDatabaseChangeInterface.h"
1.31 +#include <centralrepository.h>
1.32 +#include "LogServCacheStrings.h"
1.33 +#include "LogServCacheTypes.h"
1.34 +#include "LOGREPDEFS.H"
1.35 +
1.36 +const TInt KMinimumNumberOfDigitsToMatch = 3;
1.37 +
1.38 +////////////////////////////////////////////////////////////////////////////////////////////
1.39 +// Local functions
1.40 +
1.41 +#ifdef SYSLIBS_TEST
1.42 +
1.43 +#pragma BullseyeCoverage off
1.44 +
1.45 +static void LogStore32IntL(RFs& aFs, const TDesC& aFilePath, TInt aVal)
1.46 + {
1.47 + RFile file;
1.48 + User::LeaveIfError(file.Replace(aFs, aFilePath, EFileWrite));
1.49 + TPtrC8 p((const TUint8*)&aVal, sizeof(aVal));
1.50 + TInt err = file.Write(p);
1.51 + if(err == KErrNone)
1.52 + {
1.53 + err = file.Flush();
1.54 + }
1.55 + file.Close();
1.56 + User::LeaveIfError(err);
1.57 + }
1.58 +
1.59 +static void LogStoreContactMatchCountAndNameFormatL(TInt aContactMatchCount, TLogContactNameFormat aContactNameFormat)
1.60 + {
1.61 + RFs fs;
1.62 + CleanupClosePushL(fs);
1.63 + User::LeaveIfError(fs.Connect());
1.64 +
1.65 + _LIT(KTestDir, "c:\\test\\");
1.66 + TInt err = fs.MkDir(KTestDir);
1.67 + if(err != KErrNone && err != KErrAlreadyExists)
1.68 + {
1.69 + User::Leave(err);
1.70 + }
1.71 +
1.72 + _LIT(KLogengTestFileNameCount, "c:\\test\\test_logengconfig_count.ini");
1.73 + LogStore32IntL(fs, KLogengTestFileNameCount, aContactMatchCount);
1.74 +
1.75 + _LIT(KLogengTestFileNameFormat, "c:\\test\\test_logengconfig_format.ini");
1.76 + LogStore32IntL(fs, KLogengTestFileNameFormat, (TInt)aContactNameFormat);
1.77 +
1.78 + CleanupStack::PopAndDestroy(&fs);
1.79 + }
1.80 +
1.81 +#pragma BullseyeCoverage on
1.82 +
1.83 +#endif //SYSLIBS_TEST
1.84 +
1.85 +//This function reads logeng repository file and returns the integer value of the given key.
1.86 +static TInt LogGetRepositoryValueL(CRepository& aRepository, TInt aKey)
1.87 + {
1.88 + TInt val = -1;
1.89 + User::LeaveIfError(aRepository.Get(aKey, val));
1.90 + return val;
1.91 + }
1.92 +
1.93 +static void LogGetContactmatchCountAndNameFormatL(TInt& aContactMatchCount, TLogContactNameFormat& aContactNameFormat)
1.94 + {
1.95 + CRepository* repository = NULL;
1.96 + TRAPD(err, repository = CRepository::NewL(KUidLogengRepository));
1.97 + if(err == KErrNone)
1.98 + {
1.99 + CleanupStack::PushL(repository);
1.100 + aContactMatchCount = LogGetRepositoryValueL(*repository, KContactMatchCountRepKey);
1.101 + aContactNameFormat = static_cast <TLogContactNameFormat> (LogGetRepositoryValueL(*repository, KContactNameFormatRepKey));
1.102 + CleanupStack::PopAndDestroy(repository);
1.103 + }
1.104 + else if(err == KErrCorrupt)
1.105 + {
1.106 + __ASSERT_DEBUG(!repository, User::Invariant());
1.107 + User::Leave(err);
1.108 + }
1.109 + else
1.110 + {
1.111 + __ASSERT_DEBUG(!repository, User::Invariant());
1.112 + aContactMatchCount = KLogContactMatchCount;
1.113 + aContactNameFormat = KLogContactNameFormat;
1.114 + }
1.115 + #ifdef SYSLIBS_TEST
1.116 + LogStoreContactMatchCountAndNameFormatL(aContactMatchCount, aContactNameFormat);
1.117 + #endif
1.118 + }
1.119 +
1.120 +////////////////////////////////////////////////////////////////////////////////////////////
1.121 +// CLogAddEvent class
1.122 +
1.123 +CLogAddEvent::CLogAddEvent(MLogServDatabaseTransactionInterface& aDatabase, TInt aPriority) :
1.124 + CLogActive(aPriority),
1.125 + iDatabase(aDatabase)
1.126 + {
1.127 + }
1.128 +
1.129 +CLogAddEvent::~CLogAddEvent()
1.130 + {
1.131 + Cancel();
1.132 +
1.133 + CloseContactsPlugin();
1.134 +
1.135 + delete iDuplicate;
1.136 + delete iDuplicateFilter;
1.137 + }
1.138 +
1.139 +CLogAddEvent* CLogAddEvent::NewL(MLogServDatabaseTransactionInterface& aDatabase, TInt aPriority)
1.140 + {
1.141 + CLogAddEvent* self = new(ELeave) CLogAddEvent(aDatabase, aPriority);
1.142 + CleanupStack::PushL(self);
1.143 + self->ConstructL();
1.144 + CleanupStack::Pop(self);
1.145 + return self;
1.146 + }
1.147 +
1.148 +void CLogAddEvent::ConstructL()
1.149 + {
1.150 + iDuplicate = CLogDuplicate::NewL(iDatabase, Priority());
1.151 + iDuplicateFilter = CLogFilter::NewL();
1.152 + ::LogGetContactmatchCountAndNameFormatL(iContactMatchCount, iContactNameFormat);
1.153 + }
1.154 +
1.155 +//This method will open contacts database (if not opened yet), only if the value of
1.156 +//iContactMatchCount is not 0.
1.157 +//Se how iContactMatchCount data member is initialised.
1.158 +TBool CLogAddEvent::PerformContactMatchL()
1.159 + {
1.160 + if (iContactMatchCount <= 0 || iEvent->Contact() != KLogNullContactId)
1.161 + return EFalse;
1.162 +
1.163 + if (iContactPlugin)
1.164 + return ETrue;
1.165 +
1.166 + // Attempt to load plugin
1.167 + TRAPD( err, iContactPlugin=CLogCntModel::NewL());
1.168 +
1.169 + // If plugin doesn't exist this is equivalent to matching being disabled so we don't leave
1.170 + // for KErrNotFound
1.171 + if(err==KEComErrNoInterfaceIdentified)
1.172 + {
1.173 + // Disable contacts matching so that we don't keep attempting to match
1.174 + iContactMatchCount = 0;
1.175 + // Plugin doesn't exist
1.176 + return EFalse;
1.177 + }
1.178 +
1.179 + User::LeaveIfError(err);
1.180 +
1.181 + // Open the DB
1.182 + OpenContactsL();
1.183 +
1.184 + return ETrue;
1.185 + }
1.186 +
1.187 +void CLogAddEvent::StartL(CLogEvent& aEvent, const CLogServRecentList* aRecentList, TRequestStatus& aStatus, const RMessage2& aMessage)
1.188 + {
1.189 + __ASSERT_ALWAYS(!IsActive(), Panic(ELogAlreadyActive1));
1.190 +
1.191 + LOGTEXT("CLogAddEvent::StartL()");
1.192 +
1.193 + // Store event details which were obtained from the client side
1.194 + iEvent = &aEvent;
1.195 + iState = ELogAddEvent;
1.196 +
1.197 + if (!iDatabase.DTIIsAllowed(EWriteOp, aMessage, iEvent->EventType()))
1.198 + {
1.199 + User::Leave(KErrPermissionDenied);
1.200 + }
1.201 +
1.202 + if (PerformContactMatchL())
1.203 + iState = ELogSetContactAndRemoteParty; // Go look for a matching contact
1.204 +
1.205 + iRecentList = aRecentList;
1.206 + iEventAdded = EFalse;
1.207 +
1.208 + // Setup the event's time (UTC)
1.209 + TTime time;
1.210 + time.UniversalTime();
1.211 + iEvent->SetTime(time);
1.212 +
1.213 + // Save the observer's request status and set it to KRequestPending
1.214 + Queue(aStatus);
1.215 +
1.216 + // Start this objects RunL chain
1.217 + TRequestStatus* status = &iStatus;
1.218 + User::RequestComplete(status, KErrNone);
1.219 + SetActive();
1.220 + }
1.221 +
1.222 +void CLogAddEvent::SetEventContact()
1.223 + {
1.224 + // Start by converting the phone number text into a number
1.225 + // check we've got a long enough number to be worth checking
1.226 + if(iEvent->Number().Length() >= KMinimumNumberOfDigitsToMatch)
1.227 + {
1.228 + // now search for a contact by looking up the phone number
1.229 + TLogContactItemId contactId = KLogNullContactId;
1.230 + TRAPD(err, contactId = iContactPlugin->MatchPhoneNumberL(iEvent->Number(), iContactMatchCount));
1.231 +
1.232 + if(err == KErrNone)
1.233 + {
1.234 + // we have at least one match
1.235 + if(contactId != KLogNullContactId)
1.236 + {
1.237 + // we have a match so set the contact id
1.238 + iEvent->SetContact(contactId);
1.239 + }
1.240 + }
1.241 + }
1.242 + iEvent->SetFlags(KLogEventContactSearched);
1.243 + }
1.244 +
1.245 +void CLogAddEvent::SetRemoteParty()
1.246 + {
1.247 + // Get the contact id
1.248 + TLogContactItemId contactId = iEvent->Contact();
1.249 + if((contactId != KLogNullContactId) && (iEvent->RemoteParty().Length() == 0))
1.250 + {
1.251 + // Look it up and get the remote party info
1.252 + // Setup buffer to contain concatenated result
1.253 + TBuf<128> buf;
1.254 + // Go get the info
1.255 + TRAPD(err, iContactPlugin->ReadContactNameL(contactId, buf, iContactNameFormat));
1.256 +
1.257 + if(err == KErrNotFound)
1.258 + {
1.259 + // Couldn't find the contact with that id so set it to NULL
1.260 + iEvent->SetContact(KLogNullContactId);
1.261 + }
1.262 + else
1.263 + {
1.264 + // Found it so fill in remote party
1.265 + iEvent->SetRemoteParty(buf);
1.266 + }
1.267 + }
1.268 + }
1.269 +
1.270 +void CLogAddEvent::GetConfigL()
1.271 + {
1.272 + iConfig = iDatabase.DTICacheConfig().Config();
1.273 + if(iConfig.iMaxLogSize == 0)
1.274 + {
1.275 + LOGTEXT("CLogAddEvent::DoRunL() - logging disabled");
1.276 + User::Leave(KErrNotSupported);
1.277 + }
1.278 + }
1.279 +
1.280 +TLogTypeId CLogAddEvent::SetDescriptionL()
1.281 + {
1.282 + const TLogServCacheTypeEntry& entry = iDatabase.DTICacheTypes().FindByUid(iEvent->EventType());
1.283 + if(entry.iEventTypeId == KLogNullTypeId)
1.284 + {
1.285 + LOGTEXT("CLogAddEvent::DoRunL() - type not found");
1.286 + User::Leave(KErrNotFound);
1.287 + }
1.288 + if(!entry.iEventType->LoggingEnabled())
1.289 + {
1.290 + LOGTEXT("CLogAddEvent::DoRunL() - type not enabled");
1.291 + User::Leave(KErrNotSupported);
1.292 + }
1.293 + iEvent->SetDescription(entry.iEventType->Description());
1.294 + return entry.iEventTypeId;
1.295 + }
1.296 +
1.297 +TBool CLogAddEvent::DetectDuplicateEventsL()
1.298 + {
1.299 + TBool rc = EFalse;
1.300 + if(iRecentList)
1.301 + {
1.302 + iRecentList->GetFilter(*iEvent, *iDuplicateFilter);
1.303 + rc = iDuplicate->StartL(iEvent->Id(), iRecentList->Id(), *iDuplicateFilter, iStatus);
1.304 + }
1.305 + return rc;
1.306 + }
1.307 +
1.308 +void CLogAddEvent::DoRunL()
1.309 + {
1.310 + LOGTEXT3("CLogAddEvent::DoRunL(%d), state = %d", iStatus.Int(), iState);
1.311 +
1.312 + switch (iState)
1.313 + {
1.314 + case ELogSetContactAndRemoteParty:
1.315 + {
1.316 + SetEventContact();
1.317 + SetRemoteParty();
1.318 + TRequestStatus* status = &iStatus;
1.319 + User::RequestComplete(status, KErrNone);
1.320 + iState = ELogAddEvent;
1.321 + SetActive();
1.322 + break;
1.323 + }
1.324 + case ELogAddEvent:
1.325 + {
1.326 + GetConfigL();
1.327 + TLogTypeId typeId = SetDescriptionL();
1.328 + RLogEventDbTable tbl;
1.329 + tbl.OpenLC(iDatabase.DTIDatabase());
1.330 + ::LogPurgeMainL(iDatabase, tbl, iConfig.iMaxLogSize, 1);
1.331 + DoAddEventL(tbl, typeId, iDatabase.DTICacheStrings().GetIdL(iEvent->Direction()), iDatabase.DTICacheStrings().GetIdL(iEvent->Status()));
1.332 + CleanupStack::PopAndDestroy();//tbl
1.333 + iEventAdded = ETrue;
1.334 + if(DetectDuplicateEventsL())
1.335 + {
1.336 + iState = ELogPurgeRecent;
1.337 + SetActive();
1.338 + break;
1.339 + }
1.340 + iState = ELogPurgeRecent;
1.341 + TRequestStatus* status = &iStatus;
1.342 + User::RequestComplete(status, KErrNone);
1.343 + SetActive();
1.344 + break;
1.345 + }
1.346 + case ELogPurgeRecent:
1.347 + {
1.348 + // Delete old recent events
1.349 + if (iRecentList)
1.350 + {
1.351 + RArray<TLogId> logIds;
1.352 + ::LogGetRecentEventsLC(iDatabase, iRecentList->Id(), iConfig.iMaxRecentLogSize, logIds);
1.353 + ::LogPurgeRecentEventsL(iDatabase, logIds);
1.354 + CleanupStack::PopAndDestroy(&logIds);
1.355 + }
1.356 + }
1.357 + break;
1.358 + default:
1.359 + __ASSERT_DEBUG(ETrue, Panic(ELogBadState1));
1.360 + break;
1.361 + }
1.362 +
1.363 + LOGTEXT("CLogAddEvent::DoRunL() - end");
1.364 + }
1.365 +
1.366 +void CLogAddEvent::DoCancel()
1.367 + {
1.368 + iDuplicate->Cancel();
1.369 + CLogActive::DoCancel();
1.370 + }
1.371 +
1.372 +void CLogAddEvent::DoAddEventL(RLogEventDbTable& aTbl, TLogTypeId aTypeId, TLogStringId aDirectionId, TLogStringId aStatusId)
1.373 + {
1.374 + LOGTEXT("CLogAddEvent::DoAddEventL()");
1.375 +
1.376 + // Insert a new record
1.377 + aTbl.InsertL();
1.378 +
1.379 + aTbl.SetColL(RLogEventDbTable::iTypeColNo, (TUint32)aTypeId);
1.380 +
1.381 + if (iEvent->RemoteParty().Length() > 0)
1.382 + aTbl.SetColL(RLogEventDbTable::iRemotePartyColNo, iEvent->RemoteParty());
1.383 +
1.384 + if (iEvent->Direction().Length() > 0)
1.385 + aTbl.SetColL(RLogEventDbTable::iDirectionColNo, (TUint32)aDirectionId);
1.386 +
1.387 + aTbl.SetColL(RLogEventDbTable::iTimeColNo, iEvent->Time());
1.388 + aTbl.SetColL(RLogEventDbTable::iDurationTypeColNo, (TInt32)iEvent->DurationType());
1.389 +
1.390 + if (iEvent->DurationType() != KLogNullDurationType)
1.391 + aTbl.SetColL(RLogEventDbTable::iDurationColNo, iEvent->Duration());
1.392 +
1.393 + if (iEvent->Status().Length() > 0)
1.394 + aTbl.SetColL(RLogEventDbTable::iStatusColNo, (TUint32)aStatusId);
1.395 +
1.396 + if (iEvent->Subject().Length() > 0)
1.397 + aTbl.SetColL(RLogEventDbTable::iSubjectColNo, iEvent->Subject());
1.398 +
1.399 + if (iEvent->Number().Length() > 0)
1.400 + aTbl.SetColL(RLogEventDbTable::iNumberColNo, iEvent->Number());
1.401 +
1.402 + if (iEvent->Contact() != KLogNullContactId)
1.403 + aTbl.SetColL(RLogEventDbTable::iContactColNo, iEvent->Contact());
1.404 +
1.405 + if (iEvent->Link() != KLogNullLink)
1.406 + aTbl.SetColL(RLogEventDbTable::iLinkColNo, iEvent->Link());
1.407 +
1.408 + if (iEvent->Data().Length() > 0)
1.409 + aTbl.SetColL(RLogEventDbTable::iDataColNo, iEvent->Data());
1.410 +
1.411 + // Set the flags
1.412 + TInt bit = KLogFlagsCount;
1.413 + while(bit--)
1.414 + {
1.415 + aTbl.SetColL(RLogEventDbTable::iFlagColNo[bit], (TUint32)((iEvent->Flags() & 0x1 << bit) ? 1 : 0));
1.416 + }
1.417 +
1.418 + if (iRecentList)
1.419 + {
1.420 + __ASSERT_DEBUG(iRecentList->Id() != KLogNullRecentList, Panic(ELogNullRecentList));
1.421 + aTbl.SetColL(RLogEventDbTable::iRecentColNo, (TInt32)iRecentList->Id());
1.422 + }
1.423 +
1.424 +#ifdef SYMBIAN_ENABLE_EVENTLOGGER_DUALSIM
1.425 + if(iEvent->SimId() != KLogNullSimId)
1.426 + {
1.427 + aTbl.SetColL(RLogEventDbTable::iSimIdColNo, iEvent->SimId());
1.428 + }
1.429 + else
1.430 + {
1.431 + aTbl.SetColNullL(RLogEventDbTable::iSimIdColNo);
1.432 + }
1.433 +#endif
1.434 +
1.435 + // Assign event id and end the rowset operation
1.436 + const TLogId newId = aTbl.ColInt32(RLogEventDbTable::iIdColNo);
1.437 + iEvent->SetId(newId);
1.438 + aTbl.PutL();
1.439 +
1.440 + // Tell change interface about the addition
1.441 + iDatabase.DTIChangeInterface().DCISubmitChangedEventContextL(ELogChangeTypeEventAdded, newId);
1.442 +
1.443 + LOGTEXT("CLogAddEvent::DoAddEventL() - end");
1.444 + }
1.445 +
1.446 +void CLogAddEvent::DoComplete(TInt& aStatus)
1.447 + {
1.448 + LOGTEXT2("CLogAddEvent::DoComplete(%d)", aStatus);
1.449 +
1.450 + if (iDatabase.DTIInTransaction())
1.451 + {
1.452 + LOGTEXT2("CLogAddEvent::DoComplete() - in transaction: %d", aStatus);
1.453 + if (aStatus == KErrNone)
1.454 + aStatus = iDatabase.DTICommitAndEnd();
1.455 +
1.456 + LOGTEXT2("CLogAddEvent::DoComplete() - checking for need to rollback: %d", aStatus);
1.457 + if (aStatus < KErrNone)
1.458 + iDatabase.DTIRollBack();
1.459 + }
1.460 + else
1.461 + {
1.462 + if (iEventAdded)
1.463 + aStatus = KErrNone;
1.464 + }
1.465 +
1.466 + LOGTEXT2("CLogAddEvent::DoComplete() - final status value is: %d", aStatus);
1.467 + }
1.468 +
1.469 +//Opens the default contacts database.
1.470 +void CLogAddEvent::OpenContactsL()
1.471 + {
1.472 + //Sometimes, after a sequence of OpenContactsL()/CloseContacts() calls the Contacts server crashes
1.473 + //and OpenContactsL() leaves with error -15. In order to avoid that the following delay has been added.
1.474 + //(something related to Contacts server state machine)
1.475 + User::After(1000);
1.476 + // Attempt to open DB
1.477 + TRAPD(err,iContactPlugin->OpenContactsL());
1.478 + if(KErrNone!=err)
1.479 + {
1.480 + if(err == KErrServerTerminated)
1.481 + {
1.482 + RDebug::Print(_L("+++LogEng, LogAdd.cpp, Contacts server crashed!\r\n"));
1.483 + }
1.484 + // If DB doesn't open delete plugin
1.485 + delete iContactPlugin;
1.486 + iContactPlugin = NULL;
1.487 + User::Leave(err);
1.488 + }
1.489 + }
1.490 +
1.491 +//Closes the default contacts database and deletes the plugin.
1.492 +void CLogAddEvent::CloseContactsPlugin()
1.493 + {
1.494 + if(iContactPlugin)
1.495 + {
1.496 + iContactPlugin->CloseContacts();
1.497 + delete iContactPlugin;
1.498 + iContactPlugin = NULL;
1.499 + //REComSession::FinalClose() call moved here from logcntmodel.cpp.
1.500 + //The in-source documentation of REComSession::FinalClose() notes that:
1.501 + //"It must never be called from within a plug-in implementations class
1.502 + //destructor, especially following a DestroyImplementation() ".
1.503 + //That was the case before the function call was moved here.
1.504 + REComSession::FinalClose();
1.505 + }
1.506 + }