ncdengine/provider/server/src/ncdnodedbmanager.cpp
changeset 0 ba25891c3a9e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ncdengine/provider/server/src/ncdnodedbmanager.cpp	Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,662 @@
+/*
+* 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 CNcdNodeDbManager class
+*
+*/
+
+
+#include "ncdnodedbmanager.h"
+
+#include <e32err.h>
+#include <s32mem.h>
+#include <badesca.h>
+
+#include "ncdnodeidentifier.h"
+#include "ncdnodeidentifiereditor.h"
+#include "catalogsutils.h"
+#include "ncdstoragemanager.h"
+#include "ncdstoragebase.h"
+#include "ncdstorage.h"
+#include "ncdfilestorage.h"
+#include "ncddatabasestorage.h"
+#include "ncdproviderdefines.h"
+#include "ncdstorageclient.h"
+#include "ncdstorageitem.h"
+#include "catalogsconstants.h"
+#include "ncdnodeidentifierutils.h"
+
+#include "catalogsdebug.h"
+
+CNcdNodeDbManager::CNcdNodeDbManager(
+    MNcdStorageManager& aStorageManager )
+: CBase(),
+  iStorageManager( aStorageManager )
+    {
+    DLTRACEIN((""));
+
+    DLTRACEOUT((""));
+    }
+
+void CNcdNodeDbManager::ConstructL()
+    {
+    DLTRACEIN((""));
+
+    DLTRACEOUT((""));
+    }
+
+CNcdNodeDbManager* CNcdNodeDbManager::NewL(
+    MNcdStorageManager& aStorageManager )
+    {
+    CNcdNodeDbManager* self =
+        CNcdNodeDbManager::NewLC( aStorageManager );
+    CleanupStack::Pop( self );
+    return self;        
+    }
+
+CNcdNodeDbManager* CNcdNodeDbManager::NewLC(
+    MNcdStorageManager& aStorageManager )
+    {
+    CNcdNodeDbManager* self =
+        new( ELeave ) CNcdNodeDbManager( aStorageManager );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    return self;        
+    }
+
+
+CNcdNodeDbManager::~CNcdNodeDbManager()
+    {
+    DLTRACEIN((""));
+
+    // Do not delete storage manager here because it is not owned
+    // by this class object.
+    DLTRACEOUT((""));
+    }
+
+
+
+// Database info functions
+
+// ---------------------------------------------------------------------------
+// StorageSizeL
+// ---------------------------------------------------------------------------
+//
+TInt CNcdNodeDbManager::StorageSizeL( const TUid& aClientUid,
+                                      const MDesCArray& aSkipNamespaces )
+    {
+    DLTRACEIN((""));
+    DPROFILING_BEGIN( x );
+    TInt size( 0 );
+
+    // Get the namespaces from the storage of the given client and insert
+    // the namespace array to the cleanup stack. Notice that the array items
+    // are deleted when the array is deleted.
+    MNcdStorageClient& client = iStorageManager.StorageClientL( aClientUid.Name() );
+    MDesCArray* namespaces = client.NamespacesLC();
+
+    // Temporary variables for the loop
+    TPtrC clientNamespace;
+    TBool doNotSkip( ETrue );  
+    
+    // Start to remove all the possible namespaces from the client.  
+    for ( TInt i = 0; i < namespaces->MdcaCount(); ++i )
+        {
+        doNotSkip = ETrue;
+        clientNamespace.Set( namespaces->MdcaPoint( i ) );
+
+        // Check if this namespace should be skipped because its content
+        // is not wanted to be part of the size info.
+        for ( TInt j = 0; j < aSkipNamespaces.MdcaCount(); ++j )
+            {
+            if ( clientNamespace == aSkipNamespaces.MdcaPoint( j ) )
+                {
+                DLINFO(("Skip namespace"));
+                // This namespace should be skipped.
+                doNotSkip = EFalse;
+                break;
+                }
+            }
+        if ( doNotSkip ) 
+            {
+            DLINFO(("Add namespace size"));
+            // This size increase should not be skipped. So, add the size to the total.
+            // Storage will contains the data of the client identified by its UID
+            // The identifier id can be empty when creating storage. Only,
+            // namespace and uid are actually used.
+            CNcdNodeIdentifier* storageIdentifier = 
+                CNcdNodeIdentifier::NewLC( clientNamespace, KNullDesC, aClientUid );
+            MNcdStorage& storage = StorageL( *storageIdentifier );
+            CleanupStack::PopAndDestroy( storageIdentifier );
+
+            size += storage.SizeL();
+            }
+        }
+    
+    CleanupStack::PopAndDestroy( namespaces );
+    DPROFILING_END( x );
+    DLTRACEOUT(("Storage size: %d", size));
+    
+    return size;
+    }
+
+
+// Database read functions
+
+// ---------------------------------------------------------------------------
+// ReadFromDatabaseL
+// ---------------------------------------------------------------------------
+//
+HBufC8* CNcdNodeDbManager::ReadDataFromDatabaseL( 
+    const CNcdNodeIdentifier& aIdentifier,
+    const NcdNodeClassIds::TNcdNodeClassType aClassType )
+    {
+    DLTRACEIN((""));
+
+    HBufC8* ret( ReadDataFromDatabaseLC( aIdentifier, 
+                                         aClassType ) );
+    if ( ret != NULL )
+        {
+        CleanupStack::Pop( ret );
+        }
+
+    DLTRACEOUT((""));    
+    return ret;
+    }
+   
+// ---------------------------------------------------------------------------
+// ReadFromDatabaseLC
+// ---------------------------------------------------------------------------
+//    
+HBufC8* CNcdNodeDbManager::ReadDataFromDatabaseLC( 
+    const CNcdNodeIdentifier& aIdentifier,
+    const NcdNodeClassIds::TNcdNodeClassType aClassType )
+    {
+    DLTRACEIN((""));
+    DPROFILING_BEGIN( x );
+    DASSERT( !aIdentifier.ContainsEmptyFields() );
+        
+    // Storage will contains the data of the client identified by its UID
+    MNcdStorage& storage = StorageL( aIdentifier );
+    
+    // NOTE: this creates the database if it does not already exist.
+    MNcdDatabaseStorage& database = 
+        storage.DatabaseStorageL( NcdProviderDefines::KDefaultDatabaseUid );
+                        
+    // Get the storage item from which the node is loaded
+    // Note: database has the ownership of the item
+    MNcdStorageItem* item = 
+        database.StorageItemL( aIdentifier.NodeId(), 
+                               aClassType );    
+        
+    DLINFO(("Get data"));
+    HBufC8* data = item->GetDataLC();
+
+    DLTRACEOUT(("Returning data, length: %d", data->Length()));
+    DPROFILING_END( x );
+    return data;
+    }
+
+
+// ---------------------------------------------------------------------------
+// StartStorageLoadActionL
+// ---------------------------------------------------------------------------
+//
+void CNcdNodeDbManager::StartStorageLoadActionL( 
+    const CNcdNodeIdentifier& aIdentifier,
+    MNcdStorageDataItem& aDataItem,
+    const NcdNodeClassIds::TNcdNodeClassType aClassType )
+    {
+    DLTRACEIN((""));
+    DPROFILING_BEGIN( x );
+    if( aIdentifier.ContainsEmptyFields() )
+        {
+        DLERROR(("Empty identifier fields given"));
+
+        // For debugging purposes
+        DASSERT( EFalse );
+        
+        User::Leave( KErrArgument );
+        }
+    
+    // Here we will get the data from the storage according
+    // to the namespace and data id information. Also, class id
+    // is used to define the type of the data that is searched.
+    
+    // The type of the data should be gotten from the first four bytes (TInt32)
+    // of the stream when the Internalize function of the data item is called
+    // from the storage handler.
+
+    // Storage will contains the data of the client identified by its UID
+    MNcdStorage& storage = StorageL( aIdentifier );
+    
+    // NOTE: If db does not already exist, 
+    // this creates one into the storage.
+    MNcdDatabaseStorage& database = 
+        storage.DatabaseStorageL( NcdProviderDefines::KDefaultDatabaseUid );
+        
+    // Ensure the node exists in the database    
+    
+    if( !database.ItemExistsInStorageL( aIdentifier.NodeId(), 
+                                        aClassType ) )
+        {
+        DLINFO(("Data was not in namespace"));
+        User::Leave( KErrNotFound );            
+        }
+    
+    // Get the storage item from which the node is loaded
+    // Note: database has the ownership of the item
+    MNcdStorageItem* item = 
+        database.StorageItemL( aIdentifier.NodeId(), 
+                               aClassType );    
+        
+    // Get data from database by using aDataItem as the target so that 
+    // internalize will be called for it
+    item->SetDataItem( &aDataItem );
+    
+    // Read node data -> calls InternalizeL of aDataItem
+    item->ReadDataL();
+    DPROFILING_END( x );
+    DLTRACEOUT(("Item IsOpen: %d", item->IsOpen() ));
+    }
+
+
+// ---------------------------------------------------------------------------
+// GetAllClientItemIdentifiersL
+// ---------------------------------------------------------------------------
+//    
+void CNcdNodeDbManager::GetAllClientItemIdentifiersL( 
+    RPointerArray<CNcdNodeIdentifier>& aItemIdentifiers,
+    const TUid& aClientUid,
+    const MDesCArray& aSkipNamespaces,
+    const RArray<NcdNodeClassIds::TNcdNodeClassType>& aAcceptClassTypes  )
+    {
+    DLTRACEIN((""));
+    DPROFILING_BEGIN( x );
+    // This temporary array is used for the items that are gotten from
+    // the storages.
+    // Insert it into the cleanup stack to be sure that the array is closed
+    // if leave occurs.No need to worry about deleting array items here.
+    // They are owned by the storage.
+    RPointerArray<MNcdStorageItem> tmpItemArray;
+    CleanupClosePushL( tmpItemArray );
+    
+    // Get all the namespaces of the client. Notice that the namespaces are
+    // deleted from the array when the array is deleted.  
+    MNcdStorageClient& client = 
+        iStorageManager.StorageClientL( aClientUid.Name() );
+    MDesCArray* namespaces = client.NamespacesLC();
+
+    // Temporary variables that are used in the loops.
+    TPtrC clientNamespace;
+    TBool doNotSkip( ETrue );
+    MNcdStorageItem* tmpItem( NULL );  
+    CNcdNodeIdentifier* tmpItemIdentifier( NULL );
+    
+    // Start to remove all the possible namespaces from the client.  
+    for ( TInt i = 0; i < namespaces->MdcaCount(); ++i )
+        {
+        doNotSkip = ETrue;
+        clientNamespace.Set( namespaces->MdcaPoint( i ) );
+
+        // Check if this namespace should be skipped.
+        for ( TInt j = 0; j < aSkipNamespaces.MdcaCount(); ++j )
+            {
+            if ( clientNamespace == aSkipNamespaces.MdcaPoint( j ) )
+                {
+                DLINFO(("Skip namespace"));
+                // This namespace should be skipped
+                doNotSkip = EFalse;
+                break;
+                }
+            }
+            
+        if ( doNotSkip ) 
+            {
+            DLINFO(("Did not skip namespace"));
+            // This namespace should not be skipped. So, do your thing.
+            
+            // Storage will contains the data of the client identified by its UID
+            // The identifier id can be empty when creating storage. Only,
+            // namespace and uid are actually used.
+            CNcdNodeIdentifier* storageIdentifier = 
+                CNcdNodeIdentifier::NewLC( clientNamespace, KNullDesC, aClientUid );
+            MNcdStorage& storage = StorageL( *storageIdentifier );
+            CleanupStack::PopAndDestroy( storageIdentifier );
+                
+            // NOTE: If db does not already exist, 
+            // this creates one into the storage.
+            MNcdDatabaseStorage& database = 
+                storage.DatabaseStorageL( NcdProviderDefines::KDefaultDatabaseUid );
+                    
+            // Now get all the items from the db storage.
+            // Notice that the tmpItemArray will not own the items, but they
+            // are owned by the database.
+            database.StorageItemsL( tmpItemArray );
+            
+            DLINFO(("tmpItemArrayCount: %d", tmpItemArray.Count()));
+            TInt count = tmpItemArray.Count();
+            while ( count-- )
+                {
+                // Move the item info from tmpItemArray into the return array.
+                tmpItem = tmpItemArray [ count ];
+                for ( TInt m = 0; m < aAcceptClassTypes.Count(); ++m )
+                    {
+                    if ( tmpItem->Type() == aAcceptClassTypes[ m ] )
+                        {
+                        tmpItemIdentifier = 
+                            CNcdNodeIdentifier::NewLC( clientNamespace,
+                                                       tmpItem->Uid(), 
+                                                       aClientUid );
+
+                        aItemIdentifiers.AppendL( tmpItemIdentifier );
+                        
+                        CleanupStack::Pop( tmpItemIdentifier );                        
+                       
+                        tmpItemIdentifier = NULL;     
+                        break;                       
+                        }
+                    }
+                // Notice that the item array does not own the
+                // items. So, do not delete them but only remove them
+                // from the array.
+                tmpItemArray.Remove( count );
+                }                
+            }
+        }
+    
+    // Deletes the array and its items
+    CleanupStack::PopAndDestroy( namespaces );
+    
+    // Closes the array but does not delete items because the items
+    // are not owned by this array.
+    CleanupStack::PopAndDestroy( &tmpItemArray );
+    DPROFILING_END( x );
+    DLTRACEOUT(("Items load ok."));
+    }
+
+
+
+// Database write functions
+
+// ---------------------------------------------------------------------------
+// SaveDataIntoDatabaseL
+// ---------------------------------------------------------------------------
+//
+void CNcdNodeDbManager::SaveDataIntoDatabaseL( 
+    const CNcdNodeIdentifier& aIdentifier,
+    MNcdStorageDataItem& aDataItem,
+    const NcdNodeClassIds::TNcdNodeClassType aClassType )
+    {
+    DLTRACEIN((""));
+    DPROFILING_BEGIN( x );
+    if( aIdentifier.ContainsEmptyFields() )
+        {
+        DLERROR(("Empty identifier fields given"));
+        
+        // For debugging purposes
+        DASSERT( EFalse );
+        
+        User::Leave( KErrArgument );
+        }
+    
+    // Storage will contains the data of the client identified by its UID
+    MNcdStorage& storage = StorageL( aIdentifier );
+        
+    // NOTE: If db does not already exist, 
+    // this creates one into the storage.
+    MNcdDatabaseStorage& database = 
+        storage.DatabaseStorageL( NcdProviderDefines::KDefaultDatabaseUid );
+            
+    // Get/create the storage item where the data is saved
+    // Note: database has the ownership of the item
+    MNcdStorageItem* storageItem = 
+        database.StorageItemL( aIdentifier.NodeId(), 
+                               aClassType );    
+    
+    // Here call the storage functions that will handle 
+    // the saving of the data
+    
+    // Save new item to database
+    storageItem->SetDataItem( &aDataItem );
+    storageItem->OpenL();
+    
+    // Calls ExternalizeL for data item
+    storageItem->WriteDataL();
+    
+    // Save the data to the database.
+    // The data object implements MNcdStorageDataItem interface.
+    // So, the externalize function will insert the data to the stream
+    // that the database handler will save to the database.
+    storageItem->SaveL();        
+    DPROFILING_END( x );
+    DLTRACEOUT((""));    
+    }
+  
+
+
+// Database remove functions
+  
+// ---------------------------------------------------------------------------
+// RemoveDataFromDatabaseL
+// ---------------------------------------------------------------------------
+//    
+void CNcdNodeDbManager::RemoveDataFromDatabaseL( 
+    const CNcdNodeIdentifier& aIdentifier,
+    const NcdNodeClassIds::TNcdNodeClassType aClassType ) 
+    {
+    DLTRACEIN((""));
+    DPROFILING_BEGIN( x );
+    if( aIdentifier.ContainsEmptyFields() )
+        {
+        DLERROR(("Empty identifier fields given"));
+        DASSERT( EFalse );
+        User::Leave( KErrArgument );
+        }
+        
+    // Storage will contains the data of the client identified by its UID
+    MNcdStorage& storage = StorageL( aIdentifier );
+        
+    // NOTE: If db does not already exist, 
+    // this creates one into the storage.
+    MNcdDatabaseStorage& database = 
+        storage.DatabaseStorageL( NcdProviderDefines::KDefaultDatabaseUid );
+            
+    // Get/create the storage item where the data is saved
+    // Note: database has the ownership of the item.
+    MNcdStorageItem* storageItem = 
+        database.StorageItemL( aIdentifier.NodeId(), aClassType );    
+
+    // Remove the item from the storage
+    storageItem->RemoveFromStorageL();
+
+    // Make the removing happen.
+    database.CommitL();    
+    DPROFILING_END( x );
+    DLTRACEOUT((""));
+    }
+
+
+// ---------------------------------------------------------------------------
+// RemoveDataFromDatabaseL
+// ---------------------------------------------------------------------------
+//    
+void CNcdNodeDbManager::RemoveDataFromDatabaseL( 
+    const RPointerArray<CNcdNodeIdentifier>& aIdentifiers,
+    const RArray<NcdNodeClassIds::TNcdNodeClassType>& aClassTypes,
+    TBool aCompact ) 
+    {
+    DLTRACEIN((""));
+    DPROFILING_BEGIN( x );
+    CNcdNodeIdentifier* identifier( NULL );
+    
+    TPtrC currentNamespace;
+    TInt i = 0;
+    const TInt count = aIdentifiers.Count();
+    const TInt classCount = aClassTypes.Count();
+    while( i < count )
+        {
+        identifier = aIdentifiers[ i ];
+        if( identifier == NULL
+            || identifier->ContainsEmptyFields() )
+            {
+            DLERROR(("NULL identifier or empty identifier fields given"));
+            DASSERT( EFalse );
+            User::Leave( KErrArgument );
+            }    
+
+        currentNamespace.Set( identifier->NodeNameSpace() );    
+        // Storage will contains the data of the client identified by its UID
+        MNcdStorage& storage = StorageL( *identifier );
+            
+        // NOTE: If db does not already exist, 
+        // this creates one into the storage.
+        MNcdDatabaseStorage& database = 
+            storage.DatabaseStorageL( NcdProviderDefines::KDefaultDatabaseUid );
+
+        for ( ; i < count && 
+                currentNamespace == aIdentifiers[ i ]->NodeNameSpace(); ++i ) 
+            {
+            identifier = aIdentifiers[ i ];
+            for ( TInt j = 0; j < classCount; ++j )
+                {
+                // Get/create the storage item where the data is saved
+                // Note: database has the ownership of the item.
+                MNcdStorageItem* storageItem = 
+                    database.StorageItemL( identifier->NodeId(), aClassTypes[ j ] );    
+
+                // Remove the item from the storage
+                storageItem->RemoveFromStorageL();        
+                }
+            }
+            
+        // Commit & compact or just commit
+        if ( aCompact ) 
+            {            
+            database.Compact();        
+            }
+        else 
+            {
+            database.CommitL();
+            }
+        }        
+    DPROFILING_END( x );
+    DLTRACEOUT((""));
+    }
+
+
+// ---------------------------------------------------------------------------
+// RemoveDataFromDatabaseL
+// ---------------------------------------------------------------------------
+//    
+void CNcdNodeDbManager::RemoveDataFromDatabaseL( 
+    const CNcdNodeIdentifier& aNodeIdentifier,
+    const RArray<RNcdDatabaseItems>& aDoNotRemoveItems )
+    {
+    DLTRACEIN((""));
+    DPROFILING_BEGIN( x );
+    // Storage will contain the data of the client identified by its UID
+    // and node's namespace    
+    MNcdStorage& storage = StorageL( aNodeIdentifier );
+        
+    // NOTE: If db does not already exist, 
+    // this creates one into the storage.
+    MNcdDatabaseStorage& database = 
+        storage.DatabaseStorageL( NcdProviderDefines::KDefaultDatabaseUid );
+    
+    DLTRACE(("Removing from database"));
+    // commits and compacts data
+    database.RemoveItemsL( aDoNotRemoveItems );  
+    DPROFILING_END( x );          
+    }
+
+
+// ---------------------------------------------------------------------------
+// ClearClientL
+// ---------------------------------------------------------------------------
+//    
+void CNcdNodeDbManager::ClearClientL( const TUid& aClientUid,
+                                      const MDesCArray& aSkipNamespaces )
+    {
+    DLTRACEIN((""));
+    DPROFILING_BEGIN( x );
+    // Get the namespaces of the given client.
+    // The namespaces are inserted into the array. Notice that the items in array
+    // are deleted when the array is deleted.
+    MNcdStorageClient& client = iStorageManager.StorageClientL( aClientUid.Name() );
+    MDesCArray* namespaces = client.NamespacesLC();
+
+    // Temporary variables for the array.
+    TPtrC clientNamespace;
+    TBool doNotSkip( ETrue );  
+    
+    // Start to remove all the possible namespaces from the client.  
+    for ( TInt i = 0; i < namespaces->MdcaCount(); ++i )
+        {
+        doNotSkip = ETrue;
+        clientNamespace.Set( namespaces->MdcaPoint( i ) );
+
+        // Check if this namespace should be skipped.
+        for ( TInt j = 0; j < aSkipNamespaces.MdcaCount(); ++j )
+            {
+            if ( clientNamespace == aSkipNamespaces.MdcaPoint( j ) )
+                {
+                DLINFO(("Skip namespace"));
+                // This namespace should be skipped and not removed.
+                doNotSkip = EFalse;
+                break;
+                }
+            }
+        if ( doNotSkip ) 
+            {
+            DLINFO((_L("Remove namespace: %S"),
+                    &clientNamespace));
+            // This removal should not be skipped. So, remove.
+            client.RemoveStorageL( clientNamespace );
+            }
+        }
+    
+    CleanupStack::PopAndDestroy( namespaces );
+    DPROFILING_END( x );
+    DLTRACEOUT(("Client cleared"));
+    }
+
+
+// Misc functions
+
+// ---------------------------------------------------------------------------
+// StorageL
+// ---------------------------------------------------------------------------
+//    
+MNcdStorage& CNcdNodeDbManager::StorageL( 
+    const CNcdNodeIdentifier& aIdentifier ) const
+    {    
+    DLTRACEIN((""));
+    DPROFILING_BEGIN( x );
+    // This function needs the namespace and uid information.
+    // So, check them. Id can be empty because it is not used here.
+    if( aIdentifier.NodeNameSpace() == KNullDesC
+        || aIdentifier.ClientUid() == TUid::Null() )
+        {
+        DLERROR(("Empty ns or uid fields given"));
+
+        User::Leave( KErrArgument );
+        }    
+
+    DLINFO(("Identifier was not empty"));
+
+    return iStorageManager.CreateOrGetStorageL(
+        aIdentifier.ClientUid().Name(),
+        aIdentifier.NodeNameSpace() );
+    }
+