diff -r 000000000000 -r a41df078684a userlibandfileserver/fileserver/sfile/sf_notify.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/userlibandfileserver/fileserver/sfile/sf_notify.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,966 @@ +// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// f32\sfile\sf_notif.cpp +// +// + +#include "sf_std.h" + + + +TChangeQue FsNotify::iChangeQues[KMaxNotifyQues]; +TDiskSpaceQue FsNotify::iDiskSpaceQues[KMaxDiskQues]; +TDebugQue FsNotify::iDebugQue; +TDismountNotifyQue FsNotify::iDismountNotifyQue; + +void CNotifyInfo::Initialise(TInfoType aType,TRequestStatus* aStatus,const RMessagePtr2& aMessage,CSessionFs* aSession) +// +// +// + { + iType=aType; + iStatus=aStatus; + iMessage=aMessage; + iSession=aSession; + }; + +CNotifyInfo::~CNotifyInfo() +// +// +// + { + __ASSERT_DEBUG(!iLink.iNext,Fault(ENotifyInfoDestructor)); + } + +void CNotifyInfo::Complete(TInt aError) +// +// +// + { + __PRINT2(_L("CNotifyInfo::Complete 0x%x error=%d"),this,aError); + if (iType != EDismount || !iMessage.IsNull()) // Dismount notifiers may be completed but remain in the list + { // until handled by the client or the session is closed. + iMessage.Complete(aError); + } + } + + +void CStdChangeInfo::Initialise(TNotifyType aChangeType,TRequestStatus* aStatus,const RMessagePtr2& aMessage,CSessionFs* aSession) +// +// +// + { + iChangeType=aChangeType; + CNotifyInfo::Initialise(EStdChange,aStatus,aMessage,aSession); + } + +TUint CStdChangeInfo::RequestNotifyType(CFsRequest* aRequest) +// +// return notification type for the request +// + { + TUint notifyType=aRequest->Operation()->NotifyType(); + if(aRequest->Operation()->Function()==EFsRename) + { + __ASSERT_DEBUG(notifyType==(ENotifyDir|ENotifyFile|ENotifyEntry),Fault(EStdChangeRequestType)); + if(aRequest->Src().NamePresent()) + notifyType=ENotifyFile|ENotifyEntry; + else + notifyType=ENotifyDir|ENotifyEntry; + } + return(notifyType); + } + +TBool CStdChangeInfo::IsMatching(CFsRequest* aRequest) +// +// return ETrue if operation type of request matches that of change notification +// + { + if((iChangeType&ENotifyAll) || (iChangeType&aRequest->Operation()->NotifyType())) + return(ETrue); + else + return(EFalse); + } + +void CExtChangeInfo::Initialise(TNotifyType aChangeType,TRequestStatus* aStatus,const RMessagePtr2& aMessage,CSessionFs* aSession,const TDesC& aName) +// +// +// + { + __ASSERT_DEBUG(aName.Length()<=KMaxFileName-2,Fault(EExtChangeNameLength)); + iName=aName; + iChangeType=aChangeType; + CNotifyInfo::Initialise(EExtChange,aStatus,aMessage,aSession); + } + + +TBool CExtChangeInfo::IsMatching(CFsRequest* aRequest) +// +// return ETrue if operation notify type of request matches that of change notification +// and paths match +// + { + TInt function=aRequest->Operation()->Function(); + // if a rename occurred inform any requests if their path has been changed regardless of the notification type + if(function==EFsRename) + { + TBuf renamePath=aRequest->Src().FullName().Mid(2); + renamePath+=_L("*"); + if (iName.MatchF(renamePath)!=KErrNotFound) + return(ETrue); + } + + + //Special case where the dir the notifier is setup on has just been created + if(function==EFsMkDir) + { + TInt notDrive; + RFs::CharToDrive(aRequest->Src().Drive()[0],notDrive); //can not fail as the drive letter has been parsed already + if(aRequest->Src().Path().MatchF(iName) == 0 && aRequest->DriveNumber() == notDrive) + return ETrue; + } + + //Special case where the File the notifier is setup on has just been created by temp as the name is not known unti it has been created + if(function==EFsRename||function==EFsFileOpen||function==EFsFileCreate||function==EFsFileReplace) + { + TInt notDrive; + RFs::CharToDrive(aRequest->Src().Drive()[0],notDrive); //can not fail as the drive letter has been parsed already + if(aRequest->Src().FullName().Mid(2).MatchF(iName) == 0 && aRequest->DriveNumber() == notDrive) + return ETrue; + } + + //For the case of a file created using EFsFileTemp we can probably ignore it for special cases as it + //is created with a random name. Not specifically going to be being looked for + + if((iChangeType&ENotifyAll) || (iChangeType&RequestNotifyType(aRequest))) + { + switch (function) + { + // Notify interested requests if a SetDriveName(), SetVolume() or RawDiskWrite() operation + // occcurred. By their nature, these operations have no distinct path. All outstanding + // requests monitoring the relevant TNotifyType are potentially interested in such operations + case EFsFileWrite: + case EFsFileWriteDirty: + case EFsFileSet: + case EFsFileSetAtt: + case EFsFileSetModified: + case EFsFileSetSize: + { + TBuf root=iName; + root+=_L("*"); + + // NB share may be NULL if file server has initiated a flush of the file cache + CFileShare* share; + CFileCB* fileCache; + GetFileFromScratch(aRequest, share, fileCache); + if (share && share->File().FileName().MatchF(root) != KErrNotFound) + return(ETrue); + + } + break; + case EFsSetDriveName: + case EFsSetVolume: + case EFsRawDiskWrite: + case EFsLockDrive: + case EFsUnlockDrive: + case EFsReserveDriveSpace: + { + return(ETrue); + } + + default: + { + TBuf root = iName; + root+=_L("*"); + + if(aRequest->Src().FullName().Mid(2).MatchF(root)!=KErrNotFound) + return(ETrue); + else if(function==EFsRename||function==EFsReplace||function==EFsFileRename) + { + // - rename/replace causes the file/path to disappear + if(aRequest->Dest().FullName().Mid(2).MatchF(root)!=KErrNotFound) + { + return(ETrue); + } + + // - rename/replace causes the file/path to arrive + root=aRequest->Dest().FullName().Mid(2); + root+=_L("*"); + + if (iName.MatchF(root)!=KErrNotFound) + { + return(ETrue); + } + } + } + } + } + return(EFalse); + } + + +void CDiskSpaceInfo::Initialise(TRequestStatus* aStatus,const RMessagePtr2& aMessage,CSessionFs* aSession,TInt64 aThreshold) +// +// +// + { + __ASSERT_DEBUG(aThreshold>0,Fault(EDiskSpaceThreshold)); + iThreshold=aThreshold; + CNotifyInfo::Initialise(EDiskSpace,aStatus,aMessage,aSession); + } + +TBool CDiskSpaceInfo::IsMatching(TInt64& aBefore,TInt64& aAfter) +// +// return ETrue if the threshold has been crossed +// + { + if((aBefore>=iThreshold&&aAfteriThreshold)) + return(ETrue); + return(EFalse); + } + +void CDebugChangeInfo::Initialise(TUint aDebugType,TRequestStatus* aStatus,const RMessagePtr2& aMessage,CSessionFs* aSession) +// +// +// + { + __ASSERT_DEBUG((aDebugType&KDebugNotifyMask)&&!(aDebugType&~KDebugNotifyMask),Fault(EDebugChangeType)); + iDebugType=aDebugType; + CNotifyInfo::Initialise(EDebugChange,aStatus,aMessage,aSession); + } + +TBool CDebugChangeInfo::IsMatching(TUint aFunction) +// +// return ETrue if debug notification type matches aFunction +// + { + if(iDebugType&aFunction) + return(ETrue); + return(EFalse); + } + + +CDismountNotifyInfo::~CDismountNotifyInfo() + { + switch(iMode) + { + case EFsDismountNotifyClients: + break; + case EFsDismountRegisterClient: + __ASSERT_ALWAYS(TheDrives[iDriveNumber].DismountUnlock() >= 0, Fault(ENotifyDismountCancel)); + break; + default: + break; + } + } + +void CDismountNotifyInfo::Initialise(TNotifyDismountMode aMode, TInt aDriveNumber, TRequestStatus* aStatus,const RMessagePtr2& aMessage,CSessionFs* aSession) + { + iMode = aMode; + iDriveNumber=aDriveNumber; + CNotifyInfo::Initialise(EDismount,aStatus,aMessage,aSession); + + if (iMode == EFsDismountRegisterClient) + TheDrives[iDriveNumber].DismountLock(); + } + +TBool CDismountNotifyInfo::IsMatching(TNotifyDismountMode aMode, TInt aDriveNumber, CSessionFs* aSession) + { + if((iDriveNumber == aDriveNumber) && (iMode == aMode) && (aSession == NULL || aSession == Session())) + return(ETrue); + return(EFalse); + } + +TBaseQue::TBaseQue() +// +// +// + { + iHeader.SetOffset(_FOFF(CNotifyInfo,iLink)); + TInt r=iQLock.CreateLocal(); + __ASSERT_ALWAYS(r==KErrNone,Fault(EBaseQueConstruction)); + } + +TBaseQue::~TBaseQue() +// +// +// + { + iQLock.Close(); + } + +void TBaseQue::DoAddNotify(CNotifyInfo* aInfo) +// +// Add notification +// Que should be locked by calling function +// + { + iHeader.AddLast(*aInfo); + } + +TBool TBaseQue::DoCancelSession(CSessionFs* aSession,TInt aCompletionCode, TRequestStatus* aStatus) +// +// Cancel notification(s) setup by aSession matching aStatus if set +// Que should be locked by calling function +// + { + TDblQueIter q(iHeader); + CNotifyInfo* info; + TBool isFound=EFalse; + while((info=q++)!=NULL) + { + if(info->Session()==aSession && (!aStatus || aStatus==info->Status())) + { + isFound=ETrue; + info->Complete(aCompletionCode); + info->iLink.Deque(); + delete(info); + if(aStatus) + break; + } + } + return(isFound); + } + +void TBaseQue::DoCancelAll(TInt aCompletionCode) +// +// Cancel all notifications +// Que should be locked by calling function +// + { + TDblQueIter q(iHeader); + CNotifyInfo* info; + while((info=q++)!=NULL) + { + info->Complete(aCompletionCode); + info->iLink.Deque(); + delete(info); + } + __ASSERT_DEBUG(iHeader.IsEmpty(),Fault(EBaseQueCancel)); + } + +TBool TBaseQue::IsEmpty() +// +// Que should be locked by calling function +// + { + return iHeader.IsEmpty(); + } + +TBool TChangeQue::IsEmpty() +// +// +// + { + iQLock.Wait(); + TBool empty = TBaseQue::IsEmpty(); + iQLock.Signal(); + return(empty); + } + +TInt TChangeQue::AddNotify(CNotifyInfo* aInfo) +// +// +// + { + iQLock.Wait(); + TBaseQue::DoAddNotify(aInfo); + iQLock.Signal(); + return(KErrNone); + } + +TBool TChangeQue::CancelSession(CSessionFs* aSession,TInt aCompletionCode,TRequestStatus* aStatus) +// +// +// + { + iQLock.Wait(); + TBool isFound=TBaseQue::DoCancelSession(aSession,aCompletionCode,aStatus); + iQLock.Signal(); + return(isFound); + } + +void TChangeQue::CancelAll(TInt aCompletionCode) +// +// +// + { + iQLock.Wait(); + TBaseQue::DoCancelAll(aCompletionCode); + iQLock.Signal(); + } + +void TChangeQue::CheckChange(CFsRequest* aRequest) +// +// complete any notification in que that matches aRequest +// + { + iQLock.Wait(); + TDblQueIter q(iHeader); + CNotifyInfo* info; + while((info=q++)!=NULL) + { + __ASSERT_DEBUG(info->Type()==CNotifyInfo::EStdChange||info->Type()==CNotifyInfo::EExtChange,Fault(EChangeQueType)); + TBool isMatching; + if(info->Type()==CNotifyInfo::EStdChange) + isMatching=((CStdChangeInfo*)info)->IsMatching(aRequest); + else + isMatching=((CExtChangeInfo*)info)->IsMatching(aRequest); + if(isMatching) + { + __PRINT1(_L("TChangeQue::CheckChange()-Matching info=0x%x"),info); + info->Complete(KErrNone); + info->iLink.Deque(); + delete(info); + } + } + iQLock.Signal(); + } + +TBool TDiskSpaceQue::IsEmpty() +// +// +// + { + iQLock.Wait(); + TBool empty = TBaseQue::IsEmpty(); + iQLock.Signal(); + return(empty); + } + +TInt TDiskSpaceQue::AddNotify(CNotifyInfo* aInfo) +// +// +// + { + iQLock.Wait(); + TInt r=KErrNone; + if(iHeader.IsEmpty()) + { + r=GetFreeDiskSpace(iFreeDiskSpace); + iReservedDiskSpace = TheDrives[iDriveNumber].ReservedSpace(); + } + if(r==KErrNone) + TBaseQue::DoAddNotify(aInfo); + iQLock.Signal(); + return(r); + } + +TInt TDiskSpaceQue::CancelSession(CSessionFs* aSession,TInt aCompletionCode,TRequestStatus* aStatus) +// +// +// + { + iQLock.Wait(); + TBaseQue::DoCancelSession(aSession,aCompletionCode,aStatus); + iQLock.Signal(); + return(KErrNone); + } + +void TDiskSpaceQue::CancelAll(TInt aCompletionCode) +// +// +// + { + iQLock.Wait(); + TBaseQue::DoCancelAll(aCompletionCode); + iQLock.Signal(); + } + + +void TDiskSpaceQue::CheckDiskSpace() +// +// Complete any disk space notification whose threshold has been crossed +// + { + iQLock.Wait(); + if(iHeader.IsEmpty()) + { + iQLock.Signal(); + return; + } + TInt64 freeSpace; + TInt r=GetFreeDiskSpace(freeSpace); + TInt64 reservedSpace(TheDrives[iDriveNumber].ReservedSpace()); + if(r==KErrNone) + { + if((freeSpace==iFreeDiskSpace) && (reservedSpace==iReservedDiskSpace)) + { + iQLock.Signal(); + return; + } + TDblQueIter q(iHeader); + CNotifyInfo* info; + while((info=q++)!=NULL) + { + __ASSERT_DEBUG(info->Type()==CNotifyInfo::EDiskSpace,Fault(EDiskSpaceQueType1)); + + TInt64 newSessionFreeSpace(freeSpace); + TInt64 oldSessionFreeSpace(iFreeDiskSpace); + if(!info->Session()->ReservedAccess(iDriveNumber)) + { + newSessionFreeSpace -= reservedSpace; + oldSessionFreeSpace -= iReservedDiskSpace; + } + + if(((CDiskSpaceInfo*)info)->IsMatching(oldSessionFreeSpace,newSessionFreeSpace)) + { + __PRINT1(_L("TDiskSpaceQue::CheckDiskSpace()-Matching info=0x%x"),info); + info->Complete(KErrNone); + info->iLink.Deque(); + delete(info); + } + } + iFreeDiskSpace=freeSpace; + iReservedDiskSpace=reservedSpace; + } + else + TBaseQue::DoCancelAll(KErrNone); + iQLock.Signal(); + } + +void TDiskSpaceQue::CheckDiskSpace(TInt64& aFreeDiskSpace) +// +// +// + { + iQLock.Wait(); + if(iHeader.IsEmpty()) + { + iQLock.Signal(); + return; + } + + TInt64 reservedSpace(TheDrives[iDriveNumber].ReservedSpace()); + + if((aFreeDiskSpace==iFreeDiskSpace) && (reservedSpace==iReservedDiskSpace)) + { + iQLock.Signal(); + return; + } + TDblQueIter q(iHeader); + CNotifyInfo* info; + while((info=q++)!=NULL) + { + __ASSERT_DEBUG(info->Type()==CNotifyInfo::EDiskSpace,Fault(EDiskSpaceQueType2)); + + TInt64 newSessionFreeSpace(aFreeDiskSpace); + TInt64 oldSessionFreeSpace(iFreeDiskSpace); + if(!info->Session()->ReservedAccess(iDriveNumber)) + { + newSessionFreeSpace -= reservedSpace; + oldSessionFreeSpace -= iReservedDiskSpace; + } + + if(((CDiskSpaceInfo*)info)->IsMatching(oldSessionFreeSpace,newSessionFreeSpace)) + { + __PRINT1(_L("TDiskSpaceQue::CheckDiskSpace()-Matching info=0x%x"),info); + info->Complete(KErrNone); + info->iLink.Deque(); + delete(info); + } + } + iFreeDiskSpace=aFreeDiskSpace; + iReservedDiskSpace=reservedSpace; + iQLock.Signal(); + } + +TInt TDiskSpaceQue::GetFreeDiskSpace(TInt64& aFreeDiskSpace) +// +// +// + { + __ASSERT_DEBUG(iDriveNumber>=EDriveA&&iDriveNumber<=EDriveZ,Fault(EDiskSpaceQueDrive)); + __CHECK_DRIVETHREAD(iDriveNumber); + TInt r=TheDrives[iDriveNumber].FreeDiskSpace(aFreeDiskSpace); + return(r); + } + +TInt TDebugQue::AddNotify(CNotifyInfo* aInfo) +// +// +// + { + iQLock.Wait(); + TBaseQue::DoAddNotify(aInfo); + iQLock.Signal(); + return(KErrNone); + } + +TInt TDebugQue::CancelSession(CSessionFs* aSession,TInt aCompletionCode,TRequestStatus* aStatus) +// +// +// + { + iQLock.Wait(); + TBool isFound=TBaseQue::DoCancelSession(aSession,aCompletionCode,aStatus); + iQLock.Signal(); + return(isFound); + } + +void TDebugQue::CancelAll(TInt aCompletionCode) +// +// +// + { + iQLock.Wait(); + TBaseQue::DoCancelAll(aCompletionCode); + iQLock.Signal(); + } + +void TDebugQue::CheckDebug(TUint aDebugChange) +// +// Complete any debug notification whose debug type matches aDebugChange +// + { + iQLock.Wait(); + TDblQueIter q(iHeader); + CNotifyInfo* info; + while((info=q++)!=NULL) + { + __ASSERT_DEBUG(info->Type()==CNotifyInfo::EDebugChange,Fault(EDebugQueType)); + if(((CDebugChangeInfo*)info)->IsMatching(aDebugChange)) + { + __PRINT1(_L("TDebugQue::CheckDebug()-Matching info=0x%x"),info); + info->Complete(KErrNone); + info->iLink.Deque(); + delete(info); + } + } + iQLock.Signal(); + } + +TInt TDismountNotifyQue::AddNotify(CNotifyInfo* aInfo) +// +// +// + { + iQLock.Wait(); + TBaseQue::DoAddNotify(aInfo); + iQLock.Signal(); + return(KErrNone); + } + +TInt TDismountNotifyQue::CancelSession(CSessionFs* aSession,TInt aCompletionCode,TRequestStatus* aStatus) +// +// +// + { + iQLock.Wait(); + TBool isFound=TBaseQue::DoCancelSession(aSession,aCompletionCode,aStatus); + iQLock.Signal(); + return(isFound); + } + +void TDismountNotifyQue::CancelAll(TInt aCompletionCode) +// +// +// + { + iQLock.Wait(); + TBaseQue::DoCancelAll(aCompletionCode); + iQLock.Signal(); + } + +void TDismountNotifyQue::CheckDismount(TNotifyDismountMode aMode, TInt aDrive, TBool aRemove, TInt aError) +// +// Complete any dismount notifications on the specified drive. +// + { + iQLock.Wait(); + TDblQueIter q(iHeader); + CNotifyInfo* info; + while((info=q++)!=NULL) + { + __ASSERT_DEBUG(info->Type()==CNotifyInfo::EDismount,Fault(EBadDismountNotifyType)); + if(((CDismountNotifyInfo*)info)->IsMatching(aMode, aDrive, NULL)) + { + __PRINT1(_L("TDismountNotifyQue::CheckDismount()-Matching info=0x%x"),info); + info->Complete(aError); + if(aRemove) + { + info->iLink.Deque(); + delete(info); + } + } + } + + __ASSERT_ALWAYS(!aRemove || 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. +// + { + iQLock.Wait(); + TDblQueIter q(iHeader); + CNotifyInfo* info; + 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; + } + } + iQLock.Signal(); + return EFalse; + } + +void FsNotify::Initialise() +// +// +// + { + for(TInt i=0;iType()==CNotifyInfo::EStdChange||aInfo->Type()==CNotifyInfo::EExtChange,Fault(EBadChangeNotifyType)); + __PRINT2(_L("FsNotify::AddChange() drive=%d,info=0x%x"),aDrive,aInfo); + iChangeQues[ChangeIndex(aDrive)].AddNotify(aInfo); + return(KErrNone); + } + +TBool FsNotify::IsDiskSpaceQueEmpty(TInt aDrive) +// +// +// + { + if(iDiskSpaceQues[aDrive].IsEmpty()) + return ETrue; + + return EFalse; + } + +TInt FsNotify::AddDiskSpace(CNotifyInfo* aInfo,TInt aDrive) +// +// +// + { + __ASSERT_DEBUG(aInfo->Type()==CNotifyInfo::EDiskSpace,Fault(EBadDiskNotifyType)); + __ASSERT_DEBUG((aDrive>=EDriveA && aDrive<=EDriveZ),Fault(EDiskBadIndex1)); + __PRINT2(_L("FsNotify::AddDiskSpace() drive=%d,info=0x%x"),aDrive,aInfo); + return(iDiskSpaceQues[aDrive].AddNotify(aInfo)); + } + +TInt FsNotify::AddDebug(CNotifyInfo* aDebugInfo) +// +// +// + { + __ASSERT_DEBUG(aDebugInfo->Type()==CNotifyInfo::EDebugChange,Fault(EBadDebugNotifyType)); + __PRINT1(_L("FsNotify::AddDebug() info=0x%x"),aDebugInfo); + iDebugQue.AddNotify(aDebugInfo); + return(KErrNone); + } + +TInt FsNotify::AddDismountNotify(CNotifyInfo* aDismountNotifyInfo) +// +// +// + { + __ASSERT_DEBUG(aDismountNotifyInfo->Type()==CNotifyInfo::EDismount,Fault(EBadDismountNotifyType)); + __PRINT1(_L("FsNotify::AddDismountNotify() info=0x%x"),aDismountNotifyInfo); + iDismountNotifyQue.AddNotify(aDismountNotifyInfo); + return(KErrNone); + } + +void FsNotify::HandleChange(CFsRequest* aRequest,TInt aDrive) +// +// Check whether any change notifications need to be completed due to aRequest on aDrive +// + { + __PRINT2(_L("FsNotify::HandleChange() aRequest=0x%x, aDrive=%d"),aRequest,aDrive); + if(!aRequest->IsChangeNotify()) + return; + iChangeQues[ChangeIndex(aDrive)].CheckChange(aRequest); + iChangeQues[ChangeIndex(KDriveInvalid)].CheckChange(aRequest); + } + + +void FsNotify::HandleDiskSpace(CFsRequest* aRequest,TInt aDrive) +// +// Check whether any disk space notifications need to be completed due to aRequest on aDrive +// + { + __ASSERT_DEBUG((aDrive>=EDriveA && aDrive<=EDriveZ) || aDrive==KDriveInvalid,Fault(EDiskBadIndex2)); + __PRINT2(_L("FsNotify::HandleDiskSpace() aRequest=0x%x, aDrive=%d"),aRequest,aDrive); + + if(!aRequest->Operation()->IsDiskSpaceNotify()) + return; + TInt f = aRequest->Operation()->Function(); + if ((f == EFsFileWrite || f == EFsFileWriteDirty) && !((CFsClientMessageRequest*)aRequest)->IsFreeChanged()) + return; + if (FsThreadManager::IsDriveThread(aDrive,EFalse)) + iDiskSpaceQues[aDrive].CheckDiskSpace(); + } + +void FsNotify::HandleDiskSpace(TInt aDrive, TInt64& aFreeSpace) +// +// +// + { + __ASSERT_DEBUG((aDrive>=EDriveA && aDrive<=EDriveZ),Fault(EDiskBadIndex3)); + __PRINT1(_L("FsNotify::HandleDiskSpace() aDrive=%d"),aDrive); + iDiskSpaceQues[aDrive].CheckDiskSpace(aFreeSpace); + } + +void FsNotify::HandleDebug(TUint aFunction) +// +// Check whether any debug notifications need to be completed due to aFunction +// + { + __PRINT1(_L("FsNotify::HandleDebug() aFunction=0x%x"),aFunction); + if(!(aFunction&KDebugNotifyMask)) + return; + iDebugQue.CheckDebug(aFunction); + } + +void FsNotify::HandleDismount(TNotifyDismountMode aMode, TInt aDrive, TBool aRemove, TInt err) +// +// Handle dismount notifications for the given drive +// + { + __PRINT4(_L("FsNotify::HandleDismount() aMode = %d, aDrive=%d, aRemove=%d, err=%d"),aMode,aDrive,aRemove,err); + iDismountNotifyQue.CheckDismount(aMode, aDrive, aRemove, err); + } + +TBool FsNotify::HandlePendingDismount(CSessionFs* aSession, TInt aDrive) +// +// Checks if the session has an outstanding notification registered on the drive +// + { + __PRINT1(_L("FsNotify::HandlePendingDismount() aDrive=%d"),aDrive); + return iDismountNotifyQue.HandlePendingDismount(aSession, aDrive); + } + +void FsNotify::DiskChange(TInt aDrive) +// +// Complete all notifications in queus due to a disk change +// + { + __ASSERT_DEBUG((aDrive>=EDriveA && aDrive<=EDriveZ),Fault(EDiskChangeDrive)); + __PRINT1(_L("FsNotify::DiskChange() aDrive=%d"),aDrive); + iChangeQues[ChangeIndex(aDrive)].CancelAll(KErrNone); + iChangeQues[ChangeIndex(KDriveInvalid)].CancelAll(KErrNone); + iDiskSpaceQues[aDrive].CancelAll(KErrNone); + iDebugQue.CancelAll(KErrNone); + + // if there are any files containing dirty data, start issuing write-dirty data requests to trigger + // a critical notifier (CFileCache::HandleWriteDirtyError()) + // otherwise purge all file caches + TDrive& drive=TheDrives[aDrive]; + drive.FlushCachedFileInfo(ETrue); + } + + +void FsNotify::CancelChangeSession(CSessionFs* aSession,TRequestStatus* aStatus) +// +// Cancel change notifcation(s) setup by aSession and matching aStatus if not NULL +// + { + __PRINT2(_L("FsNotify::CancelChangeSession() aSession=0x%x aStatus=0x%x"),aSession,aStatus); + for(TInt i=0;i=EDriveA && aDrive<=EDriveZ) || aDrive==KDriveInvalid,Fault(EChangeBadIndex)); + if(aDrive==KDriveInvalid) + return(0); + else + return(aDrive+1); + } +