persistentstorage/sql/OsLayer/FileBuf64.cpp
changeset 35 0d6db0a14001
parent 22 a7ba600cb39d
child 41 3256212fc81f
equal deleted inserted replaced
25:63532cdadd44 35:0d6db0a14001
   193 	EFBufPanicNullThis,
   193 	EFBufPanicNullThis,
   194 	EFBufPanicDirty,
   194 	EFBufPanicDirty,
   195 	EFBufPanicNextReadFilePos,
   195 	EFBufPanicNextReadFilePos,
   196 	EFBufPanicNextReadFilePosHits,
   196 	EFBufPanicNextReadFilePosHits,
   197 	EFBufPanicFileBlockSize,			//15
   197 	EFBufPanicFileBlockSize,			//15
       
   198 	EFBufPanicRwDataLength,
   198 	};
   199 	};
   199 
   200 
   200 /**
   201 /**
   201 Helper function used in the implementation of the __FBUF64_ASSERT() macro.
   202 Helper function used in the implementation of the __FBUF64_ASSERT() macro.
   202 In case if the expression in __FBUF64_ASSERT() macro evaluates to false, 
   203 In case if the expression in __FBUF64_ASSERT() macro evaluates to false, 
   247 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   248 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   248 	
   249 	
   249 /**
   250 /**
   250 Initializes RFileBuf64 data members with their default values.
   251 Initializes RFileBuf64 data members with their default values.
   251 
   252 
   252 @param aSize Max file buffer size (capacity) in bytes.
   253 @param aMinCapacity Minimal file buffer size (capacity) in bytes.
   253 
   254 
   254 @panic FBuf64 1 In _DEBUG mode - aSize is 0 or negative.
   255 @panic FBuf64 1 In _DEBUG mode - aMinCapacity is 0 or negative.
   255 */
   256 */
   256 RFileBuf64::RFileBuf64(TInt aSize) :
   257 RFileBuf64::RFileBuf64(TInt aMinCapacity) :
   257 	iCapacity(aSize),
   258 	iCapacity(aMinCapacity),
   258 	iReadAheadSize(RFileBuf64::KDefaultReadAheadSize)
   259 	iReadAheadSize(RFileBuf64::KDefaultReadAheadSize),
   259 	{
   260 	iOptimized(EFalse)
   260 	__FBUF64_ASSERT(aSize > 0, EFBufPanicCapacity);
   261 	{
       
   262 	__FBUF64_ASSERT(aMinCapacity > 0, EFBufPanicCapacity);
   261 	}
   263 	}
   262 
   264 
   263 /**
   265 /**
   264 Initializes the RFileBuf64 object and creates and opens a new file that will be accessed through RFileBuf64 public interface.
   266 Initializes the RFileBuf64 object and creates and opens a new file that will be accessed through RFileBuf64 public interface.
   265 If the file already exists, an error is returned.
   267 If the file already exists, an error is returned.
   471 TInt RFileBuf64::Read(TInt64 aFilePos, TDes8& aDes)
   473 TInt RFileBuf64::Read(TInt64 aFilePos, TDes8& aDes)
   472 	{
   474 	{
   473 	__FBUF64_ASSERT(aFilePos >= 0, EFBufPanicFilePos);
   475 	__FBUF64_ASSERT(aFilePos >= 0, EFBufPanicFilePos);
   474 	__FILEBUF64_INVARIANT();
   476 	__FILEBUF64_INVARIANT();
   475 	aDes.SetLength(0);
   477 	aDes.SetLength(0);
   476 	//1. The output buffer max len is 0
   478 	//0. The output buffer max len is 0
   477 	if(aDes.MaxLength() == 0)
   479 	if(aDes.MaxLength() == 0)
   478 		{
   480 		{
   479 		__FILEBUF64_INVARIANT();
   481 		__FILEBUF64_INVARIANT();
   480 		return KErrNone;	
   482 		return KErrNone;	
   481 		}
   483 		}
   482 	//2. Initialize the "iFileSize" if it is not initialized yet
   484 	//1. Initialize the "iFileSize" if it is not initialized yet
   483 	TInt err = DoFileSize();
   485 	TInt err = DoFileSize();
   484 	if(err != KErrNone)
   486 	if(err != KErrNone)
   485 		{
   487 		{
   486 		__FILEBUF64_INVARIANT();
   488 		__FILEBUF64_INVARIANT();
   487 		return err;	
   489 		return err;	
   488 		}
   490 		}
       
   491 	//2. Optimize the buffer capacity
       
   492 	TInt len = aDes.MaxLength();
       
   493 	if((err = DoSetCapacity(len)) != KErrNone)
       
   494 		{
       
   495 		return err;
       
   496 		}
   489 	//3. Too big "read" request - read directly from the file
   497 	//3. Too big "read" request - read directly from the file
   490 	TInt len = aDes.MaxLength();
       
   491 	if(len > iCapacity)
   498 	if(len > iCapacity)
   492 		{
   499 		{
   493 		if((aFilePos + len) > iFilePos && aFilePos < (iFilePos + iLength))
   500 		if((aFilePos + len) > iFilePos && aFilePos < (iFilePos + iLength))
   494 			{//Write the pending data if the iDirty flag is set, otherwise preserve the buffer content.
   501 			{//Write the pending data if the iDirty flag is set, otherwise preserve the buffer content.
   495 			err = DoFileWrite1(aFilePos);
   502 			err = DoFileWrite1(aFilePos);
   535 					len -= ptr2.Length();
   542 					len -= ptr2.Length();
   536 					}
   543 					}
   537 				break;
   544 				break;
   538 				}
   545 				}
   539 			//The guessed from the previous "file read" operation file pos is correct. Start reading-ahead.
   546 			//The guessed from the previous "file read" operation file pos is correct. Start reading-ahead.
   540 			const TInt KMaxReadFilePosHits = 8;//The max read-ahead buffer size can be up to 2^8 times the iReadAheadSize
   547 			const TInt KMaxReadFilePosHits = 4;//The max read-ahead buffer size can be up to 2^4 times the iReadAheadSize
   541 			if(iNextReadFilePosHits < KMaxReadFilePosHits)
   548 			if(iNextReadFilePosHits < KMaxReadFilePosHits)
   542 				{
   549 				{
   543 				++iNextReadFilePosHits;
   550 				++iNextReadFilePosHits;
   544 				}
   551 				}
   545 			TInt maxReadAhead = iReadAheadSize * (1 << iNextReadFilePosHits);
   552 			TInt maxReadAhead = iReadAheadSize * (1 << iNextReadFilePosHits);
   605 	TInt err = DoFileSize();
   612 	TInt err = DoFileSize();
   606 	if(err != KErrNone)
   613 	if(err != KErrNone)
   607 		{
   614 		{
   608 		__FILEBUF64_INVARIANT();
   615 		__FILEBUF64_INVARIANT();
   609 		return err;	
   616 		return err;	
       
   617 		}
       
   618 	if((err = DoSetCapacity(aData.Length())) != KErrNone)
       
   619 		{
       
   620 		return err;
   610 		}
   621 		}
   611 	DoDiscardBufferedReadData();
   622 	DoDiscardBufferedReadData();
   612 	const TUint8* data = aData.Ptr();
   623 	const TUint8* data = aData.Ptr();
   613 	for(TInt len = aData.Length(); len > 0 && err == KErrNone;)
   624 	for(TInt len = aData.Length(); len > 0 && err == KErrNone;)
   614 		{
   625 		{
  1076 		iNextReadFilePosHits = 0;
  1087 		iNextReadFilePosHits = 0;
  1077 		}
  1088 		}
  1078 	__FILEBUF64_INVARIANT();
  1089 	__FILEBUF64_INVARIANT();
  1079 	}
  1090 	}
  1080 
  1091 
       
  1092 /**
       
  1093 Sets the most appropriate buffer capacity based on the database page size.
       
  1094 The function does a lazy evaluation. The first time the function is called and 
       
  1095 aRwDataLength parameter is recognized to be a database or journal page size, the new (optimal)
       
  1096 buffer capacity is calculated and set. All next DoSetCapacity() calls will detect that the new
       
  1097 capacity is already set and will return KErrNone.
       
  1098 
       
  1099 @param  aRwDataLength The length of the data being read or written.
       
  1100 @return KErrNone The new capacity was set successfully,
       
  1101         KErrNoMemory Out of memory.
       
  1102 */
       
  1103 TInt RFileBuf64::DoSetCapacity(TInt aRwDataLength)
       
  1104 	{
       
  1105 	const TInt KMinPageCount = 4;//the buffer capacity should be at least (KMinPageCount * page size) 
       
  1106 	                             //but not less than the original capacity.
       
  1107 	const TInt KDefaultPageSize = 1024;//The journal header size is equal to 512 bytes, so it is not easy
       
  1108                                        //to detect the 512 bytes page size. 
       
  1109 	
       
  1110 	__FBUF64_ASSERT(aRwDataLength > 0, EFBufPanicRwDataLength);
       
  1111 	__FILEBUF64_INVARIANT();
       
  1112 	if(iOptimized)
       
  1113 		{
       
  1114 		__FILEBUF64_INVARIANT();
       
  1115 		return KErrNone;
       
  1116 		}
       
  1117 	if((aRwDataLength & (aRwDataLength - 1)) != 0 || aRwDataLength < KDefaultPageSize)
       
  1118 		{
       
  1119 		__FILEBUF64_INVARIANT();
       
  1120 		return KErrNone;
       
  1121 		}
       
  1122 	//Here: aRwDataLength is power of 2 and is bigger than the default db page size.
       
  1123 	//aRwDataLength is the size of the db page.
       
  1124 	const TInt pageSize = aRwDataLength;
       
  1125 	TInt cnt = iCapacity / pageSize;//how many pages can fit in the buffer now
       
  1126 	TInt pageCount = Max(cnt, KMinPageCount);//the number of pages that should fit in the new buffer
       
  1127 	TInt newBufCapacity = pageCount * pageSize;
       
  1128 	if(newBufCapacity != iCapacity)
       
  1129 		{
       
  1130 		TUint8* newBase = static_cast <TUint8*> (User::ReAlloc(iBase, newBufCapacity));
       
  1131 		if(!newBase)
       
  1132 			{
       
  1133 			__FILEBUF64_INVARIANT();
       
  1134 			return KErrNoMemory;
       
  1135 			}
       
  1136 		iBase = newBase;
       
  1137 		iCapacity = newBufCapacity;
       
  1138 		//Adjust the initial read-ahead size to be multiple of the page size.
       
  1139 		if((iReadAheadSize % pageSize) != 0)
       
  1140 			{
       
  1141 			TInt q = iReadAheadSize / pageSize;
       
  1142 			iReadAheadSize = q != 0 ? pageSize * q : pageSize;
       
  1143 			}
       
  1144 		}
       
  1145 	iOptimized = ETrue;
       
  1146 	__FILEBUF64_INVARIANT();
       
  1147 	return KErrNone;
       
  1148 	}
       
  1149 
  1081 #ifdef _DEBUG
  1150 #ifdef _DEBUG
  1082 
  1151 
  1083 /**
  1152 /**
  1084 RFileBuf64 invariant. Called in _DEBUG mode at the beginning and before the end of every RFileBuf64 method
  1153 RFileBuf64 invariant. Called in _DEBUG mode at the beginning and before the end of every RFileBuf64 method
  1085 (except the init/destroy methods).
  1154 (except the init/destroy methods).
  1091 @panic FBuf64   4 In _DEBUG mode - negative iFilePos value.
  1160 @panic FBuf64   4 In _DEBUG mode - negative iFilePos value.
  1092 @panic FBuf64   5 In _DEBUG mode - set but negative iFileSize value.
  1161 @panic FBuf64   5 In _DEBUG mode - set but negative iFileSize value.
  1093 @panic FBuf64   6 In _DEBUG mode - null file handle (the RFile64 object is not created or already destroyed).
  1162 @panic FBuf64   6 In _DEBUG mode - null file handle (the RFile64 object is not created or already destroyed).
  1094 @panic FBuf64  13 In _DEBUG mode - set but negative iNextReadFilePos value.
  1163 @panic FBuf64  13 In _DEBUG mode - set but negative iNextReadFilePos value.
  1095 @panic FBuf64  14 In _DEBUG mode - negative iNextReadFilePosHits value.
  1164 @panic FBuf64  14 In _DEBUG mode - negative iNextReadFilePosHits value.
  1096 @panic FBuf64  15 In _DEBUG mode - iReadAheadSize is negative or is not power of two.
  1165 @panic FBuf64  15 In _DEBUG mode - iReadAheadSize is negative or is bigger than iCapacity.
  1097 */
  1166 */
  1098 void RFileBuf64::Invariant() const
  1167 void RFileBuf64::Invariant() const
  1099 	{
  1168 	{
  1100 	__FBUF64_ASSERT(this != 0, EFBufPanicNullThis);
  1169 	__FBUF64_ASSERT(this != 0, EFBufPanicNullThis);
  1101 	__FBUF64_ASSERT(iCapacity > 0, EFBufPanicCapacity);
  1170 	__FBUF64_ASSERT(iCapacity > 0, EFBufPanicCapacity);
  1104 	__FBUF64_ASSERT(iFilePos >= 0, EFBufPanicFilePos);
  1173 	__FBUF64_ASSERT(iFilePos >= 0, EFBufPanicFilePos);
  1105 	__FBUF64_ASSERT(iFileSize == KFileSizeNotSet || iFileSize >= 0, EFBufPanicFileSize);
  1174 	__FBUF64_ASSERT(iFileSize == KFileSizeNotSet || iFileSize >= 0, EFBufPanicFileSize);
  1106 	__FBUF64_ASSERT(iFile.SubSessionHandle() != 0, EFBufPanicFileHandle);
  1175 	__FBUF64_ASSERT(iFile.SubSessionHandle() != 0, EFBufPanicFileHandle);
  1107 	__FBUF64_ASSERT(iNextReadFilePos == KNextReadFilePosNotSet || iNextReadFilePos >= 0, EFBufPanicNextReadFilePos);
  1176 	__FBUF64_ASSERT(iNextReadFilePos == KNextReadFilePosNotSet || iNextReadFilePos >= 0, EFBufPanicNextReadFilePos);
  1108 	__FBUF64_ASSERT(iNextReadFilePosHits >= 0, EFBufPanicNextReadFilePosHits);
  1177 	__FBUF64_ASSERT(iNextReadFilePosHits >= 0, EFBufPanicNextReadFilePosHits);
  1109 	__FBUF64_ASSERT(iReadAheadSize > 0 && (iReadAheadSize & (iReadAheadSize - 1)) == 0, EFBufPanicFileBlockSize);
  1178 	__FBUF64_ASSERT(iReadAheadSize > 0, EFBufPanicFileBlockSize);
  1110 	}
  1179 	}
  1111 	
  1180 	
  1112 #endif
  1181 #endif