--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/datacommsserver/esockserver/ssock/ss_DataMonitoringProvider.cpp Thu Dec 17 09:22:25 2009 +0200
@@ -0,0 +1,540 @@
+// Copyright (c) 2006-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:
+// DataMonitoringProvider.cpp
+//
+//
+
+/**
+ @file
+ @internalComponent
+*/
+
+#include <comms-infras/ss_nodemessages.h>
+#include "ss_datamonitoringprovider.h"
+
+#include <comms-infras/ss_log.h>
+
+using namespace ESock;
+using namespace Messages;
+using namespace MeshMachine;
+
+EXPORT_C ADataMonitoringProvider::ADataMonitoringProvider()
+ {
+ }
+
+EXPORT_C void ADataMonitoringProvider::ConstructL()
+ {
+ InsertWrapMarkerL(EReceived);
+ SetNextNotificationThreshold(EReceived);
+ InsertWrapMarkerL(ESent);
+ SetNextNotificationThreshold(ESent);
+ }
+
+EXPORT_C ADataMonitoringProvider::~ADataMonitoringProvider()
+ {
+ TUint requestIdx;
+ TUint requestCount;
+ TNotificationRequest* notificationRequest;
+
+ // Cancel any outstanding received notification requests
+ requestCount = iReceivedNotificationRequests.Count();
+ for(requestIdx=0;requestIdx<requestCount;requestIdx++)
+ {
+ notificationRequest = iReceivedNotificationRequests[requestIdx];
+ if(!notificationRequest->Cancelled())
+ {
+ CDataMonitoringResponder::CancelRequest(notificationRequest->Responder());
+ }
+ }
+ iReceivedNotificationRequests.ResetAndDestroy();
+
+ // Cancel any outstanding sent notification requests
+ requestCount = iSentNotificationRequests.Count();
+ for(requestIdx=0;requestIdx<requestCount;requestIdx++)
+ {
+ notificationRequest = iSentNotificationRequests[requestIdx];
+ if(!notificationRequest->Cancelled())
+ {
+ CDataMonitoringResponder::CancelRequest(notificationRequest->Responder());
+ }
+ }
+ iSentNotificationRequests.ResetAndDestroy();
+ }
+
+/**
+ Responds to client request for immediate notification of the amount of data transferred.
+ @param aResponder The IPC responder for completing the client request
+ @param aClientId Not used
+*/
+EXPORT_C void ADataMonitoringProvider::RequestDataTransferred(CDataMonitoringResponder*& aResponder, TSubSessionUniqueId /* aClientId */)
+ {
+ CDataMonitoringResponder::DataTransferred(aResponder, iDataVolumes.iReceivedBytes, iDataVolumes.iSentBytes);
+ }
+
+/**
+ Cancels an outstanding client request for immediate notification of the amount of data transferred.
+ @param aClientId Not used
+ @note Method has no implementation as completion of request is immediate.
+ @see ADataMonitoringProvider::RequestDataTransferred
+*/
+EXPORT_C void ADataMonitoringProvider::CancelDataTransferredRequest(TSubSessionUniqueId /* aClientId */)
+ {
+ // Nothing to do
+ }
+
+/**
+ Responds to client request for notification of a particular volume of data having been
+ received.
+ @param aResponder The IPC responder for completing the client request
+ @param aDelta An offset from the current volume transferred at which to notify the client
+ @param aReceivedBytes An absolute data volume at which to notify the client
+ @param aClientId Id of the requesting client
+ @note Only one of the parameters aDelta and aReceivedBytes should be set for a given call
+ to this method
+*/
+EXPORT_C void ADataMonitoringProvider::RequestDataReceivedNotification(CDataMonitoringResponder*& aResponder, TUint32 aDelta, TUint32 aReceivedBytes, TSubSessionUniqueId aClientId)
+ {
+ TNotificationRequest* notificationRequest = new TNotificationRequest(aResponder, aClientId);
+ if (!notificationRequest)
+ {
+ CDataMonitoringResponder::Error(aResponder, KErrNoMemory);
+ return;
+ }
+
+ // Ensure this client has not registered before or if it has, any outstanding requests are
+ // marked as cancelled.
+ TInt requestIdx = iReceivedNotificationRequests.Find(notificationRequest, TIdentityRelation<TNotificationRequest>(TNotificationRequest::CompareClientIds));
+ if(requestIdx != KErrNotFound && !iReceivedNotificationRequests[requestIdx]->Cancelled())
+ {
+ delete notificationRequest;
+ CDataMonitoringResponder::Error(aResponder, KErrInUse);
+ return;
+ }
+
+ if(aDelta)
+ { // If the delta was set then set the threshold from that and the current received data volume
+ notificationRequest->SetThresholdFromDelta(iDataVolumes.iReceivedBytes, aDelta);
+ }
+ else
+ { // Otherwise, we were given an absolute value for the threshold
+ if(iDataVolumes.iReceivedBytes >= aReceivedBytes)
+ { // If the required threshold has already been reached then send immediate notification
+ delete notificationRequest;
+ CDataMonitoringResponder::DataReceivedNotification(aResponder, iDataVolumes.iReceivedBytes);
+ return;
+ }
+ else
+ {
+ notificationRequest->SetThreshold(aReceivedBytes);
+ }
+ }
+
+ TInt error = InsertNotificationRequest(notificationRequest, EReceived);
+ if (error!=KErrNone)
+ {
+ delete notificationRequest;
+ CDataMonitoringResponder::Error(aResponder, error);
+ return;
+ }
+
+ SetNextNotificationThreshold(EReceived);
+ }
+
+/**
+ Cancels an outstanding request for data received notification.
+
+ @param aClientId Id of the requesting client
+*/
+EXPORT_C void ADataMonitoringProvider::CancelDataReceivedNotificationRequest(TSubSessionUniqueId aClientId)
+ {
+ // Set up an exemplar request using the specified client ID
+ TNotificationRequest exemplarRequest(NULL, aClientId);
+
+ // Locate the request matching the specified client ID
+ TInt requestIdx = iReceivedNotificationRequests.Find(&exemplarRequest, TIdentityRelation<TNotificationRequest>(TNotificationRequest::CompareClientIds));
+ if(requestIdx != KErrNotFound && !iReceivedNotificationRequests[requestIdx]->Cancelled())
+ {
+ TNotificationRequest* notificationRequest = iReceivedNotificationRequests[requestIdx];
+
+ // Cancel it and complete the client
+ notificationRequest->SetCancelled();
+ CDataMonitoringResponder::CancelRequest(notificationRequest->Responder());
+ }
+ }
+
+/**
+
+*/
+EXPORT_C void ADataMonitoringProvider::RequestDataSentNotification(CDataMonitoringResponder*& aResponder, TUint32 aDelta, TUint32 aSentBytes, TSubSessionUniqueId aClientId)
+ {
+ TNotificationRequest* notificationRequest = new TNotificationRequest(aResponder, aClientId);
+ if (!notificationRequest)
+ {
+ CDataMonitoringResponder::Error(aResponder, KErrNoMemory);
+ return;
+ }
+
+ // Ensure this client has not registered before or if it has, any outstanding requests are
+ // marked as cancelled.
+ TInt requestIdx = iSentNotificationRequests.Find(notificationRequest, TIdentityRelation<TNotificationRequest>(TNotificationRequest::CompareClientIds));
+ if(requestIdx != KErrNotFound && !iSentNotificationRequests[requestIdx]->Cancelled())
+ {
+ delete notificationRequest;
+ CDataMonitoringResponder::Error(aResponder, KErrInUse);
+ return;
+ }
+
+ if(aDelta)
+ { // If the delta was set then set the threshold from that and the current sent data volume
+ notificationRequest->SetThresholdFromDelta(iDataVolumes.iSentBytes, aDelta);
+ }
+ else
+ { // Otherwise, we were given an absolute value for the threshold
+ if(iDataVolumes.iSentBytes >= aSentBytes)
+ { // If the required threshold has already been reached then send immediate notification
+ delete notificationRequest;
+ CDataMonitoringResponder::DataSentNotification(aResponder, iDataVolumes.iSentBytes);
+ return;
+ }
+ else
+ {
+ notificationRequest->SetThreshold(aSentBytes);
+ }
+ }
+
+ TInt error = InsertNotificationRequest(notificationRequest, ESent);
+ if (error!=KErrNone)
+ {
+ delete notificationRequest;
+ CDataMonitoringResponder::Error(aResponder, error);
+ return;
+ }
+
+ SetNextNotificationThreshold(ESent);
+ }
+
+/**
+ Cancels an outstanding request for data sent notification.
+
+ @param aClientId Client id of the request to be cancelled
+*/
+EXPORT_C void ADataMonitoringProvider::CancelDataSentNotificationRequest(TSubSessionUniqueId aClientId)
+ {
+ // Set up an exemplar request using the specified client id
+ TNotificationRequest exemplarRequest(NULL, aClientId);
+
+ // Locate the request matching the specified client id
+ TInt requestIdx = iSentNotificationRequests.Find(&exemplarRequest, TIdentityRelation<TNotificationRequest>(TNotificationRequest::CompareClientIds));
+ if(requestIdx != KErrNotFound && !iSentNotificationRequests[requestIdx]->Cancelled())
+ {
+ TNotificationRequest* notificationRequest = iSentNotificationRequests[requestIdx];
+
+ // Cancel it and complete the client
+ notificationRequest->SetCancelled();
+ CDataMonitoringResponder::CancelRequest(notificationRequest->Responder());
+ }
+ }
+
+/**
+ Call from data to control plane to indicate the received data volume notification
+ threshold has been reached.
+
+ @param aNotificationValue The volume of data received
+*/
+EXPORT_C void ADataMonitoringProvider::DataReceivedNotificationL(TUint32 aNotificationValue)
+ {
+ TNotificationRequest* request;
+
+ // Complete the first request in the array immediately and loop for any
+ // additional same value thresholds in the list.
+ while((iReceivedNotificationRequests.Count() > 0) &&
+ (aNotificationValue >= iReceivedNotificationRequests[0]->Threshold()))
+ {
+ request = iReceivedNotificationRequests[0];
+ if(!request->Cancelled())
+ { // Only complete if the request wasn't cancelled
+ CDataMonitoringResponder::DataReceivedNotification(request->Responder(), aNotificationValue);
+ }
+ iReceivedNotificationRequests.Remove(0);
+ delete request;
+ }
+
+ // If we've completed a wrap marker, we need to do a little housekeeping
+ if(aNotificationValue == KMaxTUint32)
+ {
+ TInt requestCount = iReceivedNotificationRequests.Count();
+ if(requestCount > 0)
+ {
+ // The remaining requests had been marked wrapped. Now we've
+ // completed the wrap marker they need to be 'unmarked' to allow
+ // new wrapped requests to be positioned correctly in the request array
+ for(TUint requestIdx=0;requestIdx<requestCount;requestIdx++)
+ {
+ iReceivedNotificationRequests[requestIdx]->SetWrapped(EFalse);
+ }
+ }
+ InsertWrapMarkerL(EReceived);
+ }
+ SetNextNotificationThreshold(EReceived);
+ }
+
+/**
+ Call from data to control plane to indicate the sent data volume notification
+ threshold has been reached.
+
+ @param aNotificationValue The volume of data received
+*/
+EXPORT_C void ADataMonitoringProvider::DataSentNotificationL(TUint32 aNotificationValue)
+ {
+ TNotificationRequest* request;
+
+ // Complete the first request in the array immediately and loop for any
+ // additional same value thresholds in the list.
+ while((iSentNotificationRequests.Count() > 0) &&
+ (aNotificationValue >= iSentNotificationRequests[0]->Threshold()))
+ {
+ request = iSentNotificationRequests[0];
+ if(!request->Cancelled())
+ { // Only complete if the request wasn't cancelled
+ CDataMonitoringResponder::DataSentNotification(request->Responder(), aNotificationValue);
+ }
+ iSentNotificationRequests.Remove(0);
+ delete request;
+ }
+
+ // If we've completed a wrap marker, we need to do a little housekeeping
+ if(aNotificationValue == KMaxTUint32)
+ {
+ TInt requestCount = iSentNotificationRequests.Count();
+ if(requestCount > 0)
+ {
+ // The remaining requests had been marked wrapped. Now we've
+ // completed the wrap marker they need to be 'unmarked' to allow
+ // new wrapped requests to be positioned correctly in the request array
+ for(TUint requestIdx=0;requestIdx<requestCount;requestIdx++)
+ {
+ iSentNotificationRequests[requestIdx]->SetWrapped(EFalse);
+ }
+ }
+ InsertWrapMarkerL(ESent);
+ }
+ SetNextNotificationThreshold(ESent);
+ }
+
+
+EXPORT_C void ADataMonitoringProvider::CancelClientExtItfRequests(TSubSessionUniqueId aClientId)
+ {
+ CancelDataSentNotificationRequest(aClientId);
+ CancelDataReceivedNotificationRequest(aClientId);
+ }
+
+/**
+ Call from a node activity upon receiving TCFMessage::TDataMonitoringInternal
+ message extension.
+*/
+EXPORT_C void ADataMonitoringProvider::DataNotificationL(const ESock::TCFDataMonitoringNotification::TDataMonitoringNotification& aNotification)
+ {
+ switch(aNotification.iValue1)
+ {
+ case EReceived:
+ DataReceivedNotificationL(aNotification.iValue2);
+ break;
+
+ case ESent:
+ DataSentNotificationL(aNotification.iValue2);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+/**
+
+*/
+void ADataMonitoringProvider::InsertWrapMarkerL(TDataMonitoringDirection aDirection)
+ {
+ TNotificationRequest* wrapMarkerRequest = new(ELeave) TNotificationRequest(NULL, 0);
+
+ wrapMarkerRequest->SetThreshold(KMaxTUint32);
+ wrapMarkerRequest->SetCancelled();
+
+ TInt ret = NotificationRequestArray(aDirection)->InsertInOrder(wrapMarkerRequest, TLinearOrder<TNotificationRequest>(TNotificationRequest::CompareThresholds));
+
+ if(ret != KErrNone)
+ {
+ // If the insert failed then the most likely reason is a KErrAlreadyExists. In any
+ // case, we definitely want to delete the wrap marker. Then we'll try and carry on
+ // as best we can.
+ delete wrapMarkerRequest;
+ }
+ }
+
+
+/**
+
+*/
+RNotificationRequestArray* ADataMonitoringProvider::NotificationRequestArray(TDataMonitoringDirection aDirection)
+ {
+ if(aDirection == EReceived)
+ {
+ return &iReceivedNotificationRequests;
+ }
+ else
+ {
+ return &iSentNotificationRequests;
+ }
+ }
+
+/**
+
+*/
+TInt ADataMonitoringProvider::InsertNotificationRequest(TNotificationRequest* aRequest, TDataMonitoringDirection aDirection)
+ {
+ TInt err;
+ err = NotificationRequestArray(aDirection)->InsertInOrderAllowRepeats(aRequest, TLinearOrder<TNotificationRequest>(TNotificationRequest::CompareThresholds));
+
+ LOG(
+ switch(aDirection)
+ {
+ case ESent:
+ ESockLog::Printf(_L("ADataMonitoringProvider(%08x)::InsertNotificationRequest - Direction: Sending"), this);
+ break;
+ case EReceived:
+ ESockLog::Printf(_L("ADataMonitoringProvider(%08x)::InsertNotificationRequest - Direction: Receiving"), this);
+ break;
+ }
+
+ for(TInt idx=0;idx<NotificationRequestArray(aDirection)->Count();idx++)
+ {
+ TNotificationRequest* req = (*NotificationRequestArray(aDirection))[idx];
+ ESockLog::Printf(_L("\tRequest %d, Threshold %d, Wrapped %d, Client id. 0x%08x"), idx, req->Threshold(), req->Wrapped(), req->ClientId());
+ }
+ )
+
+ return err;
+ }
+
+/**
+*/
+void ADataMonitoringProvider::SetNextNotificationThreshold(TDataMonitoringDirection aDirection)
+ {
+ if(NotificationRequestArray(aDirection)->Count())
+ {
+ switch(aDirection)
+ {
+ case EReceived:
+ iThresholds.iReceivedThreshold = (*NotificationRequestArray(EReceived))[0]->Threshold();
+ break;
+
+ case ESent:
+ iThresholds.iSentThreshold = (*NotificationRequestArray(ESent))[0]->Threshold();
+ break;
+ }
+ }
+ }
+
+
+/**
+
+*/
+EXPORT_C TDataMonitoringConnProvisioningInfo::TDataMonitoringConnProvisioningInfo(TDataVolumes* aDataVolumesPtr, TNotificationThresholds* aThresholdsPtr) :
+ TDataMonitoringProvisioningInfoBase(aDataVolumesPtr, aThresholdsPtr)
+ {
+ }
+
+
+/**
+
+*/
+EXPORT_C TDataMonitoringSubConnProvisioningInfo::TDataMonitoringSubConnProvisioningInfo(TDataVolumes* aDataVolumesPtr, TNotificationThresholds* aThresholdsPtr) :
+ TDataMonitoringProvisioningInfoBase(aDataVolumesPtr, aThresholdsPtr)
+ {
+ }
+
+
+/**
+ Sets the data volume notification threshold given the current transferred volume
+ and a delta from the current amount.
+
+ @param aVolume Current data volume transferred
+ @param aDelta An offset from the current volume of data transferred
+*/
+void TNotificationRequest::SetThresholdFromDelta(TUint32 aVolume, TUint32 aDelta)
+ {
+ TUint64 threshold = aVolume + aDelta;
+
+ if(threshold > KMaxTUint32)
+ {
+ iWrapped = ETrue;
+ iThreshold = threshold - KMaxTUint32;
+ }
+ else
+ {
+ iWrapped = EFalse;
+ iThreshold = threshold;
+ }
+ }
+
+/**
+ Compares two TNotificationRequest objects using their thresholds as the criteria.
+*/
+TInt TNotificationRequest::CompareThresholds(const TNotificationRequest& aFirst, const TNotificationRequest& aSecond)
+ {
+ TUint64 effectiveFirstThreshold = aFirst.iThreshold;
+ TUint64 effectiveSecondThreshold = aSecond.iThreshold;
+
+ if(aFirst.Wrapped()) effectiveFirstThreshold += KMaxTUint32;
+ if(aSecond.Wrapped()) effectiveSecondThreshold += KMaxTUint32;
+
+ if(effectiveFirstThreshold > effectiveSecondThreshold)
+ {
+ return 1;
+ }
+ else if(effectiveFirstThreshold < effectiveSecondThreshold)
+ {
+ return -1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+/**
+ Compares two TNotificationRequest objects using their client ids as the criteria.
+*/
+TBool TNotificationRequest::CompareClientIds(const TNotificationRequest& aFirst, const TNotificationRequest& aSecond)
+ {
+ if(aFirst.ClientId() == aSecond.ClientId())
+ {
+ return ETrue;
+ }
+ else
+ {
+ return EFalse;
+ }
+ }
+
+EXPORT_START_ATTRIBUTE_TABLE_AND_FN(TDataMonitoringProvisioningInfoBase, TDataMonitoringProvisioningInfoBase::iUid, TDataMonitoringProvisioningInfoBase::iId)
+ REGISTER_ATTRIBUTE(TDataMonitoringProvisioningInfoBase, iDataVolumesPtr, TMeta<TDataMonitoringProvisioningInfoBase*>)
+ REGISTER_ATTRIBUTE(TDataMonitoringProvisioningInfoBase, iThresholdsPtr, TMeta<TDataMonitoringProvisioningInfoBase*>)
+END_ATTRIBUTE_TABLE()
+
+EXPORT_START_ATTRIBUTE_TABLE_AND_FN(TDataMonitoringConnProvisioningInfo, TDataMonitoringProvisioningInfoBase::iUid, TDataMonitoringConnProvisioningInfo::iId)
+END_ATTRIBUTE_TABLE_BASE(TDataMonitoringProvisioningInfoBase, 0)
+
+EXPORT_START_ATTRIBUTE_TABLE_AND_FN(TDataMonitoringSubConnProvisioningInfo, TDataMonitoringProvisioningInfoBase::iUid, TDataMonitoringSubConnProvisioningInfo::iId)
+END_ATTRIBUTE_TABLE_BASE(TDataMonitoringProvisioningInfoBase, 0)
+