diff -r 000000000000 -r dfb7c4ff071f commsfwsupport/commselements/serverden/src/sd_mintercept.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/commsfwsupport/commselements/serverden/src/sd_mintercept.cpp Thu Dec 17 09:22:25 2009 +0200 @@ -0,0 +1,963 @@ +// Copyright (c) 2008-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: +// messageintercept.cpp +// +// + +/** + @file +*/ + +#include "sd_mintercept.h" +#include +#include +#include +#include + + +#ifdef _DEBUG +// Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module +// (if it could happen through user error then you should give it an explicit, documented, category + code) +_LIT(KSpecAssert_ElemSvrDenMIntC, "ElemSvrDenMIntC"); +#endif + +using namespace Messages; +using namespace Meta; +using namespace NetInterfaces; +using namespace Elements; +using namespace Den; + +_LIT(KMessageInterceptPanic, "message intercept panic"); +#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE +_LIT(KInitalisationTimePanic, "Panic during initialisation of message intercept"); +#endif //#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + +// Constants +//---------- +#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE +const TUint KMaxExpectedRegisteredNodes = 32; +const TUint KMaxExpectedPatterns = 32; +#endif //#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + +#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE +// Helper function for comparing two TMessageId +//--------------------------------------------- +TInt CompareTMessageId(const TNodeSignal::TMessageId& aMsg1, const TNodeSignal::TMessageId& aMsg2) + { + // return 0 is the objects are equal + // return negative value if first is less than second + // return positive if first is greater than second + if (aMsg1.Realm()==aMsg2.Realm()) + { + return aMsg1.MessageId() - aMsg2.MessageId(); + } + return aMsg1.Realm() - aMsg2.Realm(); + } +#endif //#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + +// AFallibleTestControl (control interface) +//----------------------------------------- +void AFallibleTestControl::InitL(const RArray& aArray) + { +#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + //copying the memory, not the array as its lifetime is temporary + iFallibleMessages.Reset(); + TLinearOrder order(CompareTMessageId); + for (TInt i=0; i(Dll::Tls()); + __ASSERT_DEBUG(!previous || !aContext, User::Panic(KSpecAssert_ElemSvrDenMIntC, 1)); + Dll::SetTls(aContext); + return previous; + } + +//Only to be used by CCommonWorkerThread +CMessageInterceptRegister& CMessageInterceptRegister::GetGlobal() + { + CMessageInterceptRegister* context = reinterpret_cast(Dll::Tls()); + __ASSERT_DEBUG(context, User::Panic(KSpecAssert_ElemSvrDenMIntC, 2)); + return *context; + } + +TInt CMessageInterceptRegister::MatchIncomingEvent(const TEventSummaryTriple& aEvent, TAction& aAction) + { +#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + // Fetch the current expression (from the current pattern) that we are waiting on next + const TEventExpression& expression = iPatternList.CurrentPattern().CurrentExpression(); + + // First need to look up sender and receiver in the node register + // as both need to have been registered to make anything of the incoming event + TNodeSpecifier senderNode; + TNodeSpecifier receiverNode; + + TInt errorTx = FetchRegisteredNodeInfo(aEvent.SenderId(), senderNode); + TInt errorRx = FetchRegisteredNodeInfo(aEvent.ReceiverId(), receiverNode); + + TInt matchResult; + + if(errorTx == KErrNone && errorRx == KErrNone) + { + // Create full event info (incoming event info + provider info fetched from node register) + TEventInfo fullEventInfo(senderNode, aEvent.Message(), receiverNode); + + // Compare against current expression we are matching against and return any action if a match + matchResult = CompareEventWithExpression(fullEventInfo, expression); + + // If we matched then advance the list of expressions + if(matchResult == KErrNone) + { + iPatternList.CurrentPattern().Expressions().Advance(); + + // Advance the pattern itself if necessary + if(iPatternList.CurrentPattern().IsComplete()) + { + aAction = iPatternList.CurrentPattern().Action(); + iPatternList.Advance(); + return KErrNone; + } + else + return KErrNotFound; + } + else + return KErrNotFound; + } + else + { + return KErrNotFound; + } +#else + // Fixing unused local variable warnings. + (void)aEvent; + (void)aAction; + + return KErrNotSupported; +#endif //#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + } + + +TInt CMessageInterceptRegister::CompareEventWithExpression( + const TEventInfo& aEvent, + const TEventExpression& aExpression) + { +#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + // Compare MESSAGE type first (quickest test and more often than not only a single test needed) + TBool msgMatch = aExpression.MessageExpression().Compare(aEvent.Message()); + + // If we are already not matched then no use continuing + if(!msgMatch) + { + return KErrNotFound; + } + else + { + // Now compare the SENDER properties against what we are expecting + TBool senderMatch = aExpression.SenderExpression().Compare(aEvent.Sender()); + + // If we aren't matched then no use continuing + if(!senderMatch) + { + return KErrNotFound; + } + else + { + // Firstly do we need to update tag in the node register + if(aExpression.SenderExpression().SetTagOnMatch()) + { + iRegisteredNodeTable.SetNodeTag(aEvent.Sender().Id(), aExpression.SenderExpression().TagToSet()); + } + + // Now compare the RECEIVER + TBool receiverMatch = aExpression.ReceiverExpression().Compare(aEvent.Receiver()); + + // If we aren't matched then no use continuing + if(!receiverMatch) + { + return KErrNotFound; + } + else + { + // Firstly do we need to update tag in the node register + if(aExpression.ReceiverExpression().SetTagOnMatch()) + { + iRegisteredNodeTable.SetNodeTag(aEvent.Receiver().Id(), aExpression.ReceiverExpression().TagToSet()); + } + + // ### COMPLETE MATCH ### + // We have every element so a full match + return KErrNone; + } + } + } +#else + // Fixing unused local variable warnings. + (void)aEvent; + (void)aExpression; + + return KErrNotSupported; +#endif //#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + } + +CMessageInterceptRegister* CMessageInterceptRegister::NewL() + { + CMessageInterceptRegister* self = new(ELeave) CMessageInterceptRegister(); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); + return self; + } + +void CMessageInterceptRegister::ConstructL() + { +#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + // Create the worker lock used to synchronise access to the message intercept register + // We absolutely need it so out of here if we can't create it + TInt error = iSynchronisedUseLock.CreateLocal(); + User::LeaveIfError(error); + + // Resize the node register as we need it + iRegisteredNodeTable.ReserveL(KMaxExpectedRegisteredNodes); + + // Need to make sure we reserve space for at least as many patterns to register + // Don't want to be allocating memory during operation + iPatternList.ReserveL(KMaxExpectedPatterns); + iPatternList.SetOwner(this); +#else + User::Leave(KErrNotSupported); +#endif //#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + } + +/** Look up a previously registered node */ +TInt CMessageInterceptRegister::FetchRegisteredNodeInfo(const TNodeId& aNodeId, TNodeSpecifier& aNode) + { +#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + TInt index = iRegisteredNodeTable.FindNode(aNodeId); + if (index < 0) + { + return index; + } + else + { + aNode = iRegisteredNodeTable[index]; + return KErrNone; + } +#else + // Fixing unused local variable warnings. + (void)aNodeId; + (void)aNode; + + return KErrNotSupported; +#endif //#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + } + +// Destructor +CMessageInterceptRegister::~CMessageInterceptRegister() + { +#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + iRegisteredNodeTable.Reset(); + iPatternList.ResetAndDestroy(); + iSynchronisedUseLock.Close(); + iFallibleMessages.Close(); +#endif//#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + } + +void CMessageInterceptRegister::ResetStatusVariables() + { +#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + iState = EResetState; +#endif //#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + } + +void CMessageInterceptRegister::SetComplete(TAny* aFrom) + { +#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + (void)(aFrom != NULL); //keep compiler happy + __ASSERT_DEBUG(static_cast(aFrom) == static_cast(&iPatternList), User::Panic(KSpecAssert_ElemSvrDenMIntC, 3)); + iState = EPassedState; + COMMONLOG((TWorkerThreadPublicInfo::EMainThread, KECommonServerTag, _L8("Register set complete:"))); +#else + // Fixing unused local variable warnings. + (void)aFrom; +#endif //#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + } + +#ifdef _DEBUG +void CMessageInterceptRegister::PrintAllFallibleMessages() + { +#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + for (TInt i = 0; i < iFallibleMessages.Count(); i++) + { + RDebug::Print( _L("Fallible Message: %d, Id = %d, Realm = %d\n"), i+1, iFallibleMessages[i].MessageId(), + iFallibleMessages[i].Realm()); + } +#endif //#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + } +#endif // _DEBUG + +void CMessageInterceptRegister::RelinguishAccessOperation(TAny* aPtr) + { + CMessageInterceptRegister *obj = reinterpret_cast (aPtr); + __ASSERT_DEBUG(obj, User::Panic(KSpecAssert_ElemSvrDenMIntC, 4)); + obj->RelinquishAccess(); + } + +// EXPORTED + +EXPORT_C NetInterfaces::TInterfaceControl& CMessageInterceptRegister::GetInterfaceControl() + { + CMessageInterceptRegister* context = reinterpret_cast(Dll::Tls()); + __ASSERT_DEBUG(context, User::Panic(KSpecAssert_ElemSvrDenMIntC, 5)); + return *context; + } + +// Enable the register +EXPORT_C TInt CMessageInterceptRegister::Enable() + { +#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + // ### SYNCHRONISE ACCESS ### + WaitForAccess(); + + // Must reset before re-enabling if already been completed + __ASSERT_DEBUG(iState == EResetState, User::Panic(KSpecAssert_ElemSvrDenMIntC, 6)); + iState = ERunningState; + COMMONLOG((TWorkerThreadPublicInfo::EMainThread, KECommonServerTag, _L8("Enabled:"))); + iMode = EPatternMatch; + + // ### SYNCHRONISE ACCESS ### + RelinquishAccess(); + + return KErrNone; +#else + return KErrNotSupported; +#endif // __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + } + +// MPatternMatchControl (control interface) +//----------------------------------------- + +// Reset the message intercept register (but retain the register of nodes, including any tags applied) +EXPORT_C TInt CMessageInterceptRegister::SoftReset() + { +#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + // ### SYNCHRONISE ACCESS ### + WaitForAccess(); + + // Disable the register (stop it intercepting if it is currently) + Disable(); + + // Clear the pattern table + ResetStatusVariables(); + iPatternList.ResetForReuse(ETrue); + COMMONLOG((TWorkerThreadPublicInfo::EMainThread, KECommonServerTag, _L8("Soft reset:"))); + + // ### SYNCHRONISE ACCESS ### + RelinquishAccess(); + + return KErrNone; +#else + return KErrNotSupported; +#endif // __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + } + +// Reset the whole register (patterns and node instances) +EXPORT_C TInt CMessageInterceptRegister::HardReset() + { +#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + // ### SYNCHRONISE ACCESS ### + WaitForAccess(); + + // Disable the register + Disable(); + + // Clear both registers + ResetStatusVariables(); + iPatternList.ResetForReuse(ETrue); + iRegisteredNodeTable.Reset(); + COMMONLOG((TWorkerThreadPublicInfo::EMainThread, KECommonServerTag, _L8("Hard reset:"))); + + // ### SYNCHRONISE ACCESS ### + RelinquishAccess(); + + return KErrNone; +#else + return KErrNotSupported; +#endif // __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + } + +// Allow the client to query the completion of the message pattern matching +EXPORT_C TInt CMessageInterceptRegister::QueryComplete() + { +#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + // ### SYNCHRONISE ACCESS ### + WaitForAccess(); + + TInt state = static_cast(iState); + //COMMONLOG(_L8("Query complete: status:%d"), state); + + // ### SYNCHRONISE ACCESS ### + RelinquishAccess(); + + return state; +#else + return KErrNotSupported; +#endif // __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + } + +EXPORT_C TInt CMessageInterceptRegister::AppendPattern(const CPattern* aPatternToAppend) + { +#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + // ### SYNCHRONISE ACCESS ### + WaitForAccess(); + + // Take ownership by appending to our list of patterns + TRAPD(error, iPatternList.AppendL(aPatternToAppend)); + //COMMONLOG(_L8("Append pattern: err:%d"), error); + + // ### SYNCHRONISE ACCESS ### + RelinquishAccess(); + + return error; +#else + // Fixing unused local variable warnings. + (void)aPatternToAppend; + + return KErrNotSupported; +#endif // __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + } + +// Append a new pattern to the pattern matching schedule +EXPORT_C TInt CMessageInterceptRegister::AppendExpression(const TEventExpression& aExpression) + { +#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + TInt error = KErrNone; + + // ### SYNCHRONISE ACCESS ### + WaitForAccess(); + + // Do we need a new temporary holding list + if(!iExpressionHoldingList) + { + iExpressionHoldingList = new RExpressionList(); + if(!iExpressionHoldingList) + { + User::Panic(KInitalisationTimePanic, KErrNoMemory); + } + + TRAPD(error, iExpressionHoldingList->ReserveDefaultSpaceL()); + if(error != KErrNone) + { + User::Panic(KInitalisationTimePanic, error); + } + } + + // Append our expression to the list + error = iExpressionHoldingList->Append(aExpression); + if(error != KErrNone) + { + User::Panic(KInitalisationTimePanic, error); + } + + //COMMONLOG(_L8("Append expression: err:%d"), error); + + // ### SYNCHRONISE ACCESS ### + RelinquishAccess(); + + return KErrNone; +#else + // Fixing unused local variable warnings. + (void)aExpression; + + return KErrNotSupported; +#endif // __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + } + +EXPORT_C TInt CMessageInterceptRegister::AppendAction(const TAction& aAction) + { +#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + // ### SYNCHRONISE ACCESS ### + WaitForAccess(); + + // Must have a list of expressions that we are terminating with this action + __ASSERT_DEBUG(iExpressionHoldingList, User::Panic(KSpecAssert_ElemSvrDenMIntC, 7)); + __ASSERT_DEBUG(iExpressionHoldingList->Count() > 0, User::Panic(KSpecAssert_ElemSvrDenMIntC, 8)); + TInt error; + CPattern* newPattern = NULL; + TRAP(error, newPattern = CPattern::NewL(*iExpressionHoldingList, aAction)); + if(error == KErrNone) + { + TRAP(error, iPatternList.AppendL(newPattern)); + } + + //COMMONLOG(_L8("Appended action:0x%x ErrorCode:0x%x err:%d"), aAction.Action(), aAction.Error(), error); + + // Refresh the holding store for new expressions + delete iExpressionHoldingList; + iExpressionHoldingList = NULL; + + // ### SYNCHRONISE ACCESS ### + RelinquishAccess(); + + return error; +#else + // Fixing unused local variable warnings. + (void)aAction; + + return KErrNotSupported; +#endif // __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + } + +// Enable the register using the counter +EXPORT_C TInt CMessageInterceptRegister::Enable(const TInt aMsgCount) + { +#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + // ### SYNCHRONISE ACCESS ### + WaitForAccess(); + + Disable(); + ResetStatusVariables(); + + // Must reset before re-enabling if already been completed + __ASSERT_DEBUG(iState == EResetState, User::Panic(KSpecAssert_ElemSvrDenMIntC, 9)); + iState = ERunningState; + iCount = aMsgCount; + iErrInjectedFlag = EFalse; + + COMMONLOG((TWorkerThreadPublicInfo::EMainThread, KECommonServerTag, _L8("Enabled with counter:"))); + + iMode = EFallibleTest; + + // ### SYNCHRONISE ACCESS ### + RelinquishAccess(); + + return KErrNone; +#else + // Fixing unused local variable warnings. + (void)aMsgCount; + + return KErrNotSupported; +#endif //__ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + } + +// Check +EXPORT_C TBool CMessageInterceptRegister::CheckFinished() + { +#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + TBool Result = EFalse; + + // ### SYNCHRONISE ACCESS ### + WaitForAccess(); + + if (iCount > 0) + { + Result = ETrue; + } + + // ### SYNCHRONISE ACCESS ### + RelinquishAccess(); + + return Result; +#else + return EFalse; +#endif //__ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + } + +// MNodeIntercept (interface for nodes in to the register during opertion) +//------------------------------------------------------------------------ + +// Register a newly constructed node +EXPORT_C TInt CMessageInterceptRegister::RegisterNewNode(const TNodeSpecifier& aNodeToRegister) + { +#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + TInt error = KErrNone; + + // Cheaply return if not running + if(!IsRunning()) + return KErrNone; + + // ### SYNCHRONISE ACCESS ### + WaitForAccess(); + + // Yes we need to check again as we were not under the protection of the register's mutex + // when we decided not to cheaply return above + if(IsRunning()) + { + // Something wrong if we already exist in the table + __ASSERT_DEBUG(iRegisteredNodeTable.FindNode(aNodeToRegister.Id()) < 0, User::Panic(KSpecAssert_ElemSvrDenMIntC, 10)); + error = iRegisteredNodeTable.InsertNode(aNodeToRegister); + + //COMMONLOG(_L8("Registered node: 0x%x err:%d"), aNodeToRegister.Id().Ptr(), error); + } + + // ### SYNCHRONISE ACCESS ### + RelinquishAccess(); + + return error; +#else + // Fixing unused local variable warnings. + (void)aNodeToRegister; + + return KErrNotSupported; +#endif //__ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + } + +// Perform message interception on an incoming message +EXPORT_C void CMessageInterceptRegister::QueryMessageInterceptL(const TEventSummaryTriple& aIncomingEvent) + { +#ifdef __ELEMENTS_MESSAGE_INTERCEPT_ACTIVE + TAction resultingAction; + + // Cheaply return if not running + if(!IsRunning()) + return; + + switch (iMode) + { + case EFallibleTest: + { + // Perform message interception on an incoming message for testing all fallible messages + + // ### SYNCHRONISE ACCESS ### + WaitForAccess(); + CleanupStack::PushL(TCleanupItem(RelinguishAccessOperation, this)); + + if (iErrInjectedFlag) + { + CleanupStack::PopAndDestroy(); // RelinquishAccess() is called + return; // Ignore error propagation messages + } + + // Ignore messages already tested + if (iCount > 0) + { + --iCount; + } + + if (iCount == 0) + { + TLinearOrder order(CompareTMessageId); + if (iFallibleMessages.FindInOrder(aIncomingEvent.Message().MessageId(), order) != KErrNotFound) + { + iErrInjectedFlag = ETrue; + + // TBC Error configured by client + User::Leave(KErrNoMemory); + } + else + { + // set back the counter which is used by CheckFinished + // this tells that the last msg is not a fallible one + iCount = 1; + } + } + CleanupStack::Pop(); // simply pop the TCleanupItem + // ### SYNCHRONISE ACCESS ### + RelinquishAccess(); + } + break; + + case EPatternMatch: + { + TInt error = KErrNotFound; + + // ### SYNCHRONISE ACCESS ### + WaitForAccess(); + + // We must be running at least + // Yes we need to check again as we were not under the protection of the register's mutex + // when we decided not to cheaply return above + if(IsRunning()) + { + // Query if the new event matches the event we are waiting for + // Need to peek inside the sender as NodePtr will fail as sender not necessarily in it own thread + //COMMONLOG(_L8("Event: tx:0x%x msg:%d rx:0x%x err:%d"), aIncomingEvent.SenderId().Ptr(), aIncomingEvent.Message().MessageId().MessageId(), aIncomingEvent.ReceiverId().Ptr(), error); + error = MatchIncomingEvent(aIncomingEvent, resultingAction); + } + + // ### SYNCHRONISE ACCESS ### + RelinquishAccess(); + + // If have found Cause action specified by querying the register or return as expected + if(error == KErrNone) + { + //COMMONLOG(_L8("Executing action:0x%x ErrorCode:0x%x"), resultingAction.Action(), resultingAction.Error()); + resultingAction.ExecuteActionL(); + } + } + break; + + default: + __ASSERT_DEBUG(0, User::Panic(KSpecAssert_ElemSvrDenMIntC, 11)); + break; + } +#else + // Fixing unused local variable warnings. + (void)aIncomingEvent; + + User::Leave(KErrNotSupported); +#endif //__ELEMENTS_MESSAGE_INTERCEPT_ACTIVE +} + + +// RExpressionList +//---------------- +void RExpressionList::Advance() + { + // Can't advance an empty list + __ASSERT_DEBUG(Count(), User::Panic(KSpecAssert_ElemSvrDenMIntC, 12)); + __ASSERT_DEBUG(iCurrentIndex < Count(), User::Panic(KSpecAssert_ElemSvrDenMIntC, 13)); + + COMMONLOG((TWorkerThreadPublicInfo::EMainThread, KECommonServerTag, _L8("Expression list advanced:"))); + + if((++iCurrentIndex) == Count()) + { + __ASSERT_DEBUG(iOwner, User::Panic(KSpecAssert_ElemSvrDenMIntC, 14)); + iOwner->SetComplete(this); + } + } + +void CPattern::SetComplete(TAny* aFrom) + { + (void)(aFrom != NULL); //keep compiler happy + __ASSERT_DEBUG(static_cast(aFrom) == static_cast(&iExpressions), User::Panic(KSpecAssert_ElemSvrDenMIntC, 15)); + iIsComplete = ETrue; + COMMONLOG((TWorkerThreadPublicInfo::EMainThread, KECommonServerTag, _L8("Pattern set complete:"))); + } + + +const TEventExpression& RExpressionList::CurrentExpression() const + { + // Get the current expression + __ASSERT_DEBUG(iCurrentIndex < Count(), User::Panic(KSpecAssert_ElemSvrDenMIntC, 16)); + return this->operator[](iCurrentIndex); + } + +// TMsgExpression +//--------------- +TBool TMsgExpression::Compare(const TNodeSignal& aMessage) const + { + // We consider the messages to be the same if they have the same type id + // ie. they are the same type of message and we don't consider any parameters + return (aMessage.MessageId().MessageId() == iMessageId) && (aMessage.MessageId().Realm() == iRealm); + } + +// RPatternList +//------------- +CPattern& RPatternList::CurrentPattern() + { + // Get the current pattern + __ASSERT_DEBUG(iCurrentIndex < Count(), User::Panic(KSpecAssert_ElemSvrDenMIntC, 17)); + return *(this->operator[](iCurrentIndex)); + } + +void RPatternList::Advance() + { + // Advance the list of expressions which will notify the parent register if necessary + // Shouldn't be trying to advance an empty list + __ASSERT_DEBUG(Count(), User::Panic(KSpecAssert_ElemSvrDenMIntC, 18)); + __ASSERT_DEBUG(iCurrentIndex < Count(), User::Panic(KSpecAssert_ElemSvrDenMIntC, 19)); + + COMMONLOG((TWorkerThreadPublicInfo::EMainThread, KECommonServerTag, _L8("Pattern list advanced:"))); + + if((++iCurrentIndex) == Count()) + { + __ASSERT_DEBUG(iOwner, User::Panic(KSpecAssert_ElemSvrDenMIntC, 20)); + iOwner->SetComplete(this); + } + } + +void RPatternList::ResetForReuse(TBool aSameOwner) + { + ResetAndDestroy(); + iCurrentIndex = 0; + if(!aSameOwner) + { + iOwner = NULL; + } + } + +// CPattern +//--------- +EXPORT_C CPattern* CPattern::NewL(const RExpressionList& aExpressionList, const TAction& aAction) + { + CPattern* self = new(ELeave) CPattern(aExpressionList, aAction); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); + return self; + } + +void CPattern::ConstructL() + { + } + +CPattern::~CPattern() + { + iExpressions.Reset(); + } + +const TEventExpression& CPattern::CurrentExpression() const + { + return iExpressions.CurrentExpression(); + } + +TInt CPattern::AppendExpression(TEventExpression& aExpression) + { + return iExpressions.Append(aExpression); + } + +void CPattern::InitAction(const TAction& aAction) + { + // Simply assign the new action and mark ourselves as now terminated + __ASSERT_DEBUG(!iIsTerminated, User::Panic(KSpecAssert_ElemSvrDenMIntC, 21)); + SetAction(aAction); + iIsTerminated = ETrue; + } + +TBool CPattern::IsTerminated() const + { + return iIsTerminated; + } + +void CPattern::SetAction(const TAction& aAction) + { + iAction = aAction; + } + +// RRegisteredNodeList +//-------------------- +TInt RRegisteredNodeList::SetNodeTag(const TNodeId& aNodeId, TNodeTag aTag) + { + // Lookup the tag in the + TInt index = FindInUnsignedKeyOrder(aNodeId); + + // We are in some sort of trouble if we couldn't find the + if(index < 0) + return index; + else + { + // Set the tag - can't already be tagged + __ASSERT_DEBUG(operator[](index).Tag().Length() == 0, User::Panic(KSpecAssert_ElemSvrDenMIntC, 22)); + operator[](index).SetTag(aTag); + } + + return KErrNone; + } + +TInt RRegisteredNodeList::Compare(const TNodeSpecifier& aLHS, const TNodeSpecifier& aRHS) + { + // How about just being ultra sure that nothing has changed in the world of TCookie + __ASSERT_DEBUG(aLHS.Id().Size() == 12, User::Panic(KSpecAssert_ElemSvrDenMIntC, 23)); + + // Simply compare the cookies + const TUint* LHS = (reinterpret_cast(&(aLHS.Id()))); + const TUint* RHS = (reinterpret_cast(&(aRHS.Id()))); + + if(LHS[0] < RHS[0]) + { + return -1; + } + else if(LHS[0] > RHS[0]) + { + return 1; + } + else if(LHS[1] > RHS[1]) + { + return 1; + } + return 0; + } + + +// TNodeExpression +//---------------- +TBool TNodeExpression::Compare(const TNodeSpecifier& aNode) const + { + TBool areEqual(EFalse); + + switch (iMatchType) + { + case EMatchByInstance: + { + // Compare only on the basis of earier applied identity (descriptor tag) + areEqual = (iMatchTag == aNode.Tag()); + } + break; + + case EMatchByUid: + { + // Compare only on the basis of UID + areEqual = (iUid == aNode.Uid()); + } + break; + + default: + __ASSERT_DEBUG(0, User::Panic(KSpecAssert_ElemSvrDenMIntC, 24)); + break; + } + + return areEqual; + } + +// TAction +//-------- +TInt TAction::ExecuteActionL() + { + // Simply execute the action specified + switch(iAction) + { + case ENoAction: + return KErrNone; + //break; + + case ELeaveAction: + User::Leave(iError); + break; + + case EPanicAction: + User::Panic(KMessageInterceptPanic, iError); + break; + + default: + return KErrArgument; + //break; + } + + // For what its worth + return KErrNone; + } + + +