Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Remove the mutex from test_multiplex.c. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
6374978e8f1ac091394a9f5a1896be92 |
User & Date: | dan 2016-10-27 14:51:02.086 |
Context
2016-10-31
| ||
16:49 | Add the SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE sqlite3_dbconfig() option - for disabling SQLite's default checkpoint-on-close behaviour. (check-in: 6d142025c7 user: dan tags: trunk) | |
16:16 | Add the SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE sqlite3_dbconfig() option - for disabling SQLite's default checkpoint-on-close behaviour. (Closed-Leaf check-in: 093d2fc228 user: dan tags: no-ckpt-on-close) | |
2016-10-27
| ||
14:51 | Remove the mutex from test_multiplex.c. (check-in: 6374978e8f user: dan tags: trunk) | |
01:02 | Make sure left-join markings are transferred to the virtual scalar subexpressions when decomposing a vector comparison in the ON clause of a LEFT JOIN. Fix for ticket [fef4bb4bd9185ec8f]. (check-in: 619f5cc717 user: drh tags: trunk) | |
Changes
Changes to src/test_multiplex.c.
︙ | ︙ | |||
64 65 66 67 68 69 70 | ** the multiplex VFS shim can be built as a loadable ** module. */ #define UNUSED_PARAMETER(x) (void)(x) #define MAX_PAGE_SIZE 0x10000 #define DEFAULT_SECTOR_SIZE 0x1000 | < < < < < < < < < < < < < | 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | ** the multiplex VFS shim can be built as a loadable ** module. */ #define UNUSED_PARAMETER(x) (void)(x) #define MAX_PAGE_SIZE 0x10000 #define DEFAULT_SECTOR_SIZE 0x1000 /* Maximum chunk number */ #define MX_CHUNK_NUMBER 299 /* First chunk for rollback journal files */ #define SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET 400 #define SQLITE_MULTIPLEX_WAL_8_3_OFFSET 700 |
︙ | ︙ | |||
135 136 137 138 139 140 141 | int nReal; /* Number of chunks */ char *zName; /* Base filename of this group */ int nName; /* Length of base filename */ int flags; /* Flags used for original opening */ unsigned int szChunk; /* Chunk size used for this group */ unsigned char bEnabled; /* TRUE to use Multiplex VFS for this file */ unsigned char bTruncate; /* TRUE to enable truncation of databases */ | < | 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | int nReal; /* Number of chunks */ char *zName; /* Base filename of this group */ int nName; /* Length of base filename */ int flags; /* Flags used for original opening */ unsigned int szChunk; /* Chunk size used for this group */ unsigned char bEnabled; /* TRUE to use Multiplex VFS for this file */ unsigned char bTruncate; /* TRUE to enable truncation of databases */ }; /* ** An instance of the following object represents each open connection ** to a file that is multiplex'ed. This object is a ** subclass of sqlite3_file. The sqlite3_file object for the underlying ** VFS is appended to this structure. |
︙ | ︙ | |||
183 184 185 186 187 188 189 | */ sqlite3_io_methods sIoMethodsV1; sqlite3_io_methods sIoMethodsV2; /* True when this shim has been initialized. */ int isInitialized; | < < < < < < < < < < < < < < < < < < < | 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | */ sqlite3_io_methods sIoMethodsV1; sqlite3_io_methods sIoMethodsV2; /* True when this shim has been initialized. */ int isInitialized; } gMultiplex; /************************* Utility Routines *********************************/ /* ** Compute a string length that is limited to what can be stored in ** lower 30 bits of a 32-bit signed integer. ** ** The value returned will never be negative. Nor will it ever be greater ** than the actual length of the string. For very long strings (greater ** than 1GiB) the value returned might be less than the true string length. |
︙ | ︙ | |||
515 516 517 518 519 520 521 | 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. */ | < | 482 483 484 485 486 487 488 489 490 491 492 493 494 495 | 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. */ pMultiplexOpen = (multiplexConn*)pConn; if( rc==SQLITE_OK ){ /* allocate space for group */ nName = zName ? multiplexStrlen30(zName) : 0; sz = sizeof(multiplexGroup) /* multiplexGroup */ + nName + 1; /* zName */ |
︙ | ︙ | |||
622 623 624 625 626 627 628 | if( rc==SQLITE_OK ){ if( pSubOpen->pMethods->iVersion==1 ){ pMultiplexOpen->base.pMethods = &gMultiplex.sIoMethodsV1; }else{ pMultiplexOpen->base.pMethods = &gMultiplex.sIoMethodsV2; } | < < < < < | 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 | if( rc==SQLITE_OK ){ if( pSubOpen->pMethods->iVersion==1 ){ pMultiplexOpen->base.pMethods = &gMultiplex.sIoMethodsV1; }else{ pMultiplexOpen->base.pMethods = &gMultiplex.sIoMethodsV2; } }else{ multiplexFreeComponents(pGroup); sqlite3_free(pGroup); } } sqlite3_free(zToFree); return rc; } /* ** This is the xDelete method used for the "multiplex" VFS. ** It attempts to delete the filename specified. |
︙ | ︙ | |||
734 735 736 737 738 739 740 | ** The group structure for this file is unlinked from ** our list of groups and freed. */ static int multiplexClose(sqlite3_file *pConn){ multiplexConn *p = (multiplexConn*)pConn; multiplexGroup *pGroup = p->pGroup; int rc = SQLITE_OK; | < < < < < < < < < | 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 | ** The group structure for this file is unlinked from ** our list of groups and freed. */ static int multiplexClose(sqlite3_file *pConn){ multiplexConn *p = (multiplexConn*)pConn; multiplexGroup *pGroup = p->pGroup; int rc = SQLITE_OK; multiplexFreeComponents(pGroup); sqlite3_free(pGroup); return rc; } /* Pass xRead requests thru to the original VFS after ** determining the correct chunk to operate on. ** Break up reads across chunk boundaries. */ |
︙ | ︙ | |||
841 842 843 844 845 846 847 | ** determining the correct chunk to operate on. Delete any ** chunks above the truncate mark. */ static int multiplexTruncate(sqlite3_file *pConn, sqlite3_int64 size){ multiplexConn *p = (multiplexConn*)pConn; multiplexGroup *pGroup = p->pGroup; int rc = SQLITE_OK; | < | 793 794 795 796 797 798 799 800 801 802 803 804 805 806 | ** determining the correct chunk to operate on. Delete any ** chunks above the truncate mark. */ static int multiplexTruncate(sqlite3_file *pConn, sqlite3_int64 size){ multiplexConn *p = (multiplexConn*)pConn; multiplexGroup *pGroup = p->pGroup; int rc = SQLITE_OK; if( !pGroup->bEnabled ){ sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0); if( pSubOpen==0 ){ rc = SQLITE_IOERR_TRUNCATE; }else{ rc = pSubOpen->pMethods->xTruncate(pSubOpen, size); } |
︙ | ︙ | |||
873 874 875 876 877 878 879 | pSubOpen = multiplexSubOpen(pGroup, iBaseGroup, &rc, 0, 0); if( pSubOpen ){ rc = pSubOpen->pMethods->xTruncate(pSubOpen, size % pGroup->szChunk); } } if( rc ) rc = SQLITE_IOERR_TRUNCATE; } | < < < < < | 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 | pSubOpen = multiplexSubOpen(pGroup, iBaseGroup, &rc, 0, 0); if( pSubOpen ){ rc = pSubOpen->pMethods->xTruncate(pSubOpen, size % pGroup->szChunk); } } if( rc ) rc = SQLITE_IOERR_TRUNCATE; } return rc; } /* Pass xSync requests through to the original VFS without change */ static int multiplexSync(sqlite3_file *pConn, int flags){ multiplexConn *p = (multiplexConn*)pConn; multiplexGroup *pGroup = p->pGroup; int rc = SQLITE_OK; int i; for(i=0; i<pGroup->nReal; i++){ sqlite3_file *pSubOpen = pGroup->aReal[i].p; if( pSubOpen ){ int rc2 = pSubOpen->pMethods->xSync(pSubOpen, flags); if( rc2!=SQLITE_OK ) rc = rc2; } } return rc; } /* 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; if( !pGroup->bEnabled ){ sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0); if( pSubOpen==0 ){ rc = SQLITE_IOERR_FSTAT; }else{ rc = pSubOpen->pMethods->xFileSize(pSubOpen, pSize); } }else{ *pSize = 0; for(i=0; rc==SQLITE_OK; i++){ sqlite3_int64 sz = multiplexSubSize(pGroup, i, &rc); if( sz==0 ) break; *pSize = i*(sqlite3_int64)pGroup->szChunk + sz; } } return rc; } /* Pass xLock requests through to the original VFS unchanged. */ static int multiplexLock(sqlite3_file *pConn, int lock){ multiplexConn *p = (multiplexConn*)pConn; |
︙ | ︙ | |||
1147 1148 1149 1150 1151 1152 1153 | */ int sqlite3_multiplex_initialize(const char *zOrigVfsName, int makeDefault){ sqlite3_vfs *pOrigVfs; if( gMultiplex.isInitialized ) return SQLITE_MISUSE; pOrigVfs = sqlite3_vfs_find(zOrigVfsName); if( pOrigVfs==0 ) return SQLITE_ERROR; assert( pOrigVfs!=&gMultiplex.sThisVfs ); | < < < < < | 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 | */ int sqlite3_multiplex_initialize(const char *zOrigVfsName, int makeDefault){ sqlite3_vfs *pOrigVfs; if( gMultiplex.isInitialized ) return SQLITE_MISUSE; pOrigVfs = sqlite3_vfs_find(zOrigVfsName); if( pOrigVfs==0 ) return SQLITE_ERROR; assert( pOrigVfs!=&gMultiplex.sThisVfs ); gMultiplex.isInitialized = 1; gMultiplex.pOrigVfs = pOrigVfs; gMultiplex.sThisVfs = *pOrigVfs; gMultiplex.sThisVfs.szOsFile += sizeof(multiplexConn); gMultiplex.sThisVfs.zName = SQLITE_MULTIPLEX_VFS_NAME; gMultiplex.sThisVfs.xOpen = multiplexOpen; gMultiplex.sThisVfs.xDelete = multiplexDelete; |
︙ | ︙ | |||
1210 1211 1212 1213 1214 1215 1216 | ** ** THIS ROUTINE IS NOT THREADSAFE. Call this routine exactly once while ** shutting down in order to free all remaining multiplex groups. */ int sqlite3_multiplex_shutdown(int eForce){ int rc = SQLITE_OK; if( gMultiplex.isInitialized==0 ) return SQLITE_MISUSE; | < < < < < < < | 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 | ** ** THIS ROUTINE IS NOT THREADSAFE. Call this routine exactly once while ** shutting down in order to free all remaining multiplex groups. */ int sqlite3_multiplex_shutdown(int eForce){ int rc = SQLITE_OK; if( gMultiplex.isInitialized==0 ) return SQLITE_MISUSE; gMultiplex.isInitialized = 0; sqlite3_vfs_unregister(&gMultiplex.sThisVfs); memset(&gMultiplex, 0, sizeof(gMultiplex)); return rc; } /***************************** Test Code ***********************************/ #ifdef SQLITE_TEST |
︙ | ︙ | |||
1295 1296 1297 1298 1299 1300 1301 | /* Call sqlite3_multiplex_shutdown() */ rc = sqlite3_multiplex_shutdown(objc==2); Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC); return TCL_OK; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 | /* Call sqlite3_multiplex_shutdown() */ rc = sqlite3_multiplex_shutdown(objc==2); Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC); return TCL_OK; } /* ** Tclcmd: test_multiplex_control HANDLE DBNAME SUB-COMMAND ?INT-VALUE? */ static int SQLITE_TCLAPI test_multiplex_control( ClientData cd, Tcl_Interp *interp, int objc, |
︙ | ︙ | |||
1424 1425 1426 1427 1428 1429 1430 | int Sqlitemultiplex_Init(Tcl_Interp *interp){ static struct { char *zName; Tcl_ObjCmdProc *xProc; } aCmd[] = { { "sqlite3_multiplex_initialize", test_multiplex_initialize }, { "sqlite3_multiplex_shutdown", test_multiplex_shutdown }, | < | 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 | int Sqlitemultiplex_Init(Tcl_Interp *interp){ static struct { char *zName; Tcl_ObjCmdProc *xProc; } aCmd[] = { { "sqlite3_multiplex_initialize", test_multiplex_initialize }, { "sqlite3_multiplex_shutdown", test_multiplex_shutdown }, { "sqlite3_multiplex_control", test_multiplex_control }, }; int i; for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ Tcl_CreateObjCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); } return TCL_OK; } #endif |
Changes to test/multiplex.test.
︙ | ︙ | |||
191 192 193 194 195 196 197 | do_test multiplex-2.3.1 { sqlite3 db2 test2.x db2 close } {} unset -nocomplain ::log | | | | | | | > | 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 | do_test multiplex-2.3.1 { sqlite3 db2 test2.x db2 close } {} unset -nocomplain ::log #do_test multiplex-2.4.1 { # sqlite3_multiplex_shutdown #} {SQLITE_MISUSE} do_test multiplex-2.4.2 { execsql { INSERT INTO t1 VALUES(3, randomblob(1100)) } } {} #do_test multiplex-2.4.3 { # set ::log #} {SQLITE_MISUSE {sqlite3_multiplex_shutdown() called while database connections are still open}} do_test multiplex-2.4.4 { file size [multiplex_name test.x 0] } {7168} do_test multiplex-2.4.5 { db close sqlite3 db test.x db eval vacuum db close glob test.x* |
︙ | ︙ | |||
441 442 443 444 445 446 447 | # sqlite3_multiplex_initialize "" 1 multiplex_set db main 32768 16 # Return a list of all currently defined multiplexs. proc multiplex_list {} { | | < < < < | 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 | # sqlite3_multiplex_initialize "" 1 multiplex_set db main 32768 16 # Return a list of all currently defined multiplexs. proc multiplex_list {} { glob -nocomplain test2.db* } do_test multiplex-4.1.6 { multiplex_delete test2.db sqlite3 db test2.db db eval {CREATE TABLE t2(x); INSERT INTO t2 VALUES('tab-t2');} set res [multiplex_list] |
︙ | ︙ | |||
490 491 492 493 494 495 496 | db2 close set res [multiplex_list] list [regexp {test2.db} $res] } {1} do_test multiplex-4.1.12 { db close multiplex_list | | | 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 | db2 close set res [multiplex_list] list [regexp {test2.db} $res] } {1} do_test multiplex-4.1.12 { db close multiplex_list } {test2.db} #------------------------------------------------------------------------- # The following tests test that the multiplex VFS handles malloc and IO # errors. # |
︙ | ︙ |