persistentstorage/sql/SRC/Server/SqlSrvDriveSpace.cpp
changeset 0 08ec8eefde2f
child 23 26645d81f48d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/persistentstorage/sql/SRC/Server/SqlSrvDriveSpace.cpp	Fri Jan 22 11:06:30 2010 +0200
@@ -0,0 +1,256 @@
+// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "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:
+// Reserving/Accessing/Releasing drive space - CSqlDriveSpace and RSqlDriveSpaceCol classes implementations
+// 
+//
+
+#include "SqlSrvDriveSpace.h"
+#include "SqlPanic.h"
+
+/**
+The amount of the disk space, which will be reserved at the moment of creation of
+each CDriveSpace object.
+It should be enough for the most of "delete" transactions, if they do not require a rollback transaction
+file, bigger than KReservedDiskSpace bytes.
+
+Note: this is the max possible amount, which can be reserved per file session.
+      Look for KMaxSessionDriveReserved constant value.
+
+@internalComponent
+*/
+const TInt KReservedDiskSpace = 64 * 1024;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////    CSqlDriveSpace class    //////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+Standard phase-one factory method for creation of CSqlDriveSpace objects.
+
+@param aFs File session instance
+@param aDrive Drive number
+
+@return A pointer to the created CSqlDriveSpace object.
+
+@leave KErrNoMemory,  Out of memory condition has occured;
+	   RFs::ReserveDriveSpace() return values.
+
+@panic SqlDb 4 In _DEBUG mode if aDrive is invalid
+	   
+@see RFs::ReserveDriveSpace()
+*/
+CSqlDriveSpace* CSqlDriveSpace::NewLC(RFs& aFs, TDriveNumber aDrive)
+    {
+	__SQLASSERT(aDrive >= EDriveA && aDrive <= EDriveZ, ESqlPanicBadArgument);
+    CSqlDriveSpace* self = new (ELeave) CSqlDriveSpace(aFs, aDrive);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    return self;
+    }
+
+/**
+Frees the reserved disk space.
+*/
+CSqlDriveSpace::~CSqlDriveSpace()
+    {
+	SQLDRIVESPACE_INVARIANT();
+	(void)iFs.ReleaseReserveAccess(static_cast <TInt> (iDrive));
+	(void)iFs.ReserveDriveSpace(static_cast <TInt> (iDrive), 0);
+    }
+
+/**
+Gives an access to the already reserved drive space. The method uses RFs::GetReserveAccess()
+for that. RFs::GetReserveAccess() will be called only once, when iGetAccessRefCnt is 0 - 
+this is a shared file session instance.
+
+@leave RFs::GetReserveAccess() return values
+
+@see RFs::GetReserveAccess()
+
+@panic SqlDb 12 In _DEBUG mode if iGetAccessRefCnt < 0
+*/
+void CSqlDriveSpace::GetAccessL()
+	{
+	SQLDRIVESPACE_INVARIANT();
+	//Gets an access only once, there is only one RFs session instance.
+	if(iGetAccessRefCnt == 0)
+		{
+		__SQLLEAVE_IF_ERROR(iFs.GetReserveAccess(static_cast <TInt> (iDrive)));
+		}
+	++iGetAccessRefCnt;
+	SQLDRIVESPACE_INVARIANT();
+	}
+
+/**
+Revokes access to the reserved drive space.
+
+The method calls RFs::ReleaseReserveAccess() only when iGetAccessRefCnt value reaches 0.
+
+@see RFs::ReleaseReserveAccess()
+
+@panic SqlDb 12 In _DEBUG mode if iGetAccessRefCnt < 0
+*/
+void CSqlDriveSpace::ReleaseAccess()
+	{
+	SQLDRIVESPACE_INVARIANT();
+    if(iGetAccessRefCnt == 0)
+        {
+        return;
+        }
+	if(--iGetAccessRefCnt == 0)
+		{
+        //I can't see any reason to bother the caller with errors, when the access to the 
+        //reserved space is revoked.
+		(void)iFs.ReleaseReserveAccess(static_cast <TInt> (iDrive));
+		}
+	SQLDRIVESPACE_INVARIANT();
+	}
+
+/**
+@param aFs File session instance
+@param aDrive Drive number
+
+@panic SqlDb 4 In _DEBUG mode if aDrive is invalid
+*/
+CSqlDriveSpace::CSqlDriveSpace(RFs& aFs, TDriveNumber aDrive) :
+	iFs(aFs),
+	iDrive(aDrive)
+	{
+	__SQLASSERT(aDrive >= EDriveA && aDrive <= EDriveZ, ESqlPanicBadArgument);
+	}
+
+/**
+Standard phase-two construction method for creation of CSqlDriveSpace objects.
+
+It will reserve a predefined amount of a disk space, enough for the most of the
+"delete" transactions, used by the applications.
+
+@leave RFs::ReserveDriveSpace() return values
+
+@see RFs::ReserveDriveSpace()
+*/
+void CSqlDriveSpace::ConstructL()
+    {
+	__SQLLEAVE_IF_ERROR(iFs.ReserveDriveSpace(static_cast <TInt> (iDrive), KReservedDiskSpace));
+	SQLDRIVESPACE_INVARIANT();
+    }
+
+#ifdef _DEBUG
+/**
+CSqlDriveSpace invariant.
+*/
+void CSqlDriveSpace::Invariant() const
+	{
+	__SQLASSERT(iDrive >= EDriveA && iDrive <= EDriveZ, ESqlPanicInternalError);
+	__SQLASSERT(iGetAccessRefCnt >= 0, ESqlPanicMisuse);
+	}
+#endif//_DEBUG
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////    RSqlDriveSpaceCol class    ///////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+RSqlDriveSpaceCol::RSqlDriveSpaceCol() :
+	iFs(NULL)
+	{
+	}
+
+/**
+@param aFs A reference to file session instance
+*/
+void RSqlDriveSpaceCol::Create(RFs& aFs)
+	{
+	iFs = &aFs;
+	SQLDRIVESPACECOL_INVARIANT();
+	}
+
+/**
+The method releases all the resources used by RSqlDriveSpaceCol object, including and 
+reserved drive spaces on all drives in the collection.
+*/
+void RSqlDriveSpaceCol::ResetAndDestroy()
+	{
+	//Forced release of the reserved space
+	for(TInt i=iDriveSpaceCol.Count()-1;i>=0;--i)
+		{
+		delete iDriveSpaceCol[i];
+		}
+	iDriveSpaceCol.Close();
+	iFs = NULL;
+	}
+
+/**
+Searches the collection for a CSqlDriveSpace object holding information about the reserved space on aDrive drive.
+
+@param aDrive Drive number.
+
+@return A pointer to the CSqlDriveSpace object, which handles drive space reservation requests
+        for aDriveNo drive. If there is no such object, the method returns NULL.
+
+@panic SqlDb 4 In _DEBUG mode if aDrive is invalid
+*/
+CSqlDriveSpace* RSqlDriveSpaceCol::Find(TDriveNumber aDrive)
+    {
+	__SQLASSERT(aDrive >= EDriveA && aDrive <= EDriveZ, ESqlPanicBadArgument);
+	SQLDRIVESPACECOL_INVARIANT();
+    for(TInt index=iDriveSpaceCol.Count()-1;index>=0;--index)
+        {
+        if(iDriveSpaceCol[index]->Drive() == aDrive)
+            {
+            return iDriveSpaceCol[index];
+            }
+        }
+	SQLDRIVESPACECOL_INVARIANT();
+    return NULL;
+    }
+
+/**
+The method creates a new CSqlDriveSpace object, adds it to the collection and returns a pointer to it.
+
+@param aDrive Drive number.
+
+@return A pointer to the created CDriveSpace object, which handles drive space 
+        reservation requests for aDriveNo drive.
+        
+@leave System-wide error codes, including KErrNoMemory.
+
+@panic SqlDb 4, In _DEBUG mode if aDrive is invalid.
+@panic SqlDb 12, In _DEBUG mode if a CDriveSpace object already exists for aDrive.
+*/
+CSqlDriveSpace* RSqlDriveSpaceCol::AddL(TDriveNumber aDrive)
+	{
+	__SQLASSERT(aDrive >= EDriveA && aDrive <= EDriveZ, ESqlPanicBadArgument);
+    __SQLASSERT(!Find(aDrive), ESqlPanicMisuse);
+	SQLDRIVESPACECOL_INVARIANT();
+    CSqlDriveSpace* drvSpace = CSqlDriveSpace::NewLC(*iFs, aDrive);
+    __SQLLEAVE_IF_ERROR(iDriveSpaceCol.Append(drvSpace));
+    CleanupStack::Pop(drvSpace);
+	SQLDRIVESPACECOL_INVARIANT();
+    return drvSpace;
+	}
+
+#ifdef _DEBUG
+/**
+RSqlDriveSpaceCol invariant.
+*/
+void RSqlDriveSpaceCol::Invariant() const
+	{
+	__SQLASSERT(iFs != NULL, ESqlPanicInternalError);
+    for(TInt index=iDriveSpaceCol.Count()-1;index>=0;--index)
+    	{
+		iDriveSpaceCol[index]->Invariant();
+    	}
+	}
+#endif//_DEBUG
+