mtpfws/mtpfw/src/cmtpobjectstore.cpp
branchRCL_3
changeset 4 60a94a45d437
parent 2 4843bb5893b6
child 5 3673b591050c
--- a/mtpfws/mtpfw/src/cmtpobjectstore.cpp	Mon Mar 15 12:43:12 2010 +0200
+++ b/mtpfws/mtpfw/src/cmtpobjectstore.cpp	Wed Mar 31 22:58:56 2010 +0300
@@ -53,6 +53,56 @@
 const TInt KMaxLimitCommitAfterEnumeration = 256;
 const TInt KMaxLimitCompactInEnumeration = 2048;
 const TInt KMaxLimitCompactAfterEnumeration = 1024;
+const TInt KSnapshotGranularity = 128; 
+
+
+
+
+
+CMTPObjectStore::CSnapshotWorker* CMTPObjectStore::CSnapshotWorker::NewL(CMTPObjectStore* aObjectStore, TBool aOnlyRoot)
+    {
+    CSnapshotWorker* self = new (ELeave) CMTPObjectStore::CSnapshotWorker(aObjectStore, aOnlyRoot);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    return self;
+
+    }
+
+void CMTPObjectStore::CSnapshotWorker::RunL()
+    {
+    iObjectStore->CleanDBSnapshotL(iOnlyRoot);
+    }
+
+void CMTPObjectStore::CSnapshotWorker::DoCancel()
+    {
+    //nothing to do
+    }
+
+TInt CMTPObjectStore::CSnapshotWorker::RunErr()
+    {
+    return KErrNone;
+    }
+
+void CMTPObjectStore::CSnapshotWorker::ActiveSelf()
+    {
+    TRequestStatus *status = &iStatus;
+    iStatus = KRequestPending;
+    User::RequestComplete(status, KErrNone);
+    SetActive();
+    }
+
+CMTPObjectStore::CSnapshotWorker::CSnapshotWorker(CMTPObjectStore* aObjectStore, TBool aOnlyRoot):
+        CActive(EPriorityLow), iObjectStore(aObjectStore), iOnlyRoot(aOnlyRoot)
+    {
+
+    }
+
+void CMTPObjectStore::CSnapshotWorker::ConstructL()
+    {
+    CActiveScheduler::Add(this);
+    }
+
 /**
  MTP object meta data store factory method. 
  @return A pointer to a new CMTPObjectStore instance, ownership IS transferred.
@@ -79,6 +129,7 @@
 	delete iDPIDStore;
 	delete iPkgIDStore;
 	delete iSentinal;
+	delete iSnapshotWorker;
 	TRAP_IGNORE(CommitTransactionL());
 	iDatabase.Compact();
 	iBatched.Close();
@@ -383,8 +434,6 @@
 
 void CMTPObjectStore::InsertObjectL(CMTPObjectMetaData& aObject)
 	{
-	//_LIT(KInsert, "CMTPObjectStore::InsertObjectL");
-	//volatile TTimer t(KInsert);
 	__FLOG(_L8("InsertObjectL - Entry"));
 	iCachedHandle = 0;
 	iCachedSuidHash = 0;
@@ -435,6 +484,7 @@
 				delete iEnumeratingCacheObjList[found];
 				iEnumeratingCacheObjList.Remove(found);
 				}
+			__FLOG_VA(_L8("Found in Snapshot"));
 			}
 		else
 			{//This is a totally new object. insert it after check the db to prevent user wrong operation
@@ -445,10 +495,13 @@
 				}
 			else
 				{
+				aObject.SetUint(CMTPObjectMetaData::EHandle, handle);
 				//while enumerating, we ignore the repeatedly INSERT operations.
 				//User::Leave(KErrAlreadyExists);
 				}
+			__FLOG_VA(_L8("Not Found in Snapshot"));
 			}
+		__FLOG_VA((_L8("InsertObjectL Under enmueration, needUpdateOwner %d needToInsert %d"), needUpdateOwner, needToInsert));
 		}
 	else
 		{
@@ -460,6 +513,7 @@
 			}
 		// dp is not enumerating, do a plain insert
 		needToInsert = ETrue;
+		__FLOG_VA((_L8("InsertObjectL After enmueration, needUpdateOwner %d needToInsert %d"), needUpdateOwner, needToInsert));
 		}
 	if (needToInsert)//needToInsert and needUpdateOwner can't be true at same time
 		{
@@ -540,10 +594,12 @@
 
 void CMTPObjectStore::CommitTransactionL()
 	{
+	__FLOG(_L8("CommitTransactionL Entry"));
 	if (iDatabase.InTransaction())
 		{
 		User::LeaveIfError(iDatabase.Commit());
 		}
+	__FLOG(_L8("CommitTransactionL Exit"));
 	}
 
 void CMTPObjectStore::InsertObjectsL(RPointerArray<CMTPObjectMetaData>& aObjects)
@@ -699,20 +755,25 @@
 	}
 
 void CMTPObjectStore::RemoveObjectL(const TMTPTypeUint32& aHandle)
-	{
-	if (LocateByHandleL(aHandle.Value()))
-		{
-		if (iSingletons.DpController().EnumerateState() != CMTPDataProviderController::EEnumeratedFulllyCompleted &&
-			IsMediaFormat(iBatched.ColUint16(EObjectStoreFormatCode)))
-			{
-			iMtpDeltaDataMgr->UpdateDeltaDataTableL(iBatched.ColInt64(EObjectStorePOUID), CMtpDeltaDataMgr::EDeleted);
-			}
-		iCachedSuidHash = 0;
-		iCachedHandle = 0;
-		iBatched.DeleteL();
-		IncTranOpsNumL();
-		}
-	}
+    {
+    __FLOG_VA((_L8("RemoveObjectL Entry Handle = 0x%x"), aHandle.Value()));
+    if (LocateByHandleL(aHandle.Value()))
+        {
+        if (iSingletons.DpController().EnumerateState() != CMTPDataProviderController::EEnumeratedFulllyCompleted &&
+                IsMediaFormat(iBatched.ColUint16(EObjectStoreFormatCode)))
+            {
+            
+            iMtpDeltaDataMgr->UpdateDeltaDataTableL(iBatched.ColInt64(EObjectStorePOUID), CMtpDeltaDataMgr::EDeleted);
+            }
+        iCachedSuidHash = 0;
+        iCachedHandle = 0;
+        
+        iBatched.DeleteL();
+        __FLOG(_L8("RemoveObjectL From iBacthed"));
+        IncTranOpsNumL();
+        }
+    __FLOG(_L8("RemoveObjectL Exit"));
+    }
 
 void CMTPObjectStore::RemoveObjectL(const TDesC& aSuid)
 	{
@@ -833,12 +894,12 @@
 	iReferenceMgr = CMTPReferenceMgr::NewL(*this);
 	iDPIDStore = CMTPDPIDStore::NewL(iDatabase);
 	iPkgIDStore = CMTPPkgIDStore::NewL(iDatabase);
-	iBatched.Open(iDatabase, KSQLHandleTableName, RDbRowSet::EUpdatable);
-	iBatched.SetIndex(KSQLHandleId);
-	iBatched_SuidHashID.Open(iDatabase, KSQLHandleTableName, RDbRowSet::EUpdatable);
-	iBatched_SuidHashID.SetIndex(KSQLSuidHash);
+	User::LeaveIfError(iBatched.Open(iDatabase, KSQLHandleTableName, RDbRowSet::EUpdatable));
+	User::LeaveIfError(iBatched.SetIndex(KSQLHandleId));
+	User::LeaveIfError(iBatched_SuidHashID.Open(iDatabase, KSQLHandleTableName, RDbRowSet::EUpdatable));
+	User::LeaveIfError(iBatched_SuidHashID.SetIndex(KSQLSuidHash));
 	iHandleAllocator = CMTPHandleAllocator::NewL(*this);
-	iSentinal = CEnumertingCacheItem::NewL(0, 0, 0, 0, 0);
+	iSentinal = CEnumertingCacheItem::NewL(0, 0, 0, 0, 0, 0);
 	BeginTransactionL();
 	}
 
@@ -861,7 +922,7 @@
 	else
 		{
 		err = OpenDb(fullName);
-		if (iDatabase.IsDamaged())
+		if (err==KErrNone && iDatabase.IsDamaged())
 			{
 			err = iDatabase.Recover();
 			}
@@ -981,14 +1042,17 @@
 
 TBool CMTPObjectStore::LocateByHandleL(const TUint aHandle, const TBool aReadTable /*default = ETrue*/) const
 	{
+	__FLOG_VA((_L8("LocateByHandleL - Entry aHandle 0x%x"), aHandle));
 	TBool result = EFalse;
 	if(IsInvalidHandle(aHandle))
 		{
+		__FLOG_VA((_L8("LocateByHandleL - Exit result 0x%x"), result));
 		return result;
 		}
 	
 	if (iCachedHandle == aHandle)
 		{
+		__FLOG(_L8("CacheHit"));
 		result = ETrue;
 		}
 	else
@@ -1007,6 +1071,7 @@
 		{
 		iBatched.GetL();
 		}
+	__FLOG_VA((_L8("LocateByHandleL - Exit result 0x%x"), result));
 	return result;
 	}
 
@@ -1171,107 +1236,152 @@
 		}
 	}
 
+
+
 void CMTPObjectStore::EstablishDBSnapshotL(TUint32 aStorageId)
-	{
-	//Currently, i only do this for File DP since it is non-persistent, later, if we take the proposal that 
-	//1. FileDP is the last DP to be enumerated.
-	//2. FileDP will san the whole file system, and will try to enumerate all of the objects(might on behalf of another DP) if the objects is still not
-	// in the object store after all other DP finish its enumeration.
-	//3. Then notify the related DP about the newly added objects by notification API;
-	//_LIT(KInsert, "CMTPObjectStore::EstablishDBSnapshotL");
-	//volatile TTimer t(KInsert);
-	RDbTable temp;
-	CleanupClosePushL(temp);
-	temp.Open(iDatabase, KSQLHandleTableName, RDbRowSet::EUpdatable);
+    {
+    //Currently, i only do this for File DP since it is non-persistent, later, if we take the proposal that 
+    //1. FileDP is the last DP to be enumerated.
+    //2. FileDP will san the whole file system, and will try to enumerate all of the objects(might on behalf of another DP) if the objects is still not
+    // in the object store after all other DP finish its enumeration.
+    //3. Then notify the related DP about the newly added objects by notification API;
+    __FLOG(_L8("EstablishDBSnapshotL - Entry"));
+    RDbTable temp;
+    CleanupClosePushL(temp);
+    User::LeaveIfError(temp.Open(iDatabase, KSQLHandleTableName, RDbRowSet::EUpdatable));
     if(!iCacheExist)
         {
-	TInt32 count = temp.CountL(RDbRowSet::EQuick);
+        TInt32 count = temp.CountL(RDbRowSet::EQuick);
         iEnumeratingCacheObjList.ReserveL(count);
         }
-	temp.FirstL();
-	while (!temp.AtEnd())
-		{
-		temp.GetL();
-        if (temp.ColUint8(EObjectStoreDPFlag) == 1 && (KMTPStorageAll == aStorageId || temp.ColUint32(EObjectStoreStorageId) == aStorageId))
-			{
-			TUint32 handleID = temp.ColUint32(EObjectStoreHandleId);
-			TInt64 pUID = temp.ColInt64(EObjectStorePOUID);
-			iHandleAllocator->SetIdL(handleID, pUID);
-			CEnumertingCacheItem* item = CEnumertingCacheItem::NewLC(
-					temp.ColUint32(EObjectStoreSUIDHash), handleID,
-					temp.ColUint16(EObjectStoreFormatCode), pUID, temp.ColUint8(EObjectStoreDataProviderId));
-			TInt result = iEnumeratingCacheObjList.InsertInOrder(item, TLinearOrder<CEnumertingCacheItem>(CEnumertingCacheItem::Compare));
-			if (KErrAlreadyExists == result) //hash collision
-				{
-				TInt found = iEnumeratingCacheObjList.FindInOrder(item, TLinearOrder<CEnumertingCacheItem>(CEnumertingCacheItem::Compare));
-				CEnumertingCacheItem* colliItem = iEnumeratingCacheObjList[found];
+    temp.FirstL();
+
+    while (!temp.AtEnd())
+        {
+        temp.GetL();
+        if (temp.ColUint8(EObjectStoreDPFlag) == 1 
+                && (KMTPStorageAll == aStorageId || temp.ColUint32(EObjectStoreStorageId) == aStorageId))
+            {
+            TUint32 handleID = temp.ColUint32(EObjectStoreHandleId);
+            TUint32 parentID = temp.ColUint32(EObjectStoreParentHandle);
+            TInt64 pUID = temp.ColInt64(EObjectStorePOUID);
+            iHandleAllocator->SetIdL(handleID, pUID);
+            CEnumertingCacheItem* item = CEnumertingCacheItem::NewLC(
+                    temp.ColUint32(EObjectStoreSUIDHash), handleID, parentID,
+                    temp.ColUint16(EObjectStoreFormatCode), pUID, temp.ColUint8(EObjectStoreDataProviderId));
+            TInt result = iEnumeratingCacheObjList.InsertInOrder(item, TLinearOrder<CEnumertingCacheItem>(CEnumertingCacheItem::Compare));
+            if (KErrAlreadyExists == result) //hash collision
+                {
+                TInt found = iEnumeratingCacheObjList.FindInOrder(item, TLinearOrder<CEnumertingCacheItem>(CEnumertingCacheItem::Compare));
+                CEnumertingCacheItem* colliItem = iEnumeratingCacheObjList[found];
                 TFileName suid;
-				if (colliItem->iSuid == NULL)
-					{
-					if (!LocateByHandleL(colliItem->iObjHandleId))
-					    {
-					    DbColReadStreamL(iBatched, EObjectStoreSUID, suid);
-					    
-					    colliItem->iSuid = suid.AllocL();
-					    
-					    colliItem->iSuidPtr.Set(*colliItem->iSuid);
-					    }
-					}
+                if (colliItem->iSuid == NULL)
+                    {
+                    if (LocateByHandleL(colliItem->iObjHandleId))
+                        {
+                        DbColReadStreamL(iBatched, EObjectStoreSUID, suid);
+                        colliItem->iSuid = suid.AllocL();
+                        colliItem->iSuidPtr.Set(*colliItem->iSuid);
+                        }
+                    }
+
                 DbColReadStreamL(temp, EObjectStoreSUID, suid);
-				
+                
                 item->iSuid = suid.AllocL();
                 
-				item->iSuidPtr.Set(*item->iSuid);
+                item->iSuidPtr.Set(*item->iSuid);
                 result = iEnumeratingCacheObjList.InsertInOrder(item, TLinearOrder<CEnumertingCacheItem>(CEnumertingCacheItem::Compare));
-				}
+                }
+            
             if(result != KErrAlreadyExists)
-				{
-				User::LeaveIfError(result);
-				}
-			CleanupStack::Pop(item);
-			}
-		temp.NextL();
-		}
-	CleanupStack::PopAndDestroy(&temp);
-	iCacheExist = ETrue;
-	}
+                {
+                User::LeaveIfError(result);
+                CleanupStack::Pop(item);
+                }
+            else
+                {
+                CleanupStack::PopAndDestroy(item);
+                }
+
+            }
+        temp.NextL();
+        }
 
-void CMTPObjectStore::CleanDBSnapshotL()
-	{
-	//For those items left in the iEnumeratingCacheObjList, remove the object entry if the DPID of the handle is not persistent. and populate the 
-	//roundtrip table if needed.
-	//and then close the iEnumeratingCacheObjList to release the memory.
-	//_LIT(KInsert, "CMTPObjectStore::CleanDBSnapshot");
-	//volatile TTimer t(KInsert);
-	if(iCacheExist)
-	    {
-	        iCacheExist = EFalse;
-	    }
-	else 
-	    return;
-
-	for (TInt i = iEnumeratingCacheObjList.Count() - 1; i >= 0; i--)
-		{
-		TInt rc = iNonPersistentDPList.FindInOrder(iEnumeratingCacheObjList[i]->iDpID);
-		if (rc != KErrNotFound)
-			{//This is a non persistent DP.
-			RemoveObjectL(iEnumeratingCacheObjList[i]->iObjHandleId);
-			}
-		}
-	iNonPersistentDPList.Close();
-	iEnumeratingCacheObjList.ResetAndDestroy();
-	iUpdateDeltaDataTable = ETrue;
-	iMaxCommitLimit = KMaxLimitCommitAfterEnumeration;
-	iMaxCompactLimit = KMaxLimitCompactAfterEnumeration;
+    CleanupStack::PopAndDestroy(&temp);
+    iCacheExist = ETrue;
+    __FLOG_VA((_L8("EstablishDBSnapshotL - Exit build %d items"), iEnumeratingCacheObjList.Count()));
+    }
+/*
+ * All Objects enumeration complete
+ */
+void CMTPObjectStore::ObjectsEnumComplete()
+    {
+    if(iCacheExist)
+        {
+        iCacheExist = EFalse;
+        }
+    iNonPersistentDPList.Close();
+    iEnumeratingCacheObjList.ResetAndDestroy();
+    iUpdateDeltaDataTable = ETrue;
+    iMaxCommitLimit = KMaxLimitCommitAfterEnumeration;
+    iMaxCompactLimit = KMaxLimitCompactAfterEnumeration;
     CommitTransactionL();
     User::LeaveIfError(iDatabase.Compact());
     BeginTransactionL();
-	}
+    }
+
 
-CMTPObjectStore::CEnumertingCacheItem::CEnumertingCacheItem(TUint32 aSuidHash, TUint32 aHandle, TUint32 aFormat, TUint64 aId, TUint8 aDpID)
+void CMTPObjectStore::CleanDBSnapshotL(TBool aOnlyRoot/* = EFalse*/)
+    {
+    //For those items left in the iEnumeratingCacheObjList, remove the object entry if the DPID of the handle is not persistent. and populate the 
+    //roundtrip table if needed.
+    //and then close the iEnumeratingCacheObjList to release the memory.
+    //_LIT(KInsert, "CMTPObjectStore::CleanDBSnapshot");
+    //volatile TTimer t(KInsert);
+    __FLOG(_L8("CleanDBSnapshotL Entry"));
+    if (iSnapshotWorker == NULL)
+        {
+        iSnapshotCleanPos = iEnumeratingCacheObjList.Count() - 1;
+        iSnapshotWorker = CSnapshotWorker::NewL(this, aOnlyRoot);
+        }
+    
+    //for (TInt i = iEnumeratingCacheObjList.Count() - 1; i >= 0; i--)
+    for (TInt i = 0; iSnapshotCleanPos >= 0 && i <= KSnapshotGranularity; --iSnapshotCleanPos, ++i)
+        {
+        if((aOnlyRoot && iEnumeratingCacheObjList[iSnapshotCleanPos]->iObjParentId == KMTPHandleNoParent) //only root 
+           ||(!aOnlyRoot)) //everything
+            {
+            TInt rc = iNonPersistentDPList.FindInOrder(iEnumeratingCacheObjList[iSnapshotCleanPos]->iDpID);
+            if (rc != KErrNotFound)
+                {//This is a non persistent DP.
+                __FLOG_VA((_L8("Remove Object 0x%x"), iEnumeratingCacheObjList[iSnapshotCleanPos]->iObjHandleId));
+                RemoveObjectL(iEnumeratingCacheObjList[iSnapshotCleanPos]->iObjHandleId);
+                }
+            }
+        }
+    
+    if (iSnapshotCleanPos >= 0)
+        {
+        iSnapshotWorker->ActiveSelf();
+        }
+    else
+        {
+        //TRequestStatus *status = &aStatus;
+        //User::RequestComplete(status, KErrNone);
+        iSingletons.DpController().Schedule();
+        iSnapshotCleanPos = 0;
+        delete iSnapshotWorker;
+        iSnapshotWorker = NULL;
+        }
+    
+    __FLOG(_L8("CleanDBSnapshotL Exit"));
+    }
+
+CMTPObjectStore::CEnumertingCacheItem::CEnumertingCacheItem(TUint32 aSuidHash, TUint32 aHandle, TUint32 aParent, TUint32 aFormat, TUint64 aId, TUint8 aDpID)
 	{
 	iObjSuiIdHash = aSuidHash;
 	iObjHandleId = aHandle;
+	iObjParentId = aParent;
 	iFormatcode = aFormat;
 	iPOUID = aId;
 	iDpID = aDpID;