mtpfws/mtpfw/src/cmtpobjectstore.cpp
changeset 0 d0791faffa3f
child 1 f8e15b44d440
equal deleted inserted replaced
-1:000000000000 0:d0791faffa3f
       
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 #include <bautils.h>
       
    16 #include <f32file.h>
       
    17 #include <s32file.h>
       
    18 #include "tmtptypeobjecthandle.h"
       
    19 #include <mtp/cmtpobjectmetadata.h>
       
    20 #include <mtp/cmtptypearray.h>
       
    21 #include <mtp/mmtpobjectmgr.h>
       
    22 #include <mtp/mtpdatatypeconstants.h>
       
    23 #include <mtp/mtpobjectmgrquerytypes.h>
       
    24 #include <mtp/mtpprotocolconstants.h>
       
    25 #include <mtp/tmtptypeuint32.h>
       
    26 #include "cmtphandleallocator.h"
       
    27 #include "cmtpobjectstore.h"
       
    28 #include "cmtpreferencemgr.h"
       
    29 #include "dbutility.h"
       
    30 #include "cmtpdataprovidercontroller.h"
       
    31 #include "cmtpdataprovider.h"
       
    32 #include "cmtpdpidstore.h"
       
    33 #include "cmtppkgidstore.h"
       
    34 #include "cmtpdeltadatamgr.h"
       
    35 #include <e32hashtab.h>
       
    36 #include "cmtpstoragemgr.h"
       
    37 
       
    38 _LIT(KMTPDbDriveLocation, "c:");
       
    39 _LIT(KMTPBackSlash, "\\");
       
    40 _LIT(KMTPHandleObjectDbName, "MTPObjectStore.db");
       
    41 _LIT(KMTPNoBackupFolderName, "nobackup");
       
    42 _LIT(KSQLHandleTableName, "HandleStore");
       
    43 _LIT(KSQLCreateHandleTableText, "CREATE TABLE HandleStore (HandleId UNSIGNED INTEGER, SuidHash UNSIGNED INTEGER, Suid LONG VARCHAR, DataProviderId UNSIGNED TINYINT, FormatCode UNSIGNED SMALLINT, FormatSubCode UNSIGNED SMALLINT, StorageId UNSIGNED INTEGER, Modes UNSIGNED TINYINT, POUID BIGINT, ParentHandle UNSIGNED INTEGER, DPFlag UNSIGNED TINYINT, NonConsumable UNSIGNED TINYINT, Name VARCHAR(255))");
       
    44 _LIT(KSQLHandleId, "HandleIndex");
       
    45 _LIT(KSQLCreateHandleIndexText,"CREATE UNIQUE INDEX HandleIndex on HandleStore (HandleId)");
       
    46 _LIT(KSQLSuidHash, "SuidIndex");
       
    47 _LIT(KSQLCreateSuidIndexText,"CREATE INDEX SuidIndex on HandleStore (SuidHash)");
       
    48 _LIT(KSQLParentHandle, "ParentHandleIndex");
       
    49 _LIT(KSQLCreateParentHandleText,"CREATE INDEX ParentHandleIndex on HandleStore (ParentHandle)");
       
    50 _LIT(KMTPFormat, "MTP");
       
    51 __FLOG_STMT(_LIT8(KComponent,"MTPObjectStore");)
       
    52 const TInt KMaxLimitCommitInEnumeration = 1024;
       
    53 const TInt KMaxLimitCommitAfterEnumeration = 256;
       
    54 const TInt KMaxLimitCompactInEnumeration = 2048;
       
    55 const TInt KMaxLimitCompactAfterEnumeration = 1024;
       
    56 /**
       
    57  MTP object meta data store factory method. 
       
    58  @return A pointer to a new CMTPObjectStore instance, ownership IS transferred.
       
    59  @leave One of the system wide error codes, if a processing failure occurs.
       
    60  */
       
    61 CMTPObjectStore* CMTPObjectStore::NewL()
       
    62 	{
       
    63 	CMTPObjectStore* self = new (ELeave) CMTPObjectStore();
       
    64 	CleanupStack::PushL(self);
       
    65 	self->ConstructL();
       
    66 	CleanupStack::Pop(self);
       
    67 	return self;
       
    68 	}
       
    69 
       
    70 /**
       
    71  Destructor.
       
    72  */
       
    73 CMTPObjectStore::~CMTPObjectStore()
       
    74 	{
       
    75 	delete iCompactor;
       
    76 	delete iReferenceMgr;
       
    77 	delete iHandleAllocator;
       
    78 	delete iMtpDeltaDataMgr;
       
    79 	delete iDPIDStore;
       
    80 	delete iPkgIDStore;
       
    81 	delete iSentinal;
       
    82 	TRAP_IGNORE(CommitTransactionL());
       
    83 	iDatabase.Compact();
       
    84 	iBatched.Close();
       
    85 	iBatched_SuidHashID.Close();
       
    86 	CloseDb();
       
    87 	iSingletons.Close();
       
    88 	iNonPersistentDPList.Close();
       
    89 	iEnumeratingCacheObjList.ResetAndDestroy();
       
    90 	__FLOG_CLOSE;
       
    91 	}
       
    92 
       
    93 /**
       
    94  Provides a reference to the object meta data store database.
       
    95  @return The object information store database.
       
    96  */
       
    97 RDbDatabase& CMTPObjectStore::Database()
       
    98 	{
       
    99 	return iDatabase;
       
   100 	}
       
   101 
       
   102 /**
       
   103  Provides a reference to the DPID store object.
       
   104  @return The DPID store.
       
   105  */
       
   106 CMTPDPIDStore& CMTPObjectStore::DPIDStore() const
       
   107 	{
       
   108 	return *iDPIDStore;
       
   109 	}
       
   110 
       
   111 CMTPPkgIDStore& CMTPObjectStore::PkgIDStore() const
       
   112 	{
       
   113 	return *iPkgIDStore;
       
   114 	}
       
   115 
       
   116 /**
       
   117  Provides a reference to the reference manager object.
       
   118  @return The reference manager.
       
   119  */
       
   120 CMTPReferenceMgr& CMTPObjectStore::ReferenceMgr() const
       
   121 	{
       
   122 	return *iReferenceMgr;
       
   123 	}
       
   124 
       
   125 /**
       
   126 Provides a reference to the MTP delta Data manager object.
       
   127 @return The MTP delta data manager.
       
   128 */ 
       
   129 CMtpDeltaDataMgr* CMTPObjectStore:: MtpDeltaDataMgr() const
       
   130 	{
       
   131 	return iMtpDeltaDataMgr;
       
   132 	}
       
   133 
       
   134 void CMTPObjectStore::RemoveNonPersistentObjectsL(TUint /*aDataProviderId*/)
       
   135 	{
       
   136 	}
       
   137 
       
   138 void CMTPObjectStore::MarkNonPersistentObjectsL(TUint aDataProviderId, TUint32)
       
   139 	{
       
   140 	TInt result = iNonPersistentDPList.InsertInOrder(aDataProviderId);
       
   141 	if(result != KErrAlreadyExists)
       
   142 		{
       
   143 		User::LeaveIfError(result);
       
   144 		}
       
   145 	}
       
   146 
       
   147 void CMTPObjectStore::MarkDPLoadedL(TUint aDataProviderId, TBool aFlag)
       
   148 	{
       
   149 	__FLOG(_L8("MarkDPFlafFalseL - Entry"));
       
   150 	if (!aFlag)
       
   151 		{
       
   152 		_LIT(KSQLMarkfalgDPFalse, "UPDATE HandleStore SET DPFlag = %u WHERE DataProviderId = %u");
       
   153 		iSqlStatement.Format(KSQLMarkfalgDPFalse, aFlag, aDataProviderId);
       
   154 		User::LeaveIfError(iDatabase.Execute(iSqlStatement));
       
   155 		}
       
   156 	__FLOG(_L8("MarkNonPersistentObjectsL - Exit"));
       
   157 	}
       
   158 
       
   159 TBool CMTPObjectStore::FilterObject(const RDbTable& aCurrRow,const TUint32 aStorageID,const TUint32 aFormatCode,const TUint32 aDpID) const
       
   160     {
       
   161     return  ( ((KMTPStorageAll==aStorageID) ||(aCurrRow.ColUint32(EObjectStoreStorageId)== aStorageID)) 
       
   162             
       
   163             &&((0 == aFormatCode)||(aCurrRow.ColUint16(EObjectStoreFormatCode) == aFormatCode)) 
       
   164             
       
   165             &&((aDpID==KMTPDataProviderAll)||(aCurrRow.ColUint8(EObjectStoreDataProviderId) == aDpID ))
       
   166             );
       
   167     }
       
   168 
       
   169 
       
   170 void CMTPObjectStore::TraverseL(const TMTPObjectMgrQueryParams& aParams, MTraverseAction& action) const
       
   171 	{
       
   172 	RDbTable temp;
       
   173 	CleanupClosePushL(temp);
       
   174 	temp.Open(iDatabase, KSQLHandleTableName, RDbRowSet::EUpdatable);
       
   175 
       
   176 	TUint32 tmpStorageID = 0;
       
   177 	TBool bStorageAvailable = ETrue;
       
   178 	
       
   179 	if (aParams.iParentHandle == 0)
       
   180 		{//ParentHandle is not used to filter the objects. Need to iterate throught all objects in the storage to filter based on format/dpid/storatgeid.
       
   181 		//Do not using index to iterate through the whole storage is faster than index iteration.
       
   182 		temp.FirstL();
       
   183 		while (!temp.AtEnd())
       
   184 			{
       
   185 			temp.GetL();
       
   186 			if ((MTraverseAction::EAllDP == action.Target()) || (temp.ColUint8(EObjectStoreDPFlag) == 1))//If the DP is loaded or ation for all dps.
       
   187 				{
       
   188 
       
   189 				if((aParams.iStorageId == KMTPStorageAll) &&(aParams.iFormatCode == 0)&&(iSingletons.DpController().DataProviderL(temp.ColUint8(EObjectStoreDataProviderId)).SupportedCodes( EServiceIDs ).Count() != 0))
       
   190 				    {
       
   191 				    temp.NextL();
       
   192 				    continue;
       
   193 				    }
       
   194 				
       
   195 				//check StorageID ,DPID and Formatcode
       
   196 				if ( !FilterObject(temp,aParams.iStorageId,aParams.iFormatCode,aParams.iDpId) )
       
   197 				    {
       
   198 						temp.NextL();
       
   199 						continue;
       
   200 				    }
       
   201 				    
       
   202 				//verify the whether the storageID is validated.   
       
   203 				if(tmpStorageID != temp.ColUint32(EObjectStoreStorageId))
       
   204 					{
       
   205 					tmpStorageID = temp.ColUint32(EObjectStoreStorageId);
       
   206 					bStorageAvailable = iSingletons.StorageMgr().ValidStorageId( tmpStorageID );
       
   207 					}
       
   208 				if(!bStorageAvailable)
       
   209 					{
       
   210 					temp.NextL();
       
   211 					continue;
       
   212 					}
       
   213 								
       
   214 				action.DoL(temp); 
       
   215 				}
       
   216 			temp.NextL();
       
   217 			}
       
   218 		}
       
   219 	else
       
   220 		{//Fetch the root directory
       
   221 		temp.SetIndex(KSQLParentHandle);
       
   222 		if (temp.SeekL((TUint) aParams.iParentHandle))
       
   223 			{//every storageID has the same root directory handles.KMTPHandleNoParent, therefore, need to filter the storageID
       
   224 			//if it is not KMTPStorageAll
       
   225 			while (!temp.AtEnd())
       
   226 				{
       
   227 				temp.GetL();
       
   228 				if (temp.ColUint32(EObjectStoreParentHandle) == aParams.iParentHandle)
       
   229 					{
       
   230 					if ((MTraverseAction::EAllDP == action.Target()) || (temp.ColUint8(EObjectStoreDPFlag) == 1))//If the DP is loaded or ation for all dps.
       
   231 						{
       
   232 						
       
   233             if((aParams.iStorageId == KMTPStorageAll) &&(aParams.iFormatCode == 0)&&(iSingletons.DpController().DataProviderL(temp.ColUint8(EObjectStoreDataProviderId)).SupportedCodes( EServiceIDs ).Count() != 0))
       
   234                 {
       
   235                 temp.NextL();
       
   236                 continue;
       
   237                 }
       
   238 		                
       
   239 						//check StorageID ,DPID and Formatcode
       
   240 						if ( !FilterObject(temp,aParams.iStorageId,aParams.iFormatCode,aParams.iDpId) )
       
   241 						    {
       
   242 								temp.NextL();
       
   243 								continue;
       
   244 						    }
       
   245 						    
       
   246 						//verify the whether the storageID is validated.   
       
   247 						if(tmpStorageID != temp.ColUint32(EObjectStoreStorageId))
       
   248 							{
       
   249 							tmpStorageID = temp.ColUint32(EObjectStoreStorageId);
       
   250 							bStorageAvailable = iSingletons.StorageMgr().ValidStorageId( tmpStorageID );
       
   251 							}
       
   252 						if(!bStorageAvailable)
       
   253 							{
       
   254 							temp.NextL();
       
   255 							continue;
       
   256 							}
       
   257 		                
       
   258 						action.DoL(temp);
       
   259 						}
       
   260 					temp.NextL();
       
   261 					}
       
   262 				else
       
   263 					{
       
   264 					break;//has jumped over the range of handles with the same parent handle
       
   265 					}
       
   266 				}
       
   267 			}
       
   268 		}
       
   269 	CleanupStack::PopAndDestroy(&temp);
       
   270 	//Since we fetch all handles as requested, therefore, we do not open aContext to indicate the query is completed.
       
   271 	}
       
   272 
       
   273 TUint CMTPObjectStore::CountL(const TMTPObjectMgrQueryParams& aParams) const
       
   274 	{
       
   275 	TUint i = 0;
       
   276 	TCountAction action(i);
       
   277 	TraverseL(aParams, action);
       
   278 	return i;
       
   279 	}
       
   280 
       
   281 void CMTPObjectStore::CommitReservedObjectHandleL(CMTPObjectMetaData& aObject)
       
   282 	{
       
   283 	//After the PutL called the cursor's position is not well defined.
       
   284 	iCachedHandle = 0;
       
   285 	iCachedSuidHash = 0;
       
   286 	TInt64 id = iHandleAllocator->NextPOUIDL();
       
   287 	aObject.SetUint(CMTPObjectMetaData::EIdentifier, id);
       
   288 
       
   289 	TFileName suid;
       
   290 	suid.CopyLC(aObject.DesC(CMTPObjectMetaData::ESuid));
       
   291 	TUint32 suidHash = DefaultHash::Des16(suid);
       
   292 
       
   293 	TUint32 handle = aObject.Uint(CMTPObjectMetaData::EHandle);
       
   294 	CleanupStack::PushL(TCleanupItem(CMTPObjectStore::DBUpdateFailRecover, &iBatched));
       
   295 	iBatched.InsertL();
       
   296 	iBatched.SetColL(EObjectStoreHandleId, handle);
       
   297 	iBatched.SetColL(EObjectStoreSUIDHash, suidHash);
       
   298 	DbColWriteStreamL(iBatched, EObjectStoreSUID, aObject.DesC(CMTPObjectMetaData::ESuid));	
       
   299 	iBatched.SetColL(EObjectStoreDataProviderId, aObject.Uint(CMTPObjectMetaData::EDataProviderId));
       
   300 	iBatched.SetColL(EObjectStoreFormatCode, aObject.Uint(CMTPObjectMetaData::EFormatCode));
       
   301 	iBatched.SetColL(EObjectStoreFormatSubCode, aObject.Uint(CMTPObjectMetaData::EFormatSubCode));
       
   302 	iBatched.SetColL(EObjectStoreStorageId, aObject.Uint(CMTPObjectMetaData::EStorageId));
       
   303 	iBatched.SetColL(EObjectStoreModes,aObject.Uint(CMTPObjectMetaData::EModes));
       
   304 	iBatched.SetColL(EObjectStorePOUID, id);
       
   305 	iBatched.SetColL(EObjectStoreParentHandle, aObject.Uint(CMTPObjectMetaData::EParentHandle));
       
   306 	iBatched.SetColL(EObjectStoreDPFlag, 1);
       
   307 	iBatched.SetColL(EObjectStoreNonConsumable, aObject.Uint(CMTPObjectMetaData::ENonConsumable));
       
   308 	iBatched.SetColL(EObjectStoreName, aObject.DesC(CMTPObjectMetaData::EName));
       
   309 	
       
   310 	iBatched.PutL();
       
   311 	CleanupStack::Pop(&iBatched);
       
   312 	IncTranOpsNumL();
       
   313 
       
   314 	}
       
   315 
       
   316 /*
       
   317  This API is designed intended for coping with the MTP operation GetObjectHandles which has 3 parameters.
       
   318  1. StorageID
       
   319  2. FormatCode
       
   320  3. ParentHandle.
       
   321 
       
   322  The first parameter contains the StorageID of the storage for which the list of Object Handles is desired. 
       
   323  A value of 0xFFFFFFFF may be used to indicate that a list of Object Handles of all objects on all storages 
       
   324  should be returned. If a storage is specified and the storage is unavailable, this operation should return Store_Not_Available.
       
   325 
       
   326  The second parameter is optional, and contains an Object Format datacode. Object Formats are described
       
   327  in section 4, "Object Formats". If the second parameter contains a non-0x00000000 value, it specifies that 
       
   328  a list of object handles referencing objects of a certain object format is desired. If the parameter is not used, 
       
   329  it should contain a value of 0x00000000 and objects should be included in the response dataset regardless 
       
   330  of their object format. If this parameter is not supported, the responder should return a response code of 
       
   331  Specification_By_Format_Unsupported.
       
   332 
       
   333  The third parameter may be used to restrict the list of objects that are returned by this operation to objects 
       
   334  directly contained in a particular folder (Association). If this parameter contains a non-0x00000000 value, 
       
   335  the responder should return a list of objects which have as their ParentObject the folder (Association) 
       
   336  that is identified by this parameter. If the number of objects that are contained in the root of a storage is desired, 
       
   337  a value of 0xFFFFFFFF may be passed in this operation, which indicates that only those objects with no ParentObject
       
   338  should be returned. If the first parameter indicates that all storages are included in this query, then a value of 0xFFFFFFFF
       
   339  should return a list of all objects at the root level of all storages. If this parameter is unused, it should contain a value of 0x00000000. 
       
   340 
       
   341  If the third parameter is unsupported and a non-0x00000000 value is sent in this operation, a response of 
       
   342  Parameter_Unsupported should be returned. If the use of the third parameter is supported, but the value 
       
   343  contained does not reference an actual object on the device, a response of Invalid_ObjectHandle should be returned. 
       
   344  If the use of the third parameter is supported and it contains a valid Object Handle, but the object referenced 
       
   345  is not of type Association, then a response of Invalid_ParentObject should be returned.
       
   346 
       
   347 
       
   348  */
       
   349 void CMTPObjectStore::GetObjectHandlesL(const TMTPObjectMgrQueryParams& aParams, RMTPObjectMgrQueryContext& /*aContext*/, RArray<TUint>& aHandles) const
       
   350 	{
       
   351 	TGetHandlesAction action(aHandles);
       
   352 	TraverseL(aParams, action);
       
   353 	}
       
   354 
       
   355 void CMTPObjectStore::GetObjectSuidsL(const TMTPObjectMgrQueryParams& aParams, RMTPObjectMgrQueryContext& /*aContext*/, CDesCArray& aSuids) const
       
   356 	{
       
   357 	//take the similar approach for GetObjectHandlesL, but need to pay attention for the memory usage, since every SUID might take
       
   358 	//maximum 255 bytes, if there are totally 10K objects, the maximum memory usage will be 2.5M, consider to get it in multiple calls instead of one.
       
   359 	TGetSuidsAction action(aSuids);
       
   360 	TraverseL(aParams, action);
       
   361 	}
       
   362 
       
   363 TUint32 CMTPObjectStore::HandleL(const TDesC& aSuid) const
       
   364 	{
       
   365 	TUint32 handle = KMTPHandleNone;
       
   366 	if (LocateBySuidL(aSuid))
       
   367 		{
       
   368 		handle = iBatched_SuidHashID.ColUint32(EObjectStoreHandleId);
       
   369 		}
       
   370 	return handle;
       
   371 	}
       
   372 
       
   373 void CMTPObjectStore::DBUpdateFailRecover(TAny* aTable)
       
   374 	{
       
   375 	reinterpret_cast<RDbTable*> (aTable)->Cancel();
       
   376 	}
       
   377 
       
   378 void CMTPObjectStore::InsertObjectL(CMTPObjectMetaData& aObject)
       
   379 	{
       
   380 	//_LIT(KInsert, "CMTPObjectStore::InsertObjectL");
       
   381 	//volatile TTimer t(KInsert);
       
   382 	__FLOG(_L8("InsertObjectL - Entry"));
       
   383 	iCachedHandle = 0;
       
   384 	iCachedSuidHash = 0;
       
   385 	TBool needToInsert = EFalse;
       
   386 	TBool needUpdateOwner = EFalse;
       
   387 	TUint dpId(aObject.Uint(CMTPObjectMetaData::EDataProviderId));
       
   388 	TFileName suid;
       
   389 	suid.CopyLC(aObject.DesC(CMTPObjectMetaData::ESuid));
       
   390 	TUint32 suidHash = DefaultHash::Des16(suid);
       
   391 	TUint32 parentHandle = aObject.Uint(CMTPObjectMetaData::EParentHandle);
       
   392 	TUint32 handle = KMTPHandleNone, handleInDB = KMTPHandleAll;
       
   393 	TInt64 id = 0;
       
   394 	// Check if the dp is enumerating
       
   395 	if (iSingletons.DpController().EnumerateState() != CMTPDataProviderController::EEnumerated && iCacheExist)
       
   396 		{
       
   397 		//it is in the object enumeration phase. 
       
   398 		// if it's see if we have an object with the same SUID
       
   399 		//When the MTP server startup the object enumeration, it will fetch all of the object's (SUIDHash and Handles) into in-memory ordered array.
       
   400 		//this function is to try to match the handleID for the incoming suidHash/SUID/DPID, if matched in memory, it will return the handleID
       
   401 		//considering the possible conflicting of the SUID for different file name, it need to consult the SUID in the table for eactly match.
       
   402 		//Therefore, for each object matching, it need one table lookup and file name cope and match operation.
       
   403 		//If it matched, do nothing for the table, but remove it from the in-memory ordered array.
       
   404 		//if there is no match, it is a new object, insert it into table.
       
   405 		iSentinal->iObjSuiIdHash = suidHash;
       
   406 		iSentinal->iSuidPtr.Set(aObject.DesC(CMTPObjectMetaData::ESuid));
       
   407 		TInt found = iEnumeratingCacheObjList.FindInOrder(iSentinal, TLinearOrder<CEnumertingCacheItem>(CEnumertingCacheItem::Compare));
       
   408 		if (KErrNotFound != found)
       
   409 			{//There is a match
       
   410 			if(NULL == iEnumeratingCacheObjList[found]->iSuid)
       
   411 				{//need extra check for hash collision
       
   412 				handleInDB = HandleL(aObject.DesC(CMTPObjectMetaData::ESuid));
       
   413 				}
       
   414 			handle = iEnumeratingCacheObjList[found]->iObjHandleId;
       
   415 			if((handleInDB != KMTPHandleAll) && (handleInDB != handle)) //hash collision
       
   416 				{
       
   417 				needToInsert = ETrue;
       
   418 				}
       
   419 			else
       
   420 				{
       
   421 				aObject.SetUint(CMTPObjectMetaData::EHandle, handle);
       
   422 				id = iEnumeratingCacheObjList[found]->iPOUID;
       
   423 				aObject.SetUint(CMTPObjectMetaData::EIdentifier, id);
       
   424 				if(iEnumeratingCacheObjList[found]->iFormatcode != aObject.Uint(CMTPObjectMetaData::EFormatCode))
       
   425 					{//have different owner
       
   426 					needUpdateOwner = ETrue;
       
   427 					}
       
   428 				delete iEnumeratingCacheObjList[found];
       
   429 				iEnumeratingCacheObjList.Remove(found);
       
   430 				}
       
   431 			}
       
   432 		else
       
   433 			{//This is a totally new object. insert it after check the db to prevent user wrong operation
       
   434 			handle = HandleL(aObject.DesC(CMTPObjectMetaData::ESuid));
       
   435 			if (handle == KMTPHandleNone)
       
   436 				{
       
   437 				needToInsert = ETrue;
       
   438 				}
       
   439 			else
       
   440 				{
       
   441 				User::Leave(KErrAlreadyExists);
       
   442 				}
       
   443 			}
       
   444 		}
       
   445 	else
       
   446 		{
       
   447 		handle = HandleL(aObject.DesC(CMTPObjectMetaData::ESuid));
       
   448 		if (handle != KMTPHandleNone)
       
   449 			{
       
   450 				//Leaves if id already exists in suid map table 
       
   451 			User::Leave(KErrAlreadyExists);
       
   452 			}
       
   453 		// dp is not enumerating, do a plain insert
       
   454 		needToInsert = ETrue;
       
   455 		}
       
   456 	if (needToInsert)//needToInsert and needUpdateOwner can't be true at same time
       
   457 		{
       
   458 		TUint32 parentHandle(aObject.Uint(CMTPObjectMetaData::EParentHandle));
       
   459 		handle = iHandleAllocator->NextIdL(dpId);
       
   460 		id = iHandleAllocator->NextPOUIDL();
       
   461 		aObject.SetUint(CMTPObjectMetaData::EHandle, handle);
       
   462 		aObject.SetUint(CMTPObjectMetaData::EIdentifier, id);
       
   463 		CleanupStack::PushL(TCleanupItem(CMTPObjectStore::DBUpdateFailRecover, &iBatched));
       
   464 		iBatched.InsertL();
       
   465 		iBatched.SetColL(EObjectStoreHandleId, handle);
       
   466 		iBatched.SetColL(EObjectStoreSUIDHash, suidHash);
       
   467 		DbColWriteStreamL(iBatched, EObjectStoreSUID, aObject.DesC(CMTPObjectMetaData::ESuid));
       
   468 		iBatched.SetColL(EObjectStoreDataProviderId, aObject.Uint(CMTPObjectMetaData::EDataProviderId));
       
   469 		iBatched.SetColL(EObjectStoreFormatCode, aObject.Uint(CMTPObjectMetaData::EFormatCode));
       
   470 		iBatched.SetColL(EObjectStoreFormatSubCode, aObject.Uint(CMTPObjectMetaData::EFormatSubCode));
       
   471 		iBatched.SetColL(EObjectStoreStorageId, aObject.Uint(CMTPObjectMetaData::EStorageId));
       
   472 		iBatched.SetColL(EObjectStoreModes, aObject.Uint(CMTPObjectMetaData::EModes));
       
   473 		iBatched.SetColL(EObjectStorePOUID, id);
       
   474 		iBatched.SetColL(EObjectStoreParentHandle, parentHandle);
       
   475 		iBatched.SetColL(EObjectStoreDPFlag, 1);
       
   476 		iBatched.SetColL(EObjectStoreNonConsumable, aObject.Uint(CMTPObjectMetaData::ENonConsumable));
       
   477 		iBatched.SetColL(EObjectStoreName, aObject.DesC(CMTPObjectMetaData::EName));
       
   478 		iBatched.PutL();
       
   479 		CleanupStack::Pop(&iBatched);
       
   480 		IncTranOpsNumL();
       
   481 		}
       
   482 	else if(needUpdateOwner)
       
   483 		{
       
   484 		if(iBatched.SeekL(static_cast<TUint>(handle)))
       
   485 			{
       
   486 			CleanupStack::PushL(TCleanupItem(CMTPObjectStore::DBUpdateFailRecover, &iBatched));
       
   487 			iBatched.UpdateL();
       
   488 			iBatched.SetColL(EObjectStoreDataProviderId, aObject.Uint(CMTPObjectMetaData::EDataProviderId));
       
   489 			iBatched.SetColL(EObjectStoreFormatCode, aObject.Uint(CMTPObjectMetaData::EFormatCode));
       
   490 			iBatched.SetColL(EObjectStoreFormatSubCode, aObject.Uint(CMTPObjectMetaData::EFormatSubCode));
       
   491 			iBatched.SetColL(EObjectStoreStorageId, aObject.Uint(CMTPObjectMetaData::EStorageId));
       
   492 			iBatched.SetColL(EObjectStoreModes, aObject.Uint(CMTPObjectMetaData::EModes));
       
   493 			iBatched.SetColL(EObjectStoreNonConsumable, aObject.Uint(CMTPObjectMetaData::ENonConsumable));
       
   494 			iBatched.SetColL(EObjectStoreName, aObject.DesC(CMTPObjectMetaData::EName));
       
   495 			iBatched.PutL();
       
   496 			CleanupStack::Pop(&iBatched);
       
   497 			IncTranOpsNumL();	
       
   498 			}
       
   499 		}
       
   500 	if ((needToInsert || needUpdateOwner) && IsMediaFormat(aObject.Uint(CMTPObjectMetaData::EFormatCode)))
       
   501 		{
       
   502 		if (iUpdateDeltaDataTable)
       
   503 			{
       
   504 			iMtpDeltaDataMgr->UpdateDeltaDataTableL(id, CMtpDeltaDataMgr::EAdded);
       
   505 			}
       
   506 		}
       
   507 
       
   508 	__FLOG(_L8("InsertObjectL - Exit"));
       
   509 	}
       
   510 
       
   511 void CMTPObjectStore::IncTranOpsNumL()
       
   512 	{
       
   513 	iTransactionOps++;
       
   514 	if (iTransactionOps % iMaxCommitLimit == 0)
       
   515 		{
       
   516 		CommitTransactionL();
       
   517 		if (iTransactionOps % iMaxCompactLimit == 0)
       
   518 			{
       
   519 			User::LeaveIfError(iDatabase.Compact());
       
   520 			}
       
   521 		BeginTransactionL();
       
   522 		}
       
   523 	}
       
   524 
       
   525 void CMTPObjectStore::BeginTransactionL()
       
   526 	{
       
   527 	if (!iDatabase.InTransaction())
       
   528 		{
       
   529 		User::LeaveIfError(iDatabase.Begin());
       
   530 		}
       
   531 	}
       
   532 
       
   533 void CMTPObjectStore::CommitTransactionL()
       
   534 	{
       
   535 	if (iDatabase.InTransaction())
       
   536 		{
       
   537 		User::LeaveIfError(iDatabase.Commit());
       
   538 		}
       
   539 	}
       
   540 
       
   541 void CMTPObjectStore::InsertObjectsL(RPointerArray<CMTPObjectMetaData>& aObjects)
       
   542 	{
       
   543 	TInt count = aObjects.Count();
       
   544 	for (TInt i = 0; i < count; i++)
       
   545 		{
       
   546 		InsertObjectL(*aObjects[i]);
       
   547 		}
       
   548 	}
       
   549 
       
   550 void CMTPObjectStore::ModifyObjectL(const CMTPObjectMetaData& aObject)
       
   551 	{
       
   552 	TUint32 handle = aObject.Uint(CMTPObjectMetaData::EHandle);
       
   553 	TFileName suid;
       
   554 	suid.CopyLC(aObject.DesC(CMTPObjectMetaData::ESuid));
       
   555 	TUint32 suidHash = DefaultHash::Des16(suid);
       
   556 
       
   557 	if (LocateByHandleL(handle))
       
   558 		{
       
   559 		//After the PutL called the cursor's position is not well defined.
       
   560 		iCachedHandle = 0;
       
   561 		iCachedSuidHash = 0;
       
   562 		TInt64 id = iBatched.ColInt64(EObjectStorePOUID);
       
   563 		TUint32 suidHashOld = iBatched.ColUint32(EObjectStoreSUIDHash);
       
   564 		TUint32 parentOld = iBatched.ColUint32(EObjectStoreParentHandle);
       
   565 		CleanupStack::PushL(TCleanupItem(CMTPObjectStore::DBUpdateFailRecover, &iBatched));
       
   566 		iBatched.UpdateL();
       
   567 		if(suidHashOld != suidHash)
       
   568 			{//change on index column will impact the performace
       
   569 			iBatched.SetColL(EObjectStoreSUIDHash, suidHash);
       
   570 			}
       
   571 		if(parentOld != aObject.Uint(CMTPObjectMetaData::EParentHandle))
       
   572 			{//change on index column will impact the performace
       
   573 			iBatched.SetColL(EObjectStoreParentHandle, aObject.Uint(CMTPObjectMetaData::EParentHandle));
       
   574 			}
       
   575 
       
   576 		DbColWriteStreamL(iBatched, EObjectStoreSUID, aObject.DesC(CMTPObjectMetaData::ESuid));		
       
   577 		iBatched.SetColL(EObjectStoreDataProviderId, aObject.Uint(CMTPObjectMetaData::EDataProviderId));
       
   578 		iBatched.SetColL(EObjectStoreFormatCode, aObject.Uint(CMTPObjectMetaData::EFormatCode));
       
   579 		iBatched.SetColL(EObjectStoreFormatSubCode, aObject.Uint(CMTPObjectMetaData::EFormatSubCode));
       
   580 		iBatched.SetColL(EObjectStoreStorageId, aObject.Uint(CMTPObjectMetaData::EStorageId));
       
   581 		iBatched.SetColL(EObjectStoreModes, aObject.Uint(CMTPObjectMetaData::EModes));
       
   582 		iBatched.SetColL(EObjectStoreDPFlag, 1);
       
   583 		iBatched.SetColL(EObjectStoreNonConsumable, aObject.Uint(CMTPObjectMetaData::ENonConsumable));
       
   584 		iBatched.SetColL(EObjectStoreName, aObject.DesC(CMTPObjectMetaData::EName));
       
   585 		iBatched.PutL();
       
   586 		CleanupStack::Pop(&iBatched);
       
   587 		IncTranOpsNumL();
       
   588 		if (aObject.Uint(CMTPObjectMetaData::EObjectMetaDataUpdate) && IsMediaFormat(aObject.Uint(CMTPObjectMetaData::EFormatCode)))
       
   589 			{
       
   590 			if (iUpdateDeltaDataTable)
       
   591 				{
       
   592 				iMtpDeltaDataMgr->UpdateDeltaDataTableL(id, CMtpDeltaDataMgr::EModified);
       
   593 				}
       
   594 			}
       
   595 		}
       
   596 	else
       
   597 		{
       
   598 		User::Leave(KErrNotFound);
       
   599 		}
       
   600 	}
       
   601 
       
   602 TBool CMTPObjectStore::ObjectL(const TMTPTypeUint32& aHandle, CMTPObjectMetaData& aBuf) const
       
   603 	{
       
   604 	TUint32 handleId = aHandle.Value();
       
   605 	aBuf.SetUint(CMTPObjectMetaData::EHandle, handleId);
       
   606 	return GetObjectL(handleId, aBuf);
       
   607 	}
       
   608 
       
   609 TBool CMTPObjectStore::ObjectExistsL(const TUint32 aHandle)
       
   610 	{
       
   611 	return LocateByHandleL(aHandle, EFalse);
       
   612 	}
       
   613 
       
   614 
       
   615 void CMTPObjectStore::BuildObjectMetaDataL(CMTPObjectMetaData& aBuf, const RDbTable& aTable) const
       
   616 	{
       
   617 	aBuf.SetUint(CMTPObjectMetaData::EHandle, aTable.ColUint32(EObjectStoreHandleId));
       
   618 
       
   619 	TFileName suid;
       
   620     DbColReadStreamL(aTable, EObjectStoreSUID, suid);
       
   621     aBuf.SetDesCL(CMTPObjectMetaData::ESuid, suid);
       
   622 
       
   623 	aBuf.SetUint(CMTPObjectMetaData::EFormatCode, aTable.ColUint16(EObjectStoreFormatCode));
       
   624 	aBuf.SetUint(CMTPObjectMetaData::EFormatSubCode, aTable.ColUint16(EObjectStoreFormatSubCode));
       
   625 	aBuf.SetUint(CMTPObjectMetaData::EDataProviderId, aTable.ColUint8(EObjectStoreDataProviderId));
       
   626 	aBuf.SetUint(CMTPObjectMetaData::EParentHandle, aTable.ColUint32(EObjectStoreParentHandle));
       
   627 	aBuf.SetUint(CMTPObjectMetaData::EStorageId, aTable.ColUint32(EObjectStoreStorageId));
       
   628 	aBuf.SetUint(CMTPObjectMetaData::EModes, aTable.ColUint8(EObjectStoreModes));
       
   629 	aBuf.SetUint(CMTPObjectMetaData::EIdentifier, aTable.ColInt64(EObjectStorePOUID));
       
   630 	aBuf.SetUint(CMTPObjectMetaData::ENonConsumable, aTable.ColUint8(EObjectStoreNonConsumable));
       
   631 	aBuf.SetDesCL(CMTPObjectMetaData::EName, aTable.ColDes(EObjectStoreName));
       
   632 	}
       
   633 
       
   634 TBool CMTPObjectStore::ObjectL(const TDesC& aSuid, CMTPObjectMetaData& aBuf) const
       
   635 	{
       
   636 	if (LocateBySuidL(aSuid))
       
   637 		{
       
   638 		BuildObjectMetaDataL(aBuf, iBatched_SuidHashID);
       
   639 		return ETrue;
       
   640 		}
       
   641 	return EFalse;
       
   642 	}
       
   643 
       
   644 const TPtrC CMTPObjectStore::ObjectSuidL(TUint32 aHandle) const
       
   645 	{
       
   646 	//iBatched owns the memory of Suid ?
       
   647 	if (!LocateByHandleL(aHandle))
       
   648 		{
       
   649 		User::Leave(KErrNotFound);
       
   650 		}
       
   651     DbColReadStreamL(iBatched, EObjectStoreSUID, iSuidBuf);
       
   652 	return iSuidBuf;
       
   653 	}
       
   654 
       
   655 TMTPTypeUint128 CMTPObjectStore::PuidL(TUint32 aHandle)
       
   656 	{
       
   657 	if (!LocateByHandleL(aHandle))
       
   658 		{
       
   659 		User::Leave(KErrNotFound);
       
   660 		}
       
   661 	TUint64 highHalfPOUID = static_cast<TUint64> (iBatched.ColInt64(EObjectStorePOUID));
       
   662 	// We actually use the first 64 bits to represent the PUID. this will represent 2^64=16 G xG objects, it is reasonable 
       
   663 	//to assume the Phone, as a resource-constrained device, never will reach that number, therefore, we choose
       
   664 	//only 64 bit to represent the POUID Of the objects on phone.
       
   665 	TMTPTypeUint128 result;
       
   666 	result.Set(1, highHalfPOUID);	//for the ONB
       
   667 	return result;
       
   668 	}
       
   669 
       
   670 TMTPTypeUint128 CMTPObjectStore::PuidL(const TDesC& aSuid)
       
   671 	{
       
   672 	if (!LocateBySuidL(aSuid))
       
   673 		{
       
   674 		User::Leave(KErrNotFound);
       
   675 		}
       
   676 	TUint64 highHalfPOUID = static_cast<TUint64> (iBatched_SuidHashID.ColInt64(EObjectStorePOUID));
       
   677 	// We actually use the first 64 bits to represent the PUID. this will represent 2^64=16 G xG objects, it is reasonable 
       
   678 	//to assume the Phone, as a resource-constrained device, never will reach that number, therefore, we choose
       
   679 	//only 64 bit to represent the POUID Of the objects on phone.
       
   680 	TMTPTypeUint128 result;
       
   681 	result.Set(1, highHalfPOUID);	//for the ONB
       
   682 	return result;
       
   683 	}
       
   684 
       
   685 void CMTPObjectStore::RemoveObjectL(const TMTPTypeUint32& aHandle)
       
   686 	{
       
   687 	if (LocateByHandleL(aHandle.Value()))
       
   688 		{
       
   689 		if (iSingletons.DpController().EnumerateState() != CMTPDataProviderController::EEnumerated &&
       
   690 			IsMediaFormat(iBatched.ColUint16(EObjectStoreFormatCode)))
       
   691 			{
       
   692 			iMtpDeltaDataMgr->UpdateDeltaDataTableL(iBatched.ColInt64(EObjectStorePOUID), CMtpDeltaDataMgr::EDeleted);
       
   693 			}
       
   694 		iCachedSuidHash = 0;
       
   695 		iCachedHandle = 0;
       
   696 		iBatched.DeleteL();
       
   697 		IncTranOpsNumL();
       
   698 		}
       
   699 	}
       
   700 
       
   701 void CMTPObjectStore::RemoveObjectL(const TDesC& aSuid)
       
   702 	{
       
   703 	if(LocateBySuidL(aSuid))
       
   704 		{
       
   705 		if (iSingletons.DpController().EnumerateState() != CMTPDataProviderController::EEnumerated &&
       
   706 			IsMediaFormat(iBatched_SuidHashID.ColUint16(EObjectStoreFormatCode)))
       
   707 			{
       
   708 			iMtpDeltaDataMgr->UpdateDeltaDataTableL(iBatched_SuidHashID.ColInt64(EObjectStorePOUID), CMtpDeltaDataMgr::EDeleted);
       
   709 			}
       
   710 		iCachedSuidHash = 0;
       
   711 		iCachedHandle = 0;
       
   712 		iBatched_SuidHashID.DeleteL();
       
   713 		IncTranOpsNumL();
       
   714 		}
       
   715 	}
       
   716 
       
   717 void CMTPObjectStore::RemoveObjectsL(const CDesCArray& aSuids)
       
   718 	{
       
   719 	TUint i(aSuids.Count());
       
   720 	while (i--)
       
   721 		{
       
   722 		RemoveObjectL(aSuids[i]);
       
   723 		}
       
   724 	}
       
   725 
       
   726 void CMTPObjectStore::RemoveObjectsL(TUint aDataProviderId)
       
   727 	{
       
   728 	iCachedSuidHash = 0;
       
   729 	iCachedHandle = 0;
       
   730 	TMTPObjectMgrQueryParams params(KMTPStorageAll, 0, 0, aDataProviderId);
       
   731 	TDelAction action(*this, MTraverseAction::EAllDP);
       
   732 	TraverseL(params, action);
       
   733 	}
       
   734 
       
   735 void CMTPObjectStore::RemoveObjectsByStorageIdL(TUint32 aStorageId)
       
   736 	{
       
   737 	iCachedSuidHash = 0;
       
   738 	iCachedHandle = 0;
       
   739 	TMTPObjectMgrQueryParams params(aStorageId, 0, 0);
       
   740 	TDelAction action(*this);
       
   741 	TraverseL(params, action);
       
   742 	}
       
   743 
       
   744 void CMTPObjectStore::ReserveObjectHandleL(CMTPObjectMetaData& aObject, TUint64 /*aSpaceRequired*/)
       
   745 	{
       
   746 	const TUint dp(aObject.Uint(CMTPObjectMetaData::EDataProviderId));
       
   747 	const TUint32 id(iHandleAllocator->NextIdL(dp));
       
   748 	aObject.SetUint(CMTPObjectMetaData::EHandle, id);
       
   749 	}
       
   750 
       
   751 void CMTPObjectStore::UnreserveObjectHandleL(const CMTPObjectMetaData& /*aObjectInfo*/)
       
   752 	{
       
   753 
       
   754 	}
       
   755 
       
   756 /**
       
   757  Clean unloaded data provider contents from object store
       
   758  */
       
   759 void CMTPObjectStore::CleanL()
       
   760 	{
       
   761 	__FLOG(_L8("CleanL - Entry"));
       
   762 	Swi::RSisRegistrySession sisSession;
       
   763 	User::LeaveIfError(sisSession.Connect());
       
   764 	CleanupClosePushL(sisSession);
       
   765 
       
   766 	const RArray<TUint>& loadedDPIDs = iPkgIDStore->DPIDL();
       
   767 	RArray<TUint> unInstalledDpIDs;
       
   768 	CleanupClosePushL(unInstalledDpIDs);
       
   769 	for (TUint idx(0); (idx < loadedDPIDs.Count()); ++idx)
       
   770 		{
       
   771 		TUid pkgUid = TUid::Uid(iPkgIDStore->PKGIDL(idx));
       
   772 		if (!sisSession.IsInstalledL(pkgUid))
       
   773 			{
       
   774 			//DP is uninstalled, remove DP related data from database.
       
   775 			TUint thisID = loadedDPIDs[idx];
       
   776 			__FLOG_1(_L("Data provider[%d] is removed from device!"),thisID);
       
   777 			unInstalledDpIDs.AppendL(thisID);
       
   778 			}
       
   779 		}
       
   780 	for (TUint index = 0; index < unInstalledDpIDs.Count(); ++index)
       
   781 		{
       
   782 		RemoveObjectsL(unInstalledDpIDs[index]);
       
   783 		iPkgIDStore->RemoveL(unInstalledDpIDs[index]);
       
   784 		}
       
   785 	CleanupStack::PopAndDestroy(&unInstalledDpIDs);
       
   786 	CleanupStack::PopAndDestroy(&sisSession);
       
   787 	__FLOG(_L8("CleanL - Exit"));
       
   788 	}
       
   789 
       
   790 TUint CMTPObjectStore::ObjectOwnerId(const TMTPTypeUint32& aHandle) const
       
   791     {
       
   792     if (!LocateByHandleL(aHandle.Value()))
       
   793         {
       
   794         return 0xff;
       
   795         }
       
   796     return iBatched.ColUint32(EObjectStoreDataProviderId);
       
   797     }
       
   798 /**
       
   799  Standard c++ constructor
       
   800  */
       
   801 CMTPObjectStore::CMTPObjectStore()
       
   802 	{
       
   803 	}
       
   804 
       
   805 /**
       
   806  Second phase constructor.
       
   807  */
       
   808 void CMTPObjectStore::ConstructL()
       
   809 	{
       
   810 	__FLOG_OPEN(KMTPSubsystem, KComponent);
       
   811 	iMaxCommitLimit = KMaxLimitCommitInEnumeration;
       
   812 	iMaxCompactLimit = KMaxLimitCompactInEnumeration;
       
   813 	iSingletons.OpenL();
       
   814 	InitializeDbL();
       
   815 	iCompactor = CDbCompactor::NewL(&iDatabase);
       
   816 	iMtpDeltaDataMgr = CMtpDeltaDataMgr::NewL(iDatabase);
       
   817 	iReferenceMgr = CMTPReferenceMgr::NewL(*this);
       
   818 	iDPIDStore = CMTPDPIDStore::NewL(iDatabase);
       
   819 	iPkgIDStore = CMTPPkgIDStore::NewL(iDatabase);
       
   820 	iBatched.Open(iDatabase, KSQLHandleTableName, RDbRowSet::EUpdatable);
       
   821 	iBatched.SetIndex(KSQLHandleId);
       
   822 	iBatched_SuidHashID.Open(iDatabase, KSQLHandleTableName, RDbRowSet::EUpdatable);
       
   823 	iBatched_SuidHashID.SetIndex(KSQLSuidHash);
       
   824 	iHandleAllocator = CMTPHandleAllocator::NewL(*this);
       
   825 	iSentinal = CEnumertingCacheItem::NewL(0, 0, 0, 0, 0);
       
   826 	BeginTransactionL();
       
   827 	}
       
   828 
       
   829 /**
       
   830  Initialises the database, it creates the table and index if the database does not exist, otherwise,
       
   831  it open the existing table and index
       
   832  */
       
   833 void CMTPObjectStore::InitializeDbL()
       
   834 	{
       
   835 	TFileName fullName;
       
   836 	GetFullPathName(KMTPNoBackupFolderName, fullName);
       
   837 	BaflUtils::EnsurePathExistsL(iSingletons.Fs(), fullName);
       
   838 	fullName.Append(KMTPBackSlash);
       
   839 	fullName.Append(KMTPHandleObjectDbName);
       
   840 	TInt err = KErrNone;
       
   841 	if (!BaflUtils::FileExists(iSingletons.Fs(), fullName))
       
   842 		{
       
   843 		CreateDbL(fullName);
       
   844 		}
       
   845 	else
       
   846 		{
       
   847 		err = OpenDb(fullName);
       
   848 		if (iDatabase.IsDamaged())
       
   849 			{
       
   850 			err = iDatabase.Recover();
       
   851 			}
       
   852 		}
       
   853 	
       
   854 	if (err != KErrNone)
       
   855 		{
       
   856 		CloseDb();
       
   857 		CreateDbL(fullName);
       
   858 		}
       
   859 	}
       
   860 
       
   861 /**
       
   862  Create the database with the specified database name
       
   863  @param aFileName    The name of the database to create
       
   864  */
       
   865 void CMTPObjectStore::CreateDbL(const TDesC& aFileName)
       
   866 	{
       
   867 	BaflUtils::EnsurePathExistsL(iSingletons.Fs(), aFileName);
       
   868 
       
   869 	User::LeaveIfError(iDatabase.Replace(iSingletons.Fs(), aFileName, KMTPFormat));
       
   870 	// Create table and index
       
   871 	CreateHandleTableL();
       
   872 	CreateHandleIndexL();
       
   873 	//This is the very very 1st time of MTP server running, therefore, all of the objects in the HandleStore should be added items
       
   874 	//roundtrip table will fetch the added items directly from the handlestore, do not popluate the added items to round-trip table
       
   875 	//until the enumeration is finished.
       
   876 	iUpdateDeltaDataTable = EFalse;
       
   877 	}
       
   878 
       
   879 /**
       
   880  Open the database with the specified database name
       
   881  @param aFileName    The name of the database to open
       
   882  */
       
   883 TInt CMTPObjectStore::OpenDb(const TDesC& aFileName)
       
   884 	{
       
   885 	TInt err = iDatabase.Open(iSingletons.Fs(), aFileName, KMTPFormat);
       
   886 	if(KErrNone == err)
       
   887 		{
       
   888 		TRAP(err,
       
   889 			CreateHandleTableL();
       
   890 			CreateHandleIndexL();
       
   891 			)
       
   892 		}
       
   893 	iUpdateDeltaDataTable = ETrue;
       
   894 	return err;
       
   895 	}
       
   896 
       
   897 /**
       
   898  Close the current opened database
       
   899  */
       
   900 void CMTPObjectStore::CloseDb()
       
   901 	{
       
   902 	iDatabase.Close();
       
   903 	}
       
   904 
       
   905 /**
       
   906  Create the table for storing the mapping from object handle to other properties (data provider id, storage id, formatcode, etc.)
       
   907  */
       
   908 void CMTPObjectStore::CreateHandleTableL()
       
   909 	{
       
   910 	if (!DBUtility::IsTableExistsL(iDatabase, KSQLHandleTableName))
       
   911 		{
       
   912 		User::LeaveIfError(iDatabase.Execute(KSQLCreateHandleTableText));
       
   913 		}
       
   914 	}
       
   915 
       
   916 /**
       
   917  Create three index on the table: 1. Handle, 2. SuidHash, 3. ParentHandle
       
   918  */
       
   919 void CMTPObjectStore::CreateHandleIndexL()
       
   920 	{
       
   921 	if (DBUtility::IsTableExistsL(iDatabase, KSQLHandleTableName))
       
   922 		{
       
   923 		if (!DBUtility::IsIndexExistsL(iDatabase, KSQLHandleTableName, KSQLHandleId))
       
   924 			{
       
   925 			User::LeaveIfError(iDatabase.Execute(KSQLCreateHandleIndexText));
       
   926 			}
       
   927 
       
   928 		if (!DBUtility::IsIndexExistsL(iDatabase, KSQLHandleTableName, KSQLSuidHash))
       
   929 			{
       
   930 			User::LeaveIfError(iDatabase.Execute(KSQLCreateSuidIndexText));
       
   931 			}
       
   932 
       
   933 		if (!DBUtility::IsIndexExistsL(iDatabase, KSQLHandleTableName, KSQLParentHandle))
       
   934 			{
       
   935 			User::LeaveIfError(iDatabase.Execute(KSQLCreateParentHandleText));
       
   936 			}
       
   937 		}
       
   938 	else
       
   939 		{
       
   940 		User::Leave(KErrNotFound);
       
   941 		}
       
   942 	}
       
   943 
       
   944 /**
       
   945  Get the full path of the database 
       
   946  @param aFileName    The file name of the database to be retrieved
       
   947  */
       
   948 void CMTPObjectStore::GetFullPathName(const TDesC& aName, TFileName& aFileName) const
       
   949 	{
       
   950 	iSingletons.Fs().PrivatePath(aFileName);
       
   951 	aFileName.Insert(0, KMTPDbDriveLocation);
       
   952 	aFileName.Append(aName);
       
   953 	}
       
   954 
       
   955 /**
       
   956  Initialize the handle allocator for this DP with the minimum object ID to use.
       
   957  This must not be called while an initiator has an open session or it could cause
       
   958  an object ID to be reused.
       
   959  @param aDataProviderId Data provider ID whose handle allocator must be initialized
       
   960  */
       
   961 void CMTPObjectStore::RestorePersistentObjectsL(TUint)
       
   962 	{
       
   963 
       
   964 	}
       
   965 
       
   966 TBool CMTPObjectStore::LocateByHandleL(const TUint aHandle, const TBool aReadTable /*default = ETrue*/) const
       
   967 	{
       
   968 	TBool result = EFalse;
       
   969 	if(IsInvalidHandle(aHandle))
       
   970 		{
       
   971 		return result;
       
   972 		}
       
   973 	
       
   974 	if (iCachedHandle == aHandle)
       
   975 		{
       
   976 		result = ETrue;
       
   977 		}
       
   978 	else
       
   979 		{
       
   980 		if (iBatched.SeekL(aHandle))
       
   981 			{
       
   982 			iCachedHandle = aHandle;
       
   983 			result = ETrue;
       
   984 			}
       
   985 		else
       
   986 			{
       
   987 			iCachedHandle = 0;
       
   988 			}
       
   989 		}
       
   990 	if (result && aReadTable)
       
   991 		{
       
   992 		iBatched.GetL();
       
   993 		}
       
   994 	return result;
       
   995 	}
       
   996 
       
   997 TBool CMTPObjectStore::LocateBySuidL(const TDesC& aSuid) const
       
   998 	{
       
   999 	TBool result = EFalse;
       
  1000 	TFileName suid;
       
  1001 	suid.CopyLC(aSuid);
       
  1002 	TUint32 suidHash = DefaultHash::Des16(suid);
       
  1003 	if (iCachedSuidHash == suidHash && iCachedSuidHash != 0) //the hash may generate 0 and we use 0 as a sentinel
       
  1004 		{
       
  1005 		iBatched_SuidHashID.GetL();
       
  1006 	    DbColReadStreamL(iBatched_SuidHashID, EObjectStoreSUID, suid);	    
       
  1007 		if (suid.CompareF(aSuid) == 0 )
       
  1008 			{
       
  1009 			result = ETrue;
       
  1010 			}
       
  1011 		}
       
  1012 	if (!result)
       
  1013 		{
       
  1014 		if (iBatched_SuidHashID.SeekL(static_cast<TUint> (suidHash)))
       
  1015 			{//found, but there might be multiple entries since SUIDhash might possible conflict.
       
  1016 			while (!iBatched_SuidHashID.AtEnd())
       
  1017 				{
       
  1018 				iBatched_SuidHashID.GetL();
       
  1019 		        DbColReadStreamL(iBatched_SuidHashID, EObjectStoreSUID, suid);				
       
  1020 				if (suid.CompareF(aSuid) == 0)
       
  1021 					{
       
  1022 					result = ETrue;
       
  1023 					iCachedSuidHash = suidHash;
       
  1024 					break;
       
  1025 					}
       
  1026 				else if (iBatched_SuidHashID.ColUint32(EObjectStoreSUIDHash) == suidHash)
       
  1027 					{
       
  1028 					iBatched_SuidHashID.NextL();
       
  1029 					}
       
  1030 				else
       
  1031 					{
       
  1032 					iCachedSuidHash = 0;
       
  1033 					break;//Not found
       
  1034 					}
       
  1035 				}
       
  1036 			}
       
  1037 		else
       
  1038 			{
       
  1039 			iCachedSuidHash = 0;
       
  1040 			}
       
  1041 		}
       
  1042 	return result;
       
  1043 	}
       
  1044 
       
  1045 /**
       
  1046  Get an object for the current query
       
  1047  @param aBuf if found, contains the pointer to the created object info,
       
  1048  @return ETrue if the object is found, otherwise, EFalse
       
  1049  */
       
  1050 
       
  1051 TBool CMTPObjectStore::GetObjectL(TUint32 aHandle, CMTPObjectMetaData& aObject) const
       
  1052 	{
       
  1053 	if (LocateByHandleL(aHandle))
       
  1054 		{
       
  1055 		BuildObjectMetaDataL(aObject, iBatched);
       
  1056 		return ETrue;
       
  1057 		}
       
  1058 	return EFalse;
       
  1059 	}
       
  1060 
       
  1061 /**
       
  1062  Determine if the object is of WMP supported media format
       
  1063  @param aObject the object meta data
       
  1064  @return ETrue if it is of WMP supported media format. EFalse otherwise.
       
  1065  */
       
  1066 TBool CMTPObjectStore::IsMediaFormat(TUint32 aFormatCode)
       
  1067 	{
       
  1068 	switch (aFormatCode)
       
  1069 		{
       
  1070 		//case EMTPFormatCodeUndefined:
       
  1071 		//case EMTPFormatCodeAssociation:
       
  1072 		case EMTPFormatCodeAIFF:
       
  1073 		case EMTPFormatCodeWAV:
       
  1074 		case EMTPFormatCodeMP3:
       
  1075 		case EMTPFormatCodeAVI:
       
  1076 		case EMTPFormatCodeMPEG:
       
  1077 		case EMTPFormatCodeASF:
       
  1078 		case EMTPFormatCodeEXIFJPEG:
       
  1079 		case EMTPFormatCodeTIFFEP:
       
  1080 		case EMTPFormatCodeFlashPix:
       
  1081 		case EMTPFormatCodeBMP:
       
  1082 		case EMTPFormatCodeCIFF:
       
  1083 		case EMTPFormatCodeGIF:
       
  1084 		case EMTPFormatCodeJFIF:
       
  1085 		case EMTPFormatCodeCD:
       
  1086 		case EMTPFormatCodePICT:
       
  1087 		case EMTPFormatCodePNG:
       
  1088 		case EMTPFormatCodeTIFF:
       
  1089 		case EMTPFormatCodeTIFFIT:
       
  1090 		case EMTPFormatCodeJP2:
       
  1091 		case EMTPFormatCodeJPX:
       
  1092 		case EMTPFormatCodeUndefinedFirmware:
       
  1093 		case EMTPFormatCodeWindowsImageFormat:
       
  1094 		case EMTPFormatCodeUndefinedAudio:
       
  1095 		case EMTPFormatCodeWMA:
       
  1096 		case EMTPFormatCodeOGG:
       
  1097 		case EMTPFormatCodeAAC:
       
  1098 		case EMTPFormatCodeAudible:
       
  1099 		case EMTPFormatCodeWMV:
       
  1100 		case EMTPFormatCodeMP4Container:
       
  1101 		case EMTPFormatCodeMP2:
       
  1102 		case EMTPFormatCode3GPContainer:
       
  1103 		case EMTPFormatCodeAbstractMultimediaAlbum:
       
  1104 		case EMTPFormatCodeAbstractImageAlbum:
       
  1105 		case EMTPFormatCodeAbstractAudioAlbum:
       
  1106 		case EMTPFormatCodeAbstractVideoAlbum:
       
  1107 		case EMTPFormatCodeAbstractAudioVideoPlaylist:
       
  1108 		case EMTPFormatCodeAbstractAudioPlaylist:
       
  1109 		case EMTPFormatCodeAbstractVideoPlaylist:
       
  1110 		case EMTPFormatCodeWPLPlaylist:
       
  1111 		case EMTPFormatCodeM3UPlaylist:
       
  1112 		case EMTPFormatCodeMPLPlaylist:
       
  1113 		case EMTPFormatCodeASXPlaylist:
       
  1114 		case EMTPFormatCodePLSPlaylist:
       
  1115 			return ETrue;
       
  1116 
       
  1117 		default:
       
  1118 			return EFalse;
       
  1119 		}
       
  1120 	}
       
  1121 
       
  1122 void CMTPObjectStore::CalcFreeHandlesL(TUint aDataProviderId)
       
  1123 	{
       
  1124 	TMTPTypeObjectHandle handleType(0, aDataProviderId);
       
  1125 	TUint32 minHandleForDP = handleType.Value();
       
  1126 	iCachedSuidHash = 0;
       
  1127 	iCachedHandle = 0;
       
  1128 	TUint32 preHandle = minHandleForDP, curHandle = 0;
       
  1129 	if (iBatched.SeekL((TUint) minHandleForDP, RDbTable::ELessThan))
       
  1130 		{
       
  1131 		iBatched.NextL();
       
  1132 		while (!iBatched.AtEnd())
       
  1133 			{
       
  1134 			iBatched.GetL();
       
  1135 			curHandle = iBatched.ColUint32(EObjectStoreHandleId);
       
  1136 			TMTPTypeObjectHandle handleType(curHandle);
       
  1137 			if (handleType.DpId() == aDataProviderId)
       
  1138 				{
       
  1139 				if(++ preHandle < curHandle)//base on the handle is allocated continuously
       
  1140 					{
       
  1141 					if(!iHandleAllocator->AppendHandleBlockL(aDataProviderId, preHandle, curHandle - preHandle))
       
  1142 						{
       
  1143 						break;
       
  1144 						}
       
  1145 					preHandle = curHandle;
       
  1146 					}
       
  1147 				iBatched.NextL();
       
  1148 				}
       
  1149 			else
       
  1150 				{
       
  1151 				//Has gone over the current DPid, break;
       
  1152 				break;
       
  1153 				}
       
  1154 			}
       
  1155 		}
       
  1156 	}
       
  1157 
       
  1158 void CMTPObjectStore::EstablishDBSnapshotL(TUint32 aStorageId)
       
  1159 	{
       
  1160 	//Currently, i only do this for File DP since it is non-persistent, later, if we take the proposal that 
       
  1161 	//1. FileDP is the last DP to be enumerated.
       
  1162 	//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
       
  1163 	// in the object store after all other DP finish its enumeration.
       
  1164 	//3. Then notify the related DP about the newly added objects by notification API;
       
  1165 	//_LIT(KInsert, "CMTPObjectStore::EstablishDBSnapshotL");
       
  1166 	//volatile TTimer t(KInsert);
       
  1167 	RDbTable temp;
       
  1168 	CleanupClosePushL(temp);
       
  1169 	temp.Open(iDatabase, KSQLHandleTableName, RDbRowSet::EUpdatable);
       
  1170     if(!iCacheExist)
       
  1171         {
       
  1172 	TInt32 count = temp.CountL(RDbRowSet::EQuick);
       
  1173         iEnumeratingCacheObjList.ReserveL(count);
       
  1174         }
       
  1175 	temp.FirstL();
       
  1176 	while (!temp.AtEnd())
       
  1177 		{
       
  1178 		temp.GetL();
       
  1179         if (temp.ColUint8(EObjectStoreDPFlag) == 1 && (KMTPStorageAll == aStorageId || temp.ColUint32(EObjectStoreStorageId) == aStorageId))
       
  1180 			{
       
  1181 			TUint32 handleID = temp.ColUint32(EObjectStoreHandleId);
       
  1182 			TInt64 pUID = temp.ColInt64(EObjectStorePOUID);
       
  1183 			iHandleAllocator->SetIdL(handleID, pUID);
       
  1184 			CEnumertingCacheItem* item = CEnumertingCacheItem::NewLC(
       
  1185 					temp.ColUint32(EObjectStoreSUIDHash), handleID,
       
  1186 					temp.ColUint16(EObjectStoreFormatCode), pUID, temp.ColUint8(EObjectStoreDataProviderId));
       
  1187 			TInt result = iEnumeratingCacheObjList.InsertInOrder(item, TLinearOrder<CEnumertingCacheItem>(CEnumertingCacheItem::Compare));
       
  1188 			if (KErrAlreadyExists == result) //hash collision
       
  1189 				{
       
  1190 				TInt found = iEnumeratingCacheObjList.FindInOrder(item, TLinearOrder<CEnumertingCacheItem>(CEnumertingCacheItem::Compare));
       
  1191 				CEnumertingCacheItem* colliItem = iEnumeratingCacheObjList[found];
       
  1192                 TFileName suid;
       
  1193 				if (colliItem->iSuid == NULL)
       
  1194 					{
       
  1195 					if (!LocateByHandleL(colliItem->iObjHandleId))
       
  1196 					    {
       
  1197 					    DbColReadStreamL(iBatched, EObjectStoreSUID, suid);
       
  1198 					    
       
  1199 					    colliItem->iSuid = suid.AllocL();
       
  1200 					    
       
  1201 					    colliItem->iSuidPtr.Set(*colliItem->iSuid);
       
  1202 					    }
       
  1203 					}
       
  1204                 DbColReadStreamL(temp, EObjectStoreSUID, suid);
       
  1205 				
       
  1206                 item->iSuid = suid.AllocL();
       
  1207                 
       
  1208 				item->iSuidPtr.Set(*item->iSuid);
       
  1209                 result = iEnumeratingCacheObjList.InsertInOrder(item, TLinearOrder<CEnumertingCacheItem>(CEnumertingCacheItem::Compare));
       
  1210 				}
       
  1211             if(result != KErrAlreadyExists)
       
  1212 				{
       
  1213 				User::LeaveIfError(result);
       
  1214 				}
       
  1215 			CleanupStack::Pop(item);
       
  1216 			}
       
  1217 		temp.NextL();
       
  1218 		}
       
  1219 	CleanupStack::PopAndDestroy(&temp);
       
  1220 	iCacheExist = ETrue;
       
  1221 	}
       
  1222 
       
  1223 void CMTPObjectStore::CleanDBSnapshotL()
       
  1224 	{
       
  1225 	//For those items left in the iEnumeratingCacheObjList, remove the object entry if the DPID of the handle is not persistent. and populate the 
       
  1226 	//roundtrip table if needed.
       
  1227 	//and then close the iEnumeratingCacheObjList to release the memory.
       
  1228 	//_LIT(KInsert, "CMTPObjectStore::CleanDBSnapshot");
       
  1229 	//volatile TTimer t(KInsert);
       
  1230 	if(iCacheExist)
       
  1231 	    {
       
  1232 	        iCacheExist = EFalse;
       
  1233 	    }
       
  1234 	else 
       
  1235 	    return;
       
  1236 
       
  1237 	for (TInt i = iEnumeratingCacheObjList.Count() - 1; i >= 0; i--)
       
  1238 		{
       
  1239 		TInt rc = iNonPersistentDPList.FindInOrder(iEnumeratingCacheObjList[i]->iDpID);
       
  1240 		if (rc != KErrNotFound)
       
  1241 			{//This is a non persistent DP.
       
  1242 			RemoveObjectL(iEnumeratingCacheObjList[i]->iObjHandleId);
       
  1243 			}
       
  1244 		}
       
  1245 	iNonPersistentDPList.Close();
       
  1246 	iEnumeratingCacheObjList.ResetAndDestroy();
       
  1247 	iUpdateDeltaDataTable = ETrue;
       
  1248 	iMaxCommitLimit = KMaxLimitCommitAfterEnumeration;
       
  1249 	iMaxCompactLimit = KMaxLimitCompactAfterEnumeration;
       
  1250     CommitTransactionL();
       
  1251     User::LeaveIfError(iDatabase.Compact());
       
  1252     BeginTransactionL();
       
  1253 	}
       
  1254 
       
  1255 CMTPObjectStore::CEnumertingCacheItem::CEnumertingCacheItem(TUint32 aSuidHash, TUint32 aHandle, TUint32 aFormat, TUint64 aId, TUint8 aDpID)
       
  1256 	{
       
  1257 	iObjSuiIdHash = aSuidHash;
       
  1258 	iObjHandleId = aHandle;
       
  1259 	iFormatcode = aFormat;
       
  1260 	iPOUID = aId;
       
  1261 	iDpID = aDpID;
       
  1262 	}
       
  1263 
       
  1264 TInt CMTPObjectStore::CEnumertingCacheItem::Compare(const CEnumertingCacheItem& aFirst, const CEnumertingCacheItem& aSecond)
       
  1265 	{
       
  1266 	if (aFirst.iObjSuiIdHash > aSecond.iObjSuiIdHash)
       
  1267 		{
       
  1268 		return 1;
       
  1269 		}
       
  1270 	else if (aFirst.iObjSuiIdHash < aSecond.iObjSuiIdHash)
       
  1271 		{
       
  1272 		return -1;
       
  1273 		}
       
  1274 	if ((aFirst.iSuidPtr.Length() != 0) && (aSecond.iSuidPtr.Length() != 0))
       
  1275 		{
       
  1276 		return aFirst.iSuidPtr.CompareF(aSecond.iSuidPtr);
       
  1277 		}
       
  1278 	return 0;
       
  1279 	}
       
  1280 
       
  1281 TBool CMTPObjectStore::IsInvalidHandle( TUint32 aHandle ) const
       
  1282 	{
       
  1283 	return ( (KMTPHandleAll == aHandle) || (KMTPHandleNone == aHandle) );
       
  1284 	}
       
  1285 
       
  1286 void CMTPObjectStore::DbColWriteStreamL(RDbTable& aTable, TDbColNo aCol, const TDesC16& aDes)
       
  1287     {
       
  1288     RDbColWriteStream suid;
       
  1289     suid.OpenLC(aTable, aCol);
       
  1290     suid.WriteL(aDes);
       
  1291     suid.Close();
       
  1292     CleanupStack::PopAndDestroy(); // suid
       
  1293     }
       
  1294 
       
  1295 void CMTPObjectStore::DbColReadStreamL(const RDbTable& aTable, TDbColNo aCol, TDes16& aDes) const
       
  1296     {
       
  1297     RDbColReadStream suid;
       
  1298     suid.OpenLC(aTable, aCol);
       
  1299     suid.ReadL(aDes, aTable.ColLength(aCol));
       
  1300     suid.Close();
       
  1301     CleanupStack::PopAndDestroy(); // suid
       
  1302     }