os/persistentdata/persistentstorage/sqlite3api/OsLayer/os_symbian_mt.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/persistentdata/persistentstorage/sqlite3api/OsLayer/os_symbian_mt.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,1825 @@
     1.4 +// Copyright (c) 2005-2010 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// os_symbian.cpp
    1.18 +// The Symbian OS porting layer - multi-threaded implementation.
    1.19 +// SQLite never accesses the file system and the OS services directly.
    1.20 +// SQLite uses for that sqlite3_vfs and sqlite3_file objects.
    1.21 +// sqlite3_vfs and sqlite3_file functionality is implemented in this file - 
    1.22 +// TVfs and TFileIo classes.
    1.23 +// 
    1.24 +//
    1.25 +
    1.26 +/**
    1.27 + @file
    1.28 + @see TVfs
    1.29 + @see TFileIo
    1.30 +*/
    1.31 +
    1.32 +#ifdef  SQLITE_OS_SYMBIAN
    1.33 +
    1.34 +extern "C" 
    1.35 +	{
    1.36 +	#include "sqliteInt.h"
    1.37 +	#include "os.h"
    1.38 +	#include "os_common.h"
    1.39 +	}
    1.40 +#include <e32math.h>
    1.41 +#include "os_symbian.h"
    1.42 +#include "SqliteUtil.h"
    1.43 +#include "OstTraceDefinitions.h"
    1.44 +#ifdef OST_TRACE_COMPILER_IN_USE
    1.45 +#include "os_symbian_mtTraces.h"
    1.46 +#endif
    1.47 +#include "SqliteTraceDef.h"
    1.48 +
    1.49 +//Bit-mask constant. If xOpen()'s "aFlag" parameter contains one of these bits set, then the the file top be
    1.50 +//opened or created is a journal file.
    1.51 +const TUint KJournalFileTypeBitMask = SQLITE_OPEN_MAIN_JOURNAL | SQLITE_OPEN_TEMP_JOURNAL | SQLITE_OPEN_SUBJOURNAL | SQLITE_OPEN_MASTER_JOURNAL; 
    1.52 +
    1.53 +#ifdef SQLITE_TEST
    1.54 +
    1.55 +//Count the number of fullsyncs and normal syncs.  This is used to test
    1.56 +//that syncs and fullsyncs are occuring at the right times.
    1.57 +extern "C" int sqlite3_sync_count = 0;
    1.58 +extern "C" int sqlite3_fullsync_count = 0;
    1.59 +
    1.60 +//The following variable, if set to a non-zero value, becomes the result
    1.61 +//returned from sqlite3OsCurrentTime().  This is used for testing.
    1.62 +extern "C" int sqlite3_current_time = 0;
    1.63 +
    1.64 +#endif//SQLITE_TEST
    1.65 +
    1.66 +_LIT(KCwd, ".\\");
    1.67 +
    1.68 +//Used for the random numbers generation
    1.69 +static inline TInt64& Seed()
    1.70 +	{
    1.71 +	static TInt64 seed = 0;
    1.72 +	if(seed == 0)
    1.73 +		{
    1.74 +		TTime now;
    1.75 +		now.UniversalTime();
    1.76 +		seed = now.Int64();
    1.77 +		}
    1.78 +	return seed;
    1.79 +	}
    1.80 +
    1.81 +/**
    1.82 +Os2SqliteErr() is called at the end of many of the interface functions of the OS porting layer (wherever it is appropriate - 
    1.83 +TFileIo and TVfs interfaces). The purpose of this function is to identify the "out of memory" and "disk is full" errors
    1.84 +reported by the used Symbian OS APIs (aOsErr parameter) and report them to SQLite as SQLITE_FULL and SQLITE_NOMEM errors.
    1.85 +The KErrEof error (TFileIo::Read() can return KErrEof) is reported to SQLite as SQLITE_IOERR_SHORT_READ. The rest of failures
    1.86 +are reported as the error specified in aDefaultErr parameter.
    1.87 + 
    1.88 +@param aOsErr      Symbian OS error
    1.89 +@param aDefaultErr The default SQLite error that should be used if the aOsErr parameter is not one of:
    1.90 +                     KErrNone, KErrEof, KErrNoMemory, KErrDiskFull
    1.91 +@return SQLITE_OK,               The OS porting layer function call has completed successfully, 
    1.92 +          SQLITE_IOERR_SHORT_READ, The amount of the data read is less than the requested amount,
    1.93 +          SQLITE_IOERR_NOMEM,      Out of memory,
    1.94 +          SQLITE_FULL,             The disk is full,
    1.95 +          aDefaultErr,             The rest of failures will be reported as aDefaultErr.
    1.96 +*/
    1.97 +static TInt Os2SqliteErr(TInt aOsErr, TInt aDefaultErr)
    1.98 +	{
    1.99 +	switch(aOsErr)
   1.100 +		{
   1.101 +		case KErrNone:
   1.102 +			return SQLITE_OK;	
   1.103 +		case KErrEof:
   1.104 +			return SQLITE_IOERR_SHORT_READ;
   1.105 +		case KErrNoMemory:
   1.106 +			return SQLITE_IOERR_NOMEM;
   1.107 +		case KErrDiskFull:
   1.108 +			return SQLITE_FULL;
   1.109 +		default:
   1.110 +#ifdef _DEBUG		
   1.111 +			SQLITE_TRACE_OS(OstTrace1(TRACE_INTERNALS, OS2SQLITEERR, "OS;0;Os2SqliteErr;aOsErr=%d", aOsErr));
   1.112 +#endif			
   1.113 +			break;
   1.114 +		}
   1.115 +	return aDefaultErr;
   1.116 +	}
   1.117 +	
   1.118 +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.119 +//////////////////////////  TStaticFs  /////////////////////////////////////////////////////////////////////////////////////////
   1.120 +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.121 +
   1.122 +/**
   1.123 +Connects the file session used by the SQLite OS porting layer.
   1.124 +Single RFs instance per process is used.
   1.125 +
   1.126 +@return KErrNone The operation was completed successfully,
   1.127 +                 System-wide error code if the operation has failed.
   1.128 +*/
   1.129 +TInt TStaticFs::Connect()
   1.130 +	{
   1.131 +	TInt err = iFs.Connect();
   1.132 +	if(err == KErrNone)	
   1.133 +		{
   1.134 +		err = iFs.ShareAuto();	
   1.135 +		}
   1.136 +	if(err != KErrNone)
   1.137 +		{
   1.138 +		iFs.Close();	
   1.139 +		}
   1.140 +	SQLITE_TRACE_OS(OstTraceExt2(TRACE_INTERNALS, TSTATICFS_CONNECT, "OS;0;TStaticFs::Connect;iFs.Handle()=0x%X;err=%d", iFs.Handle(), err));
   1.141 +	return err;
   1.142 +	}
   1.143 +
   1.144 +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.145 +//////////////////////////  sqlite3_mutex  /////////////////////////////////////////////////////////////////////////////////////            
   1.146 +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.147 +
   1.148 +/**
   1.149 +Initializes sqlite3_mutex data members with their default values.
   1.150 +*/
   1.151 +sqlite3_mutex::sqlite3_mutex() :
   1.152 +	iRefCount(0),
   1.153 +	iOwnerThreadId(KMaxTUint64)
   1.154 +	{
   1.155 +	SQLITE_TRACE_OS(OstTrace1(TRACE_INTERNALS, SQLITE3_MUTEX_SQLITE3_MUTEX, "OS;0x%X;sqlite3_mutex::sqlite3_mutex", (TUint)this));
   1.156 +	}
   1.157 +
   1.158 +/**
   1.159 +Closes the mutex handle.
   1.160 +*/
   1.161 +sqlite3_mutex::~sqlite3_mutex()
   1.162 +	{
   1.163 +	SQLITE_TRACE_OS(OstTrace1(TRACE_INTERNALS, SQLITE3_MUTEX_SQLITE3_MUTEX2, "OS;0x%X;sqlite3_mutex::~sqlite3_mutex", (TUint)this));
   1.164 +	iMutex.Close();
   1.165 +	}
   1.166 +
   1.167 +/**
   1.168 +Gives the calling thread an exclusive access to the SQLite resources (global variables, file handles, buffers, cache, etc.).
   1.169 +The calling thread becomes a mutex owner.
   1.170 +If the mutex is already locked by another thread, the calling thread will block until the other thread releases the mutex.
   1.171 +The method can be called by the mutex owning thread more than once, even if the mutex is already entered.
   1.172 +
   1.173 +@panic SqliteMt 23 Negative mutex lock counter (in debug builds only)
   1.174 +*/
   1.175 +void sqlite3_mutex::Enter()
   1.176 +	{
   1.177 +    __ASSERT_DEBUG(iRefCount >= 0, __SQLITEPANIC(ESqliteOsPanicMutexLockCounter));
   1.178 +	iMutex.Wait();
   1.179 +	RThread currThread;
   1.180 +	iOwnerThreadId = currThread.Id();
   1.181 +	++iRefCount;
   1.182 +	}
   1.183 +	
   1.184 +/**
   1.185 +Unlocks the mutex. If sqlite3_mutex::Enter() was called more than once by the owning thread, then the number of 
   1.186 +sqlite3_mutex::Leave() calls must eventually match the number of sqlite3_mutex::Enter() calls.
   1.187 +If there are thread(s) blocked on sqlite3_mutex::Enter(), after the mutex gets unlocked one of the waiting threads
   1.188 +will be able to lock the mutex and get an exclusive access to the guarded resources.
   1.189 +
   1.190 +@panic SqliteMt 23 Negative mutex lock counter (in debug builds only)
   1.191 +@panic SqliteMt 24 The mutex has been entered (locked) by a different thread than the current one (in debug builds only)
   1.192 +*/
   1.193 +void sqlite3_mutex::Leave()
   1.194 +	{
   1.195 +	__ASSERT_DEBUG(iRefCount > 0, __SQLITEPANIC(ESqliteOsPanicMutexLockCounter));
   1.196 +#ifdef _DEBUG
   1.197 +	RThread currThread;	
   1.198 +	__ASSERT_DEBUG(iOwnerThreadId == currThread.Id(), __SQLITEPANIC(ESqliteOsPanicMutexOwner));
   1.199 +#endif
   1.200 +	--iRefCount;
   1.201 +	iMutex.Signal();
   1.202 +	}
   1.203 +
   1.204 +/**
   1.205 +Returns true if the mutex is already locked (entered).
   1.206 +
   1.207 +@return True if the mutex is locked, false otherwise
   1.208 +*/
   1.209 +TBool sqlite3_mutex::IsHeld() const
   1.210 +	{
   1.211 +	RThread currThread;
   1.212 +	return iRefCount > 0 && iOwnerThreadId == currThread.Id();
   1.213 +	}
   1.214 +
   1.215 +/**
   1.216 +Creates the mutex.
   1.217 +
   1.218 +@return KErrNone The operation was completed successfully,
   1.219 +                 System-wide error code if the operation has failed.
   1.220 +*/
   1.221 +TInt sqlite3_mutex::Create()
   1.222 +	{
   1.223 +	TInt err = iMutex.CreateLocal();
   1.224 +	SQLITE_TRACE_OS(OstTraceExt2(TRACE_INTERNALS, SQLITE3_MUTEX_CREATE, "OS;0x%X;sqlite3_mutex::Create;err=%d", (TUint)this, err));
   1.225 +	return err;
   1.226 +	}
   1.227 +
   1.228 +/**
   1.229 +Creates new CRecursiveMutex object.
   1.230 +
   1.231 +@return A pointer to the created CRecursiveMutex object or NULL if the operation has failed.
   1.232 +*/
   1.233 +CRecursiveMutex* CRecursiveMutex::New()
   1.234 +	{
   1.235 +	CRecursiveMutex* self = new CRecursiveMutex;
   1.236 +	if(self)
   1.237 +		{
   1.238 +		if(self->Create() != KErrNone)
   1.239 +			{
   1.240 +			delete self;	
   1.241 +			self = NULL;
   1.242 +			}
   1.243 +		}
   1.244 +	SQLITE_TRACE_OS(OstTrace1(TRACE_INTERNALS, CRECURSIVEMUTEX_NEWL, "OS;0x%X;CRecursiveMutex::New", (TUint)self));
   1.245 +	return self;
   1.246 +	}
   1.247 +
   1.248 +CRecursiveMutex::~CRecursiveMutex()
   1.249 +	{
   1.250 +	}
   1.251 +
   1.252 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.253 +//////////////////////////  TMutexApi  ////////////////////////////////////////////////////////////////////////////////////////
   1.254 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.255 +
   1.256 +/**
   1.257 +Initializes the mutex system.
   1.258 +No-op function.
   1.259 +
   1.260 +@return SQLITE_OK
   1.261 +*/
   1.262 +int TMutexApi::Init()
   1.263 +	{
   1.264 +	return SQLITE_OK;
   1.265 +	}
   1.266 +	
   1.267 +/**
   1.268 +Finalizes the mutex system.
   1.269 +No-op function.
   1.270 +
   1.271 +@return SQLITE_OK
   1.272 +*/
   1.273 +int TMutexApi::End()
   1.274 +	{
   1.275 +	return SQLITE_OK;
   1.276 +	}
   1.277 +	
   1.278 +/**
   1.279 +Creates a new mutex.
   1.280 +If the request is for a static mutex, a pointer to already created static mutex will be returned.
   1.281 +
   1.282 +@param aType  The mutex type: static, fast, recursive
   1.283 +@return A pointer to the created mutex or NULL if the operation has failed
   1.284 +*/
   1.285 +sqlite3_mutex* TMutexApi::Alloc(int aType)
   1.286 +	{
   1.287 +	sqlite3_mutex* mutex = NULL;
   1.288 +	switch(aType)
   1.289 +		{
   1.290 +		case SQLITE_MUTEX_FAST:
   1.291 +		case SQLITE_MUTEX_RECURSIVE:
   1.292 +			mutex = CRecursiveMutex::New();
   1.293 +			break;
   1.294 +		default:
   1.295 +			mutex = ::StaticMutex(aType - 2);//"aType - 2" because the first SQLITE_MUTEX_STATIC_<type> mutex definition 
   1.296 +			//value is 2 (SQLITE_MUTEX_FAST is 0, SQLITE_MUTEX_RECURSIVE is 1). 
   1.297 +			break;	
   1.298 +		}
   1.299 +	SQLITE_TRACE_OS(OstTraceExt2(TRACE_INTERNALS, TMUTEXAPI_ALLOC, "OS;0;TMutexApi::Alloc;aType=%d;mutex=0x%X", aType, (TUint)mutex));
   1.300 +	return mutex;
   1.301 +	}
   1.302 +	
   1.303 +/**
   1.304 +Destroys a mutex, created previously by a call to TMutexApi::Alloc().
   1.305 +@param aMutex Pointer to the mutex object that has to be destroyed
   1.306 +*/
   1.307 +void TMutexApi::Free(sqlite3_mutex* aMutex)
   1.308 +	{
   1.309 +	SQLITE_TRACE_OS(OstTrace1(TRACE_INTERNALS, TMUTEXAPI_FREE, "OS;0;TMutexApi::Free;mutex=0x%X", (TUint)aMutex));
   1.310 +	delete aMutex;
   1.311 +	}
   1.312 +	
   1.313 +/**
   1.314 +Locks the mutex.
   1.315 +See sqlite3_mutex::Enter() for more details.
   1.316 +
   1.317 +@param aMutex Pointer to the mutex object
   1.318 +
   1.319 +@see sqlite3_mutex::Enter()
   1.320 +*/
   1.321 +void TMutexApi::Enter(sqlite3_mutex* aMutex)
   1.322 +	{
   1.323 +	aMutex->Enter();
   1.324 +	}
   1.325 +	
   1.326 +/**
   1.327 +No-op. Always returns SQLITE_BUSY.
   1.328 +
   1.329 +@return SQLITE_BUSY
   1.330 +*/
   1.331 +int TMutexApi::Try(sqlite3_mutex*)
   1.332 +	{
   1.333 +	return SQLITE_BUSY;
   1.334 +	}
   1.335 +	
   1.336 +/**
   1.337 +Unlocks the mutex.
   1.338 +See sqlite3_mutex::Leave() for more details.
   1.339 +
   1.340 +@param aMutex Pointer to the mutex object
   1.341 +
   1.342 +@see sqlite3_mutex::Leave()
   1.343 +*/
   1.344 +void TMutexApi::Leave(sqlite3_mutex* aMutex)
   1.345 +	{
   1.346 +	aMutex->Leave();
   1.347 +	}
   1.348 +	
   1.349 +/**
   1.350 +Checks whether the mutex is locked or not.
   1.351 +See sqlite3_mutex::IsHeld() for more details.
   1.352 +
   1.353 +@param aMutex Pointer to the mutex object
   1.354 +
   1.355 +@return True if the mutex is locked, false otherwise
   1.356 +
   1.357 +@see sqlite3_mutex::IsHeld()
   1.358 +*/
   1.359 +int TMutexApi::Held(sqlite3_mutex* aMutex)
   1.360 +	{
   1.361 +	return aMutex->IsHeld();
   1.362 +	}
   1.363 +	
   1.364 +/**
   1.365 +Checks whether the mutex is locked or not.
   1.366 +See sqlite3_mutex::IsHeld() for more details.
   1.367 +
   1.368 +@param aMutex Pointer to the mutex object
   1.369 +
   1.370 +@return False if the mutex is locked, true otherwise
   1.371 +
   1.372 +@see sqlite3_mutex::IsHeld()
   1.373 +*/
   1.374 +int TMutexApi::Notheld(sqlite3_mutex* aMutex)
   1.375 +	{
   1.376 +	return !aMutex->IsHeld();
   1.377 +	}
   1.378 +
   1.379 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.380 +///////////////////////////////////       SQLite init/release functions     ///////////////////////////////////////////////////
   1.381 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.382 +
   1.383 +/**
   1.384 +Initializes the OS porting layer global data.
   1.385 +*/
   1.386 +extern "C" SQLITE_EXPORT int sqlite3_os_init(void)
   1.387 +	{
   1.388 +	TInt err = sqlite3_vfs_register(VfsApi(), 1);
   1.389 +	SQLITE_TRACE_OS(OstTrace1(TRACE_INTERNALS, SQLITE3_OS_INIT, "OS;0;sqlite3_os_init;err=%d", err));
   1.390 +	return err;
   1.391 +	}
   1.392 +
   1.393 +/**
   1.394 +Destroys the OS porting layer global data.
   1.395 +*/
   1.396 +extern "C" SQLITE_EXPORT int sqlite3_os_end(void)
   1.397 +	{
   1.398 +	TInt err = sqlite3_vfs_unregister(VfsApi());
   1.399 +	SQLITE_TRACE_OS(OstTrace1(TRACE_INTERNALS, SQLITE3_OS_END, "OS;0;sqlite3_os_end;err=%d", err));
   1.400 +	return err;
   1.401 +	}
   1.402 +
   1.403 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.404 +//////////////////////////  TheFileIoApi  /////////////////////////////////////////////////////////////////////////////////////
   1.405 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.406 +
   1.407 +/**
   1.408 +Single sqlite3_io_methods instance, which data members (function pointers) are initialized with the addresses of
   1.409 +TFileIo members. 
   1.410 +TheFileIoApi is used by SQLite for performing OS independent file I/O.
   1.411 +
   1.412 +@see TFileIo
   1.413 +@see TVfs
   1.414 +
   1.415 +@internalComponent
   1.416 +*/
   1.417 +const static sqlite3_io_methods TheFileIoApi = 
   1.418 +	{
   1.419 +	1,						//Version
   1.420 +	&TFileIo::Close,
   1.421 +	&TFileIo::Read,
   1.422 +	&TFileIo::Write,
   1.423 +	&TFileIo::Truncate,
   1.424 +	&TFileIo::Sync,
   1.425 +	&TFileIo::FileSize,
   1.426 +	&TFileIo::Lock,
   1.427 +	&TFileIo::Unlock,
   1.428 +	&TFileIo::CheckReservedLock,
   1.429 +	&TFileIo::FileControl,
   1.430 +	&TFileIo::SectorSize,
   1.431 +	&TFileIo::DeviceCharacteristics
   1.432 +	};
   1.433 +	
   1.434 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.435 +//////////////////////////  TheMutexMethods  //////////////////////////////////////////////////////////////////////////////////
   1.436 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.437 +
   1.438 +/**
   1.439 +sqlite3_mutex_methods is a structure declared in sqlite3.h header file. 
   1.440 +sqlite3_mutex_methods defines the mutex interface used by SQLite and implemented by the OS porting layer.
   1.441 +*/
   1.442 +static sqlite3_mutex_methods TheMutexMethods =
   1.443 +	{
   1.444 +	&TMutexApi::Init,
   1.445 +	&TMutexApi::End,
   1.446 +	&TMutexApi::Alloc,
   1.447 +	&TMutexApi::Free,
   1.448 +	&TMutexApi::Enter,
   1.449 +	&TMutexApi::Try,
   1.450 +	&TMutexApi::Leave,
   1.451 +	&TMutexApi::Held,
   1.452 +	&TMutexApi::Notheld
   1.453 +	};
   1.454 +
   1.455 +extern "C" sqlite3_mutex_methods* sqlite3DefaultMutex(void)
   1.456 +	{
   1.457 +	return &TheMutexMethods;
   1.458 +	};
   1.459 +
   1.460 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.461 +//////////////////          UTF16<-->UTF8, conversion functions    ////////////////////////////////////////////////////////////
   1.462 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.463 +
   1.464 +/**
   1.465 +The function converts aFileName to UTF16 encoded file name, and stores the UTF16 encoded file name
   1.466 +to the place pointed by aFileNameDestBuf argument.
   1.467 +If the UTF16 conversion of the file name failed because the file name is too long or NULL, 
   1.468 +the function returns EFalse. 
   1.469 +
   1.470 +@param aFileName Expected to point to UTF8 encoded, zero terminated string.
   1.471 +				 Max allowed aFileName length is KMaxFileName (excluding terminating 0 character).
   1.472 +@param aFileNameDestBuf Output parameter. Will hold UTF16, non-zero-terminated string.
   1.473 +						The max length must be at least KMaxFileName characters.
   1.474 +                         
   1.475 +@return True if the conversion has been completed successfully						 
   1.476 +*/
   1.477 +static TBool ConvertToUnicode(const char *aFileName, TDes& aFileNameDestBuf)
   1.478 +	{
   1.479 +	if(aFileName)
   1.480 +		{
   1.481 +		wchar_t* dest = reinterpret_cast <wchar_t*> (const_cast <TUint16*> (aFileNameDestBuf.Ptr()));
   1.482 +		TInt len = mbstowcs(dest, aFileName, KMaxFileName);
   1.483 +		//Check the file name length. If it is longer than KMaxFileName characters, then the file name is not valid.
   1.484 +		if(len > 0 && len <= KMaxFileName)
   1.485 +			{
   1.486 +			aFileNameDestBuf.SetLength(len);
   1.487 +			return ETrue;
   1.488 +			}
   1.489 +		}
   1.490 +	return EFalse;
   1.491 +	}
   1.492 +
   1.493 +/**
   1.494 +The function converts aFileName to UTF8 encoded file name, and stores the UTF8 encoded file name
   1.495 +to the place pointed by aFileNameDestBuf argument.
   1.496 +If the UTF8 conversion of the file name failed because the file name is too long or NULL, 
   1.497 +the function returns EFalse. 
   1.498 +
   1.499 +@param aFileName Expected to point to UTF16 encoded, zero terminated string.
   1.500 +				 Max allowed aFileName length is KMaxFileName (excluding terminating 0 character).
   1.501 +@param aFileNameDestBuf Output parameter. Will hold UTF8, non-zero-terminated string.
   1.502 +						The max length must be at least KMaxFileName characters.
   1.503 +                         
   1.504 +@return True if the conversion has been completed successfully						 
   1.505 +*/
   1.506 +static TBool ConvertFromUnicode(const TDesC& aFileName, TDes8& aFileNameDestBuf)
   1.507 +	{
   1.508 +	char* dest = reinterpret_cast <char*> (const_cast <TUint8*> (aFileNameDestBuf.Ptr()));
   1.509 +	const wchar_t* src = reinterpret_cast <const wchar_t*> (aFileName.Ptr());
   1.510 +	TInt len = wcstombs(dest, src, KMaxFileName);
   1.511 +	//Check the file name length. If it is longer than KMaxFileName characters, then the file name is not valid.
   1.512 +	if(len > 0 && len <= KMaxFileName)
   1.513 +		{
   1.514 +		aFileNameDestBuf.SetLength(len);
   1.515 +		return ETrue;
   1.516 +		}
   1.517 +	return EFalse;
   1.518 +	}
   1.519 +
   1.520 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.521 +/////////////////////       TDbFile class definition    ///////////////////////////////////////////////////////////////////////
   1.522 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.523 +
   1.524 +const TInt KFileBufSize = 8 * 1024;	
   1.525 +
   1.526 +/**
   1.527 +Initializes TDbFile data members with their default values.
   1.528 +*/
   1.529 +inline TDbFile::TDbFile() :
   1.530 +	iFileBuf(KFileBufSize),
   1.531 +	iFullName(NULL),
   1.532 +	iSharedLockByte(0),
   1.533 +	iLockType(SQLITE_LOCK_NONE),
   1.534 +	iReadOnly(EFalse),
   1.535 +	iSectorSize(0),
   1.536 +	iDeviceCharacteristics(-1)
   1.537 +	{
   1.538 +	pMethods = 0;
   1.539 +	SQLITE_TRACE_OS(OstTrace1(TRACE_INTERNALS, TDBFILE_TDBFILE, "OS;0x%X;TDbFile::TDbFile", (TUint)this));
   1.540 +	}
   1.541 +
   1.542 +/**
   1.543 +Casts the passed sqlite3_file pointer to a reference to the derived class - TDbFile&.
   1.544 +All sqlite3_file pointers passed to TFileIo methods are actually pointers to TDbFile instances. 
   1.545 +So the cast is safe.
   1.546 +
   1.547 +@param aDbFile A pointer to a sqlite3_file instance
   1.548 +
   1.549 +@return A TDbFile reference. 
   1.550 +@see TFileIo
   1.551 +@see TVfs
   1.552 +@see TDbFile
   1.553 +
   1.554 +@panic Sqlite 20 In _DEBUG mode if aDbFile is NULL.
   1.555 +
   1.556 +@internalComponent
   1.557 +*/
   1.558 +static inline TDbFile& DbFile(sqlite3_file* aDbFile)
   1.559 +	{
   1.560 +	__ASSERT_DEBUG(aDbFile != 0, __SQLITEPANIC2(ESqliteOsPanicNullDbFilePtr));
   1.561 +	return *(static_cast <TDbFile*> (aDbFile));
   1.562 +	}
   1.563 +
   1.564 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.565 +/////////////////////       TFileIo class definition    ///////////////////////////////////////////////////////////////////////
   1.566 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.567 +
   1.568 +/**
   1.569 +SQLite OS porting layer API.
   1.570 +
   1.571 +Closes the file referred by aDbFile parameter.
   1.572 +If aDbFile.iFullName data member is not NULL, then the file will be deleted.
   1.573 +
   1.574 +@param aDbFile A pointer to a TDbFile instance, than contains the file handle to be closed.
   1.575 +
   1.576 +@return SQLITE_OK
   1.577 +
   1.578 +@see TDbFile
   1.579 +*/
   1.580 +/* static */ int TFileIo::Close(sqlite3_file* aDbFile)
   1.581 +	{
   1.582 +	TDbFile& dbFile = ::DbFile(aDbFile);
   1.583 +	SQLITE_TRACE_OS(OstTrace1(TRACE_INTERNALS, TFILEIO_CLOSE1, "OS;0x%X;TFileIo::Close", (TUint)&dbFile));
   1.584 +	dbFile.iFileBuf.Close();	
   1.585 +	if(dbFile.iFullName)
   1.586 +        {//"iFullName" will not be NULL only when TVfs::Open() is called with SQLITE_OPEN_DELETEONCLOSE flag.
   1.587 +         //That means - SQlite expects the file to be deleted after the file close operation. 
   1.588 +		__SQLITETRACE_OSEXPR(TInt err = ) TStaticFs::Fs().Delete(*dbFile.iFullName);
   1.589 +		SQLITE_TRACE_OS(OstTraceExt3(TRACE_INTERNALS, TFILEIO_CLOSE2, "OS;0x%X;TFileIo::Close;delete fileName=%S;err=%d", (TUint)&dbFile, __SQLITEPRNSTR(*dbFile.iFullName), err));
   1.590 +		delete dbFile.iFullName;
   1.591 +		dbFile.iFullName = NULL;
   1.592 +		}
   1.593 +    OpenCounter(-1);
   1.594 +	return SQLITE_OK;
   1.595 +	}
   1.596 +
   1.597 +/**
   1.598 +SQLite OS porting layer API.
   1.599 +
   1.600 +Reads from the file referred by the aDbFile parameter.
   1.601 +
   1.602 +@param aDbFile A pointer to a TDbFile instance, that contains the file handle to be read from.
   1.603 +@param aBuf Output parameter. The data read from the file will be copied there.
   1.604 +			The buffer size must be at least aAmt bytes.
   1.605 +@param aAmt The amount of data to be read form the file.
   1.606 +@param aOffset The offset in the file where the read operation should start.
   1.607 +
   1.608 +@return SQLITE_FULL,       			The disk is full,
   1.609 +	    SQLITE_IOERR_SHORT_READ, 	The amount of the data read is less than aAmt,
   1.610 +	    SQLITE_IOERR_READ, 			File read error,
   1.611 +	    SQLITE_IOERR_NOMEM,			An out of memory condition has occured,
   1.612 +	    SQLITE_OK,					The operation has completed successfully.
   1.613 +	    
   1.614 +@see TDbFile
   1.615 +*/
   1.616 +/* static */ int TFileIo::Read(sqlite3_file* aDbFile, void* aBuf, int aAmt, sqlite3_int64 aOffset)
   1.617 +	{
   1.618 +	SimulateIOError(return SQLITE_IOERR_READ);
   1.619 +	TDbFile& dbFile = ::DbFile(aDbFile);
   1.620 +	SQLITE_TRACE_OS(OstTraceExt3(TRACE_INTERNALS, TFILEIO_READ_ENTRY, "OS-Entry;0x%X;TFileIo::Read;aAmt=%d;aOffset=%lld", (TUint)&dbFile, aAmt, aOffset));
   1.621 +	TPtr8 ptr((TUint8*)aBuf, 0, aAmt);
   1.622 +	TInt err = dbFile.iFileBuf.Read(aOffset, ptr);
   1.623 +	TInt cnt = ptr.Length();
   1.624 +	TInt sqliteErr = ::Os2SqliteErr(err, SQLITE_IOERR_READ);
   1.625 +	if(cnt != aAmt && (sqliteErr == SQLITE_OK || sqliteErr == SQLITE_IOERR_SHORT_READ))
   1.626 +		{
   1.627 +		Mem::FillZ(static_cast <TUint8*> (aBuf) + cnt, aAmt - cnt);
   1.628 +		sqliteErr = SQLITE_IOERR_SHORT_READ;
   1.629 +		}
   1.630 +	SQLITE_TRACE_OS(OstTraceExt4(TRACE_INTERNALS, TFILEIO_READ_EXIT, "OS-Exit;0x%X;TFileIo::Read;cnt=%d;err=%d;sqliteErr=%d", (TUint)&dbFile, cnt, err, sqliteErr));
   1.631 +	return sqliteErr;
   1.632 +	}
   1.633 +
   1.634 +/**
   1.635 +SQLite OS porting layer API.
   1.636 +
   1.637 +Writes to the file referred by the aDbFile parameter.
   1.638 +"Write beyond the end of the file" operations are allowed.
   1.639 +
   1.640 +@param aDbFile A pointer to a TDbFile instance, that contains the file handle to be written to.
   1.641 +@param aData The data to be written to the file. The buffer size must be at least aAmt bytes.
   1.642 +@param aAmt The amount of data to be written to the file.
   1.643 +@param aOffset The offset in the file where the write operation should start.
   1.644 +
   1.645 +@return SQLITE_IOERR_WRITE, the file write operation has failed or the file is read-only,
   1.646 +		SQLITE_FULL,       	The disk is full,
   1.647 +	    SQLITE_IOERR_NOMEM,	An out of memory condition has occured,
   1.648 +	    SQLITE_OK,			The operation has completed successfully.
   1.649 +	    
   1.650 +@see TDbFile
   1.651 +*/
   1.652 +/* static */ int TFileIo::Write(sqlite3_file* aDbFile, const void* aData, int aAmt, sqlite3_int64 aOffset)
   1.653 +	{
   1.654 +	SimulateIOError(return SQLITE_IOERR_WRITE);
   1.655 +	SimulateDiskfullError(return SQLITE_FULL);
   1.656 +	TDbFile& dbFile = ::DbFile(aDbFile);
   1.657 +	SQLITE_TRACE_OS(OstTraceExt3(TRACE_INTERNALS, TFILEIO_WRITE_ENTRY, "OS-Entry;0x%X;TFileIo::Write;aAmt=%d;aOffset=%lld", (TUint)&dbFile, aAmt, aOffset));
   1.658 +	TInt err = KErrAccessDenied;
   1.659 +	if(!dbFile.iReadOnly)
   1.660 +		{
   1.661 +		TPtrC8 ptr((const TUint8*)aData, aAmt);
   1.662 +		err = dbFile.iFileBuf.Write(aOffset, ptr);
   1.663 +		}
   1.664 +	TInt sqliteErr = ::Os2SqliteErr(err, SQLITE_IOERR_WRITE);
   1.665 +	SQLITE_TRACE_OS(OstTraceExt3(TRACE_INTERNALS, TFILEIO_WRITE_EXIT, "OS-Exit;0x%X;TFileIo::Write;err=%d;sqliteErr=%d", (TUint)&dbFile, err, sqliteErr));
   1.666 +	return sqliteErr;
   1.667 +	}
   1.668 +
   1.669 +/**
   1.670 +SQLite OS porting layer API.
   1.671 +
   1.672 +Truncates the file referred by the aDbFile parameter.
   1.673 +
   1.674 +@param aDbFile A pointer to a TDbFile instance, that contains the file handle.
   1.675 +@param aLength The new file size in bytes.
   1.676 +
   1.677 +@return SQLITE_IOERR_TRUNCATE, the file truncate operation has failed or the file is read-only,
   1.678 +		SQLITE_FULL,       	The disk is full,
   1.679 +	    					The file truncate operation has failed,
   1.680 +	    SQLITE_IOERR_NOMEM,	An out of memory condition has occured,
   1.681 +	    SQLITE_OK,			The operation has completed successfully.
   1.682 +	    
   1.683 +@see TDbFile
   1.684 +*/
   1.685 +/* static */ int TFileIo::Truncate(sqlite3_file* aDbFile, sqlite3_int64 aLength)
   1.686 +	{
   1.687 +	SimulateIOError(return SQLITE_IOERR_TRUNCATE);
   1.688 +	TDbFile& dbFile = ::DbFile(aDbFile);
   1.689 +	SQLITE_TRACE_OS(OstTraceExt2(TRACE_INTERNALS, TFILEIO_TRUNCATE_ENTRY, "OS-Entry;0x%X;TFileIo::Truncate;aLength=%lld", (TUint)&dbFile, aLength));
   1.690 +	TInt err = KErrAccessDenied;
   1.691 +	if(!dbFile.iReadOnly)
   1.692 +		{
   1.693 +		err = dbFile.iFileBuf.SetSize(aLength);
   1.694 +		}
   1.695 +	TInt sqliteErr = ::Os2SqliteErr(err, SQLITE_IOERR_TRUNCATE);
   1.696 +	SQLITE_TRACE_OS(OstTraceExt3(TRACE_INTERNALS, TFILEIO_TRUNCATE_EXIT, "OS-Exit;0x%X;TFileIo::Truncate;err=%d;sqliteErr=%d", (TUint)&dbFile, err, sqliteErr));
   1.697 +	return sqliteErr;
   1.698 +	}
   1.699 +
   1.700 +/**
   1.701 +SQLite OS porting layer API.
   1.702 +
   1.703 +Flushes the file referred by the aDbFile parameter.
   1.704 +
   1.705 +@param aDbFile A pointer to a TDbFile instance, that contains the file handle.
   1.706 +@param aFlags  This parameter is not used in the production builds. It may be one of 
   1.707 +			   SQLITE_SYNC_NORMAL or SQLITE_SYNC_FULL and is used only by the TCL test suite.
   1.708 +
   1.709 +@return SQLITE_IOERR_FSYNC,	This is a read-only file, or  the file flush operation has failed,
   1.710 +	    SQLITE_IOERR_NOMEM,	An out of memory condition has occured,
   1.711 +	    SQLITE_FULL,       		The disk is full,
   1.712 +   	    SQLITE_OK,			The operation has completed successfully.
   1.713 +
   1.714 +@see TDbFile
   1.715 +*/
   1.716 +/* static */int TFileIo::Sync(sqlite3_file* aDbFile, int aFlags)
   1.717 +	{
   1.718 +	SimulateIOError(return SQLITE_IOERR_FSYNC);
   1.719 +	TDbFile& dbFile = ::DbFile(aDbFile);
   1.720 +	SQLITE_TRACE_OS(OstTrace1(TRACE_INTERNALS, TFILEIO_SYNC_ENTRY, "OS-Entry;0x%X;TFileIo::Sync", (TUint)&dbFile));
   1.721 +#ifdef SQLITE_TEST
   1.722 +	if(aFlags & SQLITE_SYNC_FULL)
   1.723 +		{
   1.724 +		sqlite3_fullsync_count++;
   1.725 +		}
   1.726 +	sqlite3_sync_count++;
   1.727 +#else
   1.728 +	aFlags = aFlags;	
   1.729 +#endif
   1.730 +	TInt err = KErrAccessDenied;
   1.731 +	if(!dbFile.iReadOnly)
   1.732 +		{
   1.733 +		err = dbFile.iFileBuf.Flush();
   1.734 +		}
   1.735 +	TInt sqliteErr = ::Os2SqliteErr(err, SQLITE_IOERR_FSYNC);
   1.736 +	SQLITE_TRACE_OS(OstTraceExt3(TRACE_INTERNALS, TFILEIO_SYNC_EXIT, "OS-Exit;0x%X;TFileIo::Sync;err=%d;sqliteErr=%d", (TUint)&dbFile, err, sqliteErr));
   1.737 +	return sqliteErr;
   1.738 +	}
   1.739 +
   1.740 +/**
   1.741 +SQLite OS porting layer API.
   1.742 +
   1.743 +Returns the size of the file referred by the aDbFile parameter.
   1.744 +
   1.745 +@param aDbFile A pointer to a TDbFile instance, that contains the file handle.
   1.746 +@param aSize Output parameter. If the function completes successfully, the file size will be stored there.
   1.747 +
   1.748 +@return SQLITE_IOERR_FSTAT,		The file size operation has failed;
   1.749 +	    SQLITE_IOERR_NOMEM,		An out of memory condition has occured;
   1.750 +	    SQLITE_OK,				The operation has completed successfully.
   1.751 +	    
   1.752 +@see TDbFile
   1.753 +*/
   1.754 +/* static */ int TFileIo::FileSize(sqlite3_file* aDbFile, sqlite3_int64* aSize)
   1.755 +	{
   1.756 +	SimulateIOError(return SQLITE_IOERR_FSTAT);
   1.757 +	TDbFile& dbFile = ::DbFile(aDbFile);
   1.758 +	SQLITE_TRACE_OS(OstTrace1(TRACE_INTERNALS, TFILEIO_FILESIZE_ENTRY, "OS-Entry;0x%X;TFileIo::FileSize", (TUint)&dbFile));
   1.759 +	TInt err =  dbFile.iFileBuf.Size(*aSize);
   1.760 +	TInt sqliteErr = ::Os2SqliteErr(err, SQLITE_IOERR_FSTAT);
   1.761 +	SQLITE_TRACE_OS(OstTraceExt4(TRACE_INTERNALS, TFILEIO_FILESIZE_EXIT, "OS-Exit;0x%X;TFileIo::FileSize;aSize=%lld;err=%d;sqliteErr=%d", (TUint)&dbFile, *aSize, err, sqliteErr));
   1.762 +	return sqliteErr;
   1.763 +	}
   1.764 +
   1.765 +/**
   1.766 +This function is called when SQLite needs to obtain a read lock. This is done by generating a
   1.767 +random file position within the first page beyond the first Gb of the file and locking a single byte there.
   1.768 +There is a possible problem with that random file position, because the database file may be shared between multiple
   1.769 +connections. That increases the possibility of generating the same "random" file position by different connections to the
   1.770 +same file. In order to minimise that, TFileIo::GetReadLock() will generate up to 3 different file positions in a case of
   1.771 +a "lock byte" failure. 
   1.772 +The generated file position will be stored in TDbFile::iSharedLockByte data member and will be used later for the 
   1.773 +unlock operation.
   1.774 +
   1.775 +@param aDbFile The Os porting layer file handle
   1.776 +@return KErrNone 	The locking operation has completed successfully,
   1.777 +		KErrLocked	The 1 byte file area that begins from the generated file position is already locked,
   1.778 +				    Some other system-wide error codes in a case of  failure.
   1.779 +
   1.780 +@see TFileIo::UnlockReadLock()
   1.781 +*/
   1.782 +/* static */TInt TFileIo::GetReadLock(TDbFile& aDbFile)
   1.783 +	{
   1.784 +	const TInt KLockTryCount = 3;
   1.785 +	TInt rc = KErrLocked;
   1.786 +	for(TInt i=0;i<KLockTryCount;++i)
   1.787 +		{
   1.788 +	    TInt lock = Math::Rand(Seed());
   1.789 +	    //Explanation regarding how the file locking works can be found in os.h file, lines 279-335.
   1.790 +	    //Shortly, in order to read pages from the database the calling thread must obtain a shared lock.
   1.791 +	    //This is done locking a randomly chosen byte - iSharedLockByte.
   1.792 +	    //The calculation of iSharedLockByte is done in a way that:
   1.793 +	    // - All calculated iSharedLockByte fit on a single page, even if the page size is chosen to be the smallest one possible.
   1.794 +	    //       That's why the "% (SHARED_SIZE - 1)" is used in the calculation;
   1.795 +	    // - The locked byte cannot be used for storing data. That is the reason SHARED_FIRST to be set to be a position beyond the
   1.796 +	    //       1Gb boundary;
   1.797 +	    TInt sharedLockByte = (lock & 0x7fffffff) % (SHARED_SIZE - 1);
   1.798 +	    rc = aDbFile.iFileBuf.Lock(SHARED_FIRST + sharedLockByte, 1);
   1.799 +	    if(rc == KErrNone)
   1.800 +	    	{
   1.801 +	    	aDbFile.iSharedLockByte = sharedLockByte;
   1.802 +	    	break;
   1.803 +	    	}
   1.804 +		}
   1.805 +	SQLITE_TRACE_OS(OstTraceExt2(TRACE_INTERNALS, TFILEIO_GETREADLOCK, "OS;0x%X;TFileIo::GetReadLock;rc=%d", (TUint)&aDbFile, rc));
   1.806 +	return rc;
   1.807 +	}
   1.808 +
   1.809 +/**
   1.810 +Unlocks the file area previously locked by the GetReadLock() call.
   1.811 +The beginning of the locked area with length 1 byte is stored in TDbFile::iSharedLockByte data member.
   1.812 +
   1.813 +@param aDbFile The Os porting layer file handle
   1.814 +
   1.815 +@return KErrNone 	The locking operation has completed successfully,
   1.816 +				    Some other system-wide error codes in a case of  failure.
   1.817 +
   1.818 +@see TFileIo::GetReadLock()
   1.819 +*/
   1.820 +/* static */TInt TFileIo::UnlockReadLock(TDbFile& aDbFile)
   1.821 +	{
   1.822 +	TInt err = aDbFile.iFileBuf.UnLock(SHARED_FIRST + aDbFile.iSharedLockByte, 1);
   1.823 +	SQLITE_TRACE_OS(OstTraceExt2(TRACE_INTERNALS, TFILEIO_UNLOCKREADLOCK, "OS;0x%X;TFileIo::UnlockReadLock;err=%d", (TUint)&aDbFile, err));
   1.824 +	return err;
   1.825 +	}
   1.826 +
   1.827 +/**
   1.828 +SQLite OS porting layer API.
   1.829 +
   1.830 +Locks the file, referred by the aDbFile parameter, with the specified lock type.
   1.831 +The file lock type is stored for later use by the CheckReservedLock() call.
   1.832 +
   1.833 +Sometimes when requesting one lock state, additional lock states
   1.834 +are inserted in between.  The locking might fail on one of the later
   1.835 +transitions leaving the lock state different from what it started but
   1.836 +still short of its goal.  The following chart shows the allowed
   1.837 +transitions and the inserted intermediate states:
   1.838 +
   1.839 +SQLITE_LOCK_NONE		-> SQLITE_LOCK_SHARED
   1.840 +SQLITE_LOCK_SHARED 		-> SQLITE_LOCK_RESERVED
   1.841 +SQLITE_LOCK_SHARED 		-> (SQLITE_LOCK_PENDING) 	-> 	SQLITE_LOCK_EXCLUSIVE
   1.842 +SQLITE_LOCK_RESERVED 	-> (SQLITE_LOCK_PENDING) 	-> 	SQLITE_LOCK_EXCLUSIVE
   1.843 +SQLITE_LOCK_PENDING 	-> SQLITE_LOCK_EXCLUSIVE
   1.844 +
   1.845 +@param aDbFile A pointer to a TDbFile instance, that contains the file handle.
   1.846 +@param aLockType Lock type: SQLITE_LOCK_NONE, SQLITE_LOCK_SHARED, SQLITE_LOCK_RESERVED, SQLITE_LOCK_PENDING or
   1.847 +				 SQLITE_LOCK_EXCLUSIVE.
   1.848 +
   1.849 +@return SQLITE_IOERR_NOMEM,	An out of memory condition has occured;
   1.850 +	    SQLITE_BUSY,	    The requested lock cannot be obtained;
   1.851 +	    SQLITE_LOCK,		File locking error,
   1.852 +	    SQLITE_OK,			The operation has completed successfully.
   1.853 +
   1.854 +@see TFileIo::CheckReservedLock()
   1.855 +@see TFileIo::Unlock()
   1.856 +	    
   1.857 +@see TDbFile
   1.858 +*/
   1.859 +/* static */ int TFileIo::Lock(sqlite3_file* aDbFile, int aLockType)
   1.860 +	{
   1.861 +	TDbFile& dbFile = ::DbFile(aDbFile);
   1.862 +	//If there is already a lock of this type or more restrictive on the aDbFile, then - do nothing.
   1.863 +	if(dbFile.iLockType >= aLockType)
   1.864 +		{
   1.865 +		SQLITE_TRACE_OS(OstTraceExt3(TRACE_INTERNALS, TFILEIO_LOCK1, "OS;0x%X;TFileIo::Lock;dbFile.iLockType=%d;aLockType=%d", (TUint)&dbFile, dbFile.iLockType, aLockType));
   1.866 +		return SQLITE_OK;
   1.867 +		}
   1.868 +
   1.869 +	//The file flushing here must be done in order to get the file buffer object content (iFileBuf data member))
   1.870 +	//synchronised with the database file content (the database file content may get modified by a different connection
   1.871 +	//at the same time).
   1.872 +	if(aLockType == SQLITE_LOCK_SHARED && !dbFile.iReadOnly)
   1.873 +		{
   1.874 +		TInt err = dbFile.iFileBuf.Flush(ETrue);
   1.875 +		if(err != KErrNone)
   1.876 +			{
   1.877 +			SQLITE_TRACE_OS(OstTraceExt2(TRACE_INTERNALS, TFILEIO_LOCK2, "OS;0x%X;TFileIo::Lock;iFileBuf.Flush() failed, err=%d", (TUint)&dbFile, err));
   1.878 +			return ::Os2SqliteErr(err, SQLITE_IOERR_LOCK);
   1.879 +			}
   1.880 +		}
   1.881 +
   1.882 +	//Make sure the locking sequence is correct
   1.883 +	__ASSERT_DEBUG(dbFile.iLockType != SQLITE_LOCK_NONE || aLockType == SQLITE_LOCK_SHARED, __SQLITEPANIC2(ESqliteOsPanicInvalidLock));
   1.884 +	__ASSERT_DEBUG(aLockType != SQLITE_LOCK_PENDING, __SQLITEPANIC2(ESqliteOsPanicInvalidLock));
   1.885 +	__ASSERT_DEBUG(aLockType != SQLITE_LOCK_RESERVED || dbFile.iLockType == SQLITE_LOCK_SHARED, __SQLITEPANIC2(ESqliteOsPanicInvalidLock));
   1.886 +		
   1.887 +	TInt rc = SQLITE_OK;    //Return code from subroutines
   1.888 +	TBool locked = ETrue;   //Result of a file lock call (the default value means: "lock accuired")
   1.889 +  	TInt newLockType = -1;	//Set dbFile.iLockType to this value before exiting
   1.890 +	TBool gotPendingLock = EFalse;//True if we acquired a SQLITE_LOCK_PENDING lock this time
   1.891 +
   1.892 +	//Lock the SQLITE_LOCK_PENDING byte if we need to acquire a SQLITE_LOCK_PENDING lock or
   1.893 +	//SQLITE_LOCK_SHARED lock. If we are acquiring a SQLITE_LOCK_SHARED lock, the acquisition of
   1.894 +	//the SQLITE_LOCK_PENDING byte is temporary.
   1.895 +	newLockType = dbFile.iLockType;
   1.896 +	if(dbFile.iLockType == SQLITE_LOCK_NONE || (aLockType == SQLITE_LOCK_EXCLUSIVE && dbFile.iLockType == SQLITE_LOCK_RESERVED))
   1.897 +		{
   1.898 +		//Try 3 times to get the pending lock.  The pending lock might be
   1.899 +		//held by another reader process who will release it momentarily.
   1.900 +		const TInt KLockTryCnt = 3;
   1.901 +		locked = EFalse;
   1.902 +		for(TInt i=0;i<KLockTryCnt && !locked;++i)
   1.903 +			{
   1.904 +			TInt err = dbFile.iFileBuf.Lock(PENDING_BYTE, 1);
   1.905 +			if(err != KErrNone && err != KErrLocked) 
   1.906 +				{
   1.907 +				return ::Os2SqliteErr(err, SQLITE_IOERR_LOCK);
   1.908 +				}
   1.909 +			locked = (err == KErrNone);
   1.910 +   			if(!locked)
   1.911 +   				{
   1.912 +				const TInt KMs = 10;
   1.913 +				TVfs::Sleep(NULL, KMs * 1000);
   1.914 +   				}
   1.915 +			}
   1.916 +		gotPendingLock = locked;
   1.917 +		}
   1.918 +
   1.919 +	//Acquire a shared lock
   1.920 +	if(aLockType == SQLITE_LOCK_SHARED && locked)
   1.921 +		{
   1.922 +		__ASSERT_DEBUG(dbFile.iLockType == SQLITE_LOCK_NONE, __SQLITEPANIC2(ESqliteOsPanicInvalidLock));
   1.923 +		TInt err = TFileIo::GetReadLock(dbFile);
   1.924 +		if(err != KErrNone && err != KErrLocked) 
   1.925 +			{
   1.926 +			SQLITE_TRACE_OS(OstTraceExt2(TRACE_INTERNALS, TFILEIO_LOCK3, "OS;0x%X;TFileIo::Lock;TFileIo::GetReadLock() failed, err=%d", (TUint)&dbFile, err));
   1.927 +			return ::Os2SqliteErr(err, SQLITE_IOERR_LOCK);
   1.928 +			}
   1.929 +		locked = (err == KErrNone);
   1.930 +		if(locked)
   1.931 +			{
   1.932 +			newLockType = SQLITE_LOCK_SHARED;
   1.933 +			}
   1.934 +  		}
   1.935 +
   1.936 +	//Acquire a RESERVED lock
   1.937 +	if(aLockType == SQLITE_LOCK_RESERVED && locked)
   1.938 +		{
   1.939 +		__ASSERT_DEBUG(dbFile.iLockType == SQLITE_LOCK_SHARED, __SQLITEPANIC2(ESqliteOsPanicInvalidLock));
   1.940 +		TInt err = dbFile.iFileBuf.Lock(RESERVED_BYTE, 1); 
   1.941 +		if(err != KErrNone && err != KErrLocked) 
   1.942 +			{
   1.943 +			SQLITE_TRACE_OS(OstTraceExt2(TRACE_INTERNALS, TFILEIO_LOCK4, "OS;0x%X;TFileIo::Lock;iFileBuf.Lock() failed, err=%d", (TUint)&dbFile, err));
   1.944 +			return ::Os2SqliteErr(err, SQLITE_IOERR_LOCK);
   1.945 +			}
   1.946 +		locked = (err == KErrNone);
   1.947 +		if(locked)
   1.948 +			{
   1.949 +			newLockType = SQLITE_LOCK_RESERVED;
   1.950 +			}
   1.951 +		}
   1.952 +
   1.953 +	// Acquire a PENDING lock
   1.954 +	if(aLockType == SQLITE_LOCK_EXCLUSIVE && locked)
   1.955 +		{
   1.956 +		newLockType = SQLITE_LOCK_PENDING;
   1.957 +		gotPendingLock = EFalse;
   1.958 +		}
   1.959 +
   1.960 +	//Acquire an EXCLUSIVE lock
   1.961 +	if(aLockType == SQLITE_LOCK_EXCLUSIVE && locked)
   1.962 +		{
   1.963 +		__ASSERT_DEBUG(dbFile.iLockType >= SQLITE_LOCK_SHARED, __SQLITEPANIC2(ESqliteOsPanicInvalidLock));
   1.964 +		(void)TFileIo::UnlockReadLock(dbFile);
   1.965 +		TInt err = dbFile.iFileBuf.Lock(SHARED_FIRST, SHARED_SIZE);
   1.966 +		if(err != KErrNone && err != KErrLocked)
   1.967 +			{
   1.968 +			SQLITE_TRACE_OS(OstTraceExt2(TRACE_INTERNALS, TFILEIO_LOCK5, "OS;0x%X;TFileIo::Lock;iFileBuf.Lock()-2 failed, err=%d", (TUint)&dbFile, err));
   1.969 +			return ::Os2SqliteErr(err, SQLITE_IOERR_LOCK);
   1.970 +			}
   1.971 +		locked = (err == KErrNone);
   1.972 +		if(locked)
   1.973 +			{
   1.974 +			newLockType = SQLITE_LOCK_EXCLUSIVE;
   1.975 +			}
   1.976 +		}
   1.977 +
   1.978 +	// If we are holding a PENDING lock that ought to be released, then
   1.979 +	// release it now.
   1.980 +	if(gotPendingLock && aLockType == SQLITE_LOCK_SHARED)
   1.981 +		{
   1.982 +		__SQLITETRACE_OSEXPR(TInt err =) dbFile.iFileBuf.UnLock(PENDING_BYTE, 1);
   1.983 +		SQLITE_TRACE_OS(OstTraceExt2(TRACE_INTERNALS, TFILEIO_LOCK6, "OS;0x%X;TFileIo::Lock;iFileBuf.UnLock()=%d", (TUint)&dbFile, err));
   1.984 +  		}
   1.985 +
   1.986 +	// Update the state of the lock has held in the file descriptor then
   1.987 +	// return the appropriate result code.
   1.988 +	rc = locked ? SQLITE_OK : SQLITE_BUSY;
   1.989 +	dbFile.iLockType = newLockType;
   1.990 +	SQLITE_TRACE_OS(OstTraceExt3(TRACE_INTERNALS, TFILEIO_LOCK7, "OS;0x%X;TFileIo::Lock;rc=%d;newLockType=%d", (TUint)&dbFile, rc, newLockType));
   1.991 +	return rc;
   1.992 +	}
   1.993 +
   1.994 +/**
   1.995 +SQLite OS porting layer API.
   1.996 +
   1.997 +Lower the locking level on file descriptor id to locktype.  locktype
   1.998 +must be either SQLITE_LOCK_NONE or SQLITE_LOCK_SHARED.
   1.999 +
  1.1000 +If the locking level of the file descriptor is already at or below
  1.1001 +the requested locking level, this routine is a no-op.
  1.1002 +
  1.1003 +It is not possible for this routine to fail if the second argument
  1.1004 +is SQLITE_LOCK_NONE. If the second argument is SQLITE_LOCK_SHARED then this routine
  1.1005 +might return SQLITE_IOERR;
  1.1006 +
  1.1007 +@param aDbFile A pointer to a TDbFile instance, that contains the file handle.
  1.1008 +@param aLockType Lock type: SQLITE_LOCK_NONE, SQLITE_LOCK_SHARED, SQLITE_LOCK_RESERVED, SQLITE_LOCK_PENDING or
  1.1009 +				 SQLITE_LOCK_EXCLUSIVE.
  1.1010 +
  1.1011 +@return SQLITE_OK,	 		 The operation has completed successfully,
  1.1012 +	     SQLITE_IOERR_UNLOCK, The unlock operation has failed. 
  1.1013 +
  1.1014 +@see TFileIo::CheckReservedLock()
  1.1015 +@see TFileIo::Lock()
  1.1016 +	    
  1.1017 +@see TDbFile
  1.1018 +*/
  1.1019 +/* static */ int TFileIo::Unlock(sqlite3_file* aDbFile, int aLockType)
  1.1020 +	{
  1.1021 +	__ASSERT_DEBUG(aLockType <= SQLITE_LOCK_SHARED, __SQLITEPANIC2(ESqliteOsPanicInvalidLock));
  1.1022 +	
  1.1023 +	TDbFile& dbFile = ::DbFile(aDbFile);
  1.1024 +	TInt rc = SQLITE_OK;
  1.1025 +	TInt currLockType = dbFile.iLockType;
  1.1026 +	
  1.1027 +	if(currLockType >= SQLITE_LOCK_EXCLUSIVE)
  1.1028 +		{
  1.1029 +		__SQLITETRACE_OSEXPR(TInt err2 =) dbFile.iFileBuf.UnLock(SHARED_FIRST, SHARED_SIZE);
  1.1030 +		SQLITE_TRACE_OS(OstTraceExt2(TRACE_INTERNALS, TFILEIO_UNLOCK1, "OS;0x%X;TFileIo::Unlock;iFileBuf.UnLock()=%d", (TUint)&dbFile, err2));
  1.1031 +		if(aLockType == SQLITE_LOCK_SHARED)
  1.1032 +    		{
  1.1033 +			TInt err = TFileIo::GetReadLock(dbFile); 
  1.1034 +			if(err != KErrNone && err != KErrLocked)
  1.1035 +				{
  1.1036 +				SQLITE_TRACE_OS(OstTraceExt2(TRACE_INTERNALS, TFILEIO_UNLOCK2, "OS;0x%X;TFileIo::Unlock;TFileIo::GetReadLock() failed, err=%d", (TUint)&dbFile, err));
  1.1037 +				return ::Os2SqliteErr(err, SQLITE_IOERR_UNLOCK);
  1.1038 +				}
  1.1039 +			if(err == KErrLocked)
  1.1040 +				{
  1.1041 +				//This should never happen. We should always be able to reacquire the read lock
  1.1042 +				rc = SQLITE_IOERR_UNLOCK;
  1.1043 +				}
  1.1044 +			}
  1.1045 +		}
  1.1046 +	if(currLockType >= SQLITE_LOCK_RESERVED)
  1.1047 +		{
  1.1048 +		__SQLITETRACE_OSEXPR(TInt err2 =) dbFile.iFileBuf.UnLock(RESERVED_BYTE, 1);
  1.1049 +		SQLITE_TRACE_OS(OstTraceExt2(TRACE_INTERNALS, TFILEIO_UNLOCK3, "OS;0x%X;TFileIo::Unlock;iFileBuf.UnLock()-2=%d", (TUint)&dbFile, err2));
  1.1050 +		}
  1.1051 +	if(aLockType == SQLITE_LOCK_NONE && currLockType >= SQLITE_LOCK_SHARED)
  1.1052 +		{
  1.1053 +		__SQLITETRACE_OSEXPR(TInt err2 =) TFileIo::UnlockReadLock(dbFile);
  1.1054 +		SQLITE_TRACE_OS(OstTraceExt2(TRACE_INTERNALS, TFILEIO_UNLOCK4, "OS;0x%X;TFileIo::Unlock;TFileIo::UnlockReadLock()=%d", (TUint)&dbFile, err2));
  1.1055 +		}
  1.1056 +	if(currLockType>= SQLITE_LOCK_PENDING)
  1.1057 +		{
  1.1058 +		__SQLITETRACE_OSEXPR(TInt err2 =) dbFile.iFileBuf.UnLock(PENDING_BYTE, 1);
  1.1059 +		SQLITE_TRACE_OS(OstTraceExt2(TRACE_INTERNALS, TFILEIO_UNLOCK5, "OS;0x%X;TFileIo::Unlock;iFileBuf.UnLock()-3=%d", (TUint)&dbFile, err2));
  1.1060 +		}
  1.1061 +		
  1.1062 +	dbFile.iLockType = aLockType;
  1.1063 +	SQLITE_TRACE_OS(OstTraceExt3(TRACE_INTERNALS, TFILEIO_UNLOCK6, "OS;0x%X;TFileIo::Unlock;rc=%d;newLockType=%d", (TUint)&dbFile, rc, aLockType));
  1.1064 +	return rc;
  1.1065 +	}
  1.1066 +
  1.1067 +/**
  1.1068 +SQLite OS porting layer API.
  1.1069 +
  1.1070 +Checks if the file lock type is SQLITE_LOCK_RESERVED or bigger.
  1.1071 +
  1.1072 +@param aDbFile A pointer to a TDbFile instance, that contains the file handle.
  1.1073 +@param aResOut Output parameter. It will be set to be non-zero if the stored lock type is bigger or equal 
  1.1074 +							     than SQLITE_LOCK_RESERVED.
  1.1075 +
  1.1076 +@return SQLITE_IOERR_CHECKRESERVEDLOCK, The operation has failed,
  1.1077 +	    SQLITE_OK 					    The operation has completed successfully.
  1.1078 +
  1.1079 +@see TFileIo::Lock()
  1.1080 +@see TFileIo::Unlock()
  1.1081 +	    
  1.1082 +@see TDbFile
  1.1083 +*/
  1.1084 +/* static */ int TFileIo::CheckReservedLock(sqlite3_file* aDbFile, int *aResOut)
  1.1085 +	{
  1.1086 +	TDbFile& dbFile = ::DbFile(aDbFile);
  1.1087 +	TInt rc;
  1.1088 +	if(dbFile.iLockType >= SQLITE_LOCK_RESERVED)
  1.1089 +		{
  1.1090 +		rc = 1;
  1.1091 +  		}
  1.1092 +	else
  1.1093 +		{
  1.1094 +		TInt err = dbFile.iFileBuf.Lock(RESERVED_BYTE, 1);
  1.1095 +		if(err != KErrNone && err != KErrLocked)
  1.1096 +			{
  1.1097 +			SQLITE_TRACE_OS(OstTraceExt2(TRACE_INTERNALS, TFILEIO_CHECKRESERVEDLOCK1, "OS;0x%X;TFileIo::CheckReservedLock;iFileBuf.Lock(), err=%d", (TUint)&dbFile, err));
  1.1098 +			return ::Os2SqliteErr(err, SQLITE_IOERR_CHECKRESERVEDLOCK);
  1.1099 +			}
  1.1100 +		rc = (err == KErrNone);
  1.1101 +		if(rc) //non-zero rc means: the lock has been successful (there wasn't a reserved lock on this file)
  1.1102 +			{
  1.1103 +			__SQLITETRACE_OSEXPR(TInt err2 =) dbFile.iFileBuf.UnLock(RESERVED_BYTE, 1);
  1.1104 +			SQLITE_TRACE_OS(OstTraceExt2(TRACE_INTERNALS, TFILEIO_CHECKRESERVEDLOCK2, "OS;0x%X;TFileIo::CheckReservedLock;iFileBuf.UnLock()=%d", (TUint)&dbFile, err2));
  1.1105 +			}
  1.1106 +    	rc = !rc;
  1.1107 +		}
  1.1108 +	*aResOut = rc;
  1.1109 +	SQLITE_TRACE_OS(OstTraceExt2(TRACE_INTERNALS, TFILEIO_CHECKRESERVEDLOCK3, "OS;0x%X;TFileIo::CheckReservedLock;rc=%d", (TUint)&dbFile, rc));
  1.1110 +	return SQLITE_OK;
  1.1111 +	}
  1.1112 +
  1.1113 +/**
  1.1114 +SQLite OS porting layer API.
  1.1115 +
  1.1116 +Performs an aOp operation on the file referred by the aDbFile parameter.
  1.1117 +Since the only supported operation at the moment is SQLITE_FCNTL_LOCKSTATE, and the current lock type is stored as
  1.1118 +a data memebr of TDbFile, the function implementation has been optimised - no file I/O calls. The stored file lock type
  1.1119 +is retured if the operation is SQLITE_FCNTL_LOCKSTATE.
  1.1120 +
  1.1121 +@param aDbFile A pointer to a TDbFile instance, that contains the file handle.
  1.1122 +@param aOp File operation type. Currently only SQLITE_FCNTL_LOCKSTATE is supported.
  1.1123 +@param aArg An additional input/output parameter which purpose depends on the type of the current file operation.
  1.1124 +			If the file operation is SQLITE_FCNTL_LOCKSTATE, then aArg is used as an output parameter, where
  1.1125 +			the file lock type is stored.
  1.1126 +
  1.1127 +@return SQLITE_ERROR,	Non-supported operation,
  1.1128 +		SQLITE_OK,	The operation has completed successfully.
  1.1129 +	    
  1.1130 +@see TDbFile
  1.1131 +*/
  1.1132 +/* static */ int TFileIo::FileControl(sqlite3_file* aDbFile, int aOp, void* aArg)
  1.1133 +	{
  1.1134 +	TDbFile& dbFile = ::DbFile(aDbFile);
  1.1135 +	TInt err = KErrNone;
  1.1136 +	switch(aOp)
  1.1137 +		{
  1.1138 +		case SQLITE_FCNTL_LOCKSTATE:
  1.1139 +			*(int*)aArg = dbFile.iLockType;
  1.1140 +			break;
  1.1141 +		default:
  1.1142 +			err = KErrArgument;
  1.1143 +			break;
  1.1144 +		}
  1.1145 +	TInt sqliteErr = err == KErrNone ? SQLITE_OK : SQLITE_ERROR;
  1.1146 +	SQLITE_TRACE_OS(OstTraceExt3(TRACE_INTERNALS, TFILEIO_FILECONTROL, "OS;0x%X;TFileIo::FileControl;err=%d;sqliteErr=%d", (TUint)&dbFile, err, sqliteErr));
  1.1147 +	return sqliteErr;
  1.1148 +	}
  1.1149 +
  1.1150 +/**
  1.1151 +SQLite OS porting layer API.
  1.1152 +
  1.1153 +Retrieves the sector size of the media of the file referred by the aDbFile parameter.
  1.1154 +Since the sector size never changes till the file is open, the function has been optimised - no file I/O calls.
  1.1155 +The sector size is retrieved during the TVfs::Open() call and stored in TDbFile::iSectorSize. The SectorSize()
  1.1156 +call returns the value of TDbFile::iSectorSize.
  1.1157 +
  1.1158 +@param aDbFile A pointer to a TDbFile instance, that contains the file handle.
  1.1159 +
  1.1160 +@return The sector size.
  1.1161 +
  1.1162 +@panic Sqlite 19 In _DEBUG mode - TDbFile::iSectorSize is negative or 0 .
  1.1163 +	    
  1.1164 +@see TDbFile
  1.1165 +@see TVfs::Open()
  1.1166 +*/
  1.1167 +/* static */ int TFileIo::SectorSize(sqlite3_file* aDbFile)
  1.1168 +	{
  1.1169 +	TDbFile& dbFile = ::DbFile(aDbFile);
  1.1170 +	__ASSERT_DEBUG(dbFile.iSectorSize > 0, __SQLITEPANIC2(ESqliteOsPanicInternalError));
  1.1171 +	if(dbFile.iSectorSize > 0)
  1.1172 +		{
  1.1173 +		return dbFile.iSectorSize;	
  1.1174 +		}
  1.1175 +	return SQLITE_DEFAULT_SECTOR_SIZE;
  1.1176 +	}
  1.1177 +
  1.1178 +/**
  1.1179 +SQLite OS porting layer API.
  1.1180 +
  1.1181 +Retrieves the device characteristics of the device of the file referred by the aDbFile parameter.
  1.1182 +Since the device characteristics never change till the file is open, the function has been optimised - no file I/O calls.
  1.1183 +The device characteristics are retrieved during the TVfs::Open() call and stored in TDbFile::iDeviceCharacteristics. 
  1.1184 +The DeviceCharacteristics() call returns the value of TDbFile::iDeviceCharacteristics.
  1.1185 +
  1.1186 +@param aDbFile A pointer to a TDbFile instance, that contains the file handle.
  1.1187 +
  1.1188 +@return A bit set containing the device characteristics.
  1.1189 +	    
  1.1190 +@panic Sqlite 19 In _DEBUG mode - TDbFile::iDeviceCharacteristics is negative or 0 .
  1.1191 +
  1.1192 +@see TDbFile
  1.1193 +@see TVfs::Open()
  1.1194 +*/
  1.1195 +/* static */ int TFileIo::DeviceCharacteristics(sqlite3_file* aDbFile)
  1.1196 +	{
  1.1197 +	TDbFile& dbFile = ::DbFile(aDbFile);
  1.1198 +	__ASSERT_DEBUG(dbFile.iDeviceCharacteristics >= 0, __SQLITEPANIC2(ESqliteOsPanicInternalError));
  1.1199 +	if(dbFile.iDeviceCharacteristics >= 0)
  1.1200 +		{
  1.1201 +		return dbFile.iDeviceCharacteristics;	
  1.1202 +		}
  1.1203 +	return 0;
  1.1204 +	}
  1.1205 +
  1.1206 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1.1207 +///////////////////////////////////       TVfs class definition     ///////////////////////////////////////////////////////////
  1.1208 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1.1209 +
  1.1210 +/**
  1.1211 +Collects information about the drive referred by the aDriveNo parameter.
  1.1212 +
  1.1213 +@param aFs			RFs instance.
  1.1214 +@param aDriveNo     The drive about which an information will be collected.
  1.1215 +@param aVolumeInfo	Output parameter. A reference to a TVolumeIOParamInfo object where the collected information will be stored.
  1.1216 +
  1.1217 +@return KErrNone,          The operation has completed succesfully;
  1.1218 +	    KErrNoMemory,      Out of memory condition has occured;
  1.1219 +                           Note that other system-wide error codes may also be returned.
  1.1220 +	    
  1.1221 +@see TVfs::Open()
  1.1222 +*/
  1.1223 +/* static */ inline TInt TVfs::DoGetVolumeIoParamInfo(RFs& aFs, TInt aDriveNo, TVolumeIOParamInfo& aVolumeInfo)
  1.1224 +	{
  1.1225 +	TInt err = aFs.VolumeIOParam(aDriveNo, aVolumeInfo);
  1.1226 +	SQLITE_TRACE_OS(OstTraceExt2(TRACE_INTERNALS, TVFS_DOGETVOLUMEIOPARAMINFO, "OS;0;TVfs::DoGetVolumeIoParamInfo;aDriveNo=%d;err=%d", aDriveNo, err));
  1.1227 +	return err;
  1.1228 +	}
  1.1229 +
  1.1230 +/**
  1.1231 +Retrieves and returns in a bit set the device characteristics.
  1.1232 +
  1.1233 +@param aDriveInfo	A TDriveInfo reference from which the device characteristics will be extracted.
  1.1234 +@param aVolumeInfo	A TVolumeIOParamInfo reference from which the device characteristics will be extracted.
  1.1235 +
  1.1236 +@return A bit set containing the device characteristics: 
  1.1237 +			SQLITE_IOCAP_SAFE_APPEND, SQLITE_IOCAP_ATOMIC, the atomic block size.
  1.1238 +	    
  1.1239 +@see TVfs::DoGetDriveInfo();
  1.1240 +@see TVfs::DoGetVolumeIoParamInfo();
  1.1241 +@see TVfs::Open()
  1.1242 +*/
  1.1243 +/* static */ TInt TVfs::DoGetDeviceCharacteristics(const TDriveInfo& aDriveInfo, const TVolumeIOParamInfo& aVolumeInfo)
  1.1244 +	{
  1.1245 +	TInt deviceCharacteristics = 0;	
  1.1246 +	if(aDriveInfo.iDriveAtt & (KDriveAttLocal | KDriveAttInternal))
  1.1247 +		{
  1.1248 +		deviceCharacteristics |= SQLITE_IOCAP_SAFE_APPEND;//Data written first, file size updated second
  1.1249 +		}
  1.1250 +	if(aDriveInfo.iDriveAtt & KDriveAttTransaction)
  1.1251 +		{
  1.1252 +		deviceCharacteristics |= SQLITE_IOCAP_ATOMIC;	
  1.1253 +		}
  1.1254 +	if(aVolumeInfo.iBlockSize >= SQLITE_DEFAULT_SECTOR_SIZE && (aVolumeInfo.iBlockSize & (aVolumeInfo.iBlockSize - 1)) == 0)	
  1.1255 +		{
  1.1256 +		switch(aVolumeInfo.iBlockSize)
  1.1257 +			{
  1.1258 +			case 512:
  1.1259 +				deviceCharacteristics |= SQLITE_IOCAP_ATOMIC512;
  1.1260 +				break;
  1.1261 +			case 1024:
  1.1262 +				deviceCharacteristics |= SQLITE_IOCAP_ATOMIC1K;
  1.1263 +				break;
  1.1264 +			case 2048:
  1.1265 +				deviceCharacteristics |= SQLITE_IOCAP_ATOMIC2K;
  1.1266 +				break;
  1.1267 +			case 4096:
  1.1268 +				deviceCharacteristics |= SQLITE_IOCAP_ATOMIC4K;
  1.1269 +				break;
  1.1270 +			case 8192:
  1.1271 +				deviceCharacteristics |= SQLITE_IOCAP_ATOMIC8K;
  1.1272 +				break;
  1.1273 +			case 16384:
  1.1274 +				deviceCharacteristics |= SQLITE_IOCAP_ATOMIC16K;
  1.1275 +				break;
  1.1276 +			case 32768:
  1.1277 +				deviceCharacteristics |= SQLITE_IOCAP_ATOMIC32K;
  1.1278 +				break;
  1.1279 +			case 65536:
  1.1280 +				deviceCharacteristics |= SQLITE_IOCAP_ATOMIC64K;
  1.1281 +				break;
  1.1282 +			default:
  1.1283 +				//Do nothing. deviceCharacteristics was initialized with 0 at the beginning of the function body.
  1.1284 +				break;
  1.1285 +			}
  1.1286 +		}
  1.1287 +	return deviceCharacteristics;
  1.1288 +	}
  1.1289 +
  1.1290 +/**
  1.1291 +Retrieves and returns the sector size of the drive referred by the aDriveInfo parameter.
  1.1292 +The sector size must be a power of two.
  1.1293 +The sector size is extracted only if aDriveInfo refers to a removable device, otherwise the
  1.1294 +SQLITE_DEFAULT_SECTOR_SIZE value (512 bytes) will be used as a sector size.
  1.1295 +
  1.1296 +@param aDriveInfo	A TDriveInfo reference.
  1.1297 +@param aVolumeInfo	A TVolumeIOParamInfo reference.
  1.1298 +
  1.1299 +@return The sector size of the drive referred by the aDriveInfo parameter.
  1.1300 +
  1.1301 +@panic Sqlite 19 In _DEBUG mode - The sector size is negative, zero or is not a power of two.
  1.1302 +	    
  1.1303 +@see TVfs::Open()
  1.1304 +*/
  1.1305 +/* static */ TInt TVfs::DoGetSectorSize(const TDriveInfo& aDriveInfo, const TVolumeIOParamInfo& aVolumeInfo)
  1.1306 +	{
  1.1307 +	//Initialize the sectorSize variable only if: 
  1.1308 +	// - aDriveInfo refers to a removable drive
  1.1309 +	// - aVolumeInfo.iBlockSize > SQLITE_DEFAULT_SECTOR_SIZE;
  1.1310 +	// - aVolumeInfo.iBlockSize is power of 2;
  1.1311 +	TInt sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
  1.1312 +	if(aDriveInfo.iDriveAtt & KDriveAttRemovable)
  1.1313 +		{
  1.1314 +		if(aVolumeInfo.iBlockSize > SQLITE_DEFAULT_SECTOR_SIZE && (aVolumeInfo.iBlockSize & (aVolumeInfo.iBlockSize - 1)) == 0)
  1.1315 +			{
  1.1316 +			sectorSize = aVolumeInfo.iBlockSize;
  1.1317 +			}
  1.1318 +		}
  1.1319 +	__ASSERT_DEBUG(sectorSize > 0 && (sectorSize & (sectorSize - 1)) == 0, __SQLITEPANIC2(ESqliteOsPanicInternalError));
  1.1320 +	return sectorSize;
  1.1321 +	}
  1.1322 +
  1.1323 +/**
  1.1324 +Retrieves in a bit set the device characteristics of the device of the file referred by the aDbFile parameter.
  1.1325 +Retrieves the sector size of the drive of the file referred by the aDbFile parameter. 
  1.1326 +The sector size and the device characteristics will be stored in iSectorSize and iDeviceCharacteristics TDbFile data members.
  1.1327 +The stored values will be used later by TFileIo::DeviceCharacteristics() and TFileIo::SectorSize().
  1.1328 +
  1.1329 +@param aDbFile	Input/Output parameter. A TDriveInfo reference. The collected information will be stored in TDbDrive
  1.1330 +				data members.
  1.1331 +@param aRecReadBufSize Output parameter. The recommended buffer size for optimised reading performance.
  1.1332 +
  1.1333 +@return KErrNone,          The operation has completed succesfully;
  1.1334 +                           Note that other system-wide error codes may also be returned.
  1.1335 +
  1.1336 +@panic Sqlite 19 In _DEBUG mode - TDbFile::iSectorSize has been already initialized.
  1.1337 +@panic Sqlite 19 In _DEBUG mode - TDbFile::iDeviceCharacteristics has been already initialized.
  1.1338 +
  1.1339 +@see TVfs::DoGetDeviceCharacteristics();
  1.1340 +@see TVfs::DoGetSectorSize();
  1.1341 +@see TVfs::Open()
  1.1342 +@see TDbFile
  1.1343 +@see TFileIo::DeviceCharacteristics()
  1.1344 +@see TFileIo::SectorSize()
  1.1345 +*/
  1.1346 +/* static */ TInt TVfs::DoGetDeviceCharacteristicsAndSectorSize(TDbFile& aDbFile, TInt& aRecReadBufSize)
  1.1347 +	{
  1.1348 +	__ASSERT_DEBUG(aDbFile.iDeviceCharacteristics < 0, __SQLITEPANIC2(ESqliteOsPanicInternalError));
  1.1349 +	__ASSERT_DEBUG(aDbFile.iSectorSize <= 0, __SQLITEPANIC2(ESqliteOsPanicInternalError));
  1.1350 +	TInt driveNo;
  1.1351 +	TDriveInfo driveInfo;
  1.1352 +	TInt err = aDbFile.iFileBuf.Drive(driveNo, driveInfo);
  1.1353 +	if(err != KErrNone)
  1.1354 +		{
  1.1355 +		return err;	
  1.1356 +		}
  1.1357 +	TVolumeIOParamInfo volumeInfo;
  1.1358 +	err = TVfs::DoGetVolumeIoParamInfo(TStaticFs::Fs(), driveNo, volumeInfo);
  1.1359 +	if(err != KErrNone)
  1.1360 +		{
  1.1361 +		return err;	
  1.1362 +		}
  1.1363 +	aDbFile.iDeviceCharacteristics = TVfs::DoGetDeviceCharacteristics(driveInfo, volumeInfo);
  1.1364 +	aDbFile.iSectorSize = TVfs::DoGetSectorSize(driveInfo, volumeInfo);
  1.1365 +	aRecReadBufSize = volumeInfo.iRecReadBufSize;
  1.1366 +	SQLITE_TRACE_OS(OstTraceExt5(TRACE_INTERNALS, TVFS_DOGETGETDEVICECHARACTERISTICSANDSECTORSIZE, "OS;0x%X;TVfs::DoGetDeviceCharacteristicsAndSectorSize;driveNo=%d;sectorSize=%d;devCharact=0x%X;readBufSize=%d", (TUint)&aDbFile, driveNo, aDbFile.iSectorSize, (TUint)aDbFile.iDeviceCharacteristics, volumeInfo.iRecReadBufSize));
  1.1367 +	return KErrNone;
  1.1368 +	}
  1.1369 +
  1.1370 +//Creates a temporary file. The file location will be the application's session path. 
  1.1371 +//If the session path does not exist, then the function will create the session path.
  1.1372 +static TInt CreateTempFile(TDbFile& aDbFile, TFileName& aFileNameOut, TInt aFileMode)
  1.1373 +	{
  1.1374 +	TFileName sessionPath;
  1.1375 +	TInt err = TStaticFs::Fs().SessionPath(sessionPath);
  1.1376 +	if(err == KErrNone)
  1.1377 +		{
  1.1378 +		err = aDbFile.iFileBuf.Temp(TStaticFs::Fs(), sessionPath, aFileNameOut, aFileMode);
  1.1379 +		if(err == KErrPathNotFound)
  1.1380 +			{
  1.1381 +			err = TStaticFs::Fs().MkDirAll(sessionPath);
  1.1382 +			if(err == KErrNone)
  1.1383 +				{
  1.1384 +				err = aDbFile.iFileBuf.Temp(TStaticFs::Fs(), sessionPath, aFileNameOut, aFileMode);
  1.1385 +				}
  1.1386 +			}
  1.1387 +		if(err == KErrNone)
  1.1388 +			{
  1.1389 +			aDbFile.iFullName = aFileNameOut.Alloc();
  1.1390 +			if(!aDbFile.iFullName)
  1.1391 +				{
  1.1392 +				aDbFile.iFileBuf.Close();
  1.1393 +				(void)TStaticFs::Fs().Delete(aFileNameOut);
  1.1394 +				err = KErrNoMemory;
  1.1395 +				}
  1.1396 +			}
  1.1397 +		}
  1.1398 +	return err;
  1.1399 +	}
  1.1400 +
  1.1401 +/**
  1.1402 +SQLite OS porting layer API.
  1.1403 +
  1.1404 +The behaviour of the RFile/RFile64::SetSize operation is not atomic for non-rugged drives. 
  1.1405 +When RFile/RFile64::SetSize() is called 2 operations occurs:-
  1.1406 +
  1.1407 +1)The cluster chain of the file is updated.
  1.1408 +2)The new file size is added to the file cache.
  1.1409 +
  1.1410 +If a power loss occurs after a SetSize there is a chance that the cluster chain was updated 
  1.1411 +but the new file size is not yet flushed to the file. This puts the file into an inconsistent state.
  1.1412 +This is most likely to occur in the journal file where the time between a SetSize and Flush can 
  1.1413 +be long. 
  1.1414 +
  1.1415 +For this reason this check is added when the file is opened to see if the end of the file can 
  1.1416 +be read straight away, if an error is returned then it is assumed that the SetSize has not be 
  1.1417 +completed previously. In this case the file is deleted and re-created.
  1.1418 + 
  1.1419 +@param aDbFile A pointer to a TDbFile instance, that contains the file handle.
  1.1420 +@param aFname A string of 16-bit wide characters containing name of the file to be checked.
  1.1421 +@param aFmode The mode in which the file is opened. These mode are documented in TFileMode.
  1.1422 +
  1.1423 +@return KErrNone,          The operation has completed succesfully;
  1.1424 +                           Note that other system-wide error codes may also be returned.
  1.1425 +@see TFileMode
  1.1426 +@see TVfs::Open()
  1.1427 +@see TDbFile
  1.1428 +*/
  1.1429 +/* static */ TInt TVfs::DoFileSizeCorruptionCheck(TDbFile& aDbFile, const TDesC& aFname, TInt aFmode)
  1.1430 +    {
  1.1431 +    const TInt KMinSize = 16;
  1.1432 +    TInt64 size;
  1.1433 +    TInt err = KErrNone ;
  1.1434 +    TBuf8<KMinSize> buf;
  1.1435 +
  1.1436 +    err = aDbFile.iFileBuf.Size(size);
  1.1437 +    if (err != KErrNone)
  1.1438 +        {
  1.1439 +        return err;
  1.1440 +        }
  1.1441 +    TBool IsMinFileSize = (size >= KMinSize);
  1.1442 +    
  1.1443 +    if (IsMinFileSize)
  1.1444 +        {
  1.1445 +        err = aDbFile.iFileBuf.Read(size - KMinSize, buf);
  1.1446 +        }
  1.1447 +    
  1.1448 +    if (err == KErrCorrupt || err == KErrEof || !IsMinFileSize)
  1.1449 +        {
  1.1450 +        aDbFile.iFileBuf.Close();
  1.1451 +        __SQLITETRACE_OSEXPR(TInt err2 =) TStaticFs::Fs().Delete(aFname);
  1.1452 +		SQLITE_TRACE_OS(OstTraceExt4(TRACE_INTERNALS, TVFS_DOFILESIZECORRUPTIONCHECK1, "OS;0x%X;TVfs::DoFileSizeCorruptionCheck;size=%lld;err=%d;deleteErr=%d", (TUint)&aDbFile, size, err, err2));
  1.1453 +        err = aDbFile.iFileBuf.Create(TStaticFs::Fs(), aFname, aFmode);
  1.1454 +		SQLITE_TRACE_OS(OstTraceExt2(TRACE_INTERNALS, TVFS_DOFILESIZECORRUPTIONCHECK2, "OS;0x%X;TVfs::DoFileSizeCorruptionCheck;createErr=%d", (TUint)&aDbFile, err));
  1.1455 +        }
  1.1456 +    return err;
  1.1457 +    }
  1.1458 +
  1.1459 +/**
  1.1460 +SQLite OS porting layer API.
  1.1461 +
  1.1462 +Opens or creates a file which name is in the aFileName parameter.
  1.1463 +If the function succeeds, the file handle and other related information will be stored in the place pointed by the 
  1.1464 +aDbFile parameter, a memory block of sizeof(TDbFile) size for which is allocated by the caller.
  1.1465 +The function will also retrieve the sector size and the device characteristics and store them in aDbFile,
  1.1466 +which is actually a TDbFile pointer, for later use.
  1.1467 +
  1.1468 +@param aFileName Zero-terminated, UTF8 encoded file name.
  1.1469 +				 If aFileName is NULL then a temporary file is created.
  1.1470 +@param aDbFile Output parameter. The file handle and other related information will be stored there.
  1.1471 +@param aFlags  "Open/Create" input flags: 
  1.1472 +					SQLITE_OPEN_DELETEONCLOSE,
  1.1473 +					SQLITE_OPEN_READWRITE,
  1.1474 +					SQLITE_OPEN_EXCLUSIVE,
  1.1475 +					SQLITE_OPEN_CREATE
  1.1476 +@param aOutFlags  "Open/Create" output flags:
  1.1477 +					SQLITE_OPEN_READWRITE,
  1.1478 +					SQLITE_OPEN_READONLY
  1.1479 +
  1.1480 +@return SQLITE_CANTOPEN,    The aFileName parameter cannot be converted to UTF16.
  1.1481 +							Any other file I/O error will also be reported as SQLITE_CANTOPEN;
  1.1482 +	    SQLITE_IOERR_NOMEM,	An out of memory condition has occured;
  1.1483 +	    SQLITE_OK,			The operation has completed successfully.
  1.1484 +	    
  1.1485 +@see TDbFile
  1.1486 +*/
  1.1487 +/* static */ int TVfs::Open(sqlite3_vfs* aVfs, const char* aFileName, sqlite3_file* aDbFile, int aFlags, int* aOutFlags)
  1.1488 +	{
  1.1489 +	TFileName fname;
  1.1490 +	if(aFileName && !::ConvertToUnicode(aFileName, fname))
  1.1491 +		{
  1.1492 +		SQLITE_TRACE_OS(OstTrace0(TRACE_INTERNALS, TVFS_OPEN1, "OS;0;TVfs::Open;ConvertToUnicode() failed"));
  1.1493 +		return SQLITE_CANTOPEN;	
  1.1494 +		}
  1.1495 +	new (aDbFile) TDbFile;
  1.1496 +	TDbFile& dbFile = ::DbFile(aDbFile);
  1.1497 +	SQLITE_TRACE_OS(OstTraceExt3(TRACE_INTERNALS, TVFS_OPEN_ENTRY, "OS-Entry;0x%X;TVfs::Open;fname=%S;aFlags=0x%X", (TUint)&aDbFile, __SQLITEPRNSTR(fname), (TUint)aFlags));
  1.1498 +	if(aFileName && (aFlags & SQLITE_OPEN_DELETEONCLOSE))
  1.1499 +		{
  1.1500 +		dbFile.iFullName = fname.Alloc();
  1.1501 +		if(!dbFile.iFullName)
  1.1502 +			{
  1.1503 +			SQLITE_TRACE_OS(OstTrace0(TRACE_INTERNALS, TVFS_OPEN2, "OS;0;TVfs::Open;fname.Alloc() failed"));
  1.1504 +			return SQLITE_IOERR_NOMEM;
  1.1505 +			}
  1.1506 +		}
  1.1507 +	TInt recReadBufSize = -1;
  1.1508 +	TInt err = KErrNone;
  1.1509 +	TInt fmode = EFileRead;
  1.1510 +	if(aFlags & SQLITE_OPEN_READWRITE)
  1.1511 +		{
  1.1512 +		fmode |= EFileWrite;
  1.1513 +		}
  1.1514 +	//SQLite TCL tests expect the journal file to be open in shared mode.
  1.1515 +	if(aFlags & SQLITE_OPEN_EXCLUSIVE && !(aFlags & SQLITE_OPEN_MAIN_JOURNAL))
  1.1516 +		{
  1.1517 +		fmode |= EFileShareExclusive;
  1.1518 +		}
  1.1519 +	else
  1.1520 +		{
  1.1521 +		fmode |= (fmode & EFileWrite) ? EFileShareAny : EFileShareReadersOnly;
  1.1522 +		}
  1.1523 +	if(!aFileName)	
  1.1524 +		{//Create temporary file
  1.1525 +		err = ::CreateTempFile(dbFile, fname, fmode);
  1.1526 +		}
  1.1527 +	else
  1.1528 +		{
  1.1529 +		err = KErrAccessDenied;//The error has to be set here, because, there is a case where none of the file create/open operations will be executed
  1.1530 +		TInt prevErr = KErrNone;
  1.1531 +		if(aFlags & SQLITE_OPEN_CREATE)
  1.1532 +			{
  1.1533 +			prevErr = err = dbFile.iFileBuf.Create(TStaticFs::Fs(), fname, fmode);
  1.1534 +			}
  1.1535 +		if(err != KErrNone && err != KErrNoMemory && err != KErrDiskFull)
  1.1536 +			{
  1.1537 +			err = dbFile.iFileBuf.Open(TStaticFs::Fs(), fname, fmode);
  1.1538 +			if(err == KErrNone && (aFlags & KJournalFileTypeBitMask))
  1.1539 +			    {
  1.1540 +                err = TVfs::DoFileSizeCorruptionCheck(dbFile, fname, fmode);
  1.1541 +			    }
  1.1542 +			}
  1.1543 +		if((err != KErrNone && err != KErrNoMemory && err != KErrDiskFull) && (aFlags & SQLITE_OPEN_READWRITE))
  1.1544 +			{
  1.1545 +			aFlags &= ~SQLITE_OPEN_READWRITE;
  1.1546 +			aFlags |= SQLITE_OPEN_READONLY;
  1.1547 +			fmode &= ~EFileWrite;
  1.1548 +			err = dbFile.iFileBuf.Open(TStaticFs::Fs(), fname, fmode);
  1.1549 +			}
  1.1550 +		if(err != KErrNone && prevErr == KErrAccessDenied)
  1.1551 +			{
  1.1552 +			err = KErrAccessDenied;
  1.1553 +			}
  1.1554 +		}
  1.1555 +	if(err == KErrNone)
  1.1556 +		{
  1.1557 +		err = TVfs::DoGetDeviceCharacteristicsAndSectorSize(dbFile, recReadBufSize);
  1.1558 +		}
  1.1559 +	if(err != KErrNone)
  1.1560 +		{
  1.1561 +		dbFile.iFileBuf.Close();	
  1.1562 +		delete dbFile.iFullName;
  1.1563 +		dbFile.iFullName = NULL;
  1.1564 +        if(!aFileName && fname.Length() > 0)
  1.1565 +            {//temporary file, the error is not KErrNone. Then delete the file (after a successfull 
  1.1566 +             //temporary file creation there could be a failed memory allocation)
  1.1567 +            (void)TStaticFs::Fs().Delete(fname);
  1.1568 +            }
  1.1569 +		}
  1.1570 +	else
  1.1571 +		{
  1.1572 +		dbFile.pMethods = &TheFileIoApi;
  1.1573 +		dbFile.iReadOnly = !(aFlags & SQLITE_OPEN_READWRITE);
  1.1574 +		if(aOutFlags)
  1.1575 +			{
  1.1576 +			*aOutFlags = dbFile.iReadOnly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_READWRITE;
  1.1577 +			}
  1.1578 +		(void)dbFile.iFileBuf.SetReadAheadSize(dbFile.iSectorSize, recReadBufSize);
  1.1579 +		OpenCounter(+1);
  1.1580 +		}
  1.1581 +	TInt sqliteErr = ::Os2SqliteErr(err, SQLITE_CANTOPEN);
  1.1582 +	SQLITE_TRACE_OS(OstTraceExt4(TRACE_INTERNALS, TVFS_OPEN_EXIT, "OS-Exit;0x%X;TVfs::Open;outFlags=0x%X;err=%d;sqliteErr=%d", (TUint)&aDbFile, aOutFlags ? (TUint)*aOutFlags : 0, err, sqliteErr));
  1.1583 +	return sqliteErr;
  1.1584 +	}
  1.1585 +
  1.1586 +/**
  1.1587 +SQLite OS porting layer API.
  1.1588 +
  1.1589 +Deletes a file which name is in the aFileName parameter.
  1.1590 +
  1.1591 +@param aFileName Zero-terminated, UTF8 encoded file name.
  1.1592 +
  1.1593 +@return SQLITE_ERROR,    	The aFileName parameter cannot be converted to UTF16.
  1.1594 +							The file name refers to a private secure database;
  1.1595 +	    SQLITE_IOERR_NOMEM,	An out of memory condition has occured;
  1.1596 +	    SQLITE_IOERR_DELETE,The delete file operation has failed;
  1.1597 +	    SQLITE_OK,			The operation has completed successfully.
  1.1598 +*/
  1.1599 +/* static */ int TVfs::Delete(sqlite3_vfs* aVfs, const char* aFileName, int /*aSyncDir*/)
  1.1600 +	{
  1.1601 +	SimulateIOError(return SQLITE_IOERR_DELETE);
  1.1602 +	TFileName fname;
  1.1603 +	if(!::ConvertToUnicode(aFileName, fname))
  1.1604 +		{
  1.1605 +		SQLITE_TRACE_OS(OstTrace0(TRACE_INTERNALS, TVFS_DELETE1, "OS;0;TVfs::Delete;ConvertToUnicode() failed"));
  1.1606 +		return SQLITE_ERROR;	
  1.1607 +		}
  1.1608 +	TInt err = TStaticFs::Fs().Delete(fname);
  1.1609 +	TInt sqliteErr = ::Os2SqliteErr(err, SQLITE_IOERR_DELETE);
  1.1610 +	SQLITE_TRACE_OS(OstTraceExt2(TRACE_INTERNALS, TVFS_DELETE2, "OS;0;TVfs::Delete;err=%d;sqliteErr=%d", err, sqliteErr));
  1.1611 +	return sqliteErr;
  1.1612 +	}
  1.1613 +
  1.1614 +/**
  1.1615 +SQLite OS porting layer API.
  1.1616 +
  1.1617 +Retrieves an information about a file which name is in the aFileName parameter.
  1.1618 +The requested information type can be: does the file exist, is the file read-only or read/write.
  1.1619 +
  1.1620 +@param aFileName Zero-terminated, UTF8 encoded file name.
  1.1621 +@param aFlags This parameter can be one of: SQLITE_ACCESS_READ, SQLITE_ACCESS_EXISTS or SQLITE_ACCESS_READWRITE.
  1.1622 +@param aResOut Output parameter, set to 1 if the tested condition is true, 0 otherwise.
  1.1623 +
  1.1624 +@return SQLITE_OK, 			The call has completed successfully,
  1.1625 +		SQLITE_IOERR_NOMEM, An out of memory conditon has occured,
  1.1626 +		SQLITE_IOERR_ACCESS,File I/O error;  
  1.1627 +*/
  1.1628 +/* static */ int TVfs::Access(sqlite3_vfs* aVfs, const char* aFileName, int aFlags, int* aResOut)
  1.1629 +	{
  1.1630 +	TFileName fname;
  1.1631 +	if(!::ConvertToUnicode(aFileName, fname))
  1.1632 +		{
  1.1633 +		SQLITE_TRACE_OS(OstTrace0(TRACE_INTERNALS, TVFS_ACCESS1, "OS;0;TVfs::Access;ConvertToUnicode() failed"));
  1.1634 +		return SQLITE_IOERR_ACCESS;
  1.1635 +		}
  1.1636 +	SQLITE_TRACE_OS(OstTraceExt2(TRACE_INTERNALS, TVFS_ACCESS_ENTRY, "OS-Entry;0;TVfs::Access;fname=%S;aFlags=0x%X", __SQLITEPRNSTR(fname), (TUint)aFlags));
  1.1637 +	TEntry entry;
  1.1638 +	TInt err = TStaticFs::Fs().Entry(fname, entry);
  1.1639 +	if(aFlags == SQLITE_ACCESS_EXISTS && err == KErrNotFound)
  1.1640 +		{
  1.1641 +		*aResOut = 0;
  1.1642 +		SQLITE_TRACE_OS(OstTrace0(TRACE_INTERNALS, TVFS_ACCESS_EXIT1, "OS-Exit;0;TVfs::Access;Exists-NoFound"));
  1.1643 +		return SQLITE_OK;
  1.1644 +		}
  1.1645 +	if(err != KErrNone)
  1.1646 +		{
  1.1647 +		SQLITE_TRACE_OS(OstTrace1(TRACE_INTERNALS, TVFS_ACCESS_EXIT2, "OS-Exit;0;TVfs::Access;err=%d", err));
  1.1648 +		return err == KErrNoMemory ? SQLITE_IOERR_NOMEM : SQLITE_IOERR_ACCESS;
  1.1649 +		}
  1.1650 +	*aResOut = 0;
  1.1651 +	switch(aFlags)
  1.1652 +		{
  1.1653 +		case SQLITE_ACCESS_READ:
  1.1654 +			*aResOut =  entry.IsReadOnly();
  1.1655 +			break;
  1.1656 +		case SQLITE_ACCESS_EXISTS:
  1.1657 +			*aResOut = 1;
  1.1658 +			break;
  1.1659 +		case SQLITE_ACCESS_READWRITE:
  1.1660 +			*aResOut = !entry.IsReadOnly();
  1.1661 +			break;
  1.1662 +		default:
  1.1663 +			break;			
  1.1664 +		}
  1.1665 +	SQLITE_TRACE_OS(OstTrace1(TRACE_INTERNALS, TVFS_ACCESS_EXIT3, "OS-Exit;0;TVfs::Access;aResOut=%d", *aResOut));
  1.1666 +	return SQLITE_OK;
  1.1667 +	}
  1.1668 +
  1.1669 +/**
  1.1670 +SQLite OS porting layer API.
  1.1671 +
  1.1672 +Accepts UTF8 encoded, zero-terminated file as an input argument in the aRelative parameter
  1.1673 +and constructs the full file path in the aBuf output parameter.
  1.1674 +
  1.1675 +If the format of aRelative argument is <[SID]FileName.[EXT]>, then the database file name will be 
  1.1676 +treated as a name of a secure database file which has to be created/opened in the server's private 
  1.1677 +directory on the system drive.
  1.1678 +
  1.1679 +If the format of aRelative argument is <Drive:[SID]FileName.[EXT]>, then the database file name 
  1.1680 +will be treated as a name of a secure database file which has to be created/opened in the server's 
  1.1681 +private directory on <Drive:> drive. 
  1.1682 +
  1.1683 +If the format of aRelative argument is <Drive:\Path\FileName.[EXT]>, then the database file name
  1.1684 +will be treated as a name of a non-secure database file in <Drive:\Path\> directory.
  1.1685 +If aRelative contains file handles, then it will be treated as a name of a file belonging to server's
  1.1686 +private data cage. 
  1.1687 +
  1.1688 +@param aRelative The input file name, zero-terminated, UTF8 encoded.
  1.1689 +@param aBufLen The output buffer length.
  1.1690 +@param aBuf Output buffer for the constructed full file name path. The allocated buffer length must be at least aBufLen bytes.
  1.1691 +
  1.1692 +@return SQLITE_ERROR, The aRelative parameter is NULL or cannot be converted to UTF16;
  1.1693 +		SQLITE_OK The operation has completed successfully.
  1.1694 +*/
  1.1695 +/* static */ int TVfs::FullPathName(sqlite3_vfs* aVfs, const char* aRelative, int aBufLen, char* aBuf)
  1.1696 +	{
  1.1697 +	if(!aRelative)	//NULL argument
  1.1698 +		{
  1.1699 +		SQLITE_TRACE_OS(OstTrace0(TRACE_INTERNALS, TVFS_FULLPATHNAME1, "OS;0;TVfs::FullPathName;err=SQLITE_ERROR"));
  1.1700 +		return SQLITE_ERROR;
  1.1701 +		}
  1.1702 +	//Convert the received file name to UTF16
  1.1703 +	TBuf<KMaxFileName + 1> fname;
  1.1704 +	if(!::ConvertToUnicode(aRelative, fname))
  1.1705 +		{
  1.1706 +		SQLITE_TRACE_OS(OstTrace0(TRACE_INTERNALS, TVFS_FULLPATHNAME_EXIT1, "OS-Exit;0;TVfs::FullPathName;ConvertToUnicode() failed"));
  1.1707 +		return SQLITE_ERROR;
  1.1708 +		}	
  1.1709 +	SQLITE_TRACE_OS(OstTraceExt2(TRACE_INTERNALS, TVFS_FULLPATHNAME_ENTRY, "OS-Entry;0;TVfs::FullPathName;fname=%S;aBufLen=%d", __SQLITEPRNSTR(fname), aBufLen));
  1.1710 +	//Search if the file name begins with ".\" - current directory
  1.1711 +	if(fname.Find(KCwd) == 0)
  1.1712 +		{
  1.1713 +		fname.Delete(0, KCwd().Length());
  1.1714 +		}
  1.1715 +	fname.Append(TChar(0));//Zero-terminate the converted file name
  1.1716 +	TFileName defaultPath;
  1.1717 +	TInt err = TStaticFs::Fs().SessionPath(defaultPath);
  1.1718 +	if(err != KErrNone)
  1.1719 +		{
  1.1720 +		SQLITE_TRACE_OS(OstTrace1(TRACE_INTERNALS, TVFS_FULLPATHNAME_EXIT4, "OS-Exit;0;TVfs::FullPathName;SessionPath() failed, err=%d", err));
  1.1721 +		return SQLITE_ERROR;
  1.1722 +		}
  1.1723 +	TParse parse;
  1.1724 +	(void)parse.Set(fname, &defaultPath, 0);//If fname does not have a path, defaultPath will be used
  1.1725 +	TPtr8 dest8(reinterpret_cast <TUint8*> (aBuf), aBufLen);	
  1.1726 +	if(!::ConvertFromUnicode(parse.FullName(), dest8))
  1.1727 +		{
  1.1728 +		SQLITE_TRACE_OS(OstTrace0(TRACE_INTERNALS, TVFS_FULLPATHNAME_EXIT2, "OS-Exit;0;TVfs::FullPathName;ConvertFromUnicode() failed"));
  1.1729 +		return SQLITE_ERROR;	
  1.1730 +		}
  1.1731 +	SQLITE_TRACE_OS(OstTrace0(TRACE_INTERNALS, TVFS_FULLPATHNAME_EXIT3, "OS-Exit;0;TVfs::FullPathName;err=SQLITE_OK"));
  1.1732 +	return SQLITE_OK;
  1.1733 +	}
  1.1734 +
  1.1735 +/**
  1.1736 +SQLite OS porting layer API.
  1.1737 +
  1.1738 +Generates a set of random numbers and stores them in the aBuf output parameter.
  1.1739 +
  1.1740 +@param aBufLen The output buffer length.
  1.1741 +@param aBuf Output buffer for the generated random numbers. The allocated buffer length must be at least aBufLen bytes.
  1.1742 +
  1.1743 +@return The length of the used part of the output buffer.
  1.1744 +*/
  1.1745 +/* static */ int TVfs::Randomness(sqlite3_vfs* aVfs, int aBufLen, char* aBuf)
  1.1746 +	{
  1.1747 +	const TInt KRandIterations = aBufLen / sizeof(int);
  1.1748 +	for(TInt i=0;i<KRandIterations;++i)
  1.1749 +		{
  1.1750 +		TInt val = Math::Rand(Seed());
  1.1751 +		Mem::Copy(&aBuf[i * sizeof(int)], &val, sizeof(val));
  1.1752 +		}
  1.1753 +	return KRandIterations * sizeof(int);
  1.1754 +	}
  1.1755 +
  1.1756 +/**
  1.1757 +SQLite OS porting layer API.
  1.1758 +
  1.1759 +Sleeps for aMicrosec microseconds.
  1.1760 +
  1.1761 +@param aMicrosec The sleep interval in microseconds.
  1.1762 +
  1.1763 +@return The aMicrosec value.
  1.1764 +*/
  1.1765 +/* static */ int TVfs::Sleep(sqlite3_vfs* aVfs, int aMicrosec)
  1.1766 +	{
  1.1767 +	User::AfterHighRes(TTimeIntervalMicroSeconds32(aMicrosec));
  1.1768 +	return aMicrosec;
  1.1769 +	}
  1.1770 +
  1.1771 +/**
  1.1772 +SQLite OS porting layer API.
  1.1773 +
  1.1774 +Retrieves the current date and time.
  1.1775 +
  1.1776 +@param aNow Output parameter, where the data and time value will be stored.
  1.1777 +			SQLite processes all times and dates as Julian Day numbers and
  1.1778 +			aNow parameter will contain the julian date and time.
  1.1779 +
  1.1780 +@return 0.
  1.1781 +*/
  1.1782 +/* static */ int TVfs::CurrentTime(sqlite3_vfs* aVfs, double* aNow)
  1.1783 +	{
  1.1784 +	TTime now;
  1.1785 +	now.UniversalTime();
  1.1786 +	TDateTime date = now.DateTime();
  1.1787 +	TInt year = date.Year();
  1.1788 +	TInt month = date.Month() + 1;
  1.1789 +	TInt day = date.Day() + 1;
  1.1790 +	
  1.1791 +    //Calculate the Julian days
  1.1792 +	TInt jd = day - 32076 +
  1.1793 +	    1461*(year + 4800 + (month - 14)/12)/4 +
  1.1794 +	    367*(month - 2 - (month - 14)/12*12)/12 -
  1.1795 +	    3*((year + 4900 + (month - 14)/12)/100)/4;
  1.1796 +          	
  1.1797 +	*aNow = jd;
  1.1798 +
  1.1799 +    // Add the fractional hours, mins and seconds
  1.1800 +	*aNow += (date.Hour() + 12.0) / 24.0;
  1.1801 +	*aNow += date.Minute() / 1440.0;
  1.1802 +	*aNow += date.Second() / 86400.0;
  1.1803 +	
  1.1804 +#ifdef SQLITE_TEST
  1.1805 +	if( sqlite3_current_time )
  1.1806 +		{
  1.1807 +    	*aNow = sqlite3_current_time / 86400.0 + 2440587.5;
  1.1808 +		}
  1.1809 +#endif
  1.1810 +	return 0;
  1.1811 +	}
  1.1812 +
  1.1813 +/**
  1.1814 +SQLite OS porting layer API.
  1.1815 +
  1.1816 +Retrieves a text description of the last OS error.
  1.1817 +Note: the method has a default "no-op" implementation at the moment. 
  1.1818 +
  1.1819 +@return 0.
  1.1820 +*/
  1.1821 +/* static */int TVfs::GetLastError(sqlite3_vfs* aVfs, int /*aBufLen*/, char* /*aBuf*/)
  1.1822 +	{
  1.1823 +	return 0;
  1.1824 +	}
  1.1825 +
  1.1826 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1.1827 +
  1.1828 +#endif//SQLITE_OS_SYMBIAN