Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge the nx-devkit changes into trunk. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
03a70c3dae8d912fccd9d72c575dc372 |
User & Date: | drh 2011-12-13 15:37:12.235 |
Context
2011-12-14
| ||
00:37 | Treat a zero return value from the Win32 APIs MultiByteToWideChar and WideCharToMultiByte as an error condition. (check-in: c65e5a36f1 user: mistachkin tags: trunk) | |
2011-12-13
| ||
15:37 | Merge the nx-devkit changes into trunk. (check-in: 03a70c3dae user: drh tags: trunk) | |
15:25 | Update the multiplex.test script to conform to that found in the "experimental" branch off of trunk. (check-in: 2eb79efbff user: drh tags: nx-devkit) | |
2011-12-12
| ||
19:48 | Fix os_unix.c so that, unless 8.3 filenames are actually in use, journal and wal file permissions are assigned correctly even if SQLITE_ENABLE_8_3_NAMES is defined. (check-in: 169e12295c user: dan tags: trunk) | |
Changes
Changes to src/loadext.c.
︙ | ︙ | |||
621 622 623 624 625 626 627 628 629 630 631 632 633 634 | ** Load all automatic extensions. ** ** If anything goes wrong, set an error in the database connection. */ void sqlite3AutoLoadExtensions(sqlite3 *db){ int i; int go = 1; int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*); wsdAutoextInit; if( wsdAutoext.nExt==0 ){ /* Common case: early out without every having to acquire a mutex */ return; } | > | 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 | ** Load all automatic extensions. ** ** If anything goes wrong, set an error in the database connection. */ void sqlite3AutoLoadExtensions(sqlite3 *db){ int i; int go = 1; int rc; int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*); wsdAutoextInit; if( wsdAutoext.nExt==0 ){ /* Common case: early out without every having to acquire a mutex */ return; } |
︙ | ︙ | |||
643 644 645 646 647 648 649 | go = 0; }else{ xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*)) wsdAutoext.aExt[i]; } sqlite3_mutex_leave(mutex); zErrmsg = 0; | | | | 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 | go = 0; }else{ xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*)) wsdAutoext.aExt[i]; } sqlite3_mutex_leave(mutex); zErrmsg = 0; if( xInit && (rc = xInit(db, &zErrmsg, &sqlite3Apis))!=0 ){ sqlite3Error(db, rc, "automatic extension loading failed: %s", zErrmsg); go = 0; } sqlite3_free(zErrmsg); } } |
Changes to src/main.c.
︙ | ︙ | |||
253 254 255 256 257 258 259 260 261 262 263 264 265 266 | ** while any part of SQLite is otherwise in use in any thread. This ** routine is not threadsafe. But it is safe to invoke this routine ** on when SQLite is already shut down. If SQLite is already shut down ** when this routine is invoked, then this routine is a harmless no-op. */ int sqlite3_shutdown(void){ if( sqlite3GlobalConfig.isInit ){ sqlite3_os_end(); sqlite3_reset_auto_extension(); sqlite3GlobalConfig.isInit = 0; } if( sqlite3GlobalConfig.isPCacheInit ){ sqlite3PcacheShutdown(); sqlite3GlobalConfig.isPCacheInit = 0; | > > > > | 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 | ** while any part of SQLite is otherwise in use in any thread. This ** routine is not threadsafe. But it is safe to invoke this routine ** on when SQLite is already shut down. If SQLite is already shut down ** when this routine is invoked, then this routine is a harmless no-op. */ int sqlite3_shutdown(void){ if( sqlite3GlobalConfig.isInit ){ #ifdef SQLITE_EXTRA_SHUTDOWN void SQLITE_EXTRA_SHUTDOWN(void); SQLITE_EXTRA_SHUTDOWN(); #endif sqlite3_os_end(); sqlite3_reset_auto_extension(); sqlite3GlobalConfig.isInit = 0; } if( sqlite3GlobalConfig.isPCacheInit ){ sqlite3PcacheShutdown(); sqlite3GlobalConfig.isPCacheInit = 0; |
︙ | ︙ | |||
2235 2236 2237 2238 2239 2240 2241 | */ sqlite3Error(db, SQLITE_OK, 0); sqlite3RegisterBuiltinFunctions(db); /* Load automatic extensions - extensions that have been registered ** using the sqlite3_automatic_extension() API. */ | > > | | | | > | 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 | */ sqlite3Error(db, SQLITE_OK, 0); sqlite3RegisterBuiltinFunctions(db); /* Load automatic extensions - extensions that have been registered ** using the sqlite3_automatic_extension() API. */ rc = sqlite3_errcode(db); if( rc==SQLITE_OK ){ sqlite3AutoLoadExtensions(db); rc = sqlite3_errcode(db); if( rc!=SQLITE_OK ){ goto opendb_out; } } #ifdef SQLITE_ENABLE_FTS1 if( !db->mallocFailed ){ extern int sqlite3Fts1Init(sqlite3*); rc = sqlite3Fts1Init(db); } |
︙ | ︙ |
Changes to src/test_multiplex.c.
︙ | ︙ | |||
209 210 211 212 213 214 215 | static int multiplexStrlen30(const char *z){ const char *z2 = z; if( z==0 ) return 0; while( *z2 ){ z2++; } return 0x3fffffff & (int)(z2 - z); } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 | static int multiplexStrlen30(const char *z){ const char *z2 = z; if( z==0 ) return 0; while( *z2 ){ z2++; } return 0x3fffffff & (int)(z2 - z); } /* Compute the filename for the iChunk-th chunk */ static int multiplexSubFilename(multiplexGroup *pGroup, int iChunk){ if( iChunk>=pGroup->nReal ){ struct multiplexReal *p; p = sqlite3_realloc(pGroup->aReal, (iChunk+1)*sizeof(*p)); if( p==0 ){ return SQLITE_NOMEM; } memset(&p[pGroup->nReal], 0, sizeof(p[0])*(iChunk+1-pGroup->nReal)); pGroup->aReal = p; pGroup->nReal = iChunk+1; } if( pGroup->zName && pGroup->aReal[iChunk].z==0 ){ char *z; int n = pGroup->nName; pGroup->aReal[iChunk].z = z = sqlite3_malloc( n+4 ); if( z==0 ){ return SQLITE_NOMEM; } memcpy(z, pGroup->zName, n+1); |
︙ | ︙ | |||
457 458 459 460 461 462 463 464 465 466 467 468 469 470 | sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */ int nName; int sz; char *zToFree = 0; UNUSED_PARAMETER(pVfs); memset(pConn, 0, pVfs->szOsFile); /* We need to create a group structure and manage ** access to this group of files. */ multiplexEnter(); pMultiplexOpen = (multiplexConn*)pConn; | > < < < < < < < < < < < < < < | | < > > > | | | | | | | | | | | | | | | | | | < | | > | 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 | sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */ int nName; int sz; char *zToFree = 0; UNUSED_PARAMETER(pVfs); memset(pConn, 0, pVfs->szOsFile); assert( zName || (flags & SQLITE_OPEN_DELETEONCLOSE) ); /* We need to create a group structure and manage ** access to this group of files. */ multiplexEnter(); pMultiplexOpen = (multiplexConn*)pConn; if( rc==SQLITE_OK ){ /* allocate space for group */ nName = zName ? multiplexStrlen30(zName) : 0; sz = sizeof(multiplexGroup) /* multiplexGroup */ + nName + 1; /* zName */ pGroup = sqlite3_malloc( sz ); if( pGroup==0 ){ rc = SQLITE_NOMEM; } } if( rc==SQLITE_OK ){ /* assign pointers to extra space allocated */ memset(pGroup, 0, sz); pMultiplexOpen->pGroup = pGroup; pGroup->bEnabled = -1; pGroup->szChunk = SQLITE_MULTIPLEX_CHUNK_SIZE; if( zName ){ char *p = (char *)&pGroup[1]; if( flags & SQLITE_OPEN_URI ){ const char *zChunkSize; zChunkSize = sqlite3_uri_parameter(zName, "chunksize"); if( zChunkSize ){ unsigned int n = 0; int i; for(i=0; zChunkSize[i]>='0' && zChunkSize[i]<='9'; i++){ n = n*10 + zChunkSize[i] - '0'; } if( n>0 ){ pGroup->szChunk = (n+0xffff)&~0xffff; }else{ /* A zero or negative chunksize disabled the multiplexor */ pGroup->bEnabled = 0; } } } pGroup->zName = p; memcpy(pGroup->zName, zName, nName+1); pGroup->nName = nName; } pGroup->flags = flags; rc = multiplexSubFilename(pGroup, 1); if( rc==SQLITE_OK ){ pSubOpen = multiplexSubOpen(pGroup, 0, &rc, pOutFlags); } if( pSubOpen ){ int exists, rc2, rc3; |
︙ | ︙ | |||
792 793 794 795 796 797 798 | /* Pass xFileSize requests through to the original VFS. ** Aggregate the size of all the chunks before returning. */ static int multiplexFileSize(sqlite3_file *pConn, sqlite3_int64 *pSize){ multiplexConn *p = (multiplexConn*)pConn; multiplexGroup *pGroup = p->pGroup; int rc = SQLITE_OK; | < | | | | | < | | < | < < | > > > | > | | < < < | | | | < < < | 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 | /* Pass xFileSize requests through to the original VFS. ** Aggregate the size of all the chunks before returning. */ static int multiplexFileSize(sqlite3_file *pConn, sqlite3_int64 *pSize){ multiplexConn *p = (multiplexConn*)pConn; multiplexGroup *pGroup = p->pGroup; int rc = SQLITE_OK; int i; multiplexEnter(); if( !pGroup->bEnabled ){ sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL); if( pSubOpen==0 ){ rc = SQLITE_IOERR_FSTAT; }else{ rc = pSubOpen->pMethods->xFileSize(pSubOpen, pSize); } }else{ sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; *pSize = 0; for(i=0; rc==SQLITE_OK; i++){ sqlite3_file *pSubOpen = 0; int exists = 0; rc = multiplexSubFilename(pGroup, i); if( rc!=SQLITE_OK ) break; if( pGroup->nReal>i && pGroup->aReal[i].p!=0 ){ exists = 1; }else if( (pGroup->flags & SQLITE_OPEN_DELETEONCLOSE)==0 ){ const char *zReal = pGroup->aReal[i].z; rc = pOrigVfs->xAccess(pOrigVfs, zReal, SQLITE_ACCESS_EXISTS, &exists); } if( exists==0 ){ /* stop at first "gap" or IO error. */ break; } if( rc==SQLITE_OK ){ pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL); } assert( pSubOpen || rc!=SQLITE_OK ); if( rc==SQLITE_OK ){ sqlite3_int64 sz = 0; rc = pSubOpen->pMethods->xFileSize(pSubOpen, &sz); if( rc==SQLITE_OK && sz>pGroup->szChunk ){ rc = SQLITE_IOERR_FSTAT; } *pSize += sz; } } } multiplexLeave(); return rc; } |
︙ | ︙ | |||
1187 1188 1189 1190 1191 1192 1193 | UNUSED_PARAMETER(objv); pResult = Tcl_NewObj(); multiplexEnter(); for(pGroup=gMultiplex.pGroups; pGroup; pGroup=pGroup->pNext){ pGroupTerm = Tcl_NewObj(); | > | | > > > | 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 | UNUSED_PARAMETER(objv); pResult = Tcl_NewObj(); multiplexEnter(); for(pGroup=gMultiplex.pGroups; pGroup; pGroup=pGroup->pNext){ pGroupTerm = Tcl_NewObj(); if( pGroup->zName ){ pGroup->zName[pGroup->nName] = '\0'; Tcl_ListObjAppendElement(interp, pGroupTerm, Tcl_NewStringObj(pGroup->zName, -1)); }else{ Tcl_ListObjAppendElement(interp, pGroupTerm, Tcl_NewObj()); } Tcl_ListObjAppendElement(interp, pGroupTerm, Tcl_NewIntObj(pGroup->nName)); Tcl_ListObjAppendElement(interp, pGroupTerm, Tcl_NewIntObj(pGroup->flags)); /* count number of chunks with open handles */ for(i=0; i<pGroup->nReal; i++){ |
︙ | ︙ |
Changes to test/multiplex.test.
︙ | ︙ | |||
9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/malloc_common.tcl set g_chunk_size [ expr ($::SQLITE_MAX_PAGE_SIZE*16384) ] set g_max_chunks 32 # This handles appending the chunk number # to the end of the filename. if # SQLITE_MULTIPLEX_EXT_OVWR is defined, then | > > > > > > > > > > | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/malloc_common.tcl # The tests in this file assume that SQLite is compiled without # ENABLE_8_3_NAMES. # ifcapable 8_3_names { puts -nonewline "SQLite compiled with SQLITE_ENABLE_8_3_NAMES. " puts "Skipping tests multiplex-*." finish_test return } set g_chunk_size [ expr ($::SQLITE_MAX_PAGE_SIZE*16384) ] set g_max_chunks 32 # This handles appending the chunk number # to the end of the filename. if # SQLITE_MULTIPLEX_EXT_OVWR is defined, then |
︙ | ︙ |
Added test/multiplex3.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | # 2011 December 13 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # # This file contains tests for error (IO, OOM etc.) handling when using # the multiplexor extension with 8.3 filenames. # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/malloc_common.tcl set ::testprefix multiplex3 ifcapable !8_3_names { puts -nonewline "SQLite compiled without SQLITE_ENABLE_8_3_NAMES. " puts "Skipping tests multiplex3-*." finish_test return } db close sqlite3_shutdown sqlite3_config_uri 1 autoinstall_test_functions sqlite3_multiplex_initialize "" 1 proc destroy_vfs_stack {} { generic_unregister stack sqlite3_multiplex_shutdown } proc multiplex_delete_db {} { forcedelete test.db for {set i 1} {$i <= 1000} {incr i} { forcedelete test.[format %03d $i] } } # Procs to save and restore the current muliplexed database. # proc multiplex_save_db {} { foreach f [glob -nocomplain sv_test.*] { forcedelete $f } foreach f [glob -nocomplain test.*] { forcecopy $f "sv_$f" } } proc multiplex_restore_db {} { foreach f [glob -nocomplain test.*] {forcedelete $f} foreach f [glob -nocomplain sv_test.*] {forcecopy $f [string range $f 3 end]} } do_test 1.0 { multiplex_delete_db sqlite3 db file:test.db?8_3_names=1 sqlite3_multiplex_control db main chunk_size [expr 256*1024] execsql { CREATE TABLE t1(a PRIMARY KEY, b); INSERT INTO t1 VALUES(randomblob(15), randomblob(2000)); INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1; -- 2 INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1; -- 4 INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1; -- 8 INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1; -- 16 INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1; -- 32 INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1; -- 64 INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1; -- 128 INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1; -- 256 INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1; -- 512 } set ::cksum1 [execsql {SELECT md5sum(a, b) FROM t1 ORDER BY a}] db close multiplex_save_db } {} do_faultsim_test 1 -prep { multiplex_restore_db sqlite3 db file:test.db?8_3_names=1 sqlite3_multiplex_control db main chunk_size [expr 256*1024] } -body { execsql "UPDATE t1 SET a=randomblob(12), b=randomblob(1500) WHERE (rowid%32)=0" } -test { faultsim_test_result {0 {}} if {$testrc!=0} { set cksum2 [execsql {SELECT md5sum(a, b) FROM t1 ORDER BY a}] if {$cksum2 != $::cksum1} { error "data mismatch" } } } catch { db close } sqlite3_multiplex_shutdown finish_test |