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
|