--- /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() );
+ }
+