--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emailservices/emailstore/message_store/server/src/ContainerStoreContainersTable.cpp Thu Dec 17 08:39:21 2009 +0200
@@ -0,0 +1,1211 @@
+/*
+* 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: Container store containers table implementation.
+*
+*/
+
+
+
+// ========
+// INCLUDES
+// ========
+
+#include <s32mem.h> // for descriptor read/write streams
+
+#include "ContainerStoreContainersTable.h"
+#include "ContainerStoreDefs.h"
+#include "ContainerStoreEncryption.h"
+#include "ContainerStoreUtils.h"
+#include "PropertiesSerializer.h"
+#include "MessageStoreClientServer.h"
+
+// =========
+// CONSTANTS
+// =========
+
+_LIT( KSelect, "SELECT " );
+_LIT( KComma, "," );
+_LIT( KFrom, " FROM " );
+_LIT( KWhere, " WHERE " );
+_LIT( KAnd, " AND " );
+_LIT( KEqualTo, "=" );
+_LIT( KGreaterThanOrEqualTo, ">=" );
+_LIT( KLessThanOrEqualTo, "<=" );
+_LIT( KOrderBy, " ORDER BY ");
+_LIT( KAsc, " ASC" );
+
+// ======================
+// METHOD IMPLEMENTATIONS
+// ======================
+
+// ==========================================================================
+// FUNCTION: OpenL
+// ==========================================================================
+CContainerStoreContainersTable* CContainerStoreContainersTable::OpenL( CContainerStoreUtils& aUtils,
+ MCustomBehaviorProvider& aCustomBehaviorProvider,
+ TUint aCountsLength,
+ CContainerStoreEncryption& aEncryption )
+ {
+ CContainerStoreContainersTable* self = new(ELeave) CContainerStoreContainersTable( aUtils, aCustomBehaviorProvider, aCountsLength, aEncryption );
+ CleanupStack::PushL( self );
+ self->OpenTableL();
+ CleanupStack::Pop( self );
+ return self;
+ } // end OpenL
+
+// ==========================================================================
+// FUNCTION: CreateL
+// ==========================================================================
+CContainerStoreContainersTable* CContainerStoreContainersTable::CreateL( CContainerStoreUtils& aUtils,
+ MCustomBehaviorProvider& aCustomBehaviorProvider,
+ TUint aCountsLength,
+ CContainerStoreEncryption& aEncryption )
+ {
+ CContainerStoreContainersTable* self = new(ELeave) CContainerStoreContainersTable( aUtils, aCustomBehaviorProvider, aCountsLength, aEncryption );
+ CleanupStack::PushL( self );
+ self->CreateTableL();
+ CleanupStack::Pop( self );
+ return self;
+ } // end CreateL
+
+// ==========================================================================
+// FUNCTION: Constructor
+// ==========================================================================
+CContainerStoreContainersTable::CContainerStoreContainersTable( CContainerStoreUtils& aUtils,
+ MCustomBehaviorProvider& aCustomBehaviorProvider,
+ TUint aCountsLength,
+ CContainerStoreEncryption& aEncryption ) :
+ CContainerStoreTable( aUtils ),
+ iCustomBehaviorProvider( aCustomBehaviorProvider ),
+ iCountsLength( aCountsLength ),
+ iEncryption( aEncryption )
+ {
+ __LOG_CONSTRUCT( "msg", "CContainerStoreContainersTable" )
+ } // end constructor
+
+// ==========================================================================
+// FUNCTION: Destructor
+// ==========================================================================
+CContainerStoreContainersTable::~CContainerStoreContainersTable()
+ {
+ iUtils.CloseTable( iTable );
+
+ __LOG_DESTRUCT
+ } // end destructor
+
+// ==========================================================================
+// FUNCTION: HierarchyL
+// ==========================================================================
+void CContainerStoreContainersTable::HierarchyL( TContainerId aId,
+ RArray<TContainerId>& aHierarchy )
+ {
+ __LOG_ENTER_SUPPRESS( "HierarchyL" )
+
+ aHierarchy.Reset();
+
+ TBool done = EFalse;
+
+ TContainerId currentId = aId;
+
+ if( !iTable.SeekL( currentId ) )
+ {
+ __LOG_WRITE_ERROR( "container not found" )
+ User::Leave( KErrNotFound );
+ } // end if
+
+ // Set a bookmark at the original container, for a quick return.
+ TDbBookmark bookmark = iTable.Bookmark();
+
+ aHierarchy.Append( currentId );
+
+ // Build the hierarchy of the container.
+ while( !done )
+ {
+ iTable.GetL();
+
+ TContainerId parentId = iTable.ColUint32( iParentIdColNum );
+
+ switch( parentId )
+ {
+ case KContainerInvalidId:
+
+ // Stop when the container has no parent container.
+ done = ETrue;
+ break;
+
+ case KUncommittedContainers:
+
+ // Stop when the container is uncommitted.
+ aHierarchy.Append( KUncommittedContainers );
+ done = ETrue;
+ break;
+
+ case KToBeDeletedContainers:
+
+ // If the container is the To Be Deleted hierarchy then treat this as a "not found" case.
+ __LOG_WRITE_ERROR( "container is in to be deleted hierarchy" )
+ User::Leave( KErrNotFound );
+ break;
+
+ default:
+
+ // Add the parent to the hierarchy.
+ aHierarchy.Append( parentId );
+
+ // Traverse to the parent entry.
+ if( !iTable.SeekL( parentId ) )
+ {
+ // This should not happen. If it has, there are orphaned records in the database.
+ __LOG_WRITE8_FORMAT1_ERROR( "orphaned container found %i", parentId )
+ User::Leave( KErrNotFound );
+ } // end if
+ break;
+
+ } // end case
+
+ } // end while
+
+ // Go back to the original container.
+ iTable.GotoL( bookmark );
+
+ } // end HierarchyL
+
+// ==========================================================================
+// FUNCTION: SeekL
+// ==========================================================================
+void CContainerStoreContainersTable::SeekL( TContainerId aId,
+ RArray<TContainerId>& aHierarchy )
+ {
+ HierarchyL( aId, aHierarchy );
+ } // end SeekL
+
+// ==========================================================================
+// FUNCTION: SeekL
+// ==========================================================================
+void CContainerStoreContainersTable::SeekL( TContainerId aId )
+ {
+ __LOG_ENTER_SUPPRESS( "SeekL" )
+
+ if( !iTable.SeekL( aId ) )
+ {
+ __LOG_WRITE_ERROR( "container not found" )
+ User::Leave( KErrNotFound );
+ } // end if
+
+ iTable.GetL();
+ } // end SeekL
+
+// ==========================================================================
+// FUNCTION: SeekL
+// ==========================================================================
+void CContainerStoreContainersTable::SeekL( TContainerId aId,
+ TContainerId& aParentId )
+ {
+ SeekL( aId );
+
+ iTable.GetL();
+
+ aParentId = iTable.ColUint32( iParentIdColNum );
+ } // end SeekL
+
+// ==========================================================================
+// FUNCTION: FindL
+// ==========================================================================
+TContainerId CContainerStoreContainersTable::FindL( const TDesC& aSqlQuery )
+ {
+ __LOG_ENTER_SUPPRESS( "FindL" )
+ __LOG_WRITE_FORMAT1_DEBUG3( "query=%S", &aSqlQuery )
+
+ TContainerId returnValue;
+
+ iTable.FirstL();
+
+ if( iTable.FindL( RDbRowSet::EForwards, aSqlQuery ) == KErrNotFound )
+ {
+ __LOG_WRITE_INFO( "No match found" )
+ returnValue = KContainerInvalidId;
+ }
+ else
+ {
+ iTable.GetL();
+ returnValue = iTable.ColUint32( iIdColNum );
+ } // end if
+
+ return returnValue;
+
+ } // end FindL
+
+// ==========================================================================
+// FUNCTION: GotoL
+// ==========================================================================
+TContainerId CContainerStoreContainersTable::GotoL( TDbBookmark aBookmark )
+ {
+ iTable.GotoL( aBookmark );
+
+ iTable.GetL();
+
+ return iTable.ColUint32( iIdColNum );
+ } // end GotoL
+
+// ==========================================================================
+// FUNCTION: Bookmark
+// ==========================================================================
+TDbBookmark CContainerStoreContainersTable::Bookmark()
+ {
+ return iTable.Bookmark();
+ } // end Bookmark
+
+// ==========================================================================
+// FUNCTION: ParentId
+// ==========================================================================
+TContainerId CContainerStoreContainersTable::ParentId()
+ {
+ return iTable.ColUint32( iParentIdColNum );
+ } // end ParentId
+
+// ==========================================================================
+// FUNCTION: OpenTableL
+// ==========================================================================
+void CContainerStoreContainersTable::OpenTableL()
+ {
+ __LOG_ENTER( "OpenTableL" )
+
+ iUtils.OpenTableL( iTable, KContainersTableName );
+
+ // Get the column numbers for the containers table.
+ CDbColSet* colSet = iTable.ColSetL();
+ CleanupStack::PushL( colSet );
+
+ iIdColNum = colSet->ColNo( KContainersTableIdCol );
+ iParentIdColNum = colSet->ColNo( KContainersTableParentIdCol );
+ iChildrenCountsColNum = colSet->ColNo( KContainersTableChildrenCountsCol );
+ iChildrenCountColNum = colSet->ColNo( KContainersTableChildrenCountCol );
+ iPropertiesColNum = colSet->ColNo( KContainersTablePropertiesCol );
+ iQuickPropertiesColNum = colSet->ColNo( KContainersTableQuickPropertiesCol );
+ iCountsColNum = colSet->ColNo( KContainersTableCountsCol );
+ iIsRowEncryptedColNum = colSet->ColNo( KContainersTableIsRowEncryptedCol );
+
+ CleanupStack::PopAndDestroy( colSet );
+
+ // Set the table's index to the ID index.
+ User::LeaveIfError( iTable.SetIndex( KContainersTableIdIndex ) );
+
+ __LOG_EXIT
+ } // end OpenTableL
+
+// ==========================================================================
+// FUNCTION: CreateTableL
+// ==========================================================================
+void CContainerStoreContainersTable::CreateTableL()
+ {
+ __LOG_ENTER( "CreateContainersTableL" )
+
+ // Create table columns
+
+ CDbColSet* colSet = CDbColSet::NewLC();
+
+ TDbCol idCol( KContainersTableIdCol, EDbColUint32 );
+ colSet->AddL( idCol );
+
+ TDbCol parentIdCol( KContainersTableParentIdCol, EDbColUint32 );
+ colSet->AddL( parentIdCol );
+
+ TDbCol childrenCountCol( KContainersTableChildrenCountCol, EDbColUint16 );
+ colSet->AddL( childrenCountCol );
+
+ TDbCol childrenCountsCol( KContainersTableChildrenCountsCol, EDbColBinary, iCountsLength );
+ colSet->AddL( childrenCountsCol );
+
+ TDbCol propertiesCol( KContainersTablePropertiesCol, EDbColLongBinary );
+ colSet->AddL( propertiesCol );
+
+ TDbCol quickPropertiesCol( KContainersTableQuickPropertiesCol, EDbColLongBinary );
+ colSet->AddL( quickPropertiesCol );
+
+ TDbCol countsCol( KContainersTableCountsCol, EDbColBinary, iCountsLength );
+ colSet->AddL( countsCol );
+
+ TDbCol isEncryptedCol( KContainersTableIsRowEncryptedCol, EDbColUint8 );
+ colSet->AddL( isEncryptedCol );
+
+ // Create table.
+
+ iUtils.CreateTableL( KContainersTableName, *colSet );
+
+ CleanupStack::PopAndDestroy( colSet );
+
+ // Create table index.
+ CreateIndexL( KContainersTableName, KContainersTableIdIndex, KContainersTableIdCol );
+
+ OpenTableL();
+
+ __LOG_EXIT
+ } // end CreateTableL
+
+// ==========================================================================
+// FUNCTION: WritePropertiesColumnL
+// ==========================================================================
+void CContainerStoreContainersTable::WritePropertiesColumnL( const TDesC8& aProperties )
+ {
+ __LOG_ENTER_SUPPRESS( "WritePropertiesColumnL" )
+
+ if( aProperties.Length() > 0 )
+ {
+ if ( IsEncrypted() )
+ {
+ EncryptAndWritePropertiesColumnL( aProperties );
+ }
+ else
+ {
+ WriteUnencryptedPropertiesColumnL( aProperties );
+ }
+ }
+ else
+ {
+ iTable.SetColNullL( iPropertiesColNum );
+ } // end if
+
+ } // end WritePropertiesColumnL
+
+// ==========================================================================
+// FUNCTION: ReadPropertiesColumnL
+// ==========================================================================
+void CContainerStoreContainersTable::ReadPropertiesColumnL( RBuf8& aProperties )
+ {
+ __LOG_ENTER_SUPPRESS( "ReadPropertiesColumnL" )
+
+ if ( IsEncrypted() )
+ {
+ ReadAndDescrptPropertiesColumnL( aProperties );
+ }
+ else
+ {
+ ReadUnencryptedPropertiesColumnL( aProperties );
+ }
+ } // end ReadPropertiesColumnL
+
+// ==========================================================================
+// FUNCTION: CreateContainerL
+// ==========================================================================
+void CContainerStoreContainersTable::CreateContainerL( TContainerId aId,
+ TContainerId aParentId,
+ const TDesC8& aProperties,
+ RBuf8& aQuickProperties )
+ {
+ __LOG_ENTER_SUPPRESS( "CreateContainerL" )
+
+ RBuf8 countsBuf;
+ CleanupClosePushL( countsBuf );
+ countsBuf.CreateL( iCountsLength );
+ iCustomBehaviorProvider.InitializeCounts( countsBuf );
+
+ // Insert an entry in the folders table.
+
+ iTable.LastL();
+
+ InsertRowLC();
+
+ iTable.SetColL( iIdColNum, aId );
+ iTable.SetColL( iParentIdColNum, aParentId );
+ iTable.SetColL( iChildrenCountColNum, 0 );
+ iTable.SetColL( iChildrenCountsColNum, countsBuf );
+
+ iTable.SetColL( iIsRowEncryptedColNum, static_cast<TUint8>( iEncryption.IsEncryptionOn() ) );
+
+ WritePropertiesColumnL( aProperties );
+
+ // Add the type bits to the assigned ID.
+ TUint type = aId & KContainerTypeMask;
+
+ UpdateQuickPropertiesAndCountsL( type, aProperties, aQuickProperties, countsBuf );
+
+ _LIT( KMyCounts, "myCounts" );
+ iCustomBehaviorProvider.LogCounts( KMyCounts, countsBuf );
+
+ PutRowUpdatesL();
+
+ if( aParentId != KUncommittedContainers && aParentId != KContainerInvalidId )
+ {
+ SeekL( aParentId );
+ IncrementParentCountsL( countsBuf );
+ } // end if
+
+ CleanupStack::PopAndDestroy( &countsBuf );
+ } // end CreateContainerL
+
+// ==========================================================================
+// FUNCTION: IncrementParentCountsL
+// ==========================================================================
+void CContainerStoreContainersTable::IncrementParentCountsL( const TDesC8& aCountsDelta )
+ {
+ __LOG_ENTER_SUPPRESS( "IncrementParentCountsL" )
+
+ PrepareRowForUpdateLC();
+
+ // Read old values.
+ TUint16 childrenCount = iTable.ColUint16( iChildrenCountColNum );
+
+ RBuf8 countsBuf;
+ CleanupClosePushL( countsBuf );
+ countsBuf.CreateL( iTable.ColDes8( iChildrenCountsColNum ) );
+
+ _LIT( KOldChildrenCounts, "oldChildrenCounts" );
+ iCustomBehaviorProvider.LogCounts( KOldChildrenCounts, countsBuf );
+
+ // Update values.
+ childrenCount++;
+
+ iCustomBehaviorProvider.IncrementParentCounts( countsBuf, aCountsDelta );
+ _LIT( KNewChildrenCounts, "newChildrenCounts" );
+ iCustomBehaviorProvider.LogCounts( KNewChildrenCounts, countsBuf );
+
+ // Write new values to database.
+ iTable.SetColL( iChildrenCountColNum, childrenCount );
+
+ iTable.SetColL( iChildrenCountsColNum, countsBuf );
+ CleanupStack::PopAndDestroy( &countsBuf );
+
+ PutRowUpdatesL();
+
+ } // end IncrementParentCountsL
+
+// ==========================================================================
+// FUNCTION: DecrementParentCountsL
+// ==========================================================================
+void CContainerStoreContainersTable::DecrementParentCountsL( const TDesC8& aCountsDelta )
+ {
+ __LOG_ENTER_SUPPRESS( "DecrementParentCountsL" )
+
+ PrepareRowForUpdateLC();
+
+ // Read old values.
+ TUint16 childrenCount = iTable.ColUint16( iChildrenCountColNum );
+
+ RBuf8 countsBuf;
+ CleanupClosePushL( countsBuf );
+ countsBuf.CreateL( iTable.ColDes8( iChildrenCountsColNum ) );
+
+ _LIT( KOldChildrenCounts, "oldChildrenCounts" );
+ iCustomBehaviorProvider.LogCounts( KOldChildrenCounts, countsBuf );
+
+ // Update values.
+ childrenCount--;
+
+ iCustomBehaviorProvider.DecrementParentCounts( countsBuf, aCountsDelta );
+
+ _LIT( KNewChildrenCounts, "newChildrenCounts" );
+ iCustomBehaviorProvider.LogCounts( KNewChildrenCounts, countsBuf );
+
+ // Write new values to database.
+ iTable.SetColL( iChildrenCountColNum, childrenCount );
+
+ iTable.SetColL( iChildrenCountsColNum, countsBuf );
+ CleanupStack::PopAndDestroy( &countsBuf );
+
+ PutRowUpdatesL();
+ } // end DecrementParentCountsL
+
+// ==========================================================================
+// FUNCTION: UpdateQuickPropertiesAndCountsL
+// ==========================================================================
+void CContainerStoreContainersTable::UpdateQuickPropertiesAndCountsL( TContainerId aType,
+ const TDesC8& aProperties,
+ RBuf8& aQuickProperties,
+ TDes8& aCounts )
+ {
+ __LOG_ENTER_SUPPRESS( "UpdateQuickPropertiesAndCountsL" )
+
+ aQuickProperties.SetLength( 0 );
+
+ iCustomBehaviorProvider.QuickPropertiesAndCountsL( aType,
+ aProperties,
+ aQuickProperties,
+ aCounts );
+
+ __LOG_WRITE8_FORMAT1_INFO( "aQuickProperties.Length()=%i", aQuickProperties.Length() )
+
+ if( aQuickProperties.Length() > 0 )
+ {
+ // The quick properties are not encrypted.
+ iUtils.WriteLongColumnL( iTable,
+ iQuickPropertiesColNum,
+ aQuickProperties );
+ }
+ else
+ {
+ // Clear the quick properties column.
+ iTable.SetColNullL( iQuickPropertiesColNum );
+
+ } // end if
+
+ _LIT( KMyCounts, "myCounts" );
+ iCustomBehaviorProvider.LogCounts( KMyCounts, aCounts );
+
+ iTable.SetColL( iCountsColNum, aCounts );
+ } // end UpdateQuickPropertiesAndCountsL
+
+// ==========================================================================
+// FUNCTION: DeleteL
+// ==========================================================================
+void CContainerStoreContainersTable::DeleteL()
+ {
+ iTable.DeleteL();
+
+ // This function is only called for objects that are already in the "to be deleted" folder hierarchy.
+ // There is no need to update the parent container since the parent container is also part of the
+ // "to be deleted" hierarchy.
+
+ } // end DeleteL
+
+// ==========================================================================
+// FUNCTION: MarkAsDeleteRetryL
+// ==========================================================================
+void CContainerStoreContainersTable::MarkAsDeleteRetryL()
+ {
+ PrepareRowForUpdateLC();
+
+ iTable.SetColL( iParentIdColNum, KToRetryDeleteContainers );
+
+ PutRowUpdatesL();
+ } // end MarkAsDeleteRetryL
+
+// ==========================================================================
+// FUNCTION: MarkForDeleteL
+// ==========================================================================
+void CContainerStoreContainersTable::MarkForDeleteL()
+ {
+ PrepareRowForUpdateLC();
+
+ iTable.SetColL( iParentIdColNum, KToBeDeletedContainers );
+
+ PutRowUpdatesL();
+ } // end MarkForDeleteL
+
+// ==========================================================================
+// FUNCTION: MoveL
+// ==========================================================================
+void CContainerStoreContainersTable::MoveL( TContainerId aNewParentId, TDes8& aTotalCountsDelta )
+ {
+ __LOG_ENTER( "MoveL" )
+
+ // Update the entry's parent ID.
+ TContainerId oldParentId = iTable.ColUint32( iParentIdColNum );
+
+ TUint length = iTable.ColLength( iQuickPropertiesColNum );
+
+ PrepareRowForUpdateLC();
+
+ iTable.SetColL( iParentIdColNum, aNewParentId );
+
+ PutRowUpdatesL();
+
+ RBuf8 myDescendentCounts;
+ CleanupClosePushL( myDescendentCounts );
+ myDescendentCounts.Create( iTable.ColLength( iChildrenCountsColNum ) );
+
+ ChildrenCountsL( myDescendentCounts, ETrue );
+
+ RBuf8 myCounts;
+ CleanupClosePushL( myCounts );
+ myCounts.CreateL( iTable.ColDes8( iCountsColNum ) );
+
+ _LIT( KMyCounts, "myCounts" );
+ iCustomBehaviorProvider.LogCounts( KMyCounts, myCounts );
+
+ iCustomBehaviorProvider.InitializeCounts( aTotalCountsDelta );
+
+ // Increment the new parent container's child counts.
+
+ if( aNewParentId != KToBeDeletedContainers )
+ {
+ SeekL( aNewParentId );
+ IncrementParentCountsL( myCounts );
+ }
+ else
+ {
+ // The item is being deleted. Decrement the total counts.
+ iCustomBehaviorProvider.DecrementParentCounts( aTotalCountsDelta, myCounts );
+ iCustomBehaviorProvider.DecrementParentCounts( aTotalCountsDelta, myDescendentCounts );
+ } // end if
+
+ // Decrement the old parent container's child counts.
+
+ if( oldParentId != KUncommittedContainers )
+ {
+ SeekL( oldParentId );
+ DecrementParentCountsL( myCounts );
+ }
+ else
+ {
+ // The item is being committed. Increment the total counts.
+ iCustomBehaviorProvider.IncrementParentCounts( aTotalCountsDelta, myCounts );
+ iCustomBehaviorProvider.IncrementParentCounts( aTotalCountsDelta, myDescendentCounts );
+ } // end if
+
+ _LIT( KaTotalCountsDelta, "aTotalCountsDelta" );
+ iCustomBehaviorProvider.LogCounts( KaTotalCountsDelta, aTotalCountsDelta );
+
+ CleanupStack::PopAndDestroy( &myCounts );
+ CleanupStack::PopAndDestroy( &myDescendentCounts );
+
+ __LOG_EXIT
+ } // end MoveL
+
+// ==========================================================================
+// FUNCTION: CopyL
+// ==========================================================================
+void CContainerStoreContainersTable::CopyL( TContainerId aNewId, TContainerId aDestinationId, RBuf8& aQuickProperties )
+ {
+ __LOG_ENTER( "Copy" )
+
+ // Copy properties.
+
+ RBuf8 propertiesBuf;
+ CleanupClosePushL( propertiesBuf );
+
+ ReadPropertiesColumnL( propertiesBuf );
+
+ CreateContainerL( aNewId, aDestinationId, propertiesBuf, aQuickProperties );
+
+ CleanupStack::PopAndDestroy( &propertiesBuf );
+
+ __LOG_EXIT
+ } // end CopyL
+
+// ==========================================================================
+// FUNCTION: ChildrenCountsL
+// ==========================================================================
+void CContainerStoreContainersTable::ChildrenCountsL( TDes8& aCounts, TBool aRecursive )
+ {
+ if ( !aRecursive )
+ {
+ aCounts.Copy( iTable.ColDes8( iChildrenCountsColNum ) );
+ }
+ else
+ {
+ RBuf8 totalCounts;
+ CleanupClosePushL( totalCounts );
+ RBuf8 childrenCounts;
+ CleanupClosePushL( childrenCounts );
+
+ TContainerId id = iTable.ColUint32( iIdColNum );
+
+ totalCounts.CreateL( iTable.ColLength( iCountsColNum ) );
+ iCustomBehaviorProvider.InitializeCounts( totalCounts );
+
+ childrenCounts.CreateL( iTable.ColDes8(iChildrenCountsColNum) );
+ iCustomBehaviorProvider.IncrementParentCounts( totalCounts, childrenCounts );
+
+ TDbBookmark bookmark = iTable.Bookmark();
+
+ RArray<TContainerId> childrens;
+ CleanupClosePushL( childrens );
+ ListChildrenL( childrens, id, EMsgStoreFolderBits, ETrue );
+
+ for ( int i = 0 ; i < childrens.Count() ; i++ )
+ {
+ iTable.SeekL( childrens[i] );
+ iTable.GetL();
+ childrenCounts.Copy( iTable.ColDes8(iChildrenCountsColNum) );
+ iCustomBehaviorProvider.IncrementParentCounts( totalCounts, childrenCounts );
+ }
+
+ aCounts.Copy( totalCounts );
+
+ iTable.GotoL( bookmark );
+
+ CleanupStack::PopAndDestroy( &childrens );
+
+ CleanupStack::PopAndDestroy( &childrenCounts );
+ CleanupStack::PopAndDestroy( &totalCounts );
+
+ }
+ } // end ChildrenCountsL
+
+// ==========================================================================
+// FUNCTION: UpdatePropertiesL
+// ==========================================================================
+void CContainerStoreContainersTable::UpdatePropertiesL( const TDesC8& aProperties,
+ RBuf8& aQuickProperties,
+ TDes8& aTotalCountsDelta,
+ TContainerId& aRealParentId )
+ {
+ __LOG_ENTER_SUPPRESS( "UpdatePropertiesL" )
+
+ RBuf8 newCountsBuf;
+ CleanupClosePushL( newCountsBuf );
+
+ RBuf8 oldCountsBuf;
+ CleanupClosePushL( oldCountsBuf );
+
+ PrepareRowForUpdateLC();
+
+ // Read the parent ID of the row.
+ aRealParentId = iTable.ColUint32( iParentIdColNum );
+
+ // Get the old counts.
+ oldCountsBuf.CreateL( iTable.ColDes8( iCountsColNum ) );
+
+ _LIT( KoldmyCountBuf, "old(my)CountBuf" );
+ iCustomBehaviorProvider.LogCounts( KoldmyCountBuf, oldCountsBuf );
+
+ // Update the properties column.
+ WritePropertiesColumnL( aProperties );
+
+ // Update the quick properties and counts columns.
+
+ TContainerId id = iTable.ColUint32( iIdColNum );
+ TContainerId type = (id & KContainerTypeMask);
+
+ newCountsBuf.CreateL( iCountsLength );
+ UpdateQuickPropertiesAndCountsL( type, aProperties, aQuickProperties, newCountsBuf );
+ _LIT(KnewmyCountBuf, "new(my)CountBuf" );
+ iCustomBehaviorProvider.LogCounts( KnewmyCountBuf, newCountsBuf );
+
+ PutRowUpdatesL();
+
+ // The total counts delta is the new counts minus the old counts.
+ aTotalCountsDelta.Copy( newCountsBuf );
+ iCustomBehaviorProvider.DecrementParentCounts( aTotalCountsDelta, oldCountsBuf );
+
+ _LIT( KaTotalCountsDelta, "aTotalCountsDelta" );
+ iCustomBehaviorProvider.LogCounts( KaTotalCountsDelta, aTotalCountsDelta );
+
+ if( aRealParentId != KUncommittedContainers )
+ {
+ SeekL( aRealParentId );
+
+ // Decrement the parent row's counts by the old count values.
+ DecrementParentCountsL( oldCountsBuf );
+
+ // Increment the parent row's counts by the new count values.
+ IncrementParentCountsL( newCountsBuf );
+
+ } // end if
+
+ CleanupStack::PopAndDestroy( &oldCountsBuf );
+ CleanupStack::PopAndDestroy( &newCountsBuf );
+
+ } // end UpdatePropertiesL
+
+// ==========================================================================
+// FUNCTION: UpdatePropertyL
+// ==========================================================================
+void CContainerStoreContainersTable::UpdatePropertyL( const TDesC8& aName,
+ TUint8 aType,
+ const TDesC8& aValue,
+ RBuf8& aQuickProperties,
+ TDes8& aTotalCountsDelta,
+ TContainerId& aRealParentId )
+ {
+ __LOG_ENTER_SUPPRESS( "UpdatePropertyL" )
+
+ RBuf8 propertiesBuf;
+ CleanupClosePushL( propertiesBuf );
+ ReadPropertiesColumnL( propertiesBuf );
+
+ // Look for an existing occurrence of the property.
+
+ TPropertiesSerializer serializer( propertiesBuf );
+
+ TBool found = serializer.Find( aName );
+
+ if( found )
+ {
+ // Property already exists. Replace the value length and value.
+ serializer.UpdateValueL( aValue );
+ }
+ else
+ {
+ // Add the property.
+ serializer.AddPropertyL( aName, aType, aValue );
+ } // end if
+
+ UpdatePropertiesL( propertiesBuf, aQuickProperties, aTotalCountsDelta, aRealParentId );
+
+ CleanupStack::PopAndDestroy( &propertiesBuf );
+
+ } // end UpdatePropertyL
+
+// ==========================================================================
+// FUNCTION: PropertiesL
+// ==========================================================================
+void CContainerStoreContainersTable::PropertiesL( RBuf8& aProperties )
+ {
+ ReadPropertiesColumnL( aProperties );
+
+ } // end PropertiesL
+
+// ==========================================================================
+// FUNCTION: PropertiesSizeL
+// ==========================================================================
+TUint CContainerStoreContainersTable::PropertiesSizeL( TContainerId aId )
+ {
+ SeekL( aId );
+ return iTable.ColLength( iPropertiesColNum );
+ } // end PropertiesSizeL
+
+// ==========================================================================
+// FUNCTION: QuickPropertiesL
+// ==========================================================================
+void CContainerStoreContainersTable::QuickPropertiesL( RBuf8& aQuickProperties )
+ {
+ // Quick properties are not encrypted
+ iUtils.ReadLongColumnL( iTable, iQuickPropertiesColNum, aQuickProperties );
+
+ } // end PropertiesL
+
+// ==========================================================================
+// FUNCTION: ListChildrenL
+// ==========================================================================
+void CContainerStoreContainersTable::ListChildrenL( RArray<TContainerId>& aChildren, TContainerId aId, TContainerId aType, TBool aRecursive )
+ {
+ __LOG_ENTER_SUPPRESS( "ListChildrenL" )
+
+ aChildren.Reset();
+
+ const TUint bufSsize = 200;
+ TBuf<bufSsize> queryString;
+
+ queryString.Copy( KSelect );
+ queryString.Append( KContainersTableIdCol );
+
+ // Only need the children count if this is a recursive search.
+ if( aRecursive )
+ {
+ queryString.Append( KComma );
+ queryString.Append( KContainersTableChildrenCountCol );
+ } // end if
+
+ queryString.Append( KFrom );
+ queryString.Append( KContainersTableName );
+ queryString.Append( KWhere );
+
+ // If the requested type isn't "any", then narrow down the query.
+ if( aType != KContainerTypeAny )
+ {
+ const TContainerId lowestId = aType;
+ const TContainerId highestId = (aType | ~KContainerTypeMask );
+
+ queryString.Append( KContainersTableIdCol );
+ queryString.Append( KGreaterThanOrEqualTo );
+ queryString.AppendNum( lowestId );
+ queryString.Append( KAnd );
+ queryString.Append( KContainersTableIdCol );
+ queryString.Append( KLessThanOrEqualTo );
+ queryString.AppendNum( highestId );
+ queryString.Append( KAnd );
+ } // end if
+
+ queryString.Append( KContainersTableParentIdCol );
+ queryString.Append( KEqualTo );
+
+ TInt queryLengthWithoutId = queryString.Length();
+
+ RDbView view;
+ CleanupClosePushL( view );
+
+ const TUint granularity = 25;
+ RArray<TContainerId> toBeSearched( granularity );
+ CleanupClosePushL( toBeSearched );
+
+ toBeSearched.Append( aId );
+
+ const TInt idColNum = 1;
+ const TInt childrenCountColNum = 2;
+
+ while( toBeSearched.Count() > 0 )
+ {
+ // Update the query to query the next ID to be searched.
+ queryString.SetLength( queryLengthWithoutId );
+ queryString.AppendNum( toBeSearched[0] );
+ toBeSearched.Remove( 0 );
+
+ if ( aType == EMsgStorePartBits )
+ {
+ //must sort the message parts by containerId in ascending order
+ // to preserve the same order as they are created
+ queryString.Append( KOrderBy );
+ queryString.Append( KContainersTableIdCol );
+ queryString.Append( KAsc );
+ __LOG_WRITE_INFO("Using order by in query");
+ }
+
+ iUtils.PopulateViewL( view, queryString );
+
+ TBool found = view.FirstL();
+
+ // Add the IDs in the view to the children array.
+ while( found )
+ {
+ view.GetL();
+
+ TUint32 cid = view.ColUint32( idColNum );
+ __LOG_WRITE_FORMAT1_INFO("Id=%x", cid);
+ aChildren.Append( cid );
+
+ // Search the container for children if this a recursive search and the child count is
+ // greater than 0.
+ if( aRecursive && ( view.ColUint32( childrenCountColNum ) > 0 ) )
+ {
+ toBeSearched.Append( view.ColUint32( idColNum ) );
+ } // end if
+
+ found = view.NextL();
+
+ } // end while
+
+ // Most close old view before preparing new one, otherwise a memory leak occurs.
+ view.Close();
+
+ } // end while
+
+ CleanupStack::PopAndDestroy( &toBeSearched );
+ CleanupStack::PopAndDestroy( &view );
+
+ } // end ListChildrenL
+
+
+// ==========================================================================
+// FUNCTION: EncryptFirstL
+// ==========================================================================
+TBool CContainerStoreContainersTable::EncryptFirstL( TDbBookmark& aNextRow )
+ {
+ __LOG_ENTER_SUPPRESS("EncryptFirstL")
+
+ TBool found = iUtils.FindFirstEncryptedOrUnencryptedL( iTable, KContainersTableIsRowEncryptedCol, EFalse, aNextRow );
+
+ return found;
+ }
+
+// ==========================================================================
+// FUNCTION: EncryptNextL
+// ==========================================================================
+TBool CContainerStoreContainersTable::EncryptNextL( TDbBookmark& aNextRow, TContainerId& aEncryptedContainerId )
+ {
+ __LOG_ENTER_SUPPRESS("EncryptNextL")
+
+ TBool hasMore = EFalse;
+ TContainerId id = KContainerInvalidId;
+
+ TRAPD( err, id = GotoL( aNextRow ) );
+ if ( err == KErrNotFound )
+ {
+ hasMore = EncryptFirstL( aNextRow );
+ }
+ else if ( err != KErrNone )
+ {
+ User::Leave( err );
+ }
+ else
+ {
+ if ( !IsEncrypted() )
+ {
+ RBuf8 propertyBuf;
+ CleanupClosePushL( propertyBuf );
+
+ //read the unencrypted properties and write the enctypted properties back
+ ReadUnencryptedPropertiesColumnL( propertyBuf );
+
+ PrepareRowForUpdateLC();
+
+ EncryptAndWritePropertiesColumnL( propertyBuf );
+
+ //update the encrypted flag
+ SetEncryptedL( ETrue );
+
+ PutRowUpdatesL();
+
+ CleanupStack::PopAndDestroy( &propertyBuf );
+
+ //set the encryptedConteinerId so that the caller can encrypt its content
+ aEncryptedContainerId = id;
+ }
+
+ hasMore = iTable.NextL();
+ if ( hasMore )
+ {
+ __LOG_WRITE_INFO("hasMore is TRUE")
+ aNextRow = iTable.Bookmark();
+ }
+ }
+
+ return hasMore;
+ }
+
+// ==========================================================================
+// FUNCTION: DecryptFirstL
+// ==========================================================================
+TBool CContainerStoreContainersTable::DecryptFirstL( TDbBookmark& aNextRow )
+ {
+ __LOG_ENTER("DecryptFirstL")
+
+ TBool found = iUtils.FindFirstEncryptedOrUnencryptedL( iTable, KContainersTableIsRowEncryptedCol, ETrue, aNextRow );
+
+ __LOG_EXIT
+
+ return found;
+ }
+
+// ==========================================================================
+// FUNCTION: DecryptNextL
+// ==========================================================================
+TBool CContainerStoreContainersTable::DecryptNextL( TDbBookmark& aNextRow, TContainerId& aDecryptedContainerId )
+ {
+ __LOG_ENTER_SUPPRESS("DecryptNextL")
+
+ TBool hasMore = EFalse;
+ TContainerId id = KContainerInvalidId;
+
+ TRAPD( err, id = GotoL( aNextRow ) );
+ if ( err == KErrNotFound )
+ {
+ hasMore = DecryptFirstL( aNextRow );
+ }
+ else if ( err != KErrNone )
+ {
+ User::Leave( err );
+ }
+ else
+ {
+ if ( IsEncrypted() )
+ {
+ RBuf8 propertyBuf;
+ CleanupClosePushL( propertyBuf );
+
+ //the row is currentlly encryptted
+ //read the encrypted properties and write the unenctypted properties back
+ ReadAndDescrptPropertiesColumnL( propertyBuf );
+
+ PrepareRowForUpdateLC();
+
+ WriteUnencryptedPropertiesColumnL( propertyBuf );
+
+ //update the encrypted flag
+ SetEncryptedL( EFalse );
+
+ PutRowUpdatesL();
+
+ CleanupStack::PopAndDestroy( &propertyBuf );
+
+ //set the aDecryptedContainerId so that the caller can decrypt its content
+ aDecryptedContainerId = id;
+ }
+
+
+ hasMore = iTable.NextL();
+ if ( hasMore )
+ {
+ __LOG_WRITE_INFO("hasMore is TRUE")
+ aNextRow = iTable.Bookmark();
+ }
+ }
+
+ return hasMore;
+ }
+
+// ==========================================================================
+// FUNCTION: ReadAndDescrptPropertiesColumnL
+// ==========================================================================
+void CContainerStoreContainersTable::ReadAndDescrptPropertiesColumnL( RBuf8& aProperties )
+ {
+ __LOG_ENTER_SUPPRESS( "ReadPropertiesColumnL" )
+
+ RBuf8 encryptedBuffer;
+ CleanupClosePushL( encryptedBuffer );
+
+ iUtils.ReadLongColumnL( iTable, iPropertiesColNum, encryptedBuffer );
+
+ if( aProperties.Length() < encryptedBuffer.Length() )
+ {
+ aProperties.ReAllocL( encryptedBuffer.Length() );
+ } // end if
+
+ if( encryptedBuffer.Length() > 0 )
+ {
+ iEncryption.DecryptL( encryptedBuffer, aProperties );
+ iEncryption.RemovePaddingL( aProperties );
+ } // end if
+
+ CleanupStack::PopAndDestroy( &encryptedBuffer );
+ }
+
+// ==========================================================================
+// FUNCTION: EncryptAndWritePropertiesColumnL
+// ==========================================================================
+void CContainerStoreContainersTable::EncryptAndWritePropertiesColumnL( const TDesC8& aProperties )
+ {
+ __LOG_ENTER_SUPPRESS( "EncryptAndWritePropertiesColumnL" )
+
+ if ( aProperties.Length() > 0 )
+ {
+ RBuf8 encryptedBuffer;
+ encryptedBuffer.CreateL( aProperties.Length() + iEncryption.BlockSizeL() );
+ CleanupClosePushL( encryptedBuffer );
+
+ RBuf8 paddedBuffer;
+ paddedBuffer.CreateL( aProperties.Length() + iEncryption.BlockSizeL() );
+ CleanupClosePushL( paddedBuffer );
+
+ paddedBuffer.Copy( aProperties );
+ iEncryption.AddPaddingL( paddedBuffer, iEncryption.BlockSizeL() );
+
+ iEncryption.EncryptL( paddedBuffer, encryptedBuffer );
+
+ CleanupStack::PopAndDestroy( &paddedBuffer );
+
+ iUtils.WriteLongColumnL( iTable, iPropertiesColNum, encryptedBuffer );
+
+ CleanupStack::PopAndDestroy( &encryptedBuffer );
+ }
+ else
+ {
+ iTable.SetColNullL( iPropertiesColNum );
+ }
+ }
+
+// ==========================================================================
+// FUNCTION: ReadUnencryptedPropertiesColumnL
+// ==========================================================================
+void CContainerStoreContainersTable::ReadUnencryptedPropertiesColumnL( RBuf8& aProperties )
+ {
+ iUtils.ReadLongColumnL( iTable, iPropertiesColNum, aProperties );
+ }
+
+// ==========================================================================
+// FUNCTION: WriteUnencryptedPropertiesColumnL
+// ==========================================================================
+void CContainerStoreContainersTable::WriteUnencryptedPropertiesColumnL( const TDesC8& aProperties )
+ {
+ iUtils.WriteLongColumnL( iTable, iPropertiesColNum, aProperties );
+ }
+
+// ==========================================================================
+// FUNCTION: IsEncrypted
+// ==========================================================================
+TBool CContainerStoreContainersTable::IsEncrypted()
+ {
+ TBool isEncrypted = static_cast<TBool>( iTable.ColUint8( iIsRowEncryptedColNum ) );
+ return isEncrypted;
+ }
+
+// ==========================================================================
+// FUNCTION: SetEncryptedL
+// ==========================================================================
+void CContainerStoreContainersTable::SetEncryptedL( TBool aIsEncrypted )
+ {
+ iTable.SetColL( iIsRowEncryptedColNum, static_cast<TUint8>(aIsEncrypted) );
+ }
+
+