--- /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();
+ }