diff -r 000000000000 -r ba25891c3a9e ncdengine/provider/server/src/ncdnodedbmanager.cpp --- /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 +#include +#include + +#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& aItemIdentifiers, + const TUid& aClientUid, + const MDesCArray& aSkipNamespaces, + const RArray& 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 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& aIdentifiers, + const RArray& 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& 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() ); + } +