mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-14 00:22:38 +03:00
Merge the nx-devkit changes into trunk.
FossilOrigin-Name: cf3bccc2e944cd2dd3efb8554682994a06115f16
This commit is contained in:
16
manifest
16
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Add\sstdio\ssupport\sto\sthe\squota\sVFS.
|
C Merge\sthe\snx-devkit\schanges\sinto\strunk.
|
||||||
D 2011-12-15T17:44:33.259
|
D 2011-12-16T13:42:03.408
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in 5b4a3e12a850b021547e43daf886b25133b44c07
|
F Makefile.in 5b4a3e12a850b021547e43daf886b25133b44c07
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
@@ -214,7 +214,7 @@ F src/test_intarray.h 489edb9068bb926583445cb02589344961054207
|
|||||||
F src/test_journal.c 03313c693cca72959dcaaf79f8d76f21c01e19ff
|
F src/test_journal.c 03313c693cca72959dcaaf79f8d76f21c01e19ff
|
||||||
F src/test_loadext.c df586c27176e3c2cb2e099c78da67bf14379a56e
|
F src/test_loadext.c df586c27176e3c2cb2e099c78da67bf14379a56e
|
||||||
F src/test_malloc.c 8d416f29ad8573f32601f6056c9d2b17472e9ad5
|
F src/test_malloc.c 8d416f29ad8573f32601f6056c9d2b17472e9ad5
|
||||||
F src/test_multiplex.c 80677a47c75ca6a035d1ac66fb59186ffd4cdd19
|
F src/test_multiplex.c 6e07b94e2fe430f7f4f0d7d67b5e58f504dea655
|
||||||
F src/test_multiplex.h e99c571bc4968b7a9363b661481f3934bfead61d
|
F src/test_multiplex.h e99c571bc4968b7a9363b661481f3934bfead61d
|
||||||
F src/test_mutex.c a6bd7b9cf6e19d989e31392b06ac8d189f0d573e
|
F src/test_mutex.c a6bd7b9cf6e19d989e31392b06ac8d189f0d573e
|
||||||
F src/test_onefile.c 40cf9e212a377a6511469384a64b01e6e34b2eec
|
F src/test_onefile.c 40cf9e212a377a6511469384a64b01e6e34b2eec
|
||||||
@@ -238,13 +238,13 @@ F src/tokenize.c c819d9f72168a035d545a5bdafe9b085b20df705
|
|||||||
F src/trigger.c ee7e178fb9188f44b532cebd449a7c1df90fb684
|
F src/trigger.c ee7e178fb9188f44b532cebd449a7c1df90fb684
|
||||||
F src/update.c d3076782c887c10e882996550345da9c4c9f9dea
|
F src/update.c d3076782c887c10e882996550345da9c4c9f9dea
|
||||||
F src/utf.c 890c67dcfcc7a74623c95baac7535aadfe265e84
|
F src/utf.c 890c67dcfcc7a74623c95baac7535aadfe265e84
|
||||||
F src/util.c 01238e2b0f24a14779181dbf991fe02620a80e31
|
F src/util.c 343508d359df65685b62e63964a40e7af4cfbe05
|
||||||
F src/vacuum.c 0c0ba2242355c6048d65e2b333abe0f7c06348fa
|
F src/vacuum.c 0c0ba2242355c6048d65e2b333abe0f7c06348fa
|
||||||
F src/vdbe.c 029add0c5197a61db588824a58570547330b9d8f
|
F src/vdbe.c 029add0c5197a61db588824a58570547330b9d8f
|
||||||
F src/vdbe.h 18f581cac1f4339ec3299f3e0cc6e11aec654cdb
|
F src/vdbe.h 18f581cac1f4339ec3299f3e0cc6e11aec654cdb
|
||||||
F src/vdbeInt.h 48c158b2fceca9682d1577e61c62da3c58cf0748
|
F src/vdbeInt.h 48c158b2fceca9682d1577e61c62da3c58cf0748
|
||||||
F src/vdbeapi.c 86189ebba2c49791d75eaa12929f3ce6527596bd
|
F src/vdbeapi.c 86189ebba2c49791d75eaa12929f3ce6527596bd
|
||||||
F src/vdbeaux.c 61a3cc2b3a713aa244598a13035471cc30b307e1
|
F src/vdbeaux.c 4a96cddec7c8cc33f98da703c1baf2a654b50cab
|
||||||
F src/vdbeblob.c 32f2a4899d67f69634ea4dd93e3f651936d732cb
|
F src/vdbeblob.c 32f2a4899d67f69634ea4dd93e3f651936d732cb
|
||||||
F src/vdbemem.c 2fc78b3e0fabcc1eaa23cd79dd2e30e6dcfe1e56
|
F src/vdbemem.c 2fc78b3e0fabcc1eaa23cd79dd2e30e6dcfe1e56
|
||||||
F src/vdbesort.c 468d43c057063e54da4f1988b38b4f46d60e7790
|
F src/vdbesort.c 468d43c057063e54da4f1988b38b4f46d60e7790
|
||||||
@@ -983,7 +983,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
|
|||||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||||
F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a
|
F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a
|
||||||
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
||||||
P da118e02c0576ce16f7a26663f59413316223d55 e85cfe9a17a2943ee0cf7915451ff6cc05908030
|
P 322bd15f97143d39b3a88d5f6cf7afb454e0666e bb40338887c912be70cb6fe3b760d87c14bb88a5
|
||||||
R 4fb854e64d34a9b880548a23455e8f4d
|
R a70f90ef372516f64947505d1ba22869
|
||||||
U drh
|
U drh
|
||||||
Z 1f8384d1da732a66b49bdc6038214de7
|
Z a2e5ef34107012b45c32946167d7851d
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
322bd15f97143d39b3a88d5f6cf7afb454e0666e
|
cf3bccc2e944cd2dd3efb8554682994a06115f16
|
||||||
@@ -133,7 +133,8 @@ struct multiplexGroup {
|
|||||||
int nName; /* Length of base filename */
|
int nName; /* Length of base filename */
|
||||||
int flags; /* Flags used for original opening */
|
int flags; /* Flags used for original opening */
|
||||||
unsigned int szChunk; /* Chunk size used for this group */
|
unsigned int szChunk; /* Chunk size used for this group */
|
||||||
int bEnabled; /* TRUE to use Multiplex VFS for this file */
|
unsigned char bEnabled; /* TRUE to use Multiplex VFS for this file */
|
||||||
|
unsigned char bTruncate; /* TRUE to enable truncation of databases */
|
||||||
multiplexGroup *pNext, *pPrev; /* Doubly linked list of all group objects */
|
multiplexGroup *pNext, *pPrev; /* Doubly linked list of all group objects */
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -216,6 +217,39 @@ static int multiplexStrlen30(const char *z){
|
|||||||
return 0x3fffffff & (int)(z2 - z);
|
return 0x3fffffff & (int)(z2 - z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Generate the file-name for chunk iChunk of the group with base name
|
||||||
|
** zBase. The file-name is written to buffer zOut before returning. Buffer
|
||||||
|
** zOut must be allocated by the caller so that it is at least (nBase+4)
|
||||||
|
** bytes in size, where nBase is the length of zBase, not including the
|
||||||
|
** nul-terminator.
|
||||||
|
*/
|
||||||
|
static void multiplexFilename(
|
||||||
|
const char *zBase, /* Filename for chunk 0 */
|
||||||
|
int nBase, /* Size of zBase in bytes (without \0) */
|
||||||
|
int flags, /* Flags used to open file */
|
||||||
|
int iChunk, /* Chunk to generate filename for */
|
||||||
|
char *zOut /* Buffer to write generated name to */
|
||||||
|
){
|
||||||
|
memcpy(zOut, zBase, nBase+1);
|
||||||
|
if( iChunk!=0 && iChunk!=SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET ){
|
||||||
|
int n = nBase;
|
||||||
|
#ifdef SQLITE_ENABLE_8_3_NAMES
|
||||||
|
int i;
|
||||||
|
for(i=n-1; i>0 && i>=n-4 && zOut[i]!='.'; i--){}
|
||||||
|
if( i>=n-4 ) n = i+1;
|
||||||
|
if( flags & SQLITE_OPEN_MAIN_JOURNAL ){
|
||||||
|
/* The extensions on overflow files for main databases are 001, 002,
|
||||||
|
** 003 and so forth. To avoid name collisions, add 400 to the
|
||||||
|
** extensions of journal files so that they are 401, 402, 403, ....
|
||||||
|
*/
|
||||||
|
iChunk += SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
sqlite3_snprintf(4,&zOut[n],"%03d",iChunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Compute the filename for the iChunk-th chunk
|
/* Compute the filename for the iChunk-th chunk
|
||||||
*/
|
*/
|
||||||
static int multiplexSubFilename(multiplexGroup *pGroup, int iChunk){
|
static int multiplexSubFilename(multiplexGroup *pGroup, int iChunk){
|
||||||
@@ -236,34 +270,24 @@ static int multiplexSubFilename(multiplexGroup *pGroup, int iChunk){
|
|||||||
if( z==0 ){
|
if( z==0 ){
|
||||||
return SQLITE_NOMEM;
|
return SQLITE_NOMEM;
|
||||||
}
|
}
|
||||||
memcpy(z, pGroup->zName, n+1);
|
multiplexFilename(pGroup->zName, pGroup->nName, pGroup->flags, iChunk, z);
|
||||||
if( iChunk>0 ){
|
|
||||||
#ifdef SQLITE_ENABLE_8_3_NAMES
|
|
||||||
int i;
|
|
||||||
for(i=n-1; i>0 && i>=n-4 && z[i]!='.'; i--){}
|
|
||||||
if( i>=n-4 ) n = i+1;
|
|
||||||
if( pGroup->flags & (SQLITE_OPEN_MAIN_JOURNAL|SQLITE_OPEN_TEMP_JOURNAL) ){
|
|
||||||
/* The extensions on overflow files for main databases are 001, 002,
|
|
||||||
** 003 and so forth. To avoid name collisions, add 400 to the
|
|
||||||
** extensions of journal files so that they are 401, 402, 403, ....
|
|
||||||
*/
|
|
||||||
iChunk += SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
sqlite3_snprintf(4,&z[n],"%03d",iChunk);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Translate an sqlite3_file* that is really a multiplexGroup* into
|
/* Translate an sqlite3_file* that is really a multiplexGroup* into
|
||||||
** the sqlite3_file* for the underlying original VFS.
|
** the sqlite3_file* for the underlying original VFS.
|
||||||
|
**
|
||||||
|
** For chunk 0, the pGroup->flags determines whether or not a new file
|
||||||
|
** is created if it does not already exist. For chunks 1 and higher, the
|
||||||
|
** file is created only if createFlag is 1.
|
||||||
*/
|
*/
|
||||||
static sqlite3_file *multiplexSubOpen(
|
static sqlite3_file *multiplexSubOpen(
|
||||||
multiplexGroup *pGroup,
|
multiplexGroup *pGroup, /* The multiplexor group */
|
||||||
int iChunk,
|
int iChunk, /* Which chunk to open. 0==original file */
|
||||||
int *rc,
|
int *rc, /* Result code in and out */
|
||||||
int *pOutFlags
|
int *pOutFlags, /* Output flags */
|
||||||
|
int createFlag /* True to create if iChunk>0 */
|
||||||
){
|
){
|
||||||
sqlite3_file *pSubOpen = 0;
|
sqlite3_file *pSubOpen = 0;
|
||||||
sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */
|
sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */
|
||||||
@@ -281,15 +305,30 @@ static sqlite3_file *multiplexSubOpen(
|
|||||||
|
|
||||||
*rc = multiplexSubFilename(pGroup, iChunk);
|
*rc = multiplexSubFilename(pGroup, iChunk);
|
||||||
if( (*rc)==SQLITE_OK && (pSubOpen = pGroup->aReal[iChunk].p)==0 ){
|
if( (*rc)==SQLITE_OK && (pSubOpen = pGroup->aReal[iChunk].p)==0 ){
|
||||||
|
int flags, bExists;
|
||||||
|
createFlag = (pGroup->flags & SQLITE_OPEN_CREATE)!=0;
|
||||||
|
flags = pGroup->flags;
|
||||||
|
if( createFlag ){
|
||||||
|
flags |= SQLITE_OPEN_CREATE;
|
||||||
|
}else if( iChunk==0 ){
|
||||||
|
/* Fall through */
|
||||||
|
}else if( pGroup->aReal[iChunk].z==0 ){
|
||||||
|
return 0;
|
||||||
|
}else{
|
||||||
|
*rc = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[iChunk].z,
|
||||||
|
SQLITE_ACCESS_EXISTS, &bExists);
|
||||||
|
if( *rc || !bExists ) return 0;
|
||||||
|
flags &= ~SQLITE_OPEN_CREATE;
|
||||||
|
}
|
||||||
pSubOpen = sqlite3_malloc( pOrigVfs->szOsFile );
|
pSubOpen = sqlite3_malloc( pOrigVfs->szOsFile );
|
||||||
if( pSubOpen==0 ){
|
if( pSubOpen==0 ){
|
||||||
*rc = SQLITE_NOMEM;
|
*rc = SQLITE_IOERR_NOMEM;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
pGroup->aReal[iChunk].p = pSubOpen;
|
pGroup->aReal[iChunk].p = pSubOpen;
|
||||||
*rc = pOrigVfs->xOpen(pOrigVfs, pGroup->aReal[iChunk].z, pSubOpen,
|
*rc = pOrigVfs->xOpen(pOrigVfs, pGroup->aReal[iChunk].z, pSubOpen,
|
||||||
pGroup->flags, pOutFlags);
|
flags, pOutFlags);
|
||||||
if( *rc!=SQLITE_OK ){
|
if( (*rc)!=SQLITE_OK ){
|
||||||
sqlite3_free(pSubOpen);
|
sqlite3_free(pSubOpen);
|
||||||
pGroup->aReal[iChunk].p = 0;
|
pGroup->aReal[iChunk].p = 0;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -298,6 +337,25 @@ static sqlite3_file *multiplexSubOpen(
|
|||||||
return pSubOpen;
|
return pSubOpen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Return the size, in bytes, of chunk number iChunk. If that chunk
|
||||||
|
** does not exist, then return 0. This function does not distingish between
|
||||||
|
** non-existant files and zero-length files.
|
||||||
|
*/
|
||||||
|
static sqlite3_int64 multiplexSubSize(
|
||||||
|
multiplexGroup *pGroup, /* The multiplexor group */
|
||||||
|
int iChunk, /* Which chunk to open. 0==original file */
|
||||||
|
int *rc /* Result code in and out */
|
||||||
|
){
|
||||||
|
sqlite3_file *pSub;
|
||||||
|
sqlite3_int64 sz = 0;
|
||||||
|
|
||||||
|
pSub = multiplexSubOpen(pGroup, iChunk, rc, NULL, 0);
|
||||||
|
if( pSub==0 ) return 0;
|
||||||
|
*rc = pSub->pMethods->xFileSize(pSub, &sz);
|
||||||
|
return sz;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** This is the implementation of the multiplex_control() SQL function.
|
** This is the implementation of the multiplex_control() SQL function.
|
||||||
*/
|
*/
|
||||||
@@ -365,7 +423,9 @@ static void multiplexSubClose(
|
|||||||
sqlite3_file *pSubOpen = pGroup->aReal[iChunk].p;
|
sqlite3_file *pSubOpen = pGroup->aReal[iChunk].p;
|
||||||
if( pSubOpen ){
|
if( pSubOpen ){
|
||||||
pSubOpen->pMethods->xClose(pSubOpen);
|
pSubOpen->pMethods->xClose(pSubOpen);
|
||||||
if( pOrigVfs ) pOrigVfs->xDelete(pOrigVfs, pGroup->aReal[iChunk].z, 0);
|
if( pOrigVfs && pGroup->aReal[iChunk].z ){
|
||||||
|
pOrigVfs->xDelete(pOrigVfs, pGroup->aReal[iChunk].z, 0);
|
||||||
|
}
|
||||||
sqlite3_free(pGroup->aReal[iChunk].p);
|
sqlite3_free(pGroup->aReal[iChunk].p);
|
||||||
}
|
}
|
||||||
sqlite3_free(pGroup->aReal[iChunk].z);
|
sqlite3_free(pGroup->aReal[iChunk].z);
|
||||||
@@ -435,6 +495,7 @@ static int multiplexOpen(
|
|||||||
memset(pGroup, 0, sz);
|
memset(pGroup, 0, sz);
|
||||||
pMultiplexOpen->pGroup = pGroup;
|
pMultiplexOpen->pGroup = pGroup;
|
||||||
pGroup->bEnabled = -1;
|
pGroup->bEnabled = -1;
|
||||||
|
pGroup->bTruncate = (flags & SQLITE_OPEN_MAIN_DB)==0;
|
||||||
pGroup->szChunk = SQLITE_MULTIPLEX_CHUNK_SIZE;
|
pGroup->szChunk = SQLITE_MULTIPLEX_CHUNK_SIZE;
|
||||||
|
|
||||||
if( zName ){
|
if( zName ){
|
||||||
@@ -455,41 +516,76 @@ static int multiplexOpen(
|
|||||||
pGroup->bEnabled = 0;
|
pGroup->bEnabled = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if( sqlite3_uri_parameter(zName, "truncate") ) pGroup->bTruncate = 1;
|
||||||
}
|
}
|
||||||
pGroup->zName = p;
|
pGroup->zName = p;
|
||||||
memcpy(pGroup->zName, zName, nName+1);
|
memcpy(pGroup->zName, zName, nName+1);
|
||||||
pGroup->nName = nName;
|
pGroup->nName = nName;
|
||||||
}
|
}
|
||||||
|
if( pGroup->bEnabled ){
|
||||||
|
/* Make sure that the chunksize is not such that the pending byte
|
||||||
|
** falls at the end of a chunk. A region of up to 64K following
|
||||||
|
** the pending byte is never written, so if the pending byte occurs
|
||||||
|
** near the end of a chunk, that chunk will be too small. */
|
||||||
|
extern int sqlite3PendingByte;
|
||||||
|
while( (sqlite3PendingByte % pGroup->szChunk)>=(pGroup->szChunk-65536) ){
|
||||||
|
pGroup->szChunk += 65536;
|
||||||
|
}
|
||||||
|
}
|
||||||
pGroup->flags = flags;
|
pGroup->flags = flags;
|
||||||
rc = multiplexSubFilename(pGroup, 1);
|
rc = multiplexSubFilename(pGroup, 1);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
pSubOpen = multiplexSubOpen(pGroup, 0, &rc, pOutFlags);
|
pSubOpen = multiplexSubOpen(pGroup, 0, &rc, pOutFlags, 0);
|
||||||
|
if( pSubOpen==0 && rc==SQLITE_OK ) rc = SQLITE_CANTOPEN;
|
||||||
}
|
}
|
||||||
if( pSubOpen ){
|
if( rc==SQLITE_OK ){
|
||||||
int exists, rc2, rc3;
|
|
||||||
sqlite3_int64 sz;
|
sqlite3_int64 sz;
|
||||||
|
|
||||||
rc2 = pSubOpen->pMethods->xFileSize(pSubOpen, &sz);
|
rc = pSubOpen->pMethods->xFileSize(pSubOpen, &sz);
|
||||||
if( rc2==SQLITE_OK && zName ){
|
if( rc==SQLITE_OK && zName ){
|
||||||
/* If the first overflow file exists and if the size of the main file
|
int bExists;
|
||||||
** is different from the chunk size, that means the chunk size is set
|
if( sz==0 ){
|
||||||
** set incorrectly. So fix it.
|
if( flags & SQLITE_OPEN_MAIN_JOURNAL ){
|
||||||
**
|
/* If opening a main journal file and the first chunk is zero
|
||||||
** Or, if the first overflow file does not exist and the main file is
|
** bytes in size, delete any subsequent chunks from the
|
||||||
** larger than the chunk size, that means the chunk size is too small.
|
** file-system. */
|
||||||
** But we have no way of determining the intended chunk size, so
|
int iChunk = 1;
|
||||||
** just disable the multiplexor all togethre.
|
do {
|
||||||
*/
|
rc = pOrigVfs->xAccess(pOrigVfs,
|
||||||
rc3 = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[1].z,
|
pGroup->aReal[iChunk].z, SQLITE_ACCESS_EXISTS, &bExists
|
||||||
SQLITE_ACCESS_EXISTS, &exists);
|
);
|
||||||
if( rc3==SQLITE_OK && exists && sz==(sz&0xffff0000) && sz>0
|
if( rc==SQLITE_OK && bExists ){
|
||||||
&& sz!=pGroup->szChunk ){
|
rc = pOrigVfs->xDelete(pOrigVfs, pGroup->aReal[iChunk].z, 0);
|
||||||
pGroup->szChunk = sz;
|
if( rc==SQLITE_OK ){
|
||||||
}else if( rc3==SQLITE_OK && !exists && sz>pGroup->szChunk ){
|
rc = multiplexSubFilename(pGroup, ++iChunk);
|
||||||
pGroup->bEnabled = 0;
|
}
|
||||||
|
}
|
||||||
|
}while( rc==SQLITE_OK && bExists );
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
/* If the first overflow file exists and if the size of the main file
|
||||||
|
** is different from the chunk size, that means the chunk size is set
|
||||||
|
** set incorrectly. So fix it.
|
||||||
|
**
|
||||||
|
** Or, if the first overflow file does not exist and the main file is
|
||||||
|
** larger than the chunk size, that means the chunk size is too small.
|
||||||
|
** But we have no way of determining the intended chunk size, so
|
||||||
|
** just disable the multiplexor all togethre.
|
||||||
|
*/
|
||||||
|
rc = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[1].z,
|
||||||
|
SQLITE_ACCESS_EXISTS, &bExists);
|
||||||
|
bExists = multiplexSubSize(pGroup, 1, &rc)>0;
|
||||||
|
if( rc==SQLITE_OK && bExists && sz==(sz&0xffff0000) && sz>0
|
||||||
|
&& sz!=pGroup->szChunk ){
|
||||||
|
pGroup->szChunk = sz;
|
||||||
|
}else if( rc==SQLITE_OK && !bExists && sz>pGroup->szChunk ){
|
||||||
|
pGroup->bEnabled = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( rc==SQLITE_OK ){
|
||||||
if( pSubOpen->pMethods->iVersion==1 ){
|
if( pSubOpen->pMethods->iVersion==1 ){
|
||||||
pMultiplexOpen->base.pMethods = &gMultiplex.sIoMethodsV1;
|
pMultiplexOpen->base.pMethods = &gMultiplex.sIoMethodsV1;
|
||||||
}else{
|
}else{
|
||||||
@@ -518,8 +614,33 @@ static int multiplexDelete(
|
|||||||
const char *zName, /* Name of file to delete */
|
const char *zName, /* Name of file to delete */
|
||||||
int syncDir
|
int syncDir
|
||||||
){
|
){
|
||||||
|
int rc;
|
||||||
sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */
|
sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */
|
||||||
return pOrigVfs->xDelete(pOrigVfs, zName, syncDir);
|
rc = pOrigVfs->xDelete(pOrigVfs, zName, syncDir);
|
||||||
|
if( rc==SQLITE_OK ){
|
||||||
|
/* If the main chunk was deleted successfully, also delete any subsequent
|
||||||
|
** chunks - starting with the last (highest numbered).
|
||||||
|
*/
|
||||||
|
int nName = strlen(zName);
|
||||||
|
char *z;
|
||||||
|
z = sqlite3_malloc(nName + 4);
|
||||||
|
if( z==0 ){
|
||||||
|
rc = SQLITE_IOERR_NOMEM;
|
||||||
|
}else{
|
||||||
|
int iChunk = 0;
|
||||||
|
int bExists;
|
||||||
|
do{
|
||||||
|
multiplexFilename(zName, nName, SQLITE_OPEN_MAIN_JOURNAL, ++iChunk, z);
|
||||||
|
rc = pOrigVfs->xAccess(pOrigVfs, z, SQLITE_ACCESS_EXISTS, &bExists);
|
||||||
|
}while( rc==SQLITE_OK && bExists );
|
||||||
|
while( rc==SQLITE_OK && iChunk>1 ){
|
||||||
|
multiplexFilename(zName, nName, SQLITE_OPEN_MAIN_JOURNAL, --iChunk, z);
|
||||||
|
rc = pOrigVfs->xDelete(pOrigVfs, z, syncDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sqlite3_free(z);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int multiplexAccess(sqlite3_vfs *a, const char *b, int c, int *d){
|
static int multiplexAccess(sqlite3_vfs *a, const char *b, int c, int *d){
|
||||||
@@ -596,7 +717,7 @@ static int multiplexRead(
|
|||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
multiplexEnter();
|
multiplexEnter();
|
||||||
if( !pGroup->bEnabled ){
|
if( !pGroup->bEnabled ){
|
||||||
sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL);
|
sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0);
|
||||||
if( pSubOpen==0 ){
|
if( pSubOpen==0 ){
|
||||||
rc = SQLITE_IOERR_READ;
|
rc = SQLITE_IOERR_READ;
|
||||||
}else{
|
}else{
|
||||||
@@ -605,7 +726,7 @@ static int multiplexRead(
|
|||||||
}else{
|
}else{
|
||||||
while( iAmt > 0 ){
|
while( iAmt > 0 ){
|
||||||
int i = (int)(iOfst / pGroup->szChunk);
|
int i = (int)(iOfst / pGroup->szChunk);
|
||||||
sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL);
|
sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL, 1);
|
||||||
if( pSubOpen ){
|
if( pSubOpen ){
|
||||||
int extra = ((int)(iOfst % pGroup->szChunk) + iAmt) - pGroup->szChunk;
|
int extra = ((int)(iOfst % pGroup->szChunk) + iAmt) - pGroup->szChunk;
|
||||||
if( extra<0 ) extra = 0;
|
if( extra<0 ) extra = 0;
|
||||||
@@ -641,7 +762,7 @@ static int multiplexWrite(
|
|||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
multiplexEnter();
|
multiplexEnter();
|
||||||
if( !pGroup->bEnabled ){
|
if( !pGroup->bEnabled ){
|
||||||
sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL);
|
sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0);
|
||||||
if( pSubOpen==0 ){
|
if( pSubOpen==0 ){
|
||||||
rc = SQLITE_IOERR_WRITE;
|
rc = SQLITE_IOERR_WRITE;
|
||||||
}else{
|
}else{
|
||||||
@@ -650,7 +771,7 @@ static int multiplexWrite(
|
|||||||
}else{
|
}else{
|
||||||
while( rc==SQLITE_OK && iAmt>0 ){
|
while( rc==SQLITE_OK && iAmt>0 ){
|
||||||
int i = (int)(iOfst / pGroup->szChunk);
|
int i = (int)(iOfst / pGroup->szChunk);
|
||||||
sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL);
|
sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL, 1);
|
||||||
if( pSubOpen ){
|
if( pSubOpen ){
|
||||||
int extra = ((int)(iOfst % pGroup->szChunk) + iAmt) -
|
int extra = ((int)(iOfst % pGroup->szChunk) + iAmt) -
|
||||||
pGroup->szChunk;
|
pGroup->szChunk;
|
||||||
@@ -678,28 +799,35 @@ static int multiplexTruncate(sqlite3_file *pConn, sqlite3_int64 size){
|
|||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
multiplexEnter();
|
multiplexEnter();
|
||||||
if( !pGroup->bEnabled ){
|
if( !pGroup->bEnabled ){
|
||||||
sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL);
|
sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0);
|
||||||
if( pSubOpen==0 ){
|
if( pSubOpen==0 ){
|
||||||
rc = SQLITE_IOERR_TRUNCATE;
|
rc = SQLITE_IOERR_TRUNCATE;
|
||||||
}else{
|
}else{
|
||||||
rc = pSubOpen->pMethods->xTruncate(pSubOpen, size);
|
rc = pSubOpen->pMethods->xTruncate(pSubOpen, size);
|
||||||
}
|
}
|
||||||
}else if( (pGroup->flags & SQLITE_OPEN_MAIN_DB)==0 ){
|
}else{
|
||||||
int rc2;
|
|
||||||
int i;
|
int i;
|
||||||
|
int iBaseGroup = (int)(size / pGroup->szChunk);
|
||||||
sqlite3_file *pSubOpen;
|
sqlite3_file *pSubOpen;
|
||||||
sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */
|
sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */
|
||||||
/* delete the chunks above the truncate limit */
|
/* delete the chunks above the truncate limit */
|
||||||
for(i=(int)(size / pGroup->szChunk)+1; i<pGroup->nReal; i++){
|
for(i = pGroup->nReal-1; i>iBaseGroup && rc==SQLITE_OK; i--){
|
||||||
multiplexSubClose(pGroup, i, pOrigVfs);
|
if( pGroup->bTruncate ){
|
||||||
|
multiplexSubClose(pGroup, i, pOrigVfs);
|
||||||
|
}else{
|
||||||
|
pSubOpen = multiplexSubOpen(pGroup, i, &rc, 0, 0);
|
||||||
|
if( pSubOpen ){
|
||||||
|
rc = pSubOpen->pMethods->xTruncate(pSubOpen, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pSubOpen = multiplexSubOpen(pGroup, (int)(size/pGroup->szChunk), &rc2,0);
|
if( rc==SQLITE_OK ){
|
||||||
if( pSubOpen ){
|
pSubOpen = multiplexSubOpen(pGroup, iBaseGroup, &rc, 0, 0);
|
||||||
rc2 = pSubOpen->pMethods->xTruncate(pSubOpen, size % pGroup->szChunk);
|
if( pSubOpen ){
|
||||||
if( rc2!=SQLITE_OK ) rc = rc2;
|
rc = pSubOpen->pMethods->xTruncate(pSubOpen, size % pGroup->szChunk);
|
||||||
}else{
|
}
|
||||||
rc = SQLITE_IOERR_TRUNCATE;
|
|
||||||
}
|
}
|
||||||
|
if( rc ) rc = SQLITE_IOERR_TRUNCATE;
|
||||||
}
|
}
|
||||||
multiplexLeave();
|
multiplexLeave();
|
||||||
return rc;
|
return rc;
|
||||||
@@ -734,42 +862,18 @@ static int multiplexFileSize(sqlite3_file *pConn, sqlite3_int64 *pSize){
|
|||||||
int i;
|
int i;
|
||||||
multiplexEnter();
|
multiplexEnter();
|
||||||
if( !pGroup->bEnabled ){
|
if( !pGroup->bEnabled ){
|
||||||
sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL);
|
sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0);
|
||||||
if( pSubOpen==0 ){
|
if( pSubOpen==0 ){
|
||||||
rc = SQLITE_IOERR_FSTAT;
|
rc = SQLITE_IOERR_FSTAT;
|
||||||
}else{
|
}else{
|
||||||
rc = pSubOpen->pMethods->xFileSize(pSubOpen, pSize);
|
rc = pSubOpen->pMethods->xFileSize(pSubOpen, pSize);
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs;
|
|
||||||
*pSize = 0;
|
*pSize = 0;
|
||||||
for(i=0; rc==SQLITE_OK; i++){
|
for(i=0; rc==SQLITE_OK; i++){
|
||||||
sqlite3_file *pSubOpen = 0;
|
sqlite3_int64 sz = multiplexSubSize(pGroup, i, &rc);
|
||||||
int exists = 0;
|
if( sz==0 ) break;
|
||||||
rc = multiplexSubFilename(pGroup, i);
|
*pSize = i*(sqlite3_int64)pGroup->szChunk + sz;
|
||||||
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();
|
multiplexLeave();
|
||||||
@@ -781,7 +885,7 @@ static int multiplexFileSize(sqlite3_file *pConn, sqlite3_int64 *pSize){
|
|||||||
static int multiplexLock(sqlite3_file *pConn, int lock){
|
static int multiplexLock(sqlite3_file *pConn, int lock){
|
||||||
multiplexConn *p = (multiplexConn*)pConn;
|
multiplexConn *p = (multiplexConn*)pConn;
|
||||||
int rc;
|
int rc;
|
||||||
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
|
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
|
||||||
if( pSubOpen ){
|
if( pSubOpen ){
|
||||||
return pSubOpen->pMethods->xLock(pSubOpen, lock);
|
return pSubOpen->pMethods->xLock(pSubOpen, lock);
|
||||||
}
|
}
|
||||||
@@ -793,7 +897,7 @@ static int multiplexLock(sqlite3_file *pConn, int lock){
|
|||||||
static int multiplexUnlock(sqlite3_file *pConn, int lock){
|
static int multiplexUnlock(sqlite3_file *pConn, int lock){
|
||||||
multiplexConn *p = (multiplexConn*)pConn;
|
multiplexConn *p = (multiplexConn*)pConn;
|
||||||
int rc;
|
int rc;
|
||||||
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
|
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
|
||||||
if( pSubOpen ){
|
if( pSubOpen ){
|
||||||
return pSubOpen->pMethods->xUnlock(pSubOpen, lock);
|
return pSubOpen->pMethods->xUnlock(pSubOpen, lock);
|
||||||
}
|
}
|
||||||
@@ -805,7 +909,7 @@ static int multiplexUnlock(sqlite3_file *pConn, int lock){
|
|||||||
static int multiplexCheckReservedLock(sqlite3_file *pConn, int *pResOut){
|
static int multiplexCheckReservedLock(sqlite3_file *pConn, int *pResOut){
|
||||||
multiplexConn *p = (multiplexConn*)pConn;
|
multiplexConn *p = (multiplexConn*)pConn;
|
||||||
int rc;
|
int rc;
|
||||||
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
|
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
|
||||||
if( pSubOpen ){
|
if( pSubOpen ){
|
||||||
return pSubOpen->pMethods->xCheckReservedLock(pSubOpen, pResOut);
|
return pSubOpen->pMethods->xCheckReservedLock(pSubOpen, pResOut);
|
||||||
}
|
}
|
||||||
@@ -853,7 +957,7 @@ static int multiplexFileControl(sqlite3_file *pConn, int op, void *pArg){
|
|||||||
rc = SQLITE_OK;
|
rc = SQLITE_OK;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL);
|
pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0);
|
||||||
if( pSubOpen ){
|
if( pSubOpen ){
|
||||||
rc = pSubOpen->pMethods->xFileControl(pSubOpen, op, pArg);
|
rc = pSubOpen->pMethods->xFileControl(pSubOpen, op, pArg);
|
||||||
if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){
|
if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){
|
||||||
@@ -870,7 +974,7 @@ static int multiplexFileControl(sqlite3_file *pConn, int op, void *pArg){
|
|||||||
static int multiplexSectorSize(sqlite3_file *pConn){
|
static int multiplexSectorSize(sqlite3_file *pConn){
|
||||||
multiplexConn *p = (multiplexConn*)pConn;
|
multiplexConn *p = (multiplexConn*)pConn;
|
||||||
int rc;
|
int rc;
|
||||||
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
|
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
|
||||||
if( pSubOpen && pSubOpen->pMethods->xSectorSize ){
|
if( pSubOpen && pSubOpen->pMethods->xSectorSize ){
|
||||||
return pSubOpen->pMethods->xSectorSize(pSubOpen);
|
return pSubOpen->pMethods->xSectorSize(pSubOpen);
|
||||||
}
|
}
|
||||||
@@ -882,7 +986,7 @@ static int multiplexSectorSize(sqlite3_file *pConn){
|
|||||||
static int multiplexDeviceCharacteristics(sqlite3_file *pConn){
|
static int multiplexDeviceCharacteristics(sqlite3_file *pConn){
|
||||||
multiplexConn *p = (multiplexConn*)pConn;
|
multiplexConn *p = (multiplexConn*)pConn;
|
||||||
int rc;
|
int rc;
|
||||||
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
|
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
|
||||||
if( pSubOpen ){
|
if( pSubOpen ){
|
||||||
return pSubOpen->pMethods->xDeviceCharacteristics(pSubOpen);
|
return pSubOpen->pMethods->xDeviceCharacteristics(pSubOpen);
|
||||||
}
|
}
|
||||||
@@ -900,7 +1004,7 @@ static int multiplexShmMap(
|
|||||||
){
|
){
|
||||||
multiplexConn *p = (multiplexConn*)pConn;
|
multiplexConn *p = (multiplexConn*)pConn;
|
||||||
int rc;
|
int rc;
|
||||||
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
|
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
|
||||||
if( pSubOpen ){
|
if( pSubOpen ){
|
||||||
return pSubOpen->pMethods->xShmMap(pSubOpen, iRegion, szRegion, bExtend,pp);
|
return pSubOpen->pMethods->xShmMap(pSubOpen, iRegion, szRegion, bExtend,pp);
|
||||||
}
|
}
|
||||||
@@ -917,7 +1021,7 @@ static int multiplexShmLock(
|
|||||||
){
|
){
|
||||||
multiplexConn *p = (multiplexConn*)pConn;
|
multiplexConn *p = (multiplexConn*)pConn;
|
||||||
int rc;
|
int rc;
|
||||||
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
|
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
|
||||||
if( pSubOpen ){
|
if( pSubOpen ){
|
||||||
return pSubOpen->pMethods->xShmLock(pSubOpen, ofst, n, flags);
|
return pSubOpen->pMethods->xShmLock(pSubOpen, ofst, n, flags);
|
||||||
}
|
}
|
||||||
@@ -929,7 +1033,7 @@ static int multiplexShmLock(
|
|||||||
static void multiplexShmBarrier(sqlite3_file *pConn){
|
static void multiplexShmBarrier(sqlite3_file *pConn){
|
||||||
multiplexConn *p = (multiplexConn*)pConn;
|
multiplexConn *p = (multiplexConn*)pConn;
|
||||||
int rc;
|
int rc;
|
||||||
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
|
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
|
||||||
if( pSubOpen ){
|
if( pSubOpen ){
|
||||||
pSubOpen->pMethods->xShmBarrier(pSubOpen);
|
pSubOpen->pMethods->xShmBarrier(pSubOpen);
|
||||||
}
|
}
|
||||||
@@ -940,7 +1044,7 @@ static void multiplexShmBarrier(sqlite3_file *pConn){
|
|||||||
static int multiplexShmUnmap(sqlite3_file *pConn, int deleteFlag){
|
static int multiplexShmUnmap(sqlite3_file *pConn, int deleteFlag){
|
||||||
multiplexConn *p = (multiplexConn*)pConn;
|
multiplexConn *p = (multiplexConn*)pConn;
|
||||||
int rc;
|
int rc;
|
||||||
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
|
sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
|
||||||
if( pSubOpen ){
|
if( pSubOpen ){
|
||||||
return pSubOpen->pMethods->xShmUnmap(pSubOpen, deleteFlag);
|
return pSubOpen->pMethods->xShmUnmap(pSubOpen, deleteFlag);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1169,6 +1169,7 @@ int sqlite3AbsInt32(int x){
|
|||||||
** test.db-journal => test.nal
|
** test.db-journal => test.nal
|
||||||
** test.db-wal => test.wal
|
** test.db-wal => test.wal
|
||||||
** test.db-shm => test.shm
|
** test.db-shm => test.shm
|
||||||
|
** test.db-mj7f3319fa => test.9fa
|
||||||
*/
|
*/
|
||||||
void sqlite3FileSuffix3(const char *zBaseFilename, char *z){
|
void sqlite3FileSuffix3(const char *zBaseFilename, char *z){
|
||||||
#if SQLITE_ENABLE_8_3_NAMES<2
|
#if SQLITE_ENABLE_8_3_NAMES<2
|
||||||
|
|||||||
@@ -1833,16 +1833,26 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
|
|||||||
sqlite3_file *pMaster = 0;
|
sqlite3_file *pMaster = 0;
|
||||||
i64 offset = 0;
|
i64 offset = 0;
|
||||||
int res;
|
int res;
|
||||||
|
int retryCount = 0;
|
||||||
|
int nMainFile;
|
||||||
|
|
||||||
/* Select a master journal file name */
|
/* Select a master journal file name */
|
||||||
|
nMainFile = sqlite3Strlen30(zMainFile);
|
||||||
|
zMaster = sqlite3MPrintf(db, "%s-mjXXXXXX9XX", zMainFile);
|
||||||
|
if( zMaster==0 ) return SQLITE_NOMEM;
|
||||||
do {
|
do {
|
||||||
u32 iRandom;
|
u32 iRandom;
|
||||||
sqlite3DbFree(db, zMaster);
|
if( retryCount++>100 ){
|
||||||
sqlite3_randomness(sizeof(iRandom), &iRandom);
|
sqlite3_log(SQLITE_FULL, "cannot find unique master-journal");
|
||||||
zMaster = sqlite3MPrintf(db, "%s-mj%08X", zMainFile, iRandom&0x7fffffff);
|
sqlite3OsDelete(pVfs, zMaster, 0);
|
||||||
if( !zMaster ){
|
break;
|
||||||
return SQLITE_NOMEM;
|
|
||||||
}
|
}
|
||||||
|
sqlite3_randomness(sizeof(iRandom), &iRandom);
|
||||||
|
sqlite3_snprintf(13, &zMaster[nMainFile], "-mj%06X9%02X",
|
||||||
|
(iRandom>>8)&0xffffff, iRandom&0xff);
|
||||||
|
/* The antipenultimate character of the master journal name must
|
||||||
|
** be "9" to avoid name collisions when using 8+3 filenames. */
|
||||||
|
assert( zMaster[sqlite3Strlen30(zMaster)-3]=='9' );
|
||||||
sqlite3FileSuffix3(zMainFile, zMaster);
|
sqlite3FileSuffix3(zMainFile, zMaster);
|
||||||
rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res);
|
rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res);
|
||||||
}while( rc==SQLITE_OK && res );
|
}while( rc==SQLITE_OK && res );
|
||||||
|
|||||||
Reference in New Issue
Block a user