mtpdataproviders/mtpimagedp/mediasyncserver/src/cmediasyncdatabase.cpp
changeset 0 d0791faffa3f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mtpdataproviders/mtpimagedp/mediasyncserver/src/cmediasyncdatabase.cpp	Tue Feb 02 01:11:40 2010 +0200
@@ -0,0 +1,501 @@
+// Copyright (c) 2009 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:
+//
+
+/**
+ @file
+ @internalTechnology
+*/
+
+#include <bautils.h>
+#include <mdesession.h>
+#include <mdequery.h>
+#include <mdeconstants.h>
+
+#include "cmediasyncserverdef.h"
+#include "cmediasyncdatabase.h"
+#include "cmediasyncdatawriter.h"
+
+__FLOG_STMT(_LIT8(KComponent,"MediaSyncDatabase");)
+
+const TInt KCompactThreshold = 50;
+const TInt KMaxRetryTimes = 3;
+const TInt KDelayPeriod = 3 * 1000000;
+
+CMediaSyncDatabase* CMediaSyncDatabase::NewL(RFs& aFs)
+    {
+    CMediaSyncDatabase* self = new (ELeave) CMediaSyncDatabase(aFs);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+void CMediaSyncDatabase::ConstructL()
+    {
+    __FLOG_OPEN(KMSSSubsystem, KComponent);
+    __FLOG(_L8("CMediaSyncDatabase::ConstructL - Entry"));
+
+    //Connect to the file server
+    User::LeaveIfError(iFs.Connect());
+
+    TFileName databasePath;
+    iFs.PrivatePath(databasePath);
+    TDriveUnit driveNum = RFs::GetSystemDrive();
+    databasePath.Insert(0, driveNum.Name());
+    databasePath.Append(KMssDbName);
+
+    CreateTableL(databasePath);    
+    
+    User::LeaveIfError(iBatched.Open(iDatabase, KImageTableName, RDbRowSet::EUpdatable));
+    
+    __FLOG(_L8("CMediaSyncDatabase::ConstructL - Exit"));
+    }
+
+CMediaSyncDatabase::CMediaSyncDatabase(RFs& aFs) :
+    iFs(aFs),
+    iDbCorrupt(EFalse),
+    iSavePosition(EFalse)
+    {
+    }
+
+CMediaSyncDatabase::~CMediaSyncDatabase()
+    {
+    __FLOG(_L8("CMediaSyncDatabase::~CMediaSyncDatabase - Entry"));
+    
+    iBatched.Close();
+    iDatabase.Close();
+    
+    __FLOG(_L8("CMediaSyncDatabase::~CMediaSyncDatabase - Exit"));
+    __FLOG_CLOSE;
+    }
+
+void CMediaSyncDatabase::CreateTableL(const TDesC& aDbFile)
+    {
+    __FLOG(_L8("CMediaSyncDatabase::CreateTableL - Entry"));
+    
+    _LIT(KSQLCreateTable, "CREATE TABLE ImageStore(ObjectId UNSIGNED INTEGER, NotificationType UNSIGNED INTEGER, URI VARCHAR(255))");           
+    
+    TInt err = KErrNone;
+    if (!BaflUtils::FileExists(iFs, aDbFile))
+        {
+        __FLOG(_L8("CreateTableL - Table ImageStore does not exist"));
+        
+        BaflUtils::EnsurePathExistsL(iFs, aDbFile);
+        
+        User::LeaveIfError(iDatabase.Create(iFs, aDbFile));
+        User::LeaveIfError(iDatabase.Execute(KSQLCreateTable));
+        TRAP_IGNORE(CreateTabIndexL());
+        }    
+    else
+        {
+        //Open the database
+        TBool recreateDbFile = EFalse;
+        err = iDatabase.Open(iFs, aDbFile);
+        if (err == KErrNone)
+            {
+            if (iDatabase.IsDamaged())
+                {
+                recreateDbFile = (iDatabase.Recover() == KErrNone) ? EFalse : ETrue;
+                }
+            }
+        else
+            {
+            recreateDbFile = ETrue;
+            }
+        
+        if (recreateDbFile)
+            {
+            __FLOG_VA((_L8("CreateTableL - Open Table ImageStore failed: %d"), err));
+            iDatabase.Close();
+
+            TInt retryCount = KMaxRetryTimes;
+            TInt result = KErrNone;            
+            for (; retryCount > 0; retryCount--)
+                {
+                result = BaflUtils::DeleteFile(iFs, aDbFile);
+                if (result == KErrNone)
+                    {
+                    // We have succesfully delete corrupt database file
+                    break;
+                    }       
+                else
+                    {
+                    User::After(KDelayPeriod);
+                    }
+                }
+            
+            User::LeaveIfError(result);
+            User::LeaveIfError(iDatabase.Create(iFs, aDbFile));
+            User::LeaveIfError(iDatabase.Execute(KSQLCreateTable));
+            TRAP_IGNORE(CreateTabIndexL());
+            iDbCorrupt = ETrue;          
+            }
+        }    
+    
+    __FLOG(_L8("CMediaSyncDatabase::CreateTableL - Exit"));
+    }
+
+void CMediaSyncDatabase::CreateTabIndexL()
+    {    
+    __FLOG(_L8("CMediaSyncDatabase::CreateTabIndexL - Entry"));
+    
+    _LIT(KSQLCreateCombinedIndexText,"CREATE UNIQUE INDEX CombinedIndex on ImageStore (ObjectId, NotificationType)");      
+    User::LeaveIfError(iDatabase.Execute(KSQLCreateCombinedIndexText));
+    
+    __FLOG(_L8("CMediaSyncDatabase::CreateTabIndexL - Exit"));
+    }
+
+void CMediaSyncDatabase::SaveNotificationsL(const RArray<TItemId>& aObjectIdArray, TObserverNotificationType aType, CMdESession& aSession)
+    {    
+    iDatabase.Begin();  
+
+    switch (aType)
+        {
+        case ENotifyAdd:
+            __FLOG(_L8("CMediaSyncDatabase::SaveNotificationsL Addition - Entry"));
+            SaveAddNotificationsL(aObjectIdArray, aSession);
+            break;
+            
+        case ENotifyRemove:
+            __FLOG(_L8("CMediaSyncDatabase::SaveNotificationsL Remove - Entry"));
+            SaveWithoutUriL(aObjectIdArray, KMssRemoval);
+            break;
+            
+        case ENotifyModify:
+            __FLOG(_L8("CMediaSyncDatabase::SaveNotificationsL Modify - Entry"));
+            SaveAndCheckWithUriL(aObjectIdArray, KMssChange, aSession);
+            break;
+            
+        default:
+            __FLOG_VA((_L8("SaveNotificationsL - Unknown argument: %d"), aType));
+            User::Leave(KErrArgument);
+            break;
+        }
+   
+    iDatabase.Commit();
+    
+    __FLOG(_L8("CMediaSyncDatabase::SaveNotificationsL - Exit"));
+    }
+
+inline TBool CMediaSyncDatabase::OptimizeL(TItemId aObjectId, TUint aType)
+    {    
+    return OptimizeL(aObjectId, aType, KNullDesC);
+    }
+
+void CMediaSyncDatabase::Rollback()
+    {
+    __ASSERT_DEBUG(iDatabase.InTransaction(), User::Invariant());
+    iDatabase.Rollback();
+    }
+
+TBool CMediaSyncDatabase::OptimizeL(TItemId aObjectId, TUint aType, const TDesC& aUri)
+    {
+    __FLOG(_L8("CMediaSyncDatabase::OptimizeL - Entry"));
+    
+    TBool saveNotification = ETrue;
+    
+    switch (aType)
+        {                
+    case KMssChange:
+        if ( UpdateUriColumnL(aObjectId, KMssAddition, aUri) ||
+             UpdateUriColumnL(aObjectId, KMssChange, aUri) )
+            {
+            saveNotification = EFalse;// ignore this update notification
+            }
+        __FLOG_VA((_L8("OptimizeL - KMssChange ObjectId: %u, Ignore saving: %d"), aObjectId, saveNotification));
+        break;
+                
+    case KMssPresent:
+        if (RemoveNotificationL(aObjectId, KMssNotPresent))
+            {
+            saveNotification = EFalse;// ignore this present notification
+            }
+        __FLOG_VA((_L8("OptimizeL - KMssPresent ObjectId: %u, Ignore saving: %d"), aObjectId, saveNotification));
+        break;        
+        
+    case KMssRemoval:
+        if (RemoveNotificationL(aObjectId, KMssAddition))
+            {
+            saveNotification = EFalse;// ignore this removal notification
+            }        
+        else
+            {
+            RemoveNotificationL(aObjectId, KMssChange);
+            }
+        __FLOG_VA((_L8("OptimizeL - KMssRemoval ObjectId: %u, Ignore saving: %d"), aObjectId, saveNotification));
+        break;
+        
+    case KMssNotPresent:
+        if (RemoveNotificationL(aObjectId, KMssPresent))
+            {
+            saveNotification = EFalse;// ignore this not present notification
+            }
+        __FLOG_VA((_L8("OptimizeL - KMssNotPresent ObjectId: %u, Ignore saving: %d"), aObjectId, saveNotification));
+        break;
+        
+    default:
+        // Nothing to do
+        break;
+        }
+    
+    __FLOG(_L8("CMediaSyncDatabase::OptimizeL - Exit"));
+    
+    return saveNotification;
+    }
+
+void CMediaSyncDatabase::SaveNotificationsL(const RArray<TItemId>& aObjectIdArray, TBool aPresent, CMdESession& aSession)
+    {        
+    iDatabase.Begin();
+   
+    if (aPresent)
+        {
+        __FLOG(_L8("CMediaSyncDatabase::SaveNotificationsL Present - Entry"));
+        SaveAndCheckWithUriL(aObjectIdArray, KMssPresent, aSession);
+        }
+    else
+        {
+        __FLOG(_L8("CMediaSyncDatabase::SaveNotificationsL Not Present - Entry"));
+        SaveWithoutUriL(aObjectIdArray, KMssNotPresent);
+        }      
+    
+    iDatabase.Commit();  
+    
+    __FLOG(_L8("CMediaSyncDatabase::SaveNotificationsL Present - Exit"));
+    }
+
+void CMediaSyncDatabase::SaveAddNotificationsL(const RArray<TItemId>& aObjectIdArray, CMdESession& aSession)
+    {
+    __FLOG(_L8("CMediaSyncDatabase::SaveAddNotificationsL - Entry"));
+    
+    CMdENamespaceDef& defaultNamespaceDef = aSession.GetDefaultNamespaceDefL();
+    CMdEObjectDef& imageObjDef = defaultNamespaceDef.GetObjectDefL(MdeConstants::Image::KImageObject); 
+
+    TInt objectCount = aObjectIdArray.Count();   
+    for (TInt i(0);i < objectCount;i++)
+        {       
+        TItemId objectId = aObjectIdArray[i];
+        CMdEObject* addObject = aSession.GetObjectL(objectId, imageObjDef);
+        if (addObject)
+            {
+            CleanupStack::PushL(addObject);
+            CleanupStack::PushL(TCleanupItem(CMediaSyncDatabase::RollbackTable, &iBatched));
+            iBatched.InsertL();
+            iBatched.SetColL(1, (TUint32)objectId);
+            iBatched.SetColL(2, KMssAddition);
+            iBatched.SetColL(3, addObject->Uri());
+            iBatched.PutL();
+            CleanupStack::Pop(&iBatched);            
+            __FLOG_VA((_L16("CMediaSyncDatabase::SaveAndCheckWithUriL - ObjectId:%u, Type:%u, URI:%S"), objectId, KMssAddition, &addObject->Uri()));
+            CleanupStack::PopAndDestroy(addObject); 
+            }                                 
+        }      
+    
+    __FLOG(_L8("CMediaSyncDatabase::SaveAddNotificationsL - Exit"));
+    }
+
+void CMediaSyncDatabase::SaveAndCheckWithUriL(const RArray<TItemId>& aObjectIdArray, TUint aType, CMdESession& aSession)
+    {
+    __FLOG(_L8("CMediaSyncDatabase::SaveAndCheckWithUriL - Entry"));
+    
+    CMdENamespaceDef& defaultNamespaceDef = aSession.GetDefaultNamespaceDefL();
+    CMdEObjectDef& imageObjDef = defaultNamespaceDef.GetObjectDefL(MdeConstants::Image::KImageObject); 
+    CMdEPropertyDef& itemTypePropDef = imageObjDef.GetPropertyDefL(MdeConstants::Object::KItemTypeProperty);    
+
+    TInt objectCount = aObjectIdArray.Count();   
+    for (TInt i(0);i < objectCount;i++)
+        {       
+        TItemId objectId = aObjectIdArray[i];          
+        CMdEObject* changeObject = aSession.GetObjectL(objectId, imageObjDef);
+        if (changeObject)
+            {
+            CleanupStack::PushL(changeObject);            
+            //only support jpeg format image files             
+            CMdEProperty* itemType = NULL;
+            TInt err = changeObject->Property(itemTypePropDef, itemType);
+            
+            if (err >= KErrNone && itemType != NULL && itemType->TextValueL().Compare(KJpegMime) == 0)
+                {                        
+                if (OptimizeL(objectId, aType, changeObject->Uri()))
+                    {                    
+                    CleanupStack::PushL(TCleanupItem(CMediaSyncDatabase::RollbackTable, &iBatched));
+                    iBatched.InsertL();
+                    iBatched.SetColL(1, (TUint32)objectId);
+                    iBatched.SetColL(2, aType);                    
+                    iBatched.SetColL(3, changeObject->Uri());
+                    iBatched.PutL();                    
+                    CleanupStack::Pop(&iBatched);
+                    __FLOG_VA((_L16("CMediaSyncDatabase::SaveAndCheckWithUriL - ObjectId:%u, Type:%u, URI:%S"), objectId, aType, &changeObject->Uri()));
+                    }
+                }
+            CleanupStack::PopAndDestroy(changeObject);            
+            }
+        }  
+    
+    __FLOG(_L8("CMediaSyncDatabase::SaveAndCheckWithUriL - Exit"));
+    }
+
+void CMediaSyncDatabase::SaveWithoutUriL(const RArray<TItemId>& aObjectIdArray, TUint aType)
+    {
+    TInt objectCount = aObjectIdArray.Count();   
+    for (TInt i(0);i < objectCount;i++)
+        {       
+        TItemId objectId = aObjectIdArray[i];        
+        if (OptimizeL(objectId, aType))
+            {
+            CleanupStack::PushL(TCleanupItem(CMediaSyncDatabase::RollbackTable, &iBatched));
+            iBatched.InsertL();
+            iBatched.SetColL(1, (TUint32)objectId);
+            iBatched.SetColL(2, aType);
+            iBatched.PutL();
+            __FLOG_VA((_L8("CMediaSyncDatabase::SaveWithoutUriL - ObjectId:%u, Type: %u"), objectId, aType));
+            CleanupStack::Pop(&iBatched);
+            }
+        }
+    
+    __FLOG(_L8("CMediaSyncDatabase::SaveWithoutUriL - Exit"));
+    }
+
+TBool CMediaSyncDatabase::UpdateUriColumnL(TItemId aObjectId, TUint aType, const TDesC& aUri)
+    {
+    __FLOG(_L8("CMediaSyncDatabase::UpdateUriColumnL - Entry"));
+    
+    TBool update = EFalse;
+    
+    iBatched.SetIndex(KSQLCombinedIndex);
+    TDbSeekMultiKey<2> seekKey;
+    seekKey.Add((TUint)aObjectId);
+    seekKey.Add(aType);
+    if (iBatched.SeekL(seekKey))
+        {
+        CleanupStack::PushL(TCleanupItem(CMediaSyncDatabase::RollbackTable, &iBatched));
+        iBatched.UpdateL();                 
+        iBatched.SetColL(3, aUri);
+        iBatched.PutL();        
+        CleanupStack::Pop(&iBatched);
+        update = ETrue;
+        __FLOG_VA((_L16("CMediaSyncDatabase::UpdateUriColumnL - ObjectId:%u, Type:%u, URI:%S"), aObjectId, aType, &aUri));
+        }    
+    
+    __FLOG(_L8("CMediaSyncDatabase::UpdateUriColumnL - Exit"));
+    return update;
+    }
+
+void CMediaSyncDatabase::RemoveAllNotificationsL()
+    {        
+    _LIT(KSQLDeleteAllNotifications, "DELETE FROM ImageStore");
+  
+    User::LeaveIfError(iDatabase.Execute(KSQLDeleteAllNotifications));    
+    iDatabase.Compact();    
+    iSavePosition = EFalse;    
+    
+    __FLOG_VA((_L8("CMediaSyncDatabase::RemoveAllNotificationsL")));
+    }
+
+TBool CMediaSyncDatabase::RemoveNotificationL(TItemId aObjectId, TUint aType)
+    {
+    TBool remove = EFalse;
+    
+    iBatched.SetIndex(KSQLCombinedIndex);
+    TDbSeekMultiKey<2> seekKey;
+    seekKey.Add((TUint)aObjectId);
+    seekKey.Add(aType);
+    if (iBatched.SeekL(seekKey))
+        {
+        iBatched.DeleteL();
+        CompactDatabase();
+        iSavePosition = EFalse;
+        remove = ETrue;
+        __FLOG_VA((_L8("CMediaSyncDatabase::RemoveNotificationL - ObjectId:%u, Type: %u"), aObjectId, aType));
+        }    
+    return remove;
+    }
+
+void CMediaSyncDatabase::CompactDatabase()
+    {
+    if (++iCompactCounter > KCompactThreshold)
+        {
+        iDatabase.Compact();
+        iCompactCounter = 0;
+        }    
+    }
+
+void CMediaSyncDatabase::FetchNotificationsL(CMediaSyncDataWriter& aResulWriter, TInt aMaxtFetchCount, TBool& aIsFinished)
+    {
+    __FLOG(_L8("CMediaSyncDatabase::FetchNotificationsL - Entry"));
+    
+    _LIT(KSQLQuery, "SELECT ObjectId, NotificationType, URI FROM ImageStore");
+    
+    RDbView view;
+    CleanupClosePushL(view);
+    
+    view.Prepare(iDatabase, TDbQuery(KSQLQuery));
+    view.EvaluateAll();
+    
+    //goto the last fetch position
+    if (iSavePosition)
+        {
+        view.GotoL(iBookmark);
+        }
+    else        
+        {
+        view.FirstL();   
+        }
+    
+    TInt entrySize = 0;
+    //tranvers records
+    while (view.AtRow() && (aMaxtFetchCount > 0))
+        {
+        view.GetL();        
+        TPtrC16 uri = view.ColDes16(3);
+        
+        entrySize = uri.Size();
+        entrySize += sizeof(TUint32);//object id size
+        entrySize += sizeof(TUint8);//type size 
+        entrySize += sizeof(TUint8);//uri size
+        
+        if (entrySize > aResulWriter.FreeSpaceBytes())
+            {
+            //there is no enought space to save entry
+            break;
+            }
+        else
+            {
+            aResulWriter.AppendEntryL(view.ColUint32(1), (TUint8)view.ColUint32(2), uri);
+            view.NextL();
+            --aMaxtFetchCount;
+            }                                       
+        }
+    
+    //save current fetch position
+    if (view.AtEnd())
+        {
+        iSavePosition = EFalse;
+        aIsFinished = ETrue;
+        }
+    else
+        {
+        iBookmark = view.Bookmark();
+        iSavePosition = ETrue;
+        aIsFinished = EFalse;
+        }
+    CleanupStack::PopAndDestroy(&view);
+    
+    __FLOG(_L8("CMediaSyncDatabase::FetchNotificationsL - Exit"));
+    }
+
+void CMediaSyncDatabase::RollbackTable(TAny* aTable)
+    {
+    reinterpret_cast<RDbTable*> (aTable)->Cancel();
+    }