persistentstorage/dbms/sdbms/Sd_DriveSpace.cpp
changeset 0 08ec8eefde2f
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Reserving/Accessing/Releasing drive space - CDriveSpace, RDriveSpaceCol, CDbsSessDriveSpace
       
    15 // classes implementations
       
    16 // 
       
    17 //
       
    18 
       
    19 #include "U32STD.H"
       
    20 #include "Sd_DriveSpace.h"
       
    21 
       
    22 /**
       
    23 That's the amount of the disk space, which will be reserved at the momemnt of creation of
       
    24 each CDriveSpace object.
       
    25 It should be enough for the most of the "delete" transactions, used by the applications.
       
    26 @internalComponent
       
    27 */
       
    28 const TInt KReservedDiskSpace = 64 * 1024;
       
    29 
       
    30 /////////////////////////////////////////////////////////////////////////////////////////////
       
    31 //CDriveSpace class 
       
    32 
       
    33 /**
       
    34 Grants access to the already reserved drive space. The method uses RFs::GetReserveAccess()
       
    35 for that. RFs::GetReserveAccess() will be called only once, when iGrantAccessRefCnt is 0 - 
       
    36 this is a shared file session instance.
       
    37 @leave RFs::GetReserveAccess() return values
       
    38 @see RFs::GetReserveAccess()
       
    39 @panic In debug mode there will be a panic with the line number as an error code if (iGrantAccessRefCnt < 0)
       
    40 */
       
    41 void CDriveSpace::GrantAccessL()
       
    42 	{
       
    43 	__ASSERT(iGrantAccessRefCnt >= 0);
       
    44 	//Grant the access only once, there is only one RFs session instance.
       
    45 	if(iGrantAccessRefCnt == 0)
       
    46 		{
       
    47 		__LEAVE_IF_ERROR(iFs.GetReserveAccess(static_cast <TInt> (iDrive)));
       
    48 		}
       
    49 	++iGrantAccessRefCnt;
       
    50 	}
       
    51 
       
    52 /**
       
    53 Revokes access to the reserved drive space.
       
    54 The method calls RFs::ReleaseReserveAccess() only when iGrantAccessRefCnt value reaches 0.
       
    55 @see RFs::ReleaseReserveAccess()
       
    56 @panic In debug mode there will be a panic with the line number as an error code if (iGrantAccessRefCnt <= 0)
       
    57 */
       
    58 void CDriveSpace::ReleaseAccess()
       
    59 	{
       
    60 	__ASSERT(iGrantAccessRefCnt > 0);
       
    61     if(iGrantAccessRefCnt == 0)
       
    62         {
       
    63         return;
       
    64         }
       
    65 	if(--iGrantAccessRefCnt == 0)
       
    66 		{
       
    67         //I can't see any reason to bother the caller with errors, when the access to the 
       
    68         //reserved space is revoked.
       
    69 		(void)iFs.ReleaseReserveAccess(static_cast <TInt> (iDrive));
       
    70 		}
       
    71 	}
       
    72 
       
    73 /**
       
    74 Standard phase-one factory method for creation of CDriveSpace objects.
       
    75 @param aFs File session instance
       
    76 @param aDrive Drive number
       
    77 @return A pointer to the created CDriveSpace object.
       
    78 @leave KErrNoMemory Out of memory
       
    79 @leave RFs::ReserveDriveSpace() return values
       
    80 @see RFs::ReserveDriveSpace()
       
    81 */
       
    82 CDriveSpace* CDriveSpace::NewLC(RFs& aFs, TDriveNumber aDrive)
       
    83     {
       
    84     CDriveSpace* self = new (ELeave) CDriveSpace(aFs, aDrive);
       
    85     CleanupStack::PushL(self);
       
    86     self->ConstructL();
       
    87     return self;
       
    88     }
       
    89 
       
    90 /**
       
    91 @param aFs File session instance
       
    92 @param aDrive Drive number
       
    93 @panic In debug mode there will be a panic with the line number as an error code if 
       
    94        (iDrive value is not between EDriveA and EDriveZ)
       
    95 */
       
    96 CDriveSpace::CDriveSpace(RFs& aFs, TDriveNumber aDrive) :
       
    97 	iFs(aFs),
       
    98 	iDrive(aDrive)
       
    99 	{
       
   100 	__ASSERT(iDrive >= EDriveA && iDrive <= EDriveZ);
       
   101 	}
       
   102 
       
   103 /**
       
   104 Frees the reserved disk space.
       
   105 @panic In debug mode there will be a panic with the line number as an error code if 
       
   106        (iGrantAccessRefCnt != 0)
       
   107 */
       
   108 CDriveSpace::~CDriveSpace()
       
   109     {
       
   110 	__ASSERT(iGrantAccessRefCnt == 0);
       
   111     if(iGrantAccessRefCnt > 0)
       
   112         {
       
   113 		(void)iFs.ReleaseReserveAccess(static_cast <TInt> (iDrive));
       
   114         }
       
   115 	(void)iFs.ReserveDriveSpace(static_cast <TInt> (iDrive), 0);
       
   116     }
       
   117 
       
   118 /**
       
   119 Standard phase-two construction method for creation of CDriveSpace objects.
       
   120 It will reserve a predefined amount of a disk space, enough for the most of the
       
   121 "delete" transactions, used by the applications.
       
   122 @leave RFs::ReserveDriveSpace() return values
       
   123 @see RFs::ReserveDriveSpace()
       
   124 */
       
   125 void CDriveSpace::ConstructL()
       
   126     {
       
   127 	__LEAVE_IF_ERROR(iFs.ReserveDriveSpace(static_cast <TInt> (iDrive), KReservedDiskSpace));
       
   128     }
       
   129 
       
   130 /////////////////////////////////////////////////////////////////////////////////////////////
       
   131 //RDriveSpaceCol class 
       
   132 
       
   133 /**
       
   134 @param aFs File session instance
       
   135 */
       
   136 RDriveSpaceCol::RDriveSpaceCol(RFs& aFs) :
       
   137 	iFs(aFs)
       
   138 	{
       
   139 	}
       
   140 
       
   141 /**
       
   142 The method releases all the resources used by RDriveSpaceCol object, including and 
       
   143 reserved drive spaces on all drives in the collection.
       
   144 */
       
   145 void RDriveSpaceCol::Close()
       
   146 	{
       
   147 	//Forced release of the reserved space
       
   148 	for(TInt i=iDriveSpaceCol.Count()-1;i>=0;--i)
       
   149 		{
       
   150 		delete iDriveSpaceCol[i];
       
   151 		}
       
   152 	iDriveSpaceCol.Close();
       
   153 	}
       
   154 
       
   155 /**
       
   156 The method returns a pointer to the CDriveSpace object, which handles all drive space
       
   157 requests, related to a particular drive.
       
   158 @param aDrive Drive number.
       
   159 @return A pointer to the CDriveSpace object, which handles drive space reservation requests
       
   160         for aDriveNo drive. If there is no such object, the method returns NULL.
       
   161 */
       
   162 CDriveSpace* RDriveSpaceCol::Find(TDriveNumber aDrive)
       
   163     {
       
   164     for(TInt index=iDriveSpaceCol.Count()-1;index>=0;--index)
       
   165         {
       
   166         if(iDriveSpaceCol[index]->iDrive == aDrive)
       
   167             {
       
   168             return iDriveSpaceCol[index];
       
   169             }
       
   170         }
       
   171     return NULL;
       
   172     }
       
   173 
       
   174 /**
       
   175 The method creates a new CDriveSpace object, adds it to the collection and 
       
   176 returns a pointer to it.
       
   177 @param aDrive Drive number.
       
   178 @return A pointer to the created CDriveSpace object, which handles drive space 
       
   179         reservation requests for aDriveNo drive.
       
   180 @leave System-wide error codes, including KErrNoMemory.
       
   181 @panic In debug mode there will be a panic with the line number as an error code if 
       
   182        a CDriveSpace object already exists for aDrive.
       
   183 */
       
   184 CDriveSpace* RDriveSpaceCol::CreateAddL(TDriveNumber aDrive)
       
   185 	{
       
   186     __ASSERT(!Find(aDrive));
       
   187     CDriveSpace* drvSpace = CDriveSpace::NewLC(iFs, aDrive);
       
   188     __LEAVE_IF_ERROR(iDriveSpaceCol.Append(drvSpace));
       
   189     CleanupStack::Pop(drvSpace);
       
   190     return drvSpace;
       
   191 	}
       
   192 
       
   193 /////////////////////////////////////////////////////////////////////////////////////////////
       
   194 //TDriveSpaceRq class 
       
   195 
       
   196 /**
       
   197 @param aDriveSpace A reference to the CDriveSpace object, which handles the reservation requests
       
   198                    for a particular drive.
       
   199 */
       
   200 CDbsSessDriveSpace::TDriveSpaceRq::TDriveSpaceRq(CDriveSpace& aDriveSpace) :
       
   201     iDriveSpace(aDriveSpace),
       
   202     iReserved(0),
       
   203     iAccessGranted(0)
       
   204     {
       
   205     }
       
   206 
       
   207 /////////////////////////////////////////////////////////////////////////////////////////////
       
   208 //CDbsSessDriveSpace class 
       
   209 
       
   210 /**
       
   211 Standard phase-one factory method for creation of CDbsSessDriveSpace objects.
       
   212 @param aDriveSpaceCol A reference to the RDriveSpaceCol collection - there should be only one
       
   213                       per DBMS server.
       
   214 @return A pointer to the created CDbsSessDriveSpace object.
       
   215 @leave KErrNoMemory Out of memory
       
   216 */
       
   217 CDbsSessDriveSpace* CDbsSessDriveSpace::NewL(RDriveSpaceCol& aDriveSpaceCol)
       
   218     {
       
   219     CDbsSessDriveSpace* self = new (ELeave) CDbsSessDriveSpace(aDriveSpaceCol);
       
   220     return self;
       
   221     }
       
   222 
       
   223 /**
       
   224 @param aDriveSpaceCol A reference to the RDriveSpaceCol collection - there should be only one
       
   225                       per DBMS server.
       
   226 */
       
   227 CDbsSessDriveSpace::CDbsSessDriveSpace(RDriveSpaceCol& aDriveSpaceCol) :
       
   228     iDriveSpaceCol(aDriveSpaceCol)
       
   229     {
       
   230     }
       
   231 
       
   232 /**
       
   233 Releases the allocated resources, which means the CDriveSpace::ReleaseAccess()
       
   234 will be called if TDriveSpaceRq::iAccessGranted for the related drive is set.
       
   235 */
       
   236 CDbsSessDriveSpace::~CDbsSessDriveSpace()
       
   237     {
       
   238     for(TInt i=iDriveSpaceRqCol.Count()-1;i>=0;--i)
       
   239         {
       
   240         TDriveSpaceRq& rq = iDriveSpaceRqCol[i];
       
   241         if(rq.iAccessGranted)
       
   242             {
       
   243             rq.iDriveSpace.ReleaseAccess();
       
   244             }
       
   245         //That's all!
       
   246         //rq.iDriveSpace object shall not be destroyed or the reserved disk space - freed!
       
   247         //It will be freed at the DBMS server shutdown.
       
   248         }//end of: for(TInt i=iDriveSpaceRqCol.Count()-1;i>=0;--i)
       
   249     iDriveSpaceRqCol.Close();
       
   250     }
       
   251 
       
   252 /**
       
   253 The method reserves the requested amount of disk space.
       
   254 Because it is a shared file session between all DBMS sessions, a predefined amount of
       
   255 disk space per drive will be reserved at the moment of the first request made by some of
       
   256 the DBMS sessions. All the requests after the first (for a particular disk drive) will
       
   257 be completed successfully without actually reserving a disk space. 
       
   258 Only the state of the related TDriveSpaceRq object will be updated to make it possible to
       
   259 control reservation/freeing requests.
       
   260 @param aDrive Drive number to reserve space on.
       
   261 @leave KErrNoMemory Out of memory
       
   262 @leave KErrInUse This DBMS session has already reserved a disk space.
       
   263 @leave RFs::ReserveDriveSpace() return values
       
   264 @see RFs::ReserveDriveSpace()
       
   265 */
       
   266 void CDbsSessDriveSpace::ReserveL(TDriveNumber aDrive)
       
   267     {
       
   268     TDriveSpaceRq& rq = GetL(aDrive);
       
   269     if(rq.iReserved || rq.iAccessGranted)
       
   270         {
       
   271         //This DBMS session already reserved a disk space (or even has an access to it).
       
   272         //The DBMS session has to free it and then can re-reserve it again.
       
   273         __LEAVE(KErrInUse);
       
   274         }
       
   275     rq.iReserved = 1; //CDriveSpace object reserves a predefined amount of disk space at
       
   276                       //at the moment of its creation, so just set rq.iReserved to non-zero,
       
   277                       //indicating that this session has reserved a disk space.
       
   278     }
       
   279 
       
   280 /**
       
   281 The method frees the reserved by the DBMS session disk space.
       
   282 The actual implementation won't free the reserved disk space. This will happen at the moment of
       
   283 the destruction of the related CDriveSpace object for aDrive drive.
       
   284 The method just updates the state of the related TDriveSpaceRq object to make it possible to
       
   285 control reservation/freeing requests.
       
   286 @param aDrive Drive number, which reserved space has to be freed.
       
   287 @panic In debug mode there will be a panic with the line number as an error code if 
       
   288        there is no TDriveSpaceRq object for aDrive. 
       
   289 @panic In debug mode there will be a panic with the line number as an error code if 
       
   290        the reserved disk space is granted but not released.
       
   291 @panic In debug mode there will be a panic with the line number as an error code if 
       
   292        there is no reserved disk space for aDrive.
       
   293 */
       
   294 void CDbsSessDriveSpace::Free(TDriveNumber aDrive)
       
   295     {
       
   296     TDriveSpaceRq* rq = Find(aDrive);
       
   297     __ASSERT(rq);//Probably an attempt to free non-reserved disk space.
       
   298     __ASSERT(!rq->iAccessGranted);//An attempt to free reserved and granted disk space.
       
   299     __ASSERT(rq->iReserved);//Probably an attempt to free non-reserved disk space.
       
   300     if(rq)
       
   301         {
       
   302         rq->iReserved = 0;//Set it to 0, without actually freeing the reserved disk space.
       
   303                           //It is shared between all DBMS sessions.
       
   304         }
       
   305     }
       
   306 
       
   307 /**
       
   308 Gets an access to the reserved drive space.
       
   309 @param aDriveNo Drive number with a reserved disk space, an access to which is requested
       
   310 @leave KErrArgument There is no reserved disk space on aDrive.
       
   311 @leave KErrInUse An access to the reserved space has already been granted.
       
   312 @leave RFs::GetReserveAccess() return values
       
   313 @see RFs::GetReserveAccess()
       
   314 */
       
   315 void CDbsSessDriveSpace::GrantAccessL(TDriveNumber aDrive)
       
   316     {
       
   317     TDriveSpaceRq* rq = Find(aDrive);
       
   318     if(!rq)
       
   319         {//Probably an attempt to get an access to a non-reserved disk space.
       
   320         __LEAVE(KErrArgument);
       
   321         }
       
   322     if(!rq->iReserved)
       
   323         {//Probably an attempt to get an access to a non-reserved disk space.
       
   324         __LEAVE(KErrArgument);
       
   325         }
       
   326     if(rq->iAccessGranted)
       
   327         {//Probably an attempt to get an access twice to the reserved disk space.
       
   328         __LEAVE(KErrInUse);
       
   329         }
       
   330     rq->iDriveSpace.GrantAccessL();
       
   331     rq->iAccessGranted = 1;
       
   332     }
       
   333 
       
   334 /**
       
   335 Releases the access to the reserved drive space.
       
   336 @param aDriveNo Drive number with a reserved disk space, the access to which has to be released.
       
   337 @panic In debug mode there will be a panic with the line number as an error code if 
       
   338        there is no TDriveSpaceRq object for aDrive. 
       
   339 @panic In debug mode there will be a panic with the line number as an error code if 
       
   340        there is no reserved disk space for aDrive. 
       
   341 @panic In debug mode there will be a panic with the line number as an error code if 
       
   342        there is no granted access to the reserved disk space. 
       
   343 */
       
   344 void CDbsSessDriveSpace::ReleaseAccess(TDriveNumber aDrive)
       
   345     {
       
   346     TDriveSpaceRq* rq = Find(aDrive);
       
   347     __ASSERT(rq);//Probably an attempt to release the access to a non-reserved disk space.
       
   348     if(rq)
       
   349         {
       
   350         __ASSERT(rq->iReserved);//Probably an attempt to release the access to a non-reserved disk space.
       
   351         __ASSERT(rq->iAccessGranted);//Probably an attempt to grant an access to the reserved disk spave twice.
       
   352         if(rq->iReserved && rq->iAccessGranted)
       
   353             {
       
   354             rq->iDriveSpace.ReleaseAccess();
       
   355             rq->iAccessGranted = 0;
       
   356             }
       
   357         }
       
   358     }
       
   359 
       
   360 /**
       
   361 The method searches iDriveSpaceRqCol collection for TDriveSpaceRq object, which drive number
       
   362 is the same as aDrive parameter.
       
   363 @param aDrive Drive number
       
   364 @return A pointer to the TDriveSpaceRq object, which has the same drive number
       
   365         NULL, if there is no such opject.
       
   366 */
       
   367 CDbsSessDriveSpace::TDriveSpaceRq* CDbsSessDriveSpace::Find(TDriveNumber aDrive)
       
   368     {
       
   369     for(TInt index=iDriveSpaceRqCol.Count()-1;index>=0;--index)
       
   370         {
       
   371         if(iDriveSpaceRqCol[index].iDriveSpace.Drive() == aDrive)
       
   372             {
       
   373             return &iDriveSpaceRqCol[index];
       
   374             }
       
   375         }
       
   376     return NULL;
       
   377     }
       
   378 
       
   379 /**
       
   380 The method creates a new TDriveSpaceRq object with aDrive as a drive number and adds it
       
   381 to iDriveSpaceRqCol collection.
       
   382 @param aDrive Drive number
       
   383 @return A reference to the created TDriveSpaceRq object
       
   384 @leave System-wide error codes, including KErrNoMemory.
       
   385 @panic In debug mode there will be a panic with the line number as an error code if 
       
   386        there is an existing TDriveSpaceRq object for aDrive. 
       
   387 */
       
   388 CDbsSessDriveSpace::TDriveSpaceRq& CDbsSessDriveSpace::CreateAddL(TDriveNumber aDrive)
       
   389     {
       
   390     __ASSERT(!Find(aDrive));
       
   391     //Check iDriveSpaceCol collection if there is a CDriveSpace object, which was already
       
   392     //created for aDrive.
       
   393     CDriveSpace* drvSpace = iDriveSpaceCol.Find(aDrive);
       
   394     if(!drvSpace)
       
   395         {//There is no CDriveSpace object for aDrive. It has to be created.
       
   396         drvSpace = iDriveSpaceCol.CreateAddL(aDrive);
       
   397         }
       
   398     __ASSERT(drvSpace);
       
   399     //Now we have the related CDriveSpace object for aDrive.
       
   400     //Create new TDriveSpaceRq object and add it to iDriveSpaceRqCol collection.
       
   401     __LEAVE_IF_ERROR(iDriveSpaceRqCol.Append(TDriveSpaceRq(*drvSpace)));
       
   402     //If Append() call fails, then we have CDriveSpace object created but not deleted.
       
   403     //It is not a problem, because CDriveSpace object was added to iDriveSpaceCol and will
       
   404     //be destroyed when iDriveSpaceCol is destroyed.
       
   405     return iDriveSpaceRqCol[iDriveSpaceRqCol.Count() - 1];
       
   406     }
       
   407 
       
   408 /**
       
   409 This method combines the functionality of CDbsSessDriveSpace::Find() and 
       
   410 CDbsSessDriveSpace::CreateAddL() methods.
       
   411 It will search for a TDriveSpaceRq object with the same drive number as aDrive.
       
   412 If such object doesn not exist, it will be created, added to iDriveSpaceRqCol and a reference
       
   413 to it - returned.
       
   414 @param aDrive Drive number
       
   415 @return A reference to the TDriveSpaceRq object, responsible for aDrive drive.
       
   416 @leave System-wide error codes, including KErrNoMemory.
       
   417 @see CDbsSessDriveSpace::Find()
       
   418 @see CDbsSessDriveSpace::CreateAddL()
       
   419 */
       
   420 CDbsSessDriveSpace::TDriveSpaceRq& CDbsSessDriveSpace::GetL(TDriveNumber aDrive)
       
   421     {
       
   422     TDriveSpaceRq* rq = Find(aDrive);
       
   423     return rq ? *rq : CreateAddL(aDrive);
       
   424     }