diff -r ac20d6a0a19d -r b982c3e940f3 telephonyprotocols/pdplayer/src/pdp_contention.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/telephonyprotocols/pdplayer/src/pdp_contention.cpp Tue Sep 14 17:55:14 2010 +0100 @@ -0,0 +1,372 @@ +// Copyright (c) 2010 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: +// + +/** + @file + @internalComponent +*/ + +#include "OstTraceDefinitions.h" +#ifdef OST_TRACE_COMPILER_IN_USE +#include "pdp_contentionTraces.h" +#endif + + +#include +#include +#include +#include +#include + +CContextTypeChecker::CContextTypeChecker(RPacketService& aPacketService, MContextEventsObserver& aCallback):CActive(EPriorityStandard), + iPacketService(aPacketService), iCallback(aCallback) + { + CActiveScheduler::Add(this); + } + +CContextTypeChecker::~CContextTypeChecker() + { + iContextName = NULL; + } + +void CContextTypeChecker::Start(const TName* aContextName) + { + iContextName = aContextName; + iPacketService.EnumerateContextsInNif(iStatus, *iContextName, iCountInNif); + SetActive(); + } + +void CContextTypeChecker::RunL() + { + User::LeaveIfError(iStatus.Int()); + if (iCountInNif == 1) // This is a primary context + { + iCallback.PrimaryContextAddedL(iContextName); + } + else + { + iCallback.SecondaryContextAdded(iContextName); + } + } + +void CContextTypeChecker::DoCancel() + { + iPacketService.CancelAsyncRequest(EPacketEnumerateContextsInNif); + } + +TInt CContextTypeChecker::RunError(TInt aError) + { + // Report an error + iCallback.ContextTypeCheckingError(iContextName, aError); + return KErrNone; // Make ActiveScheduler happy + } + + +CPrimaryContextsMonitor::CPrimaryContextsMonitor(RPacketService& aPacketService, MContentionObserver& aCallback) : CActive(EPriorityStandard), + iPacketService(aPacketService), iCallback(aCallback) + { + CActiveScheduler::Add(this); + } + +CPrimaryContextsMonitor::~CPrimaryContextsMonitor() + { + Cancel(); + iContextMonitors.ResetAndDestroy(); + delete iContextTypeChecker; + iAddedContextsNames.ResetAndDestroy(); + } + +void CPrimaryContextsMonitor::StartL() + { + iContextTypeChecker = new(ELeave) CContextTypeChecker(iPacketService, *this); + iState = EEnumeratingContexts; + iPacketService.EnumerateNifs(iStatus, iInitialNifsCount); + SetActive(); + } + +void CPrimaryContextsMonitor::PrimaryContextAddedL(const TName* aContextName) + { + // Create new status monitor for this context + StartContextStatusMonitoringL(*aContextName); + RemoveContextNameAndCheckNext(aContextName); + } + +void CPrimaryContextsMonitor::SecondaryContextAdded(const TName* aContextName) + { + // This is not a primary context, just delete its name. + RemoveContextNameAndCheckNext(aContextName); + } + +void CPrimaryContextsMonitor::RemoveContextNameAndCheckNext(const TName* aContextName) + { + TInt nameIndex = iAddedContextsNames.Find(aContextName); + __ASSERT_DEBUG(nameIndex != KErrNotFound, User::Invariant()); + delete iAddedContextsNames[nameIndex]; + iAddedContextsNames.Remove(nameIndex); + + if (iAddedContextsNames.Count() > 1) + // Should be more than one here, coz we are waiting for new context added all the time, + // so the last one item is always empty. + { + iContextTypeChecker->Start(iAddedContextsNames[0]); + } + } + +void CPrimaryContextsMonitor::PrimaryContextDeleted(const CContextStatusMonitor* aContextStatusMonitor) + { + if (aContextStatusMonitor->IsPassedThroughActiveState()) + { + iCallback.ContentionResolved(); + } + DeleteContextStatusMonitor(aContextStatusMonitor); + } + +void CPrimaryContextsMonitor::ContextTypeCheckingError(const TName* aContextName, TInt aError) + { + RemoveContextNameAndCheckNext(aContextName); + ProcessError(aError); + } + + +void CPrimaryContextsMonitor::ContextMonitoringError(const CContextStatusMonitor* aContextStatusMonitor, TInt aError) + { + DeleteContextStatusMonitor(aContextStatusMonitor); + ProcessError(aError); + } + +void CPrimaryContextsMonitor::DeleteContextStatusMonitor(const CContextStatusMonitor* aContextStatusMonitor) + { + TInt monitorIndex = iContextMonitors.Find(aContextStatusMonitor); + __ASSERT_DEBUG(monitorIndex != KErrNotFound, User::Invariant()); + delete iContextMonitors[monitorIndex]; + iContextMonitors.Remove(monitorIndex); + } + +void CPrimaryContextsMonitor::ProcessError(TInt aError) + { + __ASSERT_DEBUG(aError != KErrNone, User::Invariant()); + OstTraceDef1(OST_TRACE_CATEGORY_DEBUG, TRACE_INTERNALS, CPRIMARYCONTEXTSMONITOR_PROCESSERROR_1, ("PDP context monitoring error: %d"), aError); + (void)aError; //needed for debug builds + } + +void CPrimaryContextsMonitor::RunL() + { + User::LeaveIfError(iStatus.Int()); + SwitchStateL(); + RPacketService::TNifInfoV2Pckg nifInfoV2Pckg(iCurrentNifInfo); + switch(iState) + { + case EGettingInfo: + StartContextStatusMonitoringL(iCurrentNifInfo.iContextName); + iPacketService.GetNifInfo(iStatus, iCurrentNifIndex, nifInfoV2Pckg); + ++iCurrentNifIndex; + SetActive(); + break; + case EListening: + // All functions in RPacketService and RPacketContext, + // that can be used to check if context is primary, are asynchronous. + // We could not call them here, coz can miss some events from NotifyContextAdded + // So subscribe to NotifyContextAdded as soon as possible and check context + // type using CContextTypeChecker active object + TName *contextName = new (ELeave) TName; + CleanupStack::PushL(contextName); + iAddedContextsNames.AppendL(contextName); + CleanupStack::Pop(contextName); + // subscribe to NotifyContextAdded + iPacketService.NotifyContextAdded(iStatus, *contextName); + SetActive(); + // if there are any items in iAddedContextsNames except that one that has been added above, i.e count > 1 + // starting asynchronous context type checking + if (!iContextTypeChecker->IsActive() && iAddedContextsNames.Count()>1) + { + iContextTypeChecker->Start(iAddedContextsNames[0]); + } + break; + } + } +void CPrimaryContextsMonitor::DoCancel() + { + switch(iState) + { + case EEnumeratingContexts: + iPacketService.CancelAsyncRequest(EPacketEnumerateNifs); + break; + case EGettingInfo: + iPacketService.CancelAsyncRequest(EPacketGetNifInfo); + break; + case EListening: + iPacketService.CancelAsyncRequest(EPacketNotifyContextAdded); + break; + } + + } + +TInt CPrimaryContextsMonitor::RunError(TInt aError) + { + // Process an error + ProcessError(aError); + return KErrNone; // Make ActiveScheduler happy + } + + +void CPrimaryContextsMonitor::SwitchStateL() + { + if (iState == EEnumeratingContexts) + { + if (iInitialNifsCount > 0) + { + iState = EGettingInfo; + } + else + { + iState = EListening; + } + } + else if (iState == EGettingInfo && iCurrentNifIndex == iInitialNifsCount) + { + StartContextStatusMonitoringL(iCurrentNifInfo.iContextName); + iState = EListening; + } + } + +void CPrimaryContextsMonitor::StartContextStatusMonitoringL(const TName& aContextName) + { + CContextStatusMonitor* newStatusMonitor = new (ELeave) CContextStatusMonitor(iPacketService, *this); + CleanupStack::PushL(newStatusMonitor); + iContextMonitors.AppendL(newStatusMonitor); + CleanupStack::Pop(newStatusMonitor); + newStatusMonitor->StartL(aContextName); + } + +CContextStatusMonitor::CContextStatusMonitor(RPacketService& aPacketService, MContextEventsObserver& aCallback):CActive(EPriorityStandard), + iPacketService(aPacketService), iCallback(aCallback) + { + CActiveScheduler::Add(this); + } + +CContextStatusMonitor::~CContextStatusMonitor() + { + Cancel(); + iPacketContext.Close(); + } + +TBool CContextStatusMonitor::StartL(const TName& aContextName) + { + iContextName.Copy(aContextName); + User::LeaveIfError(iPacketContext.OpenExistingContext(iPacketService, iContextName)); + User::LeaveIfError(iPacketContext.GetStatus(iContextStatus)); + + if (iContextStatus == RPacketContext::EStatusDeleted) + { + return EFalse; + } + + if (iContextStatus == RPacketContext::EStatusActive || + iContextStatus == RPacketContext::EStatusSuspended || + iContextStatus == RPacketContext::EStatusDeactivating) + { + iWasActive = ETrue; + } + + iPacketContext.NotifyStatusChange(iStatus, iContextStatus); + SetActive(); + return ETrue; + } + +void CContextStatusMonitor::RunL() + { + User::LeaveIfError(iStatus.Int()); + if (iContextStatus == RPacketContext::EStatusActive) + { + iWasActive = ETrue; + } + + if (iContextStatus == RPacketContext::EStatusDeleted) + { + iPacketContext.CancelAsyncRequest(EPacketContextNotifyStatusChange); + iCallback.PrimaryContextDeleted(this); + } + else + { + iPacketContext.NotifyStatusChange(iStatus, iContextStatus); + SetActive(); + } + } + +void CContextStatusMonitor::DoCancel() + { + iPacketContext.CancelAsyncRequest(EPacketContextNotifyStatusChange); + } + +TInt CContextStatusMonitor::RunError(TInt aError) + { + iCallback.ContextMonitoringError(this, aError); + return KErrNone; + } + + +CPdpContentionManager* CPdpContentionManager::NewL(const ESock::CTierManagerBase& aTierManager, RPacketService& aPacketService) + { + CPdpContentionManager* self = new (ELeave) CPdpContentionManager(aTierManager); + CleanupStack::PushL(self); + self->ConstructL(aPacketService); + CleanupStack::Pop(self); + return self; + } + +CPdpContentionManager::CPdpContentionManager(const ESock::CTierManagerBase& aTierManager): +CContentionManager(aTierManager) + { + } + +CPdpContentionManager::~CPdpContentionManager() + { + delete iPrimaryContextsMonitor; + } + +void CPdpContentionManager::ConstructL(RPacketService& aPacketService) + { + iPrimaryContextsMonitor = new (ELeave) CPrimaryContextsMonitor(aPacketService, *this); + } + +void CPdpContentionManager::StartMonitoringL() + { + if (iPrimaryContextsMonitor) + { + iPrimaryContextsMonitor->StartL(); + } + } + +void CPdpContentionManager::ContentionResolved(const TContentionRequestItem& aContentionRequest, TBool aResult) + { + CPdpMetaConnectionProvider* pdpMcpr = static_cast(aContentionRequest.iMcpr); + + pdpMcpr->ContentionResolved(aContentionRequest.iPendingCprId, aResult); + } + +void CPdpContentionManager::ContentionOccured(ESock::CMetaConnectionProviderBase& aMcpr) + { + CPdpMetaConnectionProvider& pdpMcpr = static_cast(aMcpr); + + pdpMcpr.ContentionOccured(); + } + +void CPdpContentionManager::ReportContentionAvailabilityStatus(ESock::CMetaConnectionProviderBase& aMcpr, const ESock::TAvailabilityStatus& aStatus) const + { + CPdpMetaConnectionProvider& pdpMcpr = static_cast(aMcpr); + + pdpMcpr.ReportContentionAvailabilityStatus(aStatus); + } +