/* * Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). * Contact: http://www.qt-project.org/legal * 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: * Notifier step / thread, locks a contact / database, sends message to * concurrent running listener thread / step informing it what has been locked * waits for message from listner to start countdown to release of lock * listener will send message and wait for specified lock to be released * or for timeout to be invoked by cntmodel. * Sending Messages: * Set shared string to contain length of time resource will be locked for in seconds. KSharedEvents. (6) * Set shared string to contain id of contact that is locked. KSharedContact. (1) * Set shared string to contain a value, specify that new test case can start. KSharedNextTest. (aa) * Receiving messages: * Read shared string length signifying that thread should start countdown * until realease of resource. KSharedClients. (AA) * */ /** @file @publishedAll @released */ #include "concurrenttimeoutnotifierstep.h" #include "performancefunctionalitydefs.h" _LIT(KRun1,"NonTrans"); _LIT(KRun2,"Transaction"); _LIT(KTest1, "Contacts timeout test"); _LIT(KTest2, "Transaction timeout test"); const static TInt KTimeout = 50000000;//50 seconds timeout const static TInt KOneSecond = 1000000; _LIT(KDoubleChar,"AA"); CConcurrentTimeOutNotifierStep::CConcurrentTimeOutNotifierStep() : CPerformanceFunctionalityBase(KConcurrentTimeoutContacts), iSeconds( 10 ) { iConcurrent = ETrue; SetTestStepName(KConcurrentTimeoutNotifierStep); } /** runs the next test that will lock a particular resource */ void CConcurrentTimeOutNotifierStep::CConcurrentTimeOutNotifierMyActive::RunL() { const static TInt KTestCount = iStep->iTests->Count(); if( iStep->iNextTest >= KTestCount ) { CActiveScheduler::Stop(); iStep->iNextTest = 0; } else { RArray< void (CConcurrentTimeOutNotifierStep::*)() > &Tests = *( iStep->iTests ); //select test to run void (CConcurrentTimeOutNotifierStep::*TestFunction)() = Tests[ iStep->iNextTest ]; //execute test ( iStep->*TestFunction )(); Activate(); } } void CConcurrentTimeOutNotifierStep::CConcurrentTimeOutNotifierMyActive::DoCancel() { //nothing to cleanup, does nothing. } TInt CConcurrentTimeOutNotifierStep::CConcurrentTimeOutNotifierMyActive::RunError(TInt aError) { _LIT(KActiveError,"CConcurrentTimeOutNotifierStep:: Error in doTest runL: %d"); iStep->ERR_PRINTF2(KActiveError, aError ); return aError; } void CConcurrentTimeOutNotifierStep::CConcurrentTimeOutNotifierMyActive::Activate() { if(!IsActive()) { TRequestStatus *pS=&iStatus; User::RequestComplete(pS,KErrNone); SetActive(); } } CConcurrentTimeOutNotifierStep::~CConcurrentTimeOutNotifierStep() { if( iTests ) { iTests->Close(); CLEAR(iTests); } CLEAR(iMyActive); } /** create active object and test array append contact lock or transaction lock test as necessary */ void CConcurrentTimeOutNotifierStep::PreTestL() { iMyActive = new (ELeave) CConcurrentTimeOutNotifierStep::CConcurrentTimeOutNotifierMyActive( this ); iTests = new(ELeave) RArray< void (CConcurrentTimeOutNotifierStep::*)() >(); const TDesC &run = ConfigSection(); if( run == KRun1 ) { iTests->AppendL( &CConcurrentTimeOutNotifierStep::LockContactTestL ); } else if( run == KRun2 ) { iTests->AppendL( &CConcurrentTimeOutNotifierStep::LockDatabaseTestL ); } else { MissingTestPanic(); } } TVerdict CConcurrentTimeOutNotifierStep::doTestStepL() { __UHEAP_MARK; InitializeL(); _LIT(KDoStepPrint,"CConcurrentTimeOutNotifierStep::doTestStepL()"); INFO_PRINTF1(KDoStepPrint); //Block start iIterate->Reset(); SetTimerL(-1); SetContactL( -1 ); SetSharedTextL(KSharedNextTest, KDoubleChar, EFalse); CActiveScheduler::Add(iMyActive); iMyActive->Activate(); CActiveScheduler::Start(); Cleanup(); __UHEAP_MARKEND; return TestStepResult(); } /** sends message to listener specifying the length of time resource will be locked for */ void CConcurrentTimeOutNotifierStep::SetTimerL(const TInt aTime) { ShareIntL(KSharedEvents, aTime); } /** sends message to listener specifying the contact that will be locked */ void CConcurrentTimeOutNotifierStep::SetContactL(const TInt aCid) { ShareIntL(KSharedContact, aCid); } /** wait for message from listener specifying that countdown to release of resource should commence */ void CConcurrentTimeOutNotifierStep::StartCountdownL() { if ( iCountdown ) { return; } iCountdown = SharedCountL(KSharedClients) > 0; if (iCountdown) { iStart.UniversalTime(); SetSharedTextL(KSharedClients, KNullDesC, EFalse); } } /** either release resource after countdown has reached the necessary value or timeout test if countdown is not started after the timeout period has passed */ void CConcurrentTimeOutNotifierStep::ProcessWaitL(const TBool aTransaction) { StartCountdownL(); iEnd.UniversalTime(); const TInt64 KLockTime = iEnd.MicroSecondsFrom( iStart ).Int64(); const TInt64 KTestTime = iEnd.MicroSecondsFrom( iTestStart ).Int64(); if( iCountdown && ( KLockTime >= ((iSeconds - KTimeDiff) * KOneSecond) ) ) { iWaiting = EFalse; iCountdown = EFalse; if(aTransaction) { iContactsDatabase->DatabaseCommitL( EFalse );//unlock database } else { CloseL( ETrue );//unlock contact } ++iNextTest; SetSharedTextL(KSharedNextTest, KDoubleChar, EFalse); } else if( KTestTime > KTimeout ) //test has timed out { _LIT(KTimedOut,"Notifier test %d has timed out"); ERR_PRINTF2(KTimedOut, ++iNextTest); iWaiting = EFalse; iCountdown = EFalse; TESTPRINT( EFalse ); SetSharedTextL(KSharedNextTest, KDoubleChar, EFalse); iNextTest = iTests->Count(); } //else test is not complete and has not timed out... continue waiting } /* open a contact, this causes that contact to be locked */ void CConcurrentTimeOutNotifierStep::LockContactTestL() { if(iWaiting) { ProcessWaitL( EFalse ); } else { INFO_PRINTF1(KTest1); iWaiting = ETrue; TContactItemId cid = iIterate->NextL(); OpenL( cid ); //notify listener that database will be unlocked after x amount of time SetTimerL( iSeconds - KTimeDiff ); SetContactL( cid ); iTestStart.UniversalTime(); } } /* starts a transactions this causes the database to be locked */ void CConcurrentTimeOutNotifierStep::LockDatabaseTestL() { if(iWaiting) { ProcessWaitL( ETrue ); } else { INFO_PRINTF1(KTest2); iWaiting = ETrue; TContactItemId cid = iIterate->NextL(); iContactsDatabase->DatabaseBeginLC(EFalse); //notify listener that contact will be unlocked after x amount of time SetTimerL( iSeconds - KTimeDiff ); SetContactL( cid ); CleanupStack::Pop(); // cleanup item from the CContactDatabase::DatabaseBeginLC() iTestStart.UniversalTime(); } }