photosgallery/collectionframework/thumbnailcreator/src/glxtnvolumedatabase.cpp
changeset 0 4e91876724a2
child 18 bcb43dc84c44
equal deleted inserted replaced
-1:000000000000 0:4e91876724a2
       
     1 /*
       
     2 * Copyright (c) 2008-2009 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:    Implementation of CGlxtnVolumeDatabase
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 
       
    21 /**
       
    22  * @internal reviewed 31/07/2007 by Simon Brooks
       
    23  */
       
    24 
       
    25 #include "glxtnvolumedatabase.h"
       
    26 
       
    27 #include <glxtracer.h>
       
    28 #include <glxpanic.h>
       
    29 #include <s32file.h>
       
    30 
       
    31 #include "glxtnfileinfo.h"
       
    32 #include "mglxtnvolumedatabaseobserver.h"
       
    33 
       
    34 #include <glxlog.h>
       
    35 _LIT(KGlxCreateTableIds, "CREATE TABLE Ids (MediaId UNSIGNED INTEGER NOT NULL, ThumbId UNSIGNED INTEGER NOT NULL)");
       
    36 _LIT(KGlxCreateTableItems, "CREATE TABLE Items (Uri VARCHAR NOT NULL, ThumbId UNSIGNED INTEGER NOT NULL, FileSize INTEGER, ModTime TIME)");
       
    37 _LIT(KGlxCreateTableThumbnails, "CREATE TABLE Thumbnails (ThumbId UNSIGNED INTEGER NOT NULL, Width INTEGER NOT NULL, Height INTEGER NOT NULL, Format INTEGER NOT NULL, ImageData LONG VARBINARY NOT NULL)");
       
    38 _LIT(KGlxCreateIndexIds, "CREATE UNIQUE INDEX IdIndex ON Ids (MediaId)");
       
    39 _LIT(KGlxCreateIndexItems, "CREATE UNIQUE INDEX ItemIndex ON Items (ThumbId ASC)");
       
    40 _LIT(KGlxCreateIndexThumbnails, "CREATE UNIQUE INDEX ThumbnailIndex ON Thumbnails (ThumbId, Width, Height)");
       
    41 _LIT(KGlxCreateIndexThumbIds, "CREATE UNIQUE INDEX ThumbIdIndex ON Ids (ThumbId)");
       
    42 
       
    43 _LIT(KGlxTableIds, "Ids");
       
    44 _LIT(KGlxTableItems, "Items");
       
    45 _LIT(KGlxTableThumbnails, "Thumbnails");
       
    46 _LIT(KGlxIndexItems, "ItemIndex");
       
    47 _LIT(KGlxIndexThumbIds, "ThumbIdIndex");
       
    48 
       
    49 const TInt KGlxColIdMediaId = 1;
       
    50 const TInt KGlxColIdThumbId = 2;
       
    51 
       
    52 const TInt KGlxColItemUri = 1;
       
    53 const TInt KGlxColItemId = 2;
       
    54 const TInt KGlxColItemFileSize = 3;
       
    55 const TInt KGlxColItemModTime = 4;
       
    56 
       
    57 const TInt KGlxColThumbnailId = 1;
       
    58 const TInt KGlxColThumbnailWidth = 2;
       
    59 const TInt KGlxColThumbnailHeight = 3;
       
    60 const TInt KGlxColThumbnailFormat = 4;
       
    61 const TInt KGlxColThumbnailData = 5;
       
    62 
       
    63 _LIT(KGlxQueryThumbIdFromIds, "SELECT * FROM Ids WHERE MediaId = ");
       
    64 _LIT(KGlxQueryThumbIdFromItems, "SELECT * FROM Items WHERE Uri = ");
       
    65 _LIT(KGlxQueryThumbnail, "SELECT * FROM Thumbnails WHERE ThumbId = %d AND Width = %d AND Height = %d");
       
    66 _LIT(KGlxQueryAvailable, "SELECT ThumbId, Width, Height FROM Thumbnails WHERE ThumbId = %d AND Width = %d AND Height = %d");
       
    67 _LIT(KGlxQueryItems, "SELECT * FROM Items WHERE ThumbId = %d");
       
    68 
       
    69 _LIT(KGlxDeleteId, "DELETE FROM Ids WHERE MediaId = %d");
       
    70 _LIT(KGlxDeleteThumbnails, "DELETE FROM Thumbnails WHERE ThumbId = %d");
       
    71 _LIT(KGlxDeleteItem, "DELETE FROM Items WHERE ThumbId = %d");
       
    72 
       
    73 const TInt KGlxTIntMaxDigits = 11;
       
    74 
       
    75 const TUint KGlxFirstThumbnailId = 1;
       
    76 
       
    77 // -----------------------------------------------------------------------------
       
    78 // NewL
       
    79 // -----------------------------------------------------------------------------
       
    80 //
       
    81 CGlxtnVolumeDatabase* CGlxtnVolumeDatabase::NewLC(
       
    82         MGlxtnVolumeDatabaseObserver& aObserver, RFs& aFs, const TDesC& aPath)
       
    83     {
       
    84     TRACER("CGlxtnVolumeDatabase* CGlxtnVolumeDatabase::NewLC( MGlxtnVolumeDatabaseObserver& aObserver, RFs& aFs, const TDesC& aPath)");
       
    85     CGlxtnVolumeDatabase* self = 
       
    86                         new (ELeave) CGlxtnVolumeDatabase(aObserver, aFs);
       
    87     CleanupStack::PushL(self);
       
    88     self->ConstructL(aPath);
       
    89     return self;
       
    90     }
       
    91 
       
    92 // -----------------------------------------------------------------------------
       
    93 // Constructor
       
    94 // -----------------------------------------------------------------------------
       
    95 //
       
    96 CGlxtnVolumeDatabase::CGlxtnVolumeDatabase(
       
    97                                     MGlxtnVolumeDatabaseObserver& aObserver, 
       
    98                                     RFs& aFs)
       
    99     : CActive(EPriorityStandard), 
       
   100       iObserver(aObserver), iFs(aFs), iState(EStateIdle)
       
   101     {
       
   102     TRACER("CGlxtnVolumeDatabase::CGlxtnVolumeDatabase( MGlxtnVolumeDatabaseObserver& aObserver, RFs& aFs)");
       
   103     }
       
   104 
       
   105 // -----------------------------------------------------------------------------
       
   106 // ConstructL
       
   107 // -----------------------------------------------------------------------------
       
   108 //
       
   109 void CGlxtnVolumeDatabase::ConstructL(const TDesC& aPath)
       
   110     {
       
   111     TRACER("void CGlxtnVolumeDatabase::ConstructL(const TDesC& aPath)");
       
   112     iDrive = aPath.Left(KMaxDriveName);
       
   113 
       
   114     TRAPD(error, OpenDbL(iFs, aPath));
       
   115     GLX_LOG_INFO1("CGlxtnVolumeDatabase::ConstructL OpenDbL TRAP error = %d", error);
       
   116     if ( KErrNone != error )
       
   117         {
       
   118         iDatabase.Close();
       
   119         delete iStore;
       
   120         iStore = NULL;
       
   121         CreateDbL(iFs, aPath);
       
   122         }
       
   123 
       
   124     CActiveScheduler::Add(this);
       
   125     }
       
   126 
       
   127 // -----------------------------------------------------------------------------
       
   128 // Destructor
       
   129 // -----------------------------------------------------------------------------
       
   130 //
       
   131 CGlxtnVolumeDatabase::~CGlxtnVolumeDatabase() 
       
   132     {
       
   133     TRACER("CGlxtnVolumeDatabase::~CGlxtnVolumeDatabase()");
       
   134     Cancel();
       
   135     iView.Close();
       
   136     iTable.Close();
       
   137     iDbUpdater.Close();
       
   138     iDatabase.Close();
       
   139     delete iStore;
       
   140     }
       
   141 
       
   142 // -----------------------------------------------------------------------------
       
   143 // Drive
       
   144 // -----------------------------------------------------------------------------
       
   145 //
       
   146 const TDesC& CGlxtnVolumeDatabase::Drive() const
       
   147     {
       
   148     TRACER("TDesC& CGlxtnVolumeDatabase::Drive()");
       
   149     return iDrive;
       
   150     }
       
   151 
       
   152 // -----------------------------------------------------------------------------
       
   153 // GetThumbnailIdL
       
   154 // Look up thumbnail ID from Ids table
       
   155 // -----------------------------------------------------------------------------
       
   156 //
       
   157 void CGlxtnVolumeDatabase::GetThumbnailIdL( const TGlxMediaId& aMediaId )
       
   158     {
       
   159     TRACER("void CGlxtnVolumeDatabase::GetThumbnailIdL( const TGlxMediaId& aMediaId )");
       
   160     if ( EStateIdle != iState )
       
   161         {
       
   162         User::Leave(KErrNotReady);
       
   163         }
       
   164 
       
   165     GLX_LOG_INFO1("CGlxtnVolumeDatabase::GetThumbnailIdL() Media Id= %d",aMediaId.Value());
       
   166     HBufC* sql = HBufC::NewLC(
       
   167                     KGlxQueryThumbIdFromIds().Length() + KGlxTIntMaxDigits );
       
   168     *sql = KGlxQueryThumbIdFromIds;
       
   169     sql->Des().AppendNum( aMediaId.Value() );
       
   170 
       
   171     EvaluateQueryL( *sql );
       
   172     iState = EStateGettingIdFromMediaId;
       
   173 
       
   174     CleanupStack::PopAndDestroy(sql);
       
   175     }
       
   176 
       
   177 // -----------------------------------------------------------------------------
       
   178 // GetThumbnailIdL
       
   179 // Look up thumbnail ID from Items table.  If not found, add new record.
       
   180 // -----------------------------------------------------------------------------
       
   181 //
       
   182 void CGlxtnVolumeDatabase::GetThumbnailIdL(const CGlxtnFileInfo* aInfo)
       
   183     {
       
   184     TRACER("void CGlxtnVolumeDatabase::GetThumbnailIdL(const CGlxtnFileInfo* aInfo)");
       
   185     if ( EStateIdle != iState )
       
   186         {
       
   187         User::Leave(KErrNotReady);
       
   188         }
       
   189 
       
   190     iInfo = aInfo;
       
   191     HBufC* uri = QuoteSqlStringLC(iInfo->FilePath());
       
   192     HBufC* sql = HBufC::NewLC(
       
   193                     KGlxQueryThumbIdFromItems().Length() + uri->Length());
       
   194     *sql = KGlxQueryThumbIdFromItems;
       
   195     sql->Des().Append(*uri);
       
   196 
       
   197     EvaluateQueryL( *sql );
       
   198     iState = EStateGettingIdFromFilename;
       
   199 
       
   200     CleanupStack::PopAndDestroy(sql);
       
   201     CleanupStack::PopAndDestroy(uri);
       
   202     }
       
   203 
       
   204 // -----------------------------------------------------------------------------
       
   205 // GetThumbnailIdL
       
   206 // Retrieve the thumbnail id to be assigned to the next thumbnail that gets stored in the database. 
       
   207 // -----------------------------------------------------------------------------
       
   208 //
       
   209 TGlxtnThumbnailId CGlxtnVolumeDatabase::GetThumbnailId()
       
   210     {
       
   211     GLX_LOG_ENTRY_EXIT("void CGlxtnVolumeDatabase::GetThumbnailIdL()");
       
   212     TGlxtnThumbnailId thumbId( iNextThumbId );
       
   213     iNextThumbId++;
       
   214     GLX_LOG_INFO1("CGlxtnVolumeDatabase::InitializeThumbIdL iNextThumbId=%d", iNextThumbId);
       
   215     return thumbId;
       
   216     }
       
   217 
       
   218 // -----------------------------------------------------------------------------
       
   219 // StoreThumbnailIdL
       
   220 // Add record to Ids table
       
   221 // -----------------------------------------------------------------------------
       
   222 //
       
   223 void CGlxtnVolumeDatabase::StoreThumbnailIdL( const TGlxMediaId& aMediaId,
       
   224                                         const TGlxtnThumbnailId& aThumbId )
       
   225     {
       
   226     TRACER("void CGlxtnVolumeDatabase::StoreThumbnailIdL( const TGlxMediaId& aMediaId, const TGlxtnThumbnailId& aThumbId )");
       
   227     if ( EStateIdle != iState )
       
   228         {
       
   229         User::Leave(KErrNotReady);
       
   230         }
       
   231     GLX_LOG_INFO1("StoreThumbnailIdL():- Media Id = %d",aMediaId.Value());
       
   232     GLX_LOG_INFO1("StoreThumbnailIdL():- aThumbId = %d",aThumbId.Value());
       
   233     RDbTable table;
       
   234     CleanupClosePushL(table);
       
   235     User::LeaveIfError( table.Open(
       
   236                         iDatabase, KGlxTableIds, RDbRowSet::EInsertOnly ) );
       
   237 
       
   238     table.InsertL();
       
   239     table.SetColL( KGlxColIdMediaId, aMediaId.Value() );
       
   240     table.SetColL( KGlxColIdThumbId, aThumbId.Value() );
       
   241     table.PutL();
       
   242     GLX_LOG_INFO2("StoreThumbnailIdL():- Added media id [%d] and thumb id  [%d] to Ids table. ", aMediaId.Value(), aThumbId.Value());
       
   243 
       
   244     CleanupStack::PopAndDestroy(&table);
       
   245 
       
   246     iObserver.HandleThumbnailIdStoredL();
       
   247     }
       
   248 
       
   249 void CGlxtnVolumeDatabase::StoreItemsL( const TGlxtnThumbnailId& aThumbId, const CGlxtnFileInfo* aInfo )
       
   250 	{
       
   251     __ASSERT_ALWAYS(aInfo, Panic(EGlxPanicNullPointer));
       
   252     GLX_LOG_ENTRY_EXIT("void CGlxtnVolumeDatabase::StoreItemsL()");
       
   253     GLX_LOG_INFO1("StoreItemsL():- ThumbId Id = %d",aThumbId.Value());
       
   254     RDbTable table;
       
   255     CleanupClosePushL(table);
       
   256     User::LeaveIfError(table.Open(iDatabase, KGlxTableItems, RDbRowSet::EUpdatable));
       
   257     User::LeaveIfError(table.SetIndex(KGlxIndexItems));
       
   258 
       
   259     TGlxtnThumbnailId thumbId( aThumbId );
       
   260 
       
   261     HBufC* sql = HBufC::NewLC( KGlxQueryItems().Length() + KGlxTIntMaxDigits);
       
   262     sql->Des().Format( KGlxQueryItems, thumbId.Value());
       
   263 
       
   264     RDbView view;
       
   265     CleanupClosePushL(view);
       
   266     User::LeaveIfError(view.Prepare(
       
   267                        iDatabase, *sql, RDbRowSet::EReadOnly ) );
       
   268     view.EvaluateAll();
       
   269 
       
   270     if (view.IsEmptyL())
       
   271         {
       
   272         GLX_LOG_INFO("StoreItemsL() - Add a new record");
       
   273         table.InsertL();
       
   274         table.SetColL( KGlxColItemUri, aInfo->FilePath() );
       
   275         table.SetColL( KGlxColItemId, thumbId.Value() );
       
   276         table.SetColL( KGlxColItemFileSize, aInfo->iFileSize );
       
   277         table.SetColL( KGlxColItemModTime, aInfo->iFileTime );
       
   278         table.PutL();
       
   279         }
       
   280        
       
   281     CleanupStack::PopAndDestroy(&view);
       
   282     CleanupStack::PopAndDestroy(sql);
       
   283     CleanupStack::PopAndDestroy(&table);
       
   284     }
       
   285 
       
   286 // -----------------------------------------------------------------------------
       
   287 // GetThumbnailL
       
   288 // Look up thumbnail from Thumbnails table
       
   289 // -----------------------------------------------------------------------------
       
   290 //
       
   291 void CGlxtnVolumeDatabase::GetThumbnailL( const TGlxtnThumbnailId& aThumbId,
       
   292                                             const TSize& aSize )
       
   293     {
       
   294     TRACER("void CGlxtnVolumeDatabase::GetThumbnailL( const TGlxtnThumbnailId& aThumbId, const TSize& aSize )");
       
   295     if ( EStateIdle != iState )
       
   296         {
       
   297         User::Leave(KErrNotReady);
       
   298         }
       
   299 
       
   300     GLX_LOG_INFO1("GetThumbnailL():- ThumbId Id = %d",aThumbId.Value());
       
   301     GLX_LOG_INFO2("GetThumbnailL Width=%d, Height=%d", aSize.iWidth, aSize.iHeight);
       
   302     HBufC* sql = HBufC::NewLC( KGlxQueryThumbnail().Length()
       
   303                                 + 3 * KGlxTIntMaxDigits);
       
   304     sql->Des().Format( KGlxQueryThumbnail,
       
   305                         aThumbId.Value(), aSize.iWidth, aSize.iHeight );
       
   306 
       
   307     EvaluateQueryL( *sql );
       
   308     iState = EStateGettingThumbnail;
       
   309 
       
   310     CleanupStack::PopAndDestroy(sql);
       
   311     }
       
   312 
       
   313 // -----------------------------------------------------------------------------
       
   314 // CheckAvailableL
       
   315 // Check if thumbnail is in Thumbnails table
       
   316 // -----------------------------------------------------------------------------
       
   317 //
       
   318 void CGlxtnVolumeDatabase::CheckAvailableL( const TGlxtnThumbnailId& aThumbId,
       
   319                                             const TSize& aSize )
       
   320     {
       
   321     TRACER("void CGlxtnVolumeDatabase::CheckAvailableL( const TGlxtnThumbnailId& aThumbId, const TSize& aSize )");
       
   322     if ( EStateIdle != iState )
       
   323         {
       
   324         User::Leave(KErrNotReady);
       
   325         }
       
   326     GLX_LOG_INFO1("CheckAvailableL():- ThumbId = %d", aThumbId.Value());
       
   327 
       
   328     HBufC* sql = HBufC::NewLC( KGlxQueryAvailable().Length()
       
   329                                 + 3 * KGlxTIntMaxDigits);
       
   330     sql->Des().Format( KGlxQueryAvailable,
       
   331                         aThumbId.Value(), aSize.iWidth, aSize.iHeight );
       
   332 
       
   333     EvaluateQueryL( *sql );
       
   334     iState = EStateCheckingAvailability;
       
   335 
       
   336     CleanupStack::PopAndDestroy(sql);
       
   337     }
       
   338 
       
   339 // -----------------------------------------------------------------------------
       
   340 // StoreThumbnailL
       
   341 // Add record to Thumbnails table
       
   342 // -----------------------------------------------------------------------------
       
   343 //
       
   344 void CGlxtnVolumeDatabase::StoreThumbnailL( const TGlxtnThumbnailId& aThumbId,
       
   345                                            const TSize& aSize,
       
   346                                            TGlxImageDataFormat aFormat,
       
   347                                            const TDesC8& aData )
       
   348     {
       
   349     TRACER("void CGlxtnVolumeDatabase::StoreThumbnailL( const TGlxtnThumbnailId& aThumbId, const TSize& aSize, TGlxImageDataFormat aFormat, const TDesC8& aData )");
       
   350     if ( EStateIdle != iState )
       
   351         {
       
   352         User::Leave(KErrNotReady);
       
   353         }
       
   354     GLX_LOG_INFO1("StoreThumbnailL():- aThumbId = %d",aThumbId.Value());
       
   355     GLX_LOG_INFO2("StoreThumbnailL Width=%d, Height=%d", aSize.iWidth, aSize.iHeight);
       
   356 
       
   357     RDbTable table;
       
   358     CleanupClosePushL(table);
       
   359     User::LeaveIfError( table.Open(
       
   360                 iDatabase, KGlxTableThumbnails, RDbRowSet::EInsertOnly ) );
       
   361 
       
   362     table.InsertL();
       
   363     table.SetColL( KGlxColThumbnailId, aThumbId.Value() );
       
   364     table.SetColL( KGlxColThumbnailWidth, aSize.iWidth );
       
   365     table.SetColL( KGlxColThumbnailHeight, aSize.iHeight );
       
   366     table.SetColL( KGlxColThumbnailFormat, aFormat );
       
   367     table.SetColL( KGlxColThumbnailData, aData );
       
   368     table.PutL();
       
   369 
       
   370     CleanupStack::PopAndDestroy(&table);
       
   371 
       
   372     iObserver.HandleThumbnailStored();
       
   373     }
       
   374 
       
   375 // -----------------------------------------------------------------------------
       
   376 // DeleteFromIdsL
       
   377 // Delete from IDs table
       
   378 // -----------------------------------------------------------------------------
       
   379 //
       
   380 void CGlxtnVolumeDatabase::DeleteIdL( const TGlxMediaId& aMediaId )
       
   381     {
       
   382     TRACER("void CGlxtnVolumeDatabase::DeleteIdL( const TGlxMediaId& aMediaId )");
       
   383     if ( EStateIdle != iState )
       
   384         {
       
   385         User::Leave(KErrNotReady);
       
   386         }
       
   387 
       
   388     GLX_LOG_INFO1("DeleteIdL():- Media Id = %d",aMediaId.Value());
       
   389     HBufC* sql = HBufC::NewLC( KGlxDeleteId().Length() + KGlxTIntMaxDigits);
       
   390     
       
   391     sql->Des().Format( KGlxDeleteId, aMediaId.Value() );
       
   392     
       
   393     UpdateDataL( *sql );
       
   394     iState = EStateDeletingId;
       
   395     
       
   396     CleanupStack::PopAndDestroy(sql);
       
   397     }
       
   398     
       
   399 // -----------------------------------------------------------------------------
       
   400 // DeleteThumbnailsL
       
   401 // Delete Thumbnails from Thumbnail table
       
   402 // -----------------------------------------------------------------------------
       
   403 //
       
   404 void CGlxtnVolumeDatabase::DeleteThumbnailsL(
       
   405                                         const TGlxtnThumbnailId& aThumbId )
       
   406     {
       
   407     TRACER("void CGlxtnVolumeDatabase::DeleteThumbnailsL( const TGlxtnThumbnailId& aThumbId )");
       
   408     if ( EStateIdle != iState )
       
   409         {
       
   410         User::Leave(KErrNotReady);
       
   411         }
       
   412     GLX_LOG_INFO1("DeleteThumbnailsL():- aThumbId = %d",aThumbId.Value());
       
   413 
       
   414     HBufC* sql = HBufC::NewLC(KGlxDeleteThumbnails().Length() + 
       
   415                                  KGlxTIntMaxDigits);
       
   416     
       
   417     sql->Des().Format( KGlxDeleteThumbnails, aThumbId.Value() );
       
   418     
       
   419     UpdateDataL( *sql );
       
   420     iState = EStateDeletingThumbnails;
       
   421     
       
   422     CleanupStack::PopAndDestroy(sql);
       
   423     }
       
   424     
       
   425 // -----------------------------------------------------------------------------
       
   426 // DeleteItemL
       
   427 // Delete Item from Items table
       
   428 // -----------------------------------------------------------------------------
       
   429 //
       
   430 void CGlxtnVolumeDatabase::DeleteItemL( const TGlxtnThumbnailId& aThumbId )
       
   431     {
       
   432     TRACER("void CGlxtnVolumeDatabase::DeleteItemL( const TGlxtnThumbnailId& aThumbId )");
       
   433     if ( EStateIdle != iState )
       
   434         {
       
   435         User::Leave(KErrNotReady);
       
   436         }
       
   437 
       
   438     GLX_LOG_INFO1("DeleteItemL():- aThumbId = %d",aThumbId.Value());
       
   439     HBufC* sql = HBufC::NewLC( KGlxDeleteItem().Length() + KGlxTIntMaxDigits);
       
   440     
       
   441     sql->Des().Format( KGlxDeleteItem, aThumbId.Value() );
       
   442     
       
   443     UpdateDataL( *sql );
       
   444     iState = EStateDeletingItem;
       
   445     
       
   446     CleanupStack::PopAndDestroy(sql);
       
   447     }
       
   448 
       
   449 // -----------------------------------------------------------------------------
       
   450 // CleanupDatabaseL
       
   451 // Clean from database entries that do not have a corresponding media file
       
   452 // -----------------------------------------------------------------------------
       
   453 //
       
   454 void CGlxtnVolumeDatabase::CleanupDatabaseL()
       
   455     {
       
   456     TRACER("void CGlxtnVolumeDatabase::CleanupDatabaseL()");
       
   457     if ( EStateIdle != iState )
       
   458         {
       
   459         User::Leave(KErrNotReady);
       
   460         }
       
   461     User::LeaveIfError( iTable.Open(
       
   462                         iDatabase, KGlxTableItems, RDbRowSet::EUpdatable ) );
       
   463     iTable.BeginningL();
       
   464 
       
   465     SetActive();
       
   466     TRequestStatus* ts = &iStatus;
       
   467     User::RequestComplete(ts, KErrNone);
       
   468 
       
   469     iState = EStateCleaning;
       
   470     }
       
   471 
       
   472     
       
   473 // -----------------------------------------------------------------------------
       
   474 // CleanupRowL
       
   475 // Test entry in one row in Items table to see if file is available. If it is
       
   476 // not, delete this row and start process of deleting corresponding entries 
       
   477 // from Ids table and Thumbnails table
       
   478 // -----------------------------------------------------------------------------
       
   479 //
       
   480 void CGlxtnVolumeDatabase::CleanupRowL()
       
   481     {
       
   482     TRACER("void CGlxtnVolumeDatabase::CleanupRowL()");
       
   483     // Get filename
       
   484     iTable.GetL();
       
   485     TPtrC filename = iTable.ColDes(KGlxColItemUri);
       
   486    
       
   487      // does file exist?
       
   488     TTime time(0);
       
   489     TInt err = iFs.Modified(filename, time);
       
   490     GLX_LOG_INFO1("void CGlxtnVolumeDatabase::CleanupRowL() New Time = %Ld",time.Int64());
       
   491     TTime modifiedTime(0);
       
   492     modifiedTime = iTable.ColTime(KGlxColItemModTime);
       
   493     GLX_LOG_INFO1("void CGlxtnVolumeDatabase::CleanupRowL() modifiedTime (from thumb Db) = %Ld",modifiedTime.Int64());
       
   494     if(err == KErrNone && (modifiedTime.Int64() == time.Int64()))
       
   495         {
       
   496         GLX_LOG_INFO("void CGlxtnVolumeDatabase::CleanupRowL() DBmodTime and FileModTime Same");
       
   497         //yes, file exists and not modified, so complete to go to next row
       
   498         SetActive();
       
   499         TRequestStatus* ts = &iStatus;
       
   500         User::RequestComplete(ts, KErrNone);
       
   501         iState = EStateCleaning;
       
   502         }
       
   503     else
       
   504         {
       
   505         GLX_LOG_INFO("void CGlxtnVolumeDatabase::CleanupRowL() DBmodTime and FileModTime NOT Same");
       
   506         TUint thumbId = iTable.ColUint( KGlxColItemId );
       
   507         if (err != KErrNone)
       
   508 	        {
       
   509 	        GLX_LOG_INFO1("void CGlxtnVolumeDatabase::CleanupRowL() DBmodTime and FileModTime NOT Same But err = %d", err);
       
   510 	        // Problem accessing file, so delete database entries
       
   511 	        // First delete row in Items table
       
   512 	        // Delete the row (entry in Items)
       
   513 	        iTable.DeleteL();
       
   514 	        }
       
   515         else
       
   516 	        {
       
   517 	        // file modified, so update the modified time in items table
       
   518 	        iTable.UpdateL();
       
   519 	        iTable.SetColL(KGlxColItemModTime, time);
       
   520 	        iTable.PutL();
       
   521 	        }
       
   522 			
       
   523 	        // Now delete from Thumbnails
       
   524         HBufC* sql = HBufC::NewLC(KGlxDeleteThumbnails().Length() + 
       
   525 	                                     KGlxTIntMaxDigits);
       
   526         sql->Des().Format( KGlxDeleteThumbnails, thumbId );
       
   527         UpdateDataL( *sql );
       
   528         iState = EStateCleaningDeletingThumbnails;
       
   529         CleanupStack::PopAndDestroy(sql);
       
   530         }
       
   531     }
       
   532     
       
   533 // -----------------------------------------------------------------------------
       
   534 // DoCancel
       
   535 // -----------------------------------------------------------------------------
       
   536 //
       
   537 void CGlxtnVolumeDatabase::DoCancel()
       
   538     {
       
   539     TRACER("void CGlxtnVolumeDatabase::DoCancel()");
       
   540     iView.Cancel();
       
   541     iTable.Close();
       
   542     iDbUpdater.Close();
       
   543     iState = EStateIdle;
       
   544     }
       
   545 
       
   546 // -----------------------------------------------------------------------------
       
   547 // RunL
       
   548 // -----------------------------------------------------------------------------
       
   549 //
       
   550 void CGlxtnVolumeDatabase::RunL()
       
   551     {
       
   552     TRACER("void CGlxtnVolumeDatabase::RunL()");
       
   553     User::LeaveIfError(iStatus.Int());
       
   554 
       
   555     // Continue any database operations which aren't finished
       
   556     switch ( iState )
       
   557         {
       
   558         case EStateGettingIdFromMediaId:
       
   559         case EStateGettingIdFromFilename:
       
   560         case EStateGettingThumbnail:
       
   561         case EStateCheckingAvailability:
       
   562             if ( iView.Unevaluated() )
       
   563                 {
       
   564                 iView.Evaluate(iStatus);
       
   565                 SetActive();
       
   566                 return;
       
   567                 }
       
   568             break;
       
   569         case EStateDeletingId:
       
   570         case EStateDeletingThumbnails:
       
   571         case EStateDeletingItem:
       
   572         case EStateCleaningDeletingThumbnails:
       
   573             if(iStatus.Int() != 0)
       
   574                 {
       
   575                 iDbUpdater.Next(iStatus);
       
   576                 SetActive();
       
   577                 return;
       
   578                 }
       
   579             break;
       
   580         case EStateCleaning:
       
   581         // do nothing
       
   582             break;
       
   583         default:
       
   584             Panic(EGlxPanicIllegalState);
       
   585             break;
       
   586         }
       
   587 
       
   588     // Handle results of database operation
       
   589     switch ( iState )
       
   590         {
       
   591         case EStateGettingIdFromMediaId:
       
   592             {
       
   593             TGlxtnThumbnailId thumbId;
       
   594             if ( iView.FirstL() )
       
   595                 {
       
   596                 iView.GetL();
       
   597                 thumbId = iView.ColUint(KGlxColIdThumbId);
       
   598                 GLX_LOG_INFO1("RunL - EStateGettingIdFromMediaId  IF (iView.FirstL()): ThumbId = %d", thumbId.Value());
       
   599                 }
       
   600             else
       
   601                 {
       
   602                 GLX_LOG_INFO("RunL - EStateGettingIdFromMediaId (iView.FirstL()): ELSE ->  thumbId not retrieved" );                
       
   603                 }
       
   604             iView.Close();
       
   605             iState = EStateIdle;
       
   606             iObserver.HandleThumbnailIdFromMediaIdL(thumbId);
       
   607             }
       
   608             break;
       
   609 
       
   610         case EStateGettingIdFromFilename:
       
   611             {
       
   612             TGlxtnThumbnailId thumbId;
       
   613             if ( iView.FirstL() )
       
   614                 {
       
   615                 iView.GetL();
       
   616                 thumbId = iView.ColUint(KGlxColItemId);
       
   617                 iView.Close();
       
   618                 GLX_LOG_INFO1("RunL - EStateGettingIdFromFilename IF (iView.FirstL()): ThumbId =  %d", thumbId.Value());
       
   619                 }
       
   620             else
       
   621                 {
       
   622                 iView.Close();
       
   623                 GLX_LOG_INFO("RunL - EStateGettingIdFromMediaId (iView.FirstL()): ELSE ->  no Thumbnail Yet. So DoAddItemL() being called" );
       
   624                 thumbId = DoAddItemL();
       
   625                 GLX_LOG_INFO1("RunL - EStateGettingIdFromMediaId (iView.FirstL()): ELSE ->  ThumbId =  %d",  thumbId.Value());
       
   626                 }
       
   627             iState = EStateIdle;
       
   628             iInfo = NULL;
       
   629             GLX_LOG_INFO1("RunL - EStateGettingIdFromFilename - aThumbId = %d", thumbId.Value());
       
   630             iObserver.HandleThumbnailIdFromFilenameL(thumbId);
       
   631             }
       
   632             break;
       
   633 
       
   634         case EStateGettingThumbnail:
       
   635             if ( iView.FirstL() )
       
   636                 {
       
   637                 iView.GetL();
       
   638                 TGlxImageDataFormat format = static_cast<TGlxImageDataFormat>(
       
   639                                         iView.ColInt(KGlxColThumbnailFormat));
       
   640                 TInt size = iView.ColSize(KGlxColThumbnailData);
       
   641 
       
   642                 GLX_LOG_INFO("RunL: Reading Thumbnail from dB");
       
   643                 RDbColReadStream stream;
       
   644                 stream.OpenLC(iView, KGlxColThumbnailData);
       
   645                 HBufC8* data = HBufC8::NewLC(size);
       
   646                 TPtr8 ptr(data->Des());
       
   647                 // Need to specify amount to read, as the HBufC8 can be bigger
       
   648                 // than requested
       
   649                 stream.ReadL(ptr, size);    
       
   650 
       
   651                 CleanupStack::Pop(data);
       
   652                 CleanupStack::PopAndDestroy(&stream);
       
   653 
       
   654                 iView.Close();
       
   655                 iState = EStateIdle;
       
   656                 iObserver.HandleThumbnail(format, data);
       
   657                 }
       
   658             else
       
   659                 {
       
   660                 iView.Close();
       
   661                 iState = EStateIdle;
       
   662                 GLX_LOG_INFO("RunL: HandleDatabaseError - KErrNotFound");
       
   663                 iObserver.HandleDatabaseError(KErrNotFound);
       
   664                 }
       
   665             break;
       
   666             
       
   667         case EStateDeletingId:
       
   668             iState = EStateIdle;
       
   669             iDbUpdater.Close();
       
   670             iObserver.HandleMediaIdDeletedL();
       
   671             break;
       
   672             
       
   673         case EStateDeletingThumbnails:
       
   674             iState = EStateIdle;
       
   675             iDbUpdater.Close();
       
   676             iObserver.HandleThumbnailsDeletedL();
       
   677             break;
       
   678             
       
   679         case EStateDeletingItem:
       
   680             iState = EStateIdle;
       
   681             iDbUpdater.Close();
       
   682             iObserver.HandleItemDeletedL();
       
   683             break;
       
   684 
       
   685         case EStateCheckingAvailability:
       
   686             {
       
   687             TInt result = KGlxThumbnailAvailable;
       
   688             if ( iView.IsEmptyL() )
       
   689                 {
       
   690                 result = KGlxThumbnailNotAvailable;
       
   691                 }
       
   692             iView.Close();
       
   693             iState = EStateIdle;
       
   694             GLX_LOG_INFO1("RunL - EStateCheckingAvailability - result = %d", result);
       
   695             iObserver.HandleAvailabilityChecked(result);
       
   696             }
       
   697             break;
       
   698             
       
   699         case EStateCleaningDeletingThumbnails:
       
   700             iState = EStateCleaning;
       
   701             iDbUpdater.Close();      // deliberate fall through to next row
       
   702         case EStateCleaning:
       
   703             if(iTable.NextL())
       
   704                 {
       
   705                 // next row
       
   706                 CleanupRowL();
       
   707                 }
       
   708             else
       
   709                 {
       
   710                 // no more rows
       
   711                 iTable.Close();
       
   712                 iState = EStateIdle;
       
   713                 iObserver.HandleDatabaseCleanedL();
       
   714                 }
       
   715             break;
       
   716         default:
       
   717             Panic(EGlxPanicIllegalState);
       
   718             break;
       
   719         }
       
   720     }
       
   721 
       
   722 // -----------------------------------------------------------------------------
       
   723 // RunError
       
   724 // -----------------------------------------------------------------------------
       
   725 //
       
   726 TInt CGlxtnVolumeDatabase::RunError(TInt aError)
       
   727     {
       
   728     TRACER("TInt CGlxtnVolumeDatabase::RunError(TInt aError)");
       
   729     GLX_LOG_INFO2("RunL: HandleDatabaseError - iState=%d, error=%d", 
       
   730 	                                                iState, aError);
       
   731     TInt error = aError;
       
   732     iTable.Close();
       
   733     iView.Close();
       
   734     iDbUpdater.Close();
       
   735     iInfo = NULL;
       
   736 
       
   737  	if (aError == KErrCorrupt)
       
   738  		{
       
   739  		error = KErrCorruptThumbnailDatabase;
       
   740  		}
       
   741  	else if (aError == KErrEof)
       
   742         {
       
   743         error = KErrEofThumbnailDatabase;
       
   744         }
       
   745 	
       
   746     iObserver.HandleDatabaseError(error);
       
   747     iState = EStateIdle;
       
   748     return KErrNone;
       
   749     }
       
   750 
       
   751 // -----------------------------------------------------------------------------
       
   752 // OpenDbL
       
   753 // Open an existing database.
       
   754 // -----------------------------------------------------------------------------
       
   755 //
       
   756 void CGlxtnVolumeDatabase::OpenDbL(RFs& aFs, const TDesC& aFilename)
       
   757     {
       
   758     TRACER("void CGlxtnVolumeDatabase::OpenDbL(RFs& aFs, const TDesC& aFilename)");
       
   759     iStore = CFileStore::OpenL(aFs, aFilename, EFileRead | EFileWrite);
       
   760     iDatabase.OpenL(iStore, iStore->Root());
       
   761     User::LeaveIfError(iDatabase.Recover());
       
   762     
       
   763     RDbTable tableIds;
       
   764     CleanupClosePushL(tableIds);
       
   765 
       
   766     // open and check the Ids table
       
   767     User::LeaveIfError( tableIds.Open(
       
   768                         iDatabase, KGlxTableIds, RDbRowSet::EReadOnly ) );
       
   769 
       
   770     User::LeaveIfError(tableIds.SetIndex(KGlxIndexThumbIds));
       
   771     
       
   772     CleanupStack::PopAndDestroy(&tableIds);
       
   773 
       
   774     }
       
   775     
       
   776 // -----------------------------------------------------------------------------
       
   777 // InitializeThumbIdL
       
   778 // Initialize thumbnail identifier to the last known value plus one.
       
   779 // -----------------------------------------------------------------------------
       
   780 void CGlxtnVolumeDatabase::InitializeThumbIdL()
       
   781     {
       
   782     GLX_LOG_ENTRY_EXIT("void CGlxtnThumbnailDatabase::InitializeThumbIdL()");
       
   783     // Get next available thumbnail ID (synchronous)
       
   784     RDbTable tableIds;
       
   785     CleanupClosePushL(tableIds);
       
   786 
       
   787     // open and check the Ids table
       
   788     User::LeaveIfError( tableIds.Open(
       
   789                         iDatabase, KGlxTableIds, RDbRowSet::EReadOnly ) );
       
   790 
       
   791     User::LeaveIfError(tableIds.SetIndex(KGlxIndexThumbIds));
       
   792 
       
   793     // Find highest thumbnail ID in use.  New entries are added to the Items
       
   794     // table first, and deleted from the Items table last, so all IDs in use
       
   795     // will always be found there.
       
   796     // Thumbnail IDs are only unique within a volume.
       
   797     if ( tableIds.LastL() )
       
   798         {
       
   799         tableIds.GetL();
       
   800         iNextThumbId = tableIds.ColUint(KGlxColIdThumbId) + 1;
       
   801         }
       
   802     else
       
   803         {
       
   804         // Database is empty
       
   805         iNextThumbId = KGlxFirstThumbnailId;
       
   806         }
       
   807     GLX_LOG_INFO1("CGlxtnVolumeDatabase::InitializeThumbIdL iNextThumbId=%d", iNextThumbId);
       
   808 
       
   809     CleanupStack::PopAndDestroy(&tableIds);
       
   810     }
       
   811 
       
   812 // -----------------------------------------------------------------------------
       
   813 // CreateDbL
       
   814 // Create a new database.
       
   815 // -----------------------------------------------------------------------------
       
   816 //
       
   817 void CGlxtnVolumeDatabase::CreateDbL(RFs& aFs, const TDesC& aFilename)
       
   818     {
       
   819     TRACER("void CGlxtnVolumeDatabase::CreateDbL(RFs& aFs, const TDesC& aFilename)");
       
   820     // Create database, overwriting any existing file
       
   821     TInt err = aFs.MkDirAll(aFilename);
       
   822     if ( err != KErrAlreadyExists )
       
   823         {
       
   824         User::LeaveIfError(err);
       
   825         }
       
   826     iStore = CPermanentFileStore::ReplaceL(aFs, aFilename,
       
   827                                             EFileRead | EFileWrite);
       
   828                                             
       
   829     iStore->SetTypeL(KPermanentFileStoreLayoutUid);
       
   830     iStore->SetRootL(iDatabase.CreateL(iStore));
       
   831     iStore->CommitL();
       
   832     
       
   833     
       
   834     User::LeaveIfError(iDatabase.Execute(KGlxCreateTableIds));
       
   835     User::LeaveIfError(iDatabase.Execute(KGlxCreateTableItems));
       
   836     User::LeaveIfError(iDatabase.Execute(KGlxCreateTableThumbnails));
       
   837 
       
   838     User::LeaveIfError(iDatabase.Execute(KGlxCreateIndexIds));
       
   839     User::LeaveIfError(iDatabase.Execute(KGlxCreateIndexThumbIds));
       
   840     User::LeaveIfError(iDatabase.Execute(KGlxCreateIndexItems));
       
   841     User::LeaveIfError(iDatabase.Execute(KGlxCreateIndexThumbnails));
       
   842     }
       
   843 
       
   844 // -----------------------------------------------------------------------------
       
   845 // DoAddItemL
       
   846 // -----------------------------------------------------------------------------
       
   847 //
       
   848 TGlxtnThumbnailId CGlxtnVolumeDatabase::DoAddItemL()
       
   849     {
       
   850     TRACER("TGlxtnThumbnailId CGlxtnVolumeDatabase::DoAddItemL()");
       
   851     __ASSERT_ALWAYS(iInfo, Panic(EGlxPanicNullPointer));
       
   852     RDbTable table;
       
   853     CleanupClosePushL(table);
       
   854     User::LeaveIfError(table.Open(iDatabase, KGlxTableItems, RDbRowSet::EInsertOnly));
       
   855     TGlxtnThumbnailId thumbId( iNextThumbId );
       
   856     GLX_LOG_INFO1("TGlxtnThumbnailId CGlxtnVolumeDatabase::DoAddItemL() thumbId =%d", thumbId.Value());
       
   857 
       
   858     table.InsertL();
       
   859     table.SetColL( KGlxColItemUri, iInfo->FilePath() );
       
   860     table.SetColL( KGlxColItemId, thumbId.Value() );
       
   861     table.SetColL( KGlxColItemFileSize, iInfo->iFileSize );
       
   862     table.SetColL( KGlxColItemModTime, iInfo->iFileTime );
       
   863     table.PutL();
       
   864 
       
   865     CleanupStack::PopAndDestroy(&table);
       
   866     return thumbId;
       
   867     }
       
   868 
       
   869 // -----------------------------------------------------------------------------
       
   870 // EvaluateQueryL
       
   871 // -----------------------------------------------------------------------------
       
   872 //
       
   873 void CGlxtnVolumeDatabase::EvaluateQueryL( const TDbQuery &aQuery )
       
   874     {
       
   875     TRACER("void CGlxtnVolumeDatabase::EvaluateQueryL( const TDbQuery &aQuery )");
       
   876     User::LeaveIfError( iView.Prepare(
       
   877                                 iDatabase, aQuery, RDbRowSet::EReadOnly ) );
       
   878     iView.Evaluate( iStatus );
       
   879     SetActive();
       
   880     }
       
   881 
       
   882 // -----------------------------------------------------------------------------
       
   883 // UpdateDataL
       
   884 // -----------------------------------------------------------------------------
       
   885 //
       
   886 void CGlxtnVolumeDatabase::UpdateDataL( const TDesC& aSql )
       
   887     {
       
   888     TRACER("void CGlxtnVolumeDatabase::UpdateDataL( const TDesC& aSql )");
       
   889     TInt result = iDbUpdater.Execute( iDatabase, aSql );
       
   890 
       
   891     if ( result < KErrNone )
       
   892         {
       
   893         iDbUpdater.Close();
       
   894         User::Leave( result );
       
   895         }
       
   896 
       
   897     // According to documentation a result of 0 should indicate complete
       
   898     // but this does not seem to be the case
       
   899     iDbUpdater.Next( iStatus );
       
   900     SetActive();
       
   901     }
       
   902 
       
   903 // -----------------------------------------------------------------------------
       
   904 // QuoteSqlStringLC
       
   905 // -----------------------------------------------------------------------------
       
   906 //
       
   907 HBufC* CGlxtnVolumeDatabase::QuoteSqlStringLC(const TDesC& aText)
       
   908     {
       
   909     TRACER("HBufC* CGlxtnVolumeDatabase::QuoteSqlStringLC(const TDesC& aText)");
       
   910     const TText quote('\'');
       
   911     TInt length = aText.Length() + 2;
       
   912 
       
   913     for ( TInt i = 0; i < aText.Length(); i++ )
       
   914         {
       
   915         if ( quote == aText[i] )
       
   916             {
       
   917             length++;
       
   918             }
       
   919         }
       
   920 
       
   921     HBufC* text = HBufC::NewLC(length);
       
   922     TPtr ptr(text->Des());
       
   923 
       
   924     ptr.Append(quote);
       
   925     for ( TInt i = 0; i < aText.Length(); i++ )
       
   926         {
       
   927         TText chr = aText[i];
       
   928         ptr.Append(chr);
       
   929         if ( quote == chr )
       
   930             {
       
   931             ptr.Append(quote);
       
   932             }
       
   933         }
       
   934     ptr.Append(quote);
       
   935 
       
   936     return text;
       
   937     }