ncdengine/provider/server/src/ncdnodelink.cpp
changeset 0 ba25891c3a9e
--- /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<TInt>& 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<MNcdPreminetProtocolEntityRef::TDescription>(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((""));
+    }