persistentstorage/sqlite3api/OsLayer/os_symbian_mt.cpp
changeset 0 08ec8eefde2f
child 8 fa9941cf3867
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 // os_symbian.cpp
       
    15 // The Symbian OS porting layer - multi-threaded implementation.
       
    16 // SQLite never accesses the file system and the OS services directly.
       
    17 // SQLite uses for that sqlite3_vfs and sqlite3_file objects.
       
    18 // sqlite3_vfs and sqlite3_file functionality is implemented in this file - 
       
    19 // TVfs and TFileIo classes.
       
    20 // 
       
    21 //
       
    22 
       
    23 /**
       
    24  @file
       
    25  @see TVfs
       
    26  @see TFileIo
       
    27 */
       
    28 
       
    29 #ifdef  SQLITE_OS_SYMBIAN
       
    30 
       
    31 extern "C" 
       
    32 	{
       
    33 	#include "sqliteInt.h"
       
    34 	#include "os.h"
       
    35 	#include "os_common.h"
       
    36 	}
       
    37 #include <e32math.h>
       
    38 #include "os_symbian.h"
       
    39 #include "UTraceSqlite.h"
       
    40 
       
    41 #ifdef SQLITE_TEST
       
    42 
       
    43 //Count the number of fullsyncs and normal syncs.  This is used to test
       
    44 //that syncs and fullsyncs are occuring at the right times.
       
    45 extern "C" int sqlite3_sync_count = 0;
       
    46 extern "C" int sqlite3_fullsync_count = 0;
       
    47 
       
    48 //The following variable, if set to a non-zero value, becomes the result
       
    49 //returned from sqlite3OsCurrentTime().  This is used for testing.
       
    50 extern "C" int sqlite3_current_time = 0;
       
    51 
       
    52 #endif//SQLITE_TEST
       
    53 
       
    54 _LIT(KCwd, ".\\");
       
    55 
       
    56 //Used for the random numbers generation
       
    57 static inline TInt64& Seed()
       
    58 	{
       
    59 	static TInt64 seed = 0;
       
    60 	if(seed == 0)
       
    61 		{
       
    62 		TTime now;
       
    63 		now.UniversalTime();
       
    64 		seed = now.Int64();
       
    65 		}
       
    66 	return seed;
       
    67 	}
       
    68 
       
    69 /**
       
    70 Os2SqliteErr() is called at the end of many of the interface functions of the OS porting layer (wherever it is appropriate - 
       
    71 TFileIo and TVfs interfaces). The purpose of this function is to identify the "out of memory" and "disk is full" errors
       
    72 reported by the used Symbian OS APIs (aOsErr parameter) and report them to SQLite as SQLITE_FULL and SQLITE_NOMEM errors.
       
    73 The KErrEof error (TFileIo::Read() can return KErrEof) is reported to SQLite as SQLITE_IOERR_SHORT_READ. The rest of failures
       
    74 are reported as the error specified in aDefaultErr parameter.
       
    75  
       
    76 @param aOsErr      Symbian OS error
       
    77 @param aDefaultErr The default SQLite error that should be used if the aOsErr parameter is not one of:
       
    78                      KErrNone, KErrEof, KErrNoMemory, KErrDiskFull
       
    79 @return SQLITE_OK,               The OS porting layer function call has completed successfully, 
       
    80           SQLITE_IOERR_SHORT_READ, The amount of the data read is less than the requested amount,
       
    81           SQLITE_IOERR_NOMEM,      Out of memory,
       
    82           SQLITE_FULL,             The disk is full,
       
    83           aDefaultErr,             The rest of failures will be reported as aDefaultErr.
       
    84 */
       
    85 static TInt Os2SqliteErr(TInt aOsErr, TInt aDefaultErr)
       
    86 	{
       
    87 	switch(aOsErr)
       
    88 		{
       
    89 		case KErrNone:
       
    90 			return SQLITE_OK;	
       
    91 		case KErrEof:
       
    92 			return SQLITE_IOERR_SHORT_READ;
       
    93 		case KErrNoMemory:
       
    94 			return SQLITE_IOERR_NOMEM;
       
    95 		case KErrDiskFull:
       
    96 			return SQLITE_FULL;
       
    97 		default:
       
    98 #ifdef _DEBUG		
       
    99 			RDebug::Print(_L("SQLite3 C API, Os2SqliteErr(), err=%d\n"), aOsErr);
       
   100 #endif			
       
   101 			break;
       
   102 		}
       
   103 	return aDefaultErr;
       
   104 	}
       
   105 	
       
   106 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   107 //////////////////////////  TStaticFs  /////////////////////////////////////////////////////////////////////////////////////////
       
   108 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   109 
       
   110 /**
       
   111 Connects the file session used by the SQLite OS porting layer.
       
   112 Single RFs instance per process is used.
       
   113 
       
   114 @return KErrNone The operation was completed successfully,
       
   115                  System-wide error code if the operation has failed.
       
   116 */
       
   117 TInt TStaticFs::Connect()
       
   118 	{
       
   119 	TInt err = iFs.Connect();
       
   120 	if(err == KErrNone)	
       
   121 		{
       
   122 		err = iFs.ShareAuto();	
       
   123 		}
       
   124 	if(err != KErrNone)
       
   125 		{
       
   126 		iFs.Close();	
       
   127 		}
       
   128 	return err;
       
   129 	}
       
   130 
       
   131 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   132 //////////////////////////  sqlite3_mutex  /////////////////////////////////////////////////////////////////////////////////////            
       
   133 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   134 
       
   135 /**
       
   136 Initializes sqlite3_mutex data members with their default values.
       
   137 */
       
   138 sqlite3_mutex::sqlite3_mutex() :
       
   139 	iRefCount(0),
       
   140 	iOwnerThreadId(KMaxTUint64)
       
   141 	{
       
   142 	}
       
   143 
       
   144 /**
       
   145 Closes the mutex handle.
       
   146 */
       
   147 sqlite3_mutex::~sqlite3_mutex()
       
   148 	{
       
   149 	iMutex.Close();
       
   150 	}
       
   151 
       
   152 /**
       
   153 Gives the calling thread an exclusive access to the SQLite resources (global variables, file handles, buffers, cache, etc.).
       
   154 The calling thread becomes a mutex owner.
       
   155 If the mutex is already locked by another thread, the calling thread will block until the other thread releases the mutex.
       
   156 The method can be called by the mutex owning thread more than once, even if the mutex is already entered.
       
   157 */
       
   158 void sqlite3_mutex::Enter()
       
   159 	{
       
   160 	iMutex.Wait();
       
   161 	RThread currThread;
       
   162 	iOwnerThreadId = currThread.Id();
       
   163 	++iRefCount;
       
   164 	}
       
   165 	
       
   166 /**
       
   167 Unlocks the mutex. If sqlite3_mutex::Enter() was called more than once by the owning thread, then the number of 
       
   168 sqlite3_mutex::Leave() calls must eventually match the number of sqlite3_mutex::Enter() calls.
       
   169 If there are thread(s) blocked on sqlite3_mutex::Enter(), after the mutex gets unlocked one of the waiting threads
       
   170 will be able to lock the mutex and get an exclusive access to the guarded resources.
       
   171 
       
   172 @panic SqliteMt 23 Negative mutex lock counter (in debug builds only)
       
   173 @panic SqliteMt 24 The mutex has been entered (locked) by a different thread than the current one (in debug builds only)
       
   174 */
       
   175 void sqlite3_mutex::Leave()
       
   176 	{
       
   177 	__ASSERT_DEBUG(iRefCount > 0, User::Panic(KPanicCategory, EPanicMutexLockCounter));
       
   178 #ifdef _DEBUG
       
   179 	RThread currThread;	
       
   180 	__ASSERT_DEBUG(iOwnerThreadId == currThread.Id(), User::Panic(KPanicCategory, EPanicMutexOwner));
       
   181 #endif
       
   182 	--iRefCount;
       
   183 	iMutex.Signal();
       
   184 	}
       
   185 
       
   186 /**
       
   187 Returns true if the mutex is already locked (entered).
       
   188 
       
   189 @return True if the mutex is locked, false otherwise
       
   190 */
       
   191 TBool sqlite3_mutex::IsHeld() const
       
   192 	{
       
   193 	RThread currThread;
       
   194 	return iRefCount != 0 && iOwnerThreadId == currThread.Id();
       
   195 	}
       
   196 
       
   197 /**
       
   198 Creates the mutex.
       
   199 
       
   200 @return KErrNone The operation was completed successfully,
       
   201                  System-wide error code if the operation has failed.
       
   202 */
       
   203 TInt sqlite3_mutex::Create()
       
   204 	{
       
   205 	return iMutex.CreateLocal();
       
   206 	}
       
   207 
       
   208 /**
       
   209 Creates new CRecursiveMutex object.
       
   210 
       
   211 @return A pointer to the created CRecursiveMutex object or NULL if the operation has failed.
       
   212 */
       
   213 CRecursiveMutex* CRecursiveMutex::New()
       
   214 	{
       
   215 	CRecursiveMutex* self = new CRecursiveMutex;
       
   216 	if(self)
       
   217 		{
       
   218 		if(self->Create() != KErrNone)
       
   219 			{
       
   220 			delete self;	
       
   221 			self = NULL;
       
   222 			}
       
   223 		}
       
   224 	return self;
       
   225 	}
       
   226 
       
   227 CRecursiveMutex::~CRecursiveMutex()
       
   228 	{
       
   229 	}
       
   230 
       
   231 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   232 //////////////////////////  TMutexApi  ////////////////////////////////////////////////////////////////////////////////////////
       
   233 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   234 
       
   235 /**
       
   236 Initializes the mutex system.
       
   237 No-op function.
       
   238 
       
   239 @return SQLITE_OK
       
   240 */
       
   241 int TMutexApi::Init()
       
   242 	{
       
   243 	SQLUTRACE_PROFILER(0);
       
   244 	return SQLITE_OK;
       
   245 	}
       
   246 	
       
   247 /**
       
   248 Finalizes the mutex system.
       
   249 No-op function.
       
   250 
       
   251 @return SQLITE_OK
       
   252 */
       
   253 int TMutexApi::End()
       
   254 	{
       
   255 	SQLUTRACE_PROFILER(0);
       
   256 	return SQLITE_OK;
       
   257 	}
       
   258 	
       
   259 /**
       
   260 Creates a new mutex.
       
   261 If the request is for a static mutex, a pointer to already created static mutex will be returned.
       
   262 
       
   263 @param aType  The mutex type: static, fast, recursive
       
   264 @return A pointer to the created mutex or NULL if the operation has failed
       
   265 */
       
   266 sqlite3_mutex* TMutexApi::Alloc(int aType)
       
   267 	{
       
   268 	SQLUTRACE_PROFILER(0);
       
   269 	sqlite3_mutex* mutex = NULL;
       
   270 	switch(aType)
       
   271 		{
       
   272 		case SQLITE_MUTEX_FAST:
       
   273 		case SQLITE_MUTEX_RECURSIVE:
       
   274 			mutex = CRecursiveMutex::New();
       
   275 			break;
       
   276 		default:
       
   277 			mutex = ::StaticMutex(aType - 2);
       
   278 			break;	
       
   279 		}
       
   280 	return mutex;
       
   281 	}
       
   282 	
       
   283 /**
       
   284 Destroys a mutex, created previously by a call to TMutexApi::Alloc().
       
   285 @param aMutex Pointer to the mutex object that has to be destroyed
       
   286 */
       
   287 void TMutexApi::Free(sqlite3_mutex* aMutex)
       
   288 	{
       
   289 	SQLUTRACE_PROFILER(0);
       
   290 	delete aMutex;
       
   291 	}
       
   292 	
       
   293 /**
       
   294 Locks the mutex.
       
   295 See sqlite3_mutex::Enter() for more details.
       
   296 
       
   297 @param aMutex Pointer to the mutex object
       
   298 
       
   299 @see sqlite3_mutex::Enter()
       
   300 */
       
   301 void TMutexApi::Enter(sqlite3_mutex* aMutex)
       
   302 	{
       
   303 	SQLUTRACE_PROFILER(0);
       
   304 	aMutex->Enter();
       
   305 	}
       
   306 	
       
   307 /**
       
   308 No-op. Always returns SQLITE_BUSY.
       
   309 
       
   310 @return SQLITE_BUSY
       
   311 */
       
   312 int TMutexApi::Try(sqlite3_mutex*)
       
   313 	{
       
   314 	SQLUTRACE_PROFILER(0);
       
   315 	return SQLITE_BUSY;
       
   316 	}
       
   317 	
       
   318 /**
       
   319 Unlocks the mutex.
       
   320 See sqlite3_mutex::Leave() for more details.
       
   321 
       
   322 @param aMutex Pointer to the mutex object
       
   323 
       
   324 @see sqlite3_mutex::Leave()
       
   325 */
       
   326 void TMutexApi::Leave(sqlite3_mutex* aMutex)
       
   327 	{
       
   328 	SQLUTRACE_PROFILER(0);
       
   329 	aMutex->Leave();
       
   330 	}
       
   331 	
       
   332 /**
       
   333 Checks whether the mutex is locked or not.
       
   334 See sqlite3_mutex::IsHeld() for more details.
       
   335 
       
   336 @param aMutex Pointer to the mutex object
       
   337 
       
   338 @return True if the mutex is locked, false otherwise
       
   339 
       
   340 @see sqlite3_mutex::IsHeld()
       
   341 */
       
   342 int TMutexApi::Held(sqlite3_mutex* aMutex)
       
   343 	{
       
   344 	SQLUTRACE_PROFILER(0);
       
   345 	return aMutex->IsHeld();
       
   346 	}
       
   347 	
       
   348 /**
       
   349 Checks whether the mutex is locked or not.
       
   350 See sqlite3_mutex::IsHeld() for more details.
       
   351 
       
   352 @param aMutex Pointer to the mutex object
       
   353 
       
   354 @return False if the mutex is locked, true otherwise
       
   355 
       
   356 @see sqlite3_mutex::IsHeld()
       
   357 */
       
   358 int TMutexApi::Notheld(sqlite3_mutex* aMutex)
       
   359 	{
       
   360 	SQLUTRACE_PROFILER(0);
       
   361 	return !aMutex->IsHeld();
       
   362 	}
       
   363 
       
   364 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   365 ///////////////////////////////////       SQLite init/release functions     ///////////////////////////////////////////////////
       
   366 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   367 
       
   368 /**
       
   369 Initializes the OS porting layer global data.
       
   370 */
       
   371 extern "C" SQLITE_EXPORT int sqlite3_os_init(void)
       
   372 	{
       
   373 	return sqlite3_vfs_register(VfsApi(), 1);
       
   374 	}
       
   375 
       
   376 /**
       
   377 Destroys the OS porting layer global data.
       
   378 */
       
   379 extern "C" SQLITE_EXPORT int sqlite3_os_end(void)
       
   380 	{
       
   381 	return sqlite3_vfs_unregister(VfsApi());
       
   382 	}
       
   383 
       
   384 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   385 //////////////////////////  TheFileIoApi  /////////////////////////////////////////////////////////////////////////////////////
       
   386 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   387 
       
   388 /**
       
   389 Single sqlite3_io_methods instance, which data members (function pointers) are initialized with the addresses of
       
   390 TFileIo members. 
       
   391 TheFileIoApi is used by SQLite for performing OS independent file I/O.
       
   392 
       
   393 @see TFileIo
       
   394 @see TVfs
       
   395 
       
   396 @internalComponent
       
   397 */
       
   398 const static sqlite3_io_methods TheFileIoApi = 
       
   399 	{
       
   400 	1,						//Version
       
   401 	&TFileIo::Close,
       
   402 	&TFileIo::Read,
       
   403 	&TFileIo::Write,
       
   404 	&TFileIo::Truncate,
       
   405 	&TFileIo::Sync,
       
   406 	&TFileIo::FileSize,
       
   407 	&TFileIo::Lock,
       
   408 	&TFileIo::Unlock,
       
   409 	&TFileIo::CheckReservedLock,
       
   410 	&TFileIo::FileControl,
       
   411 	&TFileIo::SectorSize,
       
   412 	&TFileIo::DeviceCharacteristics
       
   413 	};
       
   414 	
       
   415 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   416 //////////////////////////  TheMutexMethods  //////////////////////////////////////////////////////////////////////////////////
       
   417 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   418 
       
   419 /**
       
   420 */
       
   421 static sqlite3_mutex_methods TheMutexMethods =
       
   422 	{
       
   423 	&TMutexApi::Init,
       
   424 	&TMutexApi::End,
       
   425 	&TMutexApi::Alloc,
       
   426 	&TMutexApi::Free,
       
   427 	&TMutexApi::Enter,
       
   428 	&TMutexApi::Try,
       
   429 	&TMutexApi::Leave,
       
   430 	&TMutexApi::Held,
       
   431 	&TMutexApi::Notheld
       
   432 	};
       
   433 
       
   434 extern "C" sqlite3_mutex_methods* sqlite3DefaultMutex(void)
       
   435 	{
       
   436 	return &TheMutexMethods;
       
   437 	};
       
   438 
       
   439 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   440 //////////////////          UTF16<-->UTF8, conversion functions    ////////////////////////////////////////////////////////////
       
   441 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   442 
       
   443 /**
       
   444 The function converts aFileName to UTF16 encoded file name, and stores the UTF16 encoded file name
       
   445 to the place pointed by aFileNameDestBuf argument.
       
   446 If the UTF16 conversion of the file name failed because the file name is too long or NULL, 
       
   447 the function returns EFalse. 
       
   448 
       
   449 @param aFileName Expected to point to UTF8 encoded, zero terminated string.
       
   450 				 Max allowed aFileName length is KMaxFileName (excluding terminating 0 character).
       
   451 @param aFileNameDestBuf Output parameter. Will hold UTF16, non-zero-terminated string.
       
   452 						The max length must be at least KMaxFileName characters.
       
   453                          
       
   454 @return True if the conversion has been completed successfully						 
       
   455 */
       
   456 static TBool ConvertToUnicode(const char *aFileName, TDes& aFileNameDestBuf)
       
   457 	{
       
   458 	if(aFileName)
       
   459 		{
       
   460 		wchar_t* dest = reinterpret_cast <wchar_t*> (const_cast <TUint16*> (aFileNameDestBuf.Ptr()));
       
   461 		TInt len = mbstowcs(dest, aFileName, KMaxFileName);
       
   462 		//Check the file name length. If it is longer than KMaxFileName characters, then the file name is not valid.
       
   463 		if(len > 0 && len <= KMaxFileName)
       
   464 			{
       
   465 			aFileNameDestBuf.SetLength(len);
       
   466 			return ETrue;
       
   467 			}
       
   468 		}
       
   469 	return EFalse;
       
   470 	}
       
   471 
       
   472 /**
       
   473 The function converts aFileName to UTF8 encoded file name, and stores the UTF8 encoded file name
       
   474 to the place pointed by aFileNameDestBuf argument.
       
   475 If the UTF8 conversion of the file name failed because the file name is too long or NULL, 
       
   476 the function returns EFalse. 
       
   477 
       
   478 @param aFileName Expected to point to UTF16 encoded, zero terminated string.
       
   479 				 Max allowed aFileName length is KMaxFileName (excluding terminating 0 character).
       
   480 @param aFileNameDestBuf Output parameter. Will hold UTF8, non-zero-terminated string.
       
   481 						The max length must be at least KMaxFileName characters.
       
   482                          
       
   483 @return True if the conversion has been completed successfully						 
       
   484 */
       
   485 static TBool ConvertFromUnicode(const TDesC& aFileName, TDes8& aFileNameDestBuf)
       
   486 	{
       
   487 	char* dest = reinterpret_cast <char*> (const_cast <TUint8*> (aFileNameDestBuf.Ptr()));
       
   488 	const wchar_t* src = reinterpret_cast <const wchar_t*> (aFileName.Ptr());
       
   489 	TInt len = wcstombs(dest, src, KMaxFileName);
       
   490 	//Check the file name length. If it is longer than KMaxFileName characters, then the file name is not valid.
       
   491 	if(len > 0 && len <= KMaxFileName)
       
   492 		{
       
   493 		aFileNameDestBuf.SetLength(len);
       
   494 		return ETrue;
       
   495 		}
       
   496 	return EFalse;
       
   497 	}
       
   498 
       
   499 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   500 /////////////////////       TDbFile class definition    ///////////////////////////////////////////////////////////////////////
       
   501 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   502 
       
   503 const TInt KFileBufSize = 8 * 1024;	
       
   504 
       
   505 /**
       
   506 Initializes TDbFile data members with their default values.
       
   507 */
       
   508 inline TDbFile::TDbFile() :
       
   509 	iFileBuf(KFileBufSize),
       
   510 	iFullName(NULL),
       
   511 	iSharedLockByte(0),
       
   512 	iLockType(SQLITE_LOCK_NONE),
       
   513 	iReadOnly(EFalse),
       
   514 	iSectorSize(0),
       
   515 	iDeviceCharacteristics(-1)
       
   516 	{
       
   517 	pMethods = 0;
       
   518 	}
       
   519 
       
   520 /**
       
   521 Casts the passed sqlite3_file pointer to a reference to the derived class - TDbFile&.
       
   522 All sqlite3_file pointers passed to TFileIo methods are actually pointers to TDbFile instances. 
       
   523 So the cast is safe.
       
   524 
       
   525 @param aDbFile A pointer to a sqlite3_file instance
       
   526 
       
   527 @return A TDbFile reference. 
       
   528 @see TFileIo
       
   529 @see TVfs
       
   530 @see TDbFile
       
   531 
       
   532 @panic Sqlite 20 In _DEBUG mode if aDbFile is NULL.
       
   533 
       
   534 @internalComponent
       
   535 */
       
   536 static inline TDbFile& DbFile(sqlite3_file* aDbFile)
       
   537 	{
       
   538 	__ASSERT_DEBUG(aDbFile != 0, User::Panic(KPanicCategory, EPanicNullDbFilePtr));
       
   539 	return *(static_cast <TDbFile*> (aDbFile));
       
   540 	}
       
   541 
       
   542 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   543 /////////////////////       TFileIo class definition    ///////////////////////////////////////////////////////////////////////
       
   544 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   545 
       
   546 /**
       
   547 SQLite OS porting layer API.
       
   548 
       
   549 Closes the file referred by aDbFile parameter.
       
   550 If aDbFile, which is actually a pointer to a TDbFile instance, the iFullName data member is not NULL, 
       
   551 then the file will be deleted.
       
   552 
       
   553 @param aDbFile A pointer to a TDbFile instance, than contains the file handle to be closed.
       
   554 
       
   555 @return SQLITE_OK
       
   556 
       
   557 @see TDbFile
       
   558 */
       
   559 /* static */ int TFileIo::Close(sqlite3_file* aDbFile)
       
   560 	{
       
   561 	SQLUTRACE_PROFILER(aDbFile);
       
   562 	TDbFile& dbFile = ::DbFile(aDbFile);
       
   563 	dbFile.iFileBuf.Close();	
       
   564 	if(dbFile.iFullName)
       
   565 		{
       
   566 		(void)TStaticFs::Fs().Delete(*dbFile.iFullName);
       
   567 		delete dbFile.iFullName;
       
   568 		dbFile.iFullName = NULL;
       
   569 		}
       
   570     OpenCounter(-1);
       
   571 	return SQLITE_OK;
       
   572 	}
       
   573 
       
   574 /**
       
   575 SQLite OS porting layer API.
       
   576 
       
   577 Reads from the file referred by the aDbFile parameter.
       
   578 
       
   579 @param aDbFile A pointer to a TDbFile instance, that contains the file handle to be read from.
       
   580 @param aBuf Output parameter. The data read from the file will be copied there.
       
   581 			The buffer size must be at least aAmt bytes.
       
   582 @param aAmt The amount of data to be read form the file.
       
   583 @param aOffset The offset in the file where the read operation should start.
       
   584 
       
   585 @return SQLITE_FULL,       			The disk is full,
       
   586 	    SQLITE_IOERR_SHORT_READ, 	The amount of the data read is less than aAmt,
       
   587 	    SQLITE_IOERR_READ, 			File read error,
       
   588 	    SQLITE_IOERR_NOMEM,			An out of memory condition has occured,
       
   589 	    SQLITE_OK,					The operation has completed successfully.
       
   590 	    
       
   591 @see TDbFile
       
   592 */
       
   593 /* static */ int TFileIo::Read(sqlite3_file* aDbFile, void* aBuf, int aAmt, sqlite3_int64 aOffset)
       
   594 	{
       
   595 	SQLUTRACE_PROFILER(aDbFile);
       
   596 	SYMBIAN_TRACE_SQLITE_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EInternals), KFileRead, aAmt, aOffset));
       
   597 	SimulateIOError(return SQLITE_IOERR_READ);
       
   598 	TDbFile& dbFile = ::DbFile(aDbFile);
       
   599 	TPtr8 ptr((TUint8*)aBuf, 0, aAmt);
       
   600 	TInt err = dbFile.iFileBuf.Read(aOffset, ptr);
       
   601 	TInt cnt = ptr.Length();
       
   602 	TInt sqliteErr = ::Os2SqliteErr(err, SQLITE_IOERR_READ);
       
   603 	if(cnt != aAmt && (sqliteErr == SQLITE_OK || sqliteErr == SQLITE_IOERR_SHORT_READ))
       
   604 		{
       
   605 		Mem::FillZ(static_cast <TUint8*> (aBuf) + cnt, aAmt - cnt);
       
   606 		sqliteErr = SQLITE_IOERR_SHORT_READ;
       
   607 		}
       
   608 	return sqliteErr;
       
   609 	}
       
   610 
       
   611 /**
       
   612 SQLite OS porting layer API.
       
   613 
       
   614 Writes to the file referred by the aDbFile parameter.
       
   615 "Write beyond the end of the file" operations are allowed.
       
   616 
       
   617 @param aDbFile A pointer to a TDbFile instance, that contains the file handle to be written to.
       
   618 @param aData The data to be written to the file. The buffer size must be at least aAmt bytes.
       
   619 @param aAmt The amount of data to be written to the file.
       
   620 @param aOffset The offset in the file where the write operation should start.
       
   621 
       
   622 @return SQLITE_IOERR_WRITE, the file write operation has failed or the file is read-only,
       
   623 		SQLITE_FULL,       	The disk is full,
       
   624 	    SQLITE_IOERR_NOMEM,	An out of memory condition has occured,
       
   625 	    SQLITE_OK,			The operation has completed successfully.
       
   626 	    
       
   627 @see TDbFile
       
   628 */
       
   629 /* static */ int TFileIo::Write(sqlite3_file* aDbFile, const void* aData, int aAmt, sqlite3_int64 aOffset)
       
   630 	{
       
   631 	SQLUTRACE_PROFILER(aDbFile);
       
   632 	SYMBIAN_TRACE_SQLITE_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EInternals), KFileWrite, aAmt, aOffset));
       
   633 	SimulateIOError(return SQLITE_IOERR_WRITE);
       
   634 	SimulateDiskfullError(return SQLITE_FULL);
       
   635 	TDbFile& dbFile = ::DbFile(aDbFile);
       
   636 	TInt err = KErrAccessDenied;
       
   637 	if(!dbFile.iReadOnly)
       
   638 		{
       
   639 		TPtrC8 ptr((const TUint8*)aData, aAmt);
       
   640 		err = dbFile.iFileBuf.Write(aOffset, ptr);
       
   641 		}
       
   642 	return ::Os2SqliteErr(err, SQLITE_IOERR_WRITE);
       
   643 	}
       
   644 
       
   645 /**
       
   646 SQLite OS porting layer API.
       
   647 
       
   648 Truncates the file referred by the aDbFile parameter.
       
   649 
       
   650 @param aDbFile A pointer to a TDbFile instance, that contains the file handle.
       
   651 @param aLength The new file size in bytes.
       
   652 
       
   653 @return SQLITE_IOERR_TRUNCATE, the file truncate operation has failed or the file is read-only,
       
   654 		SQLITE_FULL,       	The disk is full,
       
   655 	    					The file truncate operation has failed,
       
   656 	    SQLITE_IOERR_NOMEM,	An out of memory condition has occured,
       
   657 	    SQLITE_OK,			The operation has completed successfully.
       
   658 	    
       
   659 @see TDbFile
       
   660 */
       
   661 /* static */ int TFileIo::Truncate(sqlite3_file* aDbFile, sqlite3_int64 aLength)
       
   662 	{
       
   663 	SQLUTRACE_PROFILER(aDbFile);
       
   664 	SYMBIAN_TRACE_SQLITE_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EInternals), KFileTruncate, aLength));
       
   665 	SimulateIOError(return SQLITE_IOERR_TRUNCATE);
       
   666 	TDbFile& dbFile = ::DbFile(aDbFile);
       
   667 	TInt err = KErrAccessDenied;
       
   668 	if(!dbFile.iReadOnly)
       
   669 		{
       
   670 		err = dbFile.iFileBuf.SetSize(aLength);
       
   671 		}
       
   672 	return ::Os2SqliteErr(err, SQLITE_IOERR_TRUNCATE);
       
   673 	}
       
   674 
       
   675 /**
       
   676 SQLite OS porting layer API.
       
   677 
       
   678 Flushes the file referred by the aDbFile parameter.
       
   679 
       
   680 @param aDbFile A pointer to a TDbFile instance, that contains the file handle.
       
   681 @param aFlags  This parameter is not used in the production builds. It may be one of 
       
   682 			   SQLITE_SYNC_NORMAL or SQLITE_SYNC_FULL and is used only by the TCL test suite.
       
   683 
       
   684 @return SQLITE_IOERR_FSYNC,	This is a read-only file, or  the file flush operation has failed,
       
   685 	    SQLITE_IOERR_NOMEM,	An out of memory condition has occured,
       
   686 	    SQLITE_FULL,       		The disk is full,
       
   687    	    SQLITE_OK,			The operation has completed successfully.
       
   688 
       
   689 @see TDbFile
       
   690 */
       
   691 /* static */int TFileIo::Sync(sqlite3_file* aDbFile, int aFlags)
       
   692 	{
       
   693 	SQLUTRACE_PROFILER(aDbFile);
       
   694 	SimulateIOError(return SQLITE_IOERR_FSYNC);
       
   695 	TDbFile& dbFile = ::DbFile(aDbFile);
       
   696 #ifdef SQLITE_TEST
       
   697 	if(aFlags & SQLITE_SYNC_FULL)
       
   698 		{
       
   699 		sqlite3_fullsync_count++;
       
   700 		}
       
   701 	sqlite3_sync_count++;
       
   702 #else
       
   703 	aFlags = aFlags;	
       
   704 #endif
       
   705 	TInt err = KErrAccessDenied;
       
   706 	if(!dbFile.iReadOnly)
       
   707 		{
       
   708 		err = dbFile.iFileBuf.Flush();
       
   709 		}
       
   710 	return ::Os2SqliteErr(err, SQLITE_IOERR_FSYNC);
       
   711 	}
       
   712 
       
   713 /**
       
   714 SQLite OS porting layer API.
       
   715 
       
   716 Returns the size of the file referred by the aDbFile parameter.
       
   717 
       
   718 @param aDbFile A pointer to a TDbFile instance, that contains the file handle.
       
   719 @param aSize Output parameter. If the function completes successfully, the file size will be stored there.
       
   720 
       
   721 @return SQLITE_IOERR_FSTAT,		The file size operation has failed;
       
   722 	    SQLITE_IOERR_NOMEM,		An out of memory condition has occured;
       
   723 	    SQLITE_OK,				The operation has completed successfully.
       
   724 	    
       
   725 @see TDbFile
       
   726 */
       
   727 /* static */ int TFileIo::FileSize(sqlite3_file* aDbFile, sqlite3_int64* aSize)
       
   728 	{
       
   729 	SQLUTRACE_PROFILER(aDbFile);
       
   730 	SimulateIOError(return SQLITE_IOERR_FSTAT);
       
   731 	TDbFile& dbFile = ::DbFile(aDbFile);
       
   732 	TInt err =  dbFile.iFileBuf.Size(*aSize);
       
   733 	return ::Os2SqliteErr(err, SQLITE_IOERR_FSTAT);
       
   734 	}
       
   735 
       
   736 /**
       
   737 This function is called when SQLite needs to obtain a read lock. This is done by generating a
       
   738 random file position within the first page beyond the first Gb of the file and locking a single byte there.
       
   739 There is a possible problem with that random file position, because the database file may be shared between multiple
       
   740 connections. That increases the possibility of generating the same "random" file position by different connections to the
       
   741 same file. In order to minimise that, TFileIo::GetReadLock() will generate up to 3 different file positions in a case of
       
   742 a "lock byte" failure. 
       
   743 The generated file position will be stored in TDbFile::iSharedLockByte data member and will be used later for the 
       
   744 unlock operation.
       
   745 
       
   746 @param aDbFile The Os porting layer file handle
       
   747 @return KErrNone 	The locking operation has completed successfully,
       
   748 		KErrLocked	The 1 byte file area that begins from the generated file position is already locked,
       
   749 				    Some other system-wide error codes in a case of  failure.
       
   750 
       
   751 @see TFileIo::UnlockReadLock()
       
   752 */
       
   753 /* static */TInt TFileIo::GetReadLock(TDbFile& aDbFile)
       
   754 	{
       
   755 	const TInt KLockTryCount = 3;
       
   756 	TInt rc = KErrLocked;
       
   757 	for(TInt i=0;i<KLockTryCount;++i)
       
   758 		{
       
   759 	    TInt lock = Math::Rand(Seed());
       
   760 	    //Explanation regarding how the file locking works can be found in os.h file, lines 279-335.
       
   761 	    //Shortly, in order to read pages from the database the calling thread must obtain a shared lock.
       
   762 	    //This is done locking a randomly chosen byte - iSharedLockByte.
       
   763 	    //The calculation of iSharedLockByte is done in a way that:
       
   764 	    // - All calculated iSharedLockByte fit on a single page, even if the page size is chosen to be the smallest one possible.
       
   765 	    //       That's why the "% (SHARED_SIZE - 1)" is used in the calculation;
       
   766 	    // - The locked byte cannot be used for storing data. That is the reason SHARED_FIRST to be set to be a position beyond the
       
   767 	    //       1Gb boundary;
       
   768 	    TInt sharedLockByte = (lock & 0x7fffffff) % (SHARED_SIZE - 1);
       
   769 	    rc = aDbFile.iFileBuf.Lock(SHARED_FIRST + sharedLockByte, 1);
       
   770 	    if(rc == KErrNone)
       
   771 	    	{
       
   772 	    	aDbFile.iSharedLockByte = sharedLockByte;
       
   773 	    	break;
       
   774 	    	}
       
   775 		}
       
   776 	return rc;
       
   777 	}
       
   778 
       
   779 /**
       
   780 Unlocks the file area previously locked by the GetReadLock() call.
       
   781 The beginning of the locked area with length 1 byte is stored in TDbFile::iSharedLockByte data member.
       
   782 
       
   783 @param aDbFile The Os porting layer file handle
       
   784 
       
   785 @return KErrNone 	The locking operation has completed successfully,
       
   786 				    Some other system-wide error codes in a case of  failure.
       
   787 
       
   788 @see TFileIo::GetReadLock()
       
   789 */
       
   790 /* static */TInt TFileIo::UnlockReadLock(TDbFile& aDbFile)
       
   791 	{
       
   792 	return aDbFile.iFileBuf.UnLock(SHARED_FIRST + aDbFile.iSharedLockByte, 1);
       
   793 	}
       
   794 
       
   795 /**
       
   796 SQLite OS porting layer API.
       
   797 
       
   798 Locks the file, referred by the aDbFile parameter, with the specified lock type.
       
   799 The file lock type is stored for later use by the CheckReservedLock() call.
       
   800 
       
   801 Sometimes when requesting one lock state, additional lock states
       
   802 are inserted in between.  The locking might fail on one of the later
       
   803 transitions leaving the lock state different from what it started but
       
   804 still short of its goal.  The following chart shows the allowed
       
   805 transitions and the inserted intermediate states:
       
   806 
       
   807 SQLITE_LOCK_NONE		-> SQLITE_LOCK_SHARED
       
   808 SQLITE_LOCK_SHARED 		-> SQLITE_LOCK_RESERVED
       
   809 SQLITE_LOCK_SHARED 		-> (SQLITE_LOCK_PENDING) 	-> 	SQLITE_LOCK_EXCLUSIVE
       
   810 SQLITE_LOCK_RESERVED 	-> (SQLITE_LOCK_PENDING) 	-> 	SQLITE_LOCK_EXCLUSIVE
       
   811 SQLITE_LOCK_PENDING 	-> SQLITE_LOCK_EXCLUSIVE
       
   812 
       
   813 @param aDbFile A pointer to a TDbFile instance, that contains the file handle.
       
   814 @param aLockType Lock type: SQLITE_LOCK_NONE, SQLITE_LOCK_SHARED, SQLITE_LOCK_RESERVED, SQLITE_LOCK_PENDING or
       
   815 				 SQLITE_LOCK_EXCLUSIVE.
       
   816 
       
   817 @return SQLITE_IOERR_NOMEM,	An out of memory condition has occured;
       
   818 	    SQLITE_BUSY,	    The requested lock cannot be obtained;
       
   819 	    SQLITE_LOCK,		File locking error,
       
   820 	    SQLITE_OK,			The operation has completed successfully.
       
   821 
       
   822 @see TFileIo::CheckReservedLock()
       
   823 @see TFileIo::Unlock()
       
   824 	    
       
   825 @see TDbFile
       
   826 */
       
   827 /* static */ int TFileIo::Lock(sqlite3_file* aDbFile, int aLockType)
       
   828 	{
       
   829 	SQLUTRACE_PROFILER(aDbFile);
       
   830 	TDbFile& dbFile = ::DbFile(aDbFile);
       
   831 	//If there is already a lock of this type or more restrictive on the aDbFile, then - do nothing.
       
   832 	if(dbFile.iLockType >= aLockType)
       
   833 		{
       
   834 		return SQLITE_OK;
       
   835 		}
       
   836 
       
   837 	//The file flushing here must be done in order to get the file buffer object content (iFileBuf data member))
       
   838 	//synchronised with the database file content (the database file content may get modified by a different connection
       
   839 	//at the same time).
       
   840 	if(aLockType == SQLITE_LOCK_SHARED && !dbFile.iReadOnly)
       
   841 		{
       
   842 		TInt err = dbFile.iFileBuf.Flush(ETrue);
       
   843 		if(err != KErrNone)
       
   844 			{
       
   845 			return ::Os2SqliteErr(err, SQLITE_IOERR_LOCK);
       
   846 			}
       
   847 		}
       
   848 
       
   849 	//Make sure the locking sequence is correct
       
   850 	__ASSERT_DEBUG(dbFile.iLockType != SQLITE_LOCK_NONE || aLockType == SQLITE_LOCK_SHARED, User::Panic(KPanicCategory, EPanicInvalidLock));
       
   851 	__ASSERT_DEBUG(aLockType != SQLITE_LOCK_PENDING, User::Panic(KPanicCategory, EPanicInvalidLock));
       
   852 	__ASSERT_DEBUG(aLockType != SQLITE_LOCK_RESERVED || dbFile.iLockType == SQLITE_LOCK_SHARED, User::Panic(KPanicCategory, EPanicInvalidLock));
       
   853 		
       
   854 	TInt rc = SQLITE_OK;    //Return code from subroutines
       
   855 	TBool locked = ETrue;   //Result of a file lock call (the default value means: "lock accuired")
       
   856   	TInt newLockType = -1;	//Set dbFile.iLockType to this value before exiting
       
   857 	TBool gotPendingLock = EFalse;//True if we acquired a SQLITE_LOCK_PENDING lock this time
       
   858 
       
   859 	//Lock the SQLITE_LOCK_PENDING byte if we need to acquire a SQLITE_LOCK_PENDING lock or
       
   860 	//SQLITE_LOCK_SHARED lock. If we are acquiring a SQLITE_LOCK_SHARED lock, the acquisition of
       
   861 	//the SQLITE_LOCK_PENDING byte is temporary.
       
   862 	newLockType = dbFile.iLockType;
       
   863 	if(dbFile.iLockType == SQLITE_LOCK_NONE || (aLockType == SQLITE_LOCK_EXCLUSIVE && dbFile.iLockType == SQLITE_LOCK_RESERVED))
       
   864 		{
       
   865 		//Try 3 times to get the pending lock.  The pending lock might be
       
   866 		//held by another reader process who will release it momentarily.
       
   867 		const TInt KLockTryCnt = 3;
       
   868 		locked = EFalse;
       
   869 		for(TInt i=0;i<KLockTryCnt && !locked;++i)
       
   870 			{
       
   871 			TInt err = dbFile.iFileBuf.Lock(PENDING_BYTE, 1);
       
   872 			if(err != KErrNone && err != KErrLocked) 
       
   873 				{
       
   874 				return ::Os2SqliteErr(err, SQLITE_IOERR_LOCK);
       
   875 				}
       
   876 			locked = (err == KErrNone);
       
   877    			if(!locked)
       
   878    				{
       
   879 				const TInt KMs = 10;
       
   880 				TVfs::Sleep(NULL, KMs * 1000);
       
   881    				}
       
   882 			}
       
   883 		gotPendingLock = locked;
       
   884 		}
       
   885 
       
   886 	//Acquire a shared lock
       
   887 	if(aLockType == SQLITE_LOCK_SHARED && locked)
       
   888 		{
       
   889 		__ASSERT_DEBUG(dbFile.iLockType == SQLITE_LOCK_NONE, User::Panic(KPanicCategory, EPanicInvalidLock));
       
   890 		TInt err = TFileIo::GetReadLock(dbFile);
       
   891 		if(err != KErrNone && err != KErrLocked) 
       
   892 			{
       
   893 			return ::Os2SqliteErr(err, SQLITE_IOERR_LOCK);
       
   894 			}
       
   895 		locked = (err == KErrNone);
       
   896 		if(locked)
       
   897 			{
       
   898 			newLockType = SQLITE_LOCK_SHARED;
       
   899 			}
       
   900   		}
       
   901 
       
   902 	//Acquire a RESERVED lock
       
   903 	if(aLockType == SQLITE_LOCK_RESERVED && locked)
       
   904 		{
       
   905 		__ASSERT_DEBUG(dbFile.iLockType == SQLITE_LOCK_SHARED, User::Panic(KPanicCategory, EPanicInvalidLock));
       
   906 		TInt err = dbFile.iFileBuf.Lock(RESERVED_BYTE, 1); 
       
   907 		if(err != KErrNone && err != KErrLocked) 
       
   908 			{
       
   909 			return ::Os2SqliteErr(err, SQLITE_IOERR_LOCK);
       
   910 			}
       
   911 		locked = (err == KErrNone);
       
   912 		if(locked)
       
   913 			{
       
   914 			newLockType = SQLITE_LOCK_RESERVED;
       
   915 			}
       
   916 		}
       
   917 
       
   918 	// Acquire a PENDING lock
       
   919 	if(aLockType == SQLITE_LOCK_EXCLUSIVE && locked)
       
   920 		{
       
   921 		newLockType = SQLITE_LOCK_PENDING;
       
   922 		gotPendingLock = EFalse;
       
   923 		}
       
   924 
       
   925 	//Acquire an EXCLUSIVE lock
       
   926 	if(aLockType == SQLITE_LOCK_EXCLUSIVE && locked)
       
   927 		{
       
   928 		__ASSERT_DEBUG(dbFile.iLockType >= SQLITE_LOCK_SHARED, User::Panic(KPanicCategory, EPanicInvalidLock));
       
   929 		(void)TFileIo::UnlockReadLock(dbFile);
       
   930 		TInt err = dbFile.iFileBuf.Lock(SHARED_FIRST, SHARED_SIZE);
       
   931 		if(err != KErrNone && err != KErrLocked)
       
   932 			{
       
   933 			return ::Os2SqliteErr(err, SQLITE_IOERR_LOCK);
       
   934 			}
       
   935 		locked = (err == KErrNone);
       
   936 		if(locked)
       
   937 			{
       
   938 			newLockType = SQLITE_LOCK_EXCLUSIVE;
       
   939 			}
       
   940 		}
       
   941 
       
   942 	// If we are holding a PENDING lock that ought to be released, then
       
   943 	// release it now.
       
   944 	if(gotPendingLock && aLockType == SQLITE_LOCK_SHARED)
       
   945 		{
       
   946 		(void)dbFile.iFileBuf.UnLock(PENDING_BYTE, 1);
       
   947   		}
       
   948 
       
   949 	// Update the state of the lock has held in the file descriptor then
       
   950 	// return the appropriate result code.
       
   951 	rc = locked ? SQLITE_OK : SQLITE_BUSY;
       
   952 	dbFile.iLockType = newLockType;
       
   953 	return rc;
       
   954 	}
       
   955 
       
   956 /**
       
   957 SQLite OS porting layer API.
       
   958 
       
   959 Lower the locking level on file descriptor id to locktype.  locktype
       
   960 must be either SQLITE_LOCK_NONE or SQLITE_LOCK_SHARED.
       
   961 
       
   962 If the locking level of the file descriptor is already at or below
       
   963 the requested locking level, this routine is a no-op.
       
   964 
       
   965 It is not possible for this routine to fail if the second argument
       
   966 is SQLITE_LOCK_NONE. If the second argument is SQLITE_LOCK_SHARED then this routine
       
   967 might return SQLITE_IOERR;
       
   968 
       
   969 @param aDbFile A pointer to a TDbFile instance, that contains the file handle.
       
   970 @param aLockType Lock type: SQLITE_LOCK_NONE, SQLITE_LOCK_SHARED, SQLITE_LOCK_RESERVED, SQLITE_LOCK_PENDING or
       
   971 				 SQLITE_LOCK_EXCLUSIVE.
       
   972 
       
   973 @return SQLITE_OK,	 		 The operation has completed successfully,
       
   974 	     SQLITE_IOERR_UNLOCK, The unlock operation has failed. 
       
   975 
       
   976 @see TFileIo::CheckReservedLock()
       
   977 @see TFileIo::Lock()
       
   978 	    
       
   979 @see TDbFile
       
   980 */
       
   981 /* static */ int TFileIo::Unlock(sqlite3_file* aDbFile, int aLockType)
       
   982 	{
       
   983 	__ASSERT_DEBUG(aLockType <= SQLITE_LOCK_SHARED, User::Panic(KPanicCategory, EPanicInvalidLock));
       
   984 	
       
   985 	SQLUTRACE_PROFILER(aDbFile);
       
   986 	TDbFile& dbFile = ::DbFile(aDbFile);
       
   987 	TInt rc = SQLITE_OK;
       
   988 	TInt currLockType = dbFile.iLockType;
       
   989 	
       
   990 	if(currLockType >= SQLITE_LOCK_EXCLUSIVE)
       
   991 		{
       
   992 		(void)dbFile.iFileBuf.UnLock(SHARED_FIRST, SHARED_SIZE);
       
   993 		if(aLockType == SQLITE_LOCK_SHARED)
       
   994     		{
       
   995 			TInt err = TFileIo::GetReadLock(dbFile); 
       
   996 			if(err != KErrNone && err != KErrLocked)
       
   997 				{
       
   998 				return ::Os2SqliteErr(err, SQLITE_IOERR_UNLOCK);
       
   999 				}
       
  1000 			if(err == KErrLocked)
       
  1001 				{
       
  1002 				//This should never happen. We should always be able to reacquire the read lock
       
  1003 				rc = SQLITE_IOERR_UNLOCK;
       
  1004 				}
       
  1005 			}
       
  1006 		}
       
  1007 	if(currLockType >= SQLITE_LOCK_RESERVED)
       
  1008 		{
       
  1009     	(void)dbFile.iFileBuf.UnLock(RESERVED_BYTE, 1);
       
  1010 		}
       
  1011 	if(aLockType == SQLITE_LOCK_NONE && currLockType >= SQLITE_LOCK_SHARED)
       
  1012 		{
       
  1013 		(void)TFileIo::UnlockReadLock(dbFile);
       
  1014 		}
       
  1015 	if(currLockType>= SQLITE_LOCK_PENDING)
       
  1016 		{
       
  1017 		(void)dbFile.iFileBuf.UnLock(PENDING_BYTE, 1);
       
  1018 		}
       
  1019 		
       
  1020 	dbFile.iLockType = aLockType;
       
  1021 	return rc;
       
  1022 	}
       
  1023 
       
  1024 /**
       
  1025 SQLite OS porting layer API.
       
  1026 
       
  1027 Checks if the file lock type is SQLITE_LOCK_RESERVED or bigger.
       
  1028 
       
  1029 @param aDbFile A pointer to a TDbFile instance, that contains the file handle.
       
  1030 @param aResOut Output parameter. It should be set to 1 if the stored lock type is bigger or equal 
       
  1031 							     than SQLITE_LOCK_RESERVED.
       
  1032 
       
  1033 @return SQLITE_IOERR_CHECKRESERVEDLOCK, The operation has failed,
       
  1034 	    SQLITE_OK 					    The operation has completed successfully.
       
  1035 
       
  1036 @see TFileIo::Lock()
       
  1037 @see TFileIo::Unlock()
       
  1038 	    
       
  1039 @see TDbFile
       
  1040 */
       
  1041 /* static */ int TFileIo::CheckReservedLock(sqlite3_file* aDbFile, int *aResOut)
       
  1042 	{
       
  1043 	SQLUTRACE_PROFILER(aDbFile);
       
  1044 	TDbFile& dbFile = ::DbFile(aDbFile);
       
  1045 	TInt rc;
       
  1046 	if(dbFile.iLockType >= SQLITE_LOCK_RESERVED)
       
  1047 		{
       
  1048 		rc = 1;
       
  1049   		}
       
  1050 	else
       
  1051 		{
       
  1052 		TInt err = dbFile.iFileBuf.Lock(RESERVED_BYTE, 1);
       
  1053 		if(err != KErrNone && err != KErrLocked)
       
  1054 			{
       
  1055 			return ::Os2SqliteErr(err, SQLITE_IOERR_CHECKRESERVEDLOCK);
       
  1056 			}
       
  1057 		rc = (err == KErrNone);
       
  1058 		if(rc) //non-zero rc means: the lock has been successful (there wasn't a reserved lock on this file)
       
  1059 			{
       
  1060 			(void)dbFile.iFileBuf.UnLock(RESERVED_BYTE, 1);
       
  1061 			}
       
  1062     	rc = !rc;
       
  1063 		}
       
  1064 	*aResOut = rc;
       
  1065 	return SQLITE_OK;
       
  1066 	}
       
  1067 
       
  1068 /**
       
  1069 SQLite OS porting layer API.
       
  1070 
       
  1071 Performs an aOp operation on the file referred by the aDbFile parameter.
       
  1072 Since the only supported operation at the moment is SQLITE_FCNTL_LOCKSTATE, and the current lock type is stored as
       
  1073 a data memebr of TDbFile, the function implementation has been optimised - no file I/O calls. The stored file lock type
       
  1074 is retured if the operation is SQLITE_FCNTL_LOCKSTATE.
       
  1075 
       
  1076 @param aDbFile A pointer to a TDbFile instance, that contains the file handle.
       
  1077 @param aOp File operation type. Currently only SQLITE_FCNTL_LOCKSTATE is supported.
       
  1078 @param aArg An additional input/output parameter which purpose depends on the type of the current file operation.
       
  1079 			If the file operation is SQLITE_FCNTL_LOCKSTATE, then aArg is used as an output parameter, where
       
  1080 			the file lock type is stored.
       
  1081 
       
  1082 @return SQLITE_ERROR,	Non-supported operation,
       
  1083 		SQLITE_OK,	The operation has completed successfully.
       
  1084 	    
       
  1085 @see TDbFile
       
  1086 */
       
  1087 /* static */ int TFileIo::FileControl(sqlite3_file* aDbFile, int aOp, void* aArg)
       
  1088 	{
       
  1089 	SQLUTRACE_PROFILER(aDbFile);
       
  1090 	TDbFile& dbFile = ::DbFile(aDbFile);
       
  1091 	SYMBIAN_TRACE_SQLITE_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EInternals), KFileFileCtr, aOp, dbFile.iFullName));
       
  1092 	TInt err = KErrNone;
       
  1093 	switch(aOp)
       
  1094 		{
       
  1095 		case SQLITE_FCNTL_LOCKSTATE:
       
  1096 			*(int*)aArg = dbFile.iLockType;
       
  1097 			break;
       
  1098 		default:
       
  1099 			err = KErrArgument;
       
  1100 			break;
       
  1101 		}
       
  1102 	return err == KErrNone ? SQLITE_OK : SQLITE_ERROR;
       
  1103 	}
       
  1104 
       
  1105 /**
       
  1106 SQLite OS porting layer API.
       
  1107 
       
  1108 Retrieves the sector size of the media of the file referred by the aDbFile parameter.
       
  1109 Since the sector size never changes till the file is open, the function has been optimised - no file I/O calls.
       
  1110 The sector size is retrieved during the TVfs::Open() call and stored in TDbFile::iSectorSize. The SectorSize()
       
  1111 call returns the value of TDbFile::iSectorSize.
       
  1112 
       
  1113 @param aDbFile A pointer to a TDbFile instance, that contains the file handle.
       
  1114 
       
  1115 @return The sector size.
       
  1116 
       
  1117 @panic Sqlite 19 In _DEBUG mode - TDbFile::iSectorSize is negative or 0 .
       
  1118 	    
       
  1119 @see TDbFile
       
  1120 @see TVfs::Open()
       
  1121 */
       
  1122 /* static */ int TFileIo::SectorSize(sqlite3_file* aDbFile)
       
  1123 	{
       
  1124 	SQLUTRACE_PROFILER(aDbFile);
       
  1125 	TDbFile& dbFile = ::DbFile(aDbFile);
       
  1126 	__ASSERT_DEBUG(dbFile.iSectorSize > 0, User::Panic(KPanicCategory, EPanicInternalError));
       
  1127 	if(dbFile.iSectorSize > 0)
       
  1128 		{
       
  1129 		return dbFile.iSectorSize;	
       
  1130 		}
       
  1131 	return SQLITE_DEFAULT_SECTOR_SIZE;
       
  1132 	}
       
  1133 
       
  1134 /**
       
  1135 SQLite OS porting layer API.
       
  1136 
       
  1137 Retrieves the device characteristics of the device of the file referred by the aDbFile parameter.
       
  1138 Since the device characteristics never change till the file is open, the function has been optimised - no file I/O calls.
       
  1139 The device characteristics are retrieved during the TVfs::Open() call and stored in TDbFile::iDeviceCharacteristics. 
       
  1140 The DeviceCharacteristics() call returns the value of TDbFile::iDeviceCharacteristics.
       
  1141 
       
  1142 @param aDbFile A pointer to a TDbFile instance, that contains the file handle.
       
  1143 
       
  1144 @return A bit set containing the device characteristics.
       
  1145 	    
       
  1146 @panic Sqlite 19 In _DEBUG mode - TDbFile::iDeviceCharacteristics is negative or 0 .
       
  1147 
       
  1148 @see TDbFile
       
  1149 @see TVfs::Open()
       
  1150 */
       
  1151 /* static */ int TFileIo::DeviceCharacteristics(sqlite3_file* aDbFile)
       
  1152 	{
       
  1153 	SQLUTRACE_PROFILER(aDbFile);
       
  1154 	TDbFile& dbFile = ::DbFile(aDbFile);
       
  1155 	__ASSERT_DEBUG(dbFile.iDeviceCharacteristics >= 0, User::Panic(KPanicCategory, EPanicInternalError));
       
  1156 	if(dbFile.iDeviceCharacteristics >= 0)
       
  1157 		{
       
  1158 		return dbFile.iDeviceCharacteristics;	
       
  1159 		}
       
  1160 	return 0;
       
  1161 	}
       
  1162 
       
  1163 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
  1164 ///////////////////////////////////       TVfs class definition     ///////////////////////////////////////////////////////////
       
  1165 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
  1166 
       
  1167 /**
       
  1168 Collects information about the drive referred by the aDriveNo parameter.
       
  1169 
       
  1170 @param aFs			RFs instance.
       
  1171 @param aDriveNo     The drive about which an information will be collected.
       
  1172 @param aVolumeInfo	Output parameter. A reference to a TVolumeIOParamInfo object where the collected information will be stored.
       
  1173 
       
  1174 @return KErrNone,          The operation has completed succesfully;
       
  1175 	    KErrNoMemory,      Out of memory condition has occured;
       
  1176                            Note that other system-wide error codes may also be returned.
       
  1177 	    
       
  1178 @see TVfs::Open()
       
  1179 */
       
  1180 /* static */ inline TInt TVfs::DoGetVolumeIoParamInfo(RFs& aFs, TInt aDriveNo, TVolumeIOParamInfo& aVolumeInfo)
       
  1181 	{
       
  1182 	return aFs.VolumeIOParam(aDriveNo, aVolumeInfo);
       
  1183 	}
       
  1184 
       
  1185 /**
       
  1186 Retrieves and returns in a bit set the device characteristics.
       
  1187 
       
  1188 @param aDriveInfo	A TDriveInfo reference from which the device characteristics will be extracted.
       
  1189 @param aVolumeInfo	A TVolumeIOParamInfo reference from which the device characteristics will be extracted.
       
  1190 
       
  1191 @return A bit set containing the device characteristics: 
       
  1192 			SQLITE_IOCAP_SAFE_APPEND, SQLITE_IOCAP_ATOMIC, the atomic block size.
       
  1193 	    
       
  1194 @see TVfs::DoGetDriveInfo();
       
  1195 @see TVfs::DoGetVolumeIoParamInfo();
       
  1196 @see TVfs::Open()
       
  1197 */
       
  1198 /* static */ TInt TVfs::DoGetDeviceCharacteristics(const TDriveInfo& aDriveInfo, const TVolumeIOParamInfo& aVolumeInfo)
       
  1199 	{
       
  1200 	TInt deviceCharacteristics = 0;	
       
  1201 	if(aDriveInfo.iDriveAtt & (KDriveAttLocal | KDriveAttInternal))
       
  1202 		{
       
  1203 		deviceCharacteristics |= SQLITE_IOCAP_SAFE_APPEND;//Data written first, file size updated second
       
  1204 		}
       
  1205 	if(aDriveInfo.iDriveAtt & KDriveAttTransaction)
       
  1206 		{
       
  1207 		deviceCharacteristics |= SQLITE_IOCAP_ATOMIC;	
       
  1208 		}
       
  1209 	if(aVolumeInfo.iBlockSize >= SQLITE_DEFAULT_SECTOR_SIZE && (aVolumeInfo.iBlockSize & (aVolumeInfo.iBlockSize - 1)) == 0)	
       
  1210 		{
       
  1211 		switch(aVolumeInfo.iBlockSize)
       
  1212 			{
       
  1213 			case 512:
       
  1214 				deviceCharacteristics |= SQLITE_IOCAP_ATOMIC512;
       
  1215 				break;
       
  1216 			case 1024:
       
  1217 				deviceCharacteristics |= SQLITE_IOCAP_ATOMIC1K;
       
  1218 				break;
       
  1219 			case 2048:
       
  1220 				deviceCharacteristics |= SQLITE_IOCAP_ATOMIC2K;
       
  1221 				break;
       
  1222 			case 4096:
       
  1223 				deviceCharacteristics |= SQLITE_IOCAP_ATOMIC4K;
       
  1224 				break;
       
  1225 			case 8192:
       
  1226 				deviceCharacteristics |= SQLITE_IOCAP_ATOMIC8K;
       
  1227 				break;
       
  1228 			case 16384:
       
  1229 				deviceCharacteristics |= SQLITE_IOCAP_ATOMIC16K;
       
  1230 				break;
       
  1231 			case 32768:
       
  1232 				deviceCharacteristics |= SQLITE_IOCAP_ATOMIC32K;
       
  1233 				break;
       
  1234 			case 65536:
       
  1235 				deviceCharacteristics |= SQLITE_IOCAP_ATOMIC64K;
       
  1236 				break;
       
  1237 			default:
       
  1238 				//Do nothing. deviceCharacteristics was initialized with 0 at the beginning of the function body.
       
  1239 				break;
       
  1240 			}
       
  1241 		}
       
  1242 	return deviceCharacteristics;
       
  1243 	}
       
  1244 
       
  1245 /**
       
  1246 Retrieves and returns the sector size of the drive referred by the aDriveInfo parameter.
       
  1247 The sector size must be a power of two.
       
  1248 The sector size is extracted only if aDriveInfo refers to a removable device, otherwise the
       
  1249 SQLITE_DEFAULT_SECTOR_SIZE value (512 bytes) will be used as a sector size.
       
  1250 
       
  1251 @param aDriveInfo	A TDriveInfo reference.
       
  1252 @param aVolumeInfo	A TVolumeIOParamInfo reference.
       
  1253 
       
  1254 @return The sector size of the drive referred by the aDriveInfo parameter.
       
  1255 
       
  1256 @panic Sqlite 19 In _DEBUG mode - The sector size is negative, zero or is not a power of two.
       
  1257 	    
       
  1258 @see TVfs::Open()
       
  1259 */
       
  1260 /* static */ TInt TVfs::DoGetSectorSize(const TDriveInfo& aDriveInfo, const TVolumeIOParamInfo& aVolumeInfo)
       
  1261 	{
       
  1262 	//Initialize the sectorSize variable only if: 
       
  1263 	// - aDriveInfo refers to a removable drive
       
  1264 	// - aVolumeInfo.iBlockSize > SQLITE_DEFAULT_SECTOR_SIZE;
       
  1265 	// - aVolumeInfo.iBlockSize is power of 2;
       
  1266 	TInt sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
       
  1267 	if(aDriveInfo.iDriveAtt & KDriveAttRemovable)
       
  1268 		{
       
  1269 		if(aVolumeInfo.iBlockSize > SQLITE_DEFAULT_SECTOR_SIZE && (aVolumeInfo.iBlockSize & (aVolumeInfo.iBlockSize - 1)) == 0)
       
  1270 			{
       
  1271 			sectorSize = aVolumeInfo.iBlockSize;
       
  1272 			}
       
  1273 		}
       
  1274 	__ASSERT_DEBUG(sectorSize > 0 && (sectorSize & (sectorSize - 1)) == 0, User::Panic(KPanicCategory, EPanicInternalError));
       
  1275 	return sectorSize;
       
  1276 	}
       
  1277 
       
  1278 /**
       
  1279 Retrieves in a bit set the device characteristics of the device of the file referred by the aDbFile parameter.
       
  1280 Retrieves the sector size of the drive of the file referred by the aDbFile parameter. 
       
  1281 The sector size and the device characteristics will be stored in iSectorSize and iDeviceCharacteristics TDbFile data members.
       
  1282 The stored values will be used later by TFileIo::DeviceCharacteristics() and TFileIo::SectorSize().
       
  1283 
       
  1284 @param aDbFile	Input/Output parameter. A TDriveInfo reference. The collected information will be stored in TDbDrive
       
  1285 				data members.
       
  1286 @param aRecReadBufSize Output parameter. The recommended buffer size for optimised reading performance.
       
  1287 
       
  1288 @return KErrNone,          The operation has completed succesfully;
       
  1289                            Note that other system-wide error codes may also be returned.
       
  1290 
       
  1291 @panic Sqlite 19 In _DEBUG mode - TDbFile::iSectorSize has been already initialized.
       
  1292 @panic Sqlite 19 In _DEBUG mode - TDbFile::iDeviceCharacteristics has been already initialized.
       
  1293 
       
  1294 @see TVfs::DoGetDeviceCharacteristics();
       
  1295 @see TVfs::DoGetSectorSize();
       
  1296 @see TVfs::Open()
       
  1297 @see TDbFile
       
  1298 @see TFileIo::DeviceCharacteristics()
       
  1299 @see TFileIo::SectorSize()
       
  1300 */
       
  1301 /* static */ TInt TVfs::DoGetDeviceCharacteristicsAndSectorSize(TDbFile& aDbFile, TInt& aRecReadBufSize)
       
  1302 	{
       
  1303 	__ASSERT_DEBUG(aDbFile.iDeviceCharacteristics < 0, User::Panic(KPanicCategory, EPanicInternalError));
       
  1304 	__ASSERT_DEBUG(aDbFile.iSectorSize <= 0, User::Panic(KPanicCategory, EPanicInternalError));
       
  1305 	TInt driveNo;
       
  1306 	TDriveInfo driveInfo;
       
  1307 	TInt err = aDbFile.iFileBuf.Drive(driveNo, driveInfo);
       
  1308 	if(err != KErrNone)
       
  1309 		{
       
  1310 		return err;	
       
  1311 		}
       
  1312 	TVolumeIOParamInfo volumeInfo;
       
  1313 	err = TVfs::DoGetVolumeIoParamInfo(TStaticFs::Fs(), driveNo, volumeInfo);
       
  1314 	if(err != KErrNone)
       
  1315 		{
       
  1316 		return err;	
       
  1317 		}
       
  1318 	aDbFile.iDeviceCharacteristics = TVfs::DoGetDeviceCharacteristics(driveInfo, volumeInfo);
       
  1319 	aDbFile.iSectorSize = TVfs::DoGetSectorSize(driveInfo, volumeInfo);
       
  1320 	aRecReadBufSize = volumeInfo.iRecReadBufSize;
       
  1321 	return KErrNone;
       
  1322 	}
       
  1323 
       
  1324 //Creates a temporary file. The file location will be the application's session path. 
       
  1325 //If the session path does not exist, then the function will create the session path.
       
  1326 static TInt CreateTempFile(TDbFile& aDbFile, TFileName& aFileNameOut, TInt aFileMode)
       
  1327 	{
       
  1328 	TFileName sessionPath;
       
  1329 	TInt err = TStaticFs::Fs().SessionPath(sessionPath);
       
  1330 	if(err == KErrNone)
       
  1331 		{
       
  1332 		err = aDbFile.iFileBuf.Temp(TStaticFs::Fs(), sessionPath, aFileNameOut, aFileMode);
       
  1333 		if(err == KErrPathNotFound)
       
  1334 			{
       
  1335 			err = TStaticFs::Fs().MkDirAll(sessionPath);
       
  1336 			if(err == KErrNone)
       
  1337 				{
       
  1338 				err = aDbFile.iFileBuf.Temp(TStaticFs::Fs(), sessionPath, aFileNameOut, aFileMode);
       
  1339 				}
       
  1340 			}
       
  1341 		if(err == KErrNone)
       
  1342 			{
       
  1343 			aDbFile.iFullName = aFileNameOut.Alloc();
       
  1344 			if(!aDbFile.iFullName)
       
  1345 				{
       
  1346 				aDbFile.iFileBuf.Close();
       
  1347 				(void)TStaticFs::Fs().Delete(aFileNameOut);
       
  1348 				err = KErrNoMemory;
       
  1349 				}
       
  1350 			}
       
  1351 		}
       
  1352 	return err;
       
  1353 	}
       
  1354 
       
  1355 /**
       
  1356 SQLite OS porting layer API.
       
  1357 
       
  1358 Opens or creates a file which name is in the aFileName parameter.
       
  1359 If the function succeeds, the file handle and other related information will be stored in the place pointed by the 
       
  1360 aDbFile parameter, a memory block of sizeof(TDbFile) size for which is allocated by the caller.
       
  1361 The function will also retrieve the sector size and the device characteristics and store them in aDbFile,
       
  1362 which is actually a TDbFile pointer, for later use.
       
  1363 
       
  1364 @param aFileName Zero-terminated, UTF8 encoded file name.
       
  1365 				 If aFileName is NULL then a temporary file is created.
       
  1366 @param aDbFile Output parameter. The file handle and other related information will be stored there.
       
  1367 @param aFlags  "Open/Create" input flags: 
       
  1368 					SQLITE_OPEN_DELETEONCLOSE,
       
  1369 					SQLITE_OPEN_READWRITE,
       
  1370 					SQLITE_OPEN_EXCLUSIVE,
       
  1371 					SQLITE_OPEN_CREATE
       
  1372 @param aOutFlags  "Open/Create" output flags:
       
  1373 					SQLITE_OPEN_READWRITE,
       
  1374 					SQLITE_OPEN_READONLY
       
  1375 
       
  1376 @return SQLITE_CANTOPEN,    The aFileName parameter cannot be converted to UTF16.
       
  1377 							Any other file I/O error will also be reported as SQLITE_CANTOPEN;
       
  1378 	    SQLITE_IOERR_NOMEM,	An out of memory condition has occured;
       
  1379 	    SQLITE_OK,			The operation has completed successfully.
       
  1380 	    
       
  1381 @see TDbFile
       
  1382 */
       
  1383 /* static */ int TVfs::Open(sqlite3_vfs* aVfs, const char* aFileName, sqlite3_file* aDbFile, int aFlags, int* aOutFlags)
       
  1384 	{
       
  1385 	SQLUTRACE_PROFILER(aVfs);
       
  1386 	TFileName fname;
       
  1387 	if(aFileName && !::ConvertToUnicode(aFileName, fname))
       
  1388 		{
       
  1389 		return SQLITE_CANTOPEN;	
       
  1390 		}
       
  1391 	SYMBIAN_TRACE_SQLITE_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EInternals), KFileOpen, aDbFile, &fname));
       
  1392 	new (aDbFile) TDbFile;
       
  1393 	TDbFile& dbFile = ::DbFile(aDbFile);
       
  1394 	if(aFileName && (aFlags & SQLITE_OPEN_DELETEONCLOSE))
       
  1395 		{
       
  1396 		dbFile.iFullName = fname.Alloc();
       
  1397 		if(!dbFile.iFullName)
       
  1398 			{
       
  1399 			return SQLITE_IOERR_NOMEM;
       
  1400 			}
       
  1401 		}
       
  1402 	TInt recReadBufSize = -1;
       
  1403 	TInt err = KErrNone;
       
  1404 	TInt fmode = EFileRead;
       
  1405 	if(aFlags & SQLITE_OPEN_READWRITE)
       
  1406 		{
       
  1407 		fmode |= EFileWrite;
       
  1408 		}
       
  1409 	//SQLite TCL tests expect the journal file to be open in shared mode.
       
  1410 	if(aFlags & SQLITE_OPEN_EXCLUSIVE && !(aFlags & SQLITE_OPEN_MAIN_JOURNAL))
       
  1411 		{
       
  1412 		fmode |= EFileShareExclusive;
       
  1413 		}
       
  1414 	else
       
  1415 		{
       
  1416 		fmode |= (fmode & EFileWrite) ? EFileShareAny : EFileShareReadersOnly;
       
  1417 		}
       
  1418 	if(!aFileName)	
       
  1419 		{//Create temporary file
       
  1420 		err = ::CreateTempFile(dbFile, fname, fmode);
       
  1421 		}
       
  1422 	else
       
  1423 		{
       
  1424 		err = KErrGeneral;//The error has to be set here, because, there is case where none of the file create/open operations will be executed
       
  1425 		if(aFlags & SQLITE_OPEN_CREATE)
       
  1426 			{
       
  1427 			err = dbFile.iFileBuf.Create(TStaticFs::Fs(), fname, fmode);
       
  1428 			}
       
  1429 		if(err != KErrNone && err != KErrNoMemory)
       
  1430 			{
       
  1431 			err = dbFile.iFileBuf.Open(TStaticFs::Fs(), fname, fmode);
       
  1432 			}
       
  1433 		if((err != KErrNone && err != KErrNoMemory) && (aFlags & SQLITE_OPEN_READWRITE))
       
  1434 			{
       
  1435 			aFlags &= ~SQLITE_OPEN_READWRITE;
       
  1436 			aFlags |= SQLITE_OPEN_READONLY;
       
  1437 			fmode &= ~EFileWrite;
       
  1438 			err = dbFile.iFileBuf.Open(TStaticFs::Fs(), fname, fmode);
       
  1439 			}
       
  1440 		}
       
  1441 	if(err == KErrNone)
       
  1442 		{
       
  1443 		err = TVfs::DoGetDeviceCharacteristicsAndSectorSize(dbFile, recReadBufSize);
       
  1444 		}
       
  1445 	if(err != KErrNone)
       
  1446 		{
       
  1447 		dbFile.iFileBuf.Close();	
       
  1448 		delete dbFile.iFullName;
       
  1449 		dbFile.iFullName = NULL;
       
  1450 		}
       
  1451 	else
       
  1452 		{
       
  1453 		dbFile.pMethods = &TheFileIoApi;
       
  1454 		dbFile.iReadOnly = !(aFlags & SQLITE_OPEN_READWRITE);
       
  1455 		if(aOutFlags)
       
  1456 			{
       
  1457 			*aOutFlags = dbFile.iReadOnly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_READWRITE;
       
  1458 			}
       
  1459 		(void)dbFile.iFileBuf.SetReadAheadSize(dbFile.iSectorSize, recReadBufSize);
       
  1460 		OpenCounter(+1);
       
  1461 		}
       
  1462 	return ::Os2SqliteErr(err, SQLITE_CANTOPEN);
       
  1463 	}
       
  1464 
       
  1465 /**
       
  1466 SQLite OS porting layer API.
       
  1467 
       
  1468 Deletes a file which name is in the aFileName parameter.
       
  1469 
       
  1470 @param aFileName Zero-terminated, UTF8 encoded file name.
       
  1471 
       
  1472 @return SQLITE_ERROR,    	The aFileName parameter cannot be converted to UTF16.
       
  1473 							The file name refers to a private secure database;
       
  1474 	    SQLITE_IOERR_NOMEM,	An out of memory condition has occured;
       
  1475 	    SQLITE_IOERR_DELETE,The delete file operation has failed;
       
  1476 	    SQLITE_OK,			The operation has completed successfully.
       
  1477 */
       
  1478 /* static */ int TVfs::Delete(sqlite3_vfs* aVfs, const char* aFileName, int /*aSyncDir*/)
       
  1479 	{
       
  1480 	SQLUTRACE_PROFILER(aVfs);
       
  1481 	SimulateIOError(return SQLITE_IOERR_DELETE);
       
  1482 	TFileName fname;
       
  1483 	if(!::ConvertToUnicode(aFileName, fname))
       
  1484 		{
       
  1485 		return SQLITE_ERROR;	
       
  1486 		}
       
  1487 	SYMBIAN_TRACE_SQLITE_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EInternals), KFileName, &fname));
       
  1488 	TInt err = TStaticFs::Fs().Delete(fname);
       
  1489 	return ::Os2SqliteErr(err, SQLITE_IOERR_DELETE);
       
  1490 	}
       
  1491 
       
  1492 /**
       
  1493 SQLite OS porting layer API.
       
  1494 
       
  1495 Retrieves an information about a file which name is in the aFileName parameter.
       
  1496 The requested information type can be: does the file exist, is the file read-only or read/write.
       
  1497 
       
  1498 @param aFileName Zero-terminated, UTF8 encoded file name.
       
  1499 @param aFlags This parameter can be one of: SQLITE_ACCESS_READ, SQLITE_ACCESS_EXISTS or SQLITE_ACCESS_READWRITE.
       
  1500 @param aResOut Output parameter, set to 1 if the tested condition is true, 0 otherwise.
       
  1501 
       
  1502 @return SQLITE_OK, 			The call has completed successfully,
       
  1503 		SQLITE_IOERR_NOMEM, An out of memory conditon has occured,
       
  1504 		SQLITE_IOERR_ACCESS,File I/O error;  
       
  1505 */
       
  1506 /* static */ int TVfs::Access(sqlite3_vfs* aVfs, const char* aFileName, int aFlags, int* aResOut)
       
  1507 	{
       
  1508 	SQLUTRACE_PROFILER(aVfs);
       
  1509 	TFileName fname;
       
  1510 	if(!::ConvertToUnicode(aFileName, fname))
       
  1511 		{
       
  1512 		return SQLITE_IOERR_ACCESS;
       
  1513 		}
       
  1514 	SYMBIAN_TRACE_SQLITE_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EInternals), KFileName, &fname));
       
  1515 	TEntry entry;
       
  1516 	TInt err = TStaticFs::Fs().Entry(fname, entry);
       
  1517 	if(aFlags == SQLITE_ACCESS_EXISTS && err == KErrNotFound)
       
  1518 		{
       
  1519 		*aResOut = 0;
       
  1520 		return SQLITE_OK;
       
  1521 		}
       
  1522 	if(err != KErrNone)
       
  1523 		{
       
  1524 		return err == KErrNoMemory ? SQLITE_IOERR_NOMEM : SQLITE_IOERR_ACCESS;
       
  1525 		}
       
  1526 	*aResOut = 0;
       
  1527 	switch(aFlags)
       
  1528 		{
       
  1529 		case SQLITE_ACCESS_READ:
       
  1530 			*aResOut =  entry.IsReadOnly();
       
  1531 			break;
       
  1532 		case SQLITE_ACCESS_EXISTS:
       
  1533 			*aResOut = 1;
       
  1534 			break;
       
  1535 		case SQLITE_ACCESS_READWRITE:
       
  1536 			*aResOut = !entry.IsReadOnly();
       
  1537 			break;
       
  1538 		default:
       
  1539 			break;			
       
  1540 		}
       
  1541 	return SQLITE_OK;
       
  1542 	}
       
  1543 
       
  1544 /**
       
  1545 SQLite OS porting layer API.
       
  1546 
       
  1547 Accepts UTF8 encoded, zero-terminated file as an input argument in the aRelative parameter
       
  1548 and constructs the full file path in the aBuf output parameter.
       
  1549 
       
  1550 If the format of aRelative argument is <[SID]FileName.[EXT]>, then the database file name will be 
       
  1551 treated as a name of a secure database file which has to be created/opened in the server's private 
       
  1552 directory on the system drive.
       
  1553 
       
  1554 If the format of aRelative argument is <Drive:[SID]FileName.[EXT]>, then the database file name 
       
  1555 will be treated as a name of a secure database file which has to be created/opened in the server's 
       
  1556 private directory on <Drive:> drive. 
       
  1557 
       
  1558 If the format of aRelative argument is <Drive:\Path\FileName.[EXT]>, then the database file name
       
  1559 will be treated as a name of a non-secure database file in <Drive:\Path\> directory.
       
  1560 If aRelative contains file handles, then it will be treated as a name of a file belonging to server's
       
  1561 private data cage. 
       
  1562 
       
  1563 @param aRelative The input file name, zero-terminated, UTF8 encoded.
       
  1564 @param aBufLen The output buffer length.
       
  1565 @param aBuf Output buffer for the constructed full file name path. The allocated buffer length must be at least aBufLen bytes.
       
  1566 
       
  1567 @return SQLITE_ERROR, The aRelative parameter is NULL or cannot be converted to UTF16;
       
  1568 		SQLITE_OK The operation has completed successfully.
       
  1569 */
       
  1570 /* static */ int TVfs::FullPathName(sqlite3_vfs* aVfs, const char* aRelative, int aBufLen, char* aBuf)
       
  1571 	{
       
  1572 	SQLUTRACE_PROFILER(aVfs);
       
  1573 	if(!aRelative)	//NULL argument
       
  1574 		{
       
  1575 		return SQLITE_ERROR;
       
  1576 		}
       
  1577 	//Convert the received file name to UTF16
       
  1578 	TBuf<KMaxFileName + 1> fname;
       
  1579 	if(!::ConvertToUnicode(aRelative, fname))
       
  1580 		{
       
  1581 		return SQLITE_ERROR;
       
  1582 		}	
       
  1583 	SYMBIAN_TRACE_SQLITE_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EInternals), KFileName, &fname));
       
  1584 	//Search if the file name begins with ".\" - current directory
       
  1585 	if(fname.Find(KCwd) == 0)
       
  1586 		{
       
  1587 		fname.Delete(0, KCwd().Length());
       
  1588 		}
       
  1589 	fname.Append(TChar(0));//Zero-terminate the converted file name
       
  1590 	TFileName defaultPath;
       
  1591 	TInt err = TStaticFs::Fs().SessionPath(defaultPath);
       
  1592 	if(err != KErrNone)
       
  1593 		{
       
  1594 		return SQLITE_ERROR;
       
  1595 		}
       
  1596 	TParse parse;
       
  1597 	(void)parse.Set(fname, &defaultPath, 0);//If fname does not have a path, defaultPath will be used
       
  1598 	TPtr8 dest8(reinterpret_cast <TUint8*> (aBuf), aBufLen);	
       
  1599 	if(!::ConvertFromUnicode(parse.FullName(), dest8))
       
  1600 		{
       
  1601 		return SQLITE_ERROR;	
       
  1602 		}
       
  1603 	return SQLITE_OK;
       
  1604 	}
       
  1605 
       
  1606 /**
       
  1607 SQLite OS porting layer API.
       
  1608 
       
  1609 Generates a set of random numbers and stores them in the aBuf output parameter.
       
  1610 
       
  1611 @param aBufLen The output buffer length.
       
  1612 @param aBuf Output buffer for the generated random numbers. The allocated buffer length must be at least aBufLen bytes.
       
  1613 
       
  1614 @return The length of the used part of the output buffer.
       
  1615 */
       
  1616 /* static */ int TVfs::Randomness(sqlite3_vfs* aVfs, int aBufLen, char* aBuf)
       
  1617 	{
       
  1618 	SQLUTRACE_PROFILER(aVfs);
       
  1619 	const TInt KRandIterations = aBufLen / sizeof(int);
       
  1620 	for(TInt i=0;i<KRandIterations;++i)
       
  1621 		{
       
  1622 		TInt val = Math::Rand(Seed());
       
  1623 		Mem::Copy(&aBuf[i * sizeof(int)], &val, sizeof(val));
       
  1624 		}
       
  1625 	return KRandIterations * sizeof(int);
       
  1626 	}
       
  1627 
       
  1628 /**
       
  1629 SQLite OS porting layer API.
       
  1630 
       
  1631 Sleeps for aMicrosec microseconds.
       
  1632 
       
  1633 @param aMicrosec The sleep interval in microseconds.
       
  1634 
       
  1635 @return The aMicrosec value.
       
  1636 */
       
  1637 /* static */ int TVfs::Sleep(sqlite3_vfs* aVfs, int aMicrosec)
       
  1638 	{
       
  1639 	SQLUTRACE_PROFILER(aVfs);
       
  1640 	User::AfterHighRes(TTimeIntervalMicroSeconds32(aMicrosec));
       
  1641 	return aMicrosec;
       
  1642 	}
       
  1643 
       
  1644 /**
       
  1645 SQLite OS porting layer API.
       
  1646 
       
  1647 Retrieves the current date and time.
       
  1648 
       
  1649 @param aNow Output parameter, where the data and time value will be stored.
       
  1650 			SQLite processes all times and dates as Julian Day numbers and
       
  1651 			aNow parameter will contain the julian date and time.
       
  1652 
       
  1653 @return 0.
       
  1654 */
       
  1655 /* static */ int TVfs::CurrentTime(sqlite3_vfs* aVfs, double* aNow)
       
  1656 	{
       
  1657 	SQLUTRACE_PROFILER(aVfs);
       
  1658 	TTime now;
       
  1659 	now.UniversalTime();
       
  1660 	TDateTime date = now.DateTime();
       
  1661 	TInt year = date.Year();
       
  1662 	TInt month = date.Month() + 1;
       
  1663 	TInt day = date.Day() + 1;
       
  1664 	
       
  1665     //Calculate the Julian days
       
  1666 	TInt jd = day - 32076 +
       
  1667 	    1461*(year + 4800 + (month - 14)/12)/4 +
       
  1668 	    367*(month - 2 - (month - 14)/12*12)/12 -
       
  1669 	    3*((year + 4900 + (month - 14)/12)/100)/4;
       
  1670           	
       
  1671 	*aNow = jd;
       
  1672 
       
  1673     // Add the fractional hours, mins and seconds
       
  1674 	*aNow += (date.Hour() + 12.0) / 24.0;
       
  1675 	*aNow += date.Minute() / 1440.0;
       
  1676 	*aNow += date.Second() / 86400.0;
       
  1677 	
       
  1678 #ifdef SQLITE_TEST
       
  1679 	if( sqlite3_current_time )
       
  1680 		{
       
  1681     	*aNow = sqlite3_current_time / 86400.0 + 2440587.5;
       
  1682 		}
       
  1683 #endif
       
  1684 	return 0;
       
  1685 	}
       
  1686 
       
  1687 /**
       
  1688 SQLite OS porting layer API.
       
  1689 
       
  1690 Retrieves a text description of the last OS error.
       
  1691 Note: the method has a default "no-op" implementation at the moment. 
       
  1692 
       
  1693 @return 0.
       
  1694 */
       
  1695 /* static */int TVfs::GetLastError(sqlite3_vfs* aVfs, int /*aBufLen*/, char* /*aBuf*/)
       
  1696 	{
       
  1697 	SQLUTRACE_PROFILER(aVfs);
       
  1698 	return 0;
       
  1699 	}
       
  1700 
       
  1701 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
  1702 
       
  1703 #endif//SQLITE_OS_SYMBIAN