diff -r 6b1d113cdff3 -r 6638e7f4bd8f cellularsrvapitest/datatransferhaitest/common/src/DataDealer.cpp --- a/cellularsrvapitest/datatransferhaitest/common/src/DataDealer.cpp Mon May 03 13:37:20 2010 +0300 +++ b/cellularsrvapitest/datatransferhaitest/common/src/DataDealer.cpp Thu May 06 15:10:38 2010 +0100 @@ -1,341 +1,341 @@ -/* -* Copyright (c) 2005-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 -#include -#include - -#include "DataDealer.h" -#include "DataDealerParams.h" - -// We cannot use UIDs that are reserved from Symbian (neither protected -// nor unprotected) since Publish&Subscribe properties require that -// the running process they are defined in has the secure id that matches -// the id of the P&S property (secure id check is not made for legacy UIDs -// which are < 0x10273357). -// So we use a UID from development range: 0x00000000 - 0x0FFFFFFF -const TUid KPropertyCategory = { 0x077A5355 }; -//const TUid KPropertyCategory = { 0xA00023E0 }; - -// Time to wait before re-checking property values -const TInt KWaitForPropertyTime( 100000 ); - - -const TUid KDataDealerImplUID1 = {0xA00023E2}; - -/** - * @param aProducer Set to ETrue if this is a producer instance. - * @param aKey The Publish&Subscribe key that is used for data passing. - */ -CDataDealer* CDataDealer::NewL( const TBool aProducer, const TUint aKey ) - { - TDataDealerParams params( aProducer, aKey ); - - TAny* implementation = - REComSession::CreateImplementationL( KDataDealerImplUID1, - _FOFF( CDataDealer, iDtorID ), - ¶ms ); - - - CDataDealer* self = new (ELeave) CDataDealer( params.iProducer, params.iKey ); - CleanupStack::PushL(self); - self->ConstructL(); - CleanupStack::Pop(self); - - return self; - } - -CDataDealer::~CDataDealer() - { - // wait that the property is empty (= data consumed) - TRAPD( err, WaitForConsumerL() ); - if( err != KErrNone ) - { - // WaitForConsumerL error! - } - - // The producer is responsible of creating and destroying the property - if( iProducer ) - { - // CDataDealer: This is a producer instance, delete the P&S property - TInt err = iProperty.Delete( KPropertyCategory, iKey ); - if( err != KErrNone ) - { - // CDataDealer: Could not delete property - } - iProperty.Close(); - } - - - // Notify the ECom server that we released one implementation of some - // DLL. When the counter hits zero ECom server may unload the DLL. - REComSession::DestroyedImplementation( iDtorID ); - } - -void CDataDealer::ConstructL() - { - // The producer is responsible of creating and destroying the property - if( iProducer ) - { - // CDataDealer: This is a producer instance, create the P&S property - TInt err = iProperty.Define( KPropertyCategory, - iKey, - RProperty::EByteArray, - iPropertySize ); - if( err == KErrAlreadyExists ) - { - // Property already exists. Clear contents. - User::LeaveIfError( iProperty.Set( KPropertyCategory, iKey, KNullDesC8 ) ); - } - else if( err != KErrNone ) - { - // Could not create pub&sub property - User::Leave( err ); - } - } - // Consumer waits that the property is created by producer - else - { - WaitForPropertyToBeCreatedL(); - } - } - - -/** - * Consumer uses this to wait for the property to be created by producer - * when DataDealer is constructed. - */ -void CDataDealer::WaitForPropertyToBeCreatedL() - { - const TInt KTempPropertyValueLength(2); - TBuf8 tempValue; - - TInt err = iProperty.Get( KPropertyCategory, iKey, tempValue ); - while( err == KErrNotFound ) - { - // Property did not created yet, wait - const TInt KWaitForProperty( 500000 ); - // User::After here is not a critical error. It is used here to wait for the RProperty instance - // to be created. The best solution would be to use RProperty notifications to do that but it is - // currently too heavy considering how DataDealer is used: in testing context without any UI - User::After( KWaitForProperty ); - err = iProperty.Get( KPropertyCategory, iKey, tempValue ); - } - if( err != KErrNone && err != KErrOverflow ) - { - // Unexpected error! - User::Leave( err ); - } - } - -CDataDealer::CDataDealer( const TBool aProducer, const TUint aKey ) -: CBase(), - // Use KMaxPropertySize as default size to ensure "real time" setting of a value - iPropertySize( RProperty::KMaxPropertySize ), - iProducer( aProducer ), - iKey( aKey ), - iDtorID() - { - } - -/** - * Produce data to the data storage defined in the constructor. - */ -void CDataDealer::ProduceDataL( const TDesC8& aData ) - { - // "CDataDealer::ProduceDataL: %S", &aData - - // Check for misuse - if( !iProducer ) User::Leave( KErrNotSupported ); - - for( TInt i(0); i < aData.Length(); i += iPropertySize ) - { - // wait that the property is empty (= data consumed) - WaitForConsumerL(); - - // Then write data block-by-block - TPtrC8 dataBlock( KNullDesC8 ); - if( ( i + iPropertySize ) < aData.Length() ) - dataBlock.Set( aData.Mid( i, iPropertySize ) ); - else - dataBlock.Set( aData.Mid( i, aData.Length() - i ) ); - // Write single block - User::LeaveIfError( iProperty.Set( KPropertyCategory, iKey, dataBlock ) ); - } - } - -/** - * Wait synchronously until the consumer has deleted the data we have produced. - * Used by data dealer that is producing data. - */ -void CDataDealer::WaitForConsumerL() - { - const TInt KTempPropertyValueLength(2); - TBuf8 tempValue; - - TInt err = iProperty.Get( KPropertyCategory, iKey, tempValue ); - - if( err != KErrOverflow && err != KErrNone ) - { - // un-expected error - // CDataDealer: Could not get property value. - User::Leave( err ); - } - - while( err == KErrOverflow || tempValue != KNullDesC8 ) - { - // Not empty yet, wait - - // User::After here is not a critical error. It is used here to wait for the RProperty instance - // to be created. The best solution would be to use RProperty notifications to do that but it is - // currently too heavy considering how DataDealer is used: in testing context without any UI - User::After( KWaitForPropertyTime ); // CSI: 92 # - err = iProperty.Get( KPropertyCategory, iKey, tempValue ); - } - - } - -/** - * @param aData On return contains a pointer to heap descriptor containing the received data. - */ -void CDataDealer::ConsumeDataL( HBufC8*& aData ) - { - // Check for misuse - if( iProducer ) User::Leave( KErrNotSupported ); - - TInt err( KErrNone ); - HBufC8* data = HBufC8::NewLC( iPropertySize ); - TPtr8 dataPtr = data->Des(); - const TInt KMinHBufCLength(1); - HBufC8* wholeData = HBufC8::NewLC( KMinHBufCLength ); - - // Loop until the property is destroyed by the producer - for( TInt i(0); err != KErrNotFound; ) - { - // check if the property exists and has data - err = iProperty.Get( KPropertyCategory, iKey, dataPtr ); - TBool empty = ( dataPtr == KNullDesC8 ); - if( err == KErrNone ) - { - if( empty ) - { - // Property empty, cannot consume, wait - // If the property exists but is empty, wait for data - // User::After here is not a critical error. It is used here to wait for the RProperty instance - // to be created. The best solution would be to use RProperty notifications to do that but it is - // currently too heavy considering how DataDealer is used: in testing context without any UI - User::After( KWaitForPropertyTime ); // CSI: 92 # - } - else - { - // Clear the property... - User::LeaveIfError( iProperty.Set( KPropertyCategory, iKey, KNullDesC8 ) ); - - // Append the retrieved data to the buffer that will be returned - // CDataDealer: Data ready, consumed - HBufC8* newWholeData = wholeData->ReAllocL( wholeData->Length() + iPropertySize ); - CleanupStack::Pop( wholeData ); - wholeData = newWholeData; - CleanupStack::PushL( wholeData ); - wholeData->Des().Append( *data ); - // Clear the buffer - dataPtr.Zero(); - - // ..and set new storage index - i += iPropertySize; - } - } - // If the property is not found, it means that there is (no more) data to be consumed available - else if( err != KErrNotFound ) - { - // CDataDealer: Could not open the property. - User::Leave( err ); - } - } - - // "CDataDealer::ConsumeDataL: %S", wholeData - // Ownership transferred - CleanupStack::Pop( wholeData ); - aData = wholeData; - CleanupStack::PopAndDestroy( data ); - } - -/** - * Consume data that is produced to the data storage defined in the constructor. - * @param aData On return contains a pointer to heap descriptor containing the received data. - * @param aMaxSize The maximum size of the data block. - * @param aMore ETrue if there is more data to be consumed. - */ -void CDataDealer::ConsumeDataL( HBufC8*& aData, const TInt aMaxSize, TBool& aMore ) - { - // Check for misuse - if( iProducer ) User::Leave( KErrNotSupported ); - - HBufC8* data = HBufC8::NewLC( iPropertySize ); - TPtr8 dataPtr = data->Des(); - - // Loop until data is produced to the property - TInt err( KErrNone ); - while( err != KErrNotFound && dataPtr.Length() == 0 ) - { - // check if the property exists and has data - err = iProperty.Get( KPropertyCategory, iKey, dataPtr ); - TBool empty = ( dataPtr == KNullDesC8 ); - - if( err == KErrNone ) - { - if( empty ) - { - // If the property exists but is empty, wait for data - // User::After here is not a critical error. It is used here to wait for the RProperty instance - // to be created. The best solution would be to use RProperty notifications to do that but it is - // currently too heavy considering how DataDealer is used: in testing context without any UI - User::After( KWaitForPropertyTime ); // CSI: 92 # - } - else if( dataPtr.Length() > aMaxSize ) - { - // Too long data (%i, max: %i): consuming only the first block", dataPtr.Length(), aMaxSize - // Consuming only the first aMaxSize characters; save the rest of the data to the property - iProperty.Set( KPropertyCategory, iKey, dataPtr.Right( dataPtr.Length() - aMaxSize ) ); - // Take the first aMaxSize characters and ignore the rest - data->Des().Copy( dataPtr.Left( aMaxSize ) ); - } - else - { - // Clear the property... - User::LeaveIfError( iProperty.Set( KPropertyCategory, iKey, KNullDesC8 ) ); - } - } - // If the property is not found, it means that there is (no more) data to be consumed available - else if( err == KErrNotFound ) - { - // CDataDealer: No more data in the property (KErrNotFound) - aMore = EFalse; - } - else - { - // CDataDealer: Could not open the property. - aMore = EFalse; - User::Leave( err ); - } - } - - CleanupStack::Pop( data ); - aData = data; - } - +/* +* Copyright (c) 2005-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 +#include +#include + +#include "DataDealer.h" +#include "DataDealerParams.h" + +// We cannot use UIDs that are reserved from Symbian (neither protected +// nor unprotected) since Publish&Subscribe properties require that +// the running process they are defined in has the secure id that matches +// the id of the P&S property (secure id check is not made for legacy UIDs +// which are < 0x10273357). +// So we use a UID from development range: 0x00000000 - 0x0FFFFFFF +const TUid KPropertyCategory = { 0x077A5355 }; +//const TUid KPropertyCategory = { 0xA00023E0 }; + +// Time to wait before re-checking property values +const TInt KWaitForPropertyTime( 100000 ); + + +const TUid KDataDealerImplUID1 = {0xA00023E2}; + +/** + * @param aProducer Set to ETrue if this is a producer instance. + * @param aKey The Publish&Subscribe key that is used for data passing. + */ +CDataDealer* CDataDealer::NewL( const TBool aProducer, const TUint aKey ) + { + TDataDealerParams params( aProducer, aKey ); + + TAny* implementation = + REComSession::CreateImplementationL( KDataDealerImplUID1, + _FOFF( CDataDealer, iDtorID ), + ¶ms ); + + + CDataDealer* self = new (ELeave) CDataDealer( params.iProducer, params.iKey ); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + + return self; + } + +CDataDealer::~CDataDealer() + { + // wait that the property is empty (= data consumed) + TRAPD( err, WaitForConsumerL() ); + if( err != KErrNone ) + { + // WaitForConsumerL error! + } + + // The producer is responsible of creating and destroying the property + if( iProducer ) + { + // CDataDealer: This is a producer instance, delete the P&S property + TInt err = iProperty.Delete( KPropertyCategory, iKey ); + if( err != KErrNone ) + { + // CDataDealer: Could not delete property + } + iProperty.Close(); + } + + + // Notify the ECom server that we released one implementation of some + // DLL. When the counter hits zero ECom server may unload the DLL. + REComSession::DestroyedImplementation( iDtorID ); + } + +void CDataDealer::ConstructL() + { + // The producer is responsible of creating and destroying the property + if( iProducer ) + { + // CDataDealer: This is a producer instance, create the P&S property + TInt err = iProperty.Define( KPropertyCategory, + iKey, + RProperty::EByteArray, + iPropertySize ); + if( err == KErrAlreadyExists ) + { + // Property already exists. Clear contents. + User::LeaveIfError( iProperty.Set( KPropertyCategory, iKey, KNullDesC8 ) ); + } + else if( err != KErrNone ) + { + // Could not create pub&sub property + User::Leave( err ); + } + } + // Consumer waits that the property is created by producer + else + { + WaitForPropertyToBeCreatedL(); + } + } + + +/** + * Consumer uses this to wait for the property to be created by producer + * when DataDealer is constructed. + */ +void CDataDealer::WaitForPropertyToBeCreatedL() + { + const TInt KTempPropertyValueLength(2); + TBuf8 tempValue; + + TInt err = iProperty.Get( KPropertyCategory, iKey, tempValue ); + while( err == KErrNotFound ) + { + // Property did not created yet, wait + const TInt KWaitForProperty( 500000 ); + // User::After here is not a critical error. It is used here to wait for the RProperty instance + // to be created. The best solution would be to use RProperty notifications to do that but it is + // currently too heavy considering how DataDealer is used: in testing context without any UI + User::After( KWaitForProperty ); + err = iProperty.Get( KPropertyCategory, iKey, tempValue ); + } + if( err != KErrNone && err != KErrOverflow ) + { + // Unexpected error! + User::Leave( err ); + } + } + +CDataDealer::CDataDealer( const TBool aProducer, const TUint aKey ) +: CBase(), + // Use KMaxPropertySize as default size to ensure "real time" setting of a value + iPropertySize( RProperty::KMaxPropertySize ), + iProducer( aProducer ), + iKey( aKey ), + iDtorID() + { + } + +/** + * Produce data to the data storage defined in the constructor. + */ +void CDataDealer::ProduceDataL( const TDesC8& aData ) + { + // "CDataDealer::ProduceDataL: %S", &aData + + // Check for misuse + if( !iProducer ) User::Leave( KErrNotSupported ); + + for( TInt i(0); i < aData.Length(); i += iPropertySize ) + { + // wait that the property is empty (= data consumed) + WaitForConsumerL(); + + // Then write data block-by-block + TPtrC8 dataBlock( KNullDesC8 ); + if( ( i + iPropertySize ) < aData.Length() ) + dataBlock.Set( aData.Mid( i, iPropertySize ) ); + else + dataBlock.Set( aData.Mid( i, aData.Length() - i ) ); + // Write single block + User::LeaveIfError( iProperty.Set( KPropertyCategory, iKey, dataBlock ) ); + } + } + +/** + * Wait synchronously until the consumer has deleted the data we have produced. + * Used by data dealer that is producing data. + */ +void CDataDealer::WaitForConsumerL() + { + const TInt KTempPropertyValueLength(2); + TBuf8 tempValue; + + TInt err = iProperty.Get( KPropertyCategory, iKey, tempValue ); + + if( err != KErrOverflow && err != KErrNone ) + { + // un-expected error + // CDataDealer: Could not get property value. + User::Leave( err ); + } + + while( err == KErrOverflow || tempValue != KNullDesC8 ) + { + // Not empty yet, wait + + // User::After here is not a critical error. It is used here to wait for the RProperty instance + // to be created. The best solution would be to use RProperty notifications to do that but it is + // currently too heavy considering how DataDealer is used: in testing context without any UI + User::After( KWaitForPropertyTime ); // CSI: 92 # + err = iProperty.Get( KPropertyCategory, iKey, tempValue ); + } + + } + +/** + * @param aData On return contains a pointer to heap descriptor containing the received data. + */ +void CDataDealer::ConsumeDataL( HBufC8*& aData ) + { + // Check for misuse + if( iProducer ) User::Leave( KErrNotSupported ); + + TInt err( KErrNone ); + HBufC8* data = HBufC8::NewLC( iPropertySize ); + TPtr8 dataPtr = data->Des(); + const TInt KMinHBufCLength(1); + HBufC8* wholeData = HBufC8::NewLC( KMinHBufCLength ); + + // Loop until the property is destroyed by the producer + for( TInt i(0); err != KErrNotFound; ) + { + // check if the property exists and has data + err = iProperty.Get( KPropertyCategory, iKey, dataPtr ); + TBool empty = ( dataPtr == KNullDesC8 ); + if( err == KErrNone ) + { + if( empty ) + { + // Property empty, cannot consume, wait + // If the property exists but is empty, wait for data + // User::After here is not a critical error. It is used here to wait for the RProperty instance + // to be created. The best solution would be to use RProperty notifications to do that but it is + // currently too heavy considering how DataDealer is used: in testing context without any UI + User::After( KWaitForPropertyTime ); // CSI: 92 # + } + else + { + // Clear the property... + User::LeaveIfError( iProperty.Set( KPropertyCategory, iKey, KNullDesC8 ) ); + + // Append the retrieved data to the buffer that will be returned + // CDataDealer: Data ready, consumed + HBufC8* newWholeData = wholeData->ReAllocL( wholeData->Length() + iPropertySize ); + CleanupStack::Pop( wholeData ); + wholeData = newWholeData; + CleanupStack::PushL( wholeData ); + wholeData->Des().Append( *data ); + // Clear the buffer + dataPtr.Zero(); + + // ..and set new storage index + i += iPropertySize; + } + } + // If the property is not found, it means that there is (no more) data to be consumed available + else if( err != KErrNotFound ) + { + // CDataDealer: Could not open the property. + User::Leave( err ); + } + } + + // "CDataDealer::ConsumeDataL: %S", wholeData + // Ownership transferred + CleanupStack::Pop( wholeData ); + aData = wholeData; + CleanupStack::PopAndDestroy( data ); + } + +/** + * Consume data that is produced to the data storage defined in the constructor. + * @param aData On return contains a pointer to heap descriptor containing the received data. + * @param aMaxSize The maximum size of the data block. + * @param aMore ETrue if there is more data to be consumed. + */ +void CDataDealer::ConsumeDataL( HBufC8*& aData, const TInt aMaxSize, TBool& aMore ) + { + // Check for misuse + if( iProducer ) User::Leave( KErrNotSupported ); + + HBufC8* data = HBufC8::NewLC( iPropertySize ); + TPtr8 dataPtr = data->Des(); + + // Loop until data is produced to the property + TInt err( KErrNone ); + while( err != KErrNotFound && dataPtr.Length() == 0 ) + { + // check if the property exists and has data + err = iProperty.Get( KPropertyCategory, iKey, dataPtr ); + TBool empty = ( dataPtr == KNullDesC8 ); + + if( err == KErrNone ) + { + if( empty ) + { + // If the property exists but is empty, wait for data + // User::After here is not a critical error. It is used here to wait for the RProperty instance + // to be created. The best solution would be to use RProperty notifications to do that but it is + // currently too heavy considering how DataDealer is used: in testing context without any UI + User::After( KWaitForPropertyTime ); // CSI: 92 # + } + else if( dataPtr.Length() > aMaxSize ) + { + // Too long data (%i, max: %i): consuming only the first block", dataPtr.Length(), aMaxSize + // Consuming only the first aMaxSize characters; save the rest of the data to the property + iProperty.Set( KPropertyCategory, iKey, dataPtr.Right( dataPtr.Length() - aMaxSize ) ); + // Take the first aMaxSize characters and ignore the rest + data->Des().Copy( dataPtr.Left( aMaxSize ) ); + } + else + { + // Clear the property... + User::LeaveIfError( iProperty.Set( KPropertyCategory, iKey, KNullDesC8 ) ); + } + } + // If the property is not found, it means that there is (no more) data to be consumed available + else if( err == KErrNotFound ) + { + // CDataDealer: No more data in the property (KErrNotFound) + aMore = EFalse; + } + else + { + // CDataDealer: Could not open the property. + aMore = EFalse; + User::Leave( err ); + } + } + + CleanupStack::Pop( data ); + aData = data; + } +