mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +03:00
Separate sqlite3_io_methods objects for database files and journals.
FossilOrigin-Name: 74fbf6c2a97729e481d5562344e960d0c237aeb1f07240262d32a24fb1f4b5a3
This commit is contained in:
338
ext/misc/vfskv.c
338
ext/misc/vfskv.c
@ -28,11 +28,15 @@ SQLITE_EXTENSION_INIT1
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
** Debugging logic
|
** Debugging logic
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* KVVFS_TRACE() is used for tracing calls to kvstorage routines. */
|
||||||
#if 0
|
#if 0
|
||||||
#define KVVFS_TRACE(X) printf X;
|
#define KVVFS_TRACE(X) printf X;
|
||||||
#else
|
#else
|
||||||
#define KVVFS_TRACE(X)
|
#define KVVFS_TRACE(X)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* KVVFS_LOG() is used for tracing calls to the VFS interface */
|
||||||
#if 0
|
#if 0
|
||||||
#define KVVFS_LOG(X) printf X;
|
#define KVVFS_LOG(X) printf X;
|
||||||
#else
|
#else
|
||||||
@ -88,11 +92,16 @@ struct KVVfsFile {
|
|||||||
** Methods for KVVfsFile
|
** Methods for KVVfsFile
|
||||||
*/
|
*/
|
||||||
static int kvvfsClose(sqlite3_file*);
|
static int kvvfsClose(sqlite3_file*);
|
||||||
static int kvvfsRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
|
static int kvvfsReadDb(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
|
||||||
static int kvvfsWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
|
static int kvvfsReadJrnl(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
|
||||||
static int kvvfsTruncate(sqlite3_file*, sqlite3_int64 size);
|
static int kvvfsWriteDb(sqlite3_file*,const void*,int iAmt, sqlite3_int64);
|
||||||
static int kvvfsSync(sqlite3_file*, int flags);
|
static int kvvfsWriteJrnl(sqlite3_file*,const void*,int iAmt, sqlite3_int64);
|
||||||
static int kvvfsFileSize(sqlite3_file*, sqlite3_int64 *pSize);
|
static int kvvfsTruncateDb(sqlite3_file*, sqlite3_int64 size);
|
||||||
|
static int kvvfsTruncateJrnl(sqlite3_file*, sqlite3_int64 size);
|
||||||
|
static int kvvfsSyncDb(sqlite3_file*, int flags);
|
||||||
|
static int kvvfsSyncJrnl(sqlite3_file*, int flags);
|
||||||
|
static int kvvfsFileSizeDb(sqlite3_file*, sqlite3_int64 *pSize);
|
||||||
|
static int kvvfsFileSizeJrnl(sqlite3_file*, sqlite3_int64 *pSize);
|
||||||
static int kvvfsLock(sqlite3_file*, int);
|
static int kvvfsLock(sqlite3_file*, int);
|
||||||
static int kvvfsUnlock(sqlite3_file*, int);
|
static int kvvfsUnlock(sqlite3_file*, int);
|
||||||
static int kvvfsCheckReservedLock(sqlite3_file*, int *pResOut);
|
static int kvvfsCheckReservedLock(sqlite3_file*, int *pResOut);
|
||||||
@ -139,14 +148,40 @@ static KVVfsVfs kvvfs_vfs = {
|
|||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
static sqlite3_io_methods kvvfs_io_methods = {
|
/* Methods for sqlite3_file objects referencing a database file
|
||||||
|
*/
|
||||||
|
static sqlite3_io_methods kvvfs_db_io_methods = {
|
||||||
1, /* iVersion */
|
1, /* iVersion */
|
||||||
kvvfsClose, /* xClose */
|
kvvfsClose, /* xClose */
|
||||||
kvvfsRead, /* xRead */
|
kvvfsReadDb, /* xRead */
|
||||||
kvvfsWrite, /* xWrite */
|
kvvfsWriteDb, /* xWrite */
|
||||||
kvvfsTruncate, /* xTruncate */
|
kvvfsTruncateDb, /* xTruncate */
|
||||||
kvvfsSync, /* xSync */
|
kvvfsSyncDb, /* xSync */
|
||||||
kvvfsFileSize, /* xFileSize */
|
kvvfsFileSizeDb, /* xFileSize */
|
||||||
|
kvvfsLock, /* xLock */
|
||||||
|
kvvfsUnlock, /* xUnlock */
|
||||||
|
kvvfsCheckReservedLock, /* xCheckReservedLock */
|
||||||
|
kvvfsFileControl, /* xFileControl */
|
||||||
|
kvvfsSectorSize, /* xSectorSize */
|
||||||
|
kvvfsDeviceCharacteristics, /* xDeviceCharacteristics */
|
||||||
|
0, /* xShmMap */
|
||||||
|
0, /* xShmLock */
|
||||||
|
0, /* xShmBarrier */
|
||||||
|
0, /* xShmUnmap */
|
||||||
|
0, /* xFetch */
|
||||||
|
0 /* xUnfetch */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Methods for sqlite3_file objects referencing a rollback journal
|
||||||
|
*/
|
||||||
|
static sqlite3_io_methods kvvfs_jrnl_io_methods = {
|
||||||
|
1, /* iVersion */
|
||||||
|
kvvfsClose, /* xClose */
|
||||||
|
kvvfsReadJrnl, /* xRead */
|
||||||
|
kvvfsWriteJrnl, /* xWrite */
|
||||||
|
kvvfsTruncateJrnl, /* xTruncate */
|
||||||
|
kvvfsSyncJrnl, /* xSync */
|
||||||
|
kvvfsFileSizeJrnl, /* xFileSize */
|
||||||
kvvfsLock, /* xLock */
|
kvvfsLock, /* xLock */
|
||||||
kvvfsUnlock, /* xUnlock */
|
kvvfsUnlock, /* xUnlock */
|
||||||
kvvfsCheckReservedLock, /* xCheckReservedLock */
|
kvvfsCheckReservedLock, /* xCheckReservedLock */
|
||||||
@ -200,8 +235,9 @@ static int kvstorageWrite(
|
|||||||
kvstorageMakeKey(pStore, zKey);
|
kvstorageMakeKey(pStore, zKey);
|
||||||
fd = fopen(pStore->zKey, "wb");
|
fd = fopen(pStore->zKey, "wb");
|
||||||
if( fd ){
|
if( fd ){
|
||||||
KVVFS_TRACE(("KVVFS-WRITE %-14s (%d) %.30s\n", pStore->zKey,
|
KVVFS_TRACE(("KVVFS-WRITE %-10s (%d) %.50s%s\n", pStore->zKey,
|
||||||
(int)strlen(zData), zData));
|
(int)strlen(zData), zData,
|
||||||
|
strlen(zData)>50 ? "..." : ""));
|
||||||
fputs(zData, fd);
|
fputs(zData, fd);
|
||||||
fclose(fd);
|
fclose(fd);
|
||||||
return 0;
|
return 0;
|
||||||
@ -215,7 +251,7 @@ static int kvstorageWrite(
|
|||||||
static int kvstorageDelete(KVStorage *pStore, const char *zKey){
|
static int kvstorageDelete(KVStorage *pStore, const char *zKey){
|
||||||
kvstorageMakeKey(pStore, zKey);
|
kvstorageMakeKey(pStore, zKey);
|
||||||
unlink(pStore->zKey);
|
unlink(pStore->zKey);
|
||||||
KVVFS_TRACE(("KVVFS-DELETE %-14s\n", pStore->zKey));
|
KVVFS_TRACE(("KVVFS-DELETE %-10s\n", pStore->zKey));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,14 +280,14 @@ static int kvstorageRead(
|
|||||||
|| stat(pStore->zKey, &buf)!=0
|
|| stat(pStore->zKey, &buf)!=0
|
||||||
|| !S_ISREG(buf.st_mode)
|
|| !S_ISREG(buf.st_mode)
|
||||||
){
|
){
|
||||||
KVVFS_TRACE(("KVVFS-READ %-14s (-1)\n", pStore->zKey));
|
KVVFS_TRACE(("KVVFS-READ %-10s (-1)\n", pStore->zKey));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if( nBuf<0 ){
|
if( nBuf<0 ){
|
||||||
return (int)buf.st_size;
|
return (int)buf.st_size;
|
||||||
}else if( nBuf==1 ){
|
}else if( nBuf==1 ){
|
||||||
zBuf[0] = 0;
|
zBuf[0] = 0;
|
||||||
KVVFS_TRACE(("KVVFS-READ %-14s (%d)\n", pStore->zKey,
|
KVVFS_TRACE(("KVVFS-READ %-10s (%d)\n", pStore->zKey,
|
||||||
(int)buf.st_size));
|
(int)buf.st_size));
|
||||||
return (int)buf.st_size;
|
return (int)buf.st_size;
|
||||||
}
|
}
|
||||||
@ -260,49 +296,20 @@ static int kvstorageRead(
|
|||||||
}
|
}
|
||||||
fd = fopen(pStore->zKey, "rb");
|
fd = fopen(pStore->zKey, "rb");
|
||||||
if( fd==0 ){
|
if( fd==0 ){
|
||||||
KVVFS_TRACE(("KVVFS-READ %-14s (-1)\n", pStore->zKey));
|
KVVFS_TRACE(("KVVFS-READ %-10s (-1)\n", pStore->zKey));
|
||||||
return -1;
|
return -1;
|
||||||
}else{
|
}else{
|
||||||
sqlite3_int64 n = fread(zBuf, 1, nBuf-1, fd);
|
sqlite3_int64 n = fread(zBuf, 1, nBuf-1, fd);
|
||||||
fclose(fd);
|
fclose(fd);
|
||||||
zBuf[n] = 0;
|
zBuf[n] = 0;
|
||||||
KVVFS_TRACE(("KVVFS-READ %-14s (%lld) %.30s\n", pStore->zKey,
|
KVVFS_TRACE(("KVVFS-READ %-10s (%lld) %.50s%s\n", pStore->zKey,
|
||||||
n, zBuf));
|
n, zBuf, n>50 ? "..." : ""));
|
||||||
return (int)n;
|
return (int)n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****** Utility subroutines ************************************************/
|
||||||
|
|
||||||
/****** The main VFS code **************************************************/
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Close an kvvfs-file.
|
|
||||||
*/
|
|
||||||
static int kvvfsClose(sqlite3_file *pProtoFile){
|
|
||||||
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
|
|
||||||
KVVfsVfs *pVfs = pFile->pVfs;
|
|
||||||
|
|
||||||
KVVFS_LOG(("xClose %s\n", pFile->isJournal ? "journal" : "db"));
|
|
||||||
if( pVfs->pFiles==pFile ){
|
|
||||||
pVfs->pFiles = pFile->pNext;
|
|
||||||
if( pVfs->pFiles==0 ){
|
|
||||||
kvstorageClose(pVfs->pStore);
|
|
||||||
pVfs->pStore = 0;
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
KVVfsFile *pX = pVfs->pFiles;
|
|
||||||
while( 1 ){
|
|
||||||
assert( pX );
|
|
||||||
if( pX->pNext==pFile ){
|
|
||||||
pX->pNext = pFile->pNext;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
pX = pX->pNext;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sqlite3_free(pFile->aJrnl);
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Encode binary into the text encoded used to persist on disk.
|
** Encode binary into the text encoded used to persist on disk.
|
||||||
@ -311,6 +318,20 @@ static int kvvfsClose(sqlite3_file *pProtoFile){
|
|||||||
**
|
**
|
||||||
** Return the actual length of the encoded text, not counting the
|
** Return the actual length of the encoded text, not counting the
|
||||||
** zero terminator at the end.
|
** zero terminator at the end.
|
||||||
|
**
|
||||||
|
** Encoding format
|
||||||
|
** ---------------
|
||||||
|
**
|
||||||
|
** * Non-zero bytes are encoded as upper-case hexadecimal
|
||||||
|
**
|
||||||
|
** * A sequence of one or more zero-bytes that are not at the
|
||||||
|
** beginning of the buffer are encoded as a little-endian
|
||||||
|
** base-26 number using a..z. "a" means 0. "b" means 1,
|
||||||
|
** "z" means 25. "ab" means 26. "ac" means 52. And so forth.
|
||||||
|
**
|
||||||
|
** * Because there is no overlap between the encoding characters
|
||||||
|
** of hexadecimal and base-26 numbers, it is always clear where
|
||||||
|
** one stops and the next begins.
|
||||||
*/
|
*/
|
||||||
static int kvvfsEncode(const char *aData, int nData, char *aOut){
|
static int kvvfsEncode(const char *aData, int nData, char *aOut){
|
||||||
int i, j;
|
int i, j;
|
||||||
@ -384,9 +405,11 @@ static int kvvfsDecode(const char *aIn, char *aOut, int nOut){
|
|||||||
** and store the decoding there. Or leave pFile->aJrnl set to NULL
|
** and store the decoding there. Or leave pFile->aJrnl set to NULL
|
||||||
** if an error is encountered.
|
** if an error is encountered.
|
||||||
**
|
**
|
||||||
** The first few characters of the text encoding will be a
|
** The first few characters of the text encoding will be a little-endian
|
||||||
** base-26 number (digits a..z) that is the total number of bytes
|
** base-26 number (digits a..z) that is the total number of bytes
|
||||||
** in the decoding. Use this number to size the initial allocation.
|
** in the decoded journal file image. This base-26 number is followed
|
||||||
|
** by a single space, then the encoding of the journal. The space
|
||||||
|
** separator is required to act as a terminator for the base-26 number.
|
||||||
*/
|
*/
|
||||||
static void kvvfsDecodeJournal(
|
static void kvvfsDecodeJournal(
|
||||||
KVVfsFile *pFile, /* Store decoding in pFile->aJrnl */
|
KVVfsFile *pFile, /* Store decoding in pFile->aJrnl */
|
||||||
@ -397,10 +420,9 @@ static void kvvfsDecodeJournal(
|
|||||||
int c, i, mult;
|
int c, i, mult;
|
||||||
i = 0;
|
i = 0;
|
||||||
mult = 1;
|
mult = 1;
|
||||||
while( (c = zTxt[i])>='a' && c<='z' ){
|
while( (c = zTxt[i++])>='a' && c<='z' ){
|
||||||
n += (zTxt[i] - 'a')*mult;
|
n += (zTxt[i] - 'a')*mult;
|
||||||
mult *= 26;
|
mult *= 26;
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
sqlite3_free(pFile->aJrnl);
|
sqlite3_free(pFile->aJrnl);
|
||||||
pFile->aJrnl = sqlite3_malloc64( n );
|
pFile->aJrnl = sqlite3_malloc64( n );
|
||||||
@ -417,26 +439,73 @@ static void kvvfsDecodeJournal(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Read or write the "sz" element, containing the database file size.
|
||||||
|
*/
|
||||||
|
static sqlite3_int64 kvvfsReadFileSize(KVVfsFile *pFile){
|
||||||
|
char zData[50];
|
||||||
|
zData[0] = 0;
|
||||||
|
kvstorageRead(pFile->pVfs->pStore, "sz", zData, sizeof(zData)-1);
|
||||||
|
return strtoll(zData, 0, 0);
|
||||||
|
}
|
||||||
|
static void kvvfsWriteFileSize(KVVfsFile *pFile, sqlite3_int64 sz){
|
||||||
|
char zData[50];
|
||||||
|
sqlite3_snprintf(sizeof(zData), zData, "%lld", sz);
|
||||||
|
kvstorageWrite(pFile->pVfs->pStore, "sz", zData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****** VFS methods ********************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Close an kvvfs-file.
|
||||||
|
*/
|
||||||
|
static int kvvfsClose(sqlite3_file *pProtoFile){
|
||||||
|
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
|
||||||
|
KVVfsVfs *pVfs = pFile->pVfs;
|
||||||
|
|
||||||
|
KVVFS_LOG(("xClose %s\n", pFile->isJournal ? "journal" : "db"));
|
||||||
|
if( pVfs->pFiles==pFile ){
|
||||||
|
pVfs->pFiles = pFile->pNext;
|
||||||
|
if( pVfs->pFiles==0 ){
|
||||||
|
kvstorageClose(pVfs->pStore);
|
||||||
|
pVfs->pStore = 0;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
KVVfsFile *pX = pVfs->pFiles;
|
||||||
|
while( 1 ){
|
||||||
|
assert( pX );
|
||||||
|
if( pX->pNext==pFile ){
|
||||||
|
pX->pNext = pFile->pNext;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pX = pX->pNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sqlite3_free(pFile->aJrnl);
|
||||||
|
return SQLITE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Read from the -journal file.
|
** Read from the -journal file.
|
||||||
*/
|
*/
|
||||||
static int kvvfsReadFromJournal(
|
static int kvvfsReadJrnl(
|
||||||
KVVfsFile *pFile,
|
sqlite3_file *pProtoFile,
|
||||||
void *zBuf,
|
void *zBuf,
|
||||||
int iAmt,
|
int iAmt,
|
||||||
sqlite_int64 iOfst
|
sqlite_int64 iOfst
|
||||||
){
|
){
|
||||||
|
KVVfsFile *pFile = (KVVfsFile*)pProtoFile;
|
||||||
assert( pFile->isJournal );
|
assert( pFile->isJournal );
|
||||||
KVVFS_LOG(("xRead('journal',%d,%lld)\n", iAmt, iOfst));
|
KVVFS_LOG(("xRead('journal',%d,%lld)\n", iAmt, iOfst));
|
||||||
if( pFile->aJrnl==0 ){
|
if( pFile->aJrnl==0 ){
|
||||||
int szTxt = kvstorageRead(pFile->pVfs->pStore, "journal", 0, 0);
|
int szTxt = kvstorageRead(pFile->pVfs->pStore, "jrnl", 0, 0);
|
||||||
char *aTxt;
|
char *aTxt;
|
||||||
if( szTxt<=4 ){
|
if( szTxt<=4 ){
|
||||||
return SQLITE_IOERR;
|
return SQLITE_IOERR;
|
||||||
}
|
}
|
||||||
aTxt = sqlite3_malloc64( szTxt+1 );
|
aTxt = sqlite3_malloc64( szTxt+1 );
|
||||||
if( aTxt==0 ) return SQLITE_NOMEM;
|
if( aTxt==0 ) return SQLITE_NOMEM;
|
||||||
kvstorageRead(pFile->pVfs->pStore, "journal", aTxt, szTxt+1);
|
kvstorageRead(pFile->pVfs->pStore, "jrnl", aTxt, szTxt+1);
|
||||||
kvvfsDecodeJournal(pFile, aTxt, szTxt);
|
kvvfsDecodeJournal(pFile, aTxt, szTxt);
|
||||||
sqlite3_free(aTxt);
|
sqlite3_free(aTxt);
|
||||||
if( pFile->aJrnl==0 ) return SQLITE_IOERR;
|
if( pFile->aJrnl==0 ) return SQLITE_IOERR;
|
||||||
@ -451,12 +520,13 @@ static int kvvfsReadFromJournal(
|
|||||||
/*
|
/*
|
||||||
** Read from the database file.
|
** Read from the database file.
|
||||||
*/
|
*/
|
||||||
static int kvvfsReadFromDb(
|
static int kvvfsReadDb(
|
||||||
KVVfsFile *pFile,
|
sqlite3_file *pProtoFile,
|
||||||
void *zBuf,
|
void *zBuf,
|
||||||
int iAmt,
|
int iAmt,
|
||||||
sqlite_int64 iOfst
|
sqlite_int64 iOfst
|
||||||
){
|
){
|
||||||
|
KVVfsFile *pFile = (KVVfsFile*)pProtoFile;
|
||||||
unsigned int pgno;
|
unsigned int pgno;
|
||||||
int got, n;
|
int got, n;
|
||||||
char zKey[30];
|
char zKey[30];
|
||||||
@ -476,7 +546,7 @@ static int kvvfsReadFromDb(
|
|||||||
}else{
|
}else{
|
||||||
pgno = 1;
|
pgno = 1;
|
||||||
}
|
}
|
||||||
sqlite3_snprintf(sizeof(zKey), zKey, "pg-%u", pgno);
|
sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno);
|
||||||
got = kvstorageRead(pFile->pVfs->pStore, zKey, aData, sizeof(aData)-1);
|
got = kvstorageRead(pFile->pVfs->pStore, zKey, aData, sizeof(aData)-1);
|
||||||
if( got<0 ){
|
if( got<0 ){
|
||||||
n = 0;
|
n = 0;
|
||||||
@ -502,50 +572,16 @@ static int kvvfsReadFromDb(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Read data from an kvvfs-file.
|
|
||||||
*/
|
|
||||||
static int kvvfsRead(
|
|
||||||
sqlite3_file *pProtoFile,
|
|
||||||
void *zBuf,
|
|
||||||
int iAmt,
|
|
||||||
sqlite_int64 iOfst
|
|
||||||
){
|
|
||||||
int rc;
|
|
||||||
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
|
|
||||||
if( pFile->isJournal ){
|
|
||||||
rc = kvvfsReadFromJournal(pFile,zBuf,iAmt,iOfst);
|
|
||||||
}else{
|
|
||||||
rc = kvvfsReadFromDb(pFile,zBuf,iAmt,iOfst);
|
|
||||||
}
|
|
||||||
KVVFS_LOG(("xRead result: 0x%x\n", rc));
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Read or write the "sz" element, containing the database file size.
|
|
||||||
*/
|
|
||||||
static sqlite3_int64 kvvfsReadFileSize(KVVfsFile *pFile){
|
|
||||||
char zData[50];
|
|
||||||
zData[0] = 0;
|
|
||||||
kvstorageRead(pFile->pVfs->pStore, "sz", zData, sizeof(zData)-1);
|
|
||||||
return strtoll(zData, 0, 0);
|
|
||||||
}
|
|
||||||
static void kvvfsWriteFileSize(KVVfsFile *pFile, sqlite3_int64 sz){
|
|
||||||
char zData[50];
|
|
||||||
sqlite3_snprintf(sizeof(zData), zData, "%lld", sz);
|
|
||||||
kvstorageWrite(pFile->pVfs->pStore, "sz", zData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Write into the -journal file.
|
** Write into the -journal file.
|
||||||
*/
|
*/
|
||||||
static int kvvfsWriteToJournal(
|
static int kvvfsWriteJrnl(
|
||||||
KVVfsFile *pFile,
|
sqlite3_file *pProtoFile,
|
||||||
const void *zBuf,
|
const void *zBuf,
|
||||||
int iAmt,
|
int iAmt,
|
||||||
sqlite_int64 iOfst
|
sqlite_int64 iOfst
|
||||||
){
|
){
|
||||||
|
KVVfsFile *pFile = (KVVfsFile*)pProtoFile;
|
||||||
sqlite3_int64 iEnd = iOfst+iAmt;
|
sqlite3_int64 iEnd = iOfst+iAmt;
|
||||||
KVVFS_LOG(("xWrite('journal',%d,%lld)\n", iAmt, iOfst));
|
KVVFS_LOG(("xWrite('journal',%d,%lld)\n", iAmt, iOfst));
|
||||||
if( iEnd>=0x10000000 ) return SQLITE_FULL;
|
if( iEnd>=0x10000000 ) return SQLITE_FULL;
|
||||||
@ -567,12 +603,13 @@ static int kvvfsWriteToJournal(
|
|||||||
/*
|
/*
|
||||||
** Write into the database file.
|
** Write into the database file.
|
||||||
*/
|
*/
|
||||||
static int kvvfsWriteToDb(
|
static int kvvfsWriteDb(
|
||||||
KVVfsFile *pFile,
|
sqlite3_file *pProtoFile,
|
||||||
const void *zBuf,
|
const void *zBuf,
|
||||||
int iAmt,
|
int iAmt,
|
||||||
sqlite_int64 iOfst
|
sqlite_int64 iOfst
|
||||||
){
|
){
|
||||||
|
KVVfsFile *pFile = (KVVfsFile*)pProtoFile;
|
||||||
unsigned int pgno;
|
unsigned int pgno;
|
||||||
char zKey[30];
|
char zKey[30];
|
||||||
char aData[131073];
|
char aData[131073];
|
||||||
@ -580,7 +617,7 @@ static int kvvfsWriteToDb(
|
|||||||
assert( iAmt>=512 && iAmt<=65536 );
|
assert( iAmt>=512 && iAmt<=65536 );
|
||||||
assert( (iAmt & (iAmt-1))==0 );
|
assert( (iAmt & (iAmt-1))==0 );
|
||||||
pgno = 1 + iOfst/iAmt;
|
pgno = 1 + iOfst/iAmt;
|
||||||
sqlite3_snprintf(sizeof(zKey), zKey, "pg-%u", pgno);
|
sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno);
|
||||||
kvvfsEncode(zBuf, iAmt, aData);
|
kvvfsEncode(zBuf, iAmt, aData);
|
||||||
kvstorageWrite(pFile->pVfs->pStore, zKey, aData);
|
kvstorageWrite(pFile->pVfs->pStore, zKey, aData);
|
||||||
if( iOfst+iAmt > pFile->szDb ){
|
if( iOfst+iAmt > pFile->szDb ){
|
||||||
@ -589,41 +626,21 @@ static int kvvfsWriteToDb(
|
|||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Write data into the kvvfs-file.
|
|
||||||
*/
|
|
||||||
static int kvvfsWrite(
|
|
||||||
sqlite3_file *pProtoFile,
|
|
||||||
const void *zBuf,
|
|
||||||
int iAmt,
|
|
||||||
sqlite_int64 iOfst
|
|
||||||
){
|
|
||||||
int rc;
|
|
||||||
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
|
|
||||||
if( pFile->isJournal ){
|
|
||||||
rc = kvvfsWriteToJournal(pFile,zBuf,iAmt,iOfst);
|
|
||||||
}else{
|
|
||||||
rc = kvvfsWriteToDb(pFile,zBuf,iAmt,iOfst);
|
|
||||||
}
|
|
||||||
KVVFS_LOG(("xWrite result: 0x%x\n", rc));
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Truncate an kvvfs-file.
|
** Truncate an kvvfs-file.
|
||||||
*/
|
*/
|
||||||
static int kvvfsTruncate(sqlite3_file *pProtoFile, sqlite_int64 size){
|
static int kvvfsTruncateJrnl(sqlite3_file *pProtoFile, sqlite_int64 size){
|
||||||
|
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
|
||||||
|
KVVFS_LOG(("xTruncate('journal',%lld)\n", size));
|
||||||
|
assert( size==0 );
|
||||||
|
kvstorageDelete(pFile->pVfs->pStore, "jrnl");
|
||||||
|
sqlite3_free(pFile->aJrnl);
|
||||||
|
pFile->aJrnl = 0;
|
||||||
|
pFile->nJrnl = 0;
|
||||||
|
return SQLITE_OK;
|
||||||
|
}
|
||||||
|
static int kvvfsTruncateDb(sqlite3_file *pProtoFile, sqlite_int64 size){
|
||||||
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
|
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
|
||||||
if( pFile->isJournal ){
|
|
||||||
KVVFS_LOG(("xTruncate('journal',%lld)\n", size));
|
|
||||||
assert( size==0 );
|
|
||||||
kvstorageDelete(pFile->pVfs->pStore, "journal");
|
|
||||||
sqlite3_free(pFile->aJrnl);
|
|
||||||
pFile->aJrnl = 0;
|
|
||||||
pFile->nJrnl = 0;
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
if( pFile->szDb>size
|
if( pFile->szDb>size
|
||||||
&& pFile->szPage>0
|
&& pFile->szPage>0
|
||||||
&& (size % pFile->szPage)==0
|
&& (size % pFile->szPage)==0
|
||||||
@ -634,7 +651,7 @@ static int kvvfsTruncate(sqlite3_file *pProtoFile, sqlite_int64 size){
|
|||||||
pgno = 1 + size/pFile->szPage;
|
pgno = 1 + size/pFile->szPage;
|
||||||
pgnoMax = 2 + pFile->szDb/pFile->szPage;
|
pgnoMax = 2 + pFile->szDb/pFile->szPage;
|
||||||
while( pgno<=pgnoMax ){
|
while( pgno<=pgnoMax ){
|
||||||
sqlite3_snprintf(sizeof(zKey), zKey, "pg-%u", pgno);
|
sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno);
|
||||||
kvstorageDelete(pFile->pVfs->pStore, zKey);
|
kvstorageDelete(pFile->pVfs->pStore, zKey);
|
||||||
pgno++;
|
pgno++;
|
||||||
}
|
}
|
||||||
@ -648,20 +665,13 @@ static int kvvfsTruncate(sqlite3_file *pProtoFile, sqlite_int64 size){
|
|||||||
/*
|
/*
|
||||||
** Sync an kvvfs-file.
|
** Sync an kvvfs-file.
|
||||||
*/
|
*/
|
||||||
static int kvvfsSync(sqlite3_file *pProtoFile, int flags){
|
static int kvvfsSyncJrnl(sqlite3_file *pProtoFile, int flags){
|
||||||
int i, n;
|
int i, n;
|
||||||
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
|
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
|
||||||
char *zOut;
|
char *zOut;
|
||||||
if( !pFile->isJournal ){
|
|
||||||
KVVFS_LOG(("xSync('db')\n"));
|
|
||||||
if( pFile->szDb>0 ){
|
|
||||||
kvvfsWriteFileSize(pFile, pFile->szDb);
|
|
||||||
}
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
KVVFS_LOG(("xSync('journal')\n"));
|
KVVFS_LOG(("xSync('journal')\n"));
|
||||||
if( pFile->nJrnl<=0 ){
|
if( pFile->nJrnl<=0 ){
|
||||||
return kvvfsTruncate(pProtoFile, 0);
|
return kvvfsTruncateJrnl(pProtoFile, 0);
|
||||||
}
|
}
|
||||||
zOut = sqlite3_malloc64( pFile->nJrnl*2 + 50 );
|
zOut = sqlite3_malloc64( pFile->nJrnl*2 + 50 );
|
||||||
if( zOut==0 ){
|
if( zOut==0 ){
|
||||||
@ -673,29 +683,38 @@ static int kvvfsSync(sqlite3_file *pProtoFile, int flags){
|
|||||||
zOut[i++] = 'a' + (n%26);
|
zOut[i++] = 'a' + (n%26);
|
||||||
n /= 26;
|
n /= 26;
|
||||||
}while( n>0 );
|
}while( n>0 );
|
||||||
|
zOut[i++] = ' ';
|
||||||
kvvfsEncode(pFile->aJrnl, pFile->nJrnl, &zOut[i]);
|
kvvfsEncode(pFile->aJrnl, pFile->nJrnl, &zOut[i]);
|
||||||
kvstorageWrite(pFile->pVfs->pStore, "journal", zOut);
|
kvstorageWrite(pFile->pVfs->pStore, "jrnl", zOut);
|
||||||
sqlite3_free(zOut);
|
sqlite3_free(zOut);
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
static int kvvfsSyncDb(sqlite3_file *pProtoFile, int flags){
|
||||||
|
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
|
||||||
|
KVVFS_LOG(("xSync('db')\n"));
|
||||||
|
if( pFile->szDb>0 ){
|
||||||
|
kvvfsWriteFileSize(pFile, pFile->szDb);
|
||||||
|
}
|
||||||
|
return SQLITE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Return the current file-size of an kvvfs-file.
|
** Return the current file-size of an kvvfs-file.
|
||||||
*/
|
*/
|
||||||
static int kvvfsFileSize(sqlite3_file *pProtoFile, sqlite_int64 *pSize){
|
static int kvvfsFileSizeJrnl(sqlite3_file *pProtoFile, sqlite_int64 *pSize){
|
||||||
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
|
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
|
||||||
if( pFile->isJournal ){
|
KVVFS_LOG(("xFileSize('journal')\n"));
|
||||||
KVVFS_LOG(("xFileSize('journal')\n"));
|
*pSize = pFile->nJrnl;
|
||||||
*pSize = pFile->nJrnl;
|
return SQLITE_OK;
|
||||||
|
}
|
||||||
|
static int kvvfsFileSizeDb(sqlite3_file *pProtoFile, sqlite_int64 *pSize){
|
||||||
|
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
|
||||||
|
KVVFS_LOG(("xFileSize('db')\n"));
|
||||||
|
if( pFile->szDb>=0 ){
|
||||||
|
*pSize = pFile->szDb;
|
||||||
}else{
|
}else{
|
||||||
KVVFS_LOG(("xFileSize('db')\n"));
|
*pSize = kvvfsReadFileSize(pFile);
|
||||||
if( pFile->szDb>=0 ){
|
|
||||||
*pSize = pFile->szDb;
|
|
||||||
}else{
|
|
||||||
*pSize = kvvfsReadFileSize(pFile);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
KVVFS_LOG(("xFileSize: %lld\n", *pSize));
|
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -772,10 +791,15 @@ static int kvvfsOpen(
|
|||||||
KVVFS_LOG(("xOpen(\"%s\")\n", zName));
|
KVVFS_LOG(("xOpen(\"%s\")\n", zName));
|
||||||
pFile->aJrnl = 0;
|
pFile->aJrnl = 0;
|
||||||
pFile->nJrnl = 0;
|
pFile->nJrnl = 0;
|
||||||
pFile->isJournal = sqlite3_strglob("*-journal", zName)==0;
|
if( sqlite3_strglob("*-journal", zName)==0 ){
|
||||||
|
pFile->isJournal = 1;
|
||||||
|
pFile->base.pMethods = &kvvfs_jrnl_io_methods;
|
||||||
|
}else{
|
||||||
|
pFile->isJournal = 0;
|
||||||
|
pFile->base.pMethods = &kvvfs_db_io_methods;
|
||||||
|
}
|
||||||
pFile->szPage = -1;
|
pFile->szPage = -1;
|
||||||
pFile->szDb = -1;
|
pFile->szDb = -1;
|
||||||
pFile->base.pMethods = &kvvfs_io_methods;
|
|
||||||
pFile->pVfs = pVfs;
|
pFile->pVfs = pVfs;
|
||||||
if( pVfs->pFiles==0 ){
|
if( pVfs->pFiles==0 ){
|
||||||
pVfs->pStore = kvstorageOpen();
|
pVfs->pStore = kvstorageOpen();
|
||||||
@ -793,7 +817,7 @@ static int kvvfsOpen(
|
|||||||
static int kvvfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
|
static int kvvfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
|
||||||
KVVfsVfs *p = (KVVfsVfs*)pVfs;
|
KVVfsVfs *p = (KVVfsVfs*)pVfs;
|
||||||
if( sqlite3_strglob("*-journal",zPath)==0 ){
|
if( sqlite3_strglob("*-journal",zPath)==0 ){
|
||||||
kvstorageDelete(p->pStore, "journal");
|
kvstorageDelete(p->pStore, "jrnl");
|
||||||
}
|
}
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
@ -811,7 +835,7 @@ static int kvvfsAccess(
|
|||||||
KVVfsVfs *pVfs = (KVVfsVfs*)pProtoVfs;
|
KVVfsVfs *pVfs = (KVVfsVfs*)pProtoVfs;
|
||||||
KVVFS_LOG(("xAccess(\"%s\")\n", zPath));
|
KVVFS_LOG(("xAccess(\"%s\")\n", zPath));
|
||||||
if( sqlite3_strglob("*-journal", zPath)==0 ){
|
if( sqlite3_strglob("*-journal", zPath)==0 ){
|
||||||
*pResOut = kvstorageRead(pVfs->pStore, "journal", 0, 0)>0;
|
*pResOut = kvstorageRead(pVfs->pStore, "jrnl", 0, 0)>0;
|
||||||
}else if( sqlite3_strglob("*-wal", zPath)==0 ){
|
}else if( sqlite3_strglob("*-wal", zPath)==0 ){
|
||||||
*pResOut = 0;
|
*pResOut = 0;
|
||||||
}else{
|
}else{
|
||||||
|
12
manifest
12
manifest
@ -1,5 +1,5 @@
|
|||||||
C Simple\sreading\sand\swriting\snow\sworks.
|
C Separate\ssqlite3_io_methods\sobjects\sfor\sdatabase\sfiles\sand\sjournals.
|
||||||
D 2022-09-09T11:41:54.677
|
D 2022-09-09T14:22:41.989
|
||||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||||
@ -335,7 +335,7 @@ F ext/misc/uint.c 053fed3bce2e89583afcd4bf804d75d659879bbcedac74d0fa9ed548839a03
|
|||||||
F ext/misc/unionvtab.c 36237f0607ca954ac13a4a0e2d2ac40c33bc6e032a5f55f431713061ef1625f9
|
F ext/misc/unionvtab.c 36237f0607ca954ac13a4a0e2d2ac40c33bc6e032a5f55f431713061ef1625f9
|
||||||
F ext/misc/urifuncs.c f71360d14fa9e7626b563f1f781c6148109462741c5235ac63ae0f8917b9c751
|
F ext/misc/urifuncs.c f71360d14fa9e7626b563f1f781c6148109462741c5235ac63ae0f8917b9c751
|
||||||
F ext/misc/uuid.c 5bb2264c1b64d163efa46509544fd7500cb8769cb7c16dd52052da8d961505cf
|
F ext/misc/uuid.c 5bb2264c1b64d163efa46509544fd7500cb8769cb7c16dd52052da8d961505cf
|
||||||
F ext/misc/vfskv.c 8c0d3af0b68fdee50ff46b64bec28d693805bd5fc5e26605e198915e9392d6e3
|
F ext/misc/vfskv.c 7b2fa888cd33f41a7a3821eec10ed258fe029af41ad788a43856958c4d216432
|
||||||
F ext/misc/vfslog.c 3932ab932eeb2601dbc4447cb14d445aaa9fbe43b863ef5f014401c3420afd20
|
F ext/misc/vfslog.c 3932ab932eeb2601dbc4447cb14d445aaa9fbe43b863ef5f014401c3420afd20
|
||||||
F ext/misc/vfsstat.c 474d08efc697b8eba300082cb1eb74a5f0f3df31ed257db1cb07e72ab0e53dfb
|
F ext/misc/vfsstat.c 474d08efc697b8eba300082cb1eb74a5f0f3df31ed257db1cb07e72ab0e53dfb
|
||||||
F ext/misc/vtablog.c 5538acd0c8ddaae372331bee11608d76973436b77d6a91e8635cfc9432fba5ae
|
F ext/misc/vtablog.c 5538acd0c8ddaae372331bee11608d76973436b77d6a91e8635cfc9432fba5ae
|
||||||
@ -2001,8 +2001,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
|||||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||||
P 2e38726f46918b28b5c638967f960a20afd3fe84ad245f3bea39a1d64980435b
|
P 00845ac9ef2616e90f5f6a20da3dd040fa8bdcfe73f72fe9c06039561150a82d
|
||||||
R d99171917ec9b13f78c647c76b29147e
|
R 460848ff6f3cd63ef5eccab59824c77b
|
||||||
U drh
|
U drh
|
||||||
Z d5b6013a0fd62dab0ae32db15d37fb8f
|
Z 26961af5f4b759d7a43ac0a5cf8d117b
|
||||||
# Remove this line to create a well-formed Fossil manifest.
|
# Remove this line to create a well-formed Fossil manifest.
|
||||||
|
@ -1 +1 @@
|
|||||||
00845ac9ef2616e90f5f6a20da3dd040fa8bdcfe73f72fe9c06039561150a82d
|
74fbf6c2a97729e481d5562344e960d0c237aeb1f07240262d32a24fb1f4b5a3
|
Reference in New Issue
Block a user