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