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