diff -r 000000000000 -r d0791faffa3f mtpdataproviders/mtpimagedp/mediasyncserver/src/cmediasyncdatabase.cpp --- /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 +#include +#include +#include + +#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& 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& 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& 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& 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& 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 (aTable)->Cancel(); + }