diff -r 000000000000 -r a41df078684a userlibandfileserver/fileserver/sfile/sf_ses.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/userlibandfileserver/fileserver/sfile/sf_ses.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,647 @@ +// Copyright (c) 1995-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_ses.cpp +// +// + +#include "sf_std.h" +#include "sf_file_cache.h" +#include "sf_memory_man.h" +#ifdef SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION +#include "sf_notifier.h" +#endif //SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION + +CSessionFs::CSessionFs() + :iSessionFlags((TInt)EFsSessionFlagsAll), + iReservedDriveAccess(KReservedDriveAccessArrayGranularity, _FOFF(TReservedDriveAccess, iDriveNumber)), + iId(0) + { + } + +CSessionFs *CSessionFs::NewL() + { + return new(ELeave) CSessionFs; + } + +CSessionFs::~CSessionFs() + { + __PRINT1(_L("CSessionFs::~CSessionFs() deleting... = 0x%x"),this); + + //take out all the reserved space set by this session + while(iReservedDriveAccess.Count()) + { + TReservedDriveAccess& reserved = iReservedDriveAccess[0]; + if(reserved.iReservedSpace) + { + TheDrives[reserved.iDriveNumber].SetReservedSpace(TheDrives[reserved.iDriveNumber].ReservedSpace() - reserved.iReservedSpace); + __ASSERT_DEBUG(TheDrives[reserved.iDriveNumber].ReservedSpace() >= 0,Fault(EReserveSpaceArithmetic)); + } + iReservedDriveAccess.Remove(0); + } + iReservedDriveAccess.Close(); + + + // Need to free the requests that we own from the close queue + while (iCloseRequestCount > 0) + RequestAllocator::OpenSubFailed(this); + + if (iHandles) + delete iHandles; + + + delete iPath; + iSessionFlagsLock.Close(); + if(iDisconnectRequest) + delete(iDisconnectRequest); + } + +void CSessionFs::CreateL() +// +// Create any additional resources. +// + { + __PRINT1(_L("CSessionFs::CreateL 0x%x"),this); + + iHandles=CFsObjectIx::NewL(); + TInt r = iSessionFlagsLock.CreateLocal(); + User::LeaveIfError(r); + RMessage2 m; + + iDisconnectRequest=new(ELeave) CFsDisconnectRequest; + iDisconnectRequest->Set(m,SessionDisconnectOp,this); + + + } + +TInt CSessionFs::CurrentDrive() +// +// Return the current drive. +// + { + + TInt d; + TInt r=RFs::CharToDrive(Path()[0],d); + __ASSERT_ALWAYS(r==KErrNone,Fault(ESesPathBadDrive)); + return(d); + } + +TInt CSessionFs::CountResources() +// +// Return the number of resources owned by the session +// + { + /* what's this supposed to be doing ?? + TInt count=User::LockedInc(iResourceCount); + User::LockedDec(iResourceCount); + return(count); + */ + + return iResourceCount; // ... because that's all it does. + } + +void CSessionFs::ResourceCountMarkStart() +// +// Mark resources at this point +// + { + iResourceCountMark = CountResources(); + } + +void CSessionFs::ResourceCountMarkEnd(const RMessage2& aMessage) +// +// End resource count and check same as count start +// + { + if (iResourceCountMark!=CountResources()) + { + _LIT(KCategory,"CSessionFs"); + aMessage.Panic(KCategory,ESesFoundResCountHeaven); + } + else + aMessage.Complete(KErrNone); + } + +void CSessionFs::Disconnect(const RMessage2& aMessage) + { + __THRD_PRINT1(_L("CSessionFs::Disconnect() 0x%x"),this); + + iHandles->CloseMainThreadObjects(); + iDisconnectRequest->SetMessage((RMessage2&)aMessage); + + iDisconnectRequest->Dispatch(); + } + + +TUint CSessionFs::Reserved(TInt aDriveNumber) const + { + TReservedDriveAccess reserved(aDriveNumber); + TInt idx = iReservedDriveAccess.Find(reserved); + if(idx == KErrNotFound) + return 0; + + return iReservedDriveAccess[idx].iReservedSpace; + } + + +TInt CSessionFs::SetReserved(const TInt aDriveNumber, const TInt aReservedValue) + { + TReservedDriveAccess reserved(aDriveNumber, aReservedValue); + TInt idx = iReservedDriveAccess.Find(reserved); + if(idx == KErrNotFound) + return iReservedDriveAccess.InsertInSignedKeyOrder(reserved); + + iReservedDriveAccess[idx].iReservedSpace = aReservedValue; + return KErrNone; + + } + + +TBool CSessionFs::ReservedAccess(TInt aDriveNumber) const + { + TReservedDriveAccess reserved(aDriveNumber); + TInt idx = iReservedDriveAccess.Find(reserved); + return idx == KErrNotFound ? EFalse : iReservedDriveAccess[idx].iReservedAccess; + } + + +void CSessionFs::SetReservedAccess(const TInt aDriveNumber, const TBool aReservedAccess) + { + TReservedDriveAccess reserved(aDriveNumber); + TInt idx = iReservedDriveAccess.Find(reserved); + if(idx != KErrNotFound) + iReservedDriveAccess[idx].iReservedAccess = aReservedAccess; + } + +TBool CSessionFs::IsChangeNotify() + { + return TestSessionFlags(EFsSessionNotifyChange); + } + + +TBool CSessionFs::TestSessionFlags(TUint32 aFlags) + { + iSessionFlagsLock.Wait(); + TBool b = (iSessionFlags & aFlags) == aFlags; + iSessionFlagsLock.Signal(); + return(b); + } + + +void CSessionFs::SetSessionFlags(TUint32 aBitsToSet, TUint32 aBitsToClear) + { + iSessionFlagsLock.Wait(); + + iSessionFlags &= ~aBitsToClear; + iSessionFlags |= aBitsToSet; + + iSessionFlagsLock.Signal(); + } + +void CSessionFs::CloseRequestCountInc() + { + iSessionFlagsLock.Wait(); + iCloseRequestCount++; + iSessionFlagsLock.Signal(); + } + +void CSessionFs::CloseRequestCountDec() + { + iSessionFlagsLock.Wait(); + iCloseRequestCount--; + iSessionFlagsLock.Signal(); + } + +// +// Start resource count +// +TInt TFsResourceCountMarkStart::DoRequestL(CFsRequest* aRequest) + { + aRequest->Session()->ResourceCountMarkStart(); + return(KErrNone); + } + +TInt TFsResourceCountMarkStart::Initialise(CFsRequest* /*aRequest*/) + { + return KErrNone; + } + + +// +// Check for resource heaven +// +TInt TFsResourceCountMarkEnd::DoRequestL(CFsRequest* aRequest) + { + aRequest->Session()->ResourceCountMarkEnd(aRequest->Message()); + return(KErrNone); + } + +TInt TFsResourceCountMarkEnd::Initialise(CFsRequest* /*aRequest*/) + { + return KErrNone; + } + + +// +// Return the number of resources owned by the session +// +TInt TFsResourceCount::DoRequestL(CFsRequest* aRequest) + { + TInt resCount=aRequest->Session()->CountResources(); + TPckgC pckg(resCount); + aRequest->WriteL(KMsgPtr0,pckg); + return(KErrNone); + } + +TInt TFsResourceCount::Initialise(CFsRequest* /*aRequest*/) + { + return KErrNone; + } + + +// +// Set iNotifyUser +// +void CSessionFs::SetNotifyUser(TBool aNotification) + { + if(aNotification) + { + SetSessionFlags(EFsSessionNotifyUser, 0); + } + else + { + SetSessionFlags(0, EFsSessionNotifyUser); + } + } + +// +// Get iNotifyUser +// +TBool CSessionFs::GetNotifyUser() + { + return TestSessionFlags(EFsSessionNotifyUser); + } + +// +// Notify the user of any read or write failure +// +TInt TFsSetNotifyUser::DoRequestL(CFsRequest* aRequest) + { + TBool notification=aRequest->Message().Int0(); + aRequest->Session()->SetNotifyUser(notification); + return(KErrNone); + } + +TInt TFsSetNotifyUser::Initialise(CFsRequest* /*aRequest*/) + { + return KErrNone; + } + + +// +// Notify the user of any read or write failure +// +TInt TFsGetNotifyUser::DoRequestL(CFsRequest* aRequest) + { + TBool notification=aRequest->Session()->GetNotifyUser(); + TPtrC8 pA((TUint8*)¬ification,sizeof(TBool)); + aRequest->WriteL(KMsgPtr0,pA); + return(KErrNone); + } + +TInt TFsGetNotifyUser::Initialise(CFsRequest* /*aRequest*/) + { + return KErrNone; + } + + +// +// Get the drive name +// +TInt TFsGetDriveName::DoRequestL(CFsRequest* aRequest) + { + TInt driveNum=aRequest->Drive()->DriveNumber(); + TFileName driveName; + if (TheDriveNames[driveNum]==NULL) + driveName.SetLength(0); + else + driveName=(*TheDriveNames[driveNum]); + aRequest->WriteL(KMsgPtr1,driveName); + return(KErrNone); + } + + +TInt TFsGetDriveName::Initialise(CFsRequest* aRequest) + { + TInt r=ValidateDrive(aRequest->Message().Int0(),aRequest); + return(r); + } + + + +// +// Set the drive name +// +TInt TFsSetDriveName::DoRequestL(CFsRequest* aRequest) + { + TInt driveNum=aRequest->Drive()->DriveNumber(); + TFileName driveName; + aRequest->ReadL(KMsgPtr1,driveName); + +// Validate name - return KErrBadName if it contains illegal characters such as +// * ? / | > < + + TNameChecker checker(driveName); + TText badChar; + if (checker.IsIllegalName(badChar)) + return(KErrBadName); + + TInt len=((driveName.Length()+31)>>5)<<5; // % 32 + if (TheDriveNames[driveNum]==NULL) + TheDriveNames[driveNum]=HBufC::New(len); + else if (TheDriveNames[driveNum]->Des().MaxLength()ReAlloc(len); + if (temp==NULL) + return(KErrNoMemory); + TheDriveNames[driveNum]=temp; + } + if (TheDriveNames[driveNum]==NULL || TheDriveNames[driveNum]->Des().MaxLength()Message().Int0(),aRequest); + if (r!=KErrNone) + return(r); + if (!KCapFsSetDriveName.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("Set Drive Name"))) + return KErrPermissionDenied; + return KErrNone; + } + +TInt FlushCachedFiles(CSessionFs* aSession) + { + TInt retVal = KErrNone; + + aSession->Handles().Lock(); + TInt count = aSession->Handles().Count(); + for (TInt n=0; nHandles()[n]; + if (obj != NULL && obj->UniqueID() == FileShares->UniqueID()) + { + CFileShare* share = (CFileShare*) obj; + if (!share->IsCorrectThread()) + continue; + CFileCB& file=((CFileShare*) obj)->File(); + + CFileCache* fileCache = file.FileCache(); + if (fileCache) + { + retVal = fileCache->FlushDirty(); + if (retVal == CFsRequest::EReqActionBusy) + break; + } + } + } + aSession->Handles().Unlock(); + + return retVal; + } + +TInt TFsFlushDirtyData::DoRequestL(CFsRequest* aRequest) +// +// +// + { + __CHECK_DRIVETHREAD(aRequest->DriveNumber()); + + // Flush all dirty data + TInt r = FlushCachedFiles(aRequest->Session()); + if (r == CFsRequest::EReqActionBusy) + return r; + return KErrNone; + } + +TInt TFsFlushDirtyData::Initialise(CFsRequest* /*aRequest*/) +// +// +// + { + return(KErrNone); + } + + +// Iterate though all file shares owned by this session and cancel any async requests +TInt CancelAsyncRequests(CSessionFs* aSession) + { + TInt retVal = KErrNone; + + aSession->Handles().Lock(); + TInt count = aSession->Handles().Count(); + for (TInt n=0; nHandles()[n]; + if (obj != NULL && obj->UniqueID() == FileShares->UniqueID()) + { + CFileShare* share = (CFileShare*) obj; + if (!share->IsCorrectThread()) + continue; + CFileCB& file=((CFileShare*) obj)->File(); + file.CancelAsyncReadRequest(share, NULL); + } + } + aSession->Handles().Unlock(); + + return retVal; + } + + + +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;iSet(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()); + return(KErrNone); + } + +TInt TFsSetSessionFlags::Initialise(CFsRequest* aRequest) + { + if (!KCapFsPlugin. CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("Set Session Flags"))) + return KErrPermissionDenied; + return KErrNone; + } + +TInt TFsInitialisePropertiesFile::DoRequestL(CFsRequest* aRequest) + { + __PRINT(_L("**TFsInitialisePropertiesFile::DoRequestL**\n")); + TInt err = KErrNone; + TInt leaveErr = KErrNone; + const TBool isRomParam = aRequest->Message().Int2(); + if(isRomParam) + { + const TAny* romAddress = aRequest->Message().Ptr0(); + TBool isInRom = EFalse; + TRAP(leaveErr, User::IsRomAddress(isInRom, const_cast(romAddress))); + if (leaveErr == KErrNone) + { + const TInt length = aRequest->Message().Int1(); + err = isInRom ? F32Properties::Initialise((TInt)romAddress, length) : KErrNotSupported; + } + } + else + { + err = KErrNotSupported; + } + +#ifdef SYMBIAN_ENABLE_FAT_DIRECTORY_OPT + // Create the global cache memory manager for FAT dir cache (and other caches). + // Note: file cache uses its own cache memory manager. + if (CCacheMemoryManagerFactory::CacheMemoryManager() == NULL) + { + TGlobalCacheMemorySettings::ReadPropertiesFile(); + TRAPD(r, CCacheMemoryManagerFactory::CreateL()); + __ASSERT_ALWAYS(r==KErrNone,Fault(ECacheMemoryManagerCreateFailed)); + } +#endif // SYMBIAN_ENABLE_FAT_DIRECTORY_OPT + + // Create the page cache for file caching etc. + TGlobalFileCacheSettings::ReadPropertiesFile(); + if (TGlobalFileCacheSettings::Enabled()) + { + TRAPD(r, CCacheManagerFactory::CreateL()); + __ASSERT_ALWAYS(r==KErrNone,Fault(EFileCacheCreateFailed)); + } + + User::LeaveIfError(leaveErr); + return(err); + } + +TInt TFsInitialisePropertiesFile::Initialise(CFsRequest* aRequest) + { + if (!KCapDiskAdmin. CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("Initialise Property File"))) + { + return(KErrPermissionDenied); + } + + if (aRequest->Message().SecureId() != KEstartUidValue) + { + return(KErrPermissionDenied); + } + + aRequest->SetDriveNumber(EDriveZ); + return(KErrNone); + }