persistentstorage/sql/OsLayer/os_symbian.cpp
changeset 0 08ec8eefde2f
child 6 5ffdb8f2067f
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     1 // Copyright (c) 2005-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 // The Symbian OS porting layer - single-threaded implementation.
       
    15 // SQLite never accesses the file system and the OS services directly.
       
    16 // SQLite uses for that sqlite3_vfs and sqlite3_file objects.
       
    17 // sqlite3_vfs and sqlite3_file functionality is implemented in this file - 
       
    18 // TVfs and TFileIo classes.
       
    19 // This file is also used for the COsLayerData implementation. A single COslayerData
       
    20 // object is used by the OS porting layer for managing some global data.
       
    21 // 
       
    22 //
       
    23 
       
    24 /**
       
    25  @file
       
    26  @see TVfs
       
    27  @see TFileIo
       
    28 */
       
    29 
       
    30 #ifdef  SQLITE_OS_SYMBIAN
       
    31 
       
    32 //#define _SQLPROFILER // Enable profiling //The same macro has to be enabled in SqlAssert.h file
       
    33 
       
    34 extern "C" 
       
    35 {
       
    36 #include "sqliteInt.h"
       
    37 #include "os.h"
       
    38 }
       
    39 #include "os_common.h"
       
    40 #include "SqliteSymbian.h"
       
    41 #include "FileBuf64.h"
       
    42 #include <e32math.h>
       
    43 #include "UTraceSql.h"
       
    44 #ifdef _SQLPROFILER
       
    45 #include <hal.h>
       
    46 #include "../INC/SqlResourceProfiler.h"
       
    47 #endif
       
    48 
       
    49 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
    50 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
    51 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
    52 
       
    53 /**
       
    54 Panic category - used by asserts in this file (the OS porting layer).
       
    55 
       
    56 @see TPanicCodes
       
    57 
       
    58 @internalComponent
       
    59 */
       
    60 _LIT(KPanicCategory, "Sqlite");
       
    61 
       
    62 /**
       
    63 Panic codes - used by asserts in this file (the OS porting layer).
       
    64 
       
    65 @see KPanicCategory
       
    66 
       
    67 @internalComponent
       
    68 */
       
    69 enum TPanicCodes
       
    70 	{
       
    71 	EPanicNullOsLayerDataPtr	= 1,
       
    72 	EPanicInvalidWAmount 		= 2,
       
    73 	EPanicOffset64bit 			= 3,
       
    74 	EPanicInvalidOpType			=11,
       
    75 	EPanicInvalidFhStr			=12,
       
    76 	EPanicInvalidFhData			=13,
       
    77 	EPanicInvalidArg			=14,
       
    78 	EPanicInvalidRAmount 		=15,
       
    79 	EPanicOsLayerDataExists		=16,
       
    80 	EPanicInvalidDrive			=17,
       
    81 	EPanicInvalidSectorSize		=18,
       
    82 	EPanicInternalError			=19,
       
    83 	EPanicNullDbFilePtr			=20,
       
    84 	EPanicFastCounterFreq		=21
       
    85 	};
       
    86 
       
    87 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
    88 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
    89 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
    90 #ifdef _SQLPROFILER
       
    91 
       
    92     //Profiling counters, defined in SqlSrvResourceprofiler.cpp
       
    93     extern TInt TheSqlSrvProfilerFileRead;
       
    94     extern TInt TheSqlSrvProfilerFileWrite;
       
    95     extern TInt TheSqlSrvProfilerFileSync;
       
    96     extern TInt TheSqlSrvProfilerFileSetSize;
       
    97     
       
    98 #   define  __COUNTER_INCR(counter) ++counter
       
    99 
       
   100 	//////////////////////////////////////////////////////////////////////////////
       
   101 	////////////////////////// File I/O //////////////////////////////////////////
       
   102 	//////////////////////////////////////////////////////////////////////////////
       
   103 	
       
   104 	/**
       
   105 	This enum is used only in _SQLPROFILER mode for tracing the file system calls.
       
   106 	@internalComponent
       
   107 	@see FsCallBrkPt()
       
   108 	*/
       
   109 	enum TFsOpType
       
   110 		{
       
   111 		EFsOpFileCreate,
       
   112 		EFsOpFileOpen,
       
   113 		EFsOpFileClose,
       
   114 		EFsOpFileDelete,
       
   115 		EFsOpFileRead,
       
   116 		EFsOpFileWrite,
       
   117 		EFsOpFileSeek,
       
   118 		EFsOpFileSize,
       
   119 		EFsOpFileSetSize,
       
   120 		EFsOpFileSync,
       
   121 		EFsOpFileDrive,
       
   122 		EFsOpFileAdopt,
       
   123 		EFsOpFsClose,
       
   124 		EFsOpFsConnect,
       
   125 		EFsOpFsGetSystemDrive,
       
   126 		EFsOpFsCreatePrivatePath,
       
   127 		EFsOpFsPrivatePath,
       
   128 		EFsOpFsVolumeIoParam,
       
   129 		EFsOpFsEntry,
       
   130 		EFsOpFsAtt,
       
   131 		EFsOpFileCreateTemp,
       
   132 		EFsOpFileAttach,
       
   133 		//
       
   134 		EFsOpLast
       
   135 		};
       
   136 
       
   137 	TBool   TheFileIoProfileEnabled = EFalse;
       
   138 	TUint32 TheFileOpCounter[EFsOpLast] = {0};
       
   139 	TInt64	TheFileWriteAmount = 0;
       
   140 	TInt64	TheFileReadAmount = 0;
       
   141 			
       
   142 	/**
       
   143 	This function is used only in _SQLPROFILER mode as an appropriate place for:
       
   144 	 	- setting breakpoints for tracing the file system calls;
       
   145 	 	- collection information about the number of the file system calls;
       
   146 	 	
       
   147 	@param aFsOpType A TFsOpType enum item value, identifying the file system operation that will be executed;
       
   148 	@param a1 If the operation is "file read" or "file write" - the amount of data read/written;
       
   149 	
       
   150 	@internalComponent
       
   151 	
       
   152 	@see TFsOpType
       
   153 	*/
       
   154 	void FsCallBrkPt(TInt aFsOpType, TInt a1)
       
   155 		{
       
   156 		__ASSERT_DEBUG(aFsOpType >= 0 && aFsOpType < EFsOpLast, User::Invariant());
       
   157 		if(!TheFileIoProfileEnabled)
       
   158 			{
       
   159 			return;	
       
   160 			}
       
   161 		TFsOpType fsOpType = (TFsOpType)aFsOpType;
       
   162 		++TheFileOpCounter[fsOpType];
       
   163 		if(fsOpType == EFsOpFileWrite)
       
   164 			{
       
   165 			TheFileWriteAmount += a1;
       
   166 			}
       
   167 		else if(fsOpType == EFsOpFileRead)
       
   168 			{
       
   169 			TheFileReadAmount += a1;
       
   170 			}
       
   171 		}
       
   172 		
       
   173 #	define __FS_CALL(aFsOpType, a1) FsCallBrkPt(aFsOpType, a1)
       
   174 
       
   175 	//////////////////////////////////////////////////////////////////////////////
       
   176 	////////////////////////// Heap Stats ////////////////////////////////////////
       
   177 	//////////////////////////////////////////////////////////////////////////////
       
   178 
       
   179 	/**
       
   180 	Memory operation type: alloc, realloc, free. Used during the profiling.
       
   181 	
       
   182 	@internalComponent
       
   183 	*/
       
   184 	enum TMemOpType
       
   185 		{
       
   186 		EMemOpAlloc,
       
   187 		EMemOpRealloc,
       
   188 		EMemOpFree,
       
   189 		//
       
   190 		EMemOpLast
       
   191 		};
       
   192 
       
   193 	TBool   TheMemProfileEnabled = EFalse;//Mem operation call counters and time counters enabled/disabled
       
   194 	TBool   TheMaxAllocProfileEnabled = EFalse;//Max mem allocation enabled/disabled
       
   195 	TUint32 TheMemOpCounter[EMemOpLast] = {0};
       
   196 	TInt64 	TheMemOpTicks[EMemOpLast] = {0};
       
   197 	TInt64 	TheAllocated = 0;
       
   198 	TInt64 	TheFreed = 0;
       
   199 	TInt	TheAllocMax = 0;
       
   200 		
       
   201 	/**
       
   202 	This class is used only in _SQLPROFILER mode as an appropriate place for:
       
   203 	 	- setting breakpoints for tracing the memory allocation/deallocation calls;
       
   204 	 	- collection information about the number of the memory allocation/deallocation calls and the time spent in the calls;
       
   205 	 	
       
   206 	The constructor's parameters are:	 	
       
   207 	 - aOpType A TMemOpType enum item value, identifying the operation that will be executed;
       
   208 	 - aAmt1 The allocated/deallocated size;
       
   209 	 - aAmt2 Used only if a block of memory is reallocated in which case a2 is the old size of the block;
       
   210 	
       
   211 	@internalComponent
       
   212 	
       
   213 	@see TMemOpType
       
   214 	*/
       
   215 	class TMemCallCounter
       
   216 		{
       
   217 	public:			
       
   218 		TMemCallCounter(TMemOpType aOpType, TInt aAmt1, TInt aAmt2) :
       
   219 			iOpType(aOpType),
       
   220 			iStartTicks(0)
       
   221 			{
       
   222 			if(TheMaxAllocProfileEnabled && (iOpType == EMemOpAlloc || iOpType == EMemOpRealloc) && aAmt1 > TheAllocMax)
       
   223 				{
       
   224 				TheAllocMax = aAmt1;	
       
   225 				}
       
   226 			if(TheMemProfileEnabled)
       
   227 				{
       
   228 				++TheMemOpCounter[iOpType];
       
   229 				switch(iOpType)
       
   230 					{
       
   231 					case EMemOpAlloc:
       
   232 						TheAllocated += aAmt1;
       
   233 						break;
       
   234 					case EMemOpRealloc:
       
   235 						TheAllocated += aAmt1;
       
   236 						TheFreed += aAmt2;
       
   237 						break;
       
   238 					case EMemOpFree:
       
   239 						TheFreed += aAmt1;
       
   240 						break;
       
   241 					default:
       
   242 						__ASSERT_DEBUG(0, User::Invariant());
       
   243 						break;
       
   244 					}
       
   245 				iStartTicks = User::FastCounter();
       
   246 				}
       
   247 			}
       
   248 		~TMemCallCounter()
       
   249 			{
       
   250 			if(TheMemProfileEnabled)
       
   251 				{
       
   252 				TInt64 diffTicks = (TInt64)User::FastCounter() - (TInt64)iStartTicks;
       
   253 				if(diffTicks < 0)
       
   254 					{
       
   255 					diffTicks = KMaxTUint + diffTicks + 1;
       
   256 					}
       
   257 				TheMemOpTicks[iOpType] += diffTicks;
       
   258 				}
       
   259 			}
       
   260 	private:
       
   261 		TMemOpType	iOpType;
       
   262 		TUint32 	iStartTicks;
       
   263 		};
       
   264 		
       
   265 #	define __MEM_CALL(aMemOpType, a1, a2) TMemCallCounter memCallCounter(aMemOpType, a1, a2)
       
   266 
       
   267 	//////////////////////////////////////////////////////////////////////////////
       
   268 	////////////////////////// OS layer calls ////////////////////////////////////
       
   269 	//////////////////////////////////////////////////////////////////////////////
       
   270 	
       
   271 	//The OS porting layer call types
       
   272 	enum TOsOpType
       
   273 		{
       
   274 		EOsFileClose,
       
   275 		EOsFileRead,
       
   276 		EOsFileWrite,
       
   277 		EOsFileTruncate,
       
   278 		EOsFileSync,
       
   279 		EOsFileFileSize,
       
   280 		EOsFileLock,
       
   281 		EOsFileUnlock,
       
   282 		EOsFileCheckReservedLock,
       
   283 		EOsFileFileControl,
       
   284 		EOsFileSectorSize,
       
   285 		EOsFileDeviceCharacteristics,
       
   286 		//
       
   287 		EOsVfsOpen,
       
   288 		EOsVfsDelete,
       
   289 		EOsVfsAccess,
       
   290 		EOsVfsFullPathName,
       
   291 		EOsVfsRandomness,
       
   292 		EOsVfsSleep,
       
   293 		EOsVfsCurrentTime,
       
   294 		EOsVfsGetLastError,
       
   295 		//
       
   296 		EOsOpLast
       
   297 		};
       
   298 	
       
   299 	TBool   TheOsProfileEnabled = EFalse;
       
   300 	TUint32 TheOsOpCounter[EOsOpLast] = {0};//Each entry is a counter - how many times specific OS porting layer function has been called
       
   301 	
       
   302 #	define __OS_CALL(aOsOpType, a1, a2) 		\
       
   303 			do									\
       
   304 				{								\
       
   305 				if(TheOsProfileEnabled) 		\
       
   306 					{							\
       
   307 					++TheOsOpCounter[aOsOpType];\
       
   308 					}							\
       
   309 				}								\
       
   310 			while(0)				
       
   311 			
       
   312 	//////////////////////////////////////////////////////////////////////////////
       
   313 	////////////////////////// OS layer timings //////////////////////////////////
       
   314 	//////////////////////////////////////////////////////////////////////////////
       
   315 
       
   316 	TBool  TheOsCallTimeProfileEnabled = EFalse;//If true, the OS porting layer call timings are enabled.
       
   317 	TInt64 TheOsCallTicks[EOsOpLast];//Each entry represents the time in ticks spent in a specific OS porting layer function,
       
   318 									 //disregarding the file type (main or journal)
       
   319 	
       
   320 	TBool  TheOsCallTimeDetailedProfileEnabled = EFalse;//If true, the OS porting layer call details are enabled and for each call an entry will be added to the log file (epocwind.out).
       
   321 	TInt   TheOpCounter = 0;//Operations counter. Each OS porting layer function call increments the counter.
       
   322 	
       
   323 	//Used for storing the OS call details:
       
   324 	// - iType        - on which file the call has been made: main database file - 'M', or journal file - 'J';
       
   325 	// - iIdentifier  - two letters identifying the monitored OS porting layer function;
       
   326 	// - iCallCounter - how many times the monitored OS porting layer function has been called;	
       
   327 	// - iTicksTotal  - the total amount of time in ticks spent in the monitored OS porting layer function;	
       
   328 	// - iBytesTotal  - the total amount of bytes passed to the monitored OS porting layer function (if it is read or write);
       
   329 	struct TOsCallProfile
       
   330 		{
       
   331 		TOsCallProfile(char aType, char aIdentifier[]) :
       
   332 			iType(aType),
       
   333 			iCallCounter(0),
       
   334 			iTicksTotal(0),
       
   335 			iBytesTotal(0)
       
   336 			{
       
   337 			iIdentifier[0] = aIdentifier[0];
       
   338 			iIdentifier[1] = aIdentifier[1];
       
   339 			}
       
   340 		void Zero()
       
   341 			{
       
   342 			iCallCounter = 0;	
       
   343 			iTicksTotal = 0;	
       
   344 			iBytesTotal = 0;
       
   345 			}
       
   346 		char	iType;
       
   347 		char	iIdentifier[2];
       
   348 		TInt	iCallCounter;
       
   349 		TInt64	iTicksTotal;
       
   350 		TInt64	iBytesTotal;
       
   351 		};
       
   352 
       
   353 	//An array of TOsCallProfile entries, each entry keeps the profile of a specifc OS porting layer function, when
       
   354 	//the function was used on the main database file
       
   355 	TOsCallProfile TheOsCallMProfile[EOsOpLast] = 
       
   356 		{
       
   357 		TOsCallProfile('M', "CL"), TOsCallProfile('M', "RD"), TOsCallProfile('M', "WR"), TOsCallProfile('M', "TR"),
       
   358 		TOsCallProfile('M', "SY"), TOsCallProfile('M', "FS"), TOsCallProfile('M', "LK"), TOsCallProfile('M', "UL"),
       
   359 		TOsCallProfile('M', "CL"), TOsCallProfile('M', "FC"), TOsCallProfile('M', "SS"), TOsCallProfile('M', "DC"),
       
   360 		TOsCallProfile('M', "OP"), TOsCallProfile('M', "DE"), TOsCallProfile('M', "AC"), TOsCallProfile('M', "FN"),
       
   361 		TOsCallProfile('M', "RN"), TOsCallProfile('M', "SL"), TOsCallProfile('M', "CT"), TOsCallProfile('M', "LE")
       
   362 		};
       
   363 
       
   364 	//An array of TOsCallProfile entries, each entry keeps the profile of a specifc OS porting layer function, when
       
   365 	//the function was used on the journal file
       
   366 	TOsCallProfile TheOsCallJProfile[EOsOpLast] = 
       
   367 		{
       
   368 		TOsCallProfile('J', "CL"), TOsCallProfile('J', "RD"), TOsCallProfile('J', "WR"), TOsCallProfile('J', "TR"),
       
   369 		TOsCallProfile('J', "SY"), TOsCallProfile('J', "FS"), TOsCallProfile('J', "LK"), TOsCallProfile('J', "UL"),
       
   370 		TOsCallProfile('J', "CL"), TOsCallProfile('J', "FC"), TOsCallProfile('J', "SS"), TOsCallProfile('J', "DC"),
       
   371 		TOsCallProfile('J', "OP"), TOsCallProfile('J', "DE"), TOsCallProfile('J', "AC"), TOsCallProfile('J', "FN"),
       
   372 		TOsCallProfile('J', "RN"), TOsCallProfile('J', "SL"), TOsCallProfile('J', "CT"), TOsCallProfile('J', "LE")
       
   373 		};
       
   374 	
       
   375 	//The main class for the OS porting layer call profiles.
       
   376 	class TOsCallCounter
       
   377 		{
       
   378 	public:
       
   379 		//aOsCallTicksEntryRef - a reference to the related TheOsCallTicks[] entry;
       
   380 		//aProfileRef          - a reference to the related TOsCallProfile object - TheOsCallMProfile[] or TheOsCallJProfile[] entry;
       
   381 		//aOffset              - file offset in bytes;
       
   382 		//aBytes               - amount of bytes to be read/written;
       
   383 		TOsCallCounter(TInt64& aOsCallTicksEntryRef, TOsCallProfile& aOsCallProfileRef, TInt64 aOffset, TInt aBytes) :
       
   384 			iOsCallTicksEntryRef(aOsCallTicksEntryRef),
       
   385 			iOsCallProfileRef(aOsCallProfileRef),
       
   386 			iOffset(aOffset),
       
   387 			iBytes(aBytes)	
       
   388 			{
       
   389 			if(TheOsCallTimeProfileEnabled)
       
   390 				{
       
   391 				iStartTicks = User::FastCounter();
       
   392 				}
       
   393 			}
       
   394 		~TOsCallCounter()
       
   395 			{
       
   396 			if(TheOsCallTimeProfileEnabled)
       
   397 				{
       
   398 				TInt64 diffTicks = (TInt64)User::FastCounter() - (TInt64)iStartTicks;
       
   399 				if(diffTicks < 0)
       
   400 					{
       
   401 					diffTicks = KMaxTUint + diffTicks + 1;
       
   402 					}
       
   403 				iOsCallTicksEntryRef += diffTicks;
       
   404 				if(TheOsCallTimeDetailedProfileEnabled)
       
   405 					{
       
   406 					++TheOpCounter;
       
   407 					++iOsCallProfileRef.iCallCounter;
       
   408 					iOsCallProfileRef.iTicksTotal += diffTicks;
       
   409 					iOsCallProfileRef.iBytesTotal += iBytes;
       
   410 					//                 1    2 3   4  5  6   7   8   9   10
       
   411 					RDebug::Print(_L("'%c','%c%c',%d,%d,%ld,%d,%ld,%ld,%ld\n"), 
       
   412 						iOsCallProfileRef.iType, 			//1
       
   413 						iOsCallProfileRef.iIdentifier[0], 	//2
       
   414 						iOsCallProfileRef.iIdentifier[1],	//3
       
   415 						TheOpCounter, 						//4
       
   416 						iOsCallProfileRef.iCallCounter, 	//5
       
   417 						iOffset, 							//6
       
   418 						iBytes, 							//7
       
   419 						diffTicks, 							//8
       
   420 						iOsCallProfileRef.iBytesTotal, 		//9
       
   421 						iOsCallProfileRef.iTicksTotal);		//10
       
   422 					}
       
   423 				}
       
   424 			}
       
   425 	private:
       
   426 		TInt64&			iOsCallTicksEntryRef;
       
   427 		TOsCallProfile&	iOsCallProfileRef;
       
   428 		TInt64			iOffset;
       
   429 		TInt			iBytes;			
       
   430 		TUint32 		iStartTicks;
       
   431 		};
       
   432 		
       
   433 	inline TOsCallProfile& OsCallProfile(TBool aType, TInt aIndex)
       
   434 		{
       
   435 		return aType ? TheOsCallJProfile[aIndex] : TheOsCallMProfile[aIndex];
       
   436 		}
       
   437 		
       
   438 #	define __OSTIME_COUNTER(aOsCallTicksRef, aOsCallProfileRef, aOffset, aBytes)	TOsCallCounter osCallCounter(aOsCallTicksRef, aOsCallProfileRef, aOffset, aBytes)
       
   439 
       
   440 #else //_SQLPROFILER
       
   441 
       
   442 #   define __COUNTER_INCR(counter) void(0)
       
   443 	
       
   444 #	define __FS_CALL(aFsOpType, a1) void(0)
       
   445 
       
   446 #	define __MEM_CALL(aMemOpType, a1, a2) void(0)
       
   447 
       
   448 #	define __OS_CALL(aOpType, a1, a2) void(0)
       
   449 
       
   450 #	define __OSTIME_COUNTER(aOsCallTicksRef, aOsCallProfileRef, aOffset, aBytes)	void(0)
       
   451 
       
   452 #endif//_SQLPROFILER
       
   453 
       
   454 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   455 /////////////////////       Profiling                          ////////////////////////////////////////////////////////////////
       
   456 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   457 
       
   458 #ifdef _SQLPROFILER
       
   459 
       
   460 const TInt KMicroSecIn1Sec = 1000000;
       
   461 
       
   462 TInt FastCounterFrequency()
       
   463 	{
       
   464 	TInt ticksPerSec = 0;
       
   465 	TInt err = HAL::Get(HAL::EFastCounterFrequency, ticksPerSec);
       
   466 	__ASSERT_ALWAYS(err == KErrNone, User::Panic(KPanicCategory, EPanicFastCounterFreq));
       
   467 	return ticksPerSec;
       
   468 	}
       
   469 
       
   470 TInt sqlite3SymbianProfilerStart(TInt aCounterType)
       
   471 	{
       
   472 	const TSqlResourceProfiler::TSqlCounter KCounterType = static_cast <TSqlResourceProfiler::TSqlCounter> (aCounterType);
       
   473 	switch(KCounterType)
       
   474 		{
       
   475 		case TSqlResourceProfiler::ESqlCounterFileIO:
       
   476 			TheFileIoProfileEnabled = ETrue;
       
   477 			break;
       
   478 		case TSqlResourceProfiler::ESqlCounterOsCall:
       
   479 			TheOsProfileEnabled = ETrue;
       
   480 			break;
       
   481 		case TSqlResourceProfiler::ESqlCounterOsCallTime:
       
   482 			TheOsCallTimeProfileEnabled = ETrue;
       
   483 			break;
       
   484 		case TSqlResourceProfiler::ESqlCounterOsCallDetails:
       
   485 			TheOsCallTimeProfileEnabled = ETrue;
       
   486 			TheOsCallTimeDetailedProfileEnabled = ETrue;
       
   487 			break;
       
   488 		case TSqlResourceProfiler::ESqlCounterMemory:
       
   489 			TheMemProfileEnabled = ETrue;
       
   490 			break;
       
   491 		case TSqlResourceProfiler::ESqlCounterMaxAlloc:
       
   492 			TheMaxAllocProfileEnabled = ETrue;
       
   493 			break;
       
   494 		default:
       
   495 			return KErrNotSupported;
       
   496 		}
       
   497 	return KErrNone;
       
   498 	}
       
   499 	
       
   500 TInt sqlite3SymbianProfilerStop(TInt aCounterType)
       
   501 	{
       
   502 	const TSqlResourceProfiler::TSqlCounter KCounterType = static_cast <TSqlResourceProfiler::TSqlCounter> (aCounterType);
       
   503 	switch(KCounterType)
       
   504 		{
       
   505 		case TSqlResourceProfiler::ESqlCounterFileIO:
       
   506 			TheFileIoProfileEnabled = EFalse;
       
   507 			break;
       
   508 		case TSqlResourceProfiler::ESqlCounterOsCall:
       
   509 			TheOsProfileEnabled = EFalse;
       
   510 			break;
       
   511 		case TSqlResourceProfiler::ESqlCounterOsCallTime:
       
   512 			TheOsCallTimeProfileEnabled = EFalse;
       
   513 			break;
       
   514 		case TSqlResourceProfiler::ESqlCounterOsCallDetails:
       
   515 			TheOsCallTimeDetailedProfileEnabled = EFalse;
       
   516 			TheOsCallTimeProfileEnabled = EFalse;
       
   517 			break;
       
   518 		case TSqlResourceProfiler::ESqlCounterMemory:
       
   519 			TheMemProfileEnabled = EFalse;
       
   520 			break;
       
   521 		case TSqlResourceProfiler::ESqlCounterMaxAlloc:
       
   522 			TheMaxAllocProfileEnabled = EFalse;
       
   523 			break;
       
   524 		default:
       
   525 			return KErrNotSupported;
       
   526 		}
       
   527 	return KErrNone;
       
   528 	}
       
   529 	
       
   530 TInt sqlite3SymbianProfilerReset(TInt aCounterType)
       
   531 	{
       
   532 	const TSqlResourceProfiler::TSqlCounter KCounterType = static_cast <TSqlResourceProfiler::TSqlCounter> (aCounterType);
       
   533 	switch(KCounterType)
       
   534 		{
       
   535 		case TSqlResourceProfiler::ESqlCounterFileIO:
       
   536 			Mem::FillZ(TheFileOpCounter, sizeof(TheFileOpCounter));
       
   537 			TheFileWriteAmount = TheFileReadAmount = 0;
       
   538 			break;
       
   539 		case TSqlResourceProfiler::ESqlCounterOsCall:
       
   540 			Mem::FillZ(TheOsOpCounter, sizeof(TheOsOpCounter));
       
   541 			break;
       
   542 		case TSqlResourceProfiler::ESqlCounterOsCallTime:
       
   543 		case TSqlResourceProfiler::ESqlCounterOsCallDetails:
       
   544 			TheOpCounter = 0;
       
   545 			Mem::FillZ(TheOsCallTicks, sizeof(TheOsCallTicks));
       
   546 			for(TInt i=0;i<EOsOpLast;++i)
       
   547 				{
       
   548 				TheOsCallMProfile[i].Zero();
       
   549 				TheOsCallJProfile[i].Zero();
       
   550 				}
       
   551 			break;
       
   552 		case TSqlResourceProfiler::ESqlCounterMemory:
       
   553 			Mem::FillZ(TheMemOpCounter, sizeof(TheMemOpCounter));
       
   554 			Mem::FillZ(TheMemOpTicks, sizeof(TheMemOpTicks));
       
   555 			TheAllocated = TheFreed = 0;
       
   556 			break;
       
   557 		case TSqlResourceProfiler::ESqlCounterMaxAlloc:
       
   558 			TheAllocMax = 0;
       
   559 			break;
       
   560 		default:
       
   561 			return KErrNotSupported;
       
   562 		}
       
   563 	return KErrNone;
       
   564 	}
       
   565 	
       
   566 TInt sqlite3SymbianProfilerQuery(TInt aCounterType, TDes8& aResult)
       
   567 	{
       
   568 	const TSqlResourceProfiler::TSqlCounter KCounterType = static_cast <TSqlResourceProfiler::TSqlCounter> (aCounterType);
       
   569 	switch(KCounterType)
       
   570 		{
       
   571 		case TSqlResourceProfiler::ESqlCounterFileIO:
       
   572 			for(TInt i=0;i<EFsOpLast;++i)
       
   573 				{
       
   574 				aResult.AppendNum(TheFileOpCounter[i]);
       
   575 				aResult.Append(TChar(';'));
       
   576 				}
       
   577 			aResult.AppendNum(TheFileWriteAmount);
       
   578 			aResult.Append(TChar(';'));
       
   579 			aResult.AppendNum(TheFileReadAmount);
       
   580 			aResult.Append(TChar(';'));
       
   581 			break;
       
   582 		case TSqlResourceProfiler::ESqlCounterOsCall:
       
   583 			for(TInt i=0;i<EOsOpLast;++i)
       
   584 				{
       
   585 				aResult.AppendNum(TheOsOpCounter[i]);
       
   586 				aResult.Append(TChar(';'));
       
   587 				}
       
   588 			break;
       
   589 		case TSqlResourceProfiler::ESqlCounterOsCallTime:
       
   590 		case TSqlResourceProfiler::ESqlCounterOsCallDetails:
       
   591 			{
       
   592 			TInt ticksPerSec = FastCounterFrequency();
       
   593 			for(TInt i=0;i<EOsOpLast;++i)
       
   594 				{
       
   595 				TInt64 osCallTimeUs = (TheOsCallTicks[i] * KMicroSecIn1Sec) / ticksPerSec;
       
   596 				aResult.AppendNum(osCallTimeUs);
       
   597 				aResult.Append(TChar(';'));
       
   598 				}
       
   599 			}
       
   600 			break;
       
   601 		case TSqlResourceProfiler::ESqlCounterMemory:
       
   602 			aResult.AppendNum(TheMemOpCounter[EMemOpAlloc]);
       
   603 			aResult.Append(TChar(';'));
       
   604 			aResult.AppendNum(TheMemOpCounter[EMemOpRealloc]);
       
   605 			aResult.Append(TChar(';'));
       
   606 			aResult.AppendNum(TheMemOpCounter[EMemOpFree]);
       
   607 			aResult.Append(TChar(';'));
       
   608 			aResult.AppendNum(TheAllocated);
       
   609 			aResult.Append(TChar(';'));
       
   610 			aResult.AppendNum(TheFreed);
       
   611 			aResult.Append(TChar(';'));
       
   612 			{
       
   613 			TInt ticksPerSec = FastCounterFrequency();
       
   614 			TInt64 memOpCallTimeUs = (TheMemOpTicks[EMemOpAlloc] * KMicroSecIn1Sec) / ticksPerSec;
       
   615 			aResult.AppendNum(memOpCallTimeUs);
       
   616 			aResult.Append(TChar(';'));
       
   617 			memOpCallTimeUs = (TheMemOpTicks[EMemOpRealloc] * KMicroSecIn1Sec) / ticksPerSec;
       
   618 			aResult.AppendNum(memOpCallTimeUs);
       
   619 			aResult.Append(TChar(';'));
       
   620 			memOpCallTimeUs = (TheMemOpTicks[EMemOpFree] * KMicroSecIn1Sec) / ticksPerSec;
       
   621 			aResult.AppendNum(memOpCallTimeUs);
       
   622 			aResult.Append(TChar(';'));
       
   623 			}
       
   624 			break;
       
   625 		case TSqlResourceProfiler::ESqlCounterMaxAlloc:
       
   626 			aResult.AppendNum(TheAllocMax);
       
   627 			aResult.Append(TChar(';'));
       
   628 			break;
       
   629 		default:
       
   630 			return KErrNotSupported;
       
   631 		}
       
   632 	return KErrNone;
       
   633 	}
       
   634 	
       
   635 #else//_SQLPROFILER	
       
   636 
       
   637 TInt sqlite3SymbianProfilerStart(TInt)
       
   638 	{
       
   639 	return KErrNotSupported;	
       
   640 	}
       
   641 
       
   642 TInt sqlite3SymbianProfilerStop(TInt)
       
   643 	{
       
   644 	return KErrNotSupported;	
       
   645 	}
       
   646 
       
   647 TInt sqlite3SymbianProfilerReset(TInt)
       
   648 	{
       
   649 	return KErrNotSupported;	
       
   650 	}
       
   651 
       
   652 TInt sqlite3SymbianProfilerQuery(TInt, TDes8&)
       
   653 	{
       
   654 	return KErrNotSupported;	
       
   655 	}
       
   656 
       
   657 #endif//_SQLPROFILER
       
   658 
       
   659 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   660 /////////////////////       COsLayerData class declaration   //////////////////////////////////////////////////////////////////
       
   661 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   662 
       
   663 /**
       
   664 COsLayerData singleton class manages a single SQLite OS layer copy of the following data: 
       
   665 @code
       
   666  - file session instance;
       
   667  - process's private data path, where the temporary file will be stored (on the system drive);
       
   668  - the last OS error code, every Symbian OS API call (file system calls, etc.) will set it;
       
   669  - the stored OS error code, initialized with the last OS error code only if stored OS error code is KErrNone.
       
   670 	Each StoredOsErrorCode() call will reset it to KErrNone;
       
   671 	The reason of having two data members for storing the OS error codes is that if there is just one variable
       
   672 	and it gets initialized with the error value reported by a failed OS API call, the next successful OS API
       
   673 	call will reset it and the COsLayerData client will miss the last "real" OS API error.
       
   674  - A pointer to the current RMessage2 object, if the current operation is "open a private secure database";
       
   675  - A boolean flag - iReadOnly - used only for private secure databases, indicating whether the database is read-only or not;
       
   676 @endcode
       
   677 
       
   678 @internalComponent
       
   679 */
       
   680 NONSHARABLE_CLASS(COsLayerData)
       
   681 	{
       
   682 public:	
       
   683 	static TInt Create();
       
   684 	static inline void Destroy();
       
   685 	static inline COsLayerData& Instance();
       
   686 	
       
   687 	inline TInt SetOsErrorCode(TInt aError);
       
   688 	inline TInt StoredOsErrorCode();
       
   689 	
       
   690 	inline void StoreFhData(const RMessage2* aMsg, TBool aReadOnly);
       
   691 	inline void RetrieveAndResetFhData(const RMessage2*& aMsg, TBool& aReadOnly);
       
   692 	
       
   693 private:
       
   694 	inline COsLayerData();
       
   695 	inline ~COsLayerData();
       
   696 	TInt DoCreate();
       
   697 	
       
   698 public:
       
   699 	RFs			iFs;		//File session instance.
       
   700 	TFileName	iSysPrivDir;//"<system drive>:\" + process's private data path. Initialized in sqlite3SymbianFsOpen().
       
   701 							//Used for storing sqlite temporary files.
       
   702 	TInt64		iSeed;
       
   703 	RAllocator*	iAllocator;
       
   704 
       
   705 	enum {KZeroBufSize = SQLITE_DEFAULT_SECTOR_SIZE};
       
   706     TBuf8<KZeroBufSize> iZeroBuf;
       
   707 	
       
   708 private:	
       
   709 	static COsLayerData* 	iOsLayerData;
       
   710 	TInt					iStoredOsErrorCode;	//Contains the last OS error code.
       
   711 	const RMessage2* 		iMessage;			//Fh data
       
   712 	TBool					iReadOnly;			//Fh data
       
   713 	};
       
   714 
       
   715 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   716 ///////////////////////////////////       TDbFile struct declaration      /////////////////////////////////////////////////////
       
   717 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   718 
       
   719 /**
       
   720 TDbFile derives from the sqlite3_file structure, adding data members needed for processing the SQLite requests to the OS layer.
       
   721 When SQLite needs an access to a file, SQLite allocates memory for a new TDbFile instance and passes a pointer to that 
       
   722 instance to TVfs::Open(). TVfs::Open() creates/opens the file and initializes the TDbFile instance. 
       
   723 SQLite uses the initialized TDbFile instance (actually SQLite knows and uses the sqlite3_file, the base structure) 
       
   724 every time when needs to read or write from/to the file, using for that an appropriate TFileIo method.
       
   725 
       
   726 Note: currently RFileBuf64 object is used instead of RFile64. That improves the read/write file performance.
       
   727 
       
   728 No virtual methods here! sqlite3_file contains data members. If a virtual method is added, that will shift the offset of the
       
   729 data members from the beginning of the sqlite3_file  object by 4 bytes. This is not what SQLite (C code) expects.
       
   730 
       
   731 @internalComponent
       
   732 
       
   733 @see TVfs
       
   734 @see TFileIo
       
   735 @see TVfs::Open()
       
   736 */
       
   737 NONSHARABLE_STRUCT(TDbFile) : public sqlite3_file 
       
   738 	{
       
   739 	inline TDbFile();
       
   740 	RFileBuf64	iFileBuf;
       
   741 	HBufC*		iFullName;				//Used for the "delete file" operation (RFile64::FullName() makes an IPC call!)
       
   742 	TInt		iLockType;				//File lock type
       
   743 	TBool		iReadOnly;				//True if the file is read-only
       
   744 	TInt		iSectorSize;			//Media sector-size
       
   745 	TInt		iDeviceCharacteristics;
       
   746 	TSqlFreePageCallback iFreePageCallback;
       
   747 #ifdef _SQLPROFILER
       
   748 	TBool		iIsJournal;
       
   749 #endif	
       
   750 	};
       
   751 
       
   752 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   753 ///////////////////////////////////       TFileIo class declaration      //////////////////////////////////////////////////////
       
   754 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   755 
       
   756 /**
       
   757 TFileIo class offers static methods for performing operations on a file.
       
   758 Every TFileIo method has a pointer to a sqlite3_file instance (so, a TDbFile instance) as its first argument.
       
   759 
       
   760 SQLite never accesses the file system directly, only through function pointers, data members of the sqlite3_io_methods structure.
       
   761 The OS porting layer defines a single instance of sqlite3_io_methods structure, TheFileIoApi, and uses the TFileIo to initialize the 
       
   762 sqlite3_io_methods data members (function pointers).
       
   763 Every time when SQLite creates/opens a file using TVfs::Open(), TVfs::Open() will pass back to SQLite a pointer to the single
       
   764 initialized sqlite3_io_methods instance (TheFileIoApi) that will be used later by SQLite for accessing the file.
       
   765 
       
   766 @internalComponent
       
   767 
       
   768 @see TVfs
       
   769 @see TVfs::Open()
       
   770 @see TheFileIoApi
       
   771 @see TDbFile
       
   772 */
       
   773 NONSHARABLE_CLASS(TFileIo)
       
   774 	{
       
   775 public:	
       
   776 	static int Close(sqlite3_file* aDbFile);
       
   777 	static int Read(sqlite3_file* aDbFile, void* aBuf, int aAmt, sqlite3_int64 aOffset);
       
   778 	static int Write(sqlite3_file* aDbFile, const void* aData, int aAmt, sqlite3_int64 aOffset);
       
   779 	static int Truncate(sqlite3_file* aDbFile, sqlite3_int64 aLength);
       
   780 	static int Sync(sqlite3_file* aDbFile, int aFlags);
       
   781 	static int FileSize(sqlite3_file* aDbFile, sqlite3_int64* aSize);
       
   782 	static int Lock(sqlite3_file* aDbFile, int aLockType);
       
   783 	static int Unlock(sqlite3_file* aDbFile, int aLockType);
       
   784 	static int CheckReservedLock(sqlite3_file* aDbFile, int *aResOut);
       
   785 	static int FileControl(sqlite3_file* aDbFile, int aOp, void* aArg);
       
   786 	static int SectorSize(sqlite3_file* aDbFile);
       
   787 	static int DeviceCharacteristics(sqlite3_file* aDbFile);
       
   788 	};
       
   789 
       
   790 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   791 ///////////////////////////////////       TVfs class declaration      /////////////////////////////////////////////////////////
       
   792 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   793 
       
   794 /**
       
   795 TVfs ("VFS" - virtual file system) class offers methods for creating/openning a file, deleting a file,
       
   796 a "sleep" method, a "time" method, a "rand" method, etc.
       
   797 SQLite never accesses the OS API directly, only through the API offered by TVfs and TFileIo classes.
       
   798 
       
   799 @internalComponent
       
   800 
       
   801 @see TFileIo
       
   802 @see TheVfsApi
       
   803 @see COsLayerData
       
   804 */
       
   805 NONSHARABLE_CLASS(TVfs)
       
   806 	{
       
   807 public:		
       
   808 	static int Open(sqlite3_vfs* aVfs, const char* aFileName, sqlite3_file* aDbFile, int aFlags, int* aOutFlags);
       
   809 	static int Delete(sqlite3_vfs* aVfs, const char* aFileName, int aSyncDir);	
       
   810 	static int Access(sqlite3_vfs* aVfs, const char* aFileName, int aFlags, int* aResOut);
       
   811 	static int FullPathName(sqlite3_vfs* aVfs, const char* aRelative, int aBufLen, char* aBuf);
       
   812 	static int Randomness(sqlite3_vfs* aVfs, int aBufLen, char* aBuf);
       
   813 	static int Sleep(sqlite3_vfs* aVfs, int aMicrosec);
       
   814 	static int CurrentTime(sqlite3_vfs* aVfs, double* aNow);
       
   815 	static int GetLastError(sqlite3_vfs *sVfs, int aBufLen, char* aBuf);
       
   816 private:
       
   817 	static TInt DoOpenFromHandle(TDbFile& aDbFile, const RMessage2& aMsg, TBool aReadOnly);
       
   818 	static inline TInt DoGetVolumeIoParamInfo(RFs& aFs, TInt aDriveNo, TVolumeIOParamInfo& aVolumeInfo);
       
   819 	static TInt DoGetDeviceCharacteristics(const TDriveInfo& aDriveInfo, const TVolumeIOParamInfo& aVolumeInfo);
       
   820 	static TInt DoGetSectorSize(const TDriveInfo& aDriveInfo, const TVolumeIOParamInfo& aVolumeInfo);
       
   821 	static TInt DoGetDeviceCharacteristicsAndSectorSize(TDbFile& aDbFile, TInt& aRecReadBufSize);
       
   822 	
       
   823 	};
       
   824 
       
   825 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   826 /////////////////////       Global variables, constants    ////////////////////////////////////////////////////////////////////
       
   827 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   828 
       
   829 // The following macro specifies the size of the RFileBuf64 file buffer in KB:
       
   830 //    __SQLITE_OS_SYMBIAN_FILEBUF_KBSIZE__
       
   831 // 
       
   832 // If not set, a default value of 8 is used	
       
   833 #if !defined(__SQLITE_OS_SYMBIAN_FILEBUF_KBSIZE__)
       
   834 #define __SQLITE_OS_SYMBIAN_FILEBUF_KBSIZE__ 8
       
   835 #endif	
       
   836 const TInt KFileBufSize = __SQLITE_OS_SYMBIAN_FILEBUF_KBSIZE__ * 1024;	
       
   837 
       
   838 /**
       
   839 Pointer to the single COsLayerData instance.
       
   840 
       
   841 @see COsLayerData
       
   842 
       
   843 @internalComponent
       
   844 */
       
   845 COsLayerData* COsLayerData::iOsLayerData = NULL;
       
   846 
       
   847 /**
       
   848 Single sqlite3_io_methods instance, which data members (function pointers) are initialized with the addresses of
       
   849 TFileIo members. 
       
   850 TheFileIoApi is used by SQLite for performing OS independent file I/O.
       
   851 
       
   852 @see TFileIo
       
   853 @see TVfs
       
   854 
       
   855 @internalComponent
       
   856 */
       
   857 static sqlite3_io_methods TheFileIoApi = 
       
   858 	{
       
   859 	1,						//Version
       
   860 	&TFileIo::Close,
       
   861 	&TFileIo::Read,
       
   862 	&TFileIo::Write,
       
   863 	&TFileIo::Truncate,
       
   864 	&TFileIo::Sync,
       
   865 	&TFileIo::FileSize,
       
   866 	&TFileIo::Lock,
       
   867 	&TFileIo::Unlock,
       
   868 	&TFileIo::CheckReservedLock,
       
   869 	&TFileIo::FileControl,
       
   870 	&TFileIo::SectorSize,
       
   871 	&TFileIo::DeviceCharacteristics
       
   872 	};
       
   873 
       
   874 /**
       
   875 Single sqlite3_vfs instance, which data members (function pointers) are initialized with the addresses of
       
   876 TVfs members. TheVfsApi also keeps information regarding some other OS dependend characteristics like 
       
   877 the TDbFile size and max file name length.
       
   878 TheVfsApi is used by SQLite for accessing needed OS API.
       
   879 
       
   880 TheVfsApi can't be a constant definition. SQLite expects the "sqlite3_vfs" object to be a R/W one, because
       
   881 SQLite may have and use a chain of sqlite3_vfs instances.
       
   882 
       
   883 @see TVfs
       
   884 @see TTFileIo
       
   885 @see TDbFile
       
   886 
       
   887 @internalComponent
       
   888 */
       
   889 static sqlite3_vfs TheVfsApi = 
       
   890 	{
       
   891 	1,					//iVersion
       
   892 	sizeof(TDbFile),	//szOsFile
       
   893 	KMaxFileName,		//mxPathname
       
   894 	0,					//pNext
       
   895 	"SymbianSql",		//zName
       
   896 	0,					//pAppData
       
   897 	&TVfs::Open,
       
   898 	&TVfs::Delete,
       
   899 	&TVfs::Access,
       
   900 	&TVfs::FullPathName,
       
   901 	0,
       
   902 	0,
       
   903 	0,
       
   904 	0,
       
   905 	&TVfs::Randomness,
       
   906 	&TVfs::Sleep,
       
   907 	&TVfs::CurrentTime,
       
   908 	&TVfs::GetLastError
       
   909 	};
       
   910 
       
   911 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   912 /////////////////////       COsLayerData class definition    //////////////////////////////////////////////////////////////////
       
   913 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   914 
       
   915 /**
       
   916 Creates a single COsLayerData instance.
       
   917 
       
   918 @return KErrNone,          The operation has completed succesfully;
       
   919 	    KErrNoMemory,      Out of memory condition has occured;
       
   920                            Note that other system-wide error codes may also be returned.
       
   921                            
       
   922 @panic Sqlite 16 In _DEBUG mode - the COsLayerData instance has been created already.
       
   923 */
       
   924 /* static */ TInt COsLayerData::Create()
       
   925 	{
       
   926 	__ASSERT_DEBUG(!COsLayerData::iOsLayerData, User::Panic(KPanicCategory, EPanicOsLayerDataExists));
       
   927 	if(!COsLayerData::iOsLayerData)
       
   928 		{
       
   929 		COsLayerData::iOsLayerData = new COsLayerData;
       
   930 		if(!COsLayerData::iOsLayerData)
       
   931 			{
       
   932 			return KErrNoMemory;	
       
   933 			}
       
   934 		TInt err = COsLayerData::iOsLayerData->DoCreate();
       
   935 		if(err != KErrNone)
       
   936 			{
       
   937 			delete COsLayerData::iOsLayerData;
       
   938 			COsLayerData::iOsLayerData = NULL;
       
   939 			return err;
       
   940 			}
       
   941 		}
       
   942 	return KErrNone;
       
   943 	}
       
   944 
       
   945 /**
       
   946 Destroys the COsLayerData instance.
       
   947 */
       
   948 /* static */ inline void COsLayerData::Destroy()
       
   949 	{
       
   950 	delete COsLayerData::iOsLayerData;
       
   951 	COsLayerData::iOsLayerData = NULL;
       
   952 	}
       
   953 
       
   954 /**
       
   955 Returns a reference to the single COsLayerData instance.
       
   956 
       
   957 @panic Sqlite 1 In _DEBUG mode if the COsLayerData instance is NULL.
       
   958 */
       
   959 /* static */ inline COsLayerData& COsLayerData::Instance()
       
   960 	{
       
   961 	__ASSERT_DEBUG(COsLayerData::iOsLayerData != NULL, User::Panic(KPanicCategory, EPanicNullOsLayerDataPtr));
       
   962 	return *COsLayerData::iOsLayerData;
       
   963 	}
       
   964 
       
   965 /**
       
   966 Sets the last OS error code data member. The stored OS error code data member will be set only if it is
       
   967 KErrNone. (If it is not KErrNone it means that its value has not been accessed yet)
       
   968 An exception from the rule described above is KErrDiskFull error which, if happens, will be set always, because
       
   969 this error has a special meaning for the database clients - special actions may have to be taken if the
       
   970 disk is full.
       
   971 
       
   972 @param aError The OS error code
       
   973 @return The OS error code
       
   974 */
       
   975 inline TInt COsLayerData::SetOsErrorCode(TInt aError)
       
   976 	{
       
   977 	if(iStoredOsErrorCode == KErrNone || aError == KErrDiskFull)
       
   978 		{
       
   979 		iStoredOsErrorCode = aError;
       
   980 		}
       
   981 	return aError;
       
   982 	}
       
   983 
       
   984 /**
       
   985 Returns the last stored OS error code, which was stored by SetOsErrorCode() call.
       
   986 The function also resets the stored OS error code to KErrNone.
       
   987 
       
   988 @return The last stored OS error code
       
   989 */
       
   990 inline TInt COsLayerData::StoredOsErrorCode()
       
   991 	{
       
   992 	TInt err = iStoredOsErrorCode;
       
   993 	iStoredOsErrorCode = KErrNone;
       
   994 	return err;
       
   995 	}
       
   996 
       
   997 /**
       
   998 Stores the RMessage2 object address, file and file session handles and the read-only flag for later use when SQLite issues a 
       
   999 request for open the database file (private secure database). 
       
  1000 
       
  1001 The aMsg argument of the function can be NULL, because this fucntion is also used to reset the stored "file handle" data.
       
  1002 
       
  1003 How this function is used:
       
  1004 1) When the SQL server receives a request to establish a connection with private secure database, the SQL server
       
  1005    will add additional information to the private secure database file name, such as: 
       
  1006    	- the file handle (the private secure database is opened by the client side dll - sqldb.dll);
       
  1007    	- a pointer to the RMessage2 object used in this request;
       
  1008 2) The passed additional information will be used for adopting the file handle by calling RFile64::AdoptFromClient().
       
  1009 3) Before calling TVfs::Open() to establish a connection with the database, SQLite will call TVfs::FullPathName()
       
  1010    to retrieve the database file full path
       
  1011 4) TVfs::FullPathName() will detect that the file name contains an additional information and will extraxt the information
       
  1012    calling COsLayerData::StoreFhData().
       
  1013 5) After TVfs::FullPathName() SQLite calls TVfs::Open() where the extracted information will be used for adopting the file handle
       
  1014 
       
  1015 @param aMsg A pointer to the current RMessage2 object
       
  1016 @param aReadOnly True if the private secure database is read-only
       
  1017 */
       
  1018 inline void COsLayerData::StoreFhData(const RMessage2* aMsg, TBool aReadOnly)
       
  1019 	{
       
  1020 	iMessage = aMsg;
       
  1021 	iReadOnly = aReadOnly;
       
  1022 	}
       
  1023 
       
  1024 /**
       
  1025 Retrieves the RMessage2 object, file and file session handles. The stored data will be reset.
       
  1026 This function is used by TVfs::Open(), when a request for opening a secure private database is processed.
       
  1027 
       
  1028 @param aMsg Output parameter. A reference to a RMessage2 pointer, which will be initialized with the stored RMessage2 pointer.
       
  1029 @param aReadOnly Output parameter. The store read-only flag value will be set there.
       
  1030 
       
  1031 @panic Sqlite 13 In _DEBUG mode - aMsg is NULL.
       
  1032 */
       
  1033 inline void COsLayerData::RetrieveAndResetFhData(const RMessage2*& aMsg, TBool& aReadOnly)
       
  1034 	{
       
  1035 	__ASSERT_DEBUG(iMessage != NULL, User::Panic(KPanicCategory, EPanicInvalidFhData));
       
  1036 	aMsg = iMessage; 
       
  1037 	aReadOnly = iReadOnly;
       
  1038 	iMessage = NULL;
       
  1039 	}
       
  1040 
       
  1041 /**
       
  1042 Initializes the COsLayerData data members with their default values.
       
  1043 */
       
  1044 inline COsLayerData::COsLayerData() :
       
  1045 	iAllocator(0),
       
  1046 	iStoredOsErrorCode(KErrNone),
       
  1047 	iMessage(0),
       
  1048 	iReadOnly(EFalse)
       
  1049 	{
       
  1050 	TTime now;
       
  1051 	now.UniversalTime();
       
  1052 	iSeed = now.Int64();
       
  1053    	iZeroBuf.FillZ(COsLayerData::KZeroBufSize);
       
  1054 	}
       
  1055 
       
  1056 /**
       
  1057 Destroys the COsLayerData instance.
       
  1058 
       
  1059 Note: No SQLite functions should be called inside the destructor, because SQLite is already shutdown-ed!
       
  1060 */
       
  1061 inline COsLayerData::~COsLayerData()
       
  1062 	{
       
  1063 	__FS_CALL(EFsOpFsClose, 0);
       
  1064 	iFs.Close();	
       
  1065 	}
       
  1066 
       
  1067 /**
       
  1068 Creates a file session instance.	
       
  1069 
       
  1070 Creates the private path, where the temporary files will be stored (on the system drive).
       
  1071 
       
  1072 In a case of a failure COsLayerData::DoCreate() does not close the file session.
       
  1073 This will be made in the calling function - COsLayerData::Create().
       
  1074 
       
  1075 Note: No SQLite functions should be called inside the DoCreate() implementation, because SQLite is not initialized yet!
       
  1076 
       
  1077 @return KErrNone,          The operation has completed succesfully;
       
  1078 		KErrGeneral		   The registration of TheVfsApi has failed;
       
  1079 	    KErrNoMemory,      Out of memory condition has occured;
       
  1080                            Note that other system-wide error codes may also be returned.
       
  1081 
       
  1082 @see TVfs
       
  1083 @see TheVfsApi
       
  1084 */
       
  1085 TInt COsLayerData::DoCreate()
       
  1086 	{
       
  1087 	iAllocator = &User::Allocator();
       
  1088 	__FS_CALL(EFsOpFsConnect, 0);
       
  1089 	TInt err = iFs.Connect();
       
  1090 	if(err != KErrNone)
       
  1091 		{
       
  1092 		return err;	
       
  1093 		}
       
  1094 	//Get the system drive
       
  1095 	__FS_CALL(EFsOpFsGetSystemDrive, 0);
       
  1096 	TInt sysDrive = static_cast<TInt>(RFs::GetSystemDrive());
       
  1097 	__FS_CALL(EFsOpFsCreatePrivatePath, 0);
       
  1098 	if((err = iFs.CreatePrivatePath(sysDrive)) != KErrNone && err != KErrAlreadyExists)
       
  1099 		{
       
  1100 		return err;	
       
  1101 		}
       
  1102 	TFileName privateDir;
       
  1103 	__FS_CALL(EFsOpFsPrivatePath, 0);
       
  1104 	if((err = iFs.PrivatePath(privateDir)) != KErrNone)
       
  1105 		{
       
  1106 		return err;	
       
  1107 		}
       
  1108 	TDriveUnit drive(sysDrive);
       
  1109 	TDriveName driveName = drive.Name();
       
  1110 	TParse parse;
       
  1111 	(void)parse.Set(driveName, &privateDir, 0);//this call can't fail
       
  1112 	iSysPrivDir.Copy(parse.DriveAndPath());
       
  1113 	return KErrNone;
       
  1114 	}
       
  1115 
       
  1116 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
  1117 ///////////////////////     Symbian OS specific functions (called by the SQL server)        ///////////////////////////////////
       
  1118 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
  1119 
       
  1120 /**
       
  1121 Returns the last OS error which occured durring the operations with the database files.
       
  1122 The per-thread variable, where the last OS error is hold, will be set to KErrNone.
       
  1123 
       
  1124 This function is part of Symbian OS specific SQLITE API.
       
  1125 
       
  1126 @return The last OS error.
       
  1127 @internalComponent
       
  1128 */
       
  1129 TInt sqlite3SymbianLastOsError(void)
       
  1130 	{
       
  1131 	return COsLayerData::Instance().StoredOsErrorCode();
       
  1132 	}
       
  1133 
       
  1134 /**
       
  1135 This function must be called once before any other SQLITE API call. 
       
  1136 The function:
       
  1137 @code
       
  1138  - Initializes the OS poting layer;
       
  1139  - Initializes the SQLite library;
       
  1140 @endcode
       
  1141 
       
  1142 This function is part of the Symbian OS specific SQLITE API.
       
  1143 
       
  1144 @return Symbian OS specific error code, including KErrNoMemory.
       
  1145 
       
  1146 @internalComponent
       
  1147 */
       
  1148 TInt sqlite3SymbianLibInit(void)
       
  1149 	{
       
  1150 	TInt osErr = COsLayerData::Create();
       
  1151 	if(osErr != KErrNone)
       
  1152 		{
       
  1153 		return osErr;
       
  1154 		}
       
  1155 	osErr = KErrNone;
       
  1156 	TInt sqliteErr = sqlite3_initialize();
       
  1157 	if(sqliteErr != SQLITE_OK)
       
  1158 		{
       
  1159 		osErr = sqliteErr == SQLITE_NOMEM ? KErrNoMemory : KErrGeneral;
       
  1160 		COsLayerData::Destroy();
       
  1161 		}
       
  1162 	return osErr;
       
  1163 	}
       
  1164 
       
  1165 /**
       
  1166 This function must be called once after finishing working with sqlite.
       
  1167 The function:
       
  1168 @code
       
  1169  - Shuts down the SQLite library;
       
  1170  - Releases the allocated by the OS porting layer resources;
       
  1171 @endcode
       
  1172 
       
  1173 This function is part of the Symbian OS specific SQLITE API.
       
  1174 
       
  1175 @internalComponent
       
  1176 */
       
  1177 void sqlite3SymbianLibFinalize(void)
       
  1178 	{
       
  1179 	(void)sqlite3_shutdown();
       
  1180 	COsLayerData::Destroy();
       
  1181 	}
       
  1182 
       
  1183 /**
       
  1184 This function is part of Symbian OS specific SQLITE API.
       
  1185 
       
  1186 @return A reference to RFs instance used for sqlite file I/O operations.
       
  1187 @internalComponent
       
  1188 */
       
  1189 RFs& sqlite3SymbianFs(void)
       
  1190 	{
       
  1191 	return COsLayerData::Instance().iFs;
       
  1192 	}
       
  1193 
       
  1194 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
  1195 //////////////////          UTF16<-->UTF8, conversion functions    ////////////////////////////////////////////////////////////
       
  1196 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
  1197 
       
  1198 /**
       
  1199 The function converts aFileName to UTF16 encoded file name, and stores the UTF16 encoded file name
       
  1200 to the place pointed by aFileNameDestBuf argument.
       
  1201 If the UTF16 conversion of the file name failed because the file name is too long or NULL, 
       
  1202 the function returns EFalse. 
       
  1203 
       
  1204 @param aFileName Expected to point to UTF8 encoded, zero terminated string.
       
  1205 				 Max allowed aFileName length is KMaxFileName (excluding terminating 0 character).
       
  1206 @param aFileNameDestBuf Output parameter. Will hold UTF16, non-zero-terminated string.
       
  1207 						The max length must be at least KMaxFileName characters.
       
  1208                          
       
  1209 @return True if the conversion has been completed successfully						 
       
  1210 */
       
  1211 static TBool ConvertToUnicode(const char *aFileName, TDes& aFileNameDestBuf)
       
  1212 	{
       
  1213 	if(aFileName)
       
  1214 		{
       
  1215 		wchar_t* dest = reinterpret_cast <wchar_t*> (const_cast <TUint16*> (aFileNameDestBuf.Ptr()));
       
  1216 		TInt len = mbstowcs(dest, aFileName, aFileNameDestBuf.MaxLength());
       
  1217 		//If len == aFileNameDestBuf.MaxLength(), then the output buffer is too small.
       
  1218 		if(len > 0 && len < aFileNameDestBuf.MaxLength())
       
  1219 			{
       
  1220 			aFileNameDestBuf.SetLength(len);
       
  1221 			return ETrue;
       
  1222 			}
       
  1223 		}
       
  1224 	return EFalse;
       
  1225 	}
       
  1226 
       
  1227 /**
       
  1228 The function converts aFileName to UTF8 encoded file name, and stores the UTF8 encoded file name
       
  1229 to the place pointed by aFileNameDestBuf argument.
       
  1230 If the UTF8 conversion of the file name failed because the file name is too long or NULL, 
       
  1231 the function returns EFalse. 
       
  1232 
       
  1233 @param aFileName Expected to point to UTF16 encoded, zero terminated string.
       
  1234 				 Max allowed aFileName length is KMaxFileName (excluding terminating 0 character).
       
  1235 @param aFileNameDestBuf Output parameter. Will hold UTF8, non-zero-terminated string.
       
  1236 						The max length must be at least KMaxFileName characters.
       
  1237                          
       
  1238 @return True if the conversion has been completed successfully						 
       
  1239 */
       
  1240 static TBool ConvertFromUnicode(const TDesC& aFileName, TDes8& aFileNameDestBuf)
       
  1241 	{
       
  1242 	char* dest = reinterpret_cast <char*> (const_cast <TUint8*> (aFileNameDestBuf.Ptr()));
       
  1243 	const wchar_t* src = reinterpret_cast <const wchar_t*> (aFileName.Ptr());
       
  1244 	TInt len = wcstombs(dest, src, aFileNameDestBuf.MaxLength());
       
  1245 	//If len == aFileNameDestBuf.MaxLength(), then the output buffer is too small.
       
  1246 	if(len > 0 && len < aFileNameDestBuf.MaxLength())
       
  1247 		{
       
  1248 		aFileNameDestBuf.SetLength(len);
       
  1249 		return ETrue;
       
  1250 		}
       
  1251 	return EFalse;
       
  1252 	}
       
  1253 
       
  1254 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
  1255 //////////////////          File name, containing handles, functions   ////////////////////////////////////////////////////////
       
  1256 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
  1257 
       
  1258 const char KFhSeparator = '|';	//The symbol, which when used in the file name means that the string does not contain a real file name but file handles
       
  1259 const TInt KFhSessHandleIdx = 2;//The index of the file session handle in RMessage2 object
       
  1260 const TInt KFhFileHandleIdx = 3;//The index of the file handle in RMessage2 object
       
  1261 const TInt KFhMarkPos = 0;		//if the symbol in this position is KFhSeparator, then the string contains file handles
       
  1262 const TInt KFhRoPos = 1;		//read-only flag position in the string
       
  1263 const TInt KFhMsgAddrPos = 2;	//RMessage2 address position in the string
       
  1264 const TInt KFhMsgAddrLen = 8;	//RMessage2 address length
       
  1265 //const TInt KFhDrivePos = 1;	//Drive position in the string (after removing the read-only flag and RMessage2 object's address)
       
  1266 
       
  1267 /**
       
  1268 File name string types:
       
  1269 @code
       
  1270 	- ENotFhStr 	- The string does not contain file handles;
       
  1271 	- EFhStr		- The string contain file handles, but is not main db file;
       
  1272 	- EFhMainDbStr	- The string contain file handles and is the main db file;
       
  1273 @endcode
       
  1274 
       
  1275 Every file name passed to the OS porting layer's TVfs::Open() method falls into one of the following three categories:
       
  1276 ENotFhStr - the file name does not contain handles, EFhStr - the file name contains handles but is not a name of a private
       
  1277 secure database, EFhMainDbStr - the file name contains handles and is a name of a private secure database.
       
  1278 
       
  1279 @see TVfs::Open()
       
  1280 @see FhStringProps()
       
  1281 
       
  1282 @internalComponent
       
  1283 */
       
  1284 enum TFhStrType
       
  1285 	{
       
  1286 	ENotFhStr,						//The string does not contain file handles
       
  1287 	EFhStr,							//The string contain file handles, but is not main db file
       
  1288 	EFhMainDbStr					//The string contain file handles and is the main db file
       
  1289 	};
       
  1290 
       
  1291 /**
       
  1292 The TVfs::Open() implementation uses this function to determine the type of the file name, which can be 
       
  1293 one of the TFhStrType enum item values.
       
  1294 
       
  1295 @param aFileName Zero-terminated, UTF8 encoded file name.
       
  1296 @return The file name type, one of the TFhStrType enum item values.
       
  1297 
       
  1298 @see TVfs::Open()
       
  1299 @see TFhStrType
       
  1300 
       
  1301 @internalComponent
       
  1302 */
       
  1303 static TFhStrType FhStringProps(const char* aFileName)
       
  1304 	{
       
  1305 	char* first = strchr(aFileName, KFhSeparator);
       
  1306 	if(!first)
       
  1307 		{
       
  1308 		return ENotFhStr;
       
  1309 		}
       
  1310 	char* last = strchr(first + 1, KFhSeparator);
       
  1311 	if(!last)
       
  1312 		{
       
  1313 		return ENotFhStr;
       
  1314 		}
       
  1315 	return *(last + 1) == 0 ? EFhMainDbStr : EFhStr;
       
  1316 	}
       
  1317 
       
  1318 /**
       
  1319 Replaces all invalid characters in aFileName.
       
  1320 If the file name contains handles (so that's a private secure database related name), the additional
       
  1321 information (handles, flags, object addresses) has to be excluded from the name in order to make it usable 
       
  1322 by the file system.
       
  1323 
       
  1324 @param aFileName Output parameter. The cleaned file name will be copied there.
       
  1325 @param aPrivateDir The SQL server private data cage.
       
  1326 
       
  1327 @see TVfs::Open()
       
  1328 @see TFhStrType
       
  1329 @see FhStringProps()
       
  1330 
       
  1331 @internalComponent
       
  1332 */
       
  1333 static void FhConvertToFileName(TDes& aFileName, const TDesC& aPrivateDir)
       
  1334 	{
       
  1335 	TInt firstPos = aFileName.Locate(TChar(KFhSeparator));
       
  1336 	if(firstPos >= 0)
       
  1337 		{
       
  1338 		aFileName.Delete(firstPos, 1);
       
  1339 		TInt lastPos = aFileName.LocateReverse(TChar(KFhSeparator));
       
  1340 		if(lastPos >= 0)
       
  1341 			{
       
  1342 			aFileName.Delete(lastPos, 1);
       
  1343 			TParse parse;
       
  1344 			(void)parse.Set(aFileName, &aPrivateDir, 0);//the file name should be verified by the server
       
  1345 			aFileName.Copy(parse.FullName());
       
  1346 			}
       
  1347 		}
       
  1348 	}
       
  1349 
       
  1350 /**
       
  1351 Extracts the read-only flag and RMessage address from aDbFileName and stores them in single COsLayerData instance.
       
  1352 
       
  1353 @param aDbFileName Input/output parameter. The file name. 
       
  1354 				   It will be reformatted and won't contain the already extracted data.
       
  1355 				   The aDbFileName format is:
       
  1356 @code
       
  1357       				|<R/O flag><RMessage2 pointer><drive><app SID><file_name><file_ext>|
       
  1358 @endcode
       
  1359 
       
  1360 @see TVfs::Open()
       
  1361 @see TFhStrType
       
  1362 @see FhStringProps()
       
  1363 
       
  1364 @internalComponent
       
  1365 
       
  1366 @panic Sqlite 12 In _DEBUG mode - invalid position of the "|" character in the file name.
       
  1367 @panic Sqlite 12 In _DEBUG mode - no RMessage2 pointer can be extracted from the file name.
       
  1368 @panic Sqlite 12 In _DEBUG mode - the extracted RMessage2 pointer is NULL.
       
  1369 */
       
  1370 static void FhExtractAndStore(TDes& aDbFileName)
       
  1371 	{
       
  1372 	TInt fhStartPos = aDbFileName.Locate(TChar(KFhSeparator));
       
  1373 	__ASSERT_DEBUG(fhStartPos == KFhMarkPos, User::Panic(KPanicCategory, EPanicInvalidFhStr));
       
  1374 	//If this file name string contains file handles
       
  1375 	if(fhStartPos == KFhMarkPos)
       
  1376 		{
       
  1377 		//Extract from aDbFileName string RMessage2 object's address
       
  1378 		TLex lex(aDbFileName.Mid(fhStartPos + KFhMsgAddrPos, KFhMsgAddrLen));
       
  1379 		TUint32 addr;
       
  1380 		TInt err = lex.Val(addr, EHex);
       
  1381 		__ASSERT_DEBUG(err == KErrNone, User::Panic(KPanicCategory, EPanicInvalidFhStr));
       
  1382 		if(err == KErrNone)
       
  1383 			{
       
  1384 			//Cast the address to RMessage2 pointer.
       
  1385 			const RMessage2* msg = reinterpret_cast <const RMessage2*> (addr);
       
  1386 			__ASSERT_DEBUG(msg != NULL, User::Panic(KPanicCategory, EPanicInvalidFhStr));
       
  1387 			if(msg)
       
  1388 				{
       
  1389 				//Store the data from aDbFileName in the single COsLayerData instance.
       
  1390 				TBool readOnly = aDbFileName[fhStartPos + KFhRoPos] > '0';
       
  1391 				COsLayerData::Instance().StoreFhData(msg, readOnly);
       
  1392 				//Remove: read-only flag and RMessage2 object's address
       
  1393 				aDbFileName.Delete(fhStartPos + KFhRoPos, 1 + KFhMsgAddrLen);
       
  1394 				}
       
  1395 			}
       
  1396 		}
       
  1397 	}
       
  1398 
       
  1399 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
  1400 /////////////////////       TDbFile class definition    ///////////////////////////////////////////////////////////////////////
       
  1401 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
  1402 
       
  1403 /**
       
  1404 Initializes TDbFile data members with their default values.
       
  1405 */
       
  1406 inline TDbFile::TDbFile() :
       
  1407 	iFileBuf(KFileBufSize),
       
  1408 	iFullName(0),
       
  1409 	iLockType(SQLITE_LOCK_NONE),
       
  1410 	iReadOnly(EFalse),
       
  1411 	iSectorSize(0),
       
  1412 	iDeviceCharacteristics(-1)
       
  1413 	{
       
  1414 #ifdef _SQLPROFILER
       
  1415 	iIsJournal = EFalse;
       
  1416 #endif
       
  1417 	pMethods = 0;
       
  1418 	}
       
  1419 
       
  1420 /**
       
  1421 Casts the passed sqlite3_file pointer to a reference to the derived class - TDbFile&.
       
  1422 All sqlite3_file pointers passed to TFileIo methods are actually pointers to TDbFile instances. 
       
  1423 So the cast is safe.
       
  1424 
       
  1425 @param aDbFile A pointer to a sqlite3_file instance
       
  1426 
       
  1427 @return A TDbFile reference. 
       
  1428 @see TFileIo
       
  1429 @see TVfs
       
  1430 @see TDbFile
       
  1431 
       
  1432 @panic Sqlite 20 In _DEBUG mode if aDbFile is NULL.
       
  1433 
       
  1434 @internalComponent
       
  1435 */
       
  1436 static inline TDbFile& DbFile(sqlite3_file* aDbFile)
       
  1437 	{
       
  1438 	__ASSERT_DEBUG(aDbFile != 0, User::Panic(KPanicCategory, EPanicNullDbFilePtr));
       
  1439 	return *(static_cast <TDbFile*> (aDbFile));
       
  1440 	}
       
  1441 
       
  1442 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
  1443 /////////////////////       TFileIo class definition    ///////////////////////////////////////////////////////////////////////
       
  1444 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
  1445 
       
  1446 /**
       
  1447 SQLite OS porting layer API.
       
  1448 
       
  1449 Closes the file referred by aDbFile parameter.
       
  1450 If aDbFile, which is actually a pointer to a TDbFile instance, the iFullName data member is not NULL, 
       
  1451 then the file will be deleted.
       
  1452 
       
  1453 @param aDbFile A pointer to a TDbFile instance, than contains the file handle to be closed.
       
  1454 
       
  1455 @return SQLITE_OK
       
  1456 
       
  1457 @see TDbFile
       
  1458 */
       
  1459 /* static */ int TFileIo::Close(sqlite3_file* aDbFile)
       
  1460 	{
       
  1461 	SQLUTRACE_PROFILER(aDbFile);
       
  1462 	TDbFile& dbFile = ::DbFile(aDbFile);
       
  1463 	__OS_CALL(EOsFileClose, 0, 0);
       
  1464 	__OSTIME_COUNTER(TheOsCallTicks[EOsFileClose], ::OsCallProfile(dbFile.iIsJournal, EOsFileClose), 0, 0);
       
  1465 	__FS_CALL(EFsOpFileClose, 0);
       
  1466 	dbFile.iFileBuf.Close();
       
  1467 	if(dbFile.iFullName)
       
  1468 		{
       
  1469 		__FS_CALL(EFsOpFileDelete, 0);
       
  1470 		(void)COsLayerData::Instance().iFs.Delete(*dbFile.iFullName);
       
  1471 		delete dbFile.iFullName;
       
  1472 		}
       
  1473 	return SQLITE_OK;
       
  1474 	}
       
  1475 
       
  1476 /**
       
  1477 SQLite OS porting layer API.
       
  1478 
       
  1479 Reads from the file referred by the aDbFile parameter.
       
  1480 
       
  1481 @param aDbFile A pointer to a TDbFile instance, that contains the file handle to be read from.
       
  1482 @param aBuf Output parameter. The data read from the file will be copied there.
       
  1483 			The buffer size must be at least aAmt bytes.
       
  1484 @param aAmt The amount of data to be read form the file.
       
  1485 @param aOffset The offset in the file where the read operation should start.
       
  1486 
       
  1487 @return SQLITE_IOERR_READ, 			The file read or seek operation has failed;
       
  1488 	    SQLITE_IOERR_SHORT_READ, 	The amount of the data read is less than aAmt;
       
  1489 	    SQLITE_IOERR_NOMEM,			An out of memory condition has occured;
       
  1490 	    SQLITE_OK,					The operation has completed successfully.
       
  1491 	    
       
  1492 If the function succeeds, COsLayerData::SetOsErrorCode() is called with KErrNone, otherwise COsLayerData::SetOsErrorCode() is called
       
  1493 with the reported by the OS API error. The stored error code will be used later by the SQLite API caller.
       
  1494 
       
  1495 @see COsLayerData::SetOsErrorCode()
       
  1496 @see TDbFile
       
  1497 */
       
  1498 /* static */ int TFileIo::Read(sqlite3_file* aDbFile, void* aBuf, int aAmt, sqlite3_int64 aOffset)
       
  1499 	{
       
  1500 	SQLUTRACE_PROFILER(aDbFile);
       
  1501 	SYMBIAN_TRACE_SQL_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EInternals), KFileRead, aAmt, aOffset));
       
  1502 	TDbFile& dbFile = ::DbFile(aDbFile);
       
  1503 	__OS_CALL(EOsFileRead, 0, 0);
       
  1504 	__COUNTER_INCR(TheSqlSrvProfilerFileRead);
       
  1505 	__OSTIME_COUNTER(TheOsCallTicks[EOsFileRead], ::OsCallProfile(dbFile.iIsJournal, EOsFileRead), aOffset, aAmt);
       
  1506 	TPtr8 ptr((TUint8*)aBuf, 0, aAmt);
       
  1507 	TInt err = dbFile.iFileBuf.Read(aOffset, ptr);
       
  1508 	TInt cnt = ptr.Length();
       
  1509 	TInt sqliteErr = SQLITE_IOERR_READ;
       
  1510 	switch(err)
       
  1511 		{
       
  1512 		case KErrNone:
       
  1513 			sqliteErr = SQLITE_OK;	
       
  1514 			if(cnt != aAmt)
       
  1515 				{
       
  1516 				Mem::FillZ(static_cast <TUint8*> (aBuf) + cnt, aAmt - cnt);
       
  1517 				sqliteErr = SQLITE_IOERR_SHORT_READ;
       
  1518 				err = KErrEof;
       
  1519 				}
       
  1520 			break;
       
  1521 		case KErrEof:
       
  1522 			Mem::FillZ(static_cast <TUint8*> (aBuf) + cnt, aAmt - cnt);
       
  1523 			sqliteErr = SQLITE_IOERR_SHORT_READ;
       
  1524 			break;
       
  1525 		case KErrNoMemory:
       
  1526 			sqliteErr = SQLITE_IOERR_NOMEM;
       
  1527 			break;
       
  1528 		default:
       
  1529 			break;
       
  1530 		}
       
  1531 	COsLayerData::Instance().SetOsErrorCode(err);
       
  1532 	return sqliteErr;
       
  1533 	}
       
  1534 
       
  1535 /**
       
  1536 SQLite OS porting layer API.
       
  1537 
       
  1538 Writes to the file referred by the aDbFile parameter.
       
  1539 "Write beyond the end of the file" operations are allowed.
       
  1540 
       
  1541 If the write operation is in the 1st db file page and there is a registered "free pages" callback 
       
  1542 (TDbFile::iFreePageCallback) and the free pages count is above the defined value,
       
  1543 then the callback will be called.
       
  1544 
       
  1545 @param aDbFile A pointer to a TDbFile instance, that contains the file handle to be written to.
       
  1546 @param aData The data to be written to the file. The buffer size must be at least aAmt bytes.
       
  1547 @param aAmt The amount of data to be written to the file.
       
  1548 @param aOffset The offset in the file where the write operation should start.
       
  1549 
       
  1550 @return SQLITE_FULL,       	The file write or seek operation has failed.
       
  1551 							The disk is full;
       
  1552 	    SQLITE_IOERR_NOMEM,	An out of memory condition has occured;
       
  1553 	    SQLITE_OK,			The operation has completed successfully.
       
  1554 	    
       
  1555 If the function succeeds, COsLayerData::SetOsErrorCode() is called with KErrNone, otherwise COsLayerData::SetOsErrorCode() is called
       
  1556 with the reported by the OS API error. The stored error code will be used later by the SQLite API caller.
       
  1557 	    
       
  1558 @see COsLayerData::SetOsErrorCode()
       
  1559 @see TDbFile
       
  1560 */
       
  1561 /* static */ int TFileIo::Write(sqlite3_file* aDbFile, const void* aData, int aAmt, sqlite3_int64 aOffset)
       
  1562 	{
       
  1563 	SQLUTRACE_PROFILER(aDbFile);
       
  1564 	SYMBIAN_TRACE_SQL_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EInternals), KFileWrite, aAmt, aOffset));
       
  1565 	TDbFile& dbFile = ::DbFile(aDbFile);
       
  1566 	__OS_CALL(EOsFileWrite, 0, 0);
       
  1567     __COUNTER_INCR(TheSqlSrvProfilerFileWrite);
       
  1568 	__OSTIME_COUNTER(TheOsCallTicks[EOsFileWrite], ::OsCallProfile(dbFile.iIsJournal, EOsFileWrite), aOffset, aAmt);
       
  1569 	TInt err = KErrAccessDenied;
       
  1570 	if(!dbFile.iReadOnly)
       
  1571 		{
       
  1572 		TPtrC8 ptr((const TUint8*)aData, aAmt);
       
  1573 		err = dbFile.iFileBuf.Write(aOffset, ptr);
       
  1574 		}
       
  1575 	COsLayerData::Instance().SetOsErrorCode(err);
       
  1576 	
       
  1577 	const TInt KFreePageCountOffset = 36;//hard-coded constant. SQLite does not offer anything - a constant or #define.
       
  1578 	//The checks in the "if" bellow do:
       
  1579 	// - "err == KErrNone" - check the free page count only after a successful "write";
       
  1580 	// - "aOffset == 0"    - check the free page count only if the write operation affects the system page (at aOffset = 0);
       
  1581 	// - "aAmt >= (KFreePageCountOffset + sizeof(int))" - check the free page count only if the amount of bytes to be written
       
  1582 	//						 is more than the offset of the free page counter (othewrise the free page counter is not affected
       
  1583 	//						 by this write operation);
       
  1584 	// - "dbFile.iFreePageCallback.IsValid()" - check the free page count only if there is a valid callback;
       
  1585 	if(err == KErrNone  && aOffset == 0 && aAmt >= (KFreePageCountOffset + sizeof(int)) && dbFile.iFreePageCallback.IsValid())
       
  1586 		{
       
  1587 		const TUint8* ptr = static_cast <const TUint8*> (aData) + KFreePageCountOffset;
       
  1588 		TInt freePageCount = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3];
       
  1589 		dbFile.iFreePageCallback.CheckAndCallback(freePageCount);
       
  1590 		}
       
  1591 		
       
  1592 	return err == KErrNone ? SQLITE_OK : (err == KErrNoMemory ? SQLITE_IOERR_NOMEM : SQLITE_FULL);
       
  1593 	}
       
  1594 
       
  1595 /**
       
  1596 SQLite OS porting layer API.
       
  1597 
       
  1598 Truncates the file referred by the aDbFile parameter.
       
  1599 
       
  1600 @param aDbFile A pointer to a TDbFile instance, that contains the file handle.
       
  1601 @param aLength The new file size in bytes.
       
  1602 
       
  1603 @return SQLITE_FULL,       	The disk is full;
       
  1604 		SQLITE_IOERR,		This is a read-only file.
       
  1605 	    					The file truncate operation has failed;
       
  1606 	    SQLITE_IOERR_NOMEM,	An out of memory condition has occured;
       
  1607 	    SQLITE_OK,			The operation has completed successfully.
       
  1608 	    
       
  1609 If the function succeeds, COsLayerData::SetOsErrorCode() is called with KErrNone, otherwise COsLayerData::SetOsErrorCode() is called
       
  1610 with the reported by the OS API error. The stored error code will be used later by the SQLite API caller.
       
  1611 
       
  1612 @see COsLayerData::SetOsErrorCode()
       
  1613 @see TDbFile
       
  1614 */
       
  1615 /* static */ int TFileIo::Truncate(sqlite3_file* aDbFile, sqlite3_int64 aLength)
       
  1616 	{
       
  1617 	SQLUTRACE_PROFILER(aDbFile);
       
  1618 	SYMBIAN_TRACE_SQL_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EInternals), KFileTruncate, aLength));
       
  1619 	TDbFile& dbFile = ::DbFile(aDbFile);
       
  1620 	__OS_CALL(EOsFileTruncate, 0, 0);
       
  1621     __COUNTER_INCR(TheSqlSrvProfilerFileSetSize);
       
  1622 	__OSTIME_COUNTER(TheOsCallTicks[EOsFileTruncate], ::OsCallProfile(dbFile.iIsJournal, EOsFileTruncate), aLength, 0);
       
  1623 	if(dbFile.iReadOnly)
       
  1624 		{
       
  1625 		COsLayerData::Instance().SetOsErrorCode(KErrAccessDenied);
       
  1626   		return SQLITE_IOERR;	
       
  1627 		}
       
  1628 	__FS_CALL(EFsOpFileSetSize, 0);
       
  1629 	TInt err = dbFile.iFileBuf.SetSize(aLength);
       
  1630 	COsLayerData::Instance().SetOsErrorCode(err);
       
  1631 	return err == KErrNone ? SQLITE_OK : (err == KErrNoMemory ? SQLITE_IOERR_NOMEM : SQLITE_IOERR);
       
  1632 	}
       
  1633 
       
  1634 /**
       
  1635 SQLite OS porting layer API.
       
  1636 
       
  1637 Flushes the file referred by the aDbFile parameter.
       
  1638 
       
  1639 @param aDbFile A pointer to a TDbFile instance, that contains the file handle.
       
  1640 
       
  1641 @return SQLITE_IOERR,		This is a read-only file.
       
  1642 	    					The file flush operation has failed;
       
  1643 	    SQLITE_IOERR_NOMEM,	An out of memory condition has occured;
       
  1644 	    SQLITE_OK,			The operation has completed successfully.
       
  1645 	    
       
  1646 If the function succeeds, COsLayerData::SetOsErrorCode() is called with KErrNone, otherwise COsLayerData::SetOsErrorCode() is called
       
  1647 with the reported by the OS API error. The stored error code will be used later by the SQLite API caller.
       
  1648 
       
  1649 @see COsLayerData::SetOsErrorCode()
       
  1650 @see TDbFile
       
  1651 */
       
  1652 /* static */int TFileIo::Sync(sqlite3_file* aDbFile, int /* aFlags */)
       
  1653 	{
       
  1654 	SQLUTRACE_PROFILER(aDbFile);
       
  1655 	TDbFile& dbFile = ::DbFile(aDbFile);
       
  1656 	__OS_CALL(EOsFileSync, 0, 0);
       
  1657     __COUNTER_INCR(TheSqlSrvProfilerFileSync);
       
  1658 	__OSTIME_COUNTER(TheOsCallTicks[EOsFileSync], ::OsCallProfile(dbFile.iIsJournal, EOsFileSync), 0, 0);
       
  1659 	if(dbFile.iReadOnly)
       
  1660 		{
       
  1661 		COsLayerData::Instance().SetOsErrorCode(KErrAccessDenied);
       
  1662 		return SQLITE_IOERR;
       
  1663 		}
       
  1664 	__FS_CALL(EFsOpFileSync, 0);
       
  1665 	TInt err = dbFile.iFileBuf.Flush();
       
  1666 	COsLayerData::Instance().SetOsErrorCode(err);
       
  1667 	return err == KErrNone ? SQLITE_OK : (err == KErrNoMemory ? SQLITE_IOERR_NOMEM : SQLITE_IOERR);
       
  1668 	}
       
  1669 
       
  1670 /**
       
  1671 SQLite OS porting layer API.
       
  1672 
       
  1673 Returns the size of the file referred by the aDbFile parameter.
       
  1674 
       
  1675 @param aDbFile A pointer to a TDbFile instance, that contains the file handle.
       
  1676 @param aSize Output parameter. If the function completes successfully, the file size will be stored there.
       
  1677 
       
  1678 @return SQLITE_IOERR,			The file size operation has failed;
       
  1679 	    SQLITE_IOERR_NOMEM,		An out of memory condition has occured;
       
  1680 	    SQLITE_OK,				The operation has completed successfully.
       
  1681 	    
       
  1682 If the function succeeds, COsLayerData::SetOsErrorCode() is called with KErrNone, otherwise COsLayerData::SetOsErrorCode() is called
       
  1683 with the reported by the OS API error. The stored error code will be used later by the SQLite API caller.
       
  1684 	    
       
  1685 @see COsLayerData::SetOsErrorCode()
       
  1686 @see TDbFile
       
  1687 */
       
  1688 /* static */ int TFileIo::FileSize(sqlite3_file* aDbFile, sqlite3_int64* aSize)
       
  1689 	{
       
  1690 	SQLUTRACE_PROFILER(aDbFile);
       
  1691 	TDbFile& dbFile = ::DbFile(aDbFile);
       
  1692 	__OS_CALL(EOsFileFileSize, 0, 0);
       
  1693 	__OSTIME_COUNTER(TheOsCallTicks[EOsFileFileSize], ::OsCallProfile(dbFile.iIsJournal, EOsFileFileSize), 0, 0);
       
  1694 	__FS_CALL(EFsOpFileSize, 0);
       
  1695 	TInt err =  dbFile.iFileBuf.Size(*aSize);
       
  1696 	COsLayerData::Instance().SetOsErrorCode(err);
       
  1697 	if(err == KErrNone)
       
  1698 		{
       
  1699 		return SQLITE_OK;
       
  1700 		}
       
  1701 	return err == KErrNoMemory ? SQLITE_IOERR_NOMEM : SQLITE_IOERR;
       
  1702 	}
       
  1703 
       
  1704 /**
       
  1705 SQLite OS porting layer API.
       
  1706 
       
  1707 Locks the file, referred by the aDbFile parameter, with the specified lock type.
       
  1708 Since this is a single-threaded OS porting layer implementation, the file is not actually locked - small
       
  1709 performance optimisation. The file lock type is stored for later use by the CheckReservedLock() call.
       
  1710 
       
  1711 @param aDbFile A pointer to a TDbFile instance, that contains the file handle.
       
  1712 @param aLockType Lock type: SQLITE_LOCK_NONE, SQLITE_LOCK_SHARED, SQLITE_LOCK_RESERVED, SQLITE_LOCK_PENDING or
       
  1713 				 SQLITE_LOCK_EXCLUSIVE.
       
  1714 
       
  1715 @return SQLITE_OK,	The operation has completed successfully.
       
  1716 
       
  1717 @see TFileIo::CheckReservedLock()
       
  1718 @see TFileIo::Unlock()
       
  1719 	    
       
  1720 @see TDbFile
       
  1721 */
       
  1722 /* static */ int TFileIo::Lock(sqlite3_file* aDbFile, int aLockType)
       
  1723 	{
       
  1724 	SQLUTRACE_PROFILER(aDbFile);
       
  1725 	TDbFile& dbFile = ::DbFile(aDbFile);
       
  1726 	__OS_CALL(EOsFileLock, 0, 0);
       
  1727 	__OSTIME_COUNTER(TheOsCallTicks[EOsFileLock], ::OsCallProfile(dbFile.iIsJournal, EOsFileLock), aLockType, 0);
       
  1728 	//If there is already a lock of this type or more restrictive on the database file, do nothing.
       
  1729 	if(dbFile.iLockType >= aLockType)
       
  1730 		{
       
  1731 		return SQLITE_OK;
       
  1732 		}
       
  1733 	dbFile.iLockType = aLockType;
       
  1734 	return SQLITE_OK;
       
  1735 	}
       
  1736 
       
  1737 /**
       
  1738 SQLite OS porting layer API.
       
  1739 
       
  1740 Unlocks the file, referred by the aDbFile parameter.
       
  1741 Since this is a single-threaded OS porting layer implementation, the file never gets locked - small
       
  1742 performance optimisation. The Unlock() call only sets the stored file lock type with the aLockType value.
       
  1743 
       
  1744 @param aDbFile A pointer to a TDbFile instance, that contains the file handle.
       
  1745 @param aLockType Lock type: SQLITE_LOCK_NONE, SQLITE_LOCK_SHARED, SQLITE_LOCK_RESERVED, SQLITE_LOCK_PENDING or
       
  1746 				 SQLITE_LOCK_EXCLUSIVE.
       
  1747 
       
  1748 @return SQLITE_OK,	The operation has completed successfully.
       
  1749 
       
  1750 @see TFileIo::CheckReservedLock()
       
  1751 @see TFileIo::Lock()
       
  1752 	    
       
  1753 @see TDbFile
       
  1754 */
       
  1755 /* static */ int TFileIo::Unlock(sqlite3_file* aDbFile, int aLockType)
       
  1756 	{
       
  1757 	SQLUTRACE_PROFILER(aDbFile);
       
  1758 	TDbFile& dbFile = ::DbFile(aDbFile);
       
  1759 	__OS_CALL(EOsFileUnlock, 0, 0);
       
  1760 	__OSTIME_COUNTER(TheOsCallTicks[EOsFileUnlock], ::OsCallProfile(dbFile.iIsJournal, EOsFileUnlock), aLockType, 0);
       
  1761 	dbFile.iLockType = aLockType;
       
  1762 	return SQLITE_OK;
       
  1763 	}
       
  1764 
       
  1765 /**
       
  1766 SQLite OS porting layer API.
       
  1767 
       
  1768 Checks if the file lock type is SQLITE_LOCK_RESERVED or bigger.
       
  1769 Since this is a single-threaded OS porting layer implementation, the file never gets locked - small
       
  1770 performance optimisation. The CheckReservedLock() call only checks if the stored file lock type 
       
  1771 is bigger or equal than SQLITE_LOCK_RESERVED.
       
  1772 
       
  1773 @param aDbFile A pointer to a TDbFile instance, that contains the file handle.
       
  1774 @param aResOut Output parameter. It should be set to 1 if the stored lock type is bigger or equal 
       
  1775 							     than SQLITE_LOCK_RESERVED.
       
  1776 
       
  1777 @return SQLITE_OK.
       
  1778 
       
  1779 @see TFileIo::Lock()
       
  1780 @see TFileIo::Unlock()
       
  1781 	    
       
  1782 @see TDbFile
       
  1783 */
       
  1784 /* static */ int TFileIo::CheckReservedLock(sqlite3_file* aDbFile, int *aResOut)
       
  1785 	{
       
  1786 	SQLUTRACE_PROFILER(aDbFile);
       
  1787 	TDbFile& dbFile = ::DbFile(aDbFile);
       
  1788 	__OS_CALL(EOsFileCheckReservedLock, 0, 0);
       
  1789 	__OSTIME_COUNTER(TheOsCallTicks[EOsFileCheckReservedLock], ::OsCallProfile(dbFile.iIsJournal, EOsFileCheckReservedLock), 0, 0);
       
  1790 	*aResOut = dbFile.iLockType >= SQLITE_LOCK_RESERVED ? 1 : 0;
       
  1791   	return SQLITE_OK;
       
  1792 	}
       
  1793 
       
  1794 /**
       
  1795 SQLite OS porting layer API.
       
  1796 
       
  1797 Performs an aOp operation on the file referred by the aDbFile parameter.
       
  1798 Since the only supported operation at the moment is SQLITE_FCNTL_LOCKSTATE, and the current lock type is stored as
       
  1799 a data memebr of TDbFile, the function implementation has been optimised - no file I/O calls. The stored file lock type
       
  1800 is retured if the operation is SQLITE_FCNTL_LOCKSTATE.
       
  1801 
       
  1802 Note: The range of supported operations includes KSqlFcntlRegisterFreePageCallback now.
       
  1803       When the function is called with aOp = KSqlFcntlRegisterFreePageCallback, then a callback will be registered
       
  1804       and called when the number of the free pages goes above certain threshold.
       
  1805 
       
  1806 @param aDbFile A pointer to a TDbFile instance, that contains the file handle.
       
  1807 @param aOp File operation type. Currently only SQLITE_FCNTL_LOCKSTATE is supported.
       
  1808 @param aArg An additional input/output parameter which purpose depends on the type of the current file operation.
       
  1809 			If the file operation is SQLITE_FCNTL_LOCKSTATE, then aArg is used as an output parameter, where
       
  1810 			the file lock type is stored.
       
  1811 			If the operation type is KSqlFcntlRegisterFreePageCallback, then aArg points to a TSqlFreePageCallback object,
       
  1812 			that contains the free page threshold and the callback.
       
  1813 
       
  1814 @return SQLITE_ERROR,	Non-supported operation;
       
  1815 		SQLITE_OK,		The operation has completed successfully.
       
  1816 	    
       
  1817 @see TDbFile
       
  1818 */
       
  1819 /* static */ int TFileIo::FileControl(sqlite3_file* aDbFile, int aOp, void* aArg)
       
  1820 	{
       
  1821 	SQLUTRACE_PROFILER(aDbFile);
       
  1822 	SYMBIAN_TRACE_SQL_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EInternals), KFileFileCtr, aOp));
       
  1823 	TDbFile& dbFile = ::DbFile(aDbFile);
       
  1824 	__OS_CALL(EOsFileFileControl, 0, 0);
       
  1825 	__OSTIME_COUNTER(TheOsCallTicks[EOsFileFileControl], ::OsCallProfile(dbFile.iIsJournal, EOsFileFileControl), aOp, 0);
       
  1826 	TInt err = KErrNone;
       
  1827 	switch(aOp)
       
  1828 		{
       
  1829 		case SQLITE_FCNTL_LOCKSTATE:
       
  1830 			*(int*)aArg = dbFile.iLockType;
       
  1831 			break;
       
  1832 		case KSqlFcntlRegisterFreePageCallback:
       
  1833 			{
       
  1834 			err = KErrArgument;
       
  1835 			if(aArg)
       
  1836 				{
       
  1837 				TSqlFreePageCallback* rq = static_cast <TSqlFreePageCallback*> (aArg);
       
  1838 				if(rq->IsValid())
       
  1839 					{
       
  1840 					dbFile.iFreePageCallback = *rq;
       
  1841 					err = KErrNone;
       
  1842 					}
       
  1843 				}
       
  1844 			}
       
  1845 			break;
       
  1846 		default:
       
  1847 			err = KErrArgument;
       
  1848 			break;
       
  1849 		}
       
  1850 	COsLayerData::Instance().SetOsErrorCode(err);
       
  1851 	return err == KErrNone ? SQLITE_OK : SQLITE_ERROR;
       
  1852 	}
       
  1853 
       
  1854 /**
       
  1855 SQLite OS porting layer API.
       
  1856 
       
  1857 Retrieves the sector size of the media of the file referred by the aDbFile parameter.
       
  1858 Since the sector size never changes till the file is open, the function has been optimised - no file I/O calls.
       
  1859 The sector size is retrieved during the TVfs::Open() call and stored in TDbFile::iSectorSize. The SectorSize()
       
  1860 call returns the value of TDbFile::iSectorSize.
       
  1861 
       
  1862 @param aDbFile A pointer to a TDbFile instance, that contains the file handle.
       
  1863 
       
  1864 @return The sector size.
       
  1865 
       
  1866 @panic Sqlite 19 In _DEBUG mode - TDbFile::iSectorSize is negative or 0 .
       
  1867 	    
       
  1868 @see TDbFile
       
  1869 @see TVfs::Open()
       
  1870 */
       
  1871 /* static */ int TFileIo::SectorSize(sqlite3_file* aDbFile)
       
  1872 	{
       
  1873 	SQLUTRACE_PROFILER(aDbFile);
       
  1874 	TDbFile& dbFile = ::DbFile(aDbFile);
       
  1875 	__OS_CALL(EOsFileSectorSize, 0, 0);
       
  1876 	__OSTIME_COUNTER(TheOsCallTicks[EOsFileSectorSize], ::OsCallProfile(dbFile.iIsJournal, EOsFileSectorSize), 0, 0);
       
  1877 	__ASSERT_DEBUG(dbFile.iSectorSize > 0, User::Panic(KPanicCategory, EPanicInternalError));
       
  1878 	if(dbFile.iSectorSize > 0)
       
  1879 		{
       
  1880 		return dbFile.iSectorSize;	
       
  1881 		}
       
  1882 	return SQLITE_DEFAULT_SECTOR_SIZE;
       
  1883 	}
       
  1884 
       
  1885 /**
       
  1886 SQLite OS porting layer API.
       
  1887 
       
  1888 Retrieves the device characteristics of the device of the file referred by the aDbFile parameter.
       
  1889 Since the device characteristics never change till the file is open, the function has been optimised - no file I/O calls.
       
  1890 The device characteristics are retrieved during the TVfs::Open() call and stored in TDbFile::iDeviceCharacteristics. 
       
  1891 The DeviceCharacteristics() call returns the value of TDbFile::iDeviceCharacteristics.
       
  1892 
       
  1893 @param aDbFile A pointer to a TDbFile instance, that contains the file handle.
       
  1894 
       
  1895 @return A bit set containing the device characteristics.
       
  1896 	    
       
  1897 @panic Sqlite 19 In _DEBUG mode - TDbFile::iDeviceCharacteristics is negative or 0 .
       
  1898 
       
  1899 @see TDbFile
       
  1900 @see TVfs::Open()
       
  1901 */
       
  1902 /* static */ int TFileIo::DeviceCharacteristics(sqlite3_file* aDbFile)
       
  1903 	{
       
  1904 	SQLUTRACE_PROFILER(aDbFile);
       
  1905 	TDbFile& dbFile = ::DbFile(aDbFile);
       
  1906 	__OS_CALL(EOsFileDeviceCharacteristics, 0, 0);
       
  1907 	__OSTIME_COUNTER(TheOsCallTicks[EOsFileDeviceCharacteristics], ::OsCallProfile(dbFile.iIsJournal, EOsFileDeviceCharacteristics), 0, 0);
       
  1908 	__ASSERT_DEBUG(dbFile.iDeviceCharacteristics >= 0, User::Panic(KPanicCategory, EPanicInternalError));
       
  1909 	if(dbFile.iDeviceCharacteristics >= 0)
       
  1910 		{
       
  1911 		return dbFile.iDeviceCharacteristics;	
       
  1912 		}
       
  1913 	return 0;
       
  1914 	}
       
  1915 
       
  1916 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
  1917 ///////////////////////////////////       TVfs class definition     ///////////////////////////////////////////////////////////
       
  1918 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
  1919 
       
  1920 
       
  1921 /**
       
  1922 Opens a private secure database.
       
  1923 Actually the database file has been created or opened by the client's process. 
       
  1924 This function only adopts the passed in aMsg parameter file handle.
       
  1925 
       
  1926 @param aDbFile 		Output parameter, where the initialized file handle will be stored.
       
  1927 @param aMsg    		A reference to the current RMessage2 instance. Contains the file handle of the database created
       
  1928 					or opened by the client's process.
       
  1929 @param aReadOnly	True if the file is read-only.
       
  1930 
       
  1931 @return KErrNone,          The operation has completed succesfully;
       
  1932 	    KErrNoMemory,      Out of memory condition has occured;
       
  1933                            Note that other system-wide error codes may also be returned.
       
  1934 	    
       
  1935 @see TDbFile
       
  1936 @see TVfs::Open()
       
  1937 */
       
  1938 /* static */ TInt TVfs::DoOpenFromHandle(TDbFile& aDbFile, const RMessage2& aMsg, TBool aReadOnly)
       
  1939 	{
       
  1940 	__FS_CALL(EFsOpFileAdopt, 0);
       
  1941 	TInt err = aDbFile.iFileBuf.AdoptFromClient(aMsg, KFhSessHandleIdx, KFhFileHandleIdx);
       
  1942 	if(err == KErrNone)
       
  1943 		{
       
  1944 		aDbFile.iReadOnly = aReadOnly;
       
  1945 		}
       
  1946 	return err;
       
  1947 	};
       
  1948 
       
  1949 /**
       
  1950 Collects information about the drive referred by the aDriveNo parameter.
       
  1951 
       
  1952 @param aFs			RFs instance.
       
  1953 @param aDriveNo     The drive about which an information will be collected.
       
  1954 @param aVolumeInfo	Output parameter. A reference to a TVolumeIOParamInfo object where the collected information will be stored.
       
  1955 
       
  1956 @return KErrNone,          The operation has completed succesfully;
       
  1957 	    KErrNoMemory,      Out of memory condition has occured;
       
  1958                            Note that other system-wide error codes may also be returned.
       
  1959 	    
       
  1960 @see TVfs::Open()
       
  1961 */
       
  1962 /* static */ inline TInt TVfs::DoGetVolumeIoParamInfo(RFs& aFs, TInt aDriveNo, TVolumeIOParamInfo& aVolumeInfo)
       
  1963 	{
       
  1964 	__FS_CALL(EFsOpFsVolumeIoParam, 0);
       
  1965 	return aFs.VolumeIOParam(aDriveNo, aVolumeInfo);
       
  1966 	}
       
  1967 
       
  1968 /**
       
  1969 Retrieves and returns in a bit set the device characteristics.
       
  1970 
       
  1971 @param aDriveInfo	A TDriveInfo reference from which the device characteristics will be extracted.
       
  1972 @param aVolumeInfo	A TVolumeIOParamInfo reference from which the device characteristics will be extracted.
       
  1973 
       
  1974 @return A bit set containing the device characteristics: 
       
  1975 			SQLITE_IOCAP_SAFE_APPEND, SQLITE_IOCAP_ATOMIC, the atomic block size.
       
  1976 	    
       
  1977 @see TVfs::DoGetVolumeIoParamInfo();
       
  1978 @see TVfs::Open()
       
  1979 */
       
  1980 /* static */ TInt TVfs::DoGetDeviceCharacteristics(const TDriveInfo& aDriveInfo, const TVolumeIOParamInfo& aVolumeInfo)
       
  1981 	{
       
  1982 	TInt deviceCharacteristics = 0;	
       
  1983 	if(aDriveInfo.iDriveAtt & (KDriveAttLocal | KDriveAttInternal))
       
  1984 		{
       
  1985 		deviceCharacteristics |= SQLITE_IOCAP_SAFE_APPEND;//Data written first, file size updated second
       
  1986 		}
       
  1987 	if(aDriveInfo.iDriveAtt & KDriveAttTransaction)
       
  1988 		{
       
  1989 		deviceCharacteristics |= SQLITE_IOCAP_ATOMIC;	
       
  1990 		}
       
  1991 	if(aVolumeInfo.iBlockSize >= SQLITE_DEFAULT_SECTOR_SIZE && (aVolumeInfo.iBlockSize & (aVolumeInfo.iBlockSize - 1)) == 0)	
       
  1992 		{
       
  1993 		switch(aVolumeInfo.iBlockSize)
       
  1994 			{
       
  1995 			case 512:
       
  1996 				deviceCharacteristics |= SQLITE_IOCAP_ATOMIC512;
       
  1997 				break;
       
  1998 			case 1024:
       
  1999 				deviceCharacteristics |= SQLITE_IOCAP_ATOMIC1K;
       
  2000 				break;
       
  2001 			case 2048:
       
  2002 				deviceCharacteristics |= SQLITE_IOCAP_ATOMIC2K;
       
  2003 				break;
       
  2004 			case 4096:
       
  2005 				deviceCharacteristics |= SQLITE_IOCAP_ATOMIC4K;
       
  2006 				break;
       
  2007 			case 8192:
       
  2008 				deviceCharacteristics |= SQLITE_IOCAP_ATOMIC8K;
       
  2009 				break;
       
  2010 			case 16384:
       
  2011 				deviceCharacteristics |= SQLITE_IOCAP_ATOMIC16K;
       
  2012 				break;
       
  2013 			case 32768:
       
  2014 				deviceCharacteristics |= SQLITE_IOCAP_ATOMIC32K;
       
  2015 				break;
       
  2016 			case 65536:
       
  2017 				deviceCharacteristics |= SQLITE_IOCAP_ATOMIC64K;
       
  2018 				break;
       
  2019 			default:
       
  2020 				//Do nothing. deviceCharacteristics was initialized with 0 at the beginning of the function body.
       
  2021 				break;
       
  2022 			}
       
  2023 		}
       
  2024 	return deviceCharacteristics;
       
  2025 	}
       
  2026 
       
  2027 /**
       
  2028 Retrieves and returns the sector size of the drive referred by the aDriveInfo parameter.
       
  2029 The sector size must be a power of two.
       
  2030 The sector size is extracted only if aDriveInfo refers to a removable device, otherwise the
       
  2031 SQLITE_DEFAULT_SECTOR_SIZE value (512 bytes) will be used as a sector size.
       
  2032 
       
  2033 @param aDriveInfo	A TDriveInfo reference.
       
  2034 @param aVolumeInfo	A TVolumeIOParamInfo reference.
       
  2035 
       
  2036 @return The sector size of the drive referred by the aDriveInfo parameter.
       
  2037 
       
  2038 @panic Sqlite 19 In _DEBUG mode - The sector size is negative, zero or is not a power of two.
       
  2039 	    
       
  2040 @see TVfs::Open()
       
  2041 */
       
  2042 /* static */ TInt TVfs::DoGetSectorSize(const TDriveInfo& aDriveInfo, const TVolumeIOParamInfo& aVolumeInfo)
       
  2043 	{
       
  2044 	//Initialize the sectorSize variable only if: 
       
  2045 	// - aDriveInfo refers to a removable drive
       
  2046 	// - aVolumeInfo.iBlockSize > SQLITE_DEFAULT_SECTOR_SIZE;
       
  2047 	// - aVolumeInfo.iBlockSize is power of 2;
       
  2048 	TInt sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
       
  2049 	if(aDriveInfo.iDriveAtt & KDriveAttRemovable)
       
  2050 		{
       
  2051 		if(aVolumeInfo.iBlockSize > SQLITE_DEFAULT_SECTOR_SIZE && (aVolumeInfo.iBlockSize & (aVolumeInfo.iBlockSize - 1)) == 0)
       
  2052 			{
       
  2053 			sectorSize = aVolumeInfo.iBlockSize;
       
  2054 			}
       
  2055 		}
       
  2056 	__ASSERT_DEBUG(sectorSize > 0 && (sectorSize & (sectorSize - 1)) == 0, User::Panic(KPanicCategory, EPanicInternalError));
       
  2057 	return sectorSize;
       
  2058 	}
       
  2059 
       
  2060 /**
       
  2061 Retrieves in a bit set the device characteristics of the device of the file referred by the aDbFile parameter.
       
  2062 Retrieves the sector size of the drive of the file referred by the aDbFile parameter. 
       
  2063 The sector size and the device characteristics will be stored in iSectorSize and iDeviceCharacteristics TDbFile data members.
       
  2064 The stored values will be used later by TFileIo::DeviceCharacteristics() and TFileIo::SectorSize().
       
  2065 
       
  2066 @param aDbFile	Input/Output parameter. A TDriveInfo reference. The collected information will be stored in TDbDrive
       
  2067 				data members.
       
  2068 @param aRecReadBufSize Output parameter. The recommended buffer size for optimised reading performance.
       
  2069 
       
  2070 @return KErrNone,          The operation has completed succesfully;
       
  2071                            Note that other system-wide error codes may also be returned.
       
  2072 
       
  2073 @panic Sqlite 19 In _DEBUG mode - TDbFile::iSectorSize has been already initialized.
       
  2074 @panic Sqlite 19 In _DEBUG mode - TDbFile::iDeviceCharacteristics has been already initialized.
       
  2075 
       
  2076 @see TVfs::DoGetDeviceCharacteristics();
       
  2077 @see TVfs::DoGetSectorSize();
       
  2078 @see TVfs::Open()
       
  2079 @see TDbFile
       
  2080 @see TFileIo::DeviceCharacteristics()
       
  2081 @see TFileIo::SectorSize()
       
  2082 */
       
  2083 /* static */ TInt TVfs::DoGetDeviceCharacteristicsAndSectorSize(TDbFile& aDbFile, TInt& aRecReadBufSize)
       
  2084 	{
       
  2085 	__ASSERT_DEBUG(aDbFile.iDeviceCharacteristics < 0, User::Panic(KPanicCategory, EPanicInternalError));
       
  2086 	__ASSERT_DEBUG(aDbFile.iSectorSize <= 0, User::Panic(KPanicCategory, EPanicInternalError));
       
  2087 	TInt driveNo;
       
  2088 	TDriveInfo driveInfo;
       
  2089 	__FS_CALL(EFsOpFileDrive, 0);
       
  2090 	TInt err = aDbFile.iFileBuf.Drive(driveNo, driveInfo);
       
  2091 	if(err != KErrNone)
       
  2092 		{
       
  2093 		return err;	
       
  2094 		}
       
  2095 	TVolumeIOParamInfo volumeInfo;
       
  2096 	err = TVfs::DoGetVolumeIoParamInfo(COsLayerData::Instance().iFs, driveNo, volumeInfo);
       
  2097 	if(err != KErrNone)
       
  2098 		{
       
  2099 		return err;	
       
  2100 		}
       
  2101 	aDbFile.iDeviceCharacteristics = TVfs::DoGetDeviceCharacteristics(driveInfo, volumeInfo);
       
  2102 	aDbFile.iSectorSize = TVfs::DoGetSectorSize(driveInfo, volumeInfo);
       
  2103 	aRecReadBufSize = volumeInfo.iRecReadBufSize;
       
  2104 	return KErrNone;
       
  2105 	}
       
  2106 
       
  2107 /**
       
  2108 SQLite OS porting layer API.
       
  2109 
       
  2110 Opens or creates a file which name is in the aFileName parameter.
       
  2111 If the function succeeds, the file handle and other related information will be stored in the place pointed by the 
       
  2112 aDbFile parameter, a memory block of sizeof(TDbFile) size for which is allocated by the caller.
       
  2113 The function will also retrieve the sector size and the device characteristics and store them in aDbFile,
       
  2114 which is actually a TDbFile pointer, for later use.
       
  2115 
       
  2116 @param aFileName Zero-terminated, UTF8 encoded file name.
       
  2117 				 If aFileName is NULL then a temporary file is created.
       
  2118 @param aDbFile Output parameter. The file handle and other related information will be stored there.
       
  2119 @param aFlags  "Open/Create" input flags: 
       
  2120 					SQLITE_OPEN_DELETEONCLOSE,
       
  2121 					SQLITE_OPEN_READWRITE,
       
  2122 					SQLITE_OPEN_EXCLUSIVE,
       
  2123 					SQLITE_OPEN_CREATE
       
  2124 @param aOutFlags  "Open/Create" output flags:
       
  2125 					SQLITE_OPEN_READWRITE,
       
  2126 					SQLITE_OPEN_READONLY
       
  2127 
       
  2128 @return SQLITE_CANTOPEN,    The aFileName parameter cannot be converted to UTF16.
       
  2129 							Any other file I/O error will also be reported as SQLITE_CANTOPEN;
       
  2130 	    SQLITE_IOERR_NOMEM,	An out of memory condition has occured;
       
  2131 	    SQLITE_OK,			The operation has completed successfully.
       
  2132 	    
       
  2133 If the function succeeds, COsLayerData::SetOsErrorCode() is called with KErrNone, otherwise COsLayerData::SetOsErrorCode() is called
       
  2134 with the reported by the OS API error. The stored error code will be used later by the SQLite API caller.
       
  2135 
       
  2136 @see COsLayerData::SetOsErrorCode()
       
  2137 @see TDbFile
       
  2138 */
       
  2139 /* static */ int TVfs::Open(sqlite3_vfs* aVfs, const char* aFileName, sqlite3_file* aDbFile, int aFlags, int* aOutFlags)
       
  2140 	{
       
  2141 	SQLUTRACE_PROFILER(aVfs);
       
  2142 	__OS_CALL(EOsVfsOpen, 0, 0);
       
  2143 	__OSTIME_COUNTER(TheOsCallTicks[EOsVfsOpen], ::OsCallProfile(EFalse, EOsVfsOpen), 0, 0);
       
  2144 	COsLayerData& osLayerData = COsLayerData::Instance();
       
  2145 	TFileName fname;
       
  2146 	if(aFileName && !::ConvertToUnicode(aFileName, fname))
       
  2147 		{
       
  2148 		osLayerData.SetOsErrorCode(KErrBadName);
       
  2149 		return SQLITE_CANTOPEN;	
       
  2150 		}
       
  2151 	SYMBIAN_TRACE_SQL_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EInternals), KFileOpen, aDbFile, &fname));
       
  2152 	new (aDbFile) TDbFile;
       
  2153 	TDbFile& dbFile = ::DbFile(aDbFile);
       
  2154 	TFhStrType fhStrType = aFileName ? ::FhStringProps(aFileName) : ENotFhStr;
       
  2155 	if(aFileName && (aFlags & SQLITE_OPEN_DELETEONCLOSE))
       
  2156 		{
       
  2157 		dbFile.iFullName = fname.Alloc();
       
  2158 		if(!dbFile.iFullName)
       
  2159 			{
       
  2160 			osLayerData.SetOsErrorCode(KErrNoMemory);
       
  2161 			return SQLITE_IOERR_NOMEM;
       
  2162 			}
       
  2163 		}
       
  2164 	TInt recReadBufSize = -1;
       
  2165 	TInt err = KErrNone;
       
  2166 	if(fhStrType == EFhMainDbStr)
       
  2167 		{//Main db file, open from handle
       
  2168 		const RMessage2* msg;
       
  2169 		TBool readOnly;
       
  2170 		osLayerData.RetrieveAndResetFhData(msg, readOnly);
       
  2171 		err = msg != NULL ? TVfs::DoOpenFromHandle(dbFile, *msg, readOnly) : KErrGeneral;
       
  2172 		}
       
  2173 	else
       
  2174 		{
       
  2175 		if(fhStrType == EFhStr)
       
  2176 			{//Not the main db file. Replace invalid characters in the file name
       
  2177 			::FhConvertToFileName(fname, osLayerData.iSysPrivDir);//If fname does not have a path, iSysPrivDir will be used
       
  2178 			}
       
  2179 		TInt fmode = EFileRead;
       
  2180 		if(aFlags & SQLITE_OPEN_READWRITE)
       
  2181 			{
       
  2182 			fmode |= EFileWrite;
       
  2183 			}
       
  2184 		if(aFlags & SQLITE_OPEN_EXCLUSIVE)
       
  2185 			{
       
  2186 			fmode |= EFileShareExclusive;
       
  2187 			}
       
  2188 		if(!aFileName)	
       
  2189 			{
       
  2190 			__FS_CALL(EFsOpFileCreateTemp, 0);
       
  2191 			err = dbFile.iFileBuf.Temp(osLayerData.iFs, osLayerData.iSysPrivDir, fname, fmode);
       
  2192 			if(err == KErrNone)
       
  2193 				{
       
  2194 				dbFile.iFullName = fname.Alloc();
       
  2195 				if(!dbFile.iFullName)
       
  2196 					{
       
  2197 					err = KErrNoMemory;	
       
  2198 					}
       
  2199 				}
       
  2200 			}
       
  2201 		else
       
  2202 			{
       
  2203 			err = KErrAccessDenied;
       
  2204 			TInt prevErr = KErrNone;
       
  2205 			if(aFlags & SQLITE_OPEN_CREATE)
       
  2206 				{
       
  2207 				__FS_CALL(EFsOpFileCreate, 0);
       
  2208 				prevErr = err = dbFile.iFileBuf.Create(osLayerData.iFs, fname, fmode);
       
  2209 				}
       
  2210 			if(err != KErrNone && err != KErrNoMemory && err != KErrDiskFull)
       
  2211 				{
       
  2212 				__FS_CALL(EFsOpFileOpen, 0);
       
  2213 				err = dbFile.iFileBuf.Open(osLayerData.iFs, fname, fmode);
       
  2214 				}
       
  2215 			if((err != KErrNone && err != KErrNoMemory && err != KErrDiskFull) && (aFlags & SQLITE_OPEN_READWRITE))
       
  2216 				{
       
  2217 				aFlags &= ~SQLITE_OPEN_READWRITE;
       
  2218 				aFlags |= SQLITE_OPEN_READONLY;
       
  2219 				fmode &= ~EFileWrite;
       
  2220 				__FS_CALL(EFsOpFileOpen, 0);
       
  2221    				err = dbFile.iFileBuf.Open(osLayerData.iFs, fname, fmode);
       
  2222    				}
       
  2223 			if(err != KErrNone && prevErr == KErrAccessDenied)
       
  2224 				{
       
  2225 				err = KErrAccessDenied;
       
  2226 				}
       
  2227 			}
       
  2228 		}
       
  2229 	if(err == KErrNone)
       
  2230 		{
       
  2231 		err = TVfs::DoGetDeviceCharacteristicsAndSectorSize(dbFile, recReadBufSize);
       
  2232 		}
       
  2233 	osLayerData.SetOsErrorCode(err);
       
  2234 	if(err != KErrNone)
       
  2235 		{
       
  2236 		__FS_CALL(EFsOpFileClose, 0);
       
  2237 		dbFile.iFileBuf.Close();	
       
  2238 		delete dbFile.iFullName;
       
  2239 		dbFile.iFullName = NULL;
       
  2240 		}
       
  2241 	else
       
  2242 		{
       
  2243 		dbFile.pMethods = &TheFileIoApi;
       
  2244 		if(fhStrType != EFhMainDbStr)
       
  2245 			{
       
  2246 			dbFile.iReadOnly = !(aFlags & SQLITE_OPEN_READWRITE);
       
  2247 			}
       
  2248 		if(aOutFlags)
       
  2249 			{
       
  2250 			*aOutFlags = dbFile.iReadOnly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_READWRITE;
       
  2251 			}
       
  2252 		(void)dbFile.iFileBuf.SetReadAheadSize(dbFile.iSectorSize, recReadBufSize);
       
  2253 		}
       
  2254 #ifdef _SQLPROFILER
       
  2255 	dbFile.iIsJournal = (aFlags & SQLITE_OPEN_MAIN_JOURNAL) || (aFlags & SQLITE_OPEN_TEMP_JOURNAL) || 
       
  2256 						(aFlags & SQLITE_OPEN_SUBJOURNAL) || (aFlags & SQLITE_OPEN_MASTER_JOURNAL);
       
  2257 #endif
       
  2258 	return err == KErrNone ? SQLITE_OK : (err == KErrNoMemory ? SQLITE_IOERR_NOMEM : SQLITE_CANTOPEN);
       
  2259 	}
       
  2260 
       
  2261 /**
       
  2262 SQLite OS porting layer API.
       
  2263 
       
  2264 Deletes a file which name is in the aFileName parameter.
       
  2265 
       
  2266 @param aFileName Zero-terminated, UTF8 encoded file name.
       
  2267 
       
  2268 @return SQLITE_ERROR,    	The aFileName parameter cannot be converted to UTF16.
       
  2269 							The file name refers to a private secure database;
       
  2270 	    SQLITE_IOERR_NOMEM,	An out of memory condition has occured;
       
  2271 	    SQLITE_IOERR_DELETE,The delete file operation has failed;
       
  2272 	    SQLITE_OK,			The operation has completed successfully.
       
  2273 	    
       
  2274 If the function succeeds, COsLayerData::SetOsErrorCode() is called with KErrNone, otherwise COsLayerData::SetOsErrorCode() is called
       
  2275 with the reported by the OS API error. The stored error code will be used later by the SQLite API caller.
       
  2276 
       
  2277 @see COsLayerData::SetOsErrorCode()
       
  2278 */
       
  2279 /* static */ int TVfs::Delete(sqlite3_vfs* aVfs, const char* aFileName, int /*aSyncDir*/)
       
  2280 	{
       
  2281 	SQLUTRACE_PROFILER(aVfs);
       
  2282 	__OS_CALL(EOsVfsDelete, 0, 0);
       
  2283 	__OSTIME_COUNTER(TheOsCallTicks[EOsVfsDelete], ::OsCallProfile(EFalse, EOsVfsDelete), 0, 0);
       
  2284 	COsLayerData& osLayerData = COsLayerData::Instance();
       
  2285 	TBuf<KMaxFileName + 1> fname;
       
  2286 	if(!::ConvertToUnicode(aFileName, fname))
       
  2287 		{
       
  2288 		osLayerData.SetOsErrorCode(KErrBadName);
       
  2289 		return SQLITE_ERROR;	
       
  2290 		}
       
  2291 	SYMBIAN_TRACE_SQL_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EInternals), KFileName, &fname));
       
  2292 	TFhStrType fhStrType = FhStringProps(aFileName);
       
  2293 	if(fhStrType == EFhMainDbStr)
       
  2294 		{//Deleting files not in your own private data cage - not allowed!
       
  2295 		osLayerData.SetOsErrorCode(KErrPermissionDenied);
       
  2296 		return SQLITE_ERROR;	
       
  2297 		}
       
  2298 	if(fhStrType == EFhStr)
       
  2299 		{
       
  2300 		::FhConvertToFileName(fname, osLayerData.iSysPrivDir);//If fname does not have a path, iSysPrivDir will be used
       
  2301 		}
       
  2302 	__FS_CALL(EFsOpFileDelete, 0);
       
  2303 	TInt err = osLayerData.iFs.Delete(fname);
       
  2304 	osLayerData.SetOsErrorCode(err);
       
  2305 	return err == KErrNone ? SQLITE_OK : (err == KErrNoMemory ? SQLITE_IOERR_NOMEM : SQLITE_IOERR_DELETE);
       
  2306 	}
       
  2307 
       
  2308 /**
       
  2309 SQLite OS porting layer API.
       
  2310 
       
  2311 Retrieves an information about a file which name is in the aFileName parameter.
       
  2312 The requested information type can be: does the file exist, is the file read-only or read/write.
       
  2313 
       
  2314 @param aFileName Zero-terminated, UTF8 encoded file name.
       
  2315 @param aFlags This parameter can be one of: SQLITE_ACCESS_READ, SQLITE_ACCESS_EXISTS or SQLITE_ACCESS_READWRITE.
       
  2316 @param aResOut Output parameter, set to 1 if the tested condition is true, 0 otherwise.
       
  2317 
       
  2318 @return SQLITE_OK, 			The call has completed successfully,
       
  2319 		SQLITE_IOERR_NOMEM, An out of memory conditon has occured,
       
  2320 		SQLITE_IOERR_ACCESS,File I/O error;  
       
  2321 	    
       
  2322 If the function succeeds, COsLayerData::SetOsErrorCode() is called with KErrNone, otherwise COsLayerData::SetOsErrorCode() is called
       
  2323 with the reported by the OS API error. The stored error code will be used later by the SQLite API caller.
       
  2324 
       
  2325 @see COsLayerData::SetOsErrorCode()
       
  2326 */
       
  2327 /* static */ int TVfs::Access(sqlite3_vfs* aVfs, const char* aFileName, int aFlags, int* aResOut)
       
  2328 	{
       
  2329 	SQLUTRACE_PROFILER(aVfs);
       
  2330 	__OS_CALL(EOsVfsAccess, 0, 0);
       
  2331 	__OSTIME_COUNTER(TheOsCallTicks[EOsVfsAccess], ::OsCallProfile(EFalse, EOsVfsAccess), aFlags, 0);
       
  2332 	COsLayerData& osLayerData = COsLayerData::Instance();
       
  2333 	TBuf<KMaxFileName + 1> fname;
       
  2334 	if(!::ConvertToUnicode(aFileName, fname))
       
  2335 		{
       
  2336 		osLayerData.SetOsErrorCode(KErrGeneral);
       
  2337 		return SQLITE_IOERR_ACCESS;
       
  2338 		}
       
  2339 	SYMBIAN_TRACE_SQL_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EInternals), KFileName, &fname));
       
  2340 	TFhStrType fhStrType = ::FhStringProps(aFileName);
       
  2341 	if(fhStrType == EFhStr)
       
  2342 		{
       
  2343 		::FhConvertToFileName(fname, osLayerData.iSysPrivDir);//If fname does not have a path, iSysPrivDir will be used
       
  2344 		}
       
  2345 	TEntry entry;
       
  2346 	__FS_CALL(EFsOpFsEntry, 0);
       
  2347 	TInt err = osLayerData.iFs.Entry(fname, entry);
       
  2348 	if(aFlags == SQLITE_ACCESS_EXISTS && err == KErrNotFound)
       
  2349 		{
       
  2350 		osLayerData.SetOsErrorCode(KErrNone);
       
  2351 		*aResOut = 0;
       
  2352 		return SQLITE_OK;
       
  2353 		}
       
  2354 	if(err != KErrNone)
       
  2355 		{
       
  2356 		osLayerData.SetOsErrorCode(err);
       
  2357 		return err == KErrNoMemory ? SQLITE_IOERR_NOMEM : SQLITE_IOERR_ACCESS;
       
  2358 		}
       
  2359 	*aResOut = 0;
       
  2360 	switch(aFlags)
       
  2361 		{
       
  2362 		case SQLITE_ACCESS_READ:
       
  2363 			*aResOut =  entry.IsReadOnly();
       
  2364 			break;
       
  2365 		case SQLITE_ACCESS_EXISTS:
       
  2366 			*aResOut = 1;
       
  2367 			break;
       
  2368 		case SQLITE_ACCESS_READWRITE:
       
  2369 			*aResOut = !entry.IsReadOnly();
       
  2370 			break;
       
  2371 		default:
       
  2372 			break;			
       
  2373 		}
       
  2374 	osLayerData.SetOsErrorCode(KErrNone);
       
  2375 	return SQLITE_OK;
       
  2376 	}
       
  2377 
       
  2378 /**
       
  2379 SQLite OS porting layer API.
       
  2380 
       
  2381 Accepts UTF8 encoded, zero-terminated file as an input argument in the aRelative parameter
       
  2382 and constructs the full file path in the aBuf output parameter.
       
  2383 
       
  2384 If the format of aRelative argument is <[SID]FileName.[EXT]>, then the database file name will be 
       
  2385 treated as a name of a secure database file which has to be created/opened in the server's private 
       
  2386 directory on the system drive.
       
  2387 
       
  2388 If the format of aRelative argument is <Drive:[SID]FileName.[EXT]>, then the database file name 
       
  2389 will be treated as a name of a secure database file which has to be created/opened in the server's 
       
  2390 private directory on <Drive:> drive. 
       
  2391 
       
  2392 If the format of aRelative argument is <Drive:\Path\FileName.[EXT]>, then the database file name
       
  2393 will be treated as a name of a non-secure database file in <Drive:\Path\> directory.
       
  2394 If aRelative contains file handles, then it will be treated as a name of a file belonging to server's
       
  2395 private data cage. 
       
  2396 
       
  2397 @param aRelative The input file name, zero-terminated, UTF8 encoded.
       
  2398 @param aBufLen The output buffer length.
       
  2399 @param aBuf Output buffer for the constructed full file name path. The allocated buffer length must be at least aBufLen bytes.
       
  2400 
       
  2401 @return SQLITE_ERROR, The aRelative parameter is NULL or cannot be converted to UTF16;
       
  2402 		SQLITE_OK The operation has completed successfully.
       
  2403 */
       
  2404 /* static */ int TVfs::FullPathName(sqlite3_vfs* aVfs, const char* aRelative, int aBufLen, char* aBuf)
       
  2405 	{
       
  2406 	SQLUTRACE_PROFILER(aVfs);
       
  2407 	__OS_CALL(EOsVfsFullPathName, 0, 0);
       
  2408 	__OSTIME_COUNTER(TheOsCallTicks[EOsVfsFullPathName], ::OsCallProfile(EFalse, EOsVfsFullPathName), aBufLen, 0);
       
  2409 	COsLayerData& osLayerData = COsLayerData::Instance();
       
  2410 	osLayerData.StoreFhData(NULL, EFalse);
       
  2411 	//Convert the received file name to UTF16
       
  2412 	TBuf<KMaxFileName + 1> fname;
       
  2413 	if(!::ConvertToUnicode(aRelative, fname))
       
  2414 		{
       
  2415 		return SQLITE_ERROR;
       
  2416 		}
       
  2417 	SYMBIAN_TRACE_SQL_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EInternals), KFileName, &fname));
       
  2418 	//Zero-terminate the converted file name
       
  2419 	fname.Append(TChar(0));
       
  2420 	TParse parse;
       
  2421 	TFhStrType strType = ::FhStringProps(aRelative);//Detect string type - it may not be a real file name
       
  2422 	if(strType == EFhMainDbStr)
       
  2423 		{//The additonal information has to be extracted and fname reformatted, because SQLITE will
       
  2424 		 //use the returned full file name when making a decission to share the cache.
       
  2425 		::FhExtractAndStore(fname);
       
  2426 		(void)parse.Set(fname, 0, 0);//the file name has to be verified by the file server
       
  2427 		}
       
  2428 	else
       
  2429 		{
       
  2430 		(void)parse.Set(fname, &osLayerData.iSysPrivDir, 0);//If fname does not have a path, iSysPrivDir will be used
       
  2431 		}
       
  2432 	TPtr8 dest8(reinterpret_cast <TUint8*> (aBuf), aBufLen);	
       
  2433 	if(!::ConvertFromUnicode(parse.FullName(), dest8))
       
  2434 		{//Zero the stored fh data, because it has been initialized by the FhExtractAndStore(fname) call (couple of lines above)
       
  2435 		osLayerData.StoreFhData(NULL, EFalse);
       
  2436 		return SQLITE_ERROR;	
       
  2437 		}
       
  2438 	return SQLITE_OK;
       
  2439 	}
       
  2440 
       
  2441 /**
       
  2442 SQLite OS porting layer API.
       
  2443 
       
  2444 Generates a set of random numbers and stores them in the aBuf output parameter.
       
  2445 
       
  2446 @param aBufLen The output buffer length.
       
  2447 @param aBuf Output buffer for the generated random numbers. The allocated buffer length must be at least aBufLen bytes.
       
  2448 
       
  2449 @return The length of the used part of the output buffer.
       
  2450 */
       
  2451 /* static */ int TVfs::Randomness(sqlite3_vfs* aVfs, int aBufLen, char* aBuf)
       
  2452 	{
       
  2453 	SQLUTRACE_PROFILER(aVfs);
       
  2454 	__OS_CALL(EOsVfsRandomness, 0, 0);
       
  2455 	__OSTIME_COUNTER(TheOsCallTicks[EOsVfsRandomness], ::OsCallProfile(EFalse, EOsVfsRandomness), aBufLen, 0);
       
  2456 	COsLayerData& osLayerData = COsLayerData::Instance();
       
  2457 	const TInt KRandIterations = aBufLen / sizeof(int);
       
  2458 	for(TInt i=0;i<KRandIterations;++i)
       
  2459 		{
       
  2460 		TInt val = Math::Rand(osLayerData.iSeed);
       
  2461 		Mem::Copy(&aBuf[i * sizeof(int)], &val, sizeof(val));
       
  2462 		}
       
  2463 	return KRandIterations * sizeof(int);
       
  2464 	}
       
  2465 
       
  2466 /**
       
  2467 SQLite OS porting layer API.
       
  2468 
       
  2469 Sleeps for aMicrosec microseconds.
       
  2470 
       
  2471 @param aMicrosec The sleep interval in microseconds.
       
  2472 
       
  2473 @return The aMicrosec value.
       
  2474 */
       
  2475 /* static */ int TVfs::Sleep(sqlite3_vfs* aVfs, int aMicrosec)
       
  2476 	{
       
  2477 	SQLUTRACE_PROFILER(aVfs);
       
  2478 	__OS_CALL(EOsVfsSleep, 0, 0);
       
  2479 	__OSTIME_COUNTER(TheOsCallTicks[EOsVfsSleep], ::OsCallProfile(EFalse, EOsVfsSleep), aMicrosec, 0);
       
  2480 	User::AfterHighRes(TTimeIntervalMicroSeconds32(aMicrosec));
       
  2481 	return aMicrosec;
       
  2482 	}
       
  2483 
       
  2484 /**
       
  2485 SQLite OS porting layer API.
       
  2486 
       
  2487 Retrieves the current date and time.
       
  2488 
       
  2489 @param aNow Output parameter, where the data and time value will be stored.
       
  2490 			SQLite processes all times and dates as Julian Day numbers and
       
  2491 			aNow parameter will contain the julian date and time.
       
  2492 
       
  2493 @return 0.
       
  2494 */
       
  2495 /* static */ int TVfs::CurrentTime(sqlite3_vfs* aVfs, double* aNow)
       
  2496 	{
       
  2497 	SQLUTRACE_PROFILER(aVfs);
       
  2498 	__OS_CALL(EOsVfsCurrentTime, 0, 0);
       
  2499 	__OSTIME_COUNTER(TheOsCallTicks[EOsVfsCurrentTime], ::OsCallProfile(EFalse, EOsVfsCurrentTime), 0, 0);
       
  2500 	TTime now;
       
  2501 	now.UniversalTime();
       
  2502 	TDateTime date = now.DateTime();
       
  2503 	TInt year = date.Year();
       
  2504 	TInt month = date.Month() + 1;
       
  2505 	TInt day = date.Day() + 1;
       
  2506 	
       
  2507     //Calculate the Julian days
       
  2508 	TInt jd = day - 32076 +
       
  2509 	    1461*(year + 4800 + (month - 14)/12)/4 +
       
  2510 	    367*(month - 2 - (month - 14)/12*12)/12 -
       
  2511 	    3*((year + 4900 + (month - 14)/12)/100)/4;
       
  2512           	
       
  2513 	*aNow = jd;
       
  2514 
       
  2515     // Add the fractional hours, mins and seconds
       
  2516 	*aNow += (date.Hour() + 12.0) / 24.0;
       
  2517 	*aNow += date.Minute() / 1440.0;
       
  2518 	*aNow += date.Second() / 86400.0;
       
  2519 	
       
  2520 	return 0;
       
  2521 	}
       
  2522 
       
  2523 /**
       
  2524 SQLite OS porting layer API.
       
  2525 
       
  2526 Retrieves a text description of the last OS error.
       
  2527 Note: the method has a default "no-op" implementation at the moment. 
       
  2528 
       
  2529 @return 0.
       
  2530 */
       
  2531 /* static */int TVfs::GetLastError(sqlite3_vfs* aVfs, int /*aBufLen*/, char* /*aBuf*/)
       
  2532 	{
       
  2533 	SQLUTRACE_PROFILER(aVfs);
       
  2534 	__OS_CALL(EOsVfsGetLastError, 0, 0);
       
  2535 	__OSTIME_COUNTER(TheOsCallTicks[EOsVfsGetLastError], ::OsCallProfile(EFalse, EOsVfsGetLastError), 0, 0);
       
  2536 	return 0;
       
  2537 	}
       
  2538 
       
  2539 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
  2540 ///////////////////////////////////       Memory allocation functions     /////////////////////////////////////////////////////
       
  2541 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
  2542 
       
  2543 /**
       
  2544 SQLite OS porting layer API.
       
  2545 
       
  2546 Memory allocation routine.
       
  2547 
       
  2548 @internalComponent
       
  2549 */
       
  2550 extern "C" void* sqlite3SymbianMalloc(size_t aSize)
       
  2551 	{
       
  2552 	__MEM_CALL(EMemOpAlloc, aSize, 0);
       
  2553 	return COsLayerData::Instance().iAllocator->Alloc(aSize);
       
  2554 	}
       
  2555 
       
  2556 /**
       
  2557 SQLite OS porting layer API.
       
  2558 
       
  2559 Memory reallocation routine.
       
  2560 
       
  2561 @internalComponent
       
  2562 */
       
  2563 extern "C" void* sqlite3SymbianRealloc(void* aPtr, size_t aSize)
       
  2564 	{
       
  2565 #ifdef _SQLPROFILER
       
  2566 	TInt size = COsLayerData::Instance().iAllocator->AllocLen(aPtr);
       
  2567 	__MEM_CALL(EMemOpRealloc, aSize, size);
       
  2568 #endif
       
  2569 	return COsLayerData::Instance().iAllocator->ReAlloc(aPtr, aSize);
       
  2570 	}
       
  2571 
       
  2572 /**
       
  2573 SQLite OS porting layer API.
       
  2574 
       
  2575 Memory free routine.
       
  2576 
       
  2577 @internalComponent
       
  2578 */
       
  2579 extern "C" void sqlite3SymbianFree(void* aPtr)
       
  2580 	{
       
  2581 #ifdef _SQLPROFILER
       
  2582 	TInt size = COsLayerData::Instance().iAllocator->AllocLen(aPtr);
       
  2583 	__MEM_CALL(EMemOpFree, size, 0);
       
  2584 #endif
       
  2585 	COsLayerData::Instance().iAllocator->Free(aPtr);
       
  2586 	}
       
  2587 
       
  2588 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
  2589 ///////////////////////////////////       SQLite init/release functions     ///////////////////////////////////////////////////
       
  2590 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
  2591 
       
  2592 /**
       
  2593 Registers the single sqlite3_vfs instance ("TheVfsApi" global variable) by calling sqlite3_vfs_register()
       
  2594 */
       
  2595 extern "C" int sqlite3_os_init(void)
       
  2596 	{
       
  2597 	return sqlite3_vfs_register(&TheVfsApi, 1);//"1" means - make TheVfsApi to be the default VFS object
       
  2598 	}
       
  2599 
       
  2600 /**
       
  2601 Unregisters the single sqlite3_vfs instance ("TheVfsApi" global variable) by calling sqlite3_vfs_unregister()
       
  2602 */
       
  2603 extern "C" int sqlite3_os_end(void)
       
  2604 	{
       
  2605 	return sqlite3_vfs_unregister(&TheVfsApi);
       
  2606 	}
       
  2607 
       
  2608 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
  2609 
       
  2610 #endif//SQLITE_OS_SYMBIAN
       
  2611