--- /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<KMaxFileName> 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<KMaxFileName> 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<KMaxFileName> 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&&aAfter<iThreshold)||(aBefore<=iThreshold&&aAfter>iThreshold))
+ 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<CNotifyInfo> 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<CNotifyInfo> 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<CNotifyInfo> 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<CNotifyInfo> 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<CNotifyInfo> 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<CNotifyInfo> 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<CNotifyInfo> 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<CNotifyInfo> 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;i<KMaxDiskQues;++i)
+ {
+ iDiskSpaceQues[i].SetDriveNumber(i);
+ }
+ }
+
+TBool FsNotify::IsChangeQueEmpty(TInt aDrive)
+//
+//
+//
+ {
+ if((iChangeQues[ChangeIndex(aDrive)].IsEmpty()) && (iChangeQues[ChangeIndex(KDriveInvalid)].IsEmpty()))
+ return ETrue;
+
+ return EFalse;
+ }
+
+TInt FsNotify::AddChange(CNotifyInfo* aInfo,TInt aDrive)
+//
+//
+//
+ {
+ __ASSERT_DEBUG(aInfo->Type()==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<KMaxNotifyQues;++i)
+ {
+ TBool isFound=iChangeQues[i].CancelSession(aSession,KErrCancel,aStatus);
+ if(aStatus && isFound)
+ break;
+ }
+ }
+
+void FsNotify::CancelDiskSpaceSession(CSessionFs* aSession,TRequestStatus* aStatus)
+//
+// Cancel disk space notification(s) setup by aSession and matching aStatus if not NULL
+//
+
+ {
+ __PRINT2(_L("FsNotify::CancelDiskSpaceSession() aSession=0x%x aStatus=0x%x"),aSession,aStatus);
+ for(TInt i=0;i<KMaxDiskQues;++i)
+ {
+ TBool isFound=iDiskSpaceQues[i].CancelSession(aSession,KErrCancel,aStatus);
+ if(aStatus && isFound)
+ break;
+ }
+ }
+
+void FsNotify::CancelDebugSession(CSessionFs* aSession, TRequestStatus* aStatus)
+//
+// Cancel debug notification(s) setup by aSession and matching aStatus if not NULL
+//
+ {
+ __PRINT2(_L("FsNotify::CancelDebugSession() aSession=0x%x aStatus=0x%x"),aSession,aStatus);
+ iDebugQue.CancelSession(aSession,KErrCancel,aStatus);
+ }
+
+void FsNotify::CancelDismountNotifySession(CSessionFs* aSession, TRequestStatus* aStatus)
+//
+// Cancel all media removal notification(s) setup by aSession (if aStatus == NULL)
+// else cancels all oustanding notifications(s) for the session
+//
+ {
+ __PRINT2(_L("FsNotify::CancelDismountNotifySession() aSession=0x%x aStatus=0x%x"),aSession,aStatus);
+ iDismountNotifyQue.CancelSession(aSession,KErrCancel,aStatus);
+ }
+
+void FsNotify::CancelSession(CSessionFs* aSession)
+//
+//
+//
+ {
+ __PRINT(_L("FsNotify::CancelSession"));
+ FsNotify::CancelChangeSession(aSession);
+ FsNotify::CancelDiskSpaceSession(aSession);
+ FsNotify::CancelDebugSession(aSession);
+ FsNotify::CancelDismountNotifySession(aSession);
+ }
+
+
+TInt FsNotify::ChangeIndex(TInt aDrive)
+//
+//
+//
+ {
+ __ASSERT_DEBUG((aDrive>=EDriveA && aDrive<=EDriveZ) || aDrive==KDriveInvalid,Fault(EChangeBadIndex));
+ if(aDrive==KDriveInvalid)
+ return(0);
+ else
+ return(aDrive+1);
+ }
+