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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
17 #include <logcntmodel.h>
18 #include <logengevents.h>
20 #include "logservpanic.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"
33 const TInt KMinimumNumberOfDigitsToMatch = 3;
35 ////////////////////////////////////////////////////////////////////////////////////////////
40 #pragma BullseyeCoverage off
42 static void LogStore32IntL(RFs& aFs, const TDesC& aFilePath, TInt aVal)
45 User::LeaveIfError(file.Replace(aFs, aFilePath, EFileWrite));
46 TPtrC8 p((const TUint8*)&aVal, sizeof(aVal));
47 TInt err = file.Write(p);
53 User::LeaveIfError(err);
56 static void LogStoreContactMatchCountAndNameFormatL(TInt aContactMatchCount, TLogContactNameFormat aContactNameFormat)
59 CleanupClosePushL(fs);
60 User::LeaveIfError(fs.Connect());
62 _LIT(KTestDir, "c:\\test\\");
63 TInt err = fs.MkDir(KTestDir);
64 if(err != KErrNone && err != KErrAlreadyExists)
69 _LIT(KLogengTestFileNameCount, "c:\\test\\test_logengconfig_count.ini");
70 LogStore32IntL(fs, KLogengTestFileNameCount, aContactMatchCount);
72 _LIT(KLogengTestFileNameFormat, "c:\\test\\test_logengconfig_format.ini");
73 LogStore32IntL(fs, KLogengTestFileNameFormat, (TInt)aContactNameFormat);
75 CleanupStack::PopAndDestroy(&fs);
78 #pragma BullseyeCoverage on
82 //This function reads logeng repository file and returns the integer value of the given key.
83 static TInt LogGetRepositoryValueL(CRepository& aRepository, TInt aKey)
86 User::LeaveIfError(aRepository.Get(aKey, val));
90 static void LogGetContactmatchCountAndNameFormatL(TInt& aContactMatchCount, TLogContactNameFormat& aContactNameFormat)
92 CRepository* repository = NULL;
93 TRAPD(err, repository = CRepository::NewL(KUidLogengRepository));
96 CleanupStack::PushL(repository);
97 aContactMatchCount = LogGetRepositoryValueL(*repository, KContactMatchCountRepKey);
98 aContactNameFormat = static_cast <TLogContactNameFormat> (LogGetRepositoryValueL(*repository, KContactNameFormatRepKey));
99 CleanupStack::PopAndDestroy(repository);
101 else if(err == KErrCorrupt)
103 __ASSERT_DEBUG(!repository, User::Invariant());
108 __ASSERT_DEBUG(!repository, User::Invariant());
109 aContactMatchCount = KLogContactMatchCount;
110 aContactNameFormat = KLogContactNameFormat;
113 LogStoreContactMatchCountAndNameFormatL(aContactMatchCount, aContactNameFormat);
117 ////////////////////////////////////////////////////////////////////////////////////////////
118 // CLogAddEvent class
120 CLogAddEvent::CLogAddEvent(MLogServDatabaseTransactionInterface& aDatabase, TInt aPriority) :
121 CLogActive(aPriority),
126 CLogAddEvent::~CLogAddEvent()
130 CloseContactsPlugin();
133 delete iDuplicateFilter;
136 CLogAddEvent* CLogAddEvent::NewL(MLogServDatabaseTransactionInterface& aDatabase, TInt aPriority)
138 CLogAddEvent* self = new(ELeave) CLogAddEvent(aDatabase, aPriority);
139 CleanupStack::PushL(self);
141 CleanupStack::Pop(self);
145 void CLogAddEvent::ConstructL()
147 iDuplicate = CLogDuplicate::NewL(iDatabase, Priority());
148 iDuplicateFilter = CLogFilter::NewL();
149 ::LogGetContactmatchCountAndNameFormatL(iContactMatchCount, iContactNameFormat);
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()
157 if (iContactMatchCount <= 0 || iEvent->Contact() != KLogNullContactId)
163 // Attempt to load plugin
164 TRAPD( err, iContactPlugin=CLogCntModel::NewL());
166 // If plugin doesn't exist this is equivalent to matching being disabled so we don't leave
168 if(err==KEComErrNoInterfaceIdentified)
170 // Disable contacts matching so that we don't keep attempting to match
171 iContactMatchCount = 0;
172 // Plugin doesn't exist
176 User::LeaveIfError(err);
184 void CLogAddEvent::StartL(CLogEvent& aEvent, const CLogServRecentList* aRecentList, TRequestStatus& aStatus, const RMessage2& aMessage)
186 __ASSERT_ALWAYS(!IsActive(), Panic(ELogAlreadyActive1));
188 LOGTEXT("CLogAddEvent::StartL()");
190 // Store event details which were obtained from the client side
192 iState = ELogAddEvent;
194 if (!iDatabase.DTIIsAllowed(EWriteOp, aMessage, iEvent->EventType()))
196 User::Leave(KErrPermissionDenied);
199 if (PerformContactMatchL())
200 iState = ELogSetContactAndRemoteParty; // Go look for a matching contact
202 iRecentList = aRecentList;
203 iEventAdded = EFalse;
205 // Setup the event's time (UTC)
207 time.UniversalTime();
208 iEvent->SetTime(time);
210 // Save the observer's request status and set it to KRequestPending
213 // Start this objects RunL chain
214 TRequestStatus* status = &iStatus;
215 User::RequestComplete(status, KErrNone);
219 void CLogAddEvent::SetEventContact()
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)
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));
231 // we have at least one match
232 if(contactId != KLogNullContactId)
234 // we have a match so set the contact id
235 iEvent->SetContact(contactId);
239 iEvent->SetFlags(KLogEventContactSearched);
242 void CLogAddEvent::SetRemoteParty()
244 // Get the contact id
245 TLogContactItemId contactId = iEvent->Contact();
246 if((contactId != KLogNullContactId) && (iEvent->RemoteParty().Length() == 0))
248 // Look it up and get the remote party info
249 // Setup buffer to contain concatenated result
252 TRAPD(err, iContactPlugin->ReadContactNameL(contactId, buf, iContactNameFormat));
254 if(err == KErrNotFound)
256 // Couldn't find the contact with that id so set it to NULL
257 iEvent->SetContact(KLogNullContactId);
261 // Found it so fill in remote party
262 iEvent->SetRemoteParty(buf);
267 void CLogAddEvent::GetConfigL()
269 iConfig = iDatabase.DTICacheConfig().Config();
270 if(iConfig.iMaxLogSize == 0)
272 LOGTEXT("CLogAddEvent::DoRunL() - logging disabled");
273 User::Leave(KErrNotSupported);
277 TLogTypeId CLogAddEvent::SetDescriptionL()
279 const TLogServCacheTypeEntry& entry = iDatabase.DTICacheTypes().FindByUid(iEvent->EventType());
280 if(entry.iEventTypeId == KLogNullTypeId)
282 LOGTEXT("CLogAddEvent::DoRunL() - type not found");
283 User::Leave(KErrNotFound);
285 if(!entry.iEventType->LoggingEnabled())
287 LOGTEXT("CLogAddEvent::DoRunL() - type not enabled");
288 User::Leave(KErrNotSupported);
290 iEvent->SetDescription(entry.iEventType->Description());
291 return entry.iEventTypeId;
294 TBool CLogAddEvent::DetectDuplicateEventsL()
299 iRecentList->GetFilter(*iEvent, *iDuplicateFilter);
300 rc = iDuplicate->StartL(iEvent->Id(), iRecentList->Id(), *iDuplicateFilter, iStatus);
305 void CLogAddEvent::DoRunL()
307 LOGTEXT3("CLogAddEvent::DoRunL(%d), state = %d", iStatus.Int(), iState);
311 case ELogSetContactAndRemoteParty:
315 TRequestStatus* status = &iStatus;
316 User::RequestComplete(status, KErrNone);
317 iState = ELogAddEvent;
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
331 if(DetectDuplicateEventsL())
333 iState = ELogPurgeRecent;
337 iState = ELogPurgeRecent;
338 TRequestStatus* status = &iStatus;
339 User::RequestComplete(status, KErrNone);
343 case ELogPurgeRecent:
345 // Delete old recent events
348 RArray<TLogId> logIds;
349 ::LogGetRecentEventsLC(iDatabase, iRecentList->Id(), iConfig.iMaxRecentLogSize, logIds);
350 ::LogPurgeRecentEventsL(iDatabase, logIds);
351 CleanupStack::PopAndDestroy(&logIds);
356 __ASSERT_DEBUG(ETrue, Panic(ELogBadState1));
360 LOGTEXT("CLogAddEvent::DoRunL() - end");
363 void CLogAddEvent::DoCancel()
365 iDuplicate->Cancel();
366 CLogActive::DoCancel();
369 void CLogAddEvent::DoAddEventL(RLogEventDbTable& aTbl, TLogTypeId aTypeId, TLogStringId aDirectionId, TLogStringId aStatusId)
371 LOGTEXT("CLogAddEvent::DoAddEventL()");
373 // Insert a new record
376 aTbl.SetColL(RLogEventDbTable::iTypeColNo, (TUint32)aTypeId);
378 if (iEvent->RemoteParty().Length() > 0)
379 aTbl.SetColL(RLogEventDbTable::iRemotePartyColNo, iEvent->RemoteParty());
381 if (iEvent->Direction().Length() > 0)
382 aTbl.SetColL(RLogEventDbTable::iDirectionColNo, (TUint32)aDirectionId);
384 aTbl.SetColL(RLogEventDbTable::iTimeColNo, iEvent->Time());
385 aTbl.SetColL(RLogEventDbTable::iDurationTypeColNo, (TInt32)iEvent->DurationType());
387 if (iEvent->DurationType() != KLogNullDurationType)
388 aTbl.SetColL(RLogEventDbTable::iDurationColNo, iEvent->Duration());
390 if (iEvent->Status().Length() > 0)
391 aTbl.SetColL(RLogEventDbTable::iStatusColNo, (TUint32)aStatusId);
393 if (iEvent->Subject().Length() > 0)
394 aTbl.SetColL(RLogEventDbTable::iSubjectColNo, iEvent->Subject());
396 if (iEvent->Number().Length() > 0)
397 aTbl.SetColL(RLogEventDbTable::iNumberColNo, iEvent->Number());
399 if (iEvent->Contact() != KLogNullContactId)
400 aTbl.SetColL(RLogEventDbTable::iContactColNo, iEvent->Contact());
402 if (iEvent->Link() != KLogNullLink)
403 aTbl.SetColL(RLogEventDbTable::iLinkColNo, iEvent->Link());
405 if (iEvent->Data().Length() > 0)
406 aTbl.SetColL(RLogEventDbTable::iDataColNo, iEvent->Data());
409 TInt bit = KLogFlagsCount;
412 aTbl.SetColL(RLogEventDbTable::iFlagColNo[bit], (TUint32)((iEvent->Flags() & 0x1 << bit) ? 1 : 0));
417 __ASSERT_DEBUG(iRecentList->Id() != KLogNullRecentList, Panic(ELogNullRecentList));
418 aTbl.SetColL(RLogEventDbTable::iRecentColNo, (TInt32)iRecentList->Id());
421 #ifdef SYMBIAN_ENABLE_EVENTLOGGER_DUALSIM
422 if(iEvent->SimId() != KLogNullSimId)
424 aTbl.SetColL(RLogEventDbTable::iSimIdColNo, iEvent->SimId());
428 aTbl.SetColNullL(RLogEventDbTable::iSimIdColNo);
432 // Assign event id and end the rowset operation
433 const TLogId newId = aTbl.ColInt32(RLogEventDbTable::iIdColNo);
434 iEvent->SetId(newId);
437 // Tell change interface about the addition
438 iDatabase.DTIChangeInterface().DCISubmitChangedEventContextL(ELogChangeTypeEventAdded, newId);
440 LOGTEXT("CLogAddEvent::DoAddEventL() - end");
443 void CLogAddEvent::DoComplete(TInt& aStatus)
445 LOGTEXT2("CLogAddEvent::DoComplete(%d)", aStatus);
447 if (iDatabase.DTIInTransaction())
449 LOGTEXT2("CLogAddEvent::DoComplete() - in transaction: %d", aStatus);
450 if (aStatus == KErrNone)
451 aStatus = iDatabase.DTICommitAndEnd();
453 LOGTEXT2("CLogAddEvent::DoComplete() - checking for need to rollback: %d", aStatus);
454 if (aStatus < KErrNone)
455 iDatabase.DTIRollBack();
463 LOGTEXT2("CLogAddEvent::DoComplete() - final status value is: %d", aStatus);
466 //Opens the default contacts database.
467 void CLogAddEvent::OpenContactsL()
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)
473 // Attempt to open DB
474 TRAPD(err,iContactPlugin->OpenContactsL());
477 if(err == KErrServerTerminated)
479 RDebug::Print(_L("+++LogEng, LogAdd.cpp, Contacts server crashed!\r\n"));
481 // If DB doesn't open delete plugin
482 delete iContactPlugin;
483 iContactPlugin = NULL;
488 //Closes the default contacts database and deletes the plugin.
489 void CLogAddEvent::CloseContactsPlugin()
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();