--- a/userlibandfileserver/fileserver/sfile/sf_ses.cpp Wed Sep 22 10:53:45 2010 +0100
+++ b/userlibandfileserver/fileserver/sfile/sf_ses.cpp Mon Sep 27 10:52:00 2010 +0100
@@ -22,10 +22,13 @@
#include "sf_notifier.h"
#endif //SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION
+TInt CancelAsyncRequests(CSessionFs* aSession);
+
+
CSessionFs::CSessionFs()
:iSessionFlags((TInt)EFsSessionFlagsAll),
iReservedDriveAccess(KReservedDriveAccessArrayGranularity, _FOFF(TReservedDriveAccess, iDriveNumber)),
- iId(0)
+ iId(0), iAccessCount(1)
{
#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
__e32_atomic_add_ord32(&SessionCount, 1);
@@ -41,6 +44,13 @@
{
__PRINT1(_L("CSessionFs::~CSessionFs() deleting... = 0x%x"),this);
+ FsNotify::CancelSession(this);
+
+#ifdef SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION
+ FsNotificationManager::RemoveNotificationRequest(this);
+#endif //SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION
+
+
//take out all the reserved space set by this session
while(iReservedDriveAccess.Count())
{
@@ -65,14 +75,42 @@
delete iPath;
iSessionFlagsLock.Close();
- if(iDisconnectRequest)
- delete(iDisconnectRequest);
#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
__e32_atomic_add_ord32(&SessionCount, (TUint32) -1);
#endif
}
+void CSessionFs::Close()
+ {
+ TheFileServer->SessionQueueLockWait();
+
+ if (iAccessCount == 1)
+ {
+ // close the objects owned by this session
+ // NB closing a CFileShare may allocate a request to flush dirty data which will
+ // in turn increment iAccessCount on this session
+ if (iHandles)
+ {
+ // Cancel any ASYNC requests belonging to this session BEFORE
+ // CSessionFs is deleted to avoid a KERN-EXEC 44 (EBadMessageHandle)
+ CancelAsyncRequests(this);
+ delete iHandles;
+ iHandles = NULL;
+ }
+ }
+
+ if (__e32_atomic_tas_ord32(&iAccessCount, 1, -1, 0) == 1)
+ {
+ RMessage2 message = iMessage;
+ delete this;
+ // NB Must complete the message AFTER the session has been deleted...
+ message.Complete(KErrNone);
+ }
+
+ TheFileServer->SessionQueueLockSignal();
+ }
+
void CSessionFs::CreateL()
//
// Create any additional resources.
@@ -83,12 +121,6 @@
iHandles=CFsObjectIx::NewL();
TInt r = iSessionFlagsLock.CreateLocal();
User::LeaveIfError(r);
- RMessage2 m;
-
- iDisconnectRequest=new(ELeave) CFsDisconnectRequest;
- iDisconnectRequest->Set(m,SessionDisconnectOp,this);
-
-
}
TInt CSessionFs::CurrentDrive()
@@ -144,9 +176,10 @@
__THRD_PRINT1(_L("CSessionFs::Disconnect() 0x%x"),this);
iHandles->CloseMainThreadObjects();
- iDisconnectRequest->SetMessage((RMessage2&)aMessage);
+ iMessage = aMessage;
- iDisconnectRequest->Dispatch();
+ // close the session - if there are no requests using this session then the session will be freed
+ Close();
}
@@ -478,107 +511,6 @@
-TInt TFsCancelSession::DoRequestL(CFsRequest* aRequest)
- {
- __CHECK_DRIVETHREAD(aRequest->DriveNumber());
-
- // Cancel any outstanding requests
- CDriveThread* pT=NULL;
- TInt r=FsThreadManager::GetDriveThread(aRequest->DriveNumber(), &pT);
- if(r==KErrNone)
- pT->CompleteSessionRequests(aRequest->Session(),KErrCancel);
- // We must also cancel any ASYNC requests belonging to this session BEFORE
- // ~CSessionFs() is called to avoid a KERN-EXEC 44 (EBadMessageHandle)
- CancelAsyncRequests(aRequest->Session());
- return(r);
- }
-
-TInt TFsCancelSession::Initialise(CFsRequest* /*aRequest*/)
- {
- return(KErrNone);
- }
-
-TInt TFsSessionDisconnect::DoRequestL(CFsRequest* aRequest)
- {
- __PRINT(_L("TFsSessionDisconnect::DoRequestL()"));
- __ASSERT_DEBUG(FsThreadManager::IsDisconnectThread(),Fault(ESessionDisconnectThread1));
- CDisconnectThread* pT=FsThreadManager::GetDisconnectThread();
-
- // Complete requests on all plugins
- CFsInternalRequest* pR=pT->GetRequest();
- FsPluginManager::CompleteSessionRequests(aRequest->Session(), KErrCancel, pR);
-
- // ...and on all drives
- for(TInt i=0;i<KMaxDrives;++i)
- {
- FsThreadManager::LockDrive(i);
- if(!FsThreadManager::IsDriveAvailable(i,EFalse)||FsThreadManager::IsDriveSync(i,EFalse))
- {
- FsThreadManager::UnlockDrive(i);
- continue;
- }
- pR->Set(CancelSessionOp,aRequest->Session());
- pR->SetDriveNumber(i);
- pR->Status()=KRequestPending;
- pR->Dispatch();
- FsThreadManager::UnlockDrive(i);
- User::WaitForRequest(pR->Status());
- // check request completed or cancelled (by file system dismount which completes requests with KErrNotReady)
- __ASSERT_ALWAYS(pR->Status().Int()==KErrNone||pR->Status().Int()==KErrNotReady,Fault(ESessionDisconnectThread2));
- __THRD_PRINT2(_L("cancel session requests on drive %d r=%d"),i,pR->Status().Int());
-
- if (TFileCacheSettings::Flags(i) & (EFileCacheWriteEnabled | EFileCacheWriteOn))
- {
- FsThreadManager::LockDrive(i);
- if(!FsThreadManager::IsDriveAvailable(i,EFalse)||FsThreadManager::IsDriveSync(i,EFalse))
- {
- FsThreadManager::UnlockDrive(i);
- continue;
- }
-
- // Flush dirty data
- pR->Set(FlushDirtyDataOp,aRequest->Session());
- pR->SetDriveNumber(i);
- pR->Status()=KRequestPending;
- pR->Dispatch();
- FsThreadManager::UnlockDrive(i);
- User::WaitForRequest(pR->Status());
- // check request completed or cancelled (by file system dismount which completes requests with KErrNotReady)
- __ASSERT_ALWAYS(pR->Status().Int()==KErrNone||pR->Status().Int()==KErrNotReady,Fault(ESessionDisconnectThread2));
- __THRD_PRINT2(_L("Flush dirty data on drive %d r=%d"),i,pR->Status().Int());
- }
-
- }
- FsNotify::CancelSession(aRequest->Session());
-
-#ifdef SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION
- FsNotificationManager::RemoveNotificationRequest(aRequest->Session());
-#endif //SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION
-
-
- // don't delete session here, will be done in CFsDisconnectRequest::Complete()
- return(KErrNone);
- }
-
-TInt TFsSessionDisconnect::Initialise(CFsRequest* /*aRequest*/)
- {
- return(KErrNone);
- }
-
-TInt TFsCancelPlugin::DoRequestL(CFsRequest* aRequest)
- {
- //__ASSERT_DEBUG(FsPluginManager::IsPluginThread(),Fault(EFsPluginThreadError));
- FsPluginManager::CancelPlugin(aRequest->iCurrentPlugin,aRequest->Session());
- TInt err = aRequest->iCurrentPlugin->SessionDisconnect(aRequest->Session());
- return(err);
- }
-
-TInt TFsCancelPlugin::Initialise(CFsRequest* /*aRequest*/)
- {
- // Notify plugin of session disconnect
- return(KErrNone);
- }
-
TInt TFsSetSessionFlags::DoRequestL(CFsRequest* aRequest)
{
aRequest->Session()->SetSessionFlags(aRequest->Message().Int0(), aRequest->Message().Int1());