-C Add\sthe\sability\sto\slimit\sfilenames\sto\s8+3\susing\sthe\nSQLITE_ENABLE_8_3_NAMES\scompile-time\soption\stogether\swith\sa\sURI\nparameter\sof\s"8_3_names=1".
-D 2011-05-17T20:36:21.474
+C Update\smultiplex\sVFS\sto\shandle\sempty\sfilenames\swhich\scan\soccur\sfor\sduring\svacuuming\s(temp\sfile\snames.)
+D 2011-05-18T02:22:41.100
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 11dcc00a8d0e5202def00e81732784fb0cc4fe1d
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F src/test_journal.c 785edd54f963aefb3c1628124170a56697c68c70
F src/test_loadext.c df586c27176e3c2cb2e099c78da67bf14379a56e
F src/test_malloc.c 7ca7be34e0e09ef0ed6619544552ed95732e41f6
-F src/test_multiplex.c fdabd793ee7a9642c5a8a470def2347144c46d05
+F src/test_multiplex.c c71f0a0cdf2b89a441e0bcefb2fcdf1dd358a820
F src/test_multiplex.h e99c571bc4968b7a9363b661481f3934bfead61d
F src/test_mutex.c a6bd7b9cf6e19d989e31392b06ac8d189f0d573e
F src/test_onefile.c 40cf9e212a377a6511469384a64b01e6e34b2eec
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
F test/misc7.test 29032efcd3d826fbd409e2a7af873e7939f4a4e3
F test/misuse.test 30b3a458e5a70c31e74c291937b6c82204c59f33
-F test/multiplex.test a88f3e2c16e567e72be7296195c59fbdd6a8d3d4
+F test/multiplex.test 7a8a50c8ed72dfcf4db9ebae977f7a63184639d8
F test/mutex1.test 78b2b9bb320e51d156c4efdb71b99b051e7a4b41
F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
F test/nan.test dc212a22b36109fd1ae37154292444ef249c5ec2
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P 9593a640795458ce6e57e02dd5d702b642858f76
-R 87dd50ad185017288f71d71ad9ceabb5
-U drh
-Z 1ba151bdfae18403ba429fed62365eed
+P 96d609856025919571f781207dfa6a24b1732e8d
+R 2d9bd612a3d2dc8f2665702baad38baa
+U shaneh
+Z d27048d3dae68da084505a60e1541c3b
** 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.
*/
-int multiplexStrlen30(const char *z){
+static int multiplexStrlen30(const char *z){
const char *z2 = z;
if( z==0 ) return 0;
while( *z2 ){ z2++; }
return 0x3fffffff & (int)(z2 - z);
}
+/*
+** Create a temporary file name in zBuf. zBuf must be big enough to
+** hold at pOrigVfs->mxPathname characters. This function departs
+** from the traditional temporary name generation in the os_win
+** and os_unix VFS in several ways, but is necessary so that
+** the file name is known for temporary files (like those used
+** during vacuum.)
+**
+** N.B. This routine assumes your underlying VFS is ok with using
+** "/" as a directory seperator. This is the default for UNIXs
+** and is allowed (even mixed) for most versions of Windows.
+*/
+static int multiplexGetTempname(sqlite3_vfs *pOrigVfs, int nBuf, char *zBuf){
+ static char zChars[] =
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789";
+ int i,j;
+ int attempts = 0;
+ int exists = 0;
+ int rc = SQLITE_ERROR;
+
+ /* Check that the output buffer is large enough for
+ ** pVfs->mxPathname characters.
+ */
+ if( pOrigVfs->mxPathname <= nBuf ){
+
+ /* sqlite3_temp_directory should always be less than
+ ** pVfs->mxPathname characters.
+ */
+ sqlite3_snprintf(pOrigVfs->mxPathname,
+ zBuf,
+ "%s/",
+ sqlite3_temp_directory ? sqlite3_temp_directory : ".");
+
+ /* Check that the output buffer is large enough for the temporary file
+ ** name.
+ */
+ j = multiplexStrlen30(zBuf);
+ if( (j + 8 + 1 + 3 + 1) <= nBuf ){
+ /* Make 3 attempts to generate a unique name. */
+ do {
+ attempts++;
+ sqlite3_randomness(8, &zBuf[j]);
+ for(i=0; i<8; i++){
+ zBuf[j+i] = (char)zChars[ ((unsigned char)zBuf[j+i])%(sizeof(zChars)-1) ];
+ }
+ memcpy(&zBuf[j+i], ".tmp", 5);
+ rc = pOrigVfs->xAccess(pOrigVfs, zBuf, SQLITE_ACCESS_EXISTS, &exists);
+ } while ( (rc==SQLITE_OK) && exists && (attempts<3) );
+ if( rc==SQLITE_OK && exists ){
+ rc = SQLITE_ERROR;
+ }
+ }
+ }
+
+ return rc;
+}
+
/* Translate an sqlite3_file* that is really a multiplexGroup* into
** the sqlite3_file* for the underlying original VFS.
*/
int flags, /* Flags to control the opening */
int *pOutFlags /* Flags showing results of opening */
){
- int rc; /* Result code */
+ int rc = SQLITE_OK; /* Result code */
multiplexConn *pMultiplexOpen; /* The new multiplex file descriptor */
multiplexGroup *pGroup; /* Corresponding multiplexGroup object */
sqlite3_file *pSubOpen; /* Real file descriptor */
sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */
- int nName = multiplexStrlen30(zName);
+ int nName;
int i;
int sz;
*/
multiplexEnter();
pMultiplexOpen = (multiplexConn*)pConn;
- /* allocate space for group */
- sz = sizeof(multiplexGroup) /* multiplexGroup */
- + (sizeof(sqlite3_file *)*SQLITE_MULTIPLEX_MAX_CHUNKS) /* pReal[] */
- + (pOrigVfs->szOsFile*SQLITE_MULTIPLEX_MAX_CHUNKS) /* *pReal */
- + SQLITE_MULTIPLEX_MAX_CHUNKS /* bOpen[] */
- + nName + 1; /* zName */
+
+ /* If the second argument to this function is NULL, generate a
+ ** temporary file name to use. This will be handled by the
+ ** original xOpen method. We just need to allocate space for
+ ** it.
+ */
+ if( !zName ){
+ rc = multiplexGetTempname(pOrigVfs, pOrigVfs->mxPathname, gMultiplex.zName);
+ zName = gMultiplex.zName;
+ }
+
+ if( rc==SQLITE_OK ){
+ /* allocate space for group */
+ nName = multiplexStrlen30(zName);
+ sz = sizeof(multiplexGroup) /* multiplexGroup */
+ + (sizeof(sqlite3_file *)*SQLITE_MULTIPLEX_MAX_CHUNKS) /* pReal[] */
+ + (pOrigVfs->szOsFile*SQLITE_MULTIPLEX_MAX_CHUNKS) /* *pReal */
+ + SQLITE_MULTIPLEX_MAX_CHUNKS /* bOpen[] */
+ + nName + 1; /* zName */
#ifndef SQLITE_MULTIPLEX_EXT_OVWR
- sz += SQLITE_MULTIPLEX_EXT_SZ;
- assert(nName+SQLITE_MULTIPLEX_EXT_SZ < pOrigVfs->mxPathname);
+ sz += SQLITE_MULTIPLEX_EXT_SZ;
+ assert(nName+SQLITE_MULTIPLEX_EXT_SZ < pOrigVfs->mxPathname);
#else
- assert(nName >= SQLITE_MULTIPLEX_EXT_SZ);
- assert(nName < pOrigVfs->mxPathname);
+ assert(nName >= SQLITE_MULTIPLEX_EXT_SZ);
+ assert(nName < pOrigVfs->mxPathname);
#endif
- pGroup = sqlite3_malloc( sz );
- if( pGroup==0 ){
- rc=SQLITE_NOMEM;
- }else{
+ pGroup = sqlite3_malloc( sz );
+ if( pGroup==0 ){
+ rc=SQLITE_NOMEM;
+ }
+ }
+
+ if( rc==SQLITE_OK ){
/* assign pointers to extra space allocated */
char *p = (char *)&pGroup[1];
pMultiplexOpen->pGroup = pGroup;
}
rc2 = pOrigVfs->xAccess(pOrigVfs, gMultiplex.zName,
SQLITE_ACCESS_EXISTS, &exists);
- if( rc2==SQLITE_OK && exists){
+ if( rc2==SQLITE_OK && exists ){
/* if it exists, delete it */
rc2 = pOrigVfs->xDelete(pOrigVfs, gMultiplex.zName, syncDir);
if( rc2!=SQLITE_OK ) rc = rc2;
}
}
+#-------------------------------------------------------------------------
+# Test that you can vacuum a multiplex'ed DB.
+
+ifcapable vacuum {
+
+do_test multiplex-6.0.0 {
+ multiplex_delete test.db
+ sqlite3_multiplex_initialize "" 1
+ sqlite3 db test.db
+ multiplex_set db main 4096 16
+} {SQLITE_OK}
+
+do_test multiplex-6.1.0 {
+ execsql {
+ PRAGMA page_size=1024;
+ PRAGMA journal_mode=DELETE;
+ PRAGMA auto_vacuum=OFF;
+ }
+ execsql {
+ CREATE TABLE t1(a, b);
+ INSERT INTO t1 VALUES(1, randomblob($g_chunk_size));
+ INSERT INTO t1 VALUES(2, randomblob($g_chunk_size));
+ }
+} {}
+do_test multiplex-6.2.1 { file size [multiplex_name test.db 0] } [list $g_chunk_size]
+do_test multiplex-6.2.2 { file size [multiplex_name test.db 1] } [list $g_chunk_size]
+
+do_test multiplex-6.3.0 {
+ execsql { VACUUM }
+} {}
+
+do_test multiplex-6.99 {
+ db close
+ multiplex_delete test.db
+ sqlite3_multiplex_shutdown
+} {SQLITE_OK}
+
+}
+
+
catch { sqlite3_multiplex_shutdown }
finish_test