userlibandfileserver/fileserver/sfile/sf_file.cpp
changeset 109 b3a1d9898418
parent 90 947f0dc9f7a8
child 152 657f875b013e
--- a/userlibandfileserver/fileserver/sfile/sf_file.cpp	Mon May 03 13:47:38 2010 +0300
+++ b/userlibandfileserver/fileserver/sfile/sf_file.cpp	Fri May 14 17:13:29 2010 +0300
@@ -1830,26 +1830,13 @@
 		// check if an attempt is made to change the share mode to EFileShareExclusive
 		// while the file has multiple readers
 	if (newMode == EFileShareExclusive && (currentMode & KFileShareMask) != EFileShareExclusive)
-		{ 
-		// Check no other CFileCB is reading the file.
-		FileShares->Lock();
-		TInt count=FileShares->Count();
-		TBool found=EFalse;
-		while(count--)
-			{
-			CFileShare* fileShare=(CFileShare*)(*FileShares)[count];
-			if (&fileShare->File()==&share->File())
-				{
-				if (found)
-					{
-					FileShares->Unlock();
-					return(KErrAccessDenied);
-					}
-				found=ETrue;
-				}
-			}
-		FileShares->Unlock();
+		{
+		// Check that this is the file's only fileshare/client
+		TDblQue<CFileShare>& aShareList = (&share->File())->FileShareList();
+		if (!(aShareList.IsFirst(share) && aShareList.IsLast(share)))
+			return KErrAccessDenied;
 		}
+	
 	share->iMode&=~KFileShareMask;
 	share->iMode|=newMode;
 	share->File().SetShare(newMode);
@@ -2451,14 +2438,18 @@
 
 
 void CFileCB::PromoteShare(CFileShare* aShare)
-//
-// Manages share promotion after the share has been added to the FilsShares container.
-//
-//  - Assumes the share has already been validated using ValidateShare()
-//
-//  - The count of promoted shares (ie - non-EFileShareReadersOrWriters) is incremented
-//	  to allow the share mode to be demoted when the last promoted share is closed.
-//
+/**
+	Manages share promotion and checks the EFileSequential file mode
+	after the share has been added to the FileShares container.
+	
+	It assumes the share has already been validated using ValidateShare().
+	
+	The count of promoted shares (ie - non-EFileShareReadersOrWriters) is incremented
+	to allow the share mode to be demoted when the last promoted share is closed.
+	
+	Similarly, the count of non-EFileSequential file modes is incremented to allow
+	the file mode to be enabled when the last non-EFileSequential share is closed.
+ */
 	{
 	TShare reqShare = (TShare)(aShare->iMode & KFileShareMask);
 	if(reqShare != EFileShareReadersOrWriters)
@@ -2466,29 +2457,48 @@
 		iBody->iPromotedShares++;
 		iShare = reqShare;
 		}
+	
+	// If the file mode is not EFileSequential, then disable the 'Sequential' flag
+	if(!(aShare->iMode & EFileSequential))
+		{
+		iBody->iNonSequentialFileModes++;
+		SetSequentialMode(EFalse);
+		__PRINT(_L("CFileCB::PromoteShare - FileSequential mode is off"));
+		}
 	}
 
 
 void CFileCB::DemoteShare(CFileShare* aShare)
-//
-// Manages share demotion after the share has been removed from the FileShares container.
-//
-//  - If the share being removed is not EFileShareReadersOrWriters, then the current
-//	  share mode may require demotion back to EFileShareReadersOrWriters.
-//
-//	- This is determined by the iPromotedShares count, incremented in PromoteShare()
-//
+/**
+	Manages share demotion and checks the EFileSequential file mode
+	after the share has been removed from the FileShares container.
+	
+	If the share being removed is not EFileShareReadersOrWriters, then the current
+	share mode may require demotion back to EFileShareReadersOrWriters.
+	This is determined by the iPromotedShares count, incremented in PromoteShare().
+	
+	Similarly, if the share being removed is non-EFileSequential,
+	then the EFileSequential flag may need to be enabled,
+	which is determined by the iNonSequentialFileModes count.
+ */
 	{
-	if((aShare->iMode & KFileShareMask) != EFileShareReadersOrWriters)
+	if((aShare->iMode & KFileShareMask) != EFileShareReadersOrWriters
+		&& --iBody->iPromotedShares == 0)
 		{
-		if(--iBody->iPromotedShares == 0)
-			{
-			// Don't worry if the file has never been opened as EFileShareReadersOrWriters
-			//  - in this case the CFileCB object is about to be closed anyway.
-			iShare = EFileShareReadersOrWriters;
-			}
+		// Don't worry if the file has never been opened as EFileShareReadersOrWriters
+		//  - in this case the CFileCB object is about to be closed anyway.
+		iShare = EFileShareReadersOrWriters;
 		}
-	__ASSERT_DEBUG(iBody->iPromotedShares>=0,Fault(EFileShareBadPromoteCount));
+	__ASSERT_DEBUG(iBody->iPromotedShares>=0, Fault(EFileShareBadPromoteCount));
+	
+	if(!(aShare->iMode & EFileSequential) && --iBody->iNonSequentialFileModes == 0)
+		{
+		// As above, if the file has never been opened as EFileSequential,
+		// it implies that the CFileCB object is about to be closed anyway.
+		SetSequentialMode(ETrue);
+		__PRINT(_L("CFileCB::PromoteShare - FileSequential mode is enabled"));
+		}
+	__ASSERT_DEBUG(iBody->iNonSequentialFileModes>=0, Fault(EFileShareBadPromoteCount));
 	}
 
 
@@ -2723,7 +2733,8 @@
 
 /**
 Constructor.
-Locks the mount resource to which the shared file resides.
+Locks the mount resource to which the shared file resides
+and adds the share to the file's FileShare List.
 
 @param aFileCB File to be shared.
 */
@@ -2731,12 +2742,14 @@
 	: iFile(aFileCB)
 	{
 	AddResource(iFile->Mount());
+	iFile->AddShare(*this);
 	}
 
 /**
 Destructor.
 
 Frees mount resource to which the shared file resides,
+removes the share from the file's FileShare List,
 removes share status from the shared file and finally closes
 the file.
 */
@@ -2746,6 +2759,7 @@
 	__ASSERT_DEBUG(iCurrentRequest == NULL, Fault(ERequestQueueNotEmpty));
 
 	RemoveResource(iFile->Mount());
+	iShareLink.Deque();
 	iFile->RemoveLocks(this);
 	iFile->DemoteShare(this);
 	iFile->CancelAsyncReadRequest(this, NULL);
@@ -3027,6 +3041,7 @@
 CFileBody::CFileBody(CFileCB* aFileCB, CFileCB::MExtendedFileInterface* aExtendedFileInterface)
   : iFileCB(aFileCB),
 	iExtendedFileInterface(aExtendedFileInterface ? aExtendedFileInterface : this),
+	iShareList(_FOFF(CFileShare,iShareLink)),
 	iSizeHigh(0)
 	{
 	iFairSchedulingLen = TFileCacheSettings::FairSchedulingLen(iFileCB->DriveNumber());
@@ -3586,6 +3601,45 @@
 	}
 
 
+//---------------------------------------------------------------------------------------------------------------------
+/**
+Gets the 'Sequential' mode of the file.
+
+@return	ETrue, if the file is in 'Sequential' mode
+*/
+EXPORT_C TBool CFileCB::IsSequentialMode() const
+	{
+	return iBody->iSequential;
+	}
+
+/**
+Sets the 'Sequential' mode of the file.
+ */
+void CFileCB::SetSequentialMode(TBool aSequential)
+	{
+	iBody->iSequential = aSequential;
+	}
+
+//---------------------------------------------------------------------------------------------------------------------
+/**
+Gets the list containing the shares associated with the file.
+
+@return	The FileShare List
+*/
+TDblQue<CFileShare>& CFileCB::FileShareList() const
+	{
+	return iBody->iShareList;
+	}
+
+/**
+Adds the share to the end of the FileShare List.
+*/
+void CFileCB::AddShare(CFileShare& aFileShare)
+	{
+	iBody->iShareList.AddLast(aFileShare);
+	}
+
+
 //#####################################################################################################################
 //#  TFileShareLock class implementation
 //#####################################################################################################################