diff -r ff5437e4337c -r 48e57fb1237e userlibandfileserver/fileserver/sfile/sf_notify.cpp --- a/userlibandfileserver/fileserver/sfile/sf_notify.cpp Wed Oct 06 17:13:14 2010 +0100 +++ b/userlibandfileserver/fileserver/sfile/sf_notify.cpp Mon Oct 11 17:54:41 2010 +0100 @@ -40,7 +40,11 @@ // // { - __ASSERT_DEBUG(!iLink.iNext,Fault(ENotifyInfoDestructor)); + // message should have been completed already + __ASSERT_DEBUG(iMessage.IsNull(), Fault(ENotifyInfoDestructor)); + + __ASSERT_DEBUG(iLink.iNext,Fault(ENotifyInfoDestructor)); + iLink.Deque(); } void CNotifyInfo::Complete(TInt aError) @@ -49,10 +53,8 @@ // { __PRINT2(_L("CNotifyInfo::Complete 0x%x error=%d"),this,aError); - if (!iMessage.IsNull()) // Dismount notifiers may be completed but remain in the list - { // until handled by the client or the session is closed. + if (!iMessage.IsNull()) iMessage.Complete(aError); - } } @@ -259,12 +261,27 @@ break; case EFsDismountRegisterClient: __ASSERT_ALWAYS(TheDrives[iDriveNumber].DismountUnlock() >= 0, Fault(ENotifyDismountCancel)); + __ASSERT_ALWAYS(iMessage.IsNull(), Fault(ENotifyDismountCancel)); + TheDrives[iDriveNumber].DismountClientRemoved(); break; default: break; } } +void CDismountNotifyInfo::Complete(TInt aError) + { + __PRINT2(_L("CDismountNotifyInfo::Complete 0x%x error=%d"),this,aError); + if (!iMessage.IsNull()) + { + iMessage.Complete(aError); + // inc count of messages completed by EFsDismountNotifyClients & waiting for an EFsAllowDismount request from client + if (iMode == EFsDismountRegisterClient) + TheDrives[iDriveNumber].DismountClientAdded(); + } + } + + void CDismountNotifyInfo::Initialise(TNotifyDismountMode aMode, TInt aDriveNumber, TRequestStatus* aStatus,const RMessagePtr2& aMessage,CSessionFs* aSession) { iMode = aMode; @@ -324,7 +341,6 @@ { isFound=ETrue; info->Complete(aCompletionCode); - info->iLink.Deque(); delete(info); if(aStatus) break; @@ -333,18 +349,6 @@ return(isFound); } -CNotifyInfo* TBaseQue::DoFindEntry(CSessionFs* aSession, TRequestStatus* aStatus) - { - TDblQueIter q(iHeader); - CNotifyInfo* info; - while((info=q++)!=NULL) - { - if(info->Session()==aSession && (!aStatus || aStatus==info->Status())) - return info; - } - return NULL; - } - void TBaseQue::DoCancelAll(TInt aCompletionCode) // // Cancel all notifications @@ -356,7 +360,6 @@ while((info=q++)!=NULL) { info->Complete(aCompletionCode); - info->iLink.Deque(); delete(info); } __ASSERT_DEBUG(iHeader.IsEmpty(),Fault(EBaseQueCancel)); @@ -433,7 +436,6 @@ { __PRINT1(_L("TChangeQue::CheckChange()-Matching info=0x%x"),info); info->Complete(KErrNone); - info->iLink.Deque(); delete(info); } } @@ -530,7 +532,6 @@ { __PRINT1(_L("TDiskSpaceQue::CheckDiskSpace()-Matching info=0x%x"),info); info->Complete(KErrNone); - info->iLink.Deque(); delete(info); } } @@ -579,7 +580,6 @@ { __PRINT1(_L("TDiskSpaceQue::CheckDiskSpace()-Matching info=0x%x"),info); info->Complete(KErrNone); - info->iLink.Deque(); delete(info); } } @@ -646,7 +646,6 @@ { __PRINT1(_L("TDebugQue::CheckDebug()-Matching info=0x%x"),info); info->Complete(KErrNone); - info->iLink.Deque(); delete(info); } } @@ -664,22 +663,41 @@ return(KErrNone); } -TInt TDismountNotifyQue::CancelSession(CSessionFs* aSession,TInt aCompletionCode,TRequestStatus* aStatus) +void TDismountNotifyQue::CancelSession(CSessionFs* aSession,TInt aCompletionCode,TRequestStatus* aStatus) // -// Returns the drive number or KErrNotFound // { iQLock.Wait(); - // return the drive number - CDismountNotifyInfo* info = (CDismountNotifyInfo*) DoFindEntry(aSession, aStatus); - TInt driveNumber = info ? info->DriveNumber() : KErrNotFound; + TDblQueIter q(iHeader); + CDismountNotifyInfo* info; + while((info=q++)!=NULL) + { + if(info->Session()==aSession && (!aStatus || aStatus==info->Status())) + { + TInt driveNumber = info->DriveNumber(); + + info->Complete(aCompletionCode); + TInt mode = info->Mode(); + + delete info; + info = NULL; - TBaseQue::DoCancelSession(aSession,aCompletionCode,aStatus); + // if we're cancelling a dismount request (EFsDismountNotifyClients or EFsDismountForceDismount), + // then we need to cancel the deferred dismount and issue a disk change notification as observers + // may be expecting one... + if (mode == EFsDismountNotifyClients || mode == EFsDismountForceDismount) + { + TheDrives[driveNumber].SetDismountDeferred(EFalse); + FsNotify::DiskChange(driveNumber); + } + + if(aStatus) + break; + } + } iQLock.Signal(); - - return(driveNumber); } void TDismountNotifyQue::CancelAll(TInt aCompletionCode) @@ -708,40 +726,43 @@ __PRINT1(_L("TDismountNotifyQue::CheckDismount()-Matching info=0x%x"),info); info->Complete(aError); if(aRemove) - { - info->iLink.Deque(); - delete(info); - } + delete info; } } - __ASSERT_ALWAYS(!aRemove || TheDrives[aDrive].DismountLocked() == 0, Fault(EDismountLocked)); + __ASSERT_ALWAYS(!(aRemove && aMode == EFsDismountRegisterClient && TheDrives[aDrive].DismountLocked() > 0), Fault(EDismountLocked)); iQLock.Signal(); } TBool TDismountNotifyQue::HandlePendingDismount(CSessionFs* aSession, TInt aDrive) // -// Determine if the session has any outstanding dismount notifications on the specified drive. +// Determine if the session has any outstanding *completed* dismount notifications on the specified drive +// and delete them. Called from TFsAllowDismount::DoRequestL() // { iQLock.Wait(); - TDblQueIter q(iHeader); - CNotifyInfo* info; + TDblQueIter q(iHeader); + CDismountNotifyInfo* info; + + TBool entryFound = EFalse; + while((info=q++)!=NULL) { __ASSERT_DEBUG(info->Type()==CNotifyInfo::EDismount,Fault(EBadDismountNotifyType)); if(((CDismountNotifyInfo*)info)->IsMatching(EFsDismountRegisterClient, aDrive, aSession)) { - __PRINT1(_L("TDismountNotifyQue::CheckDismount()-Pending info=0x%x"),info); - info->iLink.Deque(); - delete(info); - iQLock.Signal(); - return ETrue; + __PRINT1(_L("TDismountNotifyQue::HandlePendingDismount()-Pending info=0x%x"),info); + + if (info->Completed()) + delete info; + + entryFound = ETrue; } } iQLock.Signal(); - return EFalse; + + return entryFound; } void FsNotify::Initialise() @@ -948,15 +969,14 @@ iDebugQue.CancelSession(aSession,KErrCancel,aStatus); } -TInt FsNotify::CancelDismountNotifySession(CSessionFs* aSession, TRequestStatus* aStatus) +void FsNotify::CancelDismountNotifySession(CSessionFs* aSession, TRequestStatus* aStatus) // // Cancel all media removal notification(s) setup by aSession (if aStatus == NULL) // else cancels all outstanding notifications(s) for the session // { __PRINT2(_L("FsNotify::CancelDismountNotifySession() aSession=0x%x aStatus=0x%x"),aSession,aStatus); - TInt drive = iDismountNotifyQue.CancelSession(aSession,KErrCancel,aStatus); - return drive; + iDismountNotifyQue.CancelSession(aSession,KErrCancel,aStatus); } void FsNotify::CancelSession(CSessionFs* aSession)