14 * Description: Implement the operation: DeleteObject |
14 * Description: Implement the operation: DeleteObject |
15 * |
15 * |
16 */ |
16 */ |
17 |
17 |
18 |
18 |
19 #include <mtp/mmtpdataproviderframework.h> |
|
20 #include <mtp/mmtpobjectmgr.h> |
19 #include <mtp/mmtpobjectmgr.h> |
21 #include <mtp/cmtpobjectmetadata.h> |
20 #include <mtp/mmtpreferencemgr.h> |
22 |
21 |
23 #include "cdeleteobject.h" |
22 #include "cdeleteobject.h" |
24 #include "mmmtpdplogger.h" |
23 #include "mmmtpdplogger.h" |
25 #include "mmmtpdpconfig.h" |
24 #include "mmmtpdpconfig.h" |
26 #include "cmmmtpdpmetadataaccesswrapper.h" |
25 #include "cmmmtpdpmetadataaccesswrapper.h" |
27 |
26 #include "mmmtpdputility.h" |
28 // static const TInt KMTPDriveGranularity = 5; |
27 |
|
28 const TInt KMaxDeletionTimes = 10; |
|
29 const TInt KDeletionThreshold = 100 * 1000; // (100 millisec) |
29 |
30 |
30 // ----------------------------------------------------------------------------- |
31 // ----------------------------------------------------------------------------- |
31 // Verification data for the DeleteObject request |
32 // Verification data for the DeleteObject request |
32 // ----------------------------------------------------------------------------- |
33 // ----------------------------------------------------------------------------- |
33 // |
34 // |
87 MMmMtpDpConfig& aDpConfig ) : |
88 MMmMtpDpConfig& aDpConfig ) : |
88 CRequestProcessor( aFramework, |
89 CRequestProcessor( aFramework, |
89 aConnection, |
90 aConnection, |
90 sizeof( KMTPDeleteObjectPolicy ) / sizeof( TMTPRequestElementInfo ), |
91 sizeof( KMTPDeleteObjectPolicy ) / sizeof( TMTPRequestElementInfo ), |
91 KMTPDeleteObjectPolicy ), |
92 KMTPDeleteObjectPolicy ), |
92 iObjectMgr( aFramework.ObjectMgr() ), |
93 iObjectsToDelete( KMmMtpRArrayGranularity ), |
93 iFs( aFramework.Fs() ), |
|
94 iObjectsToDelete( KMmMtpRArrayGranularity ), |
|
95 iDeleteError( KErrNone ), |
94 iDeleteError( KErrNone ), |
96 iDpConfig( aDpConfig ) |
95 iDpConfig( aDpConfig ) |
97 { |
96 { |
98 PRINT( _L( "Operation: DeleteObject(0x100B)" ) ); |
97 PRINT( _L( "Operation: DeleteObject(0x100B)" ) ); |
99 } |
98 } |
189 { |
188 { |
190 // Get the next object |
189 // Get the next object |
191 CMTPObjectMetaData* objectInfo = CMTPObjectMetaData::NewLC(); // + objectInfo |
190 CMTPObjectMetaData* objectInfo = CMTPObjectMetaData::NewLC(); // + objectInfo |
192 |
191 |
193 TUint32 handle = iObjectsToDelete[0]; |
192 TUint32 handle = iObjectsToDelete[0]; |
194 iObjectMgr.ObjectL( handle, *objectInfo ); |
193 iFramework.ObjectMgr().ObjectL( handle, *objectInfo ); |
195 TFileName fileName( objectInfo->DesC( CMTPObjectMetaData::ESuid ) ); |
194 TFileName fileName( objectInfo->DesC( CMTPObjectMetaData::ESuid ) ); |
196 PRINT2( _L( "MM MTP <> CDeleteObject::RunL delete object handle is 0x%x, fileName is %S" ), handle, &fileName ); |
195 PRINT2( _L( "MM MTP <> CDeleteObject::RunL delete object handle is 0x%x, fileName is %S" ), handle, &fileName ); |
197 |
196 |
198 if ( objectInfo->Uint( CMTPObjectMetaData::EFormatCode ) == EMTPFormatCodeAssociation ) |
197 if ( objectInfo->Uint( CMTPObjectMetaData::EFormatCode ) == EMTPFormatCodeAssociation ) |
199 { |
198 { |
223 void CDeleteObject::DeleteObjectL( const CMTPObjectMetaData& aObjectInfo ) |
222 void CDeleteObject::DeleteObjectL( const CMTPObjectMetaData& aObjectInfo ) |
224 { |
223 { |
225 TFileName fileName( aObjectInfo.DesC( CMTPObjectMetaData::ESuid ) ); |
224 TFileName fileName( aObjectInfo.DesC( CMTPObjectMetaData::ESuid ) ); |
226 PRINT1( _L( "MM MTP <> CDeleteObject::DeleteObjectL fileName = %S" ), &fileName ); |
225 PRINT1( _L( "MM MTP <> CDeleteObject::DeleteObjectL fileName = %S" ), &fileName ); |
227 |
226 |
228 TParsePtrC parse( fileName ); |
227 iDpConfig.GetWrapperL().SetStorageRootL( fileName ); |
229 iDpConfig.GetWrapperL().SetStorageRootL( parse.Drive() ); |
|
230 |
228 |
231 // To capture special situation: After copy, move, rename playlist folder name, |
229 // To capture special situation: After copy, move, rename playlist folder name, |
232 // record in MPX is not inlined with framework db, playlist should not be deleted |
230 // record in MPX is not inlined with framework db, playlist should not be deleted |
233 // until next session. |
231 // until next session. |
234 // This is used to keep the same behavior in mass storage and device file manager. |
232 // This is used to keep the same behavior in mass storage and device file manager. |
235 if ( aObjectInfo.Uint(CMTPObjectMetaData::EFormatCode ) |
233 if ( aObjectInfo.Uint( CMTPObjectMetaData::EFormatCode ) |
236 == EMTPFormatCodeAbstractAudioVideoPlaylist |
234 == EMTPFormatCodeAbstractAudioVideoPlaylist |
237 && !iDpConfig.GetWrapperL().IsExistL( fileName ) ) |
235 && !iDpConfig.GetWrapperL().IsExistL( fileName ) ) |
238 { |
236 { |
239 iDeleteError = KErrGeneral; |
237 iDeleteError = KErrGeneral; |
240 PRINT( _L( "MM MTP <= CDeleteObject::DeleteObjectL playlist file not exist in the MPX DB" ) ); |
238 PRINT( _L( "MM MTP <= CDeleteObject::DeleteObjectL playlist file not exist in the MPX DB" ) ); |
241 return; |
239 return; |
242 } |
240 } |
243 |
241 |
244 // 1. Delete object from file system |
242 // 1. Delete object from file system |
245 TEntry fileInfo; |
243 TEntry fileInfo; |
246 iFs.Entry( fileName, fileInfo ); |
244 iFramework.Fs().Entry( fileName, fileInfo ); |
247 if ( fileInfo.IsReadOnly() ) |
245 if ( fileInfo.IsReadOnly() ) |
248 { |
246 { |
249 iDeleteError = KErrAccessDenied; |
247 iDeleteError = KErrAccessDenied; |
250 PRINT1( _L( "MM MTP <= CDeleteObject::DeleteObjectL, \"%S\" is a read-only file"), &fileName ); |
248 PRINT1( _L( "MM MTP <= CDeleteObject::DeleteObjectL, \"%S\" is a read-only file"), &fileName ); |
251 return; |
249 return; |
252 } |
250 } |
253 iDeleteError = iFs.Delete( fileName ); |
251 // Some other component might be holding on to the file (MDS background harvesting), |
254 if ( iDeleteError != KErrNone && iDeleteError != KErrNotFound ) |
252 // try again after 100 millisec, up to 10 times, before give up |
255 { |
253 TInt count = KMaxDeletionTimes; |
256 PRINT1( _L( "MM MTP <= CDeleteObject::DeleteObjectL, Delete from file system failed, err = %d" ), iDeleteError ); |
254 while ( count > 0 ) |
257 return; |
255 { |
|
256 iDeleteError = iFramework.Fs().Delete( fileName ); |
|
257 if ( iDeleteError == KErrNone || iDeleteError == KErrNotFound ) |
|
258 { |
|
259 break; |
|
260 } |
|
261 else if ( ( iDeleteError == KErrInUse ) && ( count > 1 ) ) |
|
262 { |
|
263 User::After( KDeletionThreshold ); |
|
264 count--; |
|
265 } |
|
266 else |
|
267 { |
|
268 PRINT1( _L( "MM MTP <= CDeleteObject::DeleteObjectL, Delete from file system failed, err = %d" ), iDeleteError ); |
|
269 return; |
|
270 } |
258 } |
271 } |
259 |
272 |
260 // 2. Delete object from metadata db |
273 // 2. Delete object from metadata db |
261 TRAP( iDeleteError, iDpConfig.GetWrapperL().DeleteObjectL( fileName, aObjectInfo.Uint( CMTPObjectMetaData::EFormatCode ) )); |
274 TRAP( iDeleteError, iDpConfig.GetWrapperL().DeleteObjectL( aObjectInfo ) ); |
262 PRINT1( _L( "MM MTP <> CDeleteObject::DeleteObjectL, Delete from Media DB, err = %d" ), iDeleteError ); |
275 PRINT1( _L( "MM MTP <> CDeleteObject::DeleteObjectL, Delete from Media DB, err = %d" ), iDeleteError ); |
263 |
276 |
264 // 3. Delete object from framework db |
277 // 3. Delete object from framework db |
265 iObjectMgr.RemoveObjectL( aObjectInfo.Uint( CMTPObjectMetaData::EHandle ) ); |
278 iFramework.ObjectMgr().RemoveObjectL( aObjectInfo.Uint( CMTPObjectMetaData::EHandle ) ); |
|
279 |
|
280 // 4. If the object has references, Delete references from reference manager |
|
281 if ( MmMtpDpUtility::HasReference( aObjectInfo.Uint( CMTPObjectMetaData::EFormatCode ) ) ) |
|
282 iFramework.ReferenceMgr().RemoveReferencesL( aObjectInfo.DesC( CMTPObjectMetaData::ESuid ) ); |
266 |
283 |
267 PRINT( _L( "MM MTP <= CDeleteObject::DeleteObjectL" ) ); |
284 PRINT( _L( "MM MTP <= CDeleteObject::DeleteObjectL" ) ); |
268 } |
285 } |
269 |
286 |
270 // ----------------------------------------------------------------------------- |
287 // ----------------------------------------------------------------------------- |
340 // else if ( iFramework.ObjectMgr().ObjectOwnerId( handles[i] ) == 0 ) // We know that the device dp id is always 0, otherwise the whole MTP won't work. |
357 // else if ( iFramework.ObjectMgr().ObjectOwnerId( handles[i] ) == 0 ) // We know that the device dp id is always 0, otherwise the whole MTP won't work. |
341 // iParentHandles.AppendL( handles[i] ); |
358 // iParentHandles.AppendL( handles[i] ); |
342 else |
359 else |
343 { |
360 { |
344 CMTPObjectMetaData* objectInfo = CMTPObjectMetaData::NewLC(); // + objectInfo |
361 CMTPObjectMetaData* objectInfo = CMTPObjectMetaData::NewLC(); // + objectInfo |
345 iObjectMgr.ObjectL( handles[i], *objectInfo ); |
362 iFramework.ObjectMgr().ObjectL( handles[i], *objectInfo ); |
346 if ( EMTPFormatCodeAssociation == objectInfo->Uint( CMTPObjectMetaData::EFormatCode ) ) |
363 if ( EMTPFormatCodeAssociation == objectInfo->Uint( CMTPObjectMetaData::EFormatCode ) ) |
347 { |
364 { |
348 GetObjectHandlesL( KMTPStorageAll, handles[i] ); |
365 GetObjectHandlesL( KMTPStorageAll, handles[i] ); |
349 } |
366 } |
350 CleanupStack::PopAndDestroy( objectInfo ); // - objectInfo |
367 CleanupStack::PopAndDestroy( objectInfo ); // - objectInfo |