diff -r 000000000000 -r ba25891c3a9e ncdengine/provider/server/src/ncdnodelink.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ncdengine/provider/server/src/ncdnodelink.cpp Thu Dec 17 08:51:10 2009 +0200 @@ -0,0 +1,671 @@ +/* +* Copyright (c) 2006 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: Implements CNcdNodeLink class +* +*/ + + +#include "ncdnodelink.h" +#include "ncdnodeimpl.h" +#include "catalogssession.h" +#include "catalogsbasemessage.h" +#include "ncdnodefunctionids.h" +#include "ncdnodeclassids.h" +#include "ncdnodeidentifier.h" +#include "ncdproviderdefines.h" +#include "catalogsconstants.h" +#include "ncd_pp_entityref.h" +#include "catalogsdebug.h" +#include "catalogsutils.h" + + +CNcdNodeLink::CNcdNodeLink( CNcdNode& aNode, + NcdNodeClassIds::TNcdNodeClassId aClassId ) +: CCatalogsCommunicable(), + iClassId( aClassId ), + iNode( aNode ), + iLinkDownloadTime( KMinTInt64 ) + { + } + +void CNcdNodeLink::ConstructL() + { + iParentIdentifier = CNcdNodeIdentifier::NewL(); + iRequestParentIdentifier = CNcdNodeIdentifier::NewL(); + iMetaDataIdentifier = CNcdNodeIdentifier::NewL(); + iTimeStamp = KNullDesC().AllocL(); + iCatalogsSourceName = KNullDesC().AllocL(); + iServerUri = KNullDesC().AllocL(); + iRemoteUri = KNullDesC().AllocL(); + iMetadataTimeStamp = KNullDesC().AllocL(); + } + +CNcdNodeLink::~CNcdNodeLink() + { + DLTRACEIN(("")); + + // Do not delete node here because this link does not own it. + + delete iParentIdentifier; + iParentIdentifier = NULL; + + delete iRequestParentIdentifier; + iRequestParentIdentifier = NULL; + + delete iMetaDataIdentifier; + iMetaDataIdentifier = NULL; + + delete iTimeStamp; + iTimeStamp = NULL; + + delete iCatalogsSourceName; + iCatalogsSourceName = NULL; + + delete iServerUri; + iServerUri = NULL; + + delete iRemoteUri; + iRemoteUri = NULL; + + DeletePtr( iMetadataTimeStamp ); + iQueries.Close(); + DLTRACEOUT(("")); + } + + +NcdNodeClassIds::TNcdNodeClassId CNcdNodeLink::ClassId() const + { + return iClassId; + } + + +const TDesC& CNcdNodeLink::Timestamp() const + { + return *iTimeStamp; + } + +const TDesC& CNcdNodeLink::ServerUri() const + { + return *iServerUri; + } + +void CNcdNodeLink::SetServerUriL( const TDesC& aServerUri ) + { + AssignDesL( iServerUri, aServerUri ); + } + +const TDesC& CNcdNodeLink::RemoteUri() const + { + return *iRemoteUri; + } + +MNcdPreminetProtocolEntityRef::TDescription CNcdNodeLink::Description() const + { + return iDescription; + } + +TInt CNcdNodeLink::ValidUntilDelta() const + { + return iValidUntilDelta; + } + +void CNcdNodeLink::SetValidUntilDelta( TInt aValidUntilDelta ) + { + iValidUntilDelta = aValidUntilDelta; + iLinkDownloadTime.HomeTime(); + } + +TBool CNcdNodeLink::ValidUntilAutoUpdate() const + { + return iValidUntilAutoUpdate; + } + + +const CNcdNodeIdentifier& CNcdNodeLink::ParentIdentifier() const + { + // Parent identifier contains always at least the empty values. + return *iParentIdentifier; + } + +void CNcdNodeLink::SetParentIdentifierL( + const CNcdNodeIdentifier& aParentIdentifier ) + { + CNcdNodeIdentifier* newParent = + CNcdNodeIdentifier::NewLC( aParentIdentifier ); + + // Also set the request parent to correspond the same new identifier. + // Notice that if the user wants these two differ. The request parent + // identifier has to be reset after this function has been called. + CNcdNodeIdentifier* newRequestParent = + CNcdNodeIdentifier::NewLC( aParentIdentifier ); + + delete iRequestParentIdentifier; + iRequestParentIdentifier = newRequestParent; + CleanupStack::Pop( newRequestParent ); + + delete iParentIdentifier; + iParentIdentifier = newParent; + CleanupStack::Pop( newParent ); + } + + +const CNcdNodeIdentifier& CNcdNodeLink::RequestParentIdentifier() const + { + // Parent identifier contains always at least the empty values. + return *iRequestParentIdentifier; + } + +void CNcdNodeLink::SetRequestParentIdentifierL( + const CNcdNodeIdentifier& aRequestParentIdentifier ) + { + CNcdNodeIdentifier* newParent = + CNcdNodeIdentifier::NewL( aRequestParentIdentifier ); + delete iRequestParentIdentifier; + iRequestParentIdentifier = newParent; + } + + +TTime CNcdNodeLink::LinkDownloadTime() const + { + return iLinkDownloadTime; + } + +TTime CNcdNodeLink::ExpiredTime() const + { + DLTRACEIN(("")); + + // The expired time is the min value as default. + // Then if the node data has not actually been loaded + // this value is returned. + TTime expired( KMinTInt64 ); + + if ( ValidUntilDelta() == NcdProviderDefines::KNeverExpires ) + { + // Because the delta value is set to never expire + // value, the expire time should be as large as + // possible + DLINFO(("Delta was set to never expire. Largest expire time.")); + expired = KMaxTInt64; + } + else if ( LinkDownloadTime() != KMinTInt64 ) + { + // The expiration time can be calculated because + // the link has been downloaded and the delta value + // has been given and it is not never expire value. + DLINFO(("Calculate the expire time.")); + + // The valid until delta is given in minutes. + TTimeIntervalMinutes delta( ValidUntilDelta() ); + expired = LinkDownloadTime() + delta; + + if ( iTimeStamp->Length() && + iMetadataTimeStamp->Length() && + *iTimeStamp != *iMetadataTimeStamp ) + { + DLINFO(("Link and metadata timestamps differ, expired")); + expired = KMinTInt64; + } + + } + + DLTRACEOUT(( "Expired time: %d", expired.Int64() )); + + return expired; + } + +TBool CNcdNodeLink::IsExpired() const + { + DLTRACEIN(("")); + + TTime currentTime; + currentTime.HomeTime(); + + if ( ExpiredTime() <= currentTime ) + { + DLTRACEOUT(( "Link is expired" )); + return ETrue; + } + else + { + DLTRACEOUT(( "Link is not expired" )); + return EFalse; + } + } + +void CNcdNodeLink::SetCatalogsSourceNameL( const TDesC& aSourceName ) + { + HBufC* tmpSourceName = aSourceName.AllocL(); + delete iCatalogsSourceName; + iCatalogsSourceName = tmpSourceName; + } + +const TDesC& CNcdNodeLink::CatalogsSourceName() const + { + return *iCatalogsSourceName; + } + + +void CNcdNodeLink::SetRemoteFlag( TBool aRemoteFlag ) + { + iRemoteFlag = aRemoteFlag; + } + +TBool CNcdNodeLink::RemoteFlag() const + { + return iRemoteFlag; + } + + +const CNcdNodeIdentifier& CNcdNodeLink::MetaDataIdentifier() const + { + DLNODEID(( *iMetaDataIdentifier )); + return *iMetaDataIdentifier; + } + +void CNcdNodeLink::SetMetaDataIdentifierL( const CNcdNodeIdentifier& aIdentifier ) + { + DLTRACEIN(("")); + CNcdNodeIdentifier* newIdentifier = + CNcdNodeIdentifier::NewL( aIdentifier ); + delete iMetaDataIdentifier; + iMetaDataIdentifier = newIdentifier; + DLTRACEOUT(("")); + } + + +void CNcdNodeLink::SetMetadataTimeStampL( const TDesC& aTimeStamp ) + { + AssignDesL( iMetadataTimeStamp, aTimeStamp ); + } + + +void CNcdNodeLink::InternalizeL( const MNcdPreminetProtocolEntityRef& aData, + const CNcdNodeIdentifier& aParentIdentifier, + const CNcdNodeIdentifier& aRequestParentIdentifier, + const TUid& aClientUid ) + { + DLTRACEIN(("")); + + // Notice that we do not internalize the link id and namespace here + // because this information is contained in the node-object that + // wraps this link. + // Also, note that the catalogs source name is not set here. That value + // is set separately by using the setter function. + + HBufC* timeStamp = aData.Timestamp().AllocLC(); + HBufC* remoteUri = aData.RemoteUri().AllocLC(); + HBufC* serverUri = aData.ServerUri().AllocLC(); + + CNcdNodeIdentifier* parentIdentifier = + CNcdNodeIdentifier::NewLC( aParentIdentifier ); + CNcdNodeIdentifier* requestParentIdentifier = + CNcdNodeIdentifier::NewLC( aRequestParentIdentifier ); + + CNcdNodeIdentifier* metaDataIdentifier = + CNcdNodeIdentifier::NewLC( aData.Namespace(), + aData.Id(), + aData.ServerUri(), + aClientUid ); + + + // This may be a little bit risky if the system runs out of memory. + // Then, the array may contain only part of the actual queries. + + iQueries.Reset(); + const RArray& queries = aData.Queries(); + for ( TInt i = 0; i < queries.Count(); ++i ) + { + DLTRACE(("Query %d: %d", i, queries[ i ])); + iQueries.AppendL( queries[ i ] ); + } + + // The function will not leave after this. So, it is safe to replace + // old info by new. + + + delete iMetaDataIdentifier; + iMetaDataIdentifier = metaDataIdentifier; + CleanupStack::Pop( metaDataIdentifier ); + + delete iRequestParentIdentifier; + iRequestParentIdentifier = requestParentIdentifier; + CleanupStack::Pop( requestParentIdentifier ); + + delete iParentIdentifier; + iParentIdentifier = parentIdentifier; + CleanupStack::Pop( parentIdentifier ); + + + if ( *serverUri != KNullDesC ) + { + // Do not delete this value if it already exists. This is set + // for the root children from the operation. + delete iServerUri; + iServerUri = serverUri; + CleanupStack::Pop( serverUri ); + } + + delete iRemoteUri; + iRemoteUri = remoteUri; + CleanupStack::Pop( remoteUri ); + + delete iTimeStamp; + iTimeStamp = timeStamp; + CleanupStack::Pop( timeStamp ); + DLTRACE(( _L("timestamp: %S"), iTimeStamp )); + + iDescription = aData.Description(); + iValidUntilDelta = aData.ValidUntilDelta(); + iValidUntilAutoUpdate = aData.ValidUntilAutoUpdate(); + + // Set the download time to this exact moment. + iLinkDownloadTime.HomeTime(); + DLTRACE(( "downloadTime: %d", iLinkDownloadTime.Int64() )); + + DLTRACEOUT(("Internalization went ok :)")); + } + + +void CNcdNodeLink::ExternalizeL( RWriteStream& aStream ) + { + DLTRACEIN(("")); + // Set all the membervariable values to the stream. So, + // that the stream may be used later to create a new + // object. + + aStream.WriteInt32L( iClassId ); + + // Notice that we do not externalize the link id and namespace here + // because this information is contained in the node-object that + // wraps this link. + + ExternalizeDesL( Timestamp(), aStream ); + ExternalizeDesL( CatalogsSourceName(), aStream ); + ExternalizeDesL( RemoteUri(), aStream ); + ExternalizeDesL( ServerUri(), aStream ); + + aStream << LinkDownloadTime().Int64(); + + aStream.WriteInt32L( iDescription ); + aStream.WriteInt32L( iValidUntilDelta ); + aStream.WriteInt32L( iValidUntilAutoUpdate ); + aStream.WriteInt32L( RemoteFlag() ); + + ParentIdentifier().ExternalizeL( aStream ); + RequestParentIdentifier().ExternalizeL( aStream ); + MetaDataIdentifier().ExternalizeL( aStream ); + + aStream.WriteInt32L( iQueries.Count() ); + for ( TInt i = 0; i < iQueries.Count(); ++i ) + { + aStream.WriteInt32L( iQueries[ i ] ); + } + + DLTRACEOUT(("")); + } + + +void CNcdNodeLink::InternalizeL( RReadStream& aStream ) + { + DLTRACEIN(("")); + + // Read all the membervariable values from the stream and + // set the values for this object. + + // First get the data to the tmp variables. So, we can be sure + // that there is enough memory to set the member variables. + + HBufC* timeStamp( NULL ); + HBufC* catalogsSourceName( NULL ); + HBufC* remoteUri( NULL ); + HBufC* serverUri( NULL ); + TInt64 linkDownloadTime( 0 ); + + TInt description( 0 ); + TInt validUntilDelta( 0 ); + TBool validUntilAutoUpdate( EFalse ); + TBool remoteFlag( RemoteFlag() ); + + CNcdNodeIdentifier* parentIdentifier( NULL ); + CNcdNodeIdentifier* requestParentIdentifier( NULL ); + CNcdNodeIdentifier* metaDataIdentifier( NULL ); + + InternalizeDesL( timeStamp, aStream ); + CleanupStack::PushL( timeStamp ); + + InternalizeDesL( catalogsSourceName, aStream ); + CleanupStack::PushL( catalogsSourceName ); + + InternalizeDesL( remoteUri, aStream ); + CleanupStack::PushL( remoteUri ); + + InternalizeDesL( serverUri, aStream ); + CleanupStack::PushL( serverUri ); + + aStream >> linkDownloadTime; + + description = aStream.ReadInt32L(); + validUntilDelta = aStream.ReadInt32L(); + validUntilAutoUpdate = aStream.ReadInt32L(); + remoteFlag = aStream.ReadInt32L(); + + // The parent identifier will contain at least empty values. + parentIdentifier = CNcdNodeIdentifier::NewLC( aStream ); + requestParentIdentifier = CNcdNodeIdentifier::NewLC( aStream ); + metaDataIdentifier = CNcdNodeIdentifier::NewLC( aStream ); + + // Now that descriptors were succesfully created we + // may delete old info and replaced it by new data. + + delete iMetaDataIdentifier; + iMetaDataIdentifier = metaDataIdentifier; + CleanupStack::Pop( metaDataIdentifier ); + + delete iRequestParentIdentifier; + iRequestParentIdentifier = requestParentIdentifier; + CleanupStack::Pop( requestParentIdentifier ); + + delete iParentIdentifier; + iParentIdentifier = parentIdentifier; + CleanupStack::Pop( parentIdentifier ); + + delete iServerUri; + iServerUri = serverUri; + CleanupStack::Pop( serverUri ); + + delete iRemoteUri; + iRemoteUri = remoteUri; + CleanupStack::Pop( remoteUri ); + + delete iCatalogsSourceName; + iCatalogsSourceName = catalogsSourceName; + CleanupStack::Pop( catalogsSourceName ); + + delete iTimeStamp; + iTimeStamp = timeStamp; + CleanupStack::Pop( timeStamp ); + + iLinkDownloadTime = linkDownloadTime; + + // We can be sure that enumeration is same as TInt + iDescription = + static_cast(description); + iValidUntilDelta = validUntilDelta; + iValidUntilAutoUpdate = validUntilAutoUpdate; + iRemoteFlag = remoteFlag; + + // Handle the query data + + TInt queryCount = aStream.ReadInt32L(); + // Reset old array if it contains data + iQueries.Reset(); + for ( TInt i = 0; i < queryCount; ++i ) + { + // Because all the other info has been already set, + // here we just skip insertion if it failed for some reason. + // Insert the queries that you can. + TRAP_IGNORE( iQueries.Append( aStream.ReadInt32L() ) ); + } + + DLTRACEOUT(("")); + } + + + +void CNcdNodeLink::ReceiveMessage( MCatalogsBaseMessage* aMessage, + TInt aFunctionNumber ) + { + DLTRACEIN(("")); + + DASSERT( aMessage ); + + // Now, we can be sure that rest of the time iMessage exists. + // This member variable is set for the CounterPartLost function. + iMessage = aMessage; + + TInt trapError( KErrNone ); + + switch( aFunctionNumber ) + { + case NcdNodeFunctionIds::ENcdInternalize: + TRAP( trapError, InternalizeRequestL( *aMessage ) ); + break; + + case NcdNodeFunctionIds::ENcdRelease: + ReleaseRequest( *aMessage ); + break; + + default: + break; + } + + if ( trapError != KErrNone ) + { + // Because something went wrong the complete has not been + // yet called for the message. + // So, inform the client about the error. + aMessage->CompleteAndRelease( trapError ); + } + + // Because the message should not be used after this, set it NULL. + // So, CounterPartLost function will know that no messages are + // waiting the response at the moment. + iMessage = NULL; + + DLTRACEOUT(("")); + } + + +void CNcdNodeLink::CounterPartLost( const MCatalogsSession& aSession ) + { + // This function may be called whenever -- when the message is waiting + // response or when the message does not exist. + // iMessage may be NULL here, because in the end of the + // ReceiveMessage it is set to NULL. The life time of the message + // ends shortly after CompleteAndRelease is called. + if ( iMessage != NULL ) + { + iMessage->CounterPartLost( aSession ); + } + } + + +void CNcdNodeLink::InternalizeRequestL( MCatalogsBaseMessage& aMessage ) const + { + DLTRACEIN(("")); + + CBufBase* buf = CBufFlat::NewL( KBufExpandSize ); + CleanupStack::PushL( buf ); + + RBufWriteStream stream( *buf ); + CleanupClosePushL( stream ); + + + // Include all the necessary node data to the stream + ExternalizeDataForRequestL( stream ); + + + // Commits data to the stream when closing. + CleanupStack::PopAndDestroy( &stream ); + + if ( buf->Size() > 0 ) + { + DLTRACE(( "Completing the message, buf len: %d", buf->Ptr(0).Length() )); + } + // If this leaves, ReceiveMessage function will complete the message. + aMessage.CompleteAndReleaseL( buf->Ptr( 0 ), KErrNone ); + + + DLTRACE(("Deleting the buf")); + CleanupStack::PopAndDestroy( buf ); + + DLTRACEOUT(("")); + } + +void CNcdNodeLink::ExternalizeDataForRequestL( RWriteStream& aStream ) const + { + DLTRACEIN(("")); + + // Link existed. So, insert info that link was found. + aStream.WriteInt32L( ClassId() ); + + // Notice that the proxy does not require all the information contained + // in this class. So, send only the information that proxy wants. + + ExternalizeDesL( Timestamp(), aStream ); + ExternalizeDesL( CatalogsSourceName(), aStream ); + aStream.WriteInt32L( RemoteFlag() ); + + aStream << ExpiredTime().Int64(); + + ParentIdentifierForRequestL( aStream ); + + // Externalize the real parent too. + ParentIdentifier().ExternalizeL( aStream ); + + DLTRACEOUT(("")); + } + + +void CNcdNodeLink::ReleaseRequest( MCatalogsBaseMessage& aMessage ) const + { + DLTRACEIN(("")); + + // Decrease the reference count for this object. + // When the reference count reaches zero, this object will be destroyed + // and removed from the session. + MCatalogsSession& requestSession( aMessage.Session() ); + TInt handle( aMessage.Handle() ); + aMessage.CompleteAndRelease( KErrNone ); + requestSession.RemoveObject( handle ); + + DLTRACEOUT(("")); + } + + +CNcdNode& CNcdNodeLink::Node() const + { + return iNode; + } + + +void CNcdNodeLink::ParentIdentifierForRequestL( RWriteStream& aStream ) const + { + DLTRACEIN(("")); + + // There is always at least an empty identifier value. + RequestParentIdentifier().ExternalizeL( aStream ); + + DLTRACEOUT(("")); + }