userlibandfileserver/fileserver/sfile/sf_ses.cpp
changeset 273 6a75fa55495f
parent 90 947f0dc9f7a8
child 286 48e57fb1237e
--- 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());