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