ncdengine/provider/storage/src/ncddatabasestorageimpl.cpp
changeset 0 ba25891c3a9e
equal deleted inserted replaced
-1:000000000000 0:ba25891c3a9e
       
     1 /*
       
     2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:   ?Description
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "ncddatabasestorageimpl.h"
       
    20 
       
    21 #include <bamdesca.h>
       
    22 #include <bautils.h>
       
    23 
       
    24 #include "ncdstoragedataitem.h"
       
    25 #include "ncdstoragepanics.pan"
       
    26 #include "ncdpanics.h"
       
    27 #include "catalogsutils.h"
       
    28 #include "ncddatabaseitems.h"
       
    29 
       
    30 
       
    31 //#include "catalogsdebug.h"
       
    32 
       
    33 // disable logging for this file
       
    34 #undef DLTRACEIN
       
    35 #define DLTRACEIN( x )
       
    36 
       
    37 #undef DLTRACEOUT
       
    38 #define DLTRACEOUT( x )
       
    39 
       
    40 #undef DLTRACE
       
    41 #define DLTRACE( x )
       
    42 
       
    43 #undef DLINFO
       
    44 #define DLINFO( x )
       
    45 
       
    46 #undef DLERROR
       
    47 #define DLERROR( x )
       
    48 
       
    49 #undef DASSERT
       
    50 #define DASSERT( x )
       
    51 
       
    52 
       
    53 // SQL statement for creation of the database table
       
    54 _LIT( KNcdSqlCreateStorageTable, "\
       
    55  CREATE TABLE storage (\
       
    56  row_id COUNTER,\
       
    57  item_id LONG VARCHAR,\
       
    58  item_type INTEGER,\
       
    59  item_data LONG VARBINARY)" );
       
    60 
       
    61 enum TNcdDatabaseTableColumns
       
    62     {
       
    63     ENcdDatabaseTableColumnsId = 1,
       
    64     ENcdDatabaseTableColumnsItemId,
       
    65     ENcdDatabaseTableColumnsItemType,
       
    66     ENcdDatabaseTableColumnsItemData
       
    67     };
       
    68 
       
    69 
       
    70 // SQL statement for deleting a row from the database table
       
    71 _LIT( KNcdSqlRemoveItem, "DELETE FROM storage WHERE row_id = %d" );
       
    72 
       
    73 // These are used for removing everything else but some certain ids from a db
       
    74 _LIT( KNcdSqlRemoveItemsStart, "DELETE FROM storage WHERE " );           
       
    75 _LIT( KNcdSqlRemoveItemType, "NOT ( item_type = %d" );
       
    76 _LIT( KNcdSqlRemoveItemAnd, " AND " );
       
    77 _LIT( KNcdSqlRemoveItemStart, " AND ( item_id = '" );        
       
    78 _LIT( KNcdSqlRemoveItemStartNoType, " NOT (( item_id = '" );        
       
    79 _LIT( KNcdSqlRemoveItemOrId, "' OR item_id = '" );
       
    80 _LIT( KNcdSqlRemoveItemEnd, "'))" );
       
    81 _LIT( KNcdSqlRemoveItemEmptyEnd, ")" );
       
    82 
       
    83 
       
    84 // Select one item from the database by item id and type
       
    85 _LIT( KNcdSqlSelectOneRowByIdAndType,  "SELECT * FROM storage WHERE item_id = '%S' AND item_type = %d" );
       
    86 
       
    87 // Select one item from the database by item key
       
    88 _LIT( KNcdSqlSelectOneRowByKey,  "SELECT * FROM storage WHERE row_id = %d" );
       
    89 
       
    90 // Select all items from the database
       
    91 _LIT( KNcdSqlSelectAll,  "SELECT * FROM storage" );
       
    92 
       
    93 // File extension for database file
       
    94 _LIT( KNcdDatabaseFileExtension, "*.db" );
       
    95 
       
    96 // Amount of disk space in bytes that database is
       
    97 // allowed to waste before it is compressed
       
    98 const TInt KNcdMaxDatabaseWastedSpace = 100000;
       
    99 
       
   100 
       
   101 
       
   102 // ---------------------------------------------------------------------------
       
   103 // 
       
   104 // ---------------------------------------------------------------------------
       
   105 //
       
   106 CNcdDatabaseStorage::~CNcdDatabaseStorage()
       
   107     {
       
   108     DLTRACEIN(( "this-ptr: %X", this ));
       
   109     DoClose();
       
   110 
       
   111     if ( iDatabaseFileName ) 
       
   112         {
       
   113         DLTRACE(( _L("Database filename: %S"), iDatabaseFileName ));
       
   114         }
       
   115     delete iDatabaseFileName;
       
   116     DLTRACEOUT((""));
       
   117     }
       
   118 
       
   119 
       
   120 // ---------------------------------------------------------------------------
       
   121 // 
       
   122 // ---------------------------------------------------------------------------
       
   123 //
       
   124 CNcdDatabaseStorage* CNcdDatabaseStorage::NewL(
       
   125     RFs& aFs,
       
   126     const TDesC& aUid,
       
   127     const TDesC& aStorageFolder,
       
   128     const TDesC& aName )
       
   129     {
       
   130     DLTRACEIN(( _L("Uid: %S, folder: %S, name: %S"), &aUid, &aStorageFolder,
       
   131         &aName ));
       
   132         
       
   133     HBufC* uid = aUid.AllocLC();
       
   134     HBufC* storageFolder = aStorageFolder.AllocLC();
       
   135     HBufC* name = aName.AllocLC();
       
   136 
       
   137     DLTRACE(("Creating CNcdDatabaseStorage"));
       
   138     CNcdDatabaseStorage* storage = new (ELeave) CNcdDatabaseStorage( 
       
   139         aFs, uid, storageFolder, name );
       
   140     DLINFO(("CNcdDatabaseStorage created"));
       
   141     CleanupStack::Pop( 3 ); // uid, storageFolder, name
       
   142     
       
   143     DLTRACE(("storage-ptr: %X", storage));
       
   144     DASSERT( storage );
       
   145     CleanupStack::PushL( storage );
       
   146     DLTRACE(("Calling constructL"));
       
   147     storage->ConstructL();
       
   148     CleanupStack::Pop( storage );    
       
   149     
       
   150     return storage;
       
   151     }
       
   152 
       
   153 
       
   154 // ---------------------------------------------------------------------------
       
   155 // 
       
   156 // ---------------------------------------------------------------------------
       
   157 //
       
   158 CNcdDatabaseStorage::CNcdDatabaseStorage( 
       
   159     RFs& aFs,
       
   160     HBufC* aUid, HBufC* aStorageFolder, HBufC* aName ) :
       
   161     CNcdStorageBase( aUid, aStorageFolder, aName ),
       
   162     iFs( aFs ),
       
   163     iDatabaseFileName( NULL ),
       
   164     iUpdated( EFalse ),
       
   165     iWastedSpace( 0 ),
       
   166     iNewWastedSpace( 0 )
       
   167     {    
       
   168     }
       
   169 
       
   170 
       
   171 // ---------------------------------------------------------------------------
       
   172 // 
       
   173 // ---------------------------------------------------------------------------
       
   174 //
       
   175 void CNcdDatabaseStorage::ConstructL()
       
   176     {    
       
   177     DLTRACEIN(( _L("StorageFolder: %S, Name: %S"), iStorageFolder, iName ));
       
   178     TParse fileName;
       
   179     
       
   180     fileName.Set( *iStorageFolder, iName, &KNcdDatabaseFileExtension );
       
   181     iDatabaseFileName = fileName.FullName().AllocL();
       
   182     
       
   183     DLTRACEOUT(( _L("Fullname: %S"), iDatabaseFileName ));
       
   184     }
       
   185 
       
   186 
       
   187 // ---------------------------------------------------------------------------
       
   188 // Compact
       
   189 // ---------------------------------------------------------------------------
       
   190 //    
       
   191 void CNcdDatabaseStorage::Compact()
       
   192     {
       
   193     DLTRACEIN((""))
       
   194     iDb.Compact();
       
   195     }
       
   196 
       
   197 
       
   198 // ---------------------------------------------------------------------------
       
   199 // 
       
   200 // ---------------------------------------------------------------------------
       
   201 //    
       
   202 RDbDatabase::TSize CNcdDatabaseStorage::Size() const
       
   203     {
       
   204     if( iOpen )
       
   205         {
       
   206         return iDb.Size();
       
   207         }
       
   208     else
       
   209         {
       
   210         User::Panic( KNcdStoragePanic, ENcdStoragePanicStorageNotOpen );
       
   211         }
       
   212     
       
   213     // For compiler
       
   214     return RDbDatabase::TSize();
       
   215     }
       
   216 
       
   217 
       
   218 // ---------------------------------------------------------------------------
       
   219 // 
       
   220 // ---------------------------------------------------------------------------
       
   221 //
       
   222 TInt CNcdDatabaseStorage::DoCommit()
       
   223     {
       
   224     DLTRACEIN(( "this-ptr: %X", this ));
       
   225     if( iDb.InTransaction() )
       
   226         {
       
   227         TRAPD( err, CloseTransactionL( ETrue ) );
       
   228         return err;
       
   229         }
       
   230     else
       
   231         {
       
   232         DLTRACE(("Nothing to commit"));
       
   233         return KErrNone;
       
   234         }
       
   235     }
       
   236 
       
   237 
       
   238 // ---------------------------------------------------------------------------
       
   239 // 
       
   240 // ---------------------------------------------------------------------------
       
   241 //
       
   242 void CNcdDatabaseStorage::DoOpenL()
       
   243     {
       
   244     DLTRACEIN(("this-ptr: %X", this));
       
   245     //User::LeaveIfError( iFs.Connect() );
       
   246     
       
   247     DLTRACE((_L("Opening database: %S"), iDatabaseFileName ));
       
   248     // Try to open the database
       
   249     TInt err = iDb.Open( iFs, *iDatabaseFileName );
       
   250 
       
   251     if( err == KErrNone )
       
   252         {       
       
   253         if ( iDb.IsDamaged() ) 
       
   254             {
       
   255             DLTRACE(( "DB is damaged, try to recover" ));            
       
   256             TInt recoverErr = iDb.Recover();
       
   257             if ( recoverErr != KErrNone ) 
       
   258                 {
       
   259                 DLTRACE(("DB couldn't be recovered, recreate it"));
       
   260                 RecreateDatabaseL();
       
   261                 }
       
   262             }
       
   263             
       
   264         iDb.Compact();        
       
   265         }
       
   266     else if( err == KErrNotFound ) // If not found, create it
       
   267         {
       
   268         DLINFO(( "Data base file not found. New one is created." ));
       
   269         RecreateDatabaseL();
       
   270         }
       
   271     else if ( err == KErrCorrupt || err == KErrEof ) 
       
   272         {
       
   273         DLINFO(("Database corrupted! Create new one"));
       
   274         RecreateDatabaseL();
       
   275         }
       
   276     else
       
   277         {
       
   278         DLERROR(( "Failed with err: %i", err ));
       
   279         User::Leave( err );
       
   280         }
       
   281     DLTRACEOUT((""));
       
   282     }
       
   283     
       
   284 
       
   285 // ---------------------------------------------------------------------------
       
   286 // 
       
   287 // ---------------------------------------------------------------------------
       
   288 //
       
   289 void CNcdDatabaseStorage::DoClose()
       
   290     {
       
   291     DLTRACEIN(("this-ptr: %X", this));
       
   292     if( iOpen && iDb.InTransaction() )
       
   293         {
       
   294         DLTRACE(("Rollback"));
       
   295         iDb.Rollback();
       
   296         }
       
   297 
       
   298     DLINFO(("Close db"));
       
   299     iDb.Close();      
       
   300     DLINFO(("db closed"));
       
   301   
       
   302     iWastedSpace = 0;
       
   303     iNewWastedSpace = 0;
       
   304     iUpdated = EFalse;
       
   305 
       
   306     DLTRACEOUT((""));
       
   307     }
       
   308 
       
   309 
       
   310 // ---------------------------------------------------------------------------
       
   311 // 
       
   312 // ---------------------------------------------------------------------------
       
   313 //
       
   314 CNcdStorageItem* CNcdDatabaseStorage::CreateStorageItemLC( const TDesC& aUid, 
       
   315     TInt aType )
       
   316     {
       
   317     DLTRACEIN(( "this-ptr: %X",this ));
       
   318     CNcdDatabaseStorageItem* item = CNcdDatabaseStorageItem::NewLC( this, aUid, 
       
   319         aType );    
       
   320 
       
   321     // Begin transaction if not already began
       
   322     BeginTransactionL();
       
   323 
       
   324     RDbView dbView;
       
   325     ReadItemDataLC( dbView, aUid, aType, RDbRowSet::EUpdatable );
       
   326 
       
   327     
       
   328     if( !dbView.FirstL() ) // Item doesn't exist in database. Create it.
       
   329         {
       
   330         // Add new row
       
   331         dbView.InsertL();
       
   332 
       
   333         // Write uid to newly created row
       
   334         dbView.SetColL( ENcdDatabaseTableColumnsItemId, aUid );
       
   335 
       
   336         // Write type to newly created row
       
   337         dbView.SetColL( ENcdDatabaseTableColumnsItemType, aType );
       
   338         
       
   339         // Confirms row addition
       
   340         // This doesn't commit row to the database if transaction is started
       
   341         // In this case the row is not permanently inserted to database until the
       
   342         // last open item is closed and transaction commited.
       
   343         dbView.PutL();
       
   344         }
       
   345 
       
   346     dbView.GetL(); // Get item data
       
   347     
       
   348      // Read key column from db table and store it to the item
       
   349     item->SetDbKey( dbView.ColUint32( ENcdDatabaseTableColumnsId ) );
       
   350 
       
   351     CleanupStack::PopAndDestroy( &dbView );    
       
   352 
       
   353     return item;
       
   354     }
       
   355 
       
   356 
       
   357 // ---------------------------------------------------------------------------
       
   358 // 
       
   359 // ---------------------------------------------------------------------------
       
   360 //
       
   361 void CNcdDatabaseStorage::GetAllItemsFromStorageL( 
       
   362     RPointerArray<CNcdStorageItemIdentifier>& aItems )
       
   363     {
       
   364     DLTRACEIN(( "this-ptr: %X",this ));
       
   365     CleanupResetAndDestroyPushL( aItems );
       
   366     
       
   367     RDbView dbView;    
       
   368     
       
   369     // Read all data from database
       
   370     User::LeaveIfError( dbView.Prepare( iDb, TDbQuery( KNcdSqlSelectAll ), 
       
   371         RDbRowSet::EReadOnly ) );
       
   372 
       
   373     CleanupClosePushL( dbView );
       
   374     
       
   375     User::LeaveIfError( dbView.EvaluateAll() );
       
   376 
       
   377     dbView.BeginningL();
       
   378 
       
   379     RDbColReadStream readStream;
       
   380     
       
   381     TInt count = dbView.CountL( RDbRowSet::EQuick );
       
   382     if ( count && count != KDbUndefinedCount ) 
       
   383         {
       
   384         DLTRACE(("Reserving %d slots for the items array", count ));
       
   385         aItems.ReserveL( count );
       
   386         }
       
   387     // Loop through the whole record set and store
       
   388     // item ids and types to array
       
   389     while( dbView.NextL() )
       
   390         {
       
   391         dbView.GetL();
       
   392 
       
   393         TInt type = dbView.ColInt( ENcdDatabaseTableColumnsItemType );
       
   394 
       
   395         readStream.OpenLC( dbView, ENcdDatabaseTableColumnsItemId );
       
   396 
       
   397         HBufC8* id = GetAllDataLC( readStream );
       
   398                    
       
   399         CNcdStorageItemIdentifier* itemIdentifier = 
       
   400             CNcdStorageItemIdentifier::NewLC(
       
   401                 *id,
       
   402                 type );
       
   403 
       
   404         aItems.AppendL( itemIdentifier );
       
   405 
       
   406         CleanupStack::Pop( itemIdentifier );
       
   407         CleanupStack::PopAndDestroy( 2, &readStream ); // id, readStream
       
   408 
       
   409         }
       
   410 
       
   411     CleanupStack::PopAndDestroy( &dbView );
       
   412     CleanupStack::Pop( &aItems );
       
   413 
       
   414     }
       
   415 
       
   416 
       
   417 // ---------------------------------------------------------------------------
       
   418 // 
       
   419 // ---------------------------------------------------------------------------
       
   420 //
       
   421 HBufC8* CNcdDatabaseStorage::DoGetDataL( CNcdStorageItem* aItem )
       
   422     {
       
   423     DLTRACEIN(( "this-ptr: %X", this ));
       
   424     CNcdDatabaseStorageItem* item = (CNcdDatabaseStorageItem*) aItem;
       
   425 
       
   426     HBufC8* dataBuffer = NULL;
       
   427 
       
   428     RDbView dbView;
       
   429     ReadItemDataLC( dbView, item->DbKey() );
       
   430 
       
   431     if( dbView.FirstL() )
       
   432         {
       
   433         dbView.GetL();
       
   434 
       
   435         RDbColReadStream readStream;
       
   436         readStream.OpenLC( dbView, ENcdDatabaseTableColumnsItemData );
       
   437         dataBuffer = GetAllDataL( readStream );
       
   438         CleanupStack::PopAndDestroy( &readStream );
       
   439         }
       
   440     else
       
   441         {
       
   442         DLINFO(("Didn't find the item. Leaving with KErrNotFound"));
       
   443         // Item not found.
       
   444         User::Leave( KErrNotFound );
       
   445         }
       
   446 
       
   447     CleanupStack::PopAndDestroy( &dbView );
       
   448     DLTRACEOUT((""));
       
   449     return dataBuffer;
       
   450     }
       
   451 
       
   452 
       
   453 // ---------------------------------------------------------------------------
       
   454 // 
       
   455 // ---------------------------------------------------------------------------
       
   456 //
       
   457 void CNcdDatabaseStorage::DoRemoveItemsL( 
       
   458     const RArray<RNcdDatabaseItems>& aDoNotRemoveItems )
       
   459     {
       
   460     DLTRACEIN((""));
       
   461     NCD_ASSERT_ALWAYS( aDoNotRemoveItems.Count(), ENcdPanicInvalidArgument );
       
   462         
       
   463    
       
   464 /*
       
   465     This is the intended output:
       
   466     DELETE FROM storage WHERE 
       
   467         NOT ( item_type = 5 AND ( item_id = 'id1' OR item_id = 'id2' ))
       
   468         AND NOT ( item_type = 6 AND ( item_id = 'id3' OR item_id = 'id2' )) 
       
   469         AND NOT ( item_id = 'id4' )
       
   470 */    
       
   471     
       
   472     TInt sqlStatementSize = KNcdSqlRemoveItemsStart().Length();
       
   473         
       
   474     TInt count = aDoNotRemoveItems.Count();
       
   475     while ( count-- ) 
       
   476         {
       
   477         sqlStatementSize += 
       
   478             CalculateSqlRemovalLength( aDoNotRemoveItems[ count ] ) +
       
   479             KNcdSqlRemoveItemAnd().Length();
       
   480         
       
   481         }
       
   482     
       
   483     DLTRACE(("Max length of sql statement: %d", sqlStatementSize ));
       
   484     // SQL statement
       
   485     HBufC* sqlBuf = HBufC::NewLC( sqlStatementSize );
       
   486     TPtr sql = sqlBuf->Des();
       
   487     
       
   488     // DELETE FROM storage WHERE
       
   489     sql.Append( KNcdSqlRemoveItemsStart );    
       
   490            
       
   491     count = aDoNotRemoveItems.Count();
       
   492     for ( TInt i = 0; i < count; ++i )
       
   493         {
       
   494         DASSERT( aDoNotRemoveItems[i].iType != KErrNotFound ||
       
   495                  aDoNotRemoveItems[i].Uids().MdcaCount() );
       
   496                  
       
   497         if ( aDoNotRemoveItems[i].iType != KErrNotFound ) 
       
   498             {            
       
   499             // NOT ( item_type = x
       
   500             sql.AppendFormat( KNcdSqlRemoveItemType, aDoNotRemoveItems[i].iType );
       
   501             }
       
   502             
       
   503         if ( aDoNotRemoveItems[i].Uids().MdcaCount() ) 
       
   504             {
       
   505             const MDesCArray& uids = aDoNotRemoveItems[i].Uids();
       
   506             TInt uidCount = uids.MdcaCount();
       
   507             
       
   508             // append first item
       
   509             // AND ( item_id = '
       
   510             if ( aDoNotRemoveItems[i].iType != KErrNotFound ) 
       
   511                 {                
       
   512                 sql.Append( KNcdSqlRemoveItemStart );
       
   513                 }
       
   514             else 
       
   515                 {
       
   516                 // NOT (( item_id = '
       
   517                 sql.Append( KNcdSqlRemoveItemStartNoType );
       
   518                 }
       
   519                 
       
   520             sql.Append( uids.MdcaPoint( 0 ) );
       
   521             DLTRACE(( _L("Added: %S"), &uids.MdcaPoint( 0 ) ));
       
   522             
       
   523             for ( TInt u = 1; u < uidCount; ++u ) 
       
   524                 {
       
   525                 // ' OR item_id = '
       
   526                 sql.Append( KNcdSqlRemoveItemOrId ); 
       
   527                 sql.Append( uids.MdcaPoint( u ) );
       
   528                 DLTRACE(( _L("Added: %S"), &uids.MdcaPoint( u ) ));
       
   529                 }
       
   530             // '))    
       
   531             sql.Append( KNcdSqlRemoveItemEnd );
       
   532             }
       
   533         else 
       
   534             {
       
   535             DLTRACE(("No uids for type: %d", aDoNotRemoveItems[i].iType ));
       
   536             
       
   537             // )
       
   538             sql.Append( KNcdSqlRemoveItemEmptyEnd );
       
   539             }
       
   540         
       
   541         // and needed for others but the last        
       
   542         if ( i < count - 1 ) 
       
   543             {
       
   544             // AND
       
   545             sql.Append( KNcdSqlRemoveItemAnd );        
       
   546             }            
       
   547         }
       
   548 
       
   549     DLINFO(( _L("Sql: %S"), sqlBuf ));
       
   550     
       
   551     // Begin transaction if not already began
       
   552     TBool newTransaction = BeginTransactionL();
       
   553 
       
   554     DLINFO((" DB size before remove: %d", iDb.Size() ));
       
   555     
       
   556     // Deletes row from the database
       
   557     // Returns number of deleted rows if success
       
   558     // Otherwise returns error code
       
   559     TInt err = iDb.Execute( sql );
       
   560 
       
   561     CleanupStack::PopAndDestroy( sqlBuf );  
       
   562 
       
   563     DLTRACE(("Removed %d rows", err));
       
   564     CloseTransactionL();
       
   565     
       
   566     DLTRACE(("Compacting"));
       
   567     iDb.Compact();
       
   568     DLINFO(("DB size after remove: %d", iDb.Size() ));
       
   569     }
       
   570 
       
   571 
       
   572 // ---------------------------------------------------------------------------
       
   573 // 
       
   574 // ---------------------------------------------------------------------------
       
   575 //
       
   576 TInt CNcdDatabaseStorage::CalculateSqlRemovalLength( 
       
   577     const RNcdDatabaseItems& aItem ) const
       
   578     {
       
   579     DLTRACEIN(("type: %d, uids: %d", aItem.iType, aItem.Uids().MdcaCount() ));
       
   580     const TInt KMax32BitIntLength = 11;
       
   581     TInt size = KNcdSqlRemoveItemType().Length() + 
       
   582                 KMax32BitIntLength + 
       
   583                 KNcdSqlRemoveItemStart().Length() +
       
   584                 KNcdSqlRemoveItemEnd().Length();
       
   585     
       
   586     const MDesCArray& uids( aItem.Uids() );
       
   587     TInt count = uids.MdcaCount();            
       
   588     while ( count-- ) 
       
   589         {
       
   590         size += uids.MdcaPoint( count ).Length() +
       
   591             KNcdSqlRemoveItemOrId().Length();    
       
   592         }
       
   593     
       
   594     DLTRACEOUT(("length: %d", size ));
       
   595     return size;
       
   596     }
       
   597 
       
   598 
       
   599 // ---------------------------------------------------------------------------
       
   600 // 
       
   601 // ---------------------------------------------------------------------------
       
   602 //
       
   603 TBool CNcdDatabaseStorage::BeginTransactionL()
       
   604     {
       
   605     DLTRACEIN(( "this-ptr: %X",this ));
       
   606     // Begins transaction if not already begun
       
   607     if( iDb.InTransaction() )
       
   608         {
       
   609         DLTRACE(("Old transaction"));
       
   610         return EFalse; // Transaction already exists
       
   611         }
       
   612     else
       
   613         {
       
   614         DLTRACE(("Starting new transaction"));    
       
   615         User::LeaveIfError( iDb.Begin() ); // Try to begin new transaction
       
   616         DLTRACE(("New transaction started"));    
       
   617         return ETrue;
       
   618         }
       
   619     
       
   620     }
       
   621 
       
   622 
       
   623 // ---------------------------------------------------------------------------
       
   624 // 
       
   625 // ---------------------------------------------------------------------------
       
   626 //
       
   627 TBool CNcdDatabaseStorage::CloseTransactionL( TBool aForceClose )
       
   628     {
       
   629     DLTRACEIN(( "this-ptr: %X",this ));
       
   630     if( !aForceClose && ItemsOpen() ) // Do not commit, items open
       
   631         {
       
   632         DLTRACE(("Items open, not committing"));
       
   633         return EFalse;
       
   634         }
       
   635     else
       
   636         {
       
   637         DLTRACE(("Commit"));
       
   638         TInt err = iDb.Commit();
       
   639         if( err != KErrNone )
       
   640             {
       
   641             DLERROR(( "Commit failed with: %d", err ));
       
   642             iUpdated = EFalse;
       
   643             iDb.Rollback();
       
   644             User::Leave( err );
       
   645             }
       
   646 
       
   647         if( iUpdated )
       
   648             {
       
   649             DLTRACE(( "Updated" ));
       
   650             iUpdated = EFalse;
       
   651             iWastedSpace += iNewWastedSpace;
       
   652             iNewWastedSpace = 0;
       
   653 
       
   654             if( iWastedSpace > KNcdMaxDatabaseWastedSpace )
       
   655                 {
       
   656                 DLINFO(("WastedSpace %i > MaxWastedSpace %i -> Compact",
       
   657                     iWastedSpace, KNcdMaxDatabaseWastedSpace ));
       
   658                 iDb.Compact();
       
   659                 iWastedSpace = 0;
       
   660                 }
       
   661 
       
   662             }
       
   663 
       
   664         return ETrue;
       
   665         }
       
   666     }
       
   667 
       
   668 
       
   669 // ---------------------------------------------------------------------------
       
   670 // 
       
   671 // ---------------------------------------------------------------------------
       
   672 //
       
   673 TBool CNcdDatabaseStorage::ItemExistsL( const TDesC& aUid, TInt aType )
       
   674     {
       
   675     DLTRACEIN((_L("Uid: %S, type: %d"), &aUid, aType ));    
       
   676     
       
   677     RDbView dbView;
       
   678     ReadItemDataLC( dbView, aUid, aType );
       
   679 
       
   680     TBool exists = ( dbView.CountL() > 0 );
       
   681 
       
   682     CleanupStack::PopAndDestroy( &dbView );
       
   683 
       
   684     return exists;
       
   685     }
       
   686 
       
   687 
       
   688 // ---------------------------------------------------------------------------
       
   689 // 
       
   690 // ---------------------------------------------------------------------------
       
   691 //
       
   692 void CNcdDatabaseStorage::DoOpenItemL( CNcdStorageItem* /*aItem*/ )
       
   693     {
       
   694     BeginTransactionL();
       
   695     }
       
   696 
       
   697 
       
   698 // ---------------------------------------------------------------------------
       
   699 // 
       
   700 // ---------------------------------------------------------------------------
       
   701 //
       
   702 void CNcdDatabaseStorage::DoRollback()
       
   703     {
       
   704     DLTRACEIN((""));
       
   705     if( iDb.InTransaction() )
       
   706         {
       
   707         DLINFO(("Rollbacking"));
       
   708         iDb.Rollback();
       
   709         }
       
   710 
       
   711     }
       
   712 
       
   713 
       
   714 // ---------------------------------------------------------------------------
       
   715 // 
       
   716 // ---------------------------------------------------------------------------
       
   717 //
       
   718 void CNcdDatabaseStorage::DoRemoveItemL( CNcdStorageItem* aItem )
       
   719     {
       
   720     DLTRACEIN((""));
       
   721     CNcdDatabaseStorageItem* item = (CNcdDatabaseStorageItem*)aItem;
       
   722 
       
   723     // SQL statement
       
   724     HBufC* sqlBuf = HBufC::NewLC( KNcdSqlRemoveItem().Length() + 8 );
       
   725     TPtr sql = sqlBuf->Des();
       
   726     sql.Format( KNcdSqlRemoveItem, item->DbKey() );
       
   727 
       
   728     // Begin transaction if not already began
       
   729     TBool newTransaction = BeginTransactionL();
       
   730 
       
   731     // Deletes row from the database
       
   732     // Returns number of deleted rows if success
       
   733     // Otherwise returns error code
       
   734     TInt err = iDb.Execute( sql );
       
   735 
       
   736     CleanupStack::PopAndDestroy( sqlBuf );  
       
   737 
       
   738     DLTRACE(("Removed %d rows", err));
       
   739     if( err != 1 ) // Error occured
       
   740         {
       
   741         DLTRACE(("Error! Rollback and leave"));
       
   742         if( newTransaction )
       
   743             {
       
   744             iDb.Rollback();
       
   745             }
       
   746 
       
   747         User::Leave( KErrNotFound );
       
   748         }
       
   749     DLTRACEOUT((""));
       
   750     }
       
   751 
       
   752 
       
   753 // ---------------------------------------------------------------------------
       
   754 // 
       
   755 // ---------------------------------------------------------------------------
       
   756 //
       
   757 void CNcdDatabaseStorage::DoReadDataL( CNcdStorageItem* aItem, 
       
   758     MNcdStorageDataItem& aDataItem )
       
   759     {
       
   760     DLTRACEIN(( "this-ptr: %X", this ));
       
   761     CNcdDatabaseStorageItem* item = (CNcdDatabaseStorageItem*)aItem;
       
   762 
       
   763     DASSERT( aItem );
       
   764     RDbView dbView;
       
   765     
       
   766     ReadItemDataLC( dbView, item->DbKey() );
       
   767 
       
   768     if( dbView.FirstL() )
       
   769         {
       
   770         dbView.GetL();
       
   771 
       
   772         RDbColReadStream readStream;
       
   773         readStream.OpenLC( dbView, ENcdDatabaseTableColumnsItemData );
       
   774 
       
   775         aDataItem.InternalizeL( readStream );
       
   776         CleanupStack::PopAndDestroy( &readStream );
       
   777         }
       
   778     else
       
   779         {
       
   780         // Item not found.
       
   781         User::Leave( KErrNotFound );
       
   782         }
       
   783 
       
   784     CleanupStack::PopAndDestroy( &dbView );
       
   785     DLTRACEOUT(( "" ));
       
   786     }
       
   787 
       
   788 // ---------------------------------------------------------------------------
       
   789 // 
       
   790 // ---------------------------------------------------------------------------
       
   791 //
       
   792 void CNcdDatabaseStorage::DoWriteDataL( CNcdStorageItem* aItem, 
       
   793     MNcdStorageDataItem& aDataItem )
       
   794     {
       
   795     DLTRACEIN(( "this-ptr: %X", this ));
       
   796 
       
   797     DASSERT( aItem );
       
   798     CNcdDatabaseStorageItem* item = (CNcdDatabaseStorageItem*)aItem;
       
   799 
       
   800     // Begin transaction if not alredy begun
       
   801     BeginTransactionL();
       
   802 
       
   803     RDbView dbView;
       
   804     ReadItemDataLC( dbView, item->DbKey(), RDbRowSet::EUpdatable );
       
   805 
       
   806     if( dbView.FirstL() )
       
   807         {
       
   808         dbView.UpdateL();
       
   809 
       
   810         TInt wastedSpace = dbView.ColSize( ENcdDatabaseTableColumnsId ) +
       
   811             dbView.ColSize( ENcdDatabaseTableColumnsItemId ) +
       
   812             dbView.ColSize( ENcdDatabaseTableColumnsItemType ) +
       
   813             dbView.ColSize( ENcdDatabaseTableColumnsItemData );
       
   814 
       
   815         RDbColWriteStream stream;
       
   816         stream.OpenL( dbView, ENcdDatabaseTableColumnsItemData );
       
   817         CleanupClosePushL( stream );        
       
   818 
       
   819         aDataItem.ExternalizeL( stream );
       
   820 
       
   821         CleanupStack::PopAndDestroy( &stream );
       
   822 
       
   823         dbView.PutL();
       
   824         iUpdated = ETrue;
       
   825         iNewWastedSpace += wastedSpace;
       
   826 
       
   827         }
       
   828     else
       
   829         {
       
   830         DLERROR(("Item not found"));    
       
   831         // Item not found
       
   832         User::Leave( KErrNotFound );
       
   833         }
       
   834 
       
   835     CleanupStack::PopAndDestroy( &dbView );
       
   836     DLTRACEOUT(( "" ));
       
   837     }
       
   838     
       
   839     
       
   840 // ---------------------------------------------------------------------------
       
   841 // 
       
   842 // ---------------------------------------------------------------------------
       
   843 //
       
   844 void CNcdDatabaseStorage::ReadItemDataLC( RDbView& aItemData, 
       
   845     const TDesC& aUid, TInt aType, RDbRowSet::TAccess aAccess )
       
   846     {
       
   847     DLTRACEIN(("this-ptr: %X", this));    
       
   848     
       
   849     // Create SQL statement
       
   850     HBufC* sqlBuf = HBufC::NewLC( KNcdSqlSelectOneRowByIdAndType().Length() 
       
   851         + aUid.Length() + 7 );        
       
   852             
       
   853     TPtr sql = sqlBuf->Des();
       
   854     sql.Format( KNcdSqlSelectOneRowByIdAndType, &aUid, aType );
       
   855            
       
   856 
       
   857     User::LeaveIfError( aItemData.Prepare( iDb, TDbQuery( sql ), aAccess ) );
       
   858     
       
   859     CleanupStack::PopAndDestroy( sqlBuf );
       
   860     CleanupClosePushL( aItemData );    
       
   861 
       
   862     User::LeaveIfError( aItemData.EvaluateAll() );
       
   863     DLTRACEOUT((""));
       
   864     }
       
   865 
       
   866 
       
   867 // ---------------------------------------------------------------------------
       
   868 // 
       
   869 // ---------------------------------------------------------------------------
       
   870 //
       
   871 void CNcdDatabaseStorage::ReadItemDataLC( RDbView& aItemData, TUint32 aKey, 
       
   872     RDbRowSet::TAccess aAccess )
       
   873     {    
       
   874     DLTRACEIN(("this-ptr: %X", this));
       
   875     
       
   876     // Create SQL statement
       
   877     HBufC* sqlBuf = HBufC::NewLC( KNcdSqlSelectOneRowByKey().Length() + 9 );
       
   878     TPtr sql = sqlBuf->Des();
       
   879     sql.Format( KNcdSqlSelectOneRowByKey, aKey );
       
   880 
       
   881     User::LeaveIfError( aItemData.Prepare( iDb, TDbQuery( sql ), aAccess ) );
       
   882     CleanupStack::PopAndDestroy( sqlBuf );
       
   883     CleanupClosePushL( aItemData );
       
   884 
       
   885     User::LeaveIfError( aItemData.EvaluateAll() );
       
   886     DLTRACEOUT(("no error"));
       
   887     }
       
   888     
       
   889 
       
   890 // ---------------------------------------------------------------------------
       
   891 // 
       
   892 // ---------------------------------------------------------------------------
       
   893 //
       
   894 void CNcdDatabaseStorage::RecreateDatabaseL() 
       
   895     {
       
   896     DLTRACEIN((""));
       
   897         
       
   898     // Delete existing database file. Ignoring errors as database file
       
   899     // may not be present.
       
   900     iDb.Close();
       
   901     BaflUtils::DeleteFile( iFs, *iDatabaseFileName );
       
   902 
       
   903     // Trying to create the database
       
   904     User::LeaveIfError( iDb.Create( iFs, *iDatabaseFileName ) );
       
   905     User::LeaveIfError( iDb.Execute( KNcdSqlCreateStorageTable ) );
       
   906     }
       
   907 
       
   908 
       
   909 // ---------------------------------------------------------------------------
       
   910 // 
       
   911 // ---------------------------------------------------------------------------
       
   912 //
       
   913 CNcdDatabaseStorageItem* CNcdDatabaseStorageItem::NewLC(
       
   914             CNcdStorageBase* aStorage,
       
   915             const TDesC& aUid,
       
   916             TInt aType,
       
   917             TUint32 aDbKey )
       
   918     {
       
   919     CNcdDatabaseStorageItem* item = new (ELeave) CNcdDatabaseStorageItem( 
       
   920         aStorage, aDbKey );
       
   921         
       
   922     CleanupStack::PushL( item );
       
   923     item->ConstructL( aUid, aType );    
       
   924     return item;
       
   925     }
       
   926 
       
   927 // ---------------------------------------------------------------------------
       
   928 // 
       
   929 // ---------------------------------------------------------------------------
       
   930 //
       
   931 CNcdDatabaseStorageItem::CNcdDatabaseStorageItem( CNcdStorageBase* aStorage, 
       
   932     TUint32 aDbKey ) :
       
   933     CNcdStorageItem( aStorage ),
       
   934         iDbKey( aDbKey )
       
   935     {
       
   936     }
       
   937 
       
   938 
       
   939 // ---------------------------------------------------------------------------
       
   940 // 
       
   941 // ---------------------------------------------------------------------------
       
   942 //
       
   943 CNcdDatabaseStorageItem::~CNcdDatabaseStorageItem()
       
   944     {
       
   945     }
       
   946 
       
   947 
       
   948 // ---------------------------------------------------------------------------
       
   949 // 
       
   950 // ---------------------------------------------------------------------------
       
   951 //
       
   952 void CNcdDatabaseStorageItem::SetDbKey( TUint32 aDbKey )
       
   953     {
       
   954     iDbKey = aDbKey;
       
   955     }
       
   956 
       
   957 
       
   958 // ---------------------------------------------------------------------------
       
   959 // 
       
   960 // ---------------------------------------------------------------------------
       
   961 //
       
   962 TUint32 CNcdDatabaseStorageItem::DbKey() const
       
   963     {
       
   964     return iDbKey;
       
   965     }
       
   966