Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(68)

Side by Side Diff: third_party/sqlite/src/os_symbian.cc

Issue 3108030: Move bundled copy of sqlite one level deeper to better separate it... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « third_party/sqlite/src/os_os2.c ('k') | third_party/sqlite/src/os_unix.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2008, Google Inc.
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are met:
5 //
6 // 1. Redistributions of source code must retain the above copyright notice,
7 // this list of conditions and the following disclaimer.
8 // 2. Redistributions in binary form must reproduce the above copyright notice,
9 // this list of conditions and the following disclaimer in the documentation
10 // and/or other materials provided with the distribution.
11 // 3. Neither the name of Google Inc. nor the names of its contributors may be
12 // used to endorse or promote products derived from this software without
13 // specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
18 // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
26 // This file contains code that is specific to Symbian.
27 // Differently from the rest of SQLite, it is implemented in C++ as this is
28 // the native language of the OS and all interfaces we need to use are C++.
29 //
30 // This file follows the Gears code style guidelines.
31
32 #ifdef OS_SYMBIAN
33 #include <coemain.h>
34 #include <e32math.h>
35 #include <f32file.h>
36 #include <utf.h>
37
38 extern "C" {
39 #include "sqliteInt.h"
40 #include "os_common.h"
41 }
42
43 const TInt kFileLockAttempts = 3;
44
45 // The global file system session.
46 RFs g_fs_session;
47
48 static TInt UTF8ToUTF16(const char *in, TDes *out16) {
49 assert(in);
50 TPtrC8 in_des(reinterpret_cast<const unsigned char*>(in));
51 return CnvUtfConverter::ConvertToUnicodeFromUtf8(*out16, in_des);
52 }
53
54 static TInt UTF16ToUTF8(const TDesC16& in16, TDes8 *out8) {
55 return CnvUtfConverter::ConvertFromUnicodeToUtf8(*out8, in16);
56 }
57
58 // The SymbianFile structure is a subclass of sqlite3_file* specific to the
59 // Symbian portability layer.
60 struct SymbianFile {
61 const sqlite3_io_methods *methods;
62 RFile handle; // The file handle
63 TUint8 lock_type; // Type of lock currently held on this file
64 TUint16 shared_lock_byte; // Randomly chosen byte used as a shared lock
65 };
66
67 static SymbianFile* ConvertToSymbianFile(sqlite3_file* const id) {
68 assert(id);
69 return reinterpret_cast<SymbianFile*>(id);
70 }
71
72 static int SymbianClose(sqlite3_file *id) {
73 SymbianFile *file_id = ConvertToSymbianFile(id);
74 file_id->handle.Close();
75 OpenCounter(-1);
76 return SQLITE_OK;
77 }
78
79 static int SymbianRead(sqlite3_file *id,
80 void *buffer,
81 int amount,
82 sqlite3_int64 offset) {
83 assert(buffer);
84 assert(amount >=0);
85 assert(offset >=0);
86
87 SymbianFile* file_id = ConvertToSymbianFile(id);
88 TPtr8 dest(static_cast<unsigned char*>(buffer), amount);
89
90 if (KErrNone == file_id->handle.Read(offset, dest, amount)) {
91 if (dest.Length() == amount) {
92 return SQLITE_OK;
93 } else {
94 return SQLITE_IOERR_SHORT_READ;
95 }
96 } else {
97 return SQLITE_IOERR;
98 }
99 }
100
101 static int SymbianWrite(sqlite3_file *id,
102 const void *buffer,
103 int amount,
104 sqlite3_int64 offset) {
105 assert(buffer);
106 assert(amount >=0);
107 assert(offset >=0);
108
109 SymbianFile *file_id = ConvertToSymbianFile(id);
110 TPtrC8 src(static_cast<const unsigned char*>(buffer), amount);
111 if (file_id->handle.Write(offset, src) != KErrNone) {
112 return SQLITE_IOERR_WRITE;
113 }
114
115 return SQLITE_OK;
116 }
117
118 static int SymbianTruncate(sqlite3_file *id, sqlite3_int64 bytes) {
119 assert(bytes >=0);
120
121 SymbianFile *file_id = ConvertToSymbianFile(id);
122 if (file_id->handle.SetSize(bytes) != KErrNone) {
123 return SQLITE_IOERR;
124 }
125 return SQLITE_OK;
126 }
127
128 static int SymbianSync(sqlite3_file *id, int /*flags*/) {
129 SymbianFile *file_id = ConvertToSymbianFile(id);
130 if (file_id->handle.Flush() != KErrNone) {
131 return SQLITE_IOERR;
132 } else {
133 return SQLITE_OK;
134 }
135 }
136
137 static int SymbianFileSize(sqlite3_file *id, sqlite3_int64 *size) {
138 assert(size);
139
140 SymbianFile *file_id = ConvertToSymbianFile(id);
141 TInt size_tmp;
142 if (file_id->handle.Size(size_tmp) != KErrNone) {
143 return SQLITE_IOERR;
144 }
145 *size = size_tmp;
146 return SQLITE_OK;
147 }
148
149 // File lock/unlock functions; see os_win.c for a description
150 // of the algorithm used.
151 static int GetReadLock(SymbianFile *file) {
152 file->shared_lock_byte = Math::Random() % (SHARED_SIZE - 1);
153 return file->handle.Lock(SHARED_FIRST + file->shared_lock_byte, 1);
154 }
155
156 static int UnlockReadLock(SymbianFile *file) {
157 return file->handle.UnLock(SHARED_FIRST + file->shared_lock_byte, 1);
158 }
159
160 static int SymbianLock(sqlite3_file *id, int lock_type) {
161 SymbianFile *file = ConvertToSymbianFile(id);
162 if (file->lock_type >= lock_type) {
163 return SQLITE_OK;
164 }
165
166 // Make sure the locking sequence is correct
167 assert(file->lock_type != NO_LOCK || lock_type == SHARED_LOCK);
168 assert(lock_type != PENDING_LOCK);
169 assert(lock_type != RESERVED_LOCK || file->lock_type == SHARED_LOCK);
170
171 // Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or
172 // a SHARED lock. If we are acquiring a SHARED lock, the acquisition of
173 // the PENDING_LOCK byte is temporary.
174 int new_lock_type = file->lock_type;
175 int got_pending_lock = 0;
176 int res = KErrNone;
177 if (file->lock_type == NO_LOCK ||
178 (lock_type == EXCLUSIVE_LOCK && file->lock_type == RESERVED_LOCK)) {
179 int count = kFileLockAttempts;
180 while (count-- > 0 &&
181 (res = file->handle.Lock(PENDING_BYTE, 1)) != KErrNone ) {
182 // Try 3 times to get the pending lock. The pending lock might be
183 // held by another reader process who will release it momentarily.
184 OSTRACE2("could not get a PENDING lock. cnt=%d\n", cnt);
185 User::After(1000);
186 }
187 got_pending_lock = (res == KErrNone? 1 : 0);
188 }
189
190 // Acquire a shared lock
191 if (lock_type == SHARED_LOCK && res == KErrNone) {
192 assert(file->lock_type == NO_LOCK);
193 res = GetReadLock(file);
194 if (res == KErrNone) {
195 new_lock_type = SHARED_LOCK;
196 }
197 }
198
199 // Acquire a RESERVED lock
200 if (lock_type == RESERVED_LOCK && res == KErrNone) {
201 assert(file->lock_type == SHARED_LOCK);
202 res = file->handle.Lock(RESERVED_BYTE, 1);
203 if (res == KErrNone) {
204 new_lock_type = RESERVED_LOCK;
205 }
206 }
207
208 // Acquire a PENDING lock
209 if (lock_type == EXCLUSIVE_LOCK && res == KErrNone) {
210 new_lock_type = PENDING_LOCK;
211 got_pending_lock = 0;
212 }
213
214 // Acquire an EXCLUSIVE lock
215 if (lock_type == EXCLUSIVE_LOCK && res == KErrNone) {
216 assert(file->lock_type >= SHARED_LOCK);
217 res = UnlockReadLock(file);
218 OSTRACE2("unreadlock = %d\n", res);
219 res = file->handle.Lock(SHARED_FIRST, SHARED_SIZE);
220 if (res == KErrNone) {
221 new_lock_type = EXCLUSIVE_LOCK;
222 } else {
223 OSTRACE2("error-code = %d\n", GetLastError());
224 GetReadLock(file);
225 }
226 }
227
228 // If we are holding a PENDING lock that ought to be released, then
229 // release it now.
230 if (got_pending_lock && lock_type == SHARED_LOCK) {
231 file->handle.UnLock(PENDING_BYTE, 1);
232 }
233
234 // Update the state of the lock held in the file descriptor, then
235 // return the appropriate result code.
236 file->lock_type = new_lock_type;
237 if (res == KErrNone) {
238 return SQLITE_OK;
239 } else {
240 OSTRACE4("LOCK FAILED %d trying for %d but got %d\n", file->handle,
241 lock_type, new_lock_type);
242 return SQLITE_BUSY;
243 }
244 }
245
246 static int SymbianUnlock(sqlite3_file *id, int lock_type) {
247 int type;
248 int rc = SQLITE_OK;
249 SymbianFile *file = ConvertToSymbianFile(id);
250 assert(lock_type <= SHARED_LOCK);
251 OSTRACE5("UNLOCK %d to %d was %d(%d)\n", file->handle, lock_type,
252 file->lock_type, file->shared_lock_byte);
253 type = file->lock_type;
254 if (type >= EXCLUSIVE_LOCK) {
255 file->handle.UnLock(SHARED_FIRST, SHARED_SIZE);
256 if (lock_type == SHARED_LOCK && GetReadLock(file) != KErrNone) {
257 // This should never happen. We should always be able to
258 // reacquire the read lock
259 rc = SQLITE_IOERR_UNLOCK;
260 }
261 }
262 if (type >= RESERVED_LOCK) {
263 file->handle.UnLock(RESERVED_BYTE, 1);
264 }
265 if (lock_type == NO_LOCK && type >= SHARED_LOCK) {
266 UnlockReadLock(file);
267 }
268 if (type >= PENDING_LOCK) {
269 file->handle.UnLock(PENDING_BYTE, 1);
270 }
271 file->lock_type = lock_type;
272 return rc;
273 }
274
275 static int SymbianCheckReservedLock(sqlite3_file *id, int *result) {
276 int rc;
277 SymbianFile *file = ConvertToSymbianFile(id);
278 if (file->lock_type >= RESERVED_LOCK) {
279 rc = 1;
280 OSTRACE3("TEST WR-LOCK %d %d (local)\n", pFile->h, rc);
281 } else {
282 rc = file->handle.Lock(RESERVED_BYTE, 1);
283 if (rc == KErrNone) {
284 file->handle.UnLock(RESERVED_BYTE, 1);
285 }
286 rc = !rc;
287 OSTRACE3("TEST WR-LOCK %d %d (remote)\n", file->handle, rc);
288 }
289 *result = rc;
290 return SQLITE_OK;
291 }
292
293 static int SymbianFileControl(sqlite3_file */*id*/,
294 int /*op*/,
295 void */*arg*/) {
296 return SQLITE_OK;
297 }
298
299 static int SymbianSectorSize(sqlite3_file */*id*/) {
300 return SQLITE_DEFAULT_SECTOR_SIZE;
301 }
302
303 static int SymbianDeviceCharacteristics(sqlite3_file */*id*/) {
304 return 0;
305 }
306
307 /*
308 ** This vector defines all the methods that can operate on a
309 ** sqlite3_file for Symbian.
310 */
311 static const sqlite3_io_methods SymbianIoMethod = {
312 1, // iVersion
313 SymbianClose,
314 SymbianRead,
315 SymbianWrite,
316 SymbianTruncate,
317 SymbianSync,
318 SymbianFileSize,
319 SymbianLock,
320 SymbianUnlock,
321 SymbianCheckReservedLock,
322 SymbianFileControl,
323 SymbianSectorSize,
324 SymbianDeviceCharacteristics
325 };
326
327 // ============================================================================
328 // vfs methods begin here
329 // ============================================================================
330 static int SymbianOpen(sqlite3_vfs */*vfs*/,
331 const char *name,
332 sqlite3_file *id,
333 int flags,
334 int *out_flags) {
335 TUint desired_access;
336 TUint share_mode;
337 TInt err = KErrNone;
338 TFileName name_utf16;
339 SymbianFile *file = ConvertToSymbianFile(id);
340
341 if (out_flags) {
342 *out_flags = flags;
343 }
344
345 // if the name is NULL we have to open a temporary file.
346 if (!name) {
347 TPath private_path;
348 TFileName file_name;
349 if (g_fs_session.PrivatePath(private_path) != KErrNone) {
350 return SQLITE_CANTOPEN;
351 }
352 if (file->handle.Temp(g_fs_session,
353 private_path,
354 file_name,
355 EFileWrite) !=
356 KErrNone) {
357 return SQLITE_CANTOPEN;
358 }
359 file->methods = &SymbianIoMethod;
360 file->lock_type = NO_LOCK;
361 file->shared_lock_byte = 0;
362 OpenCounter(+1);
363 return SQLITE_OK;
364 }
365
366 if (UTF8ToUTF16(name, &name_utf16) != KErrNone)
367 return SQLITE_CANTOPEN;
368
369 if (flags & SQLITE_OPEN_READWRITE) {
370 desired_access = EFileWrite;
371 } else {
372 desired_access = EFileRead;
373 }
374 if (flags & SQLITE_OPEN_MAIN_DB) {
375 share_mode = EFileShareReadersOrWriters;
376 } else {
377 share_mode = 0;
378 }
379
380 if (flags & SQLITE_OPEN_CREATE) {
381 err = file->handle.Create(g_fs_session,
382 name_utf16,
383 desired_access | share_mode);
384 if (err != KErrNone && err != KErrAlreadyExists) {
385 return SQLITE_CANTOPEN;
386 }
387 }
388
389 if (err != KErrNone) {
390 err = file->handle.Open(g_fs_session,
391 name_utf16,
392 desired_access | share_mode);
393 if (err != KErrNone && flags & SQLITE_OPEN_READWRITE) {
394 if (out_flags) {
395 *out_flags = (flags | SQLITE_OPEN_READONLY) & ~SQLITE_OPEN_READWRITE;
396 }
397 desired_access = EFileRead;
398 err = file->handle.Open(g_fs_session,
399 name_utf16,
400 desired_access | share_mode);
401 }
402 if (err != KErrNone) {
403 return SQLITE_CANTOPEN;
404 }
405 }
406 file->methods = &SymbianIoMethod;
407 file->lock_type = NO_LOCK;
408 file->shared_lock_byte = 0;
409 OpenCounter(+1);
410 return SQLITE_OK;
411 }
412
413 static int SymbianDelete(sqlite3_vfs */*vfs*/,
414 const char *file_name,
415 int /*sync_dir*/) {
416 assert(file_name);
417 TFileName file_name_utf16;
418
419 if (UTF8ToUTF16(file_name, &file_name_utf16) != KErrNone) {
420 return SQLITE_ERROR;
421 }
422
423 TInt result = g_fs_session.Delete(file_name_utf16);
424 return (result == KErrNone || result == KErrPathNotFound)?
425 SQLITE_OK : SQLITE_IOERR_DELETE;
426 }
427
428 static int SymbianAccess(sqlite3_vfs */*vfs*/,
429 const char *file_name,
430 int flags,
431 int *result) {
432 assert(file_name);
433 TEntry entry;
434 TFileName file_name_utf16;
435
436 if (UTF8ToUTF16(file_name, &file_name_utf16) != KErrNone) {
437 return SQLITE_ERROR;
438 }
439
440 if (g_fs_session.Entry(file_name_utf16, entry) != KErrNone) {
441 *result = 0;
442 return SQLITE_OK;
443 }
444
445 switch (flags) {
446 case SQLITE_ACCESS_READ:
447 case SQLITE_ACCESS_EXISTS:
448 *result = !entry.IsDir();
449 break;
450 case SQLITE_ACCESS_READWRITE:
451 *result = !entry.IsDir() && !entry.IsReadOnly();
452 break;
453 default:
454 return SQLITE_ERROR;
455 }
456
457 return SQLITE_OK;
458 }
459
460 static int SymbianFullPathname(sqlite3_vfs */*vfs*/,
461 const char *relative,
462 int full_len,
463 char *full) {
464 assert(relative);
465 assert(full);
466
467 TParse parse;
468 TPath relative_utf16;
469 TPath base_path;
470 TPtr8 full_utf8(reinterpret_cast<unsigned char*>(full), full_len);
471
472 g_fs_session.PrivatePath(base_path);
473
474 if (UTF8ToUTF16(relative, &relative_utf16) != KErrNone) {
475 return SQLITE_ERROR;
476 }
477
478 if (parse.Set(relative_utf16, &base_path, NULL) != KErrNone) {
479 return SQLITE_ERROR;
480 }
481
482 TDesC full_utf16(parse.FullName());
483 if (UTF16ToUTF8(relative_utf16, &full_utf8) != KErrNone) {
484 return SQLITE_ERROR;
485 }
486
487 full_utf8.PtrZ();
488 return SQLITE_OK;
489 }
490
491 static int SymbianRandomness(sqlite3_vfs */*vfs*/, int buf_len, char *buffer) {
492 assert(buffer);
493 TInt64 seed = User::TickCount();
494 for (TInt i = 0; i < buf_len; i++) {
495 buffer[i] = Math::Rand(seed) % 255;
496 }
497 return SQLITE_OK;
498 }
499
500 static int SymbianSleep(sqlite3_vfs */*vfs*/, int microsec) {
501 User::After(microsec);
502 return SQLITE_OK;
503 }
504
505 int SymbianCurrentTime(sqlite3_vfs */*vfs*/, double *now) {
506 _LIT(kEpoch, "19700101:000000.000000");
507 assert(now);
508 TTime time;
509 TTime epoch_time(kEpoch);
510 TTimeIntervalSeconds interval;
511
512 time.HomeTime();
513 // calculate seconds elapsed since 1-1-1970
514 time.SecondsFrom(epoch_time, interval);
515
516 // Julian date @ 1-1-1970 = 2440587.5
517 // seconds per day = 86400.0
518 *now = interval.Int()/86400.0 + 2440587.5;
519 return SQLITE_OK;
520 }
521
522 static int SymbianGetLastError(sqlite3_vfs */*vfs*/,
523 int /*buf_len*/,
524 char */*buf*/) {
525 assert(buf[0] == '\0');
526 return 0;
527 }
528
529 // Interfaces for opening a shared library, finding entry points
530 // within the shared library, and closing the shared library.
531 // TODO(marcogelmi): implement.
532 #define SymbianDlOpen 0
533 #define SymbianDlError 0
534 #define SymbianDlSym 0
535 #define SymbianDlClose 0
536
537 // Initialize and deinitialize the operating system interface.
538 int sqlite3_os_init(void) {
539 static sqlite3_vfs symbian_vfs = {
540 1, // iVersion
541 sizeof(SymbianFile), // szOsFile
542 KMaxPath, // mxPathname
543 0, // pNext
544 "symbian", // name
545 0, // pAppData
546
547 SymbianOpen, // xOpen
548 SymbianDelete, // xDelete
549 SymbianAccess, // xAccess
550 SymbianFullPathname, // xFullPathname
551 SymbianDlOpen, // xDlOpen
552 SymbianDlError, // xDlError
553 SymbianDlSym, // xDlSym
554 SymbianDlClose, // xDlClose
555 SymbianRandomness, // xRandomness
556 SymbianSleep, // xSleep
557 SymbianCurrentTime, // xCurrentTime
558 SymbianGetLastError // xGetLastError
559 };
560
561 if (g_fs_session.Connect() != KErrNone) {
562 return SQLITE_ERROR;
563 }
564
565 if (g_fs_session.ShareAuto() != KErrNone) {
566 g_fs_session.Close();
567 return SQLITE_ERROR;
568 }
569
570 sqlite3_vfs_register(&symbian_vfs, 1);
571 return SQLITE_OK;
572 }
573
574 int sqlite3_os_end(void) {
575 g_fs_session.Close();
576 return SQLITE_OK;
577 }
578
579 #endif /* OS_SYMBIAN*/
OLDNEW
« no previous file with comments | « third_party/sqlite/src/os_os2.c ('k') | third_party/sqlite/src/os_unix.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698