|
1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // The Symbian OS porting layer - single-threaded implementation. |
|
15 // SQLite never accesses the file system and the OS services directly. |
|
16 // SQLite uses for that sqlite3_vfs and sqlite3_file objects. |
|
17 // sqlite3_vfs and sqlite3_file functionality is implemented in this file - |
|
18 // TVfs and TFileIo classes. |
|
19 // This file is also used for the COsLayerData implementation. A single COslayerData |
|
20 // object is used by the OS porting layer for managing some global data. |
|
21 // |
|
22 // |
|
23 |
|
24 /** |
|
25 @file |
|
26 @see TVfs |
|
27 @see TFileIo |
|
28 */ |
|
29 |
|
30 #ifdef SQLITE_OS_SYMBIAN |
|
31 |
|
32 //#define _SQLPROFILER // Enable profiling //The same macro has to be enabled in SqlAssert.h file |
|
33 |
|
34 extern "C" |
|
35 { |
|
36 #include "sqliteInt.h" |
|
37 #include "os.h" |
|
38 } |
|
39 #include "os_common.h" |
|
40 #include "SqliteSymbian.h" |
|
41 #include "FileBuf64.h" |
|
42 #include <e32math.h> |
|
43 #include "UTraceSql.h" |
|
44 #ifdef _SQLPROFILER |
|
45 #include <hal.h> |
|
46 #include "../INC/SqlResourceProfiler.h" |
|
47 #endif |
|
48 |
|
49 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
50 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
51 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
52 |
|
53 /** |
|
54 Panic category - used by asserts in this file (the OS porting layer). |
|
55 |
|
56 @see TPanicCodes |
|
57 |
|
58 @internalComponent |
|
59 */ |
|
60 _LIT(KPanicCategory, "Sqlite"); |
|
61 |
|
62 /** |
|
63 Panic codes - used by asserts in this file (the OS porting layer). |
|
64 |
|
65 @see KPanicCategory |
|
66 |
|
67 @internalComponent |
|
68 */ |
|
69 enum TPanicCodes |
|
70 { |
|
71 EPanicNullOsLayerDataPtr = 1, |
|
72 EPanicInvalidWAmount = 2, |
|
73 EPanicOffset64bit = 3, |
|
74 EPanicInvalidOpType =11, |
|
75 EPanicInvalidFhStr =12, |
|
76 EPanicInvalidFhData =13, |
|
77 EPanicInvalidArg =14, |
|
78 EPanicInvalidRAmount =15, |
|
79 EPanicOsLayerDataExists =16, |
|
80 EPanicInvalidDrive =17, |
|
81 EPanicInvalidSectorSize =18, |
|
82 EPanicInternalError =19, |
|
83 EPanicNullDbFilePtr =20, |
|
84 EPanicFastCounterFreq =21 |
|
85 }; |
|
86 |
|
87 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
88 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
89 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
90 #ifdef _SQLPROFILER |
|
91 |
|
92 //Profiling counters, defined in SqlSrvResourceprofiler.cpp |
|
93 extern TInt TheSqlSrvProfilerFileRead; |
|
94 extern TInt TheSqlSrvProfilerFileWrite; |
|
95 extern TInt TheSqlSrvProfilerFileSync; |
|
96 extern TInt TheSqlSrvProfilerFileSetSize; |
|
97 |
|
98 # define __COUNTER_INCR(counter) ++counter |
|
99 |
|
100 ////////////////////////////////////////////////////////////////////////////// |
|
101 ////////////////////////// File I/O ////////////////////////////////////////// |
|
102 ////////////////////////////////////////////////////////////////////////////// |
|
103 |
|
104 /** |
|
105 This enum is used only in _SQLPROFILER mode for tracing the file system calls. |
|
106 @internalComponent |
|
107 @see FsCallBrkPt() |
|
108 */ |
|
109 enum TFsOpType |
|
110 { |
|
111 EFsOpFileCreate, |
|
112 EFsOpFileOpen, |
|
113 EFsOpFileClose, |
|
114 EFsOpFileDelete, |
|
115 EFsOpFileRead, |
|
116 EFsOpFileWrite, |
|
117 EFsOpFileSeek, |
|
118 EFsOpFileSize, |
|
119 EFsOpFileSetSize, |
|
120 EFsOpFileSync, |
|
121 EFsOpFileDrive, |
|
122 EFsOpFileAdopt, |
|
123 EFsOpFsClose, |
|
124 EFsOpFsConnect, |
|
125 EFsOpFsGetSystemDrive, |
|
126 EFsOpFsCreatePrivatePath, |
|
127 EFsOpFsPrivatePath, |
|
128 EFsOpFsVolumeIoParam, |
|
129 EFsOpFsEntry, |
|
130 EFsOpFsAtt, |
|
131 EFsOpFileCreateTemp, |
|
132 EFsOpFileAttach, |
|
133 // |
|
134 EFsOpLast |
|
135 }; |
|
136 |
|
137 TBool TheFileIoProfileEnabled = EFalse; |
|
138 TUint32 TheFileOpCounter[EFsOpLast] = {0}; |
|
139 TInt64 TheFileWriteAmount = 0; |
|
140 TInt64 TheFileReadAmount = 0; |
|
141 |
|
142 /** |
|
143 This function is used only in _SQLPROFILER mode as an appropriate place for: |
|
144 - setting breakpoints for tracing the file system calls; |
|
145 - collection information about the number of the file system calls; |
|
146 |
|
147 @param aFsOpType A TFsOpType enum item value, identifying the file system operation that will be executed; |
|
148 @param a1 If the operation is "file read" or "file write" - the amount of data read/written; |
|
149 |
|
150 @internalComponent |
|
151 |
|
152 @see TFsOpType |
|
153 */ |
|
154 void FsCallBrkPt(TInt aFsOpType, TInt a1) |
|
155 { |
|
156 __ASSERT_DEBUG(aFsOpType >= 0 && aFsOpType < EFsOpLast, User::Invariant()); |
|
157 if(!TheFileIoProfileEnabled) |
|
158 { |
|
159 return; |
|
160 } |
|
161 TFsOpType fsOpType = (TFsOpType)aFsOpType; |
|
162 ++TheFileOpCounter[fsOpType]; |
|
163 if(fsOpType == EFsOpFileWrite) |
|
164 { |
|
165 TheFileWriteAmount += a1; |
|
166 } |
|
167 else if(fsOpType == EFsOpFileRead) |
|
168 { |
|
169 TheFileReadAmount += a1; |
|
170 } |
|
171 } |
|
172 |
|
173 # define __FS_CALL(aFsOpType, a1) FsCallBrkPt(aFsOpType, a1) |
|
174 |
|
175 ////////////////////////////////////////////////////////////////////////////// |
|
176 ////////////////////////// Heap Stats //////////////////////////////////////// |
|
177 ////////////////////////////////////////////////////////////////////////////// |
|
178 |
|
179 /** |
|
180 Memory operation type: alloc, realloc, free. Used during the profiling. |
|
181 |
|
182 @internalComponent |
|
183 */ |
|
184 enum TMemOpType |
|
185 { |
|
186 EMemOpAlloc, |
|
187 EMemOpRealloc, |
|
188 EMemOpFree, |
|
189 // |
|
190 EMemOpLast |
|
191 }; |
|
192 |
|
193 TBool TheMemProfileEnabled = EFalse;//Mem operation call counters and time counters enabled/disabled |
|
194 TBool TheMaxAllocProfileEnabled = EFalse;//Max mem allocation enabled/disabled |
|
195 TUint32 TheMemOpCounter[EMemOpLast] = {0}; |
|
196 TInt64 TheMemOpTicks[EMemOpLast] = {0}; |
|
197 TInt64 TheAllocated = 0; |
|
198 TInt64 TheFreed = 0; |
|
199 TInt TheAllocMax = 0; |
|
200 |
|
201 /** |
|
202 This class is used only in _SQLPROFILER mode as an appropriate place for: |
|
203 - setting breakpoints for tracing the memory allocation/deallocation calls; |
|
204 - collection information about the number of the memory allocation/deallocation calls and the time spent in the calls; |
|
205 |
|
206 The constructor's parameters are: |
|
207 - aOpType A TMemOpType enum item value, identifying the operation that will be executed; |
|
208 - aAmt1 The allocated/deallocated size; |
|
209 - aAmt2 Used only if a block of memory is reallocated in which case a2 is the old size of the block; |
|
210 |
|
211 @internalComponent |
|
212 |
|
213 @see TMemOpType |
|
214 */ |
|
215 class TMemCallCounter |
|
216 { |
|
217 public: |
|
218 TMemCallCounter(TMemOpType aOpType, TInt aAmt1, TInt aAmt2) : |
|
219 iOpType(aOpType), |
|
220 iStartTicks(0) |
|
221 { |
|
222 if(TheMaxAllocProfileEnabled && (iOpType == EMemOpAlloc || iOpType == EMemOpRealloc) && aAmt1 > TheAllocMax) |
|
223 { |
|
224 TheAllocMax = aAmt1; |
|
225 } |
|
226 if(TheMemProfileEnabled) |
|
227 { |
|
228 ++TheMemOpCounter[iOpType]; |
|
229 switch(iOpType) |
|
230 { |
|
231 case EMemOpAlloc: |
|
232 TheAllocated += aAmt1; |
|
233 break; |
|
234 case EMemOpRealloc: |
|
235 TheAllocated += aAmt1; |
|
236 TheFreed += aAmt2; |
|
237 break; |
|
238 case EMemOpFree: |
|
239 TheFreed += aAmt1; |
|
240 break; |
|
241 default: |
|
242 __ASSERT_DEBUG(0, User::Invariant()); |
|
243 break; |
|
244 } |
|
245 iStartTicks = User::FastCounter(); |
|
246 } |
|
247 } |
|
248 ~TMemCallCounter() |
|
249 { |
|
250 if(TheMemProfileEnabled) |
|
251 { |
|
252 TInt64 diffTicks = (TInt64)User::FastCounter() - (TInt64)iStartTicks; |
|
253 if(diffTicks < 0) |
|
254 { |
|
255 diffTicks = KMaxTUint + diffTicks + 1; |
|
256 } |
|
257 TheMemOpTicks[iOpType] += diffTicks; |
|
258 } |
|
259 } |
|
260 private: |
|
261 TMemOpType iOpType; |
|
262 TUint32 iStartTicks; |
|
263 }; |
|
264 |
|
265 # define __MEM_CALL(aMemOpType, a1, a2) TMemCallCounter memCallCounter(aMemOpType, a1, a2) |
|
266 |
|
267 ////////////////////////////////////////////////////////////////////////////// |
|
268 ////////////////////////// OS layer calls //////////////////////////////////// |
|
269 ////////////////////////////////////////////////////////////////////////////// |
|
270 |
|
271 //The OS porting layer call types |
|
272 enum TOsOpType |
|
273 { |
|
274 EOsFileClose, |
|
275 EOsFileRead, |
|
276 EOsFileWrite, |
|
277 EOsFileTruncate, |
|
278 EOsFileSync, |
|
279 EOsFileFileSize, |
|
280 EOsFileLock, |
|
281 EOsFileUnlock, |
|
282 EOsFileCheckReservedLock, |
|
283 EOsFileFileControl, |
|
284 EOsFileSectorSize, |
|
285 EOsFileDeviceCharacteristics, |
|
286 // |
|
287 EOsVfsOpen, |
|
288 EOsVfsDelete, |
|
289 EOsVfsAccess, |
|
290 EOsVfsFullPathName, |
|
291 EOsVfsRandomness, |
|
292 EOsVfsSleep, |
|
293 EOsVfsCurrentTime, |
|
294 EOsVfsGetLastError, |
|
295 // |
|
296 EOsOpLast |
|
297 }; |
|
298 |
|
299 TBool TheOsProfileEnabled = EFalse; |
|
300 TUint32 TheOsOpCounter[EOsOpLast] = {0};//Each entry is a counter - how many times specific OS porting layer function has been called |
|
301 |
|
302 # define __OS_CALL(aOsOpType, a1, a2) \ |
|
303 do \ |
|
304 { \ |
|
305 if(TheOsProfileEnabled) \ |
|
306 { \ |
|
307 ++TheOsOpCounter[aOsOpType];\ |
|
308 } \ |
|
309 } \ |
|
310 while(0) |
|
311 |
|
312 ////////////////////////////////////////////////////////////////////////////// |
|
313 ////////////////////////// OS layer timings ////////////////////////////////// |
|
314 ////////////////////////////////////////////////////////////////////////////// |
|
315 |
|
316 TBool TheOsCallTimeProfileEnabled = EFalse;//If true, the OS porting layer call timings are enabled. |
|
317 TInt64 TheOsCallTicks[EOsOpLast];//Each entry represents the time in ticks spent in a specific OS porting layer function, |
|
318 //disregarding the file type (main or journal) |
|
319 |
|
320 TBool TheOsCallTimeDetailedProfileEnabled = EFalse;//If true, the OS porting layer call details are enabled and for each call an entry will be added to the log file (epocwind.out). |
|
321 TInt TheOpCounter = 0;//Operations counter. Each OS porting layer function call increments the counter. |
|
322 |
|
323 //Used for storing the OS call details: |
|
324 // - iType - on which file the call has been made: main database file - 'M', or journal file - 'J'; |
|
325 // - iIdentifier - two letters identifying the monitored OS porting layer function; |
|
326 // - iCallCounter - how many times the monitored OS porting layer function has been called; |
|
327 // - iTicksTotal - the total amount of time in ticks spent in the monitored OS porting layer function; |
|
328 // - iBytesTotal - the total amount of bytes passed to the monitored OS porting layer function (if it is read or write); |
|
329 struct TOsCallProfile |
|
330 { |
|
331 TOsCallProfile(char aType, char aIdentifier[]) : |
|
332 iType(aType), |
|
333 iCallCounter(0), |
|
334 iTicksTotal(0), |
|
335 iBytesTotal(0) |
|
336 { |
|
337 iIdentifier[0] = aIdentifier[0]; |
|
338 iIdentifier[1] = aIdentifier[1]; |
|
339 } |
|
340 void Zero() |
|
341 { |
|
342 iCallCounter = 0; |
|
343 iTicksTotal = 0; |
|
344 iBytesTotal = 0; |
|
345 } |
|
346 char iType; |
|
347 char iIdentifier[2]; |
|
348 TInt iCallCounter; |
|
349 TInt64 iTicksTotal; |
|
350 TInt64 iBytesTotal; |
|
351 }; |
|
352 |
|
353 //An array of TOsCallProfile entries, each entry keeps the profile of a specifc OS porting layer function, when |
|
354 //the function was used on the main database file |
|
355 TOsCallProfile TheOsCallMProfile[EOsOpLast] = |
|
356 { |
|
357 TOsCallProfile('M', "CL"), TOsCallProfile('M', "RD"), TOsCallProfile('M', "WR"), TOsCallProfile('M', "TR"), |
|
358 TOsCallProfile('M', "SY"), TOsCallProfile('M', "FS"), TOsCallProfile('M', "LK"), TOsCallProfile('M', "UL"), |
|
359 TOsCallProfile('M', "CL"), TOsCallProfile('M', "FC"), TOsCallProfile('M', "SS"), TOsCallProfile('M', "DC"), |
|
360 TOsCallProfile('M', "OP"), TOsCallProfile('M', "DE"), TOsCallProfile('M', "AC"), TOsCallProfile('M', "FN"), |
|
361 TOsCallProfile('M', "RN"), TOsCallProfile('M', "SL"), TOsCallProfile('M', "CT"), TOsCallProfile('M', "LE") |
|
362 }; |
|
363 |
|
364 //An array of TOsCallProfile entries, each entry keeps the profile of a specifc OS porting layer function, when |
|
365 //the function was used on the journal file |
|
366 TOsCallProfile TheOsCallJProfile[EOsOpLast] = |
|
367 { |
|
368 TOsCallProfile('J', "CL"), TOsCallProfile('J', "RD"), TOsCallProfile('J', "WR"), TOsCallProfile('J', "TR"), |
|
369 TOsCallProfile('J', "SY"), TOsCallProfile('J', "FS"), TOsCallProfile('J', "LK"), TOsCallProfile('J', "UL"), |
|
370 TOsCallProfile('J', "CL"), TOsCallProfile('J', "FC"), TOsCallProfile('J', "SS"), TOsCallProfile('J', "DC"), |
|
371 TOsCallProfile('J', "OP"), TOsCallProfile('J', "DE"), TOsCallProfile('J', "AC"), TOsCallProfile('J', "FN"), |
|
372 TOsCallProfile('J', "RN"), TOsCallProfile('J', "SL"), TOsCallProfile('J', "CT"), TOsCallProfile('J', "LE") |
|
373 }; |
|
374 |
|
375 //The main class for the OS porting layer call profiles. |
|
376 class TOsCallCounter |
|
377 { |
|
378 public: |
|
379 //aOsCallTicksEntryRef - a reference to the related TheOsCallTicks[] entry; |
|
380 //aProfileRef - a reference to the related TOsCallProfile object - TheOsCallMProfile[] or TheOsCallJProfile[] entry; |
|
381 //aOffset - file offset in bytes; |
|
382 //aBytes - amount of bytes to be read/written; |
|
383 TOsCallCounter(TInt64& aOsCallTicksEntryRef, TOsCallProfile& aOsCallProfileRef, TInt64 aOffset, TInt aBytes) : |
|
384 iOsCallTicksEntryRef(aOsCallTicksEntryRef), |
|
385 iOsCallProfileRef(aOsCallProfileRef), |
|
386 iOffset(aOffset), |
|
387 iBytes(aBytes) |
|
388 { |
|
389 if(TheOsCallTimeProfileEnabled) |
|
390 { |
|
391 iStartTicks = User::FastCounter(); |
|
392 } |
|
393 } |
|
394 ~TOsCallCounter() |
|
395 { |
|
396 if(TheOsCallTimeProfileEnabled) |
|
397 { |
|
398 TInt64 diffTicks = (TInt64)User::FastCounter() - (TInt64)iStartTicks; |
|
399 if(diffTicks < 0) |
|
400 { |
|
401 diffTicks = KMaxTUint + diffTicks + 1; |
|
402 } |
|
403 iOsCallTicksEntryRef += diffTicks; |
|
404 if(TheOsCallTimeDetailedProfileEnabled) |
|
405 { |
|
406 ++TheOpCounter; |
|
407 ++iOsCallProfileRef.iCallCounter; |
|
408 iOsCallProfileRef.iTicksTotal += diffTicks; |
|
409 iOsCallProfileRef.iBytesTotal += iBytes; |
|
410 // 1 2 3 4 5 6 7 8 9 10 |
|
411 RDebug::Print(_L("'%c','%c%c',%d,%d,%ld,%d,%ld,%ld,%ld\n"), |
|
412 iOsCallProfileRef.iType, //1 |
|
413 iOsCallProfileRef.iIdentifier[0], //2 |
|
414 iOsCallProfileRef.iIdentifier[1], //3 |
|
415 TheOpCounter, //4 |
|
416 iOsCallProfileRef.iCallCounter, //5 |
|
417 iOffset, //6 |
|
418 iBytes, //7 |
|
419 diffTicks, //8 |
|
420 iOsCallProfileRef.iBytesTotal, //9 |
|
421 iOsCallProfileRef.iTicksTotal); //10 |
|
422 } |
|
423 } |
|
424 } |
|
425 private: |
|
426 TInt64& iOsCallTicksEntryRef; |
|
427 TOsCallProfile& iOsCallProfileRef; |
|
428 TInt64 iOffset; |
|
429 TInt iBytes; |
|
430 TUint32 iStartTicks; |
|
431 }; |
|
432 |
|
433 inline TOsCallProfile& OsCallProfile(TBool aType, TInt aIndex) |
|
434 { |
|
435 return aType ? TheOsCallJProfile[aIndex] : TheOsCallMProfile[aIndex]; |
|
436 } |
|
437 |
|
438 # define __OSTIME_COUNTER(aOsCallTicksRef, aOsCallProfileRef, aOffset, aBytes) TOsCallCounter osCallCounter(aOsCallTicksRef, aOsCallProfileRef, aOffset, aBytes) |
|
439 |
|
440 #else //_SQLPROFILER |
|
441 |
|
442 # define __COUNTER_INCR(counter) void(0) |
|
443 |
|
444 # define __FS_CALL(aFsOpType, a1) void(0) |
|
445 |
|
446 # define __MEM_CALL(aMemOpType, a1, a2) void(0) |
|
447 |
|
448 # define __OS_CALL(aOpType, a1, a2) void(0) |
|
449 |
|
450 # define __OSTIME_COUNTER(aOsCallTicksRef, aOsCallProfileRef, aOffset, aBytes) void(0) |
|
451 |
|
452 #endif//_SQLPROFILER |
|
453 |
|
454 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
455 ///////////////////// Profiling //////////////////////////////////////////////////////////////// |
|
456 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
457 |
|
458 #ifdef _SQLPROFILER |
|
459 |
|
460 const TInt KMicroSecIn1Sec = 1000000; |
|
461 |
|
462 TInt FastCounterFrequency() |
|
463 { |
|
464 TInt ticksPerSec = 0; |
|
465 TInt err = HAL::Get(HAL::EFastCounterFrequency, ticksPerSec); |
|
466 __ASSERT_ALWAYS(err == KErrNone, User::Panic(KPanicCategory, EPanicFastCounterFreq)); |
|
467 return ticksPerSec; |
|
468 } |
|
469 |
|
470 TInt sqlite3SymbianProfilerStart(TInt aCounterType) |
|
471 { |
|
472 const TSqlResourceProfiler::TSqlCounter KCounterType = static_cast <TSqlResourceProfiler::TSqlCounter> (aCounterType); |
|
473 switch(KCounterType) |
|
474 { |
|
475 case TSqlResourceProfiler::ESqlCounterFileIO: |
|
476 TheFileIoProfileEnabled = ETrue; |
|
477 break; |
|
478 case TSqlResourceProfiler::ESqlCounterOsCall: |
|
479 TheOsProfileEnabled = ETrue; |
|
480 break; |
|
481 case TSqlResourceProfiler::ESqlCounterOsCallTime: |
|
482 TheOsCallTimeProfileEnabled = ETrue; |
|
483 break; |
|
484 case TSqlResourceProfiler::ESqlCounterOsCallDetails: |
|
485 TheOsCallTimeProfileEnabled = ETrue; |
|
486 TheOsCallTimeDetailedProfileEnabled = ETrue; |
|
487 break; |
|
488 case TSqlResourceProfiler::ESqlCounterMemory: |
|
489 TheMemProfileEnabled = ETrue; |
|
490 break; |
|
491 case TSqlResourceProfiler::ESqlCounterMaxAlloc: |
|
492 TheMaxAllocProfileEnabled = ETrue; |
|
493 break; |
|
494 default: |
|
495 return KErrNotSupported; |
|
496 } |
|
497 return KErrNone; |
|
498 } |
|
499 |
|
500 TInt sqlite3SymbianProfilerStop(TInt aCounterType) |
|
501 { |
|
502 const TSqlResourceProfiler::TSqlCounter KCounterType = static_cast <TSqlResourceProfiler::TSqlCounter> (aCounterType); |
|
503 switch(KCounterType) |
|
504 { |
|
505 case TSqlResourceProfiler::ESqlCounterFileIO: |
|
506 TheFileIoProfileEnabled = EFalse; |
|
507 break; |
|
508 case TSqlResourceProfiler::ESqlCounterOsCall: |
|
509 TheOsProfileEnabled = EFalse; |
|
510 break; |
|
511 case TSqlResourceProfiler::ESqlCounterOsCallTime: |
|
512 TheOsCallTimeProfileEnabled = EFalse; |
|
513 break; |
|
514 case TSqlResourceProfiler::ESqlCounterOsCallDetails: |
|
515 TheOsCallTimeDetailedProfileEnabled = EFalse; |
|
516 TheOsCallTimeProfileEnabled = EFalse; |
|
517 break; |
|
518 case TSqlResourceProfiler::ESqlCounterMemory: |
|
519 TheMemProfileEnabled = EFalse; |
|
520 break; |
|
521 case TSqlResourceProfiler::ESqlCounterMaxAlloc: |
|
522 TheMaxAllocProfileEnabled = EFalse; |
|
523 break; |
|
524 default: |
|
525 return KErrNotSupported; |
|
526 } |
|
527 return KErrNone; |
|
528 } |
|
529 |
|
530 TInt sqlite3SymbianProfilerReset(TInt aCounterType) |
|
531 { |
|
532 const TSqlResourceProfiler::TSqlCounter KCounterType = static_cast <TSqlResourceProfiler::TSqlCounter> (aCounterType); |
|
533 switch(KCounterType) |
|
534 { |
|
535 case TSqlResourceProfiler::ESqlCounterFileIO: |
|
536 Mem::FillZ(TheFileOpCounter, sizeof(TheFileOpCounter)); |
|
537 TheFileWriteAmount = TheFileReadAmount = 0; |
|
538 break; |
|
539 case TSqlResourceProfiler::ESqlCounterOsCall: |
|
540 Mem::FillZ(TheOsOpCounter, sizeof(TheOsOpCounter)); |
|
541 break; |
|
542 case TSqlResourceProfiler::ESqlCounterOsCallTime: |
|
543 case TSqlResourceProfiler::ESqlCounterOsCallDetails: |
|
544 TheOpCounter = 0; |
|
545 Mem::FillZ(TheOsCallTicks, sizeof(TheOsCallTicks)); |
|
546 for(TInt i=0;i<EOsOpLast;++i) |
|
547 { |
|
548 TheOsCallMProfile[i].Zero(); |
|
549 TheOsCallJProfile[i].Zero(); |
|
550 } |
|
551 break; |
|
552 case TSqlResourceProfiler::ESqlCounterMemory: |
|
553 Mem::FillZ(TheMemOpCounter, sizeof(TheMemOpCounter)); |
|
554 Mem::FillZ(TheMemOpTicks, sizeof(TheMemOpTicks)); |
|
555 TheAllocated = TheFreed = 0; |
|
556 break; |
|
557 case TSqlResourceProfiler::ESqlCounterMaxAlloc: |
|
558 TheAllocMax = 0; |
|
559 break; |
|
560 default: |
|
561 return KErrNotSupported; |
|
562 } |
|
563 return KErrNone; |
|
564 } |
|
565 |
|
566 TInt sqlite3SymbianProfilerQuery(TInt aCounterType, TDes8& aResult) |
|
567 { |
|
568 const TSqlResourceProfiler::TSqlCounter KCounterType = static_cast <TSqlResourceProfiler::TSqlCounter> (aCounterType); |
|
569 switch(KCounterType) |
|
570 { |
|
571 case TSqlResourceProfiler::ESqlCounterFileIO: |
|
572 for(TInt i=0;i<EFsOpLast;++i) |
|
573 { |
|
574 aResult.AppendNum(TheFileOpCounter[i]); |
|
575 aResult.Append(TChar(';')); |
|
576 } |
|
577 aResult.AppendNum(TheFileWriteAmount); |
|
578 aResult.Append(TChar(';')); |
|
579 aResult.AppendNum(TheFileReadAmount); |
|
580 aResult.Append(TChar(';')); |
|
581 break; |
|
582 case TSqlResourceProfiler::ESqlCounterOsCall: |
|
583 for(TInt i=0;i<EOsOpLast;++i) |
|
584 { |
|
585 aResult.AppendNum(TheOsOpCounter[i]); |
|
586 aResult.Append(TChar(';')); |
|
587 } |
|
588 break; |
|
589 case TSqlResourceProfiler::ESqlCounterOsCallTime: |
|
590 case TSqlResourceProfiler::ESqlCounterOsCallDetails: |
|
591 { |
|
592 TInt ticksPerSec = FastCounterFrequency(); |
|
593 for(TInt i=0;i<EOsOpLast;++i) |
|
594 { |
|
595 TInt64 osCallTimeUs = (TheOsCallTicks[i] * KMicroSecIn1Sec) / ticksPerSec; |
|
596 aResult.AppendNum(osCallTimeUs); |
|
597 aResult.Append(TChar(';')); |
|
598 } |
|
599 } |
|
600 break; |
|
601 case TSqlResourceProfiler::ESqlCounterMemory: |
|
602 aResult.AppendNum(TheMemOpCounter[EMemOpAlloc]); |
|
603 aResult.Append(TChar(';')); |
|
604 aResult.AppendNum(TheMemOpCounter[EMemOpRealloc]); |
|
605 aResult.Append(TChar(';')); |
|
606 aResult.AppendNum(TheMemOpCounter[EMemOpFree]); |
|
607 aResult.Append(TChar(';')); |
|
608 aResult.AppendNum(TheAllocated); |
|
609 aResult.Append(TChar(';')); |
|
610 aResult.AppendNum(TheFreed); |
|
611 aResult.Append(TChar(';')); |
|
612 { |
|
613 TInt ticksPerSec = FastCounterFrequency(); |
|
614 TInt64 memOpCallTimeUs = (TheMemOpTicks[EMemOpAlloc] * KMicroSecIn1Sec) / ticksPerSec; |
|
615 aResult.AppendNum(memOpCallTimeUs); |
|
616 aResult.Append(TChar(';')); |
|
617 memOpCallTimeUs = (TheMemOpTicks[EMemOpRealloc] * KMicroSecIn1Sec) / ticksPerSec; |
|
618 aResult.AppendNum(memOpCallTimeUs); |
|
619 aResult.Append(TChar(';')); |
|
620 memOpCallTimeUs = (TheMemOpTicks[EMemOpFree] * KMicroSecIn1Sec) / ticksPerSec; |
|
621 aResult.AppendNum(memOpCallTimeUs); |
|
622 aResult.Append(TChar(';')); |
|
623 } |
|
624 break; |
|
625 case TSqlResourceProfiler::ESqlCounterMaxAlloc: |
|
626 aResult.AppendNum(TheAllocMax); |
|
627 aResult.Append(TChar(';')); |
|
628 break; |
|
629 default: |
|
630 return KErrNotSupported; |
|
631 } |
|
632 return KErrNone; |
|
633 } |
|
634 |
|
635 #else//_SQLPROFILER |
|
636 |
|
637 TInt sqlite3SymbianProfilerStart(TInt) |
|
638 { |
|
639 return KErrNotSupported; |
|
640 } |
|
641 |
|
642 TInt sqlite3SymbianProfilerStop(TInt) |
|
643 { |
|
644 return KErrNotSupported; |
|
645 } |
|
646 |
|
647 TInt sqlite3SymbianProfilerReset(TInt) |
|
648 { |
|
649 return KErrNotSupported; |
|
650 } |
|
651 |
|
652 TInt sqlite3SymbianProfilerQuery(TInt, TDes8&) |
|
653 { |
|
654 return KErrNotSupported; |
|
655 } |
|
656 |
|
657 #endif//_SQLPROFILER |
|
658 |
|
659 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
660 ///////////////////// COsLayerData class declaration ////////////////////////////////////////////////////////////////// |
|
661 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
662 |
|
663 /** |
|
664 COsLayerData singleton class manages a single SQLite OS layer copy of the following data: |
|
665 @code |
|
666 - file session instance; |
|
667 - process's private data path, where the temporary file will be stored (on the system drive); |
|
668 - the last OS error code, every Symbian OS API call (file system calls, etc.) will set it; |
|
669 - the stored OS error code, initialized with the last OS error code only if stored OS error code is KErrNone. |
|
670 Each StoredOsErrorCode() call will reset it to KErrNone; |
|
671 The reason of having two data members for storing the OS error codes is that if there is just one variable |
|
672 and it gets initialized with the error value reported by a failed OS API call, the next successful OS API |
|
673 call will reset it and the COsLayerData client will miss the last "real" OS API error. |
|
674 - A pointer to the current RMessage2 object, if the current operation is "open a private secure database"; |
|
675 - A boolean flag - iReadOnly - used only for private secure databases, indicating whether the database is read-only or not; |
|
676 @endcode |
|
677 |
|
678 @internalComponent |
|
679 */ |
|
680 NONSHARABLE_CLASS(COsLayerData) |
|
681 { |
|
682 public: |
|
683 static TInt Create(); |
|
684 static inline void Destroy(); |
|
685 static inline COsLayerData& Instance(); |
|
686 |
|
687 inline TInt SetOsErrorCode(TInt aError); |
|
688 inline TInt StoredOsErrorCode(); |
|
689 |
|
690 inline void StoreFhData(const RMessage2* aMsg, TBool aReadOnly); |
|
691 inline void RetrieveAndResetFhData(const RMessage2*& aMsg, TBool& aReadOnly); |
|
692 |
|
693 private: |
|
694 inline COsLayerData(); |
|
695 inline ~COsLayerData(); |
|
696 TInt DoCreate(); |
|
697 |
|
698 public: |
|
699 RFs iFs; //File session instance. |
|
700 TFileName iSysPrivDir;//"<system drive>:\" + process's private data path. Initialized in sqlite3SymbianFsOpen(). |
|
701 //Used for storing sqlite temporary files. |
|
702 TInt64 iSeed; |
|
703 RAllocator* iAllocator; |
|
704 |
|
705 enum {KZeroBufSize = SQLITE_DEFAULT_SECTOR_SIZE}; |
|
706 TBuf8<KZeroBufSize> iZeroBuf; |
|
707 |
|
708 private: |
|
709 static COsLayerData* iOsLayerData; |
|
710 TInt iStoredOsErrorCode; //Contains the last OS error code. |
|
711 const RMessage2* iMessage; //Fh data |
|
712 TBool iReadOnly; //Fh data |
|
713 }; |
|
714 |
|
715 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
716 /////////////////////////////////// TDbFile struct declaration ///////////////////////////////////////////////////// |
|
717 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
718 |
|
719 /** |
|
720 TDbFile derives from the sqlite3_file structure, adding data members needed for processing the SQLite requests to the OS layer. |
|
721 When SQLite needs an access to a file, SQLite allocates memory for a new TDbFile instance and passes a pointer to that |
|
722 instance to TVfs::Open(). TVfs::Open() creates/opens the file and initializes the TDbFile instance. |
|
723 SQLite uses the initialized TDbFile instance (actually SQLite knows and uses the sqlite3_file, the base structure) |
|
724 every time when needs to read or write from/to the file, using for that an appropriate TFileIo method. |
|
725 |
|
726 Note: currently RFileBuf64 object is used instead of RFile64. That improves the read/write file performance. |
|
727 |
|
728 No virtual methods here! sqlite3_file contains data members. If a virtual method is added, that will shift the offset of the |
|
729 data members from the beginning of the sqlite3_file object by 4 bytes. This is not what SQLite (C code) expects. |
|
730 |
|
731 @internalComponent |
|
732 |
|
733 @see TVfs |
|
734 @see TFileIo |
|
735 @see TVfs::Open() |
|
736 */ |
|
737 NONSHARABLE_STRUCT(TDbFile) : public sqlite3_file |
|
738 { |
|
739 inline TDbFile(); |
|
740 RFileBuf64 iFileBuf; |
|
741 HBufC* iFullName; //Used for the "delete file" operation (RFile64::FullName() makes an IPC call!) |
|
742 TInt iLockType; //File lock type |
|
743 TBool iReadOnly; //True if the file is read-only |
|
744 TInt iSectorSize; //Media sector-size |
|
745 TInt iDeviceCharacteristics; |
|
746 TSqlFreePageCallback iFreePageCallback; |
|
747 #ifdef _SQLPROFILER |
|
748 TBool iIsJournal; |
|
749 #endif |
|
750 }; |
|
751 |
|
752 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
753 /////////////////////////////////// TFileIo class declaration ////////////////////////////////////////////////////// |
|
754 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
755 |
|
756 /** |
|
757 TFileIo class offers static methods for performing operations on a file. |
|
758 Every TFileIo method has a pointer to a sqlite3_file instance (so, a TDbFile instance) as its first argument. |
|
759 |
|
760 SQLite never accesses the file system directly, only through function pointers, data members of the sqlite3_io_methods structure. |
|
761 The OS porting layer defines a single instance of sqlite3_io_methods structure, TheFileIoApi, and uses the TFileIo to initialize the |
|
762 sqlite3_io_methods data members (function pointers). |
|
763 Every time when SQLite creates/opens a file using TVfs::Open(), TVfs::Open() will pass back to SQLite a pointer to the single |
|
764 initialized sqlite3_io_methods instance (TheFileIoApi) that will be used later by SQLite for accessing the file. |
|
765 |
|
766 @internalComponent |
|
767 |
|
768 @see TVfs |
|
769 @see TVfs::Open() |
|
770 @see TheFileIoApi |
|
771 @see TDbFile |
|
772 */ |
|
773 NONSHARABLE_CLASS(TFileIo) |
|
774 { |
|
775 public: |
|
776 static int Close(sqlite3_file* aDbFile); |
|
777 static int Read(sqlite3_file* aDbFile, void* aBuf, int aAmt, sqlite3_int64 aOffset); |
|
778 static int Write(sqlite3_file* aDbFile, const void* aData, int aAmt, sqlite3_int64 aOffset); |
|
779 static int Truncate(sqlite3_file* aDbFile, sqlite3_int64 aLength); |
|
780 static int Sync(sqlite3_file* aDbFile, int aFlags); |
|
781 static int FileSize(sqlite3_file* aDbFile, sqlite3_int64* aSize); |
|
782 static int Lock(sqlite3_file* aDbFile, int aLockType); |
|
783 static int Unlock(sqlite3_file* aDbFile, int aLockType); |
|
784 static int CheckReservedLock(sqlite3_file* aDbFile, int *aResOut); |
|
785 static int FileControl(sqlite3_file* aDbFile, int aOp, void* aArg); |
|
786 static int SectorSize(sqlite3_file* aDbFile); |
|
787 static int DeviceCharacteristics(sqlite3_file* aDbFile); |
|
788 }; |
|
789 |
|
790 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
791 /////////////////////////////////// TVfs class declaration ///////////////////////////////////////////////////////// |
|
792 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
793 |
|
794 /** |
|
795 TVfs ("VFS" - virtual file system) class offers methods for creating/openning a file, deleting a file, |
|
796 a "sleep" method, a "time" method, a "rand" method, etc. |
|
797 SQLite never accesses the OS API directly, only through the API offered by TVfs and TFileIo classes. |
|
798 |
|
799 @internalComponent |
|
800 |
|
801 @see TFileIo |
|
802 @see TheVfsApi |
|
803 @see COsLayerData |
|
804 */ |
|
805 NONSHARABLE_CLASS(TVfs) |
|
806 { |
|
807 public: |
|
808 static int Open(sqlite3_vfs* aVfs, const char* aFileName, sqlite3_file* aDbFile, int aFlags, int* aOutFlags); |
|
809 static int Delete(sqlite3_vfs* aVfs, const char* aFileName, int aSyncDir); |
|
810 static int Access(sqlite3_vfs* aVfs, const char* aFileName, int aFlags, int* aResOut); |
|
811 static int FullPathName(sqlite3_vfs* aVfs, const char* aRelative, int aBufLen, char* aBuf); |
|
812 static int Randomness(sqlite3_vfs* aVfs, int aBufLen, char* aBuf); |
|
813 static int Sleep(sqlite3_vfs* aVfs, int aMicrosec); |
|
814 static int CurrentTime(sqlite3_vfs* aVfs, double* aNow); |
|
815 static int GetLastError(sqlite3_vfs *sVfs, int aBufLen, char* aBuf); |
|
816 private: |
|
817 static TInt DoOpenFromHandle(TDbFile& aDbFile, const RMessage2& aMsg, TBool aReadOnly); |
|
818 static inline TInt DoGetVolumeIoParamInfo(RFs& aFs, TInt aDriveNo, TVolumeIOParamInfo& aVolumeInfo); |
|
819 static TInt DoGetDeviceCharacteristics(const TDriveInfo& aDriveInfo, const TVolumeIOParamInfo& aVolumeInfo); |
|
820 static TInt DoGetSectorSize(const TDriveInfo& aDriveInfo, const TVolumeIOParamInfo& aVolumeInfo); |
|
821 static TInt DoGetDeviceCharacteristicsAndSectorSize(TDbFile& aDbFile, TInt& aRecReadBufSize); |
|
822 |
|
823 }; |
|
824 |
|
825 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
826 ///////////////////// Global variables, constants //////////////////////////////////////////////////////////////////// |
|
827 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
828 |
|
829 // The following macro specifies the size of the RFileBuf64 file buffer in KB: |
|
830 // __SQLITE_OS_SYMBIAN_FILEBUF_KBSIZE__ |
|
831 // |
|
832 // If not set, a default value of 8 is used |
|
833 #if !defined(__SQLITE_OS_SYMBIAN_FILEBUF_KBSIZE__) |
|
834 #define __SQLITE_OS_SYMBIAN_FILEBUF_KBSIZE__ 8 |
|
835 #endif |
|
836 const TInt KFileBufSize = __SQLITE_OS_SYMBIAN_FILEBUF_KBSIZE__ * 1024; |
|
837 |
|
838 /** |
|
839 Pointer to the single COsLayerData instance. |
|
840 |
|
841 @see COsLayerData |
|
842 |
|
843 @internalComponent |
|
844 */ |
|
845 COsLayerData* COsLayerData::iOsLayerData = NULL; |
|
846 |
|
847 /** |
|
848 Single sqlite3_io_methods instance, which data members (function pointers) are initialized with the addresses of |
|
849 TFileIo members. |
|
850 TheFileIoApi is used by SQLite for performing OS independent file I/O. |
|
851 |
|
852 @see TFileIo |
|
853 @see TVfs |
|
854 |
|
855 @internalComponent |
|
856 */ |
|
857 static sqlite3_io_methods TheFileIoApi = |
|
858 { |
|
859 1, //Version |
|
860 &TFileIo::Close, |
|
861 &TFileIo::Read, |
|
862 &TFileIo::Write, |
|
863 &TFileIo::Truncate, |
|
864 &TFileIo::Sync, |
|
865 &TFileIo::FileSize, |
|
866 &TFileIo::Lock, |
|
867 &TFileIo::Unlock, |
|
868 &TFileIo::CheckReservedLock, |
|
869 &TFileIo::FileControl, |
|
870 &TFileIo::SectorSize, |
|
871 &TFileIo::DeviceCharacteristics |
|
872 }; |
|
873 |
|
874 /** |
|
875 Single sqlite3_vfs instance, which data members (function pointers) are initialized with the addresses of |
|
876 TVfs members. TheVfsApi also keeps information regarding some other OS dependend characteristics like |
|
877 the TDbFile size and max file name length. |
|
878 TheVfsApi is used by SQLite for accessing needed OS API. |
|
879 |
|
880 TheVfsApi can't be a constant definition. SQLite expects the "sqlite3_vfs" object to be a R/W one, because |
|
881 SQLite may have and use a chain of sqlite3_vfs instances. |
|
882 |
|
883 @see TVfs |
|
884 @see TTFileIo |
|
885 @see TDbFile |
|
886 |
|
887 @internalComponent |
|
888 */ |
|
889 static sqlite3_vfs TheVfsApi = |
|
890 { |
|
891 1, //iVersion |
|
892 sizeof(TDbFile), //szOsFile |
|
893 KMaxFileName, //mxPathname |
|
894 0, //pNext |
|
895 "SymbianSql", //zName |
|
896 0, //pAppData |
|
897 &TVfs::Open, |
|
898 &TVfs::Delete, |
|
899 &TVfs::Access, |
|
900 &TVfs::FullPathName, |
|
901 0, |
|
902 0, |
|
903 0, |
|
904 0, |
|
905 &TVfs::Randomness, |
|
906 &TVfs::Sleep, |
|
907 &TVfs::CurrentTime, |
|
908 &TVfs::GetLastError |
|
909 }; |
|
910 |
|
911 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
912 ///////////////////// COsLayerData class definition ////////////////////////////////////////////////////////////////// |
|
913 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
914 |
|
915 /** |
|
916 Creates a single COsLayerData instance. |
|
917 |
|
918 @return KErrNone, The operation has completed succesfully; |
|
919 KErrNoMemory, Out of memory condition has occured; |
|
920 Note that other system-wide error codes may also be returned. |
|
921 |
|
922 @panic Sqlite 16 In _DEBUG mode - the COsLayerData instance has been created already. |
|
923 */ |
|
924 /* static */ TInt COsLayerData::Create() |
|
925 { |
|
926 __ASSERT_DEBUG(!COsLayerData::iOsLayerData, User::Panic(KPanicCategory, EPanicOsLayerDataExists)); |
|
927 if(!COsLayerData::iOsLayerData) |
|
928 { |
|
929 COsLayerData::iOsLayerData = new COsLayerData; |
|
930 if(!COsLayerData::iOsLayerData) |
|
931 { |
|
932 return KErrNoMemory; |
|
933 } |
|
934 TInt err = COsLayerData::iOsLayerData->DoCreate(); |
|
935 if(err != KErrNone) |
|
936 { |
|
937 delete COsLayerData::iOsLayerData; |
|
938 COsLayerData::iOsLayerData = NULL; |
|
939 return err; |
|
940 } |
|
941 } |
|
942 return KErrNone; |
|
943 } |
|
944 |
|
945 /** |
|
946 Destroys the COsLayerData instance. |
|
947 */ |
|
948 /* static */ inline void COsLayerData::Destroy() |
|
949 { |
|
950 delete COsLayerData::iOsLayerData; |
|
951 COsLayerData::iOsLayerData = NULL; |
|
952 } |
|
953 |
|
954 /** |
|
955 Returns a reference to the single COsLayerData instance. |
|
956 |
|
957 @panic Sqlite 1 In _DEBUG mode if the COsLayerData instance is NULL. |
|
958 */ |
|
959 /* static */ inline COsLayerData& COsLayerData::Instance() |
|
960 { |
|
961 __ASSERT_DEBUG(COsLayerData::iOsLayerData != NULL, User::Panic(KPanicCategory, EPanicNullOsLayerDataPtr)); |
|
962 return *COsLayerData::iOsLayerData; |
|
963 } |
|
964 |
|
965 /** |
|
966 Sets the last OS error code data member. The stored OS error code data member will be set only if it is |
|
967 KErrNone. (If it is not KErrNone it means that its value has not been accessed yet) |
|
968 An exception from the rule described above is KErrDiskFull error which, if happens, will be set always, because |
|
969 this error has a special meaning for the database clients - special actions may have to be taken if the |
|
970 disk is full. |
|
971 |
|
972 @param aError The OS error code |
|
973 @return The OS error code |
|
974 */ |
|
975 inline TInt COsLayerData::SetOsErrorCode(TInt aError) |
|
976 { |
|
977 if(iStoredOsErrorCode == KErrNone || aError == KErrDiskFull) |
|
978 { |
|
979 iStoredOsErrorCode = aError; |
|
980 } |
|
981 return aError; |
|
982 } |
|
983 |
|
984 /** |
|
985 Returns the last stored OS error code, which was stored by SetOsErrorCode() call. |
|
986 The function also resets the stored OS error code to KErrNone. |
|
987 |
|
988 @return The last stored OS error code |
|
989 */ |
|
990 inline TInt COsLayerData::StoredOsErrorCode() |
|
991 { |
|
992 TInt err = iStoredOsErrorCode; |
|
993 iStoredOsErrorCode = KErrNone; |
|
994 return err; |
|
995 } |
|
996 |
|
997 /** |
|
998 Stores the RMessage2 object address, file and file session handles and the read-only flag for later use when SQLite issues a |
|
999 request for open the database file (private secure database). |
|
1000 |
|
1001 The aMsg argument of the function can be NULL, because this fucntion is also used to reset the stored "file handle" data. |
|
1002 |
|
1003 How this function is used: |
|
1004 1) When the SQL server receives a request to establish a connection with private secure database, the SQL server |
|
1005 will add additional information to the private secure database file name, such as: |
|
1006 - the file handle (the private secure database is opened by the client side dll - sqldb.dll); |
|
1007 - a pointer to the RMessage2 object used in this request; |
|
1008 2) The passed additional information will be used for adopting the file handle by calling RFile64::AdoptFromClient(). |
|
1009 3) Before calling TVfs::Open() to establish a connection with the database, SQLite will call TVfs::FullPathName() |
|
1010 to retrieve the database file full path |
|
1011 4) TVfs::FullPathName() will detect that the file name contains an additional information and will extraxt the information |
|
1012 calling COsLayerData::StoreFhData(). |
|
1013 5) After TVfs::FullPathName() SQLite calls TVfs::Open() where the extracted information will be used for adopting the file handle |
|
1014 |
|
1015 @param aMsg A pointer to the current RMessage2 object |
|
1016 @param aReadOnly True if the private secure database is read-only |
|
1017 */ |
|
1018 inline void COsLayerData::StoreFhData(const RMessage2* aMsg, TBool aReadOnly) |
|
1019 { |
|
1020 iMessage = aMsg; |
|
1021 iReadOnly = aReadOnly; |
|
1022 } |
|
1023 |
|
1024 /** |
|
1025 Retrieves the RMessage2 object, file and file session handles. The stored data will be reset. |
|
1026 This function is used by TVfs::Open(), when a request for opening a secure private database is processed. |
|
1027 |
|
1028 @param aMsg Output parameter. A reference to a RMessage2 pointer, which will be initialized with the stored RMessage2 pointer. |
|
1029 @param aReadOnly Output parameter. The store read-only flag value will be set there. |
|
1030 |
|
1031 @panic Sqlite 13 In _DEBUG mode - aMsg is NULL. |
|
1032 */ |
|
1033 inline void COsLayerData::RetrieveAndResetFhData(const RMessage2*& aMsg, TBool& aReadOnly) |
|
1034 { |
|
1035 __ASSERT_DEBUG(iMessage != NULL, User::Panic(KPanicCategory, EPanicInvalidFhData)); |
|
1036 aMsg = iMessage; |
|
1037 aReadOnly = iReadOnly; |
|
1038 iMessage = NULL; |
|
1039 } |
|
1040 |
|
1041 /** |
|
1042 Initializes the COsLayerData data members with their default values. |
|
1043 */ |
|
1044 inline COsLayerData::COsLayerData() : |
|
1045 iAllocator(0), |
|
1046 iStoredOsErrorCode(KErrNone), |
|
1047 iMessage(0), |
|
1048 iReadOnly(EFalse) |
|
1049 { |
|
1050 TTime now; |
|
1051 now.UniversalTime(); |
|
1052 iSeed = now.Int64(); |
|
1053 iZeroBuf.FillZ(COsLayerData::KZeroBufSize); |
|
1054 } |
|
1055 |
|
1056 /** |
|
1057 Destroys the COsLayerData instance. |
|
1058 |
|
1059 Note: No SQLite functions should be called inside the destructor, because SQLite is already shutdown-ed! |
|
1060 */ |
|
1061 inline COsLayerData::~COsLayerData() |
|
1062 { |
|
1063 __FS_CALL(EFsOpFsClose, 0); |
|
1064 iFs.Close(); |
|
1065 } |
|
1066 |
|
1067 /** |
|
1068 Creates a file session instance. |
|
1069 |
|
1070 Creates the private path, where the temporary files will be stored (on the system drive). |
|
1071 |
|
1072 In a case of a failure COsLayerData::DoCreate() does not close the file session. |
|
1073 This will be made in the calling function - COsLayerData::Create(). |
|
1074 |
|
1075 Note: No SQLite functions should be called inside the DoCreate() implementation, because SQLite is not initialized yet! |
|
1076 |
|
1077 @return KErrNone, The operation has completed succesfully; |
|
1078 KErrGeneral The registration of TheVfsApi has failed; |
|
1079 KErrNoMemory, Out of memory condition has occured; |
|
1080 Note that other system-wide error codes may also be returned. |
|
1081 |
|
1082 @see TVfs |
|
1083 @see TheVfsApi |
|
1084 */ |
|
1085 TInt COsLayerData::DoCreate() |
|
1086 { |
|
1087 iAllocator = &User::Allocator(); |
|
1088 __FS_CALL(EFsOpFsConnect, 0); |
|
1089 TInt err = iFs.Connect(); |
|
1090 if(err != KErrNone) |
|
1091 { |
|
1092 return err; |
|
1093 } |
|
1094 //Get the system drive |
|
1095 __FS_CALL(EFsOpFsGetSystemDrive, 0); |
|
1096 TInt sysDrive = static_cast<TInt>(RFs::GetSystemDrive()); |
|
1097 __FS_CALL(EFsOpFsCreatePrivatePath, 0); |
|
1098 if((err = iFs.CreatePrivatePath(sysDrive)) != KErrNone && err != KErrAlreadyExists) |
|
1099 { |
|
1100 return err; |
|
1101 } |
|
1102 TFileName privateDir; |
|
1103 __FS_CALL(EFsOpFsPrivatePath, 0); |
|
1104 if((err = iFs.PrivatePath(privateDir)) != KErrNone) |
|
1105 { |
|
1106 return err; |
|
1107 } |
|
1108 TDriveUnit drive(sysDrive); |
|
1109 TDriveName driveName = drive.Name(); |
|
1110 TParse parse; |
|
1111 (void)parse.Set(driveName, &privateDir, 0);//this call can't fail |
|
1112 iSysPrivDir.Copy(parse.DriveAndPath()); |
|
1113 return KErrNone; |
|
1114 } |
|
1115 |
|
1116 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
1117 /////////////////////// Symbian OS specific functions (called by the SQL server) /////////////////////////////////// |
|
1118 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
1119 |
|
1120 /** |
|
1121 Returns the last OS error which occured durring the operations with the database files. |
|
1122 The per-thread variable, where the last OS error is hold, will be set to KErrNone. |
|
1123 |
|
1124 This function is part of Symbian OS specific SQLITE API. |
|
1125 |
|
1126 @return The last OS error. |
|
1127 @internalComponent |
|
1128 */ |
|
1129 TInt sqlite3SymbianLastOsError(void) |
|
1130 { |
|
1131 return COsLayerData::Instance().StoredOsErrorCode(); |
|
1132 } |
|
1133 |
|
1134 /** |
|
1135 This function must be called once before any other SQLITE API call. |
|
1136 The function: |
|
1137 @code |
|
1138 - Initializes the OS poting layer; |
|
1139 - Initializes the SQLite library; |
|
1140 @endcode |
|
1141 |
|
1142 This function is part of the Symbian OS specific SQLITE API. |
|
1143 |
|
1144 @return Symbian OS specific error code, including KErrNoMemory. |
|
1145 |
|
1146 @internalComponent |
|
1147 */ |
|
1148 TInt sqlite3SymbianLibInit(void) |
|
1149 { |
|
1150 TInt osErr = COsLayerData::Create(); |
|
1151 if(osErr != KErrNone) |
|
1152 { |
|
1153 return osErr; |
|
1154 } |
|
1155 osErr = KErrNone; |
|
1156 TInt sqliteErr = sqlite3_initialize(); |
|
1157 if(sqliteErr != SQLITE_OK) |
|
1158 { |
|
1159 osErr = sqliteErr == SQLITE_NOMEM ? KErrNoMemory : KErrGeneral; |
|
1160 COsLayerData::Destroy(); |
|
1161 } |
|
1162 return osErr; |
|
1163 } |
|
1164 |
|
1165 /** |
|
1166 This function must be called once after finishing working with sqlite. |
|
1167 The function: |
|
1168 @code |
|
1169 - Shuts down the SQLite library; |
|
1170 - Releases the allocated by the OS porting layer resources; |
|
1171 @endcode |
|
1172 |
|
1173 This function is part of the Symbian OS specific SQLITE API. |
|
1174 |
|
1175 @internalComponent |
|
1176 */ |
|
1177 void sqlite3SymbianLibFinalize(void) |
|
1178 { |
|
1179 (void)sqlite3_shutdown(); |
|
1180 COsLayerData::Destroy(); |
|
1181 } |
|
1182 |
|
1183 /** |
|
1184 This function is part of Symbian OS specific SQLITE API. |
|
1185 |
|
1186 @return A reference to RFs instance used for sqlite file I/O operations. |
|
1187 @internalComponent |
|
1188 */ |
|
1189 RFs& sqlite3SymbianFs(void) |
|
1190 { |
|
1191 return COsLayerData::Instance().iFs; |
|
1192 } |
|
1193 |
|
1194 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
1195 ////////////////// UTF16<-->UTF8, conversion functions //////////////////////////////////////////////////////////// |
|
1196 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
1197 |
|
1198 /** |
|
1199 The function converts aFileName to UTF16 encoded file name, and stores the UTF16 encoded file name |
|
1200 to the place pointed by aFileNameDestBuf argument. |
|
1201 If the UTF16 conversion of the file name failed because the file name is too long or NULL, |
|
1202 the function returns EFalse. |
|
1203 |
|
1204 @param aFileName Expected to point to UTF8 encoded, zero terminated string. |
|
1205 Max allowed aFileName length is KMaxFileName (excluding terminating 0 character). |
|
1206 @param aFileNameDestBuf Output parameter. Will hold UTF16, non-zero-terminated string. |
|
1207 The max length must be at least KMaxFileName characters. |
|
1208 |
|
1209 @return True if the conversion has been completed successfully |
|
1210 */ |
|
1211 static TBool ConvertToUnicode(const char *aFileName, TDes& aFileNameDestBuf) |
|
1212 { |
|
1213 if(aFileName) |
|
1214 { |
|
1215 wchar_t* dest = reinterpret_cast <wchar_t*> (const_cast <TUint16*> (aFileNameDestBuf.Ptr())); |
|
1216 TInt len = mbstowcs(dest, aFileName, aFileNameDestBuf.MaxLength()); |
|
1217 //If len == aFileNameDestBuf.MaxLength(), then the output buffer is too small. |
|
1218 if(len > 0 && len < aFileNameDestBuf.MaxLength()) |
|
1219 { |
|
1220 aFileNameDestBuf.SetLength(len); |
|
1221 return ETrue; |
|
1222 } |
|
1223 } |
|
1224 return EFalse; |
|
1225 } |
|
1226 |
|
1227 /** |
|
1228 The function converts aFileName to UTF8 encoded file name, and stores the UTF8 encoded file name |
|
1229 to the place pointed by aFileNameDestBuf argument. |
|
1230 If the UTF8 conversion of the file name failed because the file name is too long or NULL, |
|
1231 the function returns EFalse. |
|
1232 |
|
1233 @param aFileName Expected to point to UTF16 encoded, zero terminated string. |
|
1234 Max allowed aFileName length is KMaxFileName (excluding terminating 0 character). |
|
1235 @param aFileNameDestBuf Output parameter. Will hold UTF8, non-zero-terminated string. |
|
1236 The max length must be at least KMaxFileName characters. |
|
1237 |
|
1238 @return True if the conversion has been completed successfully |
|
1239 */ |
|
1240 static TBool ConvertFromUnicode(const TDesC& aFileName, TDes8& aFileNameDestBuf) |
|
1241 { |
|
1242 char* dest = reinterpret_cast <char*> (const_cast <TUint8*> (aFileNameDestBuf.Ptr())); |
|
1243 const wchar_t* src = reinterpret_cast <const wchar_t*> (aFileName.Ptr()); |
|
1244 TInt len = wcstombs(dest, src, aFileNameDestBuf.MaxLength()); |
|
1245 //If len == aFileNameDestBuf.MaxLength(), then the output buffer is too small. |
|
1246 if(len > 0 && len < aFileNameDestBuf.MaxLength()) |
|
1247 { |
|
1248 aFileNameDestBuf.SetLength(len); |
|
1249 return ETrue; |
|
1250 } |
|
1251 return EFalse; |
|
1252 } |
|
1253 |
|
1254 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
1255 ////////////////// File name, containing handles, functions //////////////////////////////////////////////////////// |
|
1256 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
1257 |
|
1258 const char KFhSeparator = '|'; //The symbol, which when used in the file name means that the string does not contain a real file name but file handles |
|
1259 const TInt KFhSessHandleIdx = 2;//The index of the file session handle in RMessage2 object |
|
1260 const TInt KFhFileHandleIdx = 3;//The index of the file handle in RMessage2 object |
|
1261 const TInt KFhMarkPos = 0; //if the symbol in this position is KFhSeparator, then the string contains file handles |
|
1262 const TInt KFhRoPos = 1; //read-only flag position in the string |
|
1263 const TInt KFhMsgAddrPos = 2; //RMessage2 address position in the string |
|
1264 const TInt KFhMsgAddrLen = 8; //RMessage2 address length |
|
1265 //const TInt KFhDrivePos = 1; //Drive position in the string (after removing the read-only flag and RMessage2 object's address) |
|
1266 |
|
1267 /** |
|
1268 File name string types: |
|
1269 @code |
|
1270 - ENotFhStr - The string does not contain file handles; |
|
1271 - EFhStr - The string contain file handles, but is not main db file; |
|
1272 - EFhMainDbStr - The string contain file handles and is the main db file; |
|
1273 @endcode |
|
1274 |
|
1275 Every file name passed to the OS porting layer's TVfs::Open() method falls into one of the following three categories: |
|
1276 ENotFhStr - the file name does not contain handles, EFhStr - the file name contains handles but is not a name of a private |
|
1277 secure database, EFhMainDbStr - the file name contains handles and is a name of a private secure database. |
|
1278 |
|
1279 @see TVfs::Open() |
|
1280 @see FhStringProps() |
|
1281 |
|
1282 @internalComponent |
|
1283 */ |
|
1284 enum TFhStrType |
|
1285 { |
|
1286 ENotFhStr, //The string does not contain file handles |
|
1287 EFhStr, //The string contain file handles, but is not main db file |
|
1288 EFhMainDbStr //The string contain file handles and is the main db file |
|
1289 }; |
|
1290 |
|
1291 /** |
|
1292 The TVfs::Open() implementation uses this function to determine the type of the file name, which can be |
|
1293 one of the TFhStrType enum item values. |
|
1294 |
|
1295 @param aFileName Zero-terminated, UTF8 encoded file name. |
|
1296 @return The file name type, one of the TFhStrType enum item values. |
|
1297 |
|
1298 @see TVfs::Open() |
|
1299 @see TFhStrType |
|
1300 |
|
1301 @internalComponent |
|
1302 */ |
|
1303 static TFhStrType FhStringProps(const char* aFileName) |
|
1304 { |
|
1305 char* first = strchr(aFileName, KFhSeparator); |
|
1306 if(!first) |
|
1307 { |
|
1308 return ENotFhStr; |
|
1309 } |
|
1310 char* last = strchr(first + 1, KFhSeparator); |
|
1311 if(!last) |
|
1312 { |
|
1313 return ENotFhStr; |
|
1314 } |
|
1315 return *(last + 1) == 0 ? EFhMainDbStr : EFhStr; |
|
1316 } |
|
1317 |
|
1318 /** |
|
1319 Replaces all invalid characters in aFileName. |
|
1320 If the file name contains handles (so that's a private secure database related name), the additional |
|
1321 information (handles, flags, object addresses) has to be excluded from the name in order to make it usable |
|
1322 by the file system. |
|
1323 |
|
1324 @param aFileName Output parameter. The cleaned file name will be copied there. |
|
1325 @param aPrivateDir The SQL server private data cage. |
|
1326 |
|
1327 @see TVfs::Open() |
|
1328 @see TFhStrType |
|
1329 @see FhStringProps() |
|
1330 |
|
1331 @internalComponent |
|
1332 */ |
|
1333 static void FhConvertToFileName(TDes& aFileName, const TDesC& aPrivateDir) |
|
1334 { |
|
1335 TInt firstPos = aFileName.Locate(TChar(KFhSeparator)); |
|
1336 if(firstPos >= 0) |
|
1337 { |
|
1338 aFileName.Delete(firstPos, 1); |
|
1339 TInt lastPos = aFileName.LocateReverse(TChar(KFhSeparator)); |
|
1340 if(lastPos >= 0) |
|
1341 { |
|
1342 aFileName.Delete(lastPos, 1); |
|
1343 TParse parse; |
|
1344 (void)parse.Set(aFileName, &aPrivateDir, 0);//the file name should be verified by the server |
|
1345 aFileName.Copy(parse.FullName()); |
|
1346 } |
|
1347 } |
|
1348 } |
|
1349 |
|
1350 /** |
|
1351 Extracts the read-only flag and RMessage address from aDbFileName and stores them in single COsLayerData instance. |
|
1352 |
|
1353 @param aDbFileName Input/output parameter. The file name. |
|
1354 It will be reformatted and won't contain the already extracted data. |
|
1355 The aDbFileName format is: |
|
1356 @code |
|
1357 |<R/O flag><RMessage2 pointer><drive><app SID><file_name><file_ext>| |
|
1358 @endcode |
|
1359 |
|
1360 @see TVfs::Open() |
|
1361 @see TFhStrType |
|
1362 @see FhStringProps() |
|
1363 |
|
1364 @internalComponent |
|
1365 |
|
1366 @panic Sqlite 12 In _DEBUG mode - invalid position of the "|" character in the file name. |
|
1367 @panic Sqlite 12 In _DEBUG mode - no RMessage2 pointer can be extracted from the file name. |
|
1368 @panic Sqlite 12 In _DEBUG mode - the extracted RMessage2 pointer is NULL. |
|
1369 */ |
|
1370 static void FhExtractAndStore(TDes& aDbFileName) |
|
1371 { |
|
1372 TInt fhStartPos = aDbFileName.Locate(TChar(KFhSeparator)); |
|
1373 __ASSERT_DEBUG(fhStartPos == KFhMarkPos, User::Panic(KPanicCategory, EPanicInvalidFhStr)); |
|
1374 //If this file name string contains file handles |
|
1375 if(fhStartPos == KFhMarkPos) |
|
1376 { |
|
1377 //Extract from aDbFileName string RMessage2 object's address |
|
1378 TLex lex(aDbFileName.Mid(fhStartPos + KFhMsgAddrPos, KFhMsgAddrLen)); |
|
1379 TUint32 addr; |
|
1380 TInt err = lex.Val(addr, EHex); |
|
1381 __ASSERT_DEBUG(err == KErrNone, User::Panic(KPanicCategory, EPanicInvalidFhStr)); |
|
1382 if(err == KErrNone) |
|
1383 { |
|
1384 //Cast the address to RMessage2 pointer. |
|
1385 const RMessage2* msg = reinterpret_cast <const RMessage2*> (addr); |
|
1386 __ASSERT_DEBUG(msg != NULL, User::Panic(KPanicCategory, EPanicInvalidFhStr)); |
|
1387 if(msg) |
|
1388 { |
|
1389 //Store the data from aDbFileName in the single COsLayerData instance. |
|
1390 TBool readOnly = aDbFileName[fhStartPos + KFhRoPos] > '0'; |
|
1391 COsLayerData::Instance().StoreFhData(msg, readOnly); |
|
1392 //Remove: read-only flag and RMessage2 object's address |
|
1393 aDbFileName.Delete(fhStartPos + KFhRoPos, 1 + KFhMsgAddrLen); |
|
1394 } |
|
1395 } |
|
1396 } |
|
1397 } |
|
1398 |
|
1399 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
1400 ///////////////////// TDbFile class definition /////////////////////////////////////////////////////////////////////// |
|
1401 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
1402 |
|
1403 /** |
|
1404 Initializes TDbFile data members with their default values. |
|
1405 */ |
|
1406 inline TDbFile::TDbFile() : |
|
1407 iFileBuf(KFileBufSize), |
|
1408 iFullName(0), |
|
1409 iLockType(SQLITE_LOCK_NONE), |
|
1410 iReadOnly(EFalse), |
|
1411 iSectorSize(0), |
|
1412 iDeviceCharacteristics(-1) |
|
1413 { |
|
1414 #ifdef _SQLPROFILER |
|
1415 iIsJournal = EFalse; |
|
1416 #endif |
|
1417 pMethods = 0; |
|
1418 } |
|
1419 |
|
1420 /** |
|
1421 Casts the passed sqlite3_file pointer to a reference to the derived class - TDbFile&. |
|
1422 All sqlite3_file pointers passed to TFileIo methods are actually pointers to TDbFile instances. |
|
1423 So the cast is safe. |
|
1424 |
|
1425 @param aDbFile A pointer to a sqlite3_file instance |
|
1426 |
|
1427 @return A TDbFile reference. |
|
1428 @see TFileIo |
|
1429 @see TVfs |
|
1430 @see TDbFile |
|
1431 |
|
1432 @panic Sqlite 20 In _DEBUG mode if aDbFile is NULL. |
|
1433 |
|
1434 @internalComponent |
|
1435 */ |
|
1436 static inline TDbFile& DbFile(sqlite3_file* aDbFile) |
|
1437 { |
|
1438 __ASSERT_DEBUG(aDbFile != 0, User::Panic(KPanicCategory, EPanicNullDbFilePtr)); |
|
1439 return *(static_cast <TDbFile*> (aDbFile)); |
|
1440 } |
|
1441 |
|
1442 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
1443 ///////////////////// TFileIo class definition /////////////////////////////////////////////////////////////////////// |
|
1444 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
1445 |
|
1446 /** |
|
1447 SQLite OS porting layer API. |
|
1448 |
|
1449 Closes the file referred by aDbFile parameter. |
|
1450 If aDbFile, which is actually a pointer to a TDbFile instance, the iFullName data member is not NULL, |
|
1451 then the file will be deleted. |
|
1452 |
|
1453 @param aDbFile A pointer to a TDbFile instance, than contains the file handle to be closed. |
|
1454 |
|
1455 @return SQLITE_OK |
|
1456 |
|
1457 @see TDbFile |
|
1458 */ |
|
1459 /* static */ int TFileIo::Close(sqlite3_file* aDbFile) |
|
1460 { |
|
1461 SQLUTRACE_PROFILER(aDbFile); |
|
1462 TDbFile& dbFile = ::DbFile(aDbFile); |
|
1463 __OS_CALL(EOsFileClose, 0, 0); |
|
1464 __OSTIME_COUNTER(TheOsCallTicks[EOsFileClose], ::OsCallProfile(dbFile.iIsJournal, EOsFileClose), 0, 0); |
|
1465 __FS_CALL(EFsOpFileClose, 0); |
|
1466 dbFile.iFileBuf.Close(); |
|
1467 if(dbFile.iFullName) |
|
1468 { |
|
1469 __FS_CALL(EFsOpFileDelete, 0); |
|
1470 (void)COsLayerData::Instance().iFs.Delete(*dbFile.iFullName); |
|
1471 delete dbFile.iFullName; |
|
1472 } |
|
1473 return SQLITE_OK; |
|
1474 } |
|
1475 |
|
1476 /** |
|
1477 SQLite OS porting layer API. |
|
1478 |
|
1479 Reads from the file referred by the aDbFile parameter. |
|
1480 |
|
1481 @param aDbFile A pointer to a TDbFile instance, that contains the file handle to be read from. |
|
1482 @param aBuf Output parameter. The data read from the file will be copied there. |
|
1483 The buffer size must be at least aAmt bytes. |
|
1484 @param aAmt The amount of data to be read form the file. |
|
1485 @param aOffset The offset in the file where the read operation should start. |
|
1486 |
|
1487 @return SQLITE_IOERR_READ, The file read or seek operation has failed; |
|
1488 SQLITE_IOERR_SHORT_READ, The amount of the data read is less than aAmt; |
|
1489 SQLITE_IOERR_NOMEM, An out of memory condition has occured; |
|
1490 SQLITE_OK, The operation has completed successfully. |
|
1491 |
|
1492 If the function succeeds, COsLayerData::SetOsErrorCode() is called with KErrNone, otherwise COsLayerData::SetOsErrorCode() is called |
|
1493 with the reported by the OS API error. The stored error code will be used later by the SQLite API caller. |
|
1494 |
|
1495 @see COsLayerData::SetOsErrorCode() |
|
1496 @see TDbFile |
|
1497 */ |
|
1498 /* static */ int TFileIo::Read(sqlite3_file* aDbFile, void* aBuf, int aAmt, sqlite3_int64 aOffset) |
|
1499 { |
|
1500 SQLUTRACE_PROFILER(aDbFile); |
|
1501 SYMBIAN_TRACE_SQL_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EInternals), KFileRead, aAmt, aOffset)); |
|
1502 TDbFile& dbFile = ::DbFile(aDbFile); |
|
1503 __OS_CALL(EOsFileRead, 0, 0); |
|
1504 __COUNTER_INCR(TheSqlSrvProfilerFileRead); |
|
1505 __OSTIME_COUNTER(TheOsCallTicks[EOsFileRead], ::OsCallProfile(dbFile.iIsJournal, EOsFileRead), aOffset, aAmt); |
|
1506 TPtr8 ptr((TUint8*)aBuf, 0, aAmt); |
|
1507 TInt err = dbFile.iFileBuf.Read(aOffset, ptr); |
|
1508 TInt cnt = ptr.Length(); |
|
1509 TInt sqliteErr = SQLITE_IOERR_READ; |
|
1510 switch(err) |
|
1511 { |
|
1512 case KErrNone: |
|
1513 sqliteErr = SQLITE_OK; |
|
1514 if(cnt != aAmt) |
|
1515 { |
|
1516 Mem::FillZ(static_cast <TUint8*> (aBuf) + cnt, aAmt - cnt); |
|
1517 sqliteErr = SQLITE_IOERR_SHORT_READ; |
|
1518 err = KErrEof; |
|
1519 } |
|
1520 break; |
|
1521 case KErrEof: |
|
1522 Mem::FillZ(static_cast <TUint8*> (aBuf) + cnt, aAmt - cnt); |
|
1523 sqliteErr = SQLITE_IOERR_SHORT_READ; |
|
1524 break; |
|
1525 case KErrNoMemory: |
|
1526 sqliteErr = SQLITE_IOERR_NOMEM; |
|
1527 break; |
|
1528 default: |
|
1529 break; |
|
1530 } |
|
1531 COsLayerData::Instance().SetOsErrorCode(err); |
|
1532 return sqliteErr; |
|
1533 } |
|
1534 |
|
1535 /** |
|
1536 SQLite OS porting layer API. |
|
1537 |
|
1538 Writes to the file referred by the aDbFile parameter. |
|
1539 "Write beyond the end of the file" operations are allowed. |
|
1540 |
|
1541 If the write operation is in the 1st db file page and there is a registered "free pages" callback |
|
1542 (TDbFile::iFreePageCallback) and the free pages count is above the defined value, |
|
1543 then the callback will be called. |
|
1544 |
|
1545 @param aDbFile A pointer to a TDbFile instance, that contains the file handle to be written to. |
|
1546 @param aData The data to be written to the file. The buffer size must be at least aAmt bytes. |
|
1547 @param aAmt The amount of data to be written to the file. |
|
1548 @param aOffset The offset in the file where the write operation should start. |
|
1549 |
|
1550 @return SQLITE_FULL, The file write or seek operation has failed. |
|
1551 The disk is full; |
|
1552 SQLITE_IOERR_NOMEM, An out of memory condition has occured; |
|
1553 SQLITE_OK, The operation has completed successfully. |
|
1554 |
|
1555 If the function succeeds, COsLayerData::SetOsErrorCode() is called with KErrNone, otherwise COsLayerData::SetOsErrorCode() is called |
|
1556 with the reported by the OS API error. The stored error code will be used later by the SQLite API caller. |
|
1557 |
|
1558 @see COsLayerData::SetOsErrorCode() |
|
1559 @see TDbFile |
|
1560 */ |
|
1561 /* static */ int TFileIo::Write(sqlite3_file* aDbFile, const void* aData, int aAmt, sqlite3_int64 aOffset) |
|
1562 { |
|
1563 SQLUTRACE_PROFILER(aDbFile); |
|
1564 SYMBIAN_TRACE_SQL_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EInternals), KFileWrite, aAmt, aOffset)); |
|
1565 TDbFile& dbFile = ::DbFile(aDbFile); |
|
1566 __OS_CALL(EOsFileWrite, 0, 0); |
|
1567 __COUNTER_INCR(TheSqlSrvProfilerFileWrite); |
|
1568 __OSTIME_COUNTER(TheOsCallTicks[EOsFileWrite], ::OsCallProfile(dbFile.iIsJournal, EOsFileWrite), aOffset, aAmt); |
|
1569 TInt err = KErrAccessDenied; |
|
1570 if(!dbFile.iReadOnly) |
|
1571 { |
|
1572 TPtrC8 ptr((const TUint8*)aData, aAmt); |
|
1573 err = dbFile.iFileBuf.Write(aOffset, ptr); |
|
1574 } |
|
1575 COsLayerData::Instance().SetOsErrorCode(err); |
|
1576 |
|
1577 const TInt KFreePageCountOffset = 36;//hard-coded constant. SQLite does not offer anything - a constant or #define. |
|
1578 //The checks in the "if" bellow do: |
|
1579 // - "err == KErrNone" - check the free page count only after a successful "write"; |
|
1580 // - "aOffset == 0" - check the free page count only if the write operation affects the system page (at aOffset = 0); |
|
1581 // - "aAmt >= (KFreePageCountOffset + sizeof(int))" - check the free page count only if the amount of bytes to be written |
|
1582 // is more than the offset of the free page counter (othewrise the free page counter is not affected |
|
1583 // by this write operation); |
|
1584 // - "dbFile.iFreePageCallback.IsValid()" - check the free page count only if there is a valid callback; |
|
1585 if(err == KErrNone && aOffset == 0 && aAmt >= (KFreePageCountOffset + sizeof(int)) && dbFile.iFreePageCallback.IsValid()) |
|
1586 { |
|
1587 const TUint8* ptr = static_cast <const TUint8*> (aData) + KFreePageCountOffset; |
|
1588 TInt freePageCount = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3]; |
|
1589 dbFile.iFreePageCallback.CheckAndCallback(freePageCount); |
|
1590 } |
|
1591 |
|
1592 return err == KErrNone ? SQLITE_OK : (err == KErrNoMemory ? SQLITE_IOERR_NOMEM : SQLITE_FULL); |
|
1593 } |
|
1594 |
|
1595 /** |
|
1596 SQLite OS porting layer API. |
|
1597 |
|
1598 Truncates the file referred by the aDbFile parameter. |
|
1599 |
|
1600 @param aDbFile A pointer to a TDbFile instance, that contains the file handle. |
|
1601 @param aLength The new file size in bytes. |
|
1602 |
|
1603 @return SQLITE_FULL, The disk is full; |
|
1604 SQLITE_IOERR, This is a read-only file. |
|
1605 The file truncate operation has failed; |
|
1606 SQLITE_IOERR_NOMEM, An out of memory condition has occured; |
|
1607 SQLITE_OK, The operation has completed successfully. |
|
1608 |
|
1609 If the function succeeds, COsLayerData::SetOsErrorCode() is called with KErrNone, otherwise COsLayerData::SetOsErrorCode() is called |
|
1610 with the reported by the OS API error. The stored error code will be used later by the SQLite API caller. |
|
1611 |
|
1612 @see COsLayerData::SetOsErrorCode() |
|
1613 @see TDbFile |
|
1614 */ |
|
1615 /* static */ int TFileIo::Truncate(sqlite3_file* aDbFile, sqlite3_int64 aLength) |
|
1616 { |
|
1617 SQLUTRACE_PROFILER(aDbFile); |
|
1618 SYMBIAN_TRACE_SQL_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EInternals), KFileTruncate, aLength)); |
|
1619 TDbFile& dbFile = ::DbFile(aDbFile); |
|
1620 __OS_CALL(EOsFileTruncate, 0, 0); |
|
1621 __COUNTER_INCR(TheSqlSrvProfilerFileSetSize); |
|
1622 __OSTIME_COUNTER(TheOsCallTicks[EOsFileTruncate], ::OsCallProfile(dbFile.iIsJournal, EOsFileTruncate), aLength, 0); |
|
1623 if(dbFile.iReadOnly) |
|
1624 { |
|
1625 COsLayerData::Instance().SetOsErrorCode(KErrAccessDenied); |
|
1626 return SQLITE_IOERR; |
|
1627 } |
|
1628 __FS_CALL(EFsOpFileSetSize, 0); |
|
1629 TInt err = dbFile.iFileBuf.SetSize(aLength); |
|
1630 COsLayerData::Instance().SetOsErrorCode(err); |
|
1631 return err == KErrNone ? SQLITE_OK : (err == KErrNoMemory ? SQLITE_IOERR_NOMEM : SQLITE_IOERR); |
|
1632 } |
|
1633 |
|
1634 /** |
|
1635 SQLite OS porting layer API. |
|
1636 |
|
1637 Flushes the file referred by the aDbFile parameter. |
|
1638 |
|
1639 @param aDbFile A pointer to a TDbFile instance, that contains the file handle. |
|
1640 |
|
1641 @return SQLITE_IOERR, This is a read-only file. |
|
1642 The file flush operation has failed; |
|
1643 SQLITE_IOERR_NOMEM, An out of memory condition has occured; |
|
1644 SQLITE_OK, The operation has completed successfully. |
|
1645 |
|
1646 If the function succeeds, COsLayerData::SetOsErrorCode() is called with KErrNone, otherwise COsLayerData::SetOsErrorCode() is called |
|
1647 with the reported by the OS API error. The stored error code will be used later by the SQLite API caller. |
|
1648 |
|
1649 @see COsLayerData::SetOsErrorCode() |
|
1650 @see TDbFile |
|
1651 */ |
|
1652 /* static */int TFileIo::Sync(sqlite3_file* aDbFile, int /* aFlags */) |
|
1653 { |
|
1654 SQLUTRACE_PROFILER(aDbFile); |
|
1655 TDbFile& dbFile = ::DbFile(aDbFile); |
|
1656 __OS_CALL(EOsFileSync, 0, 0); |
|
1657 __COUNTER_INCR(TheSqlSrvProfilerFileSync); |
|
1658 __OSTIME_COUNTER(TheOsCallTicks[EOsFileSync], ::OsCallProfile(dbFile.iIsJournal, EOsFileSync), 0, 0); |
|
1659 if(dbFile.iReadOnly) |
|
1660 { |
|
1661 COsLayerData::Instance().SetOsErrorCode(KErrAccessDenied); |
|
1662 return SQLITE_IOERR; |
|
1663 } |
|
1664 __FS_CALL(EFsOpFileSync, 0); |
|
1665 TInt err = dbFile.iFileBuf.Flush(); |
|
1666 COsLayerData::Instance().SetOsErrorCode(err); |
|
1667 return err == KErrNone ? SQLITE_OK : (err == KErrNoMemory ? SQLITE_IOERR_NOMEM : SQLITE_IOERR); |
|
1668 } |
|
1669 |
|
1670 /** |
|
1671 SQLite OS porting layer API. |
|
1672 |
|
1673 Returns the size of the file referred by the aDbFile parameter. |
|
1674 |
|
1675 @param aDbFile A pointer to a TDbFile instance, that contains the file handle. |
|
1676 @param aSize Output parameter. If the function completes successfully, the file size will be stored there. |
|
1677 |
|
1678 @return SQLITE_IOERR, The file size operation has failed; |
|
1679 SQLITE_IOERR_NOMEM, An out of memory condition has occured; |
|
1680 SQLITE_OK, The operation has completed successfully. |
|
1681 |
|
1682 If the function succeeds, COsLayerData::SetOsErrorCode() is called with KErrNone, otherwise COsLayerData::SetOsErrorCode() is called |
|
1683 with the reported by the OS API error. The stored error code will be used later by the SQLite API caller. |
|
1684 |
|
1685 @see COsLayerData::SetOsErrorCode() |
|
1686 @see TDbFile |
|
1687 */ |
|
1688 /* static */ int TFileIo::FileSize(sqlite3_file* aDbFile, sqlite3_int64* aSize) |
|
1689 { |
|
1690 SQLUTRACE_PROFILER(aDbFile); |
|
1691 TDbFile& dbFile = ::DbFile(aDbFile); |
|
1692 __OS_CALL(EOsFileFileSize, 0, 0); |
|
1693 __OSTIME_COUNTER(TheOsCallTicks[EOsFileFileSize], ::OsCallProfile(dbFile.iIsJournal, EOsFileFileSize), 0, 0); |
|
1694 __FS_CALL(EFsOpFileSize, 0); |
|
1695 TInt err = dbFile.iFileBuf.Size(*aSize); |
|
1696 COsLayerData::Instance().SetOsErrorCode(err); |
|
1697 if(err == KErrNone) |
|
1698 { |
|
1699 return SQLITE_OK; |
|
1700 } |
|
1701 return err == KErrNoMemory ? SQLITE_IOERR_NOMEM : SQLITE_IOERR; |
|
1702 } |
|
1703 |
|
1704 /** |
|
1705 SQLite OS porting layer API. |
|
1706 |
|
1707 Locks the file, referred by the aDbFile parameter, with the specified lock type. |
|
1708 Since this is a single-threaded OS porting layer implementation, the file is not actually locked - small |
|
1709 performance optimisation. The file lock type is stored for later use by the CheckReservedLock() call. |
|
1710 |
|
1711 @param aDbFile A pointer to a TDbFile instance, that contains the file handle. |
|
1712 @param aLockType Lock type: SQLITE_LOCK_NONE, SQLITE_LOCK_SHARED, SQLITE_LOCK_RESERVED, SQLITE_LOCK_PENDING or |
|
1713 SQLITE_LOCK_EXCLUSIVE. |
|
1714 |
|
1715 @return SQLITE_OK, The operation has completed successfully. |
|
1716 |
|
1717 @see TFileIo::CheckReservedLock() |
|
1718 @see TFileIo::Unlock() |
|
1719 |
|
1720 @see TDbFile |
|
1721 */ |
|
1722 /* static */ int TFileIo::Lock(sqlite3_file* aDbFile, int aLockType) |
|
1723 { |
|
1724 SQLUTRACE_PROFILER(aDbFile); |
|
1725 TDbFile& dbFile = ::DbFile(aDbFile); |
|
1726 __OS_CALL(EOsFileLock, 0, 0); |
|
1727 __OSTIME_COUNTER(TheOsCallTicks[EOsFileLock], ::OsCallProfile(dbFile.iIsJournal, EOsFileLock), aLockType, 0); |
|
1728 //If there is already a lock of this type or more restrictive on the database file, do nothing. |
|
1729 if(dbFile.iLockType >= aLockType) |
|
1730 { |
|
1731 return SQLITE_OK; |
|
1732 } |
|
1733 dbFile.iLockType = aLockType; |
|
1734 return SQLITE_OK; |
|
1735 } |
|
1736 |
|
1737 /** |
|
1738 SQLite OS porting layer API. |
|
1739 |
|
1740 Unlocks the file, referred by the aDbFile parameter. |
|
1741 Since this is a single-threaded OS porting layer implementation, the file never gets locked - small |
|
1742 performance optimisation. The Unlock() call only sets the stored file lock type with the aLockType value. |
|
1743 |
|
1744 @param aDbFile A pointer to a TDbFile instance, that contains the file handle. |
|
1745 @param aLockType Lock type: SQLITE_LOCK_NONE, SQLITE_LOCK_SHARED, SQLITE_LOCK_RESERVED, SQLITE_LOCK_PENDING or |
|
1746 SQLITE_LOCK_EXCLUSIVE. |
|
1747 |
|
1748 @return SQLITE_OK, The operation has completed successfully. |
|
1749 |
|
1750 @see TFileIo::CheckReservedLock() |
|
1751 @see TFileIo::Lock() |
|
1752 |
|
1753 @see TDbFile |
|
1754 */ |
|
1755 /* static */ int TFileIo::Unlock(sqlite3_file* aDbFile, int aLockType) |
|
1756 { |
|
1757 SQLUTRACE_PROFILER(aDbFile); |
|
1758 TDbFile& dbFile = ::DbFile(aDbFile); |
|
1759 __OS_CALL(EOsFileUnlock, 0, 0); |
|
1760 __OSTIME_COUNTER(TheOsCallTicks[EOsFileUnlock], ::OsCallProfile(dbFile.iIsJournal, EOsFileUnlock), aLockType, 0); |
|
1761 dbFile.iLockType = aLockType; |
|
1762 return SQLITE_OK; |
|
1763 } |
|
1764 |
|
1765 /** |
|
1766 SQLite OS porting layer API. |
|
1767 |
|
1768 Checks if the file lock type is SQLITE_LOCK_RESERVED or bigger. |
|
1769 Since this is a single-threaded OS porting layer implementation, the file never gets locked - small |
|
1770 performance optimisation. The CheckReservedLock() call only checks if the stored file lock type |
|
1771 is bigger or equal than SQLITE_LOCK_RESERVED. |
|
1772 |
|
1773 @param aDbFile A pointer to a TDbFile instance, that contains the file handle. |
|
1774 @param aResOut Output parameter. It should be set to 1 if the stored lock type is bigger or equal |
|
1775 than SQLITE_LOCK_RESERVED. |
|
1776 |
|
1777 @return SQLITE_OK. |
|
1778 |
|
1779 @see TFileIo::Lock() |
|
1780 @see TFileIo::Unlock() |
|
1781 |
|
1782 @see TDbFile |
|
1783 */ |
|
1784 /* static */ int TFileIo::CheckReservedLock(sqlite3_file* aDbFile, int *aResOut) |
|
1785 { |
|
1786 SQLUTRACE_PROFILER(aDbFile); |
|
1787 TDbFile& dbFile = ::DbFile(aDbFile); |
|
1788 __OS_CALL(EOsFileCheckReservedLock, 0, 0); |
|
1789 __OSTIME_COUNTER(TheOsCallTicks[EOsFileCheckReservedLock], ::OsCallProfile(dbFile.iIsJournal, EOsFileCheckReservedLock), 0, 0); |
|
1790 *aResOut = dbFile.iLockType >= SQLITE_LOCK_RESERVED ? 1 : 0; |
|
1791 return SQLITE_OK; |
|
1792 } |
|
1793 |
|
1794 /** |
|
1795 SQLite OS porting layer API. |
|
1796 |
|
1797 Performs an aOp operation on the file referred by the aDbFile parameter. |
|
1798 Since the only supported operation at the moment is SQLITE_FCNTL_LOCKSTATE, and the current lock type is stored as |
|
1799 a data memebr of TDbFile, the function implementation has been optimised - no file I/O calls. The stored file lock type |
|
1800 is retured if the operation is SQLITE_FCNTL_LOCKSTATE. |
|
1801 |
|
1802 Note: The range of supported operations includes KSqlFcntlRegisterFreePageCallback now. |
|
1803 When the function is called with aOp = KSqlFcntlRegisterFreePageCallback, then a callback will be registered |
|
1804 and called when the number of the free pages goes above certain threshold. |
|
1805 |
|
1806 @param aDbFile A pointer to a TDbFile instance, that contains the file handle. |
|
1807 @param aOp File operation type. Currently only SQLITE_FCNTL_LOCKSTATE is supported. |
|
1808 @param aArg An additional input/output parameter which purpose depends on the type of the current file operation. |
|
1809 If the file operation is SQLITE_FCNTL_LOCKSTATE, then aArg is used as an output parameter, where |
|
1810 the file lock type is stored. |
|
1811 If the operation type is KSqlFcntlRegisterFreePageCallback, then aArg points to a TSqlFreePageCallback object, |
|
1812 that contains the free page threshold and the callback. |
|
1813 |
|
1814 @return SQLITE_ERROR, Non-supported operation; |
|
1815 SQLITE_OK, The operation has completed successfully. |
|
1816 |
|
1817 @see TDbFile |
|
1818 */ |
|
1819 /* static */ int TFileIo::FileControl(sqlite3_file* aDbFile, int aOp, void* aArg) |
|
1820 { |
|
1821 SQLUTRACE_PROFILER(aDbFile); |
|
1822 SYMBIAN_TRACE_SQL_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EInternals), KFileFileCtr, aOp)); |
|
1823 TDbFile& dbFile = ::DbFile(aDbFile); |
|
1824 __OS_CALL(EOsFileFileControl, 0, 0); |
|
1825 __OSTIME_COUNTER(TheOsCallTicks[EOsFileFileControl], ::OsCallProfile(dbFile.iIsJournal, EOsFileFileControl), aOp, 0); |
|
1826 TInt err = KErrNone; |
|
1827 switch(aOp) |
|
1828 { |
|
1829 case SQLITE_FCNTL_LOCKSTATE: |
|
1830 *(int*)aArg = dbFile.iLockType; |
|
1831 break; |
|
1832 case KSqlFcntlRegisterFreePageCallback: |
|
1833 { |
|
1834 err = KErrArgument; |
|
1835 if(aArg) |
|
1836 { |
|
1837 TSqlFreePageCallback* rq = static_cast <TSqlFreePageCallback*> (aArg); |
|
1838 if(rq->IsValid()) |
|
1839 { |
|
1840 dbFile.iFreePageCallback = *rq; |
|
1841 err = KErrNone; |
|
1842 } |
|
1843 } |
|
1844 } |
|
1845 break; |
|
1846 default: |
|
1847 err = KErrArgument; |
|
1848 break; |
|
1849 } |
|
1850 COsLayerData::Instance().SetOsErrorCode(err); |
|
1851 return err == KErrNone ? SQLITE_OK : SQLITE_ERROR; |
|
1852 } |
|
1853 |
|
1854 /** |
|
1855 SQLite OS porting layer API. |
|
1856 |
|
1857 Retrieves the sector size of the media of the file referred by the aDbFile parameter. |
|
1858 Since the sector size never changes till the file is open, the function has been optimised - no file I/O calls. |
|
1859 The sector size is retrieved during the TVfs::Open() call and stored in TDbFile::iSectorSize. The SectorSize() |
|
1860 call returns the value of TDbFile::iSectorSize. |
|
1861 |
|
1862 @param aDbFile A pointer to a TDbFile instance, that contains the file handle. |
|
1863 |
|
1864 @return The sector size. |
|
1865 |
|
1866 @panic Sqlite 19 In _DEBUG mode - TDbFile::iSectorSize is negative or 0 . |
|
1867 |
|
1868 @see TDbFile |
|
1869 @see TVfs::Open() |
|
1870 */ |
|
1871 /* static */ int TFileIo::SectorSize(sqlite3_file* aDbFile) |
|
1872 { |
|
1873 SQLUTRACE_PROFILER(aDbFile); |
|
1874 TDbFile& dbFile = ::DbFile(aDbFile); |
|
1875 __OS_CALL(EOsFileSectorSize, 0, 0); |
|
1876 __OSTIME_COUNTER(TheOsCallTicks[EOsFileSectorSize], ::OsCallProfile(dbFile.iIsJournal, EOsFileSectorSize), 0, 0); |
|
1877 __ASSERT_DEBUG(dbFile.iSectorSize > 0, User::Panic(KPanicCategory, EPanicInternalError)); |
|
1878 if(dbFile.iSectorSize > 0) |
|
1879 { |
|
1880 return dbFile.iSectorSize; |
|
1881 } |
|
1882 return SQLITE_DEFAULT_SECTOR_SIZE; |
|
1883 } |
|
1884 |
|
1885 /** |
|
1886 SQLite OS porting layer API. |
|
1887 |
|
1888 Retrieves the device characteristics of the device of the file referred by the aDbFile parameter. |
|
1889 Since the device characteristics never change till the file is open, the function has been optimised - no file I/O calls. |
|
1890 The device characteristics are retrieved during the TVfs::Open() call and stored in TDbFile::iDeviceCharacteristics. |
|
1891 The DeviceCharacteristics() call returns the value of TDbFile::iDeviceCharacteristics. |
|
1892 |
|
1893 @param aDbFile A pointer to a TDbFile instance, that contains the file handle. |
|
1894 |
|
1895 @return A bit set containing the device characteristics. |
|
1896 |
|
1897 @panic Sqlite 19 In _DEBUG mode - TDbFile::iDeviceCharacteristics is negative or 0 . |
|
1898 |
|
1899 @see TDbFile |
|
1900 @see TVfs::Open() |
|
1901 */ |
|
1902 /* static */ int TFileIo::DeviceCharacteristics(sqlite3_file* aDbFile) |
|
1903 { |
|
1904 SQLUTRACE_PROFILER(aDbFile); |
|
1905 TDbFile& dbFile = ::DbFile(aDbFile); |
|
1906 __OS_CALL(EOsFileDeviceCharacteristics, 0, 0); |
|
1907 __OSTIME_COUNTER(TheOsCallTicks[EOsFileDeviceCharacteristics], ::OsCallProfile(dbFile.iIsJournal, EOsFileDeviceCharacteristics), 0, 0); |
|
1908 __ASSERT_DEBUG(dbFile.iDeviceCharacteristics >= 0, User::Panic(KPanicCategory, EPanicInternalError)); |
|
1909 if(dbFile.iDeviceCharacteristics >= 0) |
|
1910 { |
|
1911 return dbFile.iDeviceCharacteristics; |
|
1912 } |
|
1913 return 0; |
|
1914 } |
|
1915 |
|
1916 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
1917 /////////////////////////////////// TVfs class definition /////////////////////////////////////////////////////////// |
|
1918 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
1919 |
|
1920 |
|
1921 /** |
|
1922 Opens a private secure database. |
|
1923 Actually the database file has been created or opened by the client's process. |
|
1924 This function only adopts the passed in aMsg parameter file handle. |
|
1925 |
|
1926 @param aDbFile Output parameter, where the initialized file handle will be stored. |
|
1927 @param aMsg A reference to the current RMessage2 instance. Contains the file handle of the database created |
|
1928 or opened by the client's process. |
|
1929 @param aReadOnly True if the file is read-only. |
|
1930 |
|
1931 @return KErrNone, The operation has completed succesfully; |
|
1932 KErrNoMemory, Out of memory condition has occured; |
|
1933 Note that other system-wide error codes may also be returned. |
|
1934 |
|
1935 @see TDbFile |
|
1936 @see TVfs::Open() |
|
1937 */ |
|
1938 /* static */ TInt TVfs::DoOpenFromHandle(TDbFile& aDbFile, const RMessage2& aMsg, TBool aReadOnly) |
|
1939 { |
|
1940 __FS_CALL(EFsOpFileAdopt, 0); |
|
1941 TInt err = aDbFile.iFileBuf.AdoptFromClient(aMsg, KFhSessHandleIdx, KFhFileHandleIdx); |
|
1942 if(err == KErrNone) |
|
1943 { |
|
1944 aDbFile.iReadOnly = aReadOnly; |
|
1945 } |
|
1946 return err; |
|
1947 }; |
|
1948 |
|
1949 /** |
|
1950 Collects information about the drive referred by the aDriveNo parameter. |
|
1951 |
|
1952 @param aFs RFs instance. |
|
1953 @param aDriveNo The drive about which an information will be collected. |
|
1954 @param aVolumeInfo Output parameter. A reference to a TVolumeIOParamInfo object where the collected information will be stored. |
|
1955 |
|
1956 @return KErrNone, The operation has completed succesfully; |
|
1957 KErrNoMemory, Out of memory condition has occured; |
|
1958 Note that other system-wide error codes may also be returned. |
|
1959 |
|
1960 @see TVfs::Open() |
|
1961 */ |
|
1962 /* static */ inline TInt TVfs::DoGetVolumeIoParamInfo(RFs& aFs, TInt aDriveNo, TVolumeIOParamInfo& aVolumeInfo) |
|
1963 { |
|
1964 __FS_CALL(EFsOpFsVolumeIoParam, 0); |
|
1965 return aFs.VolumeIOParam(aDriveNo, aVolumeInfo); |
|
1966 } |
|
1967 |
|
1968 /** |
|
1969 Retrieves and returns in a bit set the device characteristics. |
|
1970 |
|
1971 @param aDriveInfo A TDriveInfo reference from which the device characteristics will be extracted. |
|
1972 @param aVolumeInfo A TVolumeIOParamInfo reference from which the device characteristics will be extracted. |
|
1973 |
|
1974 @return A bit set containing the device characteristics: |
|
1975 SQLITE_IOCAP_SAFE_APPEND, SQLITE_IOCAP_ATOMIC, the atomic block size. |
|
1976 |
|
1977 @see TVfs::DoGetVolumeIoParamInfo(); |
|
1978 @see TVfs::Open() |
|
1979 */ |
|
1980 /* static */ TInt TVfs::DoGetDeviceCharacteristics(const TDriveInfo& aDriveInfo, const TVolumeIOParamInfo& aVolumeInfo) |
|
1981 { |
|
1982 TInt deviceCharacteristics = 0; |
|
1983 if(aDriveInfo.iDriveAtt & (KDriveAttLocal | KDriveAttInternal)) |
|
1984 { |
|
1985 deviceCharacteristics |= SQLITE_IOCAP_SAFE_APPEND;//Data written first, file size updated second |
|
1986 } |
|
1987 if(aDriveInfo.iDriveAtt & KDriveAttTransaction) |
|
1988 { |
|
1989 deviceCharacteristics |= SQLITE_IOCAP_ATOMIC; |
|
1990 } |
|
1991 if(aVolumeInfo.iBlockSize >= SQLITE_DEFAULT_SECTOR_SIZE && (aVolumeInfo.iBlockSize & (aVolumeInfo.iBlockSize - 1)) == 0) |
|
1992 { |
|
1993 switch(aVolumeInfo.iBlockSize) |
|
1994 { |
|
1995 case 512: |
|
1996 deviceCharacteristics |= SQLITE_IOCAP_ATOMIC512; |
|
1997 break; |
|
1998 case 1024: |
|
1999 deviceCharacteristics |= SQLITE_IOCAP_ATOMIC1K; |
|
2000 break; |
|
2001 case 2048: |
|
2002 deviceCharacteristics |= SQLITE_IOCAP_ATOMIC2K; |
|
2003 break; |
|
2004 case 4096: |
|
2005 deviceCharacteristics |= SQLITE_IOCAP_ATOMIC4K; |
|
2006 break; |
|
2007 case 8192: |
|
2008 deviceCharacteristics |= SQLITE_IOCAP_ATOMIC8K; |
|
2009 break; |
|
2010 case 16384: |
|
2011 deviceCharacteristics |= SQLITE_IOCAP_ATOMIC16K; |
|
2012 break; |
|
2013 case 32768: |
|
2014 deviceCharacteristics |= SQLITE_IOCAP_ATOMIC32K; |
|
2015 break; |
|
2016 case 65536: |
|
2017 deviceCharacteristics |= SQLITE_IOCAP_ATOMIC64K; |
|
2018 break; |
|
2019 default: |
|
2020 //Do nothing. deviceCharacteristics was initialized with 0 at the beginning of the function body. |
|
2021 break; |
|
2022 } |
|
2023 } |
|
2024 return deviceCharacteristics; |
|
2025 } |
|
2026 |
|
2027 /** |
|
2028 Retrieves and returns the sector size of the drive referred by the aDriveInfo parameter. |
|
2029 The sector size must be a power of two. |
|
2030 The sector size is extracted only if aDriveInfo refers to a removable device, otherwise the |
|
2031 SQLITE_DEFAULT_SECTOR_SIZE value (512 bytes) will be used as a sector size. |
|
2032 |
|
2033 @param aDriveInfo A TDriveInfo reference. |
|
2034 @param aVolumeInfo A TVolumeIOParamInfo reference. |
|
2035 |
|
2036 @return The sector size of the drive referred by the aDriveInfo parameter. |
|
2037 |
|
2038 @panic Sqlite 19 In _DEBUG mode - The sector size is negative, zero or is not a power of two. |
|
2039 |
|
2040 @see TVfs::Open() |
|
2041 */ |
|
2042 /* static */ TInt TVfs::DoGetSectorSize(const TDriveInfo& aDriveInfo, const TVolumeIOParamInfo& aVolumeInfo) |
|
2043 { |
|
2044 //Initialize the sectorSize variable only if: |
|
2045 // - aDriveInfo refers to a removable drive |
|
2046 // - aVolumeInfo.iBlockSize > SQLITE_DEFAULT_SECTOR_SIZE; |
|
2047 // - aVolumeInfo.iBlockSize is power of 2; |
|
2048 TInt sectorSize = SQLITE_DEFAULT_SECTOR_SIZE; |
|
2049 if(aDriveInfo.iDriveAtt & KDriveAttRemovable) |
|
2050 { |
|
2051 if(aVolumeInfo.iBlockSize > SQLITE_DEFAULT_SECTOR_SIZE && (aVolumeInfo.iBlockSize & (aVolumeInfo.iBlockSize - 1)) == 0) |
|
2052 { |
|
2053 sectorSize = aVolumeInfo.iBlockSize; |
|
2054 } |
|
2055 } |
|
2056 __ASSERT_DEBUG(sectorSize > 0 && (sectorSize & (sectorSize - 1)) == 0, User::Panic(KPanicCategory, EPanicInternalError)); |
|
2057 return sectorSize; |
|
2058 } |
|
2059 |
|
2060 /** |
|
2061 Retrieves in a bit set the device characteristics of the device of the file referred by the aDbFile parameter. |
|
2062 Retrieves the sector size of the drive of the file referred by the aDbFile parameter. |
|
2063 The sector size and the device characteristics will be stored in iSectorSize and iDeviceCharacteristics TDbFile data members. |
|
2064 The stored values will be used later by TFileIo::DeviceCharacteristics() and TFileIo::SectorSize(). |
|
2065 |
|
2066 @param aDbFile Input/Output parameter. A TDriveInfo reference. The collected information will be stored in TDbDrive |
|
2067 data members. |
|
2068 @param aRecReadBufSize Output parameter. The recommended buffer size for optimised reading performance. |
|
2069 |
|
2070 @return KErrNone, The operation has completed succesfully; |
|
2071 Note that other system-wide error codes may also be returned. |
|
2072 |
|
2073 @panic Sqlite 19 In _DEBUG mode - TDbFile::iSectorSize has been already initialized. |
|
2074 @panic Sqlite 19 In _DEBUG mode - TDbFile::iDeviceCharacteristics has been already initialized. |
|
2075 |
|
2076 @see TVfs::DoGetDeviceCharacteristics(); |
|
2077 @see TVfs::DoGetSectorSize(); |
|
2078 @see TVfs::Open() |
|
2079 @see TDbFile |
|
2080 @see TFileIo::DeviceCharacteristics() |
|
2081 @see TFileIo::SectorSize() |
|
2082 */ |
|
2083 /* static */ TInt TVfs::DoGetDeviceCharacteristicsAndSectorSize(TDbFile& aDbFile, TInt& aRecReadBufSize) |
|
2084 { |
|
2085 __ASSERT_DEBUG(aDbFile.iDeviceCharacteristics < 0, User::Panic(KPanicCategory, EPanicInternalError)); |
|
2086 __ASSERT_DEBUG(aDbFile.iSectorSize <= 0, User::Panic(KPanicCategory, EPanicInternalError)); |
|
2087 TInt driveNo; |
|
2088 TDriveInfo driveInfo; |
|
2089 __FS_CALL(EFsOpFileDrive, 0); |
|
2090 TInt err = aDbFile.iFileBuf.Drive(driveNo, driveInfo); |
|
2091 if(err != KErrNone) |
|
2092 { |
|
2093 return err; |
|
2094 } |
|
2095 TVolumeIOParamInfo volumeInfo; |
|
2096 err = TVfs::DoGetVolumeIoParamInfo(COsLayerData::Instance().iFs, driveNo, volumeInfo); |
|
2097 if(err != KErrNone) |
|
2098 { |
|
2099 return err; |
|
2100 } |
|
2101 aDbFile.iDeviceCharacteristics = TVfs::DoGetDeviceCharacteristics(driveInfo, volumeInfo); |
|
2102 aDbFile.iSectorSize = TVfs::DoGetSectorSize(driveInfo, volumeInfo); |
|
2103 aRecReadBufSize = volumeInfo.iRecReadBufSize; |
|
2104 return KErrNone; |
|
2105 } |
|
2106 |
|
2107 /** |
|
2108 SQLite OS porting layer API. |
|
2109 |
|
2110 Opens or creates a file which name is in the aFileName parameter. |
|
2111 If the function succeeds, the file handle and other related information will be stored in the place pointed by the |
|
2112 aDbFile parameter, a memory block of sizeof(TDbFile) size for which is allocated by the caller. |
|
2113 The function will also retrieve the sector size and the device characteristics and store them in aDbFile, |
|
2114 which is actually a TDbFile pointer, for later use. |
|
2115 |
|
2116 @param aFileName Zero-terminated, UTF8 encoded file name. |
|
2117 If aFileName is NULL then a temporary file is created. |
|
2118 @param aDbFile Output parameter. The file handle and other related information will be stored there. |
|
2119 @param aFlags "Open/Create" input flags: |
|
2120 SQLITE_OPEN_DELETEONCLOSE, |
|
2121 SQLITE_OPEN_READWRITE, |
|
2122 SQLITE_OPEN_EXCLUSIVE, |
|
2123 SQLITE_OPEN_CREATE |
|
2124 @param aOutFlags "Open/Create" output flags: |
|
2125 SQLITE_OPEN_READWRITE, |
|
2126 SQLITE_OPEN_READONLY |
|
2127 |
|
2128 @return SQLITE_CANTOPEN, The aFileName parameter cannot be converted to UTF16. |
|
2129 Any other file I/O error will also be reported as SQLITE_CANTOPEN; |
|
2130 SQLITE_IOERR_NOMEM, An out of memory condition has occured; |
|
2131 SQLITE_OK, The operation has completed successfully. |
|
2132 |
|
2133 If the function succeeds, COsLayerData::SetOsErrorCode() is called with KErrNone, otherwise COsLayerData::SetOsErrorCode() is called |
|
2134 with the reported by the OS API error. The stored error code will be used later by the SQLite API caller. |
|
2135 |
|
2136 @see COsLayerData::SetOsErrorCode() |
|
2137 @see TDbFile |
|
2138 */ |
|
2139 /* static */ int TVfs::Open(sqlite3_vfs* aVfs, const char* aFileName, sqlite3_file* aDbFile, int aFlags, int* aOutFlags) |
|
2140 { |
|
2141 SQLUTRACE_PROFILER(aVfs); |
|
2142 __OS_CALL(EOsVfsOpen, 0, 0); |
|
2143 __OSTIME_COUNTER(TheOsCallTicks[EOsVfsOpen], ::OsCallProfile(EFalse, EOsVfsOpen), 0, 0); |
|
2144 COsLayerData& osLayerData = COsLayerData::Instance(); |
|
2145 TFileName fname; |
|
2146 if(aFileName && !::ConvertToUnicode(aFileName, fname)) |
|
2147 { |
|
2148 osLayerData.SetOsErrorCode(KErrBadName); |
|
2149 return SQLITE_CANTOPEN; |
|
2150 } |
|
2151 SYMBIAN_TRACE_SQL_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EInternals), KFileOpen, aDbFile, &fname)); |
|
2152 new (aDbFile) TDbFile; |
|
2153 TDbFile& dbFile = ::DbFile(aDbFile); |
|
2154 TFhStrType fhStrType = aFileName ? ::FhStringProps(aFileName) : ENotFhStr; |
|
2155 if(aFileName && (aFlags & SQLITE_OPEN_DELETEONCLOSE)) |
|
2156 { |
|
2157 dbFile.iFullName = fname.Alloc(); |
|
2158 if(!dbFile.iFullName) |
|
2159 { |
|
2160 osLayerData.SetOsErrorCode(KErrNoMemory); |
|
2161 return SQLITE_IOERR_NOMEM; |
|
2162 } |
|
2163 } |
|
2164 TInt recReadBufSize = -1; |
|
2165 TInt err = KErrNone; |
|
2166 if(fhStrType == EFhMainDbStr) |
|
2167 {//Main db file, open from handle |
|
2168 const RMessage2* msg; |
|
2169 TBool readOnly; |
|
2170 osLayerData.RetrieveAndResetFhData(msg, readOnly); |
|
2171 err = msg != NULL ? TVfs::DoOpenFromHandle(dbFile, *msg, readOnly) : KErrGeneral; |
|
2172 } |
|
2173 else |
|
2174 { |
|
2175 if(fhStrType == EFhStr) |
|
2176 {//Not the main db file. Replace invalid characters in the file name |
|
2177 ::FhConvertToFileName(fname, osLayerData.iSysPrivDir);//If fname does not have a path, iSysPrivDir will be used |
|
2178 } |
|
2179 TInt fmode = EFileRead; |
|
2180 if(aFlags & SQLITE_OPEN_READWRITE) |
|
2181 { |
|
2182 fmode |= EFileWrite; |
|
2183 } |
|
2184 if(aFlags & SQLITE_OPEN_EXCLUSIVE) |
|
2185 { |
|
2186 fmode |= EFileShareExclusive; |
|
2187 } |
|
2188 if(!aFileName) |
|
2189 { |
|
2190 __FS_CALL(EFsOpFileCreateTemp, 0); |
|
2191 err = dbFile.iFileBuf.Temp(osLayerData.iFs, osLayerData.iSysPrivDir, fname, fmode); |
|
2192 if(err == KErrNone) |
|
2193 { |
|
2194 dbFile.iFullName = fname.Alloc(); |
|
2195 if(!dbFile.iFullName) |
|
2196 { |
|
2197 err = KErrNoMemory; |
|
2198 } |
|
2199 } |
|
2200 } |
|
2201 else |
|
2202 { |
|
2203 err = KErrAccessDenied; |
|
2204 TInt prevErr = KErrNone; |
|
2205 if(aFlags & SQLITE_OPEN_CREATE) |
|
2206 { |
|
2207 __FS_CALL(EFsOpFileCreate, 0); |
|
2208 prevErr = err = dbFile.iFileBuf.Create(osLayerData.iFs, fname, fmode); |
|
2209 } |
|
2210 if(err != KErrNone && err != KErrNoMemory && err != KErrDiskFull) |
|
2211 { |
|
2212 __FS_CALL(EFsOpFileOpen, 0); |
|
2213 err = dbFile.iFileBuf.Open(osLayerData.iFs, fname, fmode); |
|
2214 } |
|
2215 if((err != KErrNone && err != KErrNoMemory && err != KErrDiskFull) && (aFlags & SQLITE_OPEN_READWRITE)) |
|
2216 { |
|
2217 aFlags &= ~SQLITE_OPEN_READWRITE; |
|
2218 aFlags |= SQLITE_OPEN_READONLY; |
|
2219 fmode &= ~EFileWrite; |
|
2220 __FS_CALL(EFsOpFileOpen, 0); |
|
2221 err = dbFile.iFileBuf.Open(osLayerData.iFs, fname, fmode); |
|
2222 } |
|
2223 if(err != KErrNone && prevErr == KErrAccessDenied) |
|
2224 { |
|
2225 err = KErrAccessDenied; |
|
2226 } |
|
2227 } |
|
2228 } |
|
2229 if(err == KErrNone) |
|
2230 { |
|
2231 err = TVfs::DoGetDeviceCharacteristicsAndSectorSize(dbFile, recReadBufSize); |
|
2232 } |
|
2233 osLayerData.SetOsErrorCode(err); |
|
2234 if(err != KErrNone) |
|
2235 { |
|
2236 __FS_CALL(EFsOpFileClose, 0); |
|
2237 dbFile.iFileBuf.Close(); |
|
2238 delete dbFile.iFullName; |
|
2239 dbFile.iFullName = NULL; |
|
2240 } |
|
2241 else |
|
2242 { |
|
2243 dbFile.pMethods = &TheFileIoApi; |
|
2244 if(fhStrType != EFhMainDbStr) |
|
2245 { |
|
2246 dbFile.iReadOnly = !(aFlags & SQLITE_OPEN_READWRITE); |
|
2247 } |
|
2248 if(aOutFlags) |
|
2249 { |
|
2250 *aOutFlags = dbFile.iReadOnly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_READWRITE; |
|
2251 } |
|
2252 (void)dbFile.iFileBuf.SetReadAheadSize(dbFile.iSectorSize, recReadBufSize); |
|
2253 } |
|
2254 #ifdef _SQLPROFILER |
|
2255 dbFile.iIsJournal = (aFlags & SQLITE_OPEN_MAIN_JOURNAL) || (aFlags & SQLITE_OPEN_TEMP_JOURNAL) || |
|
2256 (aFlags & SQLITE_OPEN_SUBJOURNAL) || (aFlags & SQLITE_OPEN_MASTER_JOURNAL); |
|
2257 #endif |
|
2258 return err == KErrNone ? SQLITE_OK : (err == KErrNoMemory ? SQLITE_IOERR_NOMEM : SQLITE_CANTOPEN); |
|
2259 } |
|
2260 |
|
2261 /** |
|
2262 SQLite OS porting layer API. |
|
2263 |
|
2264 Deletes a file which name is in the aFileName parameter. |
|
2265 |
|
2266 @param aFileName Zero-terminated, UTF8 encoded file name. |
|
2267 |
|
2268 @return SQLITE_ERROR, The aFileName parameter cannot be converted to UTF16. |
|
2269 The file name refers to a private secure database; |
|
2270 SQLITE_IOERR_NOMEM, An out of memory condition has occured; |
|
2271 SQLITE_IOERR_DELETE,The delete file operation has failed; |
|
2272 SQLITE_OK, The operation has completed successfully. |
|
2273 |
|
2274 If the function succeeds, COsLayerData::SetOsErrorCode() is called with KErrNone, otherwise COsLayerData::SetOsErrorCode() is called |
|
2275 with the reported by the OS API error. The stored error code will be used later by the SQLite API caller. |
|
2276 |
|
2277 @see COsLayerData::SetOsErrorCode() |
|
2278 */ |
|
2279 /* static */ int TVfs::Delete(sqlite3_vfs* aVfs, const char* aFileName, int /*aSyncDir*/) |
|
2280 { |
|
2281 SQLUTRACE_PROFILER(aVfs); |
|
2282 __OS_CALL(EOsVfsDelete, 0, 0); |
|
2283 __OSTIME_COUNTER(TheOsCallTicks[EOsVfsDelete], ::OsCallProfile(EFalse, EOsVfsDelete), 0, 0); |
|
2284 COsLayerData& osLayerData = COsLayerData::Instance(); |
|
2285 TBuf<KMaxFileName + 1> fname; |
|
2286 if(!::ConvertToUnicode(aFileName, fname)) |
|
2287 { |
|
2288 osLayerData.SetOsErrorCode(KErrBadName); |
|
2289 return SQLITE_ERROR; |
|
2290 } |
|
2291 SYMBIAN_TRACE_SQL_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EInternals), KFileName, &fname)); |
|
2292 TFhStrType fhStrType = FhStringProps(aFileName); |
|
2293 if(fhStrType == EFhMainDbStr) |
|
2294 {//Deleting files not in your own private data cage - not allowed! |
|
2295 osLayerData.SetOsErrorCode(KErrPermissionDenied); |
|
2296 return SQLITE_ERROR; |
|
2297 } |
|
2298 if(fhStrType == EFhStr) |
|
2299 { |
|
2300 ::FhConvertToFileName(fname, osLayerData.iSysPrivDir);//If fname does not have a path, iSysPrivDir will be used |
|
2301 } |
|
2302 __FS_CALL(EFsOpFileDelete, 0); |
|
2303 TInt err = osLayerData.iFs.Delete(fname); |
|
2304 osLayerData.SetOsErrorCode(err); |
|
2305 return err == KErrNone ? SQLITE_OK : (err == KErrNoMemory ? SQLITE_IOERR_NOMEM : SQLITE_IOERR_DELETE); |
|
2306 } |
|
2307 |
|
2308 /** |
|
2309 SQLite OS porting layer API. |
|
2310 |
|
2311 Retrieves an information about a file which name is in the aFileName parameter. |
|
2312 The requested information type can be: does the file exist, is the file read-only or read/write. |
|
2313 |
|
2314 @param aFileName Zero-terminated, UTF8 encoded file name. |
|
2315 @param aFlags This parameter can be one of: SQLITE_ACCESS_READ, SQLITE_ACCESS_EXISTS or SQLITE_ACCESS_READWRITE. |
|
2316 @param aResOut Output parameter, set to 1 if the tested condition is true, 0 otherwise. |
|
2317 |
|
2318 @return SQLITE_OK, The call has completed successfully, |
|
2319 SQLITE_IOERR_NOMEM, An out of memory conditon has occured, |
|
2320 SQLITE_IOERR_ACCESS,File I/O error; |
|
2321 |
|
2322 If the function succeeds, COsLayerData::SetOsErrorCode() is called with KErrNone, otherwise COsLayerData::SetOsErrorCode() is called |
|
2323 with the reported by the OS API error. The stored error code will be used later by the SQLite API caller. |
|
2324 |
|
2325 @see COsLayerData::SetOsErrorCode() |
|
2326 */ |
|
2327 /* static */ int TVfs::Access(sqlite3_vfs* aVfs, const char* aFileName, int aFlags, int* aResOut) |
|
2328 { |
|
2329 SQLUTRACE_PROFILER(aVfs); |
|
2330 __OS_CALL(EOsVfsAccess, 0, 0); |
|
2331 __OSTIME_COUNTER(TheOsCallTicks[EOsVfsAccess], ::OsCallProfile(EFalse, EOsVfsAccess), aFlags, 0); |
|
2332 COsLayerData& osLayerData = COsLayerData::Instance(); |
|
2333 TBuf<KMaxFileName + 1> fname; |
|
2334 if(!::ConvertToUnicode(aFileName, fname)) |
|
2335 { |
|
2336 osLayerData.SetOsErrorCode(KErrGeneral); |
|
2337 return SQLITE_IOERR_ACCESS; |
|
2338 } |
|
2339 SYMBIAN_TRACE_SQL_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EInternals), KFileName, &fname)); |
|
2340 TFhStrType fhStrType = ::FhStringProps(aFileName); |
|
2341 if(fhStrType == EFhStr) |
|
2342 { |
|
2343 ::FhConvertToFileName(fname, osLayerData.iSysPrivDir);//If fname does not have a path, iSysPrivDir will be used |
|
2344 } |
|
2345 TEntry entry; |
|
2346 __FS_CALL(EFsOpFsEntry, 0); |
|
2347 TInt err = osLayerData.iFs.Entry(fname, entry); |
|
2348 if(aFlags == SQLITE_ACCESS_EXISTS && err == KErrNotFound) |
|
2349 { |
|
2350 osLayerData.SetOsErrorCode(KErrNone); |
|
2351 *aResOut = 0; |
|
2352 return SQLITE_OK; |
|
2353 } |
|
2354 if(err != KErrNone) |
|
2355 { |
|
2356 osLayerData.SetOsErrorCode(err); |
|
2357 return err == KErrNoMemory ? SQLITE_IOERR_NOMEM : SQLITE_IOERR_ACCESS; |
|
2358 } |
|
2359 *aResOut = 0; |
|
2360 switch(aFlags) |
|
2361 { |
|
2362 case SQLITE_ACCESS_READ: |
|
2363 *aResOut = entry.IsReadOnly(); |
|
2364 break; |
|
2365 case SQLITE_ACCESS_EXISTS: |
|
2366 *aResOut = 1; |
|
2367 break; |
|
2368 case SQLITE_ACCESS_READWRITE: |
|
2369 *aResOut = !entry.IsReadOnly(); |
|
2370 break; |
|
2371 default: |
|
2372 break; |
|
2373 } |
|
2374 osLayerData.SetOsErrorCode(KErrNone); |
|
2375 return SQLITE_OK; |
|
2376 } |
|
2377 |
|
2378 /** |
|
2379 SQLite OS porting layer API. |
|
2380 |
|
2381 Accepts UTF8 encoded, zero-terminated file as an input argument in the aRelative parameter |
|
2382 and constructs the full file path in the aBuf output parameter. |
|
2383 |
|
2384 If the format of aRelative argument is <[SID]FileName.[EXT]>, then the database file name will be |
|
2385 treated as a name of a secure database file which has to be created/opened in the server's private |
|
2386 directory on the system drive. |
|
2387 |
|
2388 If the format of aRelative argument is <Drive:[SID]FileName.[EXT]>, then the database file name |
|
2389 will be treated as a name of a secure database file which has to be created/opened in the server's |
|
2390 private directory on <Drive:> drive. |
|
2391 |
|
2392 If the format of aRelative argument is <Drive:\Path\FileName.[EXT]>, then the database file name |
|
2393 will be treated as a name of a non-secure database file in <Drive:\Path\> directory. |
|
2394 If aRelative contains file handles, then it will be treated as a name of a file belonging to server's |
|
2395 private data cage. |
|
2396 |
|
2397 @param aRelative The input file name, zero-terminated, UTF8 encoded. |
|
2398 @param aBufLen The output buffer length. |
|
2399 @param aBuf Output buffer for the constructed full file name path. The allocated buffer length must be at least aBufLen bytes. |
|
2400 |
|
2401 @return SQLITE_ERROR, The aRelative parameter is NULL or cannot be converted to UTF16; |
|
2402 SQLITE_OK The operation has completed successfully. |
|
2403 */ |
|
2404 /* static */ int TVfs::FullPathName(sqlite3_vfs* aVfs, const char* aRelative, int aBufLen, char* aBuf) |
|
2405 { |
|
2406 SQLUTRACE_PROFILER(aVfs); |
|
2407 __OS_CALL(EOsVfsFullPathName, 0, 0); |
|
2408 __OSTIME_COUNTER(TheOsCallTicks[EOsVfsFullPathName], ::OsCallProfile(EFalse, EOsVfsFullPathName), aBufLen, 0); |
|
2409 COsLayerData& osLayerData = COsLayerData::Instance(); |
|
2410 osLayerData.StoreFhData(NULL, EFalse); |
|
2411 //Convert the received file name to UTF16 |
|
2412 TBuf<KMaxFileName + 1> fname; |
|
2413 if(!::ConvertToUnicode(aRelative, fname)) |
|
2414 { |
|
2415 return SQLITE_ERROR; |
|
2416 } |
|
2417 SYMBIAN_TRACE_SQL_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EInternals), KFileName, &fname)); |
|
2418 //Zero-terminate the converted file name |
|
2419 fname.Append(TChar(0)); |
|
2420 TParse parse; |
|
2421 TFhStrType strType = ::FhStringProps(aRelative);//Detect string type - it may not be a real file name |
|
2422 if(strType == EFhMainDbStr) |
|
2423 {//The additonal information has to be extracted and fname reformatted, because SQLITE will |
|
2424 //use the returned full file name when making a decission to share the cache. |
|
2425 ::FhExtractAndStore(fname); |
|
2426 (void)parse.Set(fname, 0, 0);//the file name has to be verified by the file server |
|
2427 } |
|
2428 else |
|
2429 { |
|
2430 (void)parse.Set(fname, &osLayerData.iSysPrivDir, 0);//If fname does not have a path, iSysPrivDir will be used |
|
2431 } |
|
2432 TPtr8 dest8(reinterpret_cast <TUint8*> (aBuf), aBufLen); |
|
2433 if(!::ConvertFromUnicode(parse.FullName(), dest8)) |
|
2434 {//Zero the stored fh data, because it has been initialized by the FhExtractAndStore(fname) call (couple of lines above) |
|
2435 osLayerData.StoreFhData(NULL, EFalse); |
|
2436 return SQLITE_ERROR; |
|
2437 } |
|
2438 return SQLITE_OK; |
|
2439 } |
|
2440 |
|
2441 /** |
|
2442 SQLite OS porting layer API. |
|
2443 |
|
2444 Generates a set of random numbers and stores them in the aBuf output parameter. |
|
2445 |
|
2446 @param aBufLen The output buffer length. |
|
2447 @param aBuf Output buffer for the generated random numbers. The allocated buffer length must be at least aBufLen bytes. |
|
2448 |
|
2449 @return The length of the used part of the output buffer. |
|
2450 */ |
|
2451 /* static */ int TVfs::Randomness(sqlite3_vfs* aVfs, int aBufLen, char* aBuf) |
|
2452 { |
|
2453 SQLUTRACE_PROFILER(aVfs); |
|
2454 __OS_CALL(EOsVfsRandomness, 0, 0); |
|
2455 __OSTIME_COUNTER(TheOsCallTicks[EOsVfsRandomness], ::OsCallProfile(EFalse, EOsVfsRandomness), aBufLen, 0); |
|
2456 COsLayerData& osLayerData = COsLayerData::Instance(); |
|
2457 const TInt KRandIterations = aBufLen / sizeof(int); |
|
2458 for(TInt i=0;i<KRandIterations;++i) |
|
2459 { |
|
2460 TInt val = Math::Rand(osLayerData.iSeed); |
|
2461 Mem::Copy(&aBuf[i * sizeof(int)], &val, sizeof(val)); |
|
2462 } |
|
2463 return KRandIterations * sizeof(int); |
|
2464 } |
|
2465 |
|
2466 /** |
|
2467 SQLite OS porting layer API. |
|
2468 |
|
2469 Sleeps for aMicrosec microseconds. |
|
2470 |
|
2471 @param aMicrosec The sleep interval in microseconds. |
|
2472 |
|
2473 @return The aMicrosec value. |
|
2474 */ |
|
2475 /* static */ int TVfs::Sleep(sqlite3_vfs* aVfs, int aMicrosec) |
|
2476 { |
|
2477 SQLUTRACE_PROFILER(aVfs); |
|
2478 __OS_CALL(EOsVfsSleep, 0, 0); |
|
2479 __OSTIME_COUNTER(TheOsCallTicks[EOsVfsSleep], ::OsCallProfile(EFalse, EOsVfsSleep), aMicrosec, 0); |
|
2480 User::AfterHighRes(TTimeIntervalMicroSeconds32(aMicrosec)); |
|
2481 return aMicrosec; |
|
2482 } |
|
2483 |
|
2484 /** |
|
2485 SQLite OS porting layer API. |
|
2486 |
|
2487 Retrieves the current date and time. |
|
2488 |
|
2489 @param aNow Output parameter, where the data and time value will be stored. |
|
2490 SQLite processes all times and dates as Julian Day numbers and |
|
2491 aNow parameter will contain the julian date and time. |
|
2492 |
|
2493 @return 0. |
|
2494 */ |
|
2495 /* static */ int TVfs::CurrentTime(sqlite3_vfs* aVfs, double* aNow) |
|
2496 { |
|
2497 SQLUTRACE_PROFILER(aVfs); |
|
2498 __OS_CALL(EOsVfsCurrentTime, 0, 0); |
|
2499 __OSTIME_COUNTER(TheOsCallTicks[EOsVfsCurrentTime], ::OsCallProfile(EFalse, EOsVfsCurrentTime), 0, 0); |
|
2500 TTime now; |
|
2501 now.UniversalTime(); |
|
2502 TDateTime date = now.DateTime(); |
|
2503 TInt year = date.Year(); |
|
2504 TInt month = date.Month() + 1; |
|
2505 TInt day = date.Day() + 1; |
|
2506 |
|
2507 //Calculate the Julian days |
|
2508 TInt jd = day - 32076 + |
|
2509 1461*(year + 4800 + (month - 14)/12)/4 + |
|
2510 367*(month - 2 - (month - 14)/12*12)/12 - |
|
2511 3*((year + 4900 + (month - 14)/12)/100)/4; |
|
2512 |
|
2513 *aNow = jd; |
|
2514 |
|
2515 // Add the fractional hours, mins and seconds |
|
2516 *aNow += (date.Hour() + 12.0) / 24.0; |
|
2517 *aNow += date.Minute() / 1440.0; |
|
2518 *aNow += date.Second() / 86400.0; |
|
2519 |
|
2520 return 0; |
|
2521 } |
|
2522 |
|
2523 /** |
|
2524 SQLite OS porting layer API. |
|
2525 |
|
2526 Retrieves a text description of the last OS error. |
|
2527 Note: the method has a default "no-op" implementation at the moment. |
|
2528 |
|
2529 @return 0. |
|
2530 */ |
|
2531 /* static */int TVfs::GetLastError(sqlite3_vfs* aVfs, int /*aBufLen*/, char* /*aBuf*/) |
|
2532 { |
|
2533 SQLUTRACE_PROFILER(aVfs); |
|
2534 __OS_CALL(EOsVfsGetLastError, 0, 0); |
|
2535 __OSTIME_COUNTER(TheOsCallTicks[EOsVfsGetLastError], ::OsCallProfile(EFalse, EOsVfsGetLastError), 0, 0); |
|
2536 return 0; |
|
2537 } |
|
2538 |
|
2539 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
2540 /////////////////////////////////// Memory allocation functions ///////////////////////////////////////////////////// |
|
2541 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
2542 |
|
2543 /** |
|
2544 SQLite OS porting layer API. |
|
2545 |
|
2546 Memory allocation routine. |
|
2547 |
|
2548 @internalComponent |
|
2549 */ |
|
2550 extern "C" void* sqlite3SymbianMalloc(size_t aSize) |
|
2551 { |
|
2552 __MEM_CALL(EMemOpAlloc, aSize, 0); |
|
2553 return COsLayerData::Instance().iAllocator->Alloc(aSize); |
|
2554 } |
|
2555 |
|
2556 /** |
|
2557 SQLite OS porting layer API. |
|
2558 |
|
2559 Memory reallocation routine. |
|
2560 |
|
2561 @internalComponent |
|
2562 */ |
|
2563 extern "C" void* sqlite3SymbianRealloc(void* aPtr, size_t aSize) |
|
2564 { |
|
2565 #ifdef _SQLPROFILER |
|
2566 TInt size = COsLayerData::Instance().iAllocator->AllocLen(aPtr); |
|
2567 __MEM_CALL(EMemOpRealloc, aSize, size); |
|
2568 #endif |
|
2569 return COsLayerData::Instance().iAllocator->ReAlloc(aPtr, aSize); |
|
2570 } |
|
2571 |
|
2572 /** |
|
2573 SQLite OS porting layer API. |
|
2574 |
|
2575 Memory free routine. |
|
2576 |
|
2577 @internalComponent |
|
2578 */ |
|
2579 extern "C" void sqlite3SymbianFree(void* aPtr) |
|
2580 { |
|
2581 #ifdef _SQLPROFILER |
|
2582 TInt size = COsLayerData::Instance().iAllocator->AllocLen(aPtr); |
|
2583 __MEM_CALL(EMemOpFree, size, 0); |
|
2584 #endif |
|
2585 COsLayerData::Instance().iAllocator->Free(aPtr); |
|
2586 } |
|
2587 |
|
2588 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
2589 /////////////////////////////////// SQLite init/release functions /////////////////////////////////////////////////// |
|
2590 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
2591 |
|
2592 /** |
|
2593 Registers the single sqlite3_vfs instance ("TheVfsApi" global variable) by calling sqlite3_vfs_register() |
|
2594 */ |
|
2595 extern "C" int sqlite3_os_init(void) |
|
2596 { |
|
2597 return sqlite3_vfs_register(&TheVfsApi, 1);//"1" means - make TheVfsApi to be the default VFS object |
|
2598 } |
|
2599 |
|
2600 /** |
|
2601 Unregisters the single sqlite3_vfs instance ("TheVfsApi" global variable) by calling sqlite3_vfs_unregister() |
|
2602 */ |
|
2603 extern "C" int sqlite3_os_end(void) |
|
2604 { |
|
2605 return sqlite3_vfs_unregister(&TheVfsApi); |
|
2606 } |
|
2607 |
|
2608 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
2609 |
|
2610 #endif//SQLITE_OS_SYMBIAN |
|
2611 |