mmappcomponents/mmmtpdataprovider/mmmtpdprequestprocessor/src/csendobject.cpp
changeset 32 edd273b3192a
parent 27 cbb1bfb7ebfb
child 35 2ee890d2f7e7
--- a/mmappcomponents/mmmtpdataprovider/mmmtpdprequestprocessor/src/csendobject.cpp	Fri May 14 16:21:14 2010 +0300
+++ b/mmappcomponents/mmmtpdataprovider/mmmtpdprequestprocessor/src/csendobject.cpp	Thu May 27 13:19:19 2010 +0300
@@ -32,6 +32,8 @@
 #include "cpropertysettingutility.h"
 #include "cmmmtpdpmetadataaccesswrapper.h"
 
+const TInt KMtpRollbackFuncCnt = 3;
+
 // Verification data for the SendObjectInfo request
 const TMTPRequestElementInfo KMTPSendObjectInfoPolicy[] =
     {
@@ -79,12 +81,8 @@
 //
 EXPORT_C CSendObject::~CSendObject()
     {
-    if ( !iNoRollback )
-        {
-        // Not finished SendObjectInfo \ SendObject pair detected.
-        Rollback();
-        PRINT( _L( "MM MTP <> CSendObject::~CSendObject, Rollback" ) );
-        }
+    Rollback();
+    iRollbackList.Close();
 
     delete iFileReceived;
     delete iParentSuid;
@@ -107,7 +105,8 @@
         CRequestProcessor( aFramework, aConnection, 0, NULL ),
         iFs( iFramework.Fs() ),
         iObjectMgr( iFramework.ObjectMgr() ),
-        iDpConfig( aDpConfig )
+        iDpConfig( aDpConfig ),
+        iRollbackList( KMtpRollbackFuncCnt )
     {
     PRINT( _L( "Operation: SendObjectInfo/SendObject/SendObjectPropList(0x100C/0x100D/0x9808)" ) );
     }
@@ -130,9 +129,7 @@
 
     PRINT1( _L( "MM MTP <> CSendObject::ConstructL DataProviderId = 0x%x" ), iFramework.DataProviderId());
 
-    iNoRollback = EFalse;
-
-    SetPSStatus();
+  
     PRINT( _L( "MM MTP <= CSendObject::ConstructL" ) );
     }
 
@@ -300,11 +297,6 @@
                 {
                 responseCode = EMTPRespCodeObjectTooLarge;
                 }
-
-            if ( ( responseCode != EMTPRespCodeOK ) && !CanStoreFileL( iStorageId, iObjectSize ) )
-                {
-                responseCode = EMTPRespCodeStoreFull;
-                }
             }
         }
 
@@ -332,6 +324,8 @@
 EXPORT_C void CSendObject::ServiceL()
     {
     PRINT( _L( "MM MTP => CSendObject::ServiceL" ) );
+    
+    MmMtpDpUtility::SetPSStatus(EMtpPSStatusActive);
 
     if ( iProgress == EObjectNone )
         {
@@ -392,22 +386,7 @@
 void CSendObject::ServiceObjectL()
     {
     PRINT( _L( "MM MTP => CSendObject::ServiceObjectL" ) );
-
-    delete iFileReceived;
-    iFileReceived = NULL;
-
-    PRINT2( _L( "MM MTP <> CSendObject::ServiceObjectL, iFullPath is %S, iObjectSize: %Lu" ), &iFullPath, iObjectSize );
-    TRAPD( err, iFileReceived = CMTPTypeFile::NewL( iFs,
-        iFullPath,
-        EFileWrite ) );
-
-    PRINT1( _L("MM MTP <> CSendObject::ServiceObjectL, Leave Code is: %d"), err );
-    User::LeaveIfError( err );
-
-    iFileReceived->SetSizeL( iObjectSize );
-
     ReceiveDataL( *iFileReceived );
-
     iProgress = ESendObjectInProgress;
 
     PRINT( _L( "MM MTP <= CSendObject::ServiceObjectL" ) );
@@ -479,12 +458,7 @@
     if ( IsTooLarge( iObjectSize ) )
         {
         SendResponseL( EMTPRespCodeObjectTooLarge );
-        result = EFalse;
-        }
-
-    if ( result && !CanStoreFileL( iStorageId, iObjectSize ) )
-        {
-        SendResponseL( EMTPRespCodeStoreFull );
+        Rollback();
         result = EFalse;
         }
 
@@ -496,6 +470,7 @@
             && iProtectionStatus != EMTPProtectionReadOnly )
             {
             SendResponseL( EMTPRespCodeParameterNotSupported );
+            Rollback();
             result = EFalse;
             }
         }
@@ -507,6 +482,7 @@
             {
             // File and/or parent pathname invalid.
             SendResponseL( EMTPRespCodeInvalidDataset );
+            Rollback();
             }
         }
 
@@ -514,16 +490,19 @@
         {
         if ( ExistsL( iFullPath ) )
             {
-            // Object with the same name already exists.
-            iNoRollback = ETrue;
             SendResponseL( EMTPRespCodeAccessDenied );
+            Rollback();
             result = EFalse;
             }
         }
 
     if ( result )
-        ReserveObjectL();
-
+        {
+        if ( KErrNone != ReserveObjectL() )
+            {
+            result = EFalse;
+            }
+        }
     PRINT1( _L( "MM MTP <= CSendObject::DoHandleResponsePhaseInfoL result = %d" ), result );
 
     return result;
@@ -542,6 +521,7 @@
 
     TInt invalidParameterIndex = KErrNotFound;
     responseCode = VerifyObjectPropListL( invalidParameterIndex );
+    TInt err = KErrNone;
 
     if ( responseCode != EMTPRespCodeOK )
         {
@@ -551,18 +531,18 @@
         parameters[2] = 0;
         parameters[3] = invalidParameterIndex;
         SendResponseL( responseCode, 4, parameters );
+        Rollback();
         }
     else if ( ExistsL( iFullPath ) )
         {
-        // Object with the same name already exists.
-        iNoRollback = ETrue;
         SendResponseL( EMTPRespCodeAccessDenied );
+        Rollback();
         }
     else
-        ReserveObjectL();
+        err = ReserveObjectL();
 
     PRINT( _L( "MM MTP <= CSendObject::DoHandleResponsePhasePropListL" ) );
-    return ( responseCode == EMTPRespCodeOK );
+    return ( responseCode == EMTPRespCodeOK && err == KErrNone);
     }
 
 // -----------------------------------------------------------------------------
@@ -576,60 +556,56 @@
 
     TBool result = ETrue;
 
+    TEntry fileEntry;
+    User::LeaveIfError( iFs.Entry( iFullPath, fileEntry ) );
+    if ( fileEntry.FileSize() != iObjectSize )
+        {
+        iFs.Delete( iFullPath );
+        iObjectMgr.UnreserveObjectHandleL( *iReceivedObjectInfo );
+        TMTPResponseCode responseCode = EMTPRespCodeObjectTooLarge;
+        if ( fileEntry.FileSize() < iObjectSize )
+            {
+            responseCode = EMTPRespCodeIncompleteTransfer;
+            }
+        SendResponseL( responseCode );
+        Rollback();
+        result = EFalse;
+        }
+
     // SendObject is cancelled or connection is dropped.
-    if ( iCancelled )
+    if ( result && iCancelled )
         {
-        // In SendObject response phase, unregister is not necessary.
-        // But there's no harm, still keep it here.
+        iFramework.RouteRequestUnregisterL( iExpectedSendObjectRequest,
+            iConnection );
+        SendResponseL( EMTPRespCodeTransactionCancelled );
+        Rollback();
+        }
+    else if ( result && !iCancelled )
+        {
+        if ( iObjectSize > 0 ) // media file
+            {
+            TRAPD( err, AddMediaToStoreL() );
+            PRINT1( _L( "MM MTP <= CSendObject::DoHandleResponsePhaseObjectL err = %d" ), err );
+
+            if ( ( iPreviousOperation == EMTPOpCodeSendObjectPropList )
+                && ( err == KErrNone ) )
+                {
+                // Only leave when getting proplist element from data received by fw.
+                // It should not happen after ReceiveDataL in which construction of proplist already succeed.
+                SetObjectPropListL();
+                }
+
+            // Commits into MTP data object enumeration store the object handle and
+            // storage space previously reserved for the specified object.
+            iFramework.ObjectMgr().CommitReservedObjectHandleL( *iReceivedObjectInfo );
+            iRollbackList.Append( &CSendObject::RemoveObjectFromDbL );
+            }
+
+        // Commit object to MTP data store
         iFramework.RouteRequestUnregisterL( iExpectedSendObjectRequest,
             iConnection );
 
-        Rollback();
-        SendResponseL( EMTPRespCodeTransactionCancelled );
-        }
-    else
-        {
-        TEntry fileEntry;
-        User::LeaveIfError( iFs.Entry( iFullPath, fileEntry ) );
-
-        if ( fileEntry.FileSize() != iObjectSize )
-            {
-            Rollback();
-            TMTPResponseCode responseCode = EMTPRespCodeObjectTooLarge;
-            if ( fileEntry.FileSize() < iObjectSize )
-                {
-                responseCode = EMTPRespCodeIncompleteTransfer;
-                }
-            SendResponseL( responseCode );
-            result = EFalse;
-            }
-        else
-            {
-            if ( iObjectSize > 0 ) // media file
-                {
-                TRAPD( err, AddMediaToStoreL() );
-                PRINT1( _L( "MM MTP <> CSendObject::DoHandleResponsePhaseObjectL err = %d" ), err );
-
-                if ( ( iPreviousOperation == EMTPOpCodeSendObjectPropList )
-                    && ( err == KErrNone ) )
-                    {
-                    // Only leave when getting proplist element from data received by fw.
-                    // It should not happen after ReceiveDataL in which construction of proplist already succeed.
-                    SetObjectPropListL();
-                    }
-
-                // Commits into MTP data object enumeration store the object handle and
-                // storage space previously reserved for the specified object.
-                iFramework.ObjectMgr().CommitReservedObjectHandleL( *iReceivedObjectInfo );
-                }
-
-            // In SendObject response phase, unregister is not necessary.
-            // But there's no harm, still keep it here.
-            iFramework.RouteRequestUnregisterL( iExpectedSendObjectRequest,
-                iConnection );
-
-            SendResponseL( EMTPRespCodeOK );
-            }
+        SendResponseL( EMTPRespCodeOK );
         }
 
     PRINT1( _L( "MM MTP <= CSendObject::DoHandleResponsePhaseObjectL result = %d" ), result );
@@ -661,6 +637,9 @@
         result = EFalse;
         }
 
+    if ( result )
+        iRollbackList.Reset();
+
     PRINT2( _L( "MM MTP <= CSendObject::DoHandleCompletingPhaseL iProgress= %d, result = %d" ),
         iProgress,
         result );
@@ -1042,31 +1021,6 @@
     return ret;
     }
 
-// -----------------------------------------------------------------------------
-// CSendObject::CanStoreFileL
-// Check if we can store the file on the storage
-// @return ETrue if yes, otherwise EFalse
-// -----------------------------------------------------------------------------
-//
-TBool CSendObject::CanStoreFileL( TUint32 aStorageId,
-    TInt64 aObjectSize ) const
-    {
-    PRINT( _L( "MM MTP => CSendObject::CanStoreFileL" ) );
-
-    TBool result = ETrue;
-    TVolumeInfo volumeInfo;
-    TInt driveNo = iFramework.StorageMgr().DriveNumber( aStorageId );
-    User::LeaveIfError( iFs.Volume( volumeInfo, driveNo ) );
-
-    if ( volumeInfo.iFree < aObjectSize )
-        {
-        result = EFalse;
-        }
-
-    PRINT1( _L( "MM MTP <= CSendObject::CanStoreFileL , result = %d" ), result );
-
-    return result;
-    }
 
 // -----------------------------------------------------------------------------
 // CSendObject::GetFullPathNameL
@@ -1171,7 +1125,7 @@
 // CSendObject::ReserveObjectL
 // -----------------------------------------------------------------------------
 //
-void CSendObject::ReserveObjectL()
+TInt CSendObject::ReserveObjectL()
     {
     PRINT( _L( "MM MTP => CSendObject::ReserveObjectL" ) );
     TInt err = KErrNone;
@@ -1187,15 +1141,42 @@
     // by the specified object information record.
     TRAP( err, iObjectMgr.ReserveObjectHandleL( *iReceivedObjectInfo,
         iObjectSize ) );
+    iRollbackList.Append( &CSendObject::UnreserveObjectL );
 
     PRINT2( _L( "MM MTP => CSendObject::ReserveObjectL iObjectsize = %Lu, Operation: 0x%x" ), iObjectSize, iOperationCode );
     if ( err != KErrNone )
-        PRINT1( _L( "MM MTP <> CSendObject::ReserveObjectL err = %d" ), err );
-    if ( iObjectSize == 0 )
+        {
+        PRINT1( _L( "MM MTP <> ReserveObjectHandleL err = %d" ), err );
+        }
+
+    if ( err == KErrNone )
+        {
+        delete iFileReceived;
+        iFileReceived = NULL;
+        PRINT2( _L( "MM MTP <> CSendObject::ServiceObjectL, iFullPath is %S, iObjectSize: %Lu" ), &iFullPath, iObjectSize );
+        iRollbackList.Append( &CSendObject::RemoveObjectFromFs );
+        TRAP( err, iFileReceived = CMTPTypeFile::NewL( iFs, iFullPath, EFileWrite ) );
+
+        PRINT1( _L("MM MTP <> CMTPTypeFile::NewL Leave Code is: %d"), err );
+        }
+
+    if ( err == KErrNone )
+        {
+        TRAP( err, iFileReceived->SetSizeL( iObjectSize ) );
+        PRINT1( _L( "MM MTP <> SetSizeL leave code:%d" ), err );
+        if ( err == KErrDiskFull )
+            {
+            SendResponseL( EMTPRespCodeStoreFull );
+            Rollback();
+            return err;
+            }
+        }
+
+    if ( err == KErrNone && iObjectSize == 0 )
         {
         // Already trapped inside SaveEmptyFileL.
         SaveEmptyFileL();
-        if( iOperationCode == EMTPOpCodeSendObjectPropList )
+        if ( iOperationCode == EMTPOpCodeSendObjectPropList )
             {
             // Only leave when getting proplist element from data received by fw.
             // It should not happen after ReceiveDataL in which construction of proplist already succeed.
@@ -1203,19 +1184,28 @@
             }
 
         iObjectMgr.CommitReservedObjectHandleL( *iReceivedObjectInfo );
+        iRollbackList.Reset();
         }
 
-    iExpectedSendObjectRequest.SetUint32( TMTPTypeRequest::ERequestSessionID,
-        iSessionId );
-    iFramework.RouteRequestRegisterL( iExpectedSendObjectRequest, iConnection );
+    if ( err == KErrNone )
+        {
+        iExpectedSendObjectRequest.SetUint32( TMTPTypeRequest::ERequestSessionID, iSessionId );
+        iFramework.RouteRequestRegisterL( iExpectedSendObjectRequest, iConnection );
 
-    TUint32 parameters[3];
-    parameters[0] = iStorageId;
-    parameters[1] = iParentHandle;
-    parameters[2] = iReceivedObjectInfo->Uint( CMTPObjectMetaData::EHandle );
-    SendResponseL( EMTPRespCodeOK, 3, parameters );
+        TUint32 parameters[3];
+        parameters[0] = iStorageId;
+        parameters[1] = iParentHandle;
+        parameters[2] = iReceivedObjectInfo->Uint( CMTPObjectMetaData::EHandle );
+        SendResponseL( EMTPRespCodeOK, 3, parameters );
+        }
+    else
+        {
+        SendResponseL( EMTPRespCodeGeneralError );
+        Rollback();
+        }
 
     PRINT( _L( "MM MTP <= CSendObject::ReserveObjectL" ) );
+    return err;
     }
 
 // -----------------------------------------------------------------------------
@@ -1248,8 +1238,13 @@
             }
         // Close the file after SetProtectionStatus to make sure other process won't open
         // the file successfully right at the time calling RFile::SetAtt.
-        delete iFileReceived;
-        iFileReceived = NULL;
+        if ( iObjectSize > 0 )
+            {
+            delete iFileReceived;
+            iFileReceived = NULL;
+            }
+        else
+            iFileReceived->File().Close();
         }
 
     PRINT( _L( "MM MTP <= CSendObject::SetProtectionStatus" ) );
@@ -1263,30 +1258,24 @@
     {
     PRINT( _L( "MM MTP => CSendObject::SaveEmptyFileL" ) );
 
-    RFile file;
-    User::LeaveIfError( file.Create( iFs, iFullPath, EFileWrite ) );
-    CleanupClosePushL( file );  // + file
-
     if ( EMTPFormatCodeAbstractAudioVideoPlaylist == iObjectFormat )
         {
-        TInt err = KErrNone;
-        err = file.SetAtt( KEntryAttSystem | KEntryAttHidden,
+        TInt err = iFileReceived->File().SetAtt( KEntryAttSystem | KEntryAttHidden,
             KEntryAttReadOnly | KEntryAttNormal );
         if ( err != KErrNone )
             PRINT1( _L( "MM MTP <> CSendObject::SaveEmptyFileL err = %d" ), err );
         iDpConfig.GetWrapperL().AddDummyFileL( iFullPath );
         }
-    CleanupStack::PopAndDestroy( &file );   // - file
 
     // add playlist to MPX DB
     TRAPD( err, AddMediaToStoreL() );
 
     if ( err != KErrNone )
-        {
-        // Ignore err even add into MPX get failed.
-        }
+        iRollbackList.Append( &CSendObject::RemoveObjectFromDbL );
+    else
+        iRollbackList.Reset();
 
-    PRINT1( _L( "MM MTP <= CSendObject::SaveEmptyFileLerr = %d" ), err );
+    PRINT1( _L( "MM MTP <= CSendObject::SaveEmptyFileL err = %d" ), err );
     }
 
 // -----------------------------------------------------------------------------
@@ -1303,7 +1292,6 @@
     // Might need to set dateadded and datemodify for further extension.
     SetProtectionStatus();
 
-    iDpConfig.GetWrapperL().SetStorageRootL( iFullPath );
     PRINT1( _L( "MM MTP <> CSendObject::AddMediaToStoreL iFullPath = %S" ), &iFullPath );
     iDpConfig.GetWrapperL().AddObjectL( *iReceivedObjectInfo );
 
@@ -1331,20 +1319,49 @@
 //
 void CSendObject::Rollback()
     {
-    // Delete this object from file system.
-    if ( iProgress == ESendObjectInProgress )
-            // || iProgress == EObjectInfoSucceed   // this line is to be commented out until SetSize is done in SendObjectInfo/SendObjectPropList
-            //||iProgress == EObjectInfoFail )
+    PRINT( _L("MM MTP => CSendObject::Rollback") );
+
+    TInt count = iRollbackList.Count();
+    PRINT1( _L("MM MTP => CSendObject::Rollback, iRollbackList.Count() = %d"), iRollbackList.Count() );
+
+    for ( TInt i = 0; i < count; i++ )
         {
-        PRINT1( _L( "MM MTP <> CSendObject::Rollback ROLLBACK_FILE %S" ), &iFullPath );
-        // Close the interrupted transfer file by delete iFileReceived object
-        delete iFileReceived;
-        iFileReceived = NULL;
+        TMmMtpRollbackAction tmp = iRollbackList[i];
+        ( this->*((TMmMtpRollbackAction)(iRollbackList[i])))();
+        }
+    iRollbackList.Reset();
+
+    PRINT( _L("MM MTP <= CSendObject::Rollback") );
+    }
+
+void CSendObject::UnreserveObjectL()
+    {
+    PRINT( _L("MM MTP => CSendObject::UnreserveObjectL") );
+    iFramework.ObjectMgr().UnreserveObjectHandleL( *iReceivedObjectInfo );
+    PRINT( _L("MM MTP <= CSendObject::UnreserveObjectL") );
+    }
 
-        iFramework.Fs().Delete( iFullPath );
-        TRAP_IGNORE( iFramework.ObjectMgr().UnreserveObjectHandleL( *iReceivedObjectInfo ) );
-        iProgress = EObjectNone;
+void CSendObject::RemoveObjectFromDbL()
+    {
+    PRINT( _L("MM MTP => CSendObject::RemoveObjectFromDbL") );
+    iFramework.ObjectMgr().RemoveObjectL( iReceivedObjectInfo->DesC( CMTPObjectMetaData::ESuid ) );
+    iDpConfig.GetWrapperL().DeleteObjectL( *iReceivedObjectInfo );
+    PRINT( _L("MM MTP <= CSendObject::RemoveObjectFromDbL") );
+    }
+
+void CSendObject::RemoveObjectFromFs()
+    {
+    PRINT( _L("MM MTP => CSendObject::RemoveObjectFromFs") );
+
+    delete iFileReceived;
+    iFileReceived = NULL;
+
+    TInt err = iFramework.Fs().Delete( iFullPath );
+    if ( err != KErrNone )
+        {
+        PRINT1( _L("MM MTP <> CSendObject::RemoveObjectFromFs err = %d"), err );
         }
+    PRINT( _L("MM MTP <= CSendObject::RemoveObjectFromFs") );
     }
 
 // end of file