--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines/contactsmodel/tsrc/t_bench.cpp Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,1029 @@
+// Copyright (c) 2000-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 <e32std.h>
+#include <e32test.h>
+#include <e32math.h>
+#include <cntdb.h>
+#include <cntitem.h>
+#include <cntfldst.h>
+#include "t_utils2.h"
+#include "t_bench.h"
+#include "T_UTILS.H"
+
+
+//
+// Configuration.
+//
+
+#define __TxEST
+#define __VxERBOSE
+
+
+//
+// Constants.
+//
+
+_LIT(KTestName,"t_bench");
+
+
+_LIT(KDbFileName,"c:contacts.cdb");
+
+_LIT(KLogFileName,"t_bench.log");
+_LIT(KBackSpace,"\x08");
+_LIT(KVisualCounterFormat,"%S%d");
+_LIT(KTimeProfileFormat,"Time taken (secs)");
+_LIT(KSystemMemoryFormat,"System memory used (Kb)");
+_LIT(KThreadMemoryFormat,"This thread memory used (Kb)");
+_LIT(KFileSizeText,"File size (bytes)");
+_LIT(KAverageTimeText,"Average time taken (secs)");
+_LIT(KResultFormatTInt,"Result #%d.%d %S [%d]");
+_LIT(KResultFormatTReal,"Result #%d.%d %S [%f]");
+_LIT(KThreadNameFormat,"T_BenchCli%2d");
+_LIT(KPhoneMatchFail,"6666666666666666");
+_LIT(KNameMatchFail,"xxxxxxxxxxxxxxxx");
+_LIT(KAsyncFindMatch,"a");
+_LIT(KNewLine,"\n");
+_LIT(KTextDefSeparator,"\t");
+
+#ifdef __VERBOSE
+_LIT(KContactSummaryFormat,"%d\t%S\t%S\t%S");
+_LIT(KAscendingSortOrder,"ascending");
+_LIT(KDescendingSortOrder,"descending");
+_LIT(KProfileResult,"Took %d\tmicrosecs for %d iteration(s)");
+#endif
+
+const TInt KNumSortClients=10;
+const TInt KClientStackSize=KDefaultStackSize;
+const TInt KClientHeapSize=0x20000;
+
+#ifdef __TEST
+const TInt KNumTypicalContacts=10;
+const TInt KNumAtypicalContacts=2;
+const TInt KNumTypicalContactsCompact=0;
+const TInt KNumAtypicalContactsCompact=0;
+#else
+const TInt KNumTypicalContacts=100;
+const TInt KNumAtypicalContacts=50;
+const TInt KNumTypicalContactsCompact=150;
+const TInt KNumAtypicalContactsCompact=50;
+#endif // __TEST
+
+
+//
+// CBenchMarker.
+//
+
+CBenchMarker::CBenchMarker() : iTest(KTestName),iVisualCounter(-1),iNumTypicalContacts(-1),iNumAtypicalContacts(-1),iNumTypicalContactsCompact(-1),iNumAtypicalContactsCompact(-1)
+ {
+ }
+
+CBenchMarker::~CBenchMarker()
+ {
+ delete iGenerator;
+ delete iDb;
+ delete iTextDef;
+ delete iLog;
+ iTest.Close();
+ iFs.Close();
+ }
+
+void CBenchMarker::ConstructL(const TDesC& aCommandLine)
+ {
+ User::LeaveIfError(iFs.Connect());
+ DecodeCommandLineL(aCommandLine);
+ iLog=CLog::NewL(iTest,iLogFileName);
+ iGenerator=CRandomContactGenerator::NewL();
+ }
+
+void CBenchMarker::DecodeCommandLineL(const TDesC& aCommandLine)
+ {
+ _LIT(KArgContactsToAdd,"-a");
+ _LIT(KArgContactsToCompact,"-c");
+ _LIT(KArgDatabaseFileName,"-d");
+ _LIT(KArgNoDataGenerationTests,"-g");
+ _LIT(KArgLogFile,"-l");
+ _LIT(KArgHelp,"-h");
+
+ TLex cl(aCommandLine);
+ while (cl.Remainder().Length()>0)
+ {
+ TPtrC token=cl.NextToken();
+
+ if (token.CompareF(KArgContactsToAdd)==0)
+ {
+ cl.SkipSpace();
+ User::LeaveIfError(cl.Val(iNumTypicalContacts));
+ cl.SkipSpace();
+ User::LeaveIfError(cl.Val(iNumAtypicalContacts));
+ }
+ else if (token.CompareF(KArgContactsToCompact)==0)
+ {
+ cl.SkipSpace();
+ User::LeaveIfError(cl.Val(iNumTypicalContactsCompact));
+ cl.SkipSpace();
+ User::LeaveIfError(cl.Val(iNumAtypicalContactsCompact));
+ }
+ else if (token.CompareF(KArgDatabaseFileName)==0)
+ {
+ iDbFileName=cl.NextToken();
+ }
+ else if (token.CompareF(KArgNoDataGenerationTests)==0)
+ {
+ iNoDataGenerationTests=ETrue;
+ }
+ else if (token.CompareF(KArgLogFile)==0)
+ {
+ iLogFileName=cl.NextToken();
+ }
+ else if (token.CompareF(KArgHelp)==0)
+ {
+ iTest.Printf(_L("Usage t_bench [options]\n\n"));
+ iTest.Printf(_L("-a <num_typical> <num_atypical> (default: %d %d)\n"),KNumTypicalContacts,KNumAtypicalContacts);
+ iTest.Printf(_L("-c <num_typical_comp> <num_atypical_comp> (default: %d %d)\n"),KNumTypicalContactsCompact,KNumAtypicalContactsCompact);
+ iTest.Printf(_L("-d <db_name> (default: %S)\n"),&KDbFileName);
+ iTest.Printf(_L("-l <log_name> (default: %S)\n"),&KLogFileName);
+ iTest.Printf(_L("-g skip data generation tests\n"));
+ iTest.Printf(_L("\n<hit any key>"));
+ iTest.Getch();
+ User::Leave(KErrNone);
+ }
+ }
+
+ if (iDbFileName.Length()==0)
+ {
+ iDbFileName=KDbFileName;
+ }
+
+ if (iLogFileName.Length()==0)
+ {
+ iLogFileName=KLogFileName;
+ }
+
+ if (iNoDataGenerationTests)
+ {
+ TUint att;
+ if (iFs.Att(iDbFileName,att)==KErrNotFound)
+ {
+ iTest.Printf(_L("-g switch ignored, because %S not found\n"),&iDbFileName);
+ iNoDataGenerationTests=EFalse;
+ }
+ }
+
+ if (iNumTypicalContacts<0)
+ {
+ iNumTypicalContacts=KNumTypicalContacts;
+ }
+
+ if (iNumAtypicalContacts<0)
+ {
+ iNumAtypicalContacts=KNumAtypicalContacts;
+ }
+
+ if (iNumTypicalContactsCompact<0)
+ {
+ iNumTypicalContactsCompact=KNumTypicalContactsCompact;
+ }
+
+ if (iNumAtypicalContactsCompact<0)
+ {
+ iNumAtypicalContactsCompact=KNumAtypicalContactsCompact;
+ }
+ }
+
+void CBenchMarker::RunL()
+ {
+ iTest.Printf(_L("Starting CntModel benchmarks...\n")); // This forces the console to get loaded under WINS - would otherwise scew profiles.
+
+ for (TInt i=0;i<ENumTests;++i)
+ {
+ StartProfile();
+ TInt timeMinorNumber=0;
+ TRAPD(err,timeMinorNumber=DoTestL(TTest(i)));
+ if (err)
+ {
+ iLog->LogLine(_L("Test %d left with %d"),i,err);
+ break;
+ }
+
+ LogResult(i,timeMinorNumber,KTimeProfileFormat,EndProfile());
+
+ User::CompressAllHeaps();
+ TMemoryInfoV1Buf memoryBuf;
+ UserHal::MemoryInfo(memoryBuf);
+ TMemoryInfoV1 memory(memoryBuf());
+ const TInt totalK=memory.iTotalRamInBytes>>10;
+ const TInt freeK=memory.iFreeRamInBytes>>10;
+ const TInt usedK=totalK-freeK;
+ LogResult(i,timeMinorNumber+1,KSystemMemoryFormat,usedK);
+
+ TInt allocSize;
+ User::Heap().AllocSize(allocSize);;
+ allocSize>>=10;
+ LogResult(i,timeMinorNumber+2,KThreadMemoryFormat,allocSize);
+ }
+
+ iTest.Printf(_L("Dump log to comm port? (y/n) "));
+ TKeyCode key=iTest.Getch();
+ if (key=='y' || key=='Y')
+ {
+writelog:
+ iLog->WriteLogToCommPortL();
+ }
+ iTest.Printf(_L("\nAgain? (y/n)"));
+ key=iTest.Getch();
+ if (key=='y' || key=='Y')
+ {
+ goto writelog;
+ }
+ }
+
+TInt CBenchMarker::DoTestL(TTest aTest)
+ {
+ TInt timeMinorNumber=0;
+ iLog->Log(_L("Test #%d "),aTest);
+ TPtrC match;
+
+ switch (aTest)
+ {
+ case EOpenNewDb:
+ iLog->LogLine(_L("Open new database"));
+ if (iNoDataGenerationTests)
+ {
+ iDb=CContactDatabase::OpenL(iDbFileName);
+ }
+ else
+ {
+ iDb=CContactDatabase::ReplaceL(iDbFileName);
+ LogResult(aTest,0,KFileSizeText,DbFileSize());
+ timeMinorNumber=1;
+ }
+ iGenerator->SetDbL(*iDb);
+ break;
+ case ECreateSecondaryClients:
+ iLog->LogLine(_L("Create %d secondary client threads"),KNumSecondaryClients);
+ CreateSecondaryClients();
+ break;
+ case EAddContacts:
+ iLog->LogLine(_L("Add %d typical and %d atypical contacts"),iNumTypicalContacts,iNumAtypicalContacts);
+ if (!iNoDataGenerationTests)
+ {
+ LogResult(aTest,0,KAverageTimeText,AddContactsL());
+ LogResult(aTest,1,KFileSizeText,DbFileSize());
+ timeMinorNumber=2;
+ }
+ break;
+ case ECompactDb:
+ iLog->LogLine(_L("Compact database"));
+ if (!iNoDataGenerationTests)
+ {
+ iDb->CompactL();
+ LogResult(aTest,0,KFileSizeText,DbFileSize());
+ timeMinorNumber=1;
+ }
+ break;
+ case EAddAndCompact:
+ iLog->LogLine(_L("Add %d typical and %d atypical contacts (compact after each)"),iNumTypicalContactsCompact,iNumAtypicalContactsCompact);
+ if (!iNoDataGenerationTests)
+ {
+ LogResult(aTest,0,KAverageTimeText,AddContactsCompactL());
+ LogResult(aTest,1,KFileSizeText,DbFileSize());
+ timeMinorNumber=2;
+ }
+ break;
+ case EGetSortedItems:
+ iLog->LogLine(_L("Get sorted id array by firstname, lastname, company name"));
+ DoSortL();
+ break;
+ case ELogContactSummary:
+ iLog->LogLine(_L("Log contact summary"));
+ LogContactSummaryL(EFalse);
+ break;
+ case ELogContactSummaryFast:
+ iLog->LogLine(_L("Log contact summary using TContactTextDefItem"));
+ LogContactSummaryL(ETrue);
+ break;
+ case EOpenRContactView:
+ iLog->LogLine(_L("Open RContactView"));
+ OpenRContactViewL();
+ break;
+ case ESetSortOrderOfRContactView:
+ iLog->LogLine(_L("Set order of RContactView"));
+ SetSortOrderOfRContactViewL();
+ break;
+ case EGetSortOrderOfRContactView:
+ iLog->LogLine(_L("Get order of RContactView"));
+ GetSortOrderOfRContactViewL();
+ break;
+ case ELogContactSummaryWithRContactView:
+ iLog->LogLine(_L("Log contact summary using RContactView"));
+ LogContactSummaryFromRContactViewL(EFalse);
+ break;
+ case ELogContactSummaryFastWithRContactView:
+ iLog->LogLine(_L("Log contact summary using RContactView and TContactTextDefItem"));
+ LogContactSummaryFromRContactViewL(ETrue);
+ break;
+ case EFindWithRContactView:
+ iLog->LogLine(_L("Find TContactItemId from RContactView"));
+ FindInRContactViewL();
+ break;
+ case ECloseRContactView:
+ iLog->LogLine(_L("Close RContactView"));
+#ifdef __USE_NEW_INTERFACES
+ iSortedIdList.Close();
+#endif
+ break;
+ case EFindFromLargeFieldSetSuceed:
+ match.Set(iGenerator->NameMatch());
+ iLog->LogLine(_L("FindLC %S using large field set (will suceed)"),&match);
+ FindFromLargeFieldSetL(match);
+ break;
+ case EFindFromLargeFieldSetFail:
+ iLog->LogLine(_L("FindLC %S using large field set (will fail)"),&KNameMatchFail);
+ FindFromLargeFieldSetL(KNameMatchFail);
+ break;
+ case EFindFromSmallFieldSetSuceed:
+ match.Set(iGenerator->NameMatch());
+ iLog->LogLine(_L("FindLC %S using small field set (will suceed)"),&match);
+ FindFromSmallFieldSetL(match);
+ break;
+ case EFindFromSmallFieldSetFail:
+ iLog->LogLine(_L("FindLC %S using small field set (will fail)"),&KNameMatchFail);
+ FindFromSmallFieldSetL(KNameMatchFail);
+ break;
+ case EFindPhoneNumberSuceed:
+ match.Set(iGenerator->PhoneMatch());
+ iLog->LogLine(_L("FindLC %S using just phone field (will suceed)"),&match);
+ FindPhoneNumberL(match);
+ break;
+ case EFindPhoneNumberFail:
+ iLog->LogLine(_L("FindLC %S using just phone field (will fail)"),&KPhoneMatchFail);
+ FindPhoneNumberL(KPhoneMatchFail);
+ break;
+ case EFindEmailAddressSuceed:
+ match.Set(iGenerator->EmailMatch());
+ iLog->LogLine(_L("FindLC %S using just email field (will suceed)"),&match);
+ FindEmailAddressL(match);
+ break;
+ case EFindEmailAddressFail:
+ iLog->LogLine(_L("FindLC %S using just email field (will fail)"),&KNameMatchFail);
+ FindEmailAddressL(KNameMatchFail);
+ break;
+ case EFindAsyncFromLargeFieldSet:
+ iLog->LogLine(_L("FindAsyncL %S using large field set"),&KAsyncFindMatch);
+ FindAsyncFromLargeFieldSetL(KAsyncFindMatch);
+ break;
+ case EFindAsyncFromSmallFieldSet:
+ iLog->LogLine(_L("FindAsyncL %S using small field set"),&KAsyncFindMatch);
+ FindAsyncFromSmallFieldSetL(KAsyncFindMatch);
+ break;
+ case ECloseDb:
+ iLog->LogLine(_L("Close database"));
+ delete iDb;
+ iDb=NULL;
+ break;
+ case ECloseSecondaryClients:
+ iLog->LogLine(_L("Close secondary clients"));
+ CloseSecondaryClients();
+ break;
+ case EOpenExistingDb:
+ iLog->LogLine(_L("Open existing database"));
+ iDb=CContactDatabase::OpenL(iDbFileName);
+ break;
+ case EMultiClientSort:
+ iLog->LogLine(_L("%d client simultaneous sort"),KNumSortClients);
+ CreateSortClients();
+ break;
+ case ENumTests:
+ ASSERT(EFalse);
+ break;
+ }
+
+ return timeMinorNumber;
+ }
+
+void CBenchMarker::StartProfile()
+ {
+ CCntTest::ProfileReset(0,1); // reset profiles 0-1
+ CCntTest::ProfileStart(0);
+ }
+
+TReal CBenchMarker::EndProfile()
+ {
+ CCntTest::ProfileEnd(0);
+ TCntProfile profile[1];
+ CCntTest::ProfileResult(profile,0,1);
+ return TReal(profile[0].iTime/1000000.0);
+ }
+
+void CBenchMarker::StartAverageProfile()
+ {
+ iAverageProfileCounter=0;
+ iNumAverageProfiles=0;
+ CCntTest::ProfileReset(1,1);
+ CCntTest::ProfileStart(1);
+ }
+
+void CBenchMarker::UpdateAverageProfile(TInt aNumIterations)
+ {
+ CCntTest::ProfileEnd(1);
+ TCntProfile profile[1];
+ CCntTest::ProfileResult(profile,1,1);
+ iAverageProfileCounter+=profile[0].iTime;
+ iNumAverageProfiles+=aNumIterations;
+ CCntTest::ProfileReset(1,1);
+ CCntTest::ProfileStart(1);
+#ifdef __VERBOSE
+ iLog->LogLineNoEcho(KProfileResult,profile[0].iTime,aNumIterations);
+#endif
+ }
+
+TReal CBenchMarker::EndAverageProfile()
+ {
+ CCntTest::ProfileEnd(1);
+ if (iNumAverageProfiles>0)
+ {
+ return TReal((iAverageProfileCounter/iNumAverageProfiles)/1000000.0);
+ }
+
+ return TReal(0.0);
+ }
+
+TReal CBenchMarker::AddContactsL()
+ {
+ iTest.Printf(_L("Adding "));
+ StartAverageProfile();
+
+ TInt ii;
+ for (ii=0;ii<iNumTypicalContacts;++ii)
+ {
+ IncVisualCounter();
+ iGenerator->AddTypicalRandomContactL();
+ UpdateAverageProfile(1);
+ }
+
+ for (ii=0;ii<iNumAtypicalContacts;++ii)
+ {
+ IncVisualCounter();
+ iGenerator->AddAtypicalRandomContactL();
+ UpdateAverageProfile(1);
+ }
+
+ EndVisualCounter();
+ return EndAverageProfile();
+ }
+
+TReal CBenchMarker::AddContactsCompactL()
+ {
+ iTest.Printf(_L("Adding "));
+ StartAverageProfile();
+
+ TInt ii;
+ for (ii=0;ii<iNumTypicalContactsCompact;++ii)
+ {
+ IncVisualCounter();
+ iGenerator->AddTypicalRandomContactL();
+ iDb->CompactL();
+ UpdateAverageProfile(1);
+ }
+
+ for (ii=0;ii<iNumAtypicalContactsCompact;++ii)
+ {
+ IncVisualCounter();
+ iGenerator->AddAtypicalRandomContactL();
+ iDb->CompactL();
+ UpdateAverageProfile(1);
+ }
+
+ EndVisualCounter();
+ return EndAverageProfile();
+ }
+
+#ifdef __USE_NEW_INTERFACES
+void CBenchMarker::LogContactSummaryFromRContactViewL(TBool aFaster)
+ {
+ iTest.Printf(_L("Logging "));
+ const TInt numContacts(iSortedIdList.Count());
+ for (TInt ii=0;ii<numContacts;++ii)
+ {
+ IncVisualCounter();
+ LogContactSummaryL(aFaster,iSortedIdList.GetL(ii));
+ }
+ EndVisualCounter();
+ }
+#else
+void CBenchMarker::LogContactSummaryFromRContactViewL(TBool)
+ {
+ }
+#endif
+
+void CBenchMarker::OpenRContactViewL()
+ {
+#ifdef __USE_NEW_INTERFACES
+ User::LeaveIfError(iSortedIdList.Open(*iDb));
+#endif
+ }
+
+void CBenchMarker::SetSortOrderOfRContactViewL()
+ {
+#ifdef __USE_NEW_INTERFACES
+ CArrayFix<CContactDatabase::TSortPref>* sortOrder=new(ELeave)CArrayFixFlat<CContactDatabase::TSortPref>(2);
+ CleanupStack::PushL(sortOrder);
+ sortOrder->AppendL(CContactDatabase::TSortPref(KUidContactFieldGivenName));
+ sortOrder->AppendL(CContactDatabase::TSortPref(KUidContactFieldFamilyName));
+ sortOrder->AppendL(CContactDatabase::TSortPref(KUidContactFieldCompanyName));
+ iSortedIdList.ChangeSortOrderL(*sortOrder);
+ CleanupStack::PopAndDestroy(); // sortOrder
+#endif
+ }
+
+void CBenchMarker::GetSortOrderOfRContactViewL()
+ {
+#ifdef __USE_NEW_INTERFACES
+ const CArrayFix<CContactDatabase::TSortPref>& sortOrder=iSortedIdList.SortOrderLC();
+#ifdef __VERBOSE
+ const TInt numSortPrefs=sortOrder.Count();
+ for (TInt ii=0;ii<numSortPrefs;++ii)
+ {
+ iLog->LogLineNoEcho(_L("Sort pref %d field type: %x order: %S"),ii,sortOrder[ii].iFieldType,(sortOrder[ii].iOrder==CContactDatabase::TSortPref::EAsc) ? &KAscendingSortOrder : &KDescendingSortOrder);
+ }
+#else
+ sortOrder.Count();
+#endif
+ CleanupStack::PopAndDestroy(); // sortOrder
+#endif
+ }
+
+void CBenchMarker::FindInRContactViewL()
+ {
+#ifdef __USE_NEW_INTERFACES
+ const TContactItemId id=iSortedIdList.GetL(iSortedIdList.Count()-1);
+ const TInt index=iSortedIdList.Find(id);
+ ASSERT(index==iSortedIdList.Count()-1);
+ iLog->LogLine(_L("Found TContactItemId %d for index %d"),id,index);
+#endif
+ }
+
+void CBenchMarker::LogContactSummaryL(TBool aFaster)
+ {
+ iTest.Printf(_L("Logging "));
+ const TInt numContacts(iSortedItems->Count());
+ for (TInt ii=0;ii<numContacts;++ii)
+ {
+ IncVisualCounter();
+ LogContactSummaryL(aFaster,(*iSortedItems)[ii]);
+ }
+ EndVisualCounter();
+ }
+
+void CBenchMarker::LogContactSummaryL(TBool aFaster,TContactItemId aContactItemId)
+ {
+ if (aFaster)
+ {
+ if (iTextDef==NULL)
+ {
+ iTextDef=CContactTextDef::NewL();
+ iTextDef->AppendL(TContactTextDefItem(KUidContactFieldGivenName,KTextDefSeparator));
+ iTextDef->AppendL(TContactTextDefItem(KUidContactFieldFamilyName,KTextDefSeparator));
+ iTextDef->AppendL(TContactTextDefItem(KUidContactFieldCompanyName,KTextDefSeparator));
+ }
+
+ TBuf<128> buf;
+ iDb->ReadContactTextDefL(aContactItemId,buf,iTextDef);
+#ifdef __VERBOSE
+ iLog->LogLineNoEcho(buf);
+#endif
+ }
+ else
+ {
+ CContactItem* thisContactItem=iDb->ReadContactLC(aContactItemId);
+ CTestContact* thisContact=CTestContact::NewLC(*thisContactItem);
+
+#ifdef __VERBOSE
+ const TPtrC firstName(thisContact->FirstNameL());
+ const TPtrC lastName(thisContact->LastNameL());
+ const TPtrC companyName(thisContact->CompanyNameL());
+ iLog->LogLineNoEcho(KContactSummaryFormat,thisContactItem->Id(),&firstName,&lastName,&companyName);
+#else
+ thisContact->FirstNameL();
+ thisContact->LastNameL();
+ thisContact->CompanyNameL();
+#endif
+ CleanupStack::PopAndDestroy(2); // thisContact, thisContactItem.
+ }
+ }
+
+
+void CBenchMarker::DoSortL()
+ {
+ CContactTextDef* textDef=CContactTextDef::NewLC();
+ textDef->AppendL(TContactTextDefItem(KUidContactFieldGivenName));
+ textDef->AppendL(TContactTextDefItem(KUidContactFieldFamilyName));
+ textDef->AppendL(TContactTextDefItem(KUidContactFieldCompanyName));
+ iDb->SetTextDefinitionL(textDef); // Takes ownership.
+ CleanupStack::Pop(); // textDef.
+ CArrayFix<CContactDatabase::TSortPref>* sortOrder=new(ELeave)CArrayFixFlat<CContactDatabase::TSortPref>(2);
+ CleanupStack::PushL(sortOrder);
+ sortOrder->AppendL(CContactDatabase::TSortPref(KUidContactFieldDefinedText));
+ iDb->SortL(sortOrder); // Takes ownership.
+ CleanupStack::Pop(); // sortOrder
+ iSortedItems=iDb->SortedItemsL();
+ }
+
+void CBenchMarker::FindFromLargeFieldSetL(const TDesC& aTextToFind)
+ {
+ CContactItemFieldDef* def=new(ELeave) CContactItemFieldDef();
+ CleanupStack::PushL(def);
+ def->AppendL(KUidContactFieldGivenName);
+ def->AppendL(KUidContactFieldFamilyName);
+ def->AppendL(KUidContactFieldCompanyName);
+ def->AppendL(KUidContactFieldPhoneNumber);
+ def->AppendL(KUidContactFieldFax);
+ def->AppendL(KUidContactFieldEMail);
+ def->AppendL(KUidContactFieldUrl);
+ def->AppendL(KUidContactFieldAddress);
+ def->AppendL(KUidContactFieldLocality);
+ def->AppendL(KUidContactFieldRegion);
+ def->AppendL(KUidContactFieldPostcode);
+ def->AppendL(KUidContactFieldCountry);
+ def->AppendL(KUidContactFieldNote);
+ DoFindL(aTextToFind,*def);
+ CleanupStack::PopAndDestroy(); // def.
+ }
+
+void CBenchMarker::FindFromSmallFieldSetL(const TDesC& aTextToFind)
+ {
+ CContactItemFieldDef* def=new(ELeave) CContactItemFieldDef();
+ CleanupStack::PushL(def);
+ def->AppendL(KUidContactFieldGivenName);
+ def->AppendL(KUidContactFieldFamilyName);
+ def->AppendL(KUidContactFieldCompanyName);
+ DoFindL(aTextToFind,*def);
+ CleanupStack::PopAndDestroy(); // def.
+ }
+
+void CBenchMarker::FindPhoneNumberL(const TDesC& aTextToFind)
+ {
+ CContactItemFieldDef* def=new(ELeave) CContactItemFieldDef();
+ CleanupStack::PushL(def);
+ def->AppendL(KUidContactFieldPhoneNumber);
+ DoFindL(aTextToFind,*def);
+ CleanupStack::PopAndDestroy(); // def.
+ }
+
+void CBenchMarker::FindEmailAddressL(const TDesC& aTextToFind)
+ {
+ CContactItemFieldDef* def=new(ELeave) CContactItemFieldDef();
+ CleanupStack::PushL(def);
+ def->AppendL(KUidContactFieldEMail);
+ DoFindL(aTextToFind,*def);
+ CleanupStack::PopAndDestroy(); // def.
+ }
+
+TReal CBenchMarker::FindAsyncFromLargeFieldSetL(const TDesC& aTextToFind)
+ {
+ CContactItemFieldDef* def=new(ELeave) CContactItemFieldDef();
+ CleanupStack::PushL(def);
+ def->AppendL(KUidContactFieldGivenName);
+ def->AppendL(KUidContactFieldFamilyName);
+ def->AppendL(KUidContactFieldCompanyName);
+ def->AppendL(KUidContactFieldPhoneNumber);
+ def->AppendL(KUidContactFieldFax);
+ def->AppendL(KUidContactFieldEMail);
+ def->AppendL(KUidContactFieldUrl);
+ def->AppendL(KUidContactFieldAddress);
+ def->AppendL(KUidContactFieldLocality);
+ def->AppendL(KUidContactFieldRegion);
+ def->AppendL(KUidContactFieldPostcode);
+ def->AppendL(KUidContactFieldCountry);
+ def->AppendL(KUidContactFieldNote);
+ TReal averageTime=DoFindAsyncL(aTextToFind,*def);
+ CleanupStack::PopAndDestroy(); // def.
+ return averageTime;
+ }
+
+TReal CBenchMarker::FindAsyncFromSmallFieldSetL(const TDesC& aTextToFind)
+ {
+ CContactItemFieldDef* def=new(ELeave) CContactItemFieldDef();
+ CleanupStack::PushL(def);
+ def->AppendL(KUidContactFieldGivenName);
+ def->AppendL(KUidContactFieldFamilyName);
+ def->AppendL(KUidContactFieldCompanyName);
+ TReal averageTime=DoFindAsyncL(aTextToFind,*def);
+ CleanupStack::PopAndDestroy(); // def.
+ return averageTime;
+ }
+
+void CBenchMarker::DoFindL(const TDesC& aTextToFind,const CContactItemFieldDef& aFieldDef)
+ {
+ CContactIdArray* matchList=iDb->FindLC(aTextToFind,&aFieldDef);
+
+#ifdef __VERBOSE
+ const TInt numIds=matchList->Count();
+ iLog->LogLine(_L("Matched %d contact(s)"),numIds);
+ for (TInt ii=0;ii<numIds;++ii)
+ {
+ LogContactSummaryL(ETrue,(*matchList)[ii]);
+ }
+#else
+ matchList->Count();
+#endif
+
+ CleanupStack::PopAndDestroy(); // matchList.
+ }
+
+TReal CBenchMarker::DoFindAsyncL(const TDesC& aTextToFind,const CContactItemFieldDef& aFieldDef)
+ {
+ iTest.Printf(_L("Found "));
+ StartAverageProfile();
+ iIdleFinder=iDb->FindAsyncL(aTextToFind,&aFieldDef,this);
+ CleanupStack::PushL(iIdleFinder); // Handle on cleanup stack because object is very temporary.
+ CActiveScheduler::Start();
+
+ EndVisualCounter();
+#ifdef __VERBOSE
+ CContactIdArray* matchList=iIdleFinder->TakeContactIds();
+ CleanupStack::PushL(matchList);
+ const TInt numIds=matchList->Count();
+ iLog->LogLine(_L("Matched %d contact(s)"),numIds);
+ for (TInt ii=0;ii<numIds;++ii)
+ {
+ LogContactSummaryL(ETrue,(*matchList)[ii]);
+ }
+ CleanupStack::PopAndDestroy(); // matchList.
+#endif
+
+ CleanupStack::PopAndDestroy(); // iIdleFinder.
+ return EndAverageProfile();
+ }
+
+void CBenchMarker::IdleFindCallback()
+ {
+ IncVisualCounter();
+ UpdateAverageProfile(1);
+ if (iIdleFinder->IsComplete())
+ {
+ CActiveScheduler::Stop();
+ }
+ }
+
+#ifndef __USE_NEW_INTERFACES
+GLDEF_C void DoSortL(CContactDatabase& aDb)
+ {
+ CContactTextDef* textDef=CContactTextDef::NewLC();
+ textDef->AppendL(TContactTextDefItem(KUidContactFieldGivenName));
+ textDef->AppendL(TContactTextDefItem(KUidContactFieldFamilyName));
+ textDef->AppendL(TContactTextDefItem(KUidContactFieldCompanyName));
+ aDb.SetTextDefinitionL(textDef); // Takes ownership.
+ CleanupStack::Pop(); // textDef.
+ CArrayFix<CContactDatabase::TSortPref>* sortOrder=new(ELeave)CArrayFixFlat<CContactDatabase::TSortPref>(2);
+ CleanupStack::PushL(sortOrder);
+ sortOrder->AppendL(CContactDatabase::TSortPref(KUidContactFieldDefinedText));
+ aDb.SortL(sortOrder); // Takes ownership.
+ CleanupStack::Pop(); // sortOrder
+ }
+#endif
+
+GLDEF_C TInt T_BenchClientThreadStart(TAny* aPtr)
+ {
+ TThreadCommandLine* comLine=STATIC_CAST(TThreadCommandLine*, aPtr);
+ RThread owningThread=comLine->iOwningThread;
+ TRequestStatus* initialStatus=comLine->iInitialStatus;
+ TRequestStatus* completionStatus=comLine->iCompletionStatus;
+ TFileName dbFileName=comLine->iDbFileName;
+ if (comLine->iExitAfterSort)
+ {
+ owningThread.RequestComplete(initialStatus,KErrNone);
+ }
+
+ __UHEAP_MARK;
+ TInt err;
+ CActiveScheduler* scheduler=new CActiveScheduler;
+ if (scheduler)
+ {
+ CActiveScheduler::Install(scheduler);
+ CTrapCleanup* cleanup=CTrapCleanup::New();
+ if (cleanup)
+ {
+ CContactDatabase* db=NULL;
+#ifdef __USE_NEW_INTERFACES
+ RContactView sortedIdList;
+ TRAP(err,
+ db=CContactDatabase::OpenL(dbFileName);
+ User::LeaveIfError(sortedIdList.Open(*db));
+ );
+#else
+ TRAP(err,
+ db=CContactDatabase::OpenL(dbFileName);
+ DoSortL(*db);
+ );
+#endif
+ if (!comLine->iExitAfterSort)
+ {
+ owningThread.RequestComplete(initialStatus,KErrNone);
+ CActiveScheduler::Start();
+ }
+#ifdef __USE_NEW_INTERFACES
+ sortedIdList.Close();
+#endif
+ delete db;
+ delete cleanup;
+ }
+ else
+ {
+ err=KErrNoMemory;
+ }
+ delete scheduler;
+ }
+ else
+ {
+ err=KErrNoMemory;
+ }
+ __UHEAP_MARKEND;
+
+ if (comLine->iExitAfterSort)
+ {
+ owningThread.RequestComplete(completionStatus,err);
+ }
+ owningThread.Close();
+ return KErrNone;
+ }
+
+void CBenchMarker::CreateSecondaryClients()
+ {
+ // Create a set of client threads.
+ for (TInt ii=0;ii<KNumSecondaryClients;++ii)
+ {
+ TRequestStatus initialStatus(KRequestPending);
+ TThreadCommandLine comLine(&initialStatus,NULL,iDbFileName,EFalse);
+ TBuf<32> threadName;
+ threadName.Format(KThreadNameFormat,ii);
+ secondaryClient[ii].Create(threadName,T_BenchClientThreadStart,KClientStackSize,KClientHeapSize,KClientHeapSize,&comLine);
+ comLine.iOwningThread.Duplicate(secondaryClient[ii]);
+ secondaryClient[ii].Resume();
+ User::WaitForRequest(initialStatus);
+ }
+ }
+
+void CBenchMarker::CloseSecondaryClients()
+ {
+ for (TInt ii=0;ii<KNumSecondaryClients;++ii)
+ {
+ secondaryClient[ii].Kill(KErrNone);
+ secondaryClient[ii].Close();
+ }
+ }
+
+void CBenchMarker::CreateSortClients()
+ {
+ TRequestStatus completionStatus[KNumSortClients];
+
+ // Create a set of client threads.
+ for (TInt ii=0;ii<KNumSortClients;++ii)
+ {
+ completionStatus[ii]=KRequestPending;
+ TRequestStatus initialStatus(KRequestPending);
+ TThreadCommandLine comLine(&initialStatus,&(completionStatus[ii]),iDbFileName,ETrue);
+ RThread thread;
+ TBuf<32> threadName;
+ threadName.Format(KThreadNameFormat,ii);
+ thread.Create(threadName,T_BenchClientThreadStart,KClientStackSize,KClientHeapSize,KClientHeapSize,&comLine);
+ comLine.iOwningThread.Duplicate(thread);
+ thread.Resume();
+ thread.Close();
+ User::WaitForRequest(initialStatus);
+ }
+
+ // Wait for all the clients to finish.
+ TBool moreClientsToComplete;
+ TInt numWaits=-1;
+ do
+ {
+ ++numWaits;
+ User::WaitForAnyRequest();
+ moreClientsToComplete=EFalse;
+ for (TInt ii=0;ii<KNumSortClients;++ii)
+ {
+ if (completionStatus[ii].Int()==KRequestPending)
+ {
+ moreClientsToComplete=ETrue;
+ break;
+ }
+ }
+ }
+ while (moreClientsToComplete);
+
+ while (numWaits<(KNumSortClients-1))
+ {
+ ++numWaits;
+ User::WaitForAnyRequest();
+ }
+ }
+
+void CBenchMarker::IncVisualCounter()
+ {
+ TBuf<8> backSpaceBuf;
+
+ if (iVisualCounter>=0)
+ {
+ TInt numDigits=1;
+ TInt divisor=10;
+
+ FOREVER
+ {
+ if (iVisualCounter/divisor>0)
+ {
+ divisor*=10;
+ ++numDigits;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ for (TInt ii=0;ii<numDigits;++ii)
+ {
+ backSpaceBuf.Append(KBackSpace);
+ }
+ }
+
+ iTest.Printf(KVisualCounterFormat,&backSpaceBuf,++iVisualCounter);
+ }
+
+void CBenchMarker::EndVisualCounter()
+ {
+ iTest.Printf(KNewLine);
+ iVisualCounter=-1;
+ }
+
+TInt CBenchMarker::DbFileSize()
+ {
+ TEntry dbEntry;
+ TInt err=iFs.Entry(iDbFileName,dbEntry);
+ if (err==KErrNone)
+ {
+ return dbEntry.iSize;
+ }
+
+ return err;
+ }
+
+void CBenchMarker::LogResult(TInt aMajorTestNum,TInt aMinorTestNum,const TDesC& aDescription,TInt aResult)
+ {
+ iLog->LogLine(KResultFormatTInt,aMajorTestNum,aMinorTestNum,&aDescription,aResult);
+ }
+
+void CBenchMarker::LogResult(TInt aMajorTestNum,TInt aMinorTestNum,const TDesC& aDescription,TReal aResult)
+ {
+ iLog->LogLine(KResultFormatTReal,aMajorTestNum,aMinorTestNum,&aDescription,aResult);
+ }
+
+
+//
+// Main.
+//
+
+GLDEF_C TInt E32Main()
+ {
+ RDebug::Print(_L("t_bench started"));
+ __UHEAP_MARK;
+ TBuf<256> commandLine;
+ User::CommandLine(commandLine);
+
+ CActiveScheduler* scheduler=new CActiveScheduler;
+ if (scheduler)
+ {
+ CActiveScheduler::Install(scheduler);
+ CTrapCleanup* cleanup=CTrapCleanup::New();
+ if (cleanup)
+ {
+ CBenchMarker* benchMarker=new CBenchMarker();
+ if (benchMarker)
+ {
+ TRAPD(err,
+ benchMarker->ConstructL(commandLine);
+ benchMarker->RunL();
+ );
+ RDebug::Print(_L("t_bench finish with %d error"),err);
+ delete benchMarker;
+ }
+ delete cleanup;
+ }
+ delete scheduler;
+ }
+ __UHEAP_MARKEND;
+ return KErrNone;
+ }