From 59ece7e1060e00b711f9967706379cb7d2214cc3 Mon Sep 17 00:00:00 2001 From: drh <> Date: Wed, 7 Sep 2022 17:29:22 +0000 Subject: [PATCH 01/13] Non-working code towards a VFS for text key/value storage. FossilOrigin-Name: f9c89ee8d5ef46342bea78fa8d4da058d9ea628183ec985642bbda1cdfeacd5f --- ext/misc/vfskv.c | 645 +++++++++++++++++++++++++++++++++++++++++++++++ manifest | 15 +- manifest.uuid | 2 +- 3 files changed, 655 insertions(+), 7 deletions(-) create mode 100644 ext/misc/vfskv.c diff --git a/ext/misc/vfskv.c b/ext/misc/vfskv.c new file mode 100644 index 0000000000..4d8d797a4f --- /dev/null +++ b/ext/misc/vfskv.c @@ -0,0 +1,645 @@ +/* +** 2022-09-06 +** +** 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 an experimental VFS layer that operates on a +** Key/Value storage engine where both keys and values must be pure +** text. +*/ +#include "sqlite3.h" +#include +#include +#include +#include +#include +#include +#include + + +/***************************************************************************** +** The low-level storage engine +*/ +typedef struct KVStorage KVStorage; +struct KVStorage { + char *zDir; + char zKey[50]; +}; + +static KVStorage *kvstorageOpen(void); +static void kvstorageClose(KVStorage*); +static int kvstorageWrite(KVStorage*, const char *zKey, const char *zData); +static int kvstorageDelete(KVStorage*, const char *zKey); +static int kvstorageSize(KVStorage*, const char *zKey); +static int kvstorageRead(KVStorage*, const char *zKey, char *zBuf, int nBuf); + + +/* +** Forward declaration of objects used by this utility +*/ +typedef struct KVVfsVfs KVVfsVfs; +typedef struct KVVfsFile KVVfsFile; + +struct KVVfsVfs { + sqlite3_vfs base; /* VFS methods */ + KVStorage *pStore; /* Single command KV storage object */ + KVVfsFile *pFiles; /* List of open KVVfsFile objects */ +}; + +struct KVVfsFile { + sqlite3_file base; /* IO methods */ + KVVfsVfs *pVfs; /* The VFS to which this file belongs */ + KVVfsFile *pNext; /* Next in list of all files */ + int isJournal; /* True if this is a journal file */ + int nJrnl; /* Space allocated for aJrnl[] */ + char *aJrnl; /* Journal content */ +}; + +/* +** Methods for KVVfsFile +*/ +static int kvvfsClose(sqlite3_file*); +static int kvvfsRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); +static int kvvfsWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst); +static int kvvfsTruncate(sqlite3_file*, sqlite3_int64 size); +static int kvvfsSync(sqlite3_file*, int flags); +static int kvvfsFileSize(sqlite3_file*, sqlite3_int64 *pSize); +static int kvvfsLock(sqlite3_file*, int); +static int kvvfsUnlock(sqlite3_file*, int); +static int kvvfsCheckReservedLock(sqlite3_file*, int *pResOut); +static int kvvfsFileControl(sqlite3_file*, int op, void *pArg); +static int kvvfsSectorSize(sqlite3_file*); +static int kvvfsDeviceCharacteristics(sqlite3_file*); + +/* +** Methods for KVVfsVfs +*/ +static int kvvfsOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *); +static int kvvfsDelete(sqlite3_vfs*, const char *zName, int syncDir); +static int kvvfsAccess(sqlite3_vfs*, const char *zName, int flags, int *); +static int kvvfsFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut); +static void *kvvfsDlOpen(sqlite3_vfs*, const char *zFilename); +static void kvvfsDlError(sqlite3_vfs*, int nByte, char *zErrMsg); +static void (*kvvfsDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void); +static void kvvfsDlClose(sqlite3_vfs*, void*); +static int kvvfsRandomness(sqlite3_vfs*, int nByte, char *zOut); +static int kvvfsSleep(sqlite3_vfs*, int microseconds); +static int kvvfsCurrentTime(sqlite3_vfs*, double*); +static int kvvfsGetLastError(sqlite3_vfs*, int, char *); +static int kvvfsCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*); + +static KVVfsVfs kvvfs_vfs = { + { + 1, /* iVersion */ + sizeof(KVVfsFile), /* szOsFile */ + 1024, /* mxPathname */ + 0, /* pNext */ + "kvvfs", /* zName */ + 0, /* pAppData */ + kvvfsOpen, /* xOpen */ + kvvfsDelete, /* xDelete */ + kvvfsAccess, /* xAccess */ + kvvfsFullPathname, /* xFullPathname */ + kvvfsDlOpen, /* xDlOpen */ + 0, /* xDlError */ + 0, /* xDlSym */ + 0, /* xDlClose */ + kvvfsRandomness, /* xRandomness */ + kvvfsSleep, /* xSleep */ + kvvfsCurrentTime, /* xCurrentTime */ + 0, /* xGetLastError */ + kvvfsCurrentTimeInt64, /* xCurrentTimeInt64 */ + }, + 0, + 0 +}; + +static sqlite3_io_methods kvvfs_io_methods = { + 1, /* iVersion */ + kvvfsClose, /* xClose */ + kvvfsRead, /* xRead */ + kvvfsWrite, /* xWrite */ + kvvfsTruncate, /* xTruncate */ + kvvfsSync, /* xSync */ + kvvfsFileSize, /* 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 */ +}; + +/****** Storage subsystem **************************************************/ + +/* Allocate a new storage subsystem. +** Return NULL if OOM +*/ +static KVStorage *kvstorageOpen(void){ + KVStorage *pStore; + pStore = sqlite3_malloc64( sizeof(*pStore) ); + if( pStore==0 ) return 0; + memset(pStore, 0, sizeof(*pStore)); + return pStore; +} + +/* Free all resources associated with the storage subsystem */ +static void kvstorageClose(KVStorage *pStore){ + sqlite3_free(pStore); +} + +/* Expand the key name with an appropriate prefix and put the result +** in pStore->zKey[] +*/ +static void kvstorageMakeKey(KVStorage *pStore, const char *zKey){ + sqlite3_snprintf(sizeof(pStore->zKey), pStore->zKey, "kvvfs-%s", zKey); +} + +/* Write content into a key. zKey is of limited size. zData should be +** pure text. In other words, zData has already been encoded. +** +** Return the number of errors. +*/ +static int kvstorageWrite( + KVStorage *pStore, + const char *zKey, + const char *zData +){ + FILE *fd; + kvstorageMakeKey(pStore, zKey); + fd = fopen(pStore->zKey, "wb"); + if( fd==0 ) return 1; + if( fd ){ + fputs(zData, fd); + fclose(fd); + } + return 0; +} + +/* Delete a key +*/ +static int kvstorageDelete(KVStorage *pStore, const char *zKey){ + kvstorageMakeKey(pStore, zKey); + unlink(pStore->zKey); + return 0; +} + +/* Read the value associated with a key and put the result in the first +** nBuf bytes of zBuf[]. The value might be truncated if zBuf is not large +** enough to hold it all. The value put into zBuf will always be zero +** terminated. +** +** Return the total number of bytes in the data, without truncation, and +** not counting the final zero terminator. Return -1 if the key does +** not exist. +** +** If nBuf==0 then this routine simply returns the size of the data without +** actually reading it. +*/ +static int kvstorageRead( + KVStorage *pStore, + const char *zKey, + char *zBuf, + int nBuf +){ + FILE *fd; + struct stat buf; + kvstorageMakeKey(pStore, zKey); + if( access(pStore->zKey, R_OK)!=0 + || stat(pStore->zKey, &buf)!=0 + || !S_ISREG(buf.st_mode) + ){ + return -1; + } + if( nBuf<0 ){ + return (int)buf.st_size; + }else if( nBuf==1 ){ + zBuf[0] = 0; + return (int)buf.st_size; + } + if( nBuf-1 > buf.st_size ){ + nBuf = buf.st_size + 1; + } + fd = fopen(pStore->zKey, "rb"); + if( fd==0 ) return -1; + fread(zBuf, nBuf-1, 1, fd); + fclose(fd); + return nBuf-1; +} + + +/****** The main VFS code **************************************************/ + +/* +** Close an kvvfs-file. +*/ +static int kvvfsClose(sqlite3_file *pProtoFile){ + KVVfsFile *pFile = (KVVfsFile *)pProtoFile; + KVVfsVfs *pVfs = pFile->pVfs; + + 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->aData); + sqlite3_free(pFile); + return SQLITE_OK; +} + +/* +** Encode binary into the text encoded used to persist on disk. +** The output text is stored in aOut[], which must be at least +** nData+1 bytes in length. +** +** Return the actual length of the encoded text, not counting the +** zero terminator at the end. +*/ +static int kvvfsEncode(const char *aData, int nData, char *aOut){ + int i, j; + const unsigned *a = (const unsigned char*)aData; + for(i=j=0; i>4]; + aOut[j++] = "0123456789ABCDEF"[c&0xf]; + }else{ + /* A sequence of 1 or more zeros is stored as a little-endian + ** base-26 number using a..z as the digits. So one zero is "b". + ** Two zeros is "c". 25 zeros is "z", 26 zeros is "ba" and so forth. + */ + int k; + for(k=1; a[i+k]==0 && i+k0 ){ + aOut[j++] = 'a'+(k%26); + k /= 26; + } + } + } + aOut[j] = 0; + return j; +} + +/* Convert hex to binary */ +static char kvvfsHexToBinary(char c){ + if( c>='0' && c<='9' ) return c - '0'; + if( c>='a' && c<='f' ) return c - 'a' + 10; + return 0; +} + +/* +** Decode the text encoding back to binary. The binary content is +** written into pOut, which must be at least nOut bytes in length. +*/ +static int kvvfsDecode(const char *aIn, char *aOut, int nOut){ + char *aOut; + int i, j, k; + int c; + i = 0; + j = 0; + while( (c = aIn[i])!=0 ){ + if( c>='a' ){ + int n = 0; + while( c>='a' && c<='z' ){ + n = n*26 + c - 'a'; + c = aIn[++i]; + } + if( j+n>nOut ) return -1; + while( n-->0 ){ + aOut[j++] = 0; + } + }else{ + if( j>nOut ) return -1; + aOut[j] = kvvfsHexToBinary(aIn[i])<<4; + i++; + aOut[j] += kvvfsHexToBinary(aIn[i]); + i++; + } + } + return j; +} + +/* +** Read from the -journal file. +*/ +static int kvvfsReadFromJournal( + KVVfsFile *pFile, + void *zBuf, + int iAmt, + sqlite_int64 iOfst +){ + assert( pFile->isJournal ); + if( pFile->aJrnl==0 ){ + int szTxt = kvstorageRead(pFile->pVfs->pStore, "journal", 0, 0); + char *aTxt; + if( szTxt<=4 ){ + return SQLITE_IOERR; + } + aTxt = sqlite3_malloc64( szTxt+1 ); + if( aTxt==0 ) return SQLITE_NOMEM; + kvstorageRead(pFile->pVfs->pStore, "journal", aTxt, szTxt+1); + kvvfsDecodeJournal(pFile, aTxt, szTxt); + sqlite3_free(aTxt); + if( pFile->aData==0 ) return SQLITE_IOERR; + } + if( iOfst+iAmt>pFile->nJrnl ){ + return SQLITE_IOERR_SHORT_READ; + } + mcmcpy(zBuf, pFile->aJrnl+iOfst, iAmt); + return SQLITE_OK; +} + +/* +** Read from the database file. +*/ +static int kvvfsReadFromDb( + KVVfsFile *pFile, + void *zBuf, + int iAmt, + sqlite_int64 iOfst +){ + return SQLITE_IOERR; +} + + +/* +** 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); + } + return rc; +} + +/* +** Write into the -journal file. +*/ +static int kvvfsWriteToJournal( + KVVfsFile *pFile, + const void *zBuf, + int iAmt, + sqlite_int64 iOfst +){ + return SQLITE_IOERR; +} + +/* +** Read from the database file. +*/ +static int kvvfsWriteToDb( + KVVfsFile *pFile, + const void *zBuf, + int iAmt, + sqlite_int64 iOfst +){ + return SQLITE_IOERR; +} + + +/* +** 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); + } + return rc; +} + +/* +** Truncate an kvvfs-file. +*/ +static int kvvfsTruncate(sqlite3_file *pFile, sqlite_int64 size){ + int rc; + KVVfsFile *pFile = (KVVfsFile *)pProtoFile; + rc = SQLITE_IOERR; + return rc; +} + +/* +** Sync an kvvfs-file. +*/ +static int kvvfsSync(sqlite3_file *pFile, int flags){ + int rc; + KVVfsFile *pFile = (KVVfsFile *)pProtoFile; + rc = SQLITE_IOERR; + return rc; +} + +/* +** Return the current file-size of an kvvfs-file. +*/ +static int kvvfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ + int rc; + KVVfsFile *pFile = (KVVfsFile *)pProtoFile; + *pSize = 0; + rc = SQLITE_IOERR; + return rc; +} + +/* +** Lock an kvvfs-file. +*/ +static int kvvfsLock(sqlite3_file *pFile, int eLock){ + int rc; + KVVfsFile *pFile = (KVVfsFile *)pProtoFile; + rc = SQLITE_IOERR; + return rc; +} + +/* +** Unlock an kvvfs-file. +*/ +static int kvvfsUnlock(sqlite3_file *pFile, int eLock){ + int rc; + KVVfsFile *pFile = (KVVfsFile *)pProtoFile; + rc = SQLITE_IOERR; + return rc; +} + +/* +** Check if another file-handle holds a RESERVED lock on an kvvfs-file. +*/ +static int kvvfsCheckReservedLock(sqlite3_file *pFile, int *pResOut){ + int rc; + KVVfsFile *pFile = (KVVfsFile *)pProtoFile; + *pResOut = 0; + rc = SQLITE_IOERR; + return rc; +} + +/* +** File control method. For custom operations on an kvvfs-file. +*/ +static int kvvfsFileControl(sqlite3_file *pFile, int op, void *pArg){ + int rc; + KVVfsFile *pFile = (KVVfsFile *)pProtoFile; + rc = SQLITE_NOTFOUND; + return rc; +} + +/* +** Return the sector-size in bytes for an kvvfs-file. +*/ +static int kvvfsSectorSize(sqlite3_file *pFile){ + return 4096; +} + +/* +** Return the device characteristic flags supported by an kvvfs-file. +*/ +static int kvvfsDeviceCharacteristics(sqlite3_file *pFile){ + return 0; +} + + +/* +** Open an kvvfs file handle. +*/ +static int kvvfsOpen( + sqlite3_vfs *pProtoVfs, + const char *zName, + sqlite3_file *pProtoFile, + int flags, + int *pOutFlags +){ + int rc; + KVVfsFile *pFile = (KVVfsFile*)pProtoFile; + KVVfsVfs *pVfs = (KVVfsVfs*)pProtoVfs; + + + return rc; +} + +/* +** Delete the file located at zPath. If the dirSync argument is true, +** ensure the file-system modifications are synced to disk before +** returning. +*/ +static int kvvfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ + KVVfsVfs *p = (KVVfsVfs*)pVfs; + if( sqlite3_strglob("*-journal",zPath)==0 ){ + kvstorageDelete(p->pStore, "journal"); + } + return SQLITE_OK; +} + +/* +** Test for access permissions. Return true if the requested permission +** is available, or false otherwise. +*/ +static int kvvfsAccess( + sqlite3_vfs *pVfs, + const char *zPath, + int flags, + int *pResOut +){ + *pResOut = 1; + return SQLITE_OK; +} + +/* +** Populate buffer zOut with the full canonical pathname corresponding +** to the pathname in zPath. zOut is guaranteed to point to a buffer +** of at least (INST_MAX_PATHNAME+1) bytes. +*/ +static int kvvfsFullPathname( + sqlite3_vfs *pVfs, + const char *zPath, + int nOut, + char *zOut +){ + size_t nPath = strlen(zPath); + if( nOut Date: Thu, 8 Sep 2022 15:48:01 +0000 Subject: [PATCH 02/13] Code snapshot. Completely untested. Probably does not compile. FossilOrigin-Name: 51e267696d25f2f83b5bb847d5254ab15573ef1a16ea3d7dd8279c73c0bee539 --- ext/misc/vfskv.c | 241 +++++++++++++++++++++++++++++++++++++++++------ manifest | 15 ++- manifest.uuid | 2 +- 3 files changed, 217 insertions(+), 41 deletions(-) diff --git a/ext/misc/vfskv.c b/ext/misc/vfskv.c index 4d8d797a4f..0773f70945 100644 --- a/ext/misc/vfskv.c +++ b/ext/misc/vfskv.c @@ -47,19 +47,26 @@ static int kvstorageRead(KVStorage*, const char *zKey, char *zBuf, int nBuf); typedef struct KVVfsVfs KVVfsVfs; typedef struct KVVfsFile KVVfsFile; + +/* All information about the database */ struct KVVfsVfs { sqlite3_vfs base; /* VFS methods */ KVStorage *pStore; /* Single command KV storage object */ KVVfsFile *pFiles; /* List of open KVVfsFile objects */ }; +/* A single open file. There are only two files represented by this +** VFS - the database and the rollback journal. +*/ struct KVVfsFile { sqlite3_file base; /* IO methods */ KVVfsVfs *pVfs; /* The VFS to which this file belongs */ KVVfsFile *pNext; /* Next in list of all files */ int isJournal; /* True if this is a journal file */ - int nJrnl; /* Space allocated for aJrnl[] */ + unsigned int nJrnl; /* Space allocated for aJrnl[] */ char *aJrnl; /* Journal content */ + int szPage; /* Last known page size */ + sqlite3_int64 szDb; /* Database file size. -1 means unknown */ }; /* @@ -291,7 +298,8 @@ static int kvvfsEncode(const char *aData, int nData, char *aOut){ }else{ /* A sequence of 1 or more zeros is stored as a little-endian ** base-26 number using a..z as the digits. So one zero is "b". - ** Two zeros is "c". 25 zeros is "z", 26 zeros is "ba" and so forth. + ** Two zeros is "c". 25 zeros is "z", 26 zeros is "ab", 27 is "bb", + ** and so forth. */ int k; for(k=1; a[i+k]==0 && i+k='a' ){ int n = 0; + int mult = 1; while( c>='a' && c<='z' ){ - n = n*26 + c - 'a'; + n += (c - 'a')*mult; + mult *= 26; c = aIn[++i]; } if( j+n>nOut ) return -1; @@ -345,6 +357,44 @@ static int kvvfsDecode(const char *aIn, char *aOut, int nOut){ return j; } +/* +** Decode a complete journal file. Allocate space in pFile->aJrnl +** and store the decoding there. Or leave pFile->aJrnl set to NULL +** if an error is encountered. +** +** The first few characters of the text encoding will be a +** base-26 number (digits a..z) that is the total number of bytes +** in the decoding. Use this number to size the initial allocation. +*/ +static void kvvfsDecodeJournal( + KVVfsFile *pFile, /* Store decoding in pFile->aJrnl */ + const char *zTxt, /* Text encoding. Zero-terminated */ + int nTxt /* Bytes in zTxt, excluding zero terminator */ +){ + unsigned int n; + int c, i, mult; + i = 0; + mult = 1; + while( (c = zTxt[i])>='a' && c<='z' ){ + n += (zTxt[i] - 'a')*mult; + mult *= 26; + i++; + } + sqlite3_free(pFile->aJrnl); + pFile->aJrnl = sqlite3_malloc64( n ); + if( pFile->aJrnl==0 ){ + pFile->nJrnl = 0; + return; + } + pFile->nJrnl = n; + n = kvvfsDecode(zTxt+i, pFile->aJrnl, pFile->nJrnl); + if( nnJrnl ){ + sqlite3_free(pFile->aJrnl); + pFile->aJrnl = 0; + pFile->nJrnl = 0; + } +} + /* ** Read from the -journal file. */ @@ -384,7 +434,36 @@ static int kvvfsReadFromDb( int iAmt, sqlite_int64 iOfst ){ - return SQLITE_IOERR; + unsigned int pgno; + KVVfsPage *pPage; + int got; + char zKey[30]; + char aData[131073]; + assert( pFile->szDb>=0 ); + assert( iOfst>=0 ); + assert( iAmt>=0 ); + if( (iOfst % iAmt)!=0 ){ + return SQLITE_IOERR_READ; + } + if( iAmt!=100 || iOfst!=0 ){ + if( (iAmt & (iAmt-1))!=0 || iAmt<512 || iAmt>65536 ){ + return SQLITE_IOERR_READ; + } + pFile->szPage = iAmt; + } + pgno = 1 + iOfst/iAmt; + sqlite3_snprintf(sizeof(zKey), zKey, "pg-%u", pgno) + got = kvstorageRead(pFile->pVfs->pStore, zKey, aData, sizeof(aData)-1); + if( got<0 ){ + return SQLITE_IOERR_READ; + } + aData[got] = 0; + n = kvvfsDecode(aData, zBuf, iAmt); + if( npVfs->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. */ @@ -416,11 +510,25 @@ static int kvvfsWriteToJournal( int iAmt, sqlite_int64 iOfst ){ - return SQLITE_IOERR; + sqlite3_int64 iEnd = iOfst+iAmt; + if( iEnd>=0x10000000 ) return SQLITE_FULL; + if( pFile->aJrnl==0 || pFile->nJrnlaJrnl, iEnd); + if( aNew==0 ){ + return SQLITE_IOERR_NOMEM; + } + pFile->aJrnl = aNew; + if( pFile->nJrnlaJrnl+pFile->nJrnl, 0, iOfst-pFile->nJrnl); + } + pFile->nJrnl = iEnd; + } + memcpy(pFile->aJrnl+iOfst, zBuf, iAmt); + return SQLITE_OK; } /* -** Read from the database file. +** Write into the database file. */ static int kvvfsWriteToDb( KVVfsFile *pFile, @@ -428,7 +536,19 @@ static int kvvfsWriteToDb( int iAmt, sqlite_int64 iOfst ){ - return SQLITE_IOERR; + unsigned int pgno; + char zKey[30]; + char aData[131073]; + assert( iAmt>=512 && iAmt<=65536 ); + assert( (iAmt & (iAmt-1))==0 ); + pgno = 1 + iOfst/iAmt; + sqlite3_snprintf(sizeof(zKey), zKey, "pg-%u", pgno) + nData = kvvfsEncode(zBuf, iAmt, aData); + kvstorageWrite(pFile->pVfs->pStore, zKey, aData); + if( iOfst+iAmt > pFile->szDb ){ + pFile->szDb = iOfst + iAmt; + } + return SQLITE_OK; } @@ -454,20 +574,65 @@ static int kvvfsWrite( /* ** Truncate an kvvfs-file. */ -static int kvvfsTruncate(sqlite3_file *pFile, sqlite_int64 size){ - int rc; +static int kvvfsTruncate(sqlite3_file *pProtoFile, sqlite_int64 size){ KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - rc = SQLITE_IOERR; - return rc; + if( pFile->isJournal ){ + assert( size==0 ); + kvstorageDelete(pFile->pVfs->pStore, "journal"); + sqlite3_free(pFile->aData); + pFile->aData = 0; + pFile->nData = 0; + return SQLITE_OK; + } + if( pFile->szDb>size + && pFile->szPage>0 + && (size % pFile->szPage)==0 + ){ + char zKey[50]; + unsigned int pgno, pgnoMax; + pgno = 1 + size/pFile->szPage; + pgnoMax = 2 + pFile->szDb/pFile->szPage; + while( pgno<=pgnoMax ){ + sqlite3_snprintf(sizeof(zKey), zKey, "pg-%u", pgno); + kvstorageDelete(pFile->pVfs->pStore, zKey); + pgno++; + } + pFile->szDb = size; + kvvfsWriteFileSize(pFile->pVfs->pStore, size); + return SQLITE_OK; + } + return SQLITE_IOERR; } /* ** Sync an kvvfs-file. */ -static int kvvfsSync(sqlite3_file *pFile, int flags){ - int rc; +static int kvvfsSync(sqlite3_file *pProtoFile, int flags){ + int i, k, n; KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - rc = SQLITE_IOERR; + char *zOut; + if( !pFile->isJournal ){ + if( pFile->szDb>0 ){ + kvvfsWriteFileSize(pFile, pFile->szDb); + } + return SQLITE_OK; + } + if( pFile->nJrnl<=0 ){ + return kvvfsTruncate(pProtoFile, 0); + } + zOut = sqlite3_malloc64( pFile->nJrnl*2 + 50 ); + if( zOut==0 ){ + return SQLITE_IOERR_NOMEM; + } + n = pFile->nJrnl; + i = 0; + do{ + zOut[i++] = 'a' + (n%26); + n /= 26; + }while( n>0 ); + kvvfsEncode(pFile->aJrnl, pFile->nJrnl, &zOut[i]); + kvstorageWrite(pFile->pVfs->pStore, "journal", zOut); + sqlite3_free(zOut); return rc; } @@ -475,31 +640,37 @@ static int kvvfsSync(sqlite3_file *pFile, int flags){ ** Return the current file-size of an kvvfs-file. */ static int kvvfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ - int rc; KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - *pSize = 0; - rc = SQLITE_IOERR; - return rc; + if( pFile->isJournal ){ + *pSize = pFile->nJrnl; + }else{ + *pSize = pFile->szDb; + } + return SQLITE_OK; } /* ** Lock an kvvfs-file. */ static int kvvfsLock(sqlite3_file *pFile, int eLock){ - int rc; KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - rc = SQLITE_IOERR; - return rc; + assert( !pFile->isJournal ); + if( eLock!=SQLITE_LOCK_NONE ){ + pFile->szDb = kvvfsReadFileSize(pFile); + } + return SQLITE_OK; } /* ** Unlock an kvvfs-file. */ static int kvvfsUnlock(sqlite3_file *pFile, int eLock){ - int rc; KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - rc = SQLITE_IOERR; - return rc; + assert( !pFile->isJournal ); + if( eLock==SQLITE_LOCK_NONE ){ + pFile->szDb = -1; + } + return SQLITE_OK; } /* @@ -509,7 +680,7 @@ static int kvvfsCheckReservedLock(sqlite3_file *pFile, int *pResOut){ int rc; KVVfsFile *pFile = (KVVfsFile *)pProtoFile; *pResOut = 0; - rc = SQLITE_IOERR; + rc = SQLITE_OK; return rc; } @@ -527,7 +698,7 @@ static int kvvfsFileControl(sqlite3_file *pFile, int op, void *pArg){ ** Return the sector-size in bytes for an kvvfs-file. */ static int kvvfsSectorSize(sqlite3_file *pFile){ - return 4096; + return 512; } /* @@ -548,12 +719,15 @@ static int kvvfsOpen( int flags, int *pOutFlags ){ - int rc; KVVfsFile *pFile = (KVVfsFile*)pProtoFile; KVVfsVfs *pVfs = (KVVfsVfs*)pProtoVfs; - + pFile->aJrnl = 0; + pFile->nJrnl = 0; + pFile->isJournal = sqlite3_strglob("*-journal", zName)==0; + pFile->szPage = -1; + pFile->szDb = -1; - return rc; + return SQLITE_OK; } /* @@ -574,12 +748,17 @@ static int kvvfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ ** is available, or false otherwise. */ static int kvvfsAccess( - sqlite3_vfs *pVfs, + sqlite3_vfs *pProtoVfs, const char *zPath, int flags, int *pResOut ){ - *pResOut = 1; + KVVfsVfs *pVfs = (KVVfsVfs*)pProtoVfs; + if( sqlite3_strglob("*-journal", zPath)==0 ){ + *pResOut = kvstorageRead(pVfs->pStore, "journal", 0, 0)>0; + }else{ + *pResOut = 1; + } return SQLITE_OK; } diff --git a/manifest b/manifest index dfddb1fb37..f872ac3349 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Non-working\scode\stowards\sa\sVFS\sfor\stext\skey/value\sstorage. -D 2022-09-07T17:29:22.881 +C Code\ssnapshot.\s\sCompletely\suntested.\s\sProbably\sdoes\snot\scompile. +D 2022-09-08T15:48:01.413 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -335,7 +335,7 @@ F ext/misc/uint.c 053fed3bce2e89583afcd4bf804d75d659879bbcedac74d0fa9ed548839a03 F ext/misc/unionvtab.c 36237f0607ca954ac13a4a0e2d2ac40c33bc6e032a5f55f431713061ef1625f9 F ext/misc/urifuncs.c f71360d14fa9e7626b563f1f781c6148109462741c5235ac63ae0f8917b9c751 F ext/misc/uuid.c 5bb2264c1b64d163efa46509544fd7500cb8769cb7c16dd52052da8d961505cf -F ext/misc/vfskv.c aebaf8b59b70a066c2c0ba9344db0494ff50452ff6b4e79c9133e7a2ea112a99 +F ext/misc/vfskv.c cb82423dcc37af07953d71f15518e8a75d81b2dbab45dc237e181c5b03373703 F ext/misc/vfslog.c 3932ab932eeb2601dbc4447cb14d445aaa9fbe43b863ef5f014401c3420afd20 F ext/misc/vfsstat.c 474d08efc697b8eba300082cb1eb74a5f0f3df31ed257db1cb07e72ab0e53dfb F ext/misc/vtablog.c 5538acd0c8ddaae372331bee11608d76973436b77d6a91e8635cfc9432fba5ae @@ -2001,11 +2001,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 6b00ecb59fd303f7985902c35a46db9e729201d4beaedea46596b728d9e4b1c8 -R 26f26a2d9ce78c288f974e48234fd3a7 -T *branch * kv-vfs -T *sym-kv-vfs * -T -sym-trunk * +P f9c89ee8d5ef46342bea78fa8d4da058d9ea628183ec985642bbda1cdfeacd5f +R fed5a09fb1667ca82dde0796f5fd6c9d U drh -Z 68d678ebfc334c4be8e66c0fb69610ed +Z ee96129288f9f67591a72cc787991652 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index d9d59da7ca..8e900ee9c5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f9c89ee8d5ef46342bea78fa8d4da058d9ea628183ec985642bbda1cdfeacd5f \ No newline at end of file +51e267696d25f2f83b5bb847d5254ab15573ef1a16ea3d7dd8279c73c0bee539 \ No newline at end of file From e3485ee9966a1d888cda478f92b098d13ab138dd Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 8 Sep 2022 16:27:50 +0000 Subject: [PATCH 03/13] Compiles without error, but untested. FossilOrigin-Name: a329939c32e33d8d00066ba3d4327f07cca1b4e67de0b8d85f1e7f98afe40954 --- ext/misc/vfskv.c | 130 ++++++++++++++++++++++++++++------------------- manifest | 12 ++--- manifest.uuid | 2 +- 3 files changed, 86 insertions(+), 58 deletions(-) diff --git a/ext/misc/vfskv.c b/ext/misc/vfskv.c index 0773f70945..5d71816a82 100644 --- a/ext/misc/vfskv.c +++ b/ext/misc/vfskv.c @@ -14,14 +14,25 @@ ** Key/Value storage engine where both keys and values must be pure ** text. */ -#include "sqlite3.h" +#include +SQLITE_EXTENSION_INIT1 #include #include #include -#include +#include #include #include #include +#include + +/***************************************************************************** +** Debugging logic +*/ +#if 1 +#define KVVFS_TRACE(X) printf X; +#else +#define KVVFS_TRACE(X) +#endif /***************************************************************************** @@ -37,7 +48,6 @@ static KVStorage *kvstorageOpen(void); static void kvstorageClose(KVStorage*); static int kvstorageWrite(KVStorage*, const char *zKey, const char *zData); static int kvstorageDelete(KVStorage*, const char *zKey); -static int kvstorageSize(KVStorage*, const char *zKey); static int kvstorageRead(KVStorage*, const char *zKey, char *zBuf, int nBuf); @@ -93,13 +103,9 @@ static int kvvfsDelete(sqlite3_vfs*, const char *zName, int syncDir); static int kvvfsAccess(sqlite3_vfs*, const char *zName, int flags, int *); static int kvvfsFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut); static void *kvvfsDlOpen(sqlite3_vfs*, const char *zFilename); -static void kvvfsDlError(sqlite3_vfs*, int nByte, char *zErrMsg); -static void (*kvvfsDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void); -static void kvvfsDlClose(sqlite3_vfs*, void*); static int kvvfsRandomness(sqlite3_vfs*, int nByte, char *zOut); static int kvvfsSleep(sqlite3_vfs*, int microseconds); static int kvvfsCurrentTime(sqlite3_vfs*, double*); -static int kvvfsGetLastError(sqlite3_vfs*, int, char *); static int kvvfsCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*); static KVVfsVfs kvvfs_vfs = { @@ -122,7 +128,7 @@ static KVVfsVfs kvvfs_vfs = { kvvfsSleep, /* xSleep */ kvvfsCurrentTime, /* xCurrentTime */ 0, /* xGetLastError */ - kvvfsCurrentTimeInt64, /* xCurrentTimeInt64 */ + kvvfsCurrentTimeInt64 /* xCurrentTimeInt64 */ }, 0, 0 @@ -141,7 +147,7 @@ static sqlite3_io_methods kvvfs_io_methods = { kvvfsCheckReservedLock, /* xCheckReservedLock */ kvvfsFileControl, /* xFileControl */ kvvfsSectorSize, /* xSectorSize */ - kvvfsDeviceCharacteristics /* xDeviceCharacteristics */ + kvvfsDeviceCharacteristics, /* xDeviceCharacteristics */ 0, /* xShmMap */ 0, /* xShmLock */ 0, /* xShmBarrier */ @@ -188,12 +194,15 @@ static int kvstorageWrite( FILE *fd; kvstorageMakeKey(pStore, zKey); fd = fopen(pStore->zKey, "wb"); - if( fd==0 ) return 1; if( fd ){ + KVVFS_TRACE(("KVVFS-WRITE %-12s (%d) %.30s\n", pStore->zKey, + (int)strlen(zData), zData)); fputs(zData, fd); fclose(fd); + return 0; + }else{ + return 1; } - return 0; } /* Delete a key @@ -201,6 +210,7 @@ static int kvstorageWrite( static int kvstorageDelete(KVStorage *pStore, const char *zKey){ kvstorageMakeKey(pStore, zKey); unlink(pStore->zKey); + KVVFS_TRACE(("KVVFS-DELETE %-12s\n", pStore->zKey)); return 0; } @@ -229,22 +239,31 @@ static int kvstorageRead( || stat(pStore->zKey, &buf)!=0 || !S_ISREG(buf.st_mode) ){ + KVVFS_TRACE(("KVVFS-READ %-12s (-1)\n", pStore->zKey)); return -1; } if( nBuf<0 ){ return (int)buf.st_size; }else if( nBuf==1 ){ zBuf[0] = 0; + KVVFS_TRACE(("KVVFS-READ %-12s (%d)\n", pStore->zKey, + (int)buf.st_size)); return (int)buf.st_size; } if( nBuf-1 > buf.st_size ){ nBuf = buf.st_size + 1; } fd = fopen(pStore->zKey, "rb"); - if( fd==0 ) return -1; - fread(zBuf, nBuf-1, 1, fd); - fclose(fd); - return nBuf-1; + if( fd==0 ){ + KVVFS_TRACE(("KVVFS-READ %-12s (-1)\n", pStore->zKey)); + return -1; + }else{ + fread(zBuf, nBuf-1, 1, fd); + fclose(fd); + KVVFS_TRACE(("KVVFS-READ %-12s (%d) %.30s\n", pStore->zKey, + nBuf-1, zBuf)); + return nBuf-1; + } } @@ -274,7 +293,7 @@ static int kvvfsClose(sqlite3_file *pProtoFile){ pX = pX->pNext; } } - sqlite3_free(pFile->aData); + sqlite3_free(pFile->aJrnl); sqlite3_free(pFile); return SQLITE_OK; } @@ -289,7 +308,7 @@ static int kvvfsClose(sqlite3_file *pProtoFile){ */ static int kvvfsEncode(const char *aData, int nData, char *aOut){ int i, j; - const unsigned *a = (const unsigned char*)aData; + const unsigned char *a = (const unsigned char*)aData; for(i=j=0; ipVfs->pStore, "journal", aTxt, szTxt+1); kvvfsDecodeJournal(pFile, aTxt, szTxt); sqlite3_free(aTxt); - if( pFile->aData==0 ) return SQLITE_IOERR; + if( pFile->aJrnl==0 ) return SQLITE_IOERR; } if( iOfst+iAmt>pFile->nJrnl ){ return SQLITE_IOERR_SHORT_READ; } - mcmcpy(zBuf, pFile->aJrnl+iOfst, iAmt); + memcpy(zBuf, pFile->aJrnl+iOfst, iAmt); return SQLITE_OK; } @@ -435,8 +453,7 @@ static int kvvfsReadFromDb( sqlite_int64 iOfst ){ unsigned int pgno; - KVVfsPage *pPage; - int got; + int got, n; char zKey[30]; char aData[131073]; assert( pFile->szDb>=0 ); @@ -452,7 +469,7 @@ static int kvvfsReadFromDb( pFile->szPage = iAmt; } pgno = 1 + iOfst/iAmt; - sqlite3_snprintf(sizeof(zKey), zKey, "pg-%u", pgno) + sqlite3_snprintf(sizeof(zKey), zKey, "pg-%u", pgno); got = kvstorageRead(pFile->pVfs->pStore, zKey, aData, sizeof(aData)-1); if( got<0 ){ return SQLITE_IOERR_READ; @@ -542,8 +559,8 @@ static int kvvfsWriteToDb( assert( iAmt>=512 && iAmt<=65536 ); assert( (iAmt & (iAmt-1))==0 ); pgno = 1 + iOfst/iAmt; - sqlite3_snprintf(sizeof(zKey), zKey, "pg-%u", pgno) - nData = kvvfsEncode(zBuf, iAmt, aData); + sqlite3_snprintf(sizeof(zKey), zKey, "pg-%u", pgno); + kvvfsEncode(zBuf, iAmt, aData); kvstorageWrite(pFile->pVfs->pStore, zKey, aData); if( iOfst+iAmt > pFile->szDb ){ pFile->szDb = iOfst + iAmt; @@ -579,9 +596,9 @@ static int kvvfsTruncate(sqlite3_file *pProtoFile, sqlite_int64 size){ if( pFile->isJournal ){ assert( size==0 ); kvstorageDelete(pFile->pVfs->pStore, "journal"); - sqlite3_free(pFile->aData); - pFile->aData = 0; - pFile->nData = 0; + sqlite3_free(pFile->aJrnl); + pFile->aJrnl = 0; + pFile->nJrnl = 0; return SQLITE_OK; } if( pFile->szDb>size @@ -598,7 +615,7 @@ static int kvvfsTruncate(sqlite3_file *pProtoFile, sqlite_int64 size){ pgno++; } pFile->szDb = size; - kvvfsWriteFileSize(pFile->pVfs->pStore, size); + kvvfsWriteFileSize(pFile, size); return SQLITE_OK; } return SQLITE_IOERR; @@ -608,7 +625,7 @@ static int kvvfsTruncate(sqlite3_file *pProtoFile, sqlite_int64 size){ ** Sync an kvvfs-file. */ static int kvvfsSync(sqlite3_file *pProtoFile, int flags){ - int i, k, n; + int i, n; KVVfsFile *pFile = (KVVfsFile *)pProtoFile; char *zOut; if( !pFile->isJournal ){ @@ -633,13 +650,13 @@ static int kvvfsSync(sqlite3_file *pProtoFile, int flags){ kvvfsEncode(pFile->aJrnl, pFile->nJrnl, &zOut[i]); kvstorageWrite(pFile->pVfs->pStore, "journal", zOut); sqlite3_free(zOut); - return rc; + return SQLITE_OK; } /* ** Return the current file-size of an kvvfs-file. */ -static int kvvfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ +static int kvvfsFileSize(sqlite3_file *pProtoFile, sqlite_int64 *pSize){ KVVfsFile *pFile = (KVVfsFile *)pProtoFile; if( pFile->isJournal ){ *pSize = pFile->nJrnl; @@ -652,7 +669,7 @@ static int kvvfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ /* ** Lock an kvvfs-file. */ -static int kvvfsLock(sqlite3_file *pFile, int eLock){ +static int kvvfsLock(sqlite3_file *pProtoFile, int eLock){ KVVfsFile *pFile = (KVVfsFile *)pProtoFile; assert( !pFile->isJournal ); if( eLock!=SQLITE_LOCK_NONE ){ @@ -664,7 +681,7 @@ static int kvvfsLock(sqlite3_file *pFile, int eLock){ /* ** Unlock an kvvfs-file. */ -static int kvvfsUnlock(sqlite3_file *pFile, int eLock){ +static int kvvfsUnlock(sqlite3_file *pProtoFile, int eLock){ KVVfsFile *pFile = (KVVfsFile *)pProtoFile; assert( !pFile->isJournal ); if( eLock==SQLITE_LOCK_NONE ){ @@ -676,22 +693,16 @@ static int kvvfsUnlock(sqlite3_file *pFile, int eLock){ /* ** Check if another file-handle holds a RESERVED lock on an kvvfs-file. */ -static int kvvfsCheckReservedLock(sqlite3_file *pFile, int *pResOut){ - int rc; - KVVfsFile *pFile = (KVVfsFile *)pProtoFile; +static int kvvfsCheckReservedLock(sqlite3_file *pProtoFile, int *pResOut){ *pResOut = 0; - rc = SQLITE_OK; - return rc; + return SQLITE_OK; } /* ** File control method. For custom operations on an kvvfs-file. */ -static int kvvfsFileControl(sqlite3_file *pFile, int op, void *pArg){ - int rc; - KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - rc = SQLITE_NOTFOUND; - return rc; +static int kvvfsFileControl(sqlite3_file *pProtoFile, int op, void *pArg){ + return SQLITE_NOTFOUND; } /* @@ -704,7 +715,7 @@ static int kvvfsSectorSize(sqlite3_file *pFile){ /* ** Return the device characteristic flags supported by an kvvfs-file. */ -static int kvvfsDeviceCharacteristics(sqlite3_file *pFile){ +static int kvvfsDeviceCharacteristics(sqlite3_file *pProtoFile){ return 0; } @@ -726,7 +737,13 @@ static int kvvfsOpen( pFile->isJournal = sqlite3_strglob("*-journal", zName)==0; pFile->szPage = -1; pFile->szDb = -1; - + pFile->base.pMethods = &kvvfs_io_methods; + pFile->pVfs = pVfs; + if( pVfs->pFiles==0 ){ + pVfs->pStore = kvstorageOpen(); + } + pFile->pNext = pVfs->pFiles; + pVfs->pFiles = pFile; return SQLITE_OK; } @@ -776,7 +793,7 @@ static int kvvfsFullPathname( size_t nPath = strlen(zPath); if( nOut Date: Thu, 8 Sep 2022 17:12:12 +0000 Subject: [PATCH 04/13] Compiles and loads as an extension. Starts to run but quickly hits issues. FossilOrigin-Name: 2e38726f46918b28b5c638967f960a20afd3fe84ad245f3bea39a1d64980435b --- ext/misc/vfskv.c | 23 ++++++++++++----------- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/ext/misc/vfskv.c b/ext/misc/vfskv.c index 5d71816a82..bde2f08336 100644 --- a/ext/misc/vfskv.c +++ b/ext/misc/vfskv.c @@ -195,7 +195,7 @@ static int kvstorageWrite( kvstorageMakeKey(pStore, zKey); fd = fopen(pStore->zKey, "wb"); if( fd ){ - KVVFS_TRACE(("KVVFS-WRITE %-12s (%d) %.30s\n", pStore->zKey, + KVVFS_TRACE(("KVVFS-WRITE %-14s (%d) %.30s\n", pStore->zKey, (int)strlen(zData), zData)); fputs(zData, fd); fclose(fd); @@ -210,7 +210,7 @@ static int kvstorageWrite( static int kvstorageDelete(KVStorage *pStore, const char *zKey){ kvstorageMakeKey(pStore, zKey); unlink(pStore->zKey); - KVVFS_TRACE(("KVVFS-DELETE %-12s\n", pStore->zKey)); + KVVFS_TRACE(("KVVFS-DELETE %-14s\n", pStore->zKey)); return 0; } @@ -239,14 +239,14 @@ static int kvstorageRead( || stat(pStore->zKey, &buf)!=0 || !S_ISREG(buf.st_mode) ){ - KVVFS_TRACE(("KVVFS-READ %-12s (-1)\n", pStore->zKey)); + KVVFS_TRACE(("KVVFS-READ %-14s (-1)\n", pStore->zKey)); return -1; } if( nBuf<0 ){ return (int)buf.st_size; }else if( nBuf==1 ){ zBuf[0] = 0; - KVVFS_TRACE(("KVVFS-READ %-12s (%d)\n", pStore->zKey, + KVVFS_TRACE(("KVVFS-READ %-14s (%d)\n", pStore->zKey, (int)buf.st_size)); return (int)buf.st_size; } @@ -255,12 +255,12 @@ static int kvstorageRead( } fd = fopen(pStore->zKey, "rb"); if( fd==0 ){ - KVVFS_TRACE(("KVVFS-READ %-12s (-1)\n", pStore->zKey)); + KVVFS_TRACE(("KVVFS-READ %-14s (-1)\n", pStore->zKey)); return -1; }else{ fread(zBuf, nBuf-1, 1, fd); fclose(fd); - KVVFS_TRACE(("KVVFS-READ %-12s (%d) %.30s\n", pStore->zKey, + KVVFS_TRACE(("KVVFS-READ %-14s (%d) %.30s\n", pStore->zKey, nBuf-1, zBuf)); return nBuf-1; } @@ -456,7 +456,6 @@ static int kvvfsReadFromDb( int got, n; char zKey[30]; char aData[131073]; - assert( pFile->szDb>=0 ); assert( iOfst>=0 ); assert( iAmt>=0 ); if( (iOfst % iAmt)!=0 ){ @@ -472,10 +471,11 @@ static int kvvfsReadFromDb( sqlite3_snprintf(sizeof(zKey), zKey, "pg-%u", pgno); got = kvstorageRead(pFile->pVfs->pStore, zKey, aData, sizeof(aData)-1); if( got<0 ){ - return SQLITE_IOERR_READ; + n = 0; + }else{ + aData[got] = 0; + n = kvvfsDecode(aData, zBuf, iAmt); } - aData[got] = 0; - n = kvvfsDecode(aData, zBuf, iAmt); if( n Date: Fri, 9 Sep 2022 11:41:54 +0000 Subject: [PATCH 05/13] Simple reading and writing now works. FossilOrigin-Name: 00845ac9ef2616e90f5f6a20da3dd040fa8bdcfe73f72fe9c06039561150a82d --- ext/misc/vfskv.c | 83 ++++++++++++++++++++++++++++++++++++------------ manifest | 12 +++---- manifest.uuid | 2 +- 3 files changed, 70 insertions(+), 27 deletions(-) diff --git a/ext/misc/vfskv.c b/ext/misc/vfskv.c index bde2f08336..9897cd8185 100644 --- a/ext/misc/vfskv.c +++ b/ext/misc/vfskv.c @@ -28,11 +28,16 @@ SQLITE_EXTENSION_INIT1 /***************************************************************************** ** Debugging logic */ -#if 1 +#if 0 #define KVVFS_TRACE(X) printf X; #else #define KVVFS_TRACE(X) #endif +#if 0 +#define KVVFS_LOG(X) printf X; +#else +#define KVVFS_LOG(X) +#endif /***************************************************************************** @@ -258,11 +263,12 @@ static int kvstorageRead( KVVFS_TRACE(("KVVFS-READ %-14s (-1)\n", pStore->zKey)); return -1; }else{ - fread(zBuf, nBuf-1, 1, fd); + sqlite3_int64 n = fread(zBuf, 1, nBuf-1, fd); fclose(fd); - KVVFS_TRACE(("KVVFS-READ %-14s (%d) %.30s\n", pStore->zKey, - nBuf-1, zBuf)); - return nBuf-1; + zBuf[n] = 0; + KVVFS_TRACE(("KVVFS-READ %-14s (%lld) %.30s\n", pStore->zKey, + n, zBuf)); + return (int)n; } } @@ -276,6 +282,7 @@ 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 ){ @@ -294,7 +301,6 @@ static int kvvfsClose(sqlite3_file *pProtoFile){ } } sqlite3_free(pFile->aJrnl); - sqlite3_free(pFile); return SQLITE_OK; } @@ -321,8 +327,8 @@ static int kvvfsEncode(const char *aData, int nData, char *aOut){ ** and so forth. */ int k; - for(k=1; a[i+k]==0 && i+k0 ){ aOut[j++] = 'a'+(k%26); k /= 26; @@ -336,7 +342,7 @@ static int kvvfsEncode(const char *aData, int nData, char *aOut){ /* Convert hex to binary */ static char kvvfsHexToBinary(char c){ if( c>='0' && c<='9' ) return c - '0'; - if( c>='a' && c<='f' ) return c - 'a' + 10; + if( c>='A' && c<='F' ) return c - 'A' + 10; return 0; } @@ -366,10 +372,8 @@ static int kvvfsDecode(const char *aIn, char *aOut, int nOut){ } }else{ if( j>nOut ) return -1; - aOut[j] = kvvfsHexToBinary(aIn[i])<<4; - i++; - aOut[j] += kvvfsHexToBinary(aIn[i]); - i++; + aOut[j] = kvvfsHexToBinary(aIn[i++])<<4; + aOut[j++] += kvvfsHexToBinary(aIn[i++]); } } return j; @@ -423,6 +427,7 @@ static int kvvfsReadFromJournal( sqlite_int64 iOfst ){ assert( pFile->isJournal ); + KVVFS_LOG(("xRead('journal',%d,%lld)\n", iAmt, iOfst)); if( pFile->aJrnl==0 ){ int szTxt = kvstorageRead(pFile->pVfs->pStore, "journal", 0, 0); char *aTxt; @@ -458,23 +463,36 @@ static int kvvfsReadFromDb( char aData[131073]; assert( iOfst>=0 ); assert( iAmt>=0 ); - if( (iOfst % iAmt)!=0 ){ - return SQLITE_IOERR_READ; - } - if( iAmt!=100 || iOfst!=0 ){ + KVVFS_LOG(("xRead('db',%d,%lld)\n", iAmt, iOfst)); + if( iOfst+iAmt>=512 ){ + if( (iOfst % iAmt)!=0 ){ + return SQLITE_IOERR_READ; + } if( (iAmt & (iAmt-1))!=0 || iAmt<512 || iAmt>65536 ){ return SQLITE_IOERR_READ; } pFile->szPage = iAmt; + pgno = 1 + iOfst/iAmt; + }else{ + pgno = 1; } - pgno = 1 + iOfst/iAmt; sqlite3_snprintf(sizeof(zKey), zKey, "pg-%u", pgno); got = kvstorageRead(pFile->pVfs->pStore, zKey, aData, sizeof(aData)-1); if( got<0 ){ n = 0; }else{ aData[got] = 0; - n = kvvfsDecode(aData, zBuf, iAmt); + if( iOfst+iAmt<512 ){ + n = kvvfsDecode(aData, &aData[1000], 1000); + if( n>=iOfst+iAmt ){ + memcpy(zBuf, &aData[1000+iOfst], iAmt); + n = iAmt; + }else{ + n = 0; + } + }else{ + n = kvvfsDecode(aData, zBuf, iAmt); + } } if( n=0x10000000 ) return SQLITE_FULL; if( pFile->aJrnl==0 || pFile->nJrnlaJrnl, iEnd); @@ -556,6 +576,7 @@ static int kvvfsWriteToDb( unsigned int pgno; char zKey[30]; char aData[131073]; + KVVFS_LOG(("xWrite('db',%d,%lld)\n", iAmt, iOfst)); assert( iAmt>=512 && iAmt<=65536 ); assert( (iAmt & (iAmt-1))==0 ); pgno = 1 + iOfst/iAmt; @@ -585,6 +606,7 @@ static int kvvfsWrite( }else{ rc = kvvfsWriteToDb(pFile,zBuf,iAmt,iOfst); } + KVVFS_LOG(("xWrite result: 0x%x\n", rc)); return rc; } @@ -594,6 +616,7 @@ static int kvvfsWrite( static int kvvfsTruncate(sqlite3_file *pProtoFile, sqlite_int64 size){ 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); @@ -607,6 +630,7 @@ static int kvvfsTruncate(sqlite3_file *pProtoFile, sqlite_int64 size){ ){ char zKey[50]; unsigned int pgno, pgnoMax; + KVVFS_LOG(("xTruncate('db',%lld)\n", size)); pgno = 1 + size/pFile->szPage; pgnoMax = 2 + pFile->szDb/pFile->szPage; while( pgno<=pgnoMax ){ @@ -629,11 +653,13 @@ static int kvvfsSync(sqlite3_file *pProtoFile, int flags){ KVVfsFile *pFile = (KVVfsFile *)pProtoFile; 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")); if( pFile->nJrnl<=0 ){ return kvvfsTruncate(pProtoFile, 0); } @@ -659,10 +685,17 @@ static int kvvfsSync(sqlite3_file *pProtoFile, int flags){ static int kvvfsFileSize(sqlite3_file *pProtoFile, sqlite_int64 *pSize){ KVVfsFile *pFile = (KVVfsFile *)pProtoFile; if( pFile->isJournal ){ + KVVFS_LOG(("xFileSize('journal')\n")); *pSize = pFile->nJrnl; }else{ - *pSize = pFile->szDb; + KVVFS_LOG(("xFileSize('db')\n")); + if( pFile->szDb>=0 ){ + *pSize = pFile->szDb; + }else{ + *pSize = kvvfsReadFileSize(pFile); + } } + KVVFS_LOG(("xFileSize: %lld\n", *pSize)); return SQLITE_OK; } @@ -672,6 +705,8 @@ static int kvvfsFileSize(sqlite3_file *pProtoFile, sqlite_int64 *pSize){ static int kvvfsLock(sqlite3_file *pProtoFile, int eLock){ KVVfsFile *pFile = (KVVfsFile *)pProtoFile; assert( !pFile->isJournal ); + KVVFS_LOG(("xLock(%d)\n", eLock)); + if( eLock!=SQLITE_LOCK_NONE ){ pFile->szDb = kvvfsReadFileSize(pFile); } @@ -684,6 +719,7 @@ static int kvvfsLock(sqlite3_file *pProtoFile, int eLock){ static int kvvfsUnlock(sqlite3_file *pProtoFile, int eLock){ KVVfsFile *pFile = (KVVfsFile *)pProtoFile; assert( !pFile->isJournal ); + KVVFS_LOG(("xUnlock(%d)\n", eLock)); if( eLock==SQLITE_LOCK_NONE ){ pFile->szDb = -1; } @@ -694,6 +730,7 @@ static int kvvfsUnlock(sqlite3_file *pProtoFile, int eLock){ ** Check if another file-handle holds a RESERVED lock on an kvvfs-file. */ static int kvvfsCheckReservedLock(sqlite3_file *pProtoFile, int *pResOut){ + KVVFS_LOG(("xCheckReservedLock\n")); *pResOut = 0; return SQLITE_OK; } @@ -732,6 +769,7 @@ static int kvvfsOpen( ){ KVVfsFile *pFile = (KVVfsFile*)pProtoFile; KVVfsVfs *pVfs = (KVVfsVfs*)pProtoVfs; + KVVFS_LOG(("xOpen(\"%s\")\n", zName)); pFile->aJrnl = 0; pFile->nJrnl = 0; pFile->isJournal = sqlite3_strglob("*-journal", zName)==0; @@ -771,11 +809,15 @@ static int kvvfsAccess( int *pResOut ){ KVVfsVfs *pVfs = (KVVfsVfs*)pProtoVfs; + KVVFS_LOG(("xAccess(\"%s\")\n", zPath)); if( sqlite3_strglob("*-journal", zPath)==0 ){ *pResOut = kvstorageRead(pVfs->pStore, "journal", 0, 0)>0; + }else if( sqlite3_strglob("*-wal", zPath)==0 ){ + *pResOut = 0; }else{ *pResOut = 1; } + KVVFS_LOG(("xAccess returns %d\n",*pResOut)); return SQLITE_OK; } @@ -791,6 +833,7 @@ static int kvvfsFullPathname( char *zOut ){ size_t nPath = strlen(zPath); + KVVFS_LOG(("xFullPathname(\"%s\")\n", zPath)); if( nOut Date: Fri, 9 Sep 2022 14:22:41 +0000 Subject: [PATCH 06/13] Separate sqlite3_io_methods objects for database files and journals. FossilOrigin-Name: 74fbf6c2a97729e481d5562344e960d0c237aeb1f07240262d32a24fb1f4b5a3 --- ext/misc/vfskv.c | 338 +++++++++++++++++++++++++---------------------- manifest | 12 +- manifest.uuid | 2 +- 3 files changed, 188 insertions(+), 164 deletions(-) diff --git a/ext/misc/vfskv.c b/ext/misc/vfskv.c index 9897cd8185..05259eaa43 100644 --- a/ext/misc/vfskv.c +++ b/ext/misc/vfskv.c @@ -28,11 +28,15 @@ SQLITE_EXTENSION_INIT1 /***************************************************************************** ** Debugging logic */ + +/* KVVFS_TRACE() is used for tracing calls to kvstorage routines. */ #if 0 #define KVVFS_TRACE(X) printf X; #else #define KVVFS_TRACE(X) #endif + +/* KVVFS_LOG() is used for tracing calls to the VFS interface */ #if 0 #define KVVFS_LOG(X) printf X; #else @@ -88,11 +92,16 @@ struct KVVfsFile { ** Methods for KVVfsFile */ static int kvvfsClose(sqlite3_file*); -static int kvvfsRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); -static int kvvfsWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst); -static int kvvfsTruncate(sqlite3_file*, sqlite3_int64 size); -static int kvvfsSync(sqlite3_file*, int flags); -static int kvvfsFileSize(sqlite3_file*, sqlite3_int64 *pSize); +static int kvvfsReadDb(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); +static int kvvfsReadJrnl(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); +static int kvvfsWriteDb(sqlite3_file*,const void*,int iAmt, sqlite3_int64); +static int kvvfsWriteJrnl(sqlite3_file*,const void*,int iAmt, sqlite3_int64); +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 kvvfsUnlock(sqlite3_file*, int); static int kvvfsCheckReservedLock(sqlite3_file*, int *pResOut); @@ -139,14 +148,40 @@ static KVVfsVfs kvvfs_vfs = { 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 */ kvvfsClose, /* xClose */ - kvvfsRead, /* xRead */ - kvvfsWrite, /* xWrite */ - kvvfsTruncate, /* xTruncate */ - kvvfsSync, /* xSync */ - kvvfsFileSize, /* xFileSize */ + kvvfsReadDb, /* xRead */ + kvvfsWriteDb, /* xWrite */ + kvvfsTruncateDb, /* xTruncate */ + kvvfsSyncDb, /* xSync */ + 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 */ kvvfsUnlock, /* xUnlock */ kvvfsCheckReservedLock, /* xCheckReservedLock */ @@ -200,8 +235,9 @@ static int kvstorageWrite( kvstorageMakeKey(pStore, zKey); fd = fopen(pStore->zKey, "wb"); if( fd ){ - KVVFS_TRACE(("KVVFS-WRITE %-14s (%d) %.30s\n", pStore->zKey, - (int)strlen(zData), zData)); + KVVFS_TRACE(("KVVFS-WRITE %-10s (%d) %.50s%s\n", pStore->zKey, + (int)strlen(zData), zData, + strlen(zData)>50 ? "..." : "")); fputs(zData, fd); fclose(fd); return 0; @@ -215,7 +251,7 @@ static int kvstorageWrite( static int kvstorageDelete(KVStorage *pStore, const char *zKey){ kvstorageMakeKey(pStore, zKey); unlink(pStore->zKey); - KVVFS_TRACE(("KVVFS-DELETE %-14s\n", pStore->zKey)); + KVVFS_TRACE(("KVVFS-DELETE %-10s\n", pStore->zKey)); return 0; } @@ -244,14 +280,14 @@ static int kvstorageRead( || stat(pStore->zKey, &buf)!=0 || !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; } if( nBuf<0 ){ return (int)buf.st_size; }else if( nBuf==1 ){ 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)); return (int)buf.st_size; } @@ -260,49 +296,20 @@ static int kvstorageRead( } fd = fopen(pStore->zKey, "rb"); if( fd==0 ){ - KVVFS_TRACE(("KVVFS-READ %-14s (-1)\n", pStore->zKey)); + KVVFS_TRACE(("KVVFS-READ %-10s (-1)\n", pStore->zKey)); return -1; }else{ sqlite3_int64 n = fread(zBuf, 1, nBuf-1, fd); fclose(fd); zBuf[n] = 0; - KVVFS_TRACE(("KVVFS-READ %-14s (%lld) %.30s\n", pStore->zKey, - n, zBuf)); + KVVFS_TRACE(("KVVFS-READ %-10s (%lld) %.50s%s\n", pStore->zKey, + n, zBuf, n>50 ? "..." : "")); 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. @@ -311,6 +318,20 @@ static int kvvfsClose(sqlite3_file *pProtoFile){ ** ** Return the actual length of the encoded text, not counting the ** 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){ 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 ** 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 -** 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( KVVfsFile *pFile, /* Store decoding in pFile->aJrnl */ @@ -397,10 +420,9 @@ static void kvvfsDecodeJournal( int c, i, mult; i = 0; mult = 1; - while( (c = zTxt[i])>='a' && c<='z' ){ + while( (c = zTxt[i++])>='a' && c<='z' ){ n += (zTxt[i] - 'a')*mult; mult *= 26; - i++; } sqlite3_free(pFile->aJrnl); 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. */ -static int kvvfsReadFromJournal( - KVVfsFile *pFile, +static int kvvfsReadJrnl( + sqlite3_file *pProtoFile, void *zBuf, int iAmt, sqlite_int64 iOfst ){ + KVVfsFile *pFile = (KVVfsFile*)pProtoFile; assert( pFile->isJournal ); KVVFS_LOG(("xRead('journal',%d,%lld)\n", iAmt, iOfst)); if( pFile->aJrnl==0 ){ - int szTxt = kvstorageRead(pFile->pVfs->pStore, "journal", 0, 0); + int szTxt = kvstorageRead(pFile->pVfs->pStore, "jrnl", 0, 0); char *aTxt; if( szTxt<=4 ){ return SQLITE_IOERR; } aTxt = sqlite3_malloc64( szTxt+1 ); 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); sqlite3_free(aTxt); if( pFile->aJrnl==0 ) return SQLITE_IOERR; @@ -451,12 +520,13 @@ static int kvvfsReadFromJournal( /* ** Read from the database file. */ -static int kvvfsReadFromDb( - KVVfsFile *pFile, +static int kvvfsReadDb( + sqlite3_file *pProtoFile, void *zBuf, int iAmt, sqlite_int64 iOfst ){ + KVVfsFile *pFile = (KVVfsFile*)pProtoFile; unsigned int pgno; int got, n; char zKey[30]; @@ -476,7 +546,7 @@ static int kvvfsReadFromDb( }else{ 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); if( got<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. */ -static int kvvfsWriteToJournal( - KVVfsFile *pFile, +static int kvvfsWriteJrnl( + sqlite3_file *pProtoFile, const void *zBuf, int iAmt, sqlite_int64 iOfst ){ + KVVfsFile *pFile = (KVVfsFile*)pProtoFile; sqlite3_int64 iEnd = iOfst+iAmt; KVVFS_LOG(("xWrite('journal',%d,%lld)\n", iAmt, iOfst)); if( iEnd>=0x10000000 ) return SQLITE_FULL; @@ -567,12 +603,13 @@ static int kvvfsWriteToJournal( /* ** Write into the database file. */ -static int kvvfsWriteToDb( - KVVfsFile *pFile, +static int kvvfsWriteDb( + sqlite3_file *pProtoFile, const void *zBuf, int iAmt, sqlite_int64 iOfst ){ + KVVfsFile *pFile = (KVVfsFile*)pProtoFile; unsigned int pgno; char zKey[30]; char aData[131073]; @@ -580,7 +617,7 @@ static int kvvfsWriteToDb( assert( iAmt>=512 && iAmt<=65536 ); assert( (iAmt & (iAmt-1))==0 ); pgno = 1 + iOfst/iAmt; - sqlite3_snprintf(sizeof(zKey), zKey, "pg-%u", pgno); + sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno); kvvfsEncode(zBuf, iAmt, aData); kvstorageWrite(pFile->pVfs->pStore, zKey, aData); if( iOfst+iAmt > pFile->szDb ){ @@ -589,41 +626,21 @@ static int kvvfsWriteToDb( 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. */ -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; - 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 && 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; pgnoMax = 2 + pFile->szDb/pFile->szPage; while( pgno<=pgnoMax ){ - sqlite3_snprintf(sizeof(zKey), zKey, "pg-%u", pgno); + sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno); kvstorageDelete(pFile->pVfs->pStore, zKey); pgno++; } @@ -648,20 +665,13 @@ static int kvvfsTruncate(sqlite3_file *pProtoFile, sqlite_int64 size){ /* ** Sync an kvvfs-file. */ -static int kvvfsSync(sqlite3_file *pProtoFile, int flags){ +static int kvvfsSyncJrnl(sqlite3_file *pProtoFile, int flags){ int i, n; KVVfsFile *pFile = (KVVfsFile *)pProtoFile; 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")); if( pFile->nJrnl<=0 ){ - return kvvfsTruncate(pProtoFile, 0); + return kvvfsTruncateJrnl(pProtoFile, 0); } zOut = sqlite3_malloc64( pFile->nJrnl*2 + 50 ); if( zOut==0 ){ @@ -673,29 +683,38 @@ static int kvvfsSync(sqlite3_file *pProtoFile, int flags){ zOut[i++] = 'a' + (n%26); n /= 26; }while( n>0 ); + zOut[i++] = ' '; kvvfsEncode(pFile->aJrnl, pFile->nJrnl, &zOut[i]); - kvstorageWrite(pFile->pVfs->pStore, "journal", zOut); + kvstorageWrite(pFile->pVfs->pStore, "jrnl", zOut); sqlite3_free(zOut); 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. */ -static int kvvfsFileSize(sqlite3_file *pProtoFile, sqlite_int64 *pSize){ +static int kvvfsFileSizeJrnl(sqlite3_file *pProtoFile, sqlite_int64 *pSize){ KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - if( pFile->isJournal ){ - KVVFS_LOG(("xFileSize('journal')\n")); - *pSize = pFile->nJrnl; + KVVFS_LOG(("xFileSize('journal')\n")); + *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{ - KVVFS_LOG(("xFileSize('db')\n")); - if( pFile->szDb>=0 ){ - *pSize = pFile->szDb; - }else{ - *pSize = kvvfsReadFileSize(pFile); - } + *pSize = kvvfsReadFileSize(pFile); } - KVVFS_LOG(("xFileSize: %lld\n", *pSize)); return SQLITE_OK; } @@ -772,10 +791,15 @@ static int kvvfsOpen( KVVFS_LOG(("xOpen(\"%s\")\n", zName)); pFile->aJrnl = 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->szDb = -1; - pFile->base.pMethods = &kvvfs_io_methods; pFile->pVfs = pVfs; if( pVfs->pFiles==0 ){ pVfs->pStore = kvstorageOpen(); @@ -793,7 +817,7 @@ static int kvvfsOpen( static int kvvfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ KVVfsVfs *p = (KVVfsVfs*)pVfs; if( sqlite3_strglob("*-journal",zPath)==0 ){ - kvstorageDelete(p->pStore, "journal"); + kvstorageDelete(p->pStore, "jrnl"); } return SQLITE_OK; } @@ -811,7 +835,7 @@ static int kvvfsAccess( KVVfsVfs *pVfs = (KVVfsVfs*)pProtoVfs; KVVFS_LOG(("xAccess(\"%s\")\n", zPath)); 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 ){ *pResOut = 0; }else{ diff --git a/manifest b/manifest index 0db4723321..0a3a992338 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Simple\sreading\sand\swriting\snow\sworks. -D 2022-09-09T11:41:54.677 +C Separate\ssqlite3_io_methods\sobjects\sfor\sdatabase\sfiles\sand\sjournals. +D 2022-09-09T14:22:41.989 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -335,7 +335,7 @@ F ext/misc/uint.c 053fed3bce2e89583afcd4bf804d75d659879bbcedac74d0fa9ed548839a03 F ext/misc/unionvtab.c 36237f0607ca954ac13a4a0e2d2ac40c33bc6e032a5f55f431713061ef1625f9 F ext/misc/urifuncs.c f71360d14fa9e7626b563f1f781c6148109462741c5235ac63ae0f8917b9c751 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/vfsstat.c 474d08efc697b8eba300082cb1eb74a5f0f3df31ed257db1cb07e72ab0e53dfb 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.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 2e38726f46918b28b5c638967f960a20afd3fe84ad245f3bea39a1d64980435b -R d99171917ec9b13f78c647c76b29147e +P 00845ac9ef2616e90f5f6a20da3dd040fa8bdcfe73f72fe9c06039561150a82d +R 460848ff6f3cd63ef5eccab59824c77b U drh -Z d5b6013a0fd62dab0ae32db15d37fb8f +Z 26961af5f4b759d7a43ac0a5cf8d117b # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 43d0014bd4..581c44b250 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -00845ac9ef2616e90f5f6a20da3dd040fa8bdcfe73f72fe9c06039561150a82d \ No newline at end of file +74fbf6c2a97729e481d5562344e960d0c237aeb1f07240262d32a24fb1f4b5a3 \ No newline at end of file From 25f62508f5f45686e282893b518196a41d8a60e4 Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 9 Sep 2022 16:16:33 +0000 Subject: [PATCH 07/13] Database must be named either "local" or "session". Each has a distinct namespace. FossilOrigin-Name: c8e41279294ea7c2f041c7d4cbbd85fce47d55f2f56180ca837316f7dfd75237 --- ext/misc/vfskv.c | 257 ++++++++++++++++++++--------------------------- manifest | 12 +-- manifest.uuid | 2 +- 3 files changed, 118 insertions(+), 153 deletions(-) diff --git a/ext/misc/vfskv.c b/ext/misc/vfskv.c index 05259eaa43..fee190f256 100644 --- a/ext/misc/vfskv.c +++ b/ext/misc/vfskv.c @@ -47,40 +47,23 @@ SQLITE_EXTENSION_INIT1 /***************************************************************************** ** The low-level storage engine */ -typedef struct KVStorage KVStorage; -struct KVStorage { - char *zDir; - char zKey[50]; -}; - -static KVStorage *kvstorageOpen(void); -static void kvstorageClose(KVStorage*); -static int kvstorageWrite(KVStorage*, const char *zKey, const char *zData); -static int kvstorageDelete(KVStorage*, const char *zKey); -static int kvstorageRead(KVStorage*, const char *zKey, char *zBuf, int nBuf); +#define KVSTORAGE_KEY_SZ 24 +static int kvstorageWrite(const char*, const char *zKey, const char *zData); +static int kvstorageDelete(const char*, const char *zKey); +static int kvstorageRead(const char*, const char *zKey, char *zBuf, int nBuf); /* -** Forward declaration of objects used by this utility +** Forward declaration of objects used by this VFS implementation */ -typedef struct KVVfsVfs KVVfsVfs; typedef struct KVVfsFile KVVfsFile; - -/* All information about the database */ -struct KVVfsVfs { - sqlite3_vfs base; /* VFS methods */ - KVStorage *pStore; /* Single command KV storage object */ - KVVfsFile *pFiles; /* List of open KVVfsFile objects */ -}; - /* A single open file. There are only two files represented by this ** VFS - the database and the rollback journal. */ struct KVVfsFile { sqlite3_file base; /* IO methods */ - KVVfsVfs *pVfs; /* The VFS to which this file belongs */ - KVVfsFile *pNext; /* Next in list of all files */ + const char *zClass; /* Storage class */ int isJournal; /* True if this is a journal file */ unsigned int nJrnl; /* Space allocated for aJrnl[] */ char *aJrnl; /* Journal content */ @@ -110,7 +93,7 @@ static int kvvfsSectorSize(sqlite3_file*); static int kvvfsDeviceCharacteristics(sqlite3_file*); /* -** Methods for KVVfsVfs +** Methods for sqlite3_vfs */ static int kvvfsOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *); static int kvvfsDelete(sqlite3_vfs*, const char *zName, int syncDir); @@ -122,30 +105,26 @@ static int kvvfsSleep(sqlite3_vfs*, int microseconds); static int kvvfsCurrentTime(sqlite3_vfs*, double*); static int kvvfsCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*); -static KVVfsVfs kvvfs_vfs = { - { - 1, /* iVersion */ - sizeof(KVVfsFile), /* szOsFile */ - 1024, /* mxPathname */ - 0, /* pNext */ - "kvvfs", /* zName */ - 0, /* pAppData */ - kvvfsOpen, /* xOpen */ - kvvfsDelete, /* xDelete */ - kvvfsAccess, /* xAccess */ - kvvfsFullPathname, /* xFullPathname */ - kvvfsDlOpen, /* xDlOpen */ - 0, /* xDlError */ - 0, /* xDlSym */ - 0, /* xDlClose */ - kvvfsRandomness, /* xRandomness */ - kvvfsSleep, /* xSleep */ - kvvfsCurrentTime, /* xCurrentTime */ - 0, /* xGetLastError */ - kvvfsCurrentTimeInt64 /* xCurrentTimeInt64 */ - }, - 0, - 0 +static sqlite3_vfs kvvfs_vfs = { + 1, /* iVersion */ + sizeof(KVVfsFile), /* szOsFile */ + 1024, /* mxPathname */ + 0, /* pNext */ + "kvvfs", /* zName */ + 0, /* pAppData */ + kvvfsOpen, /* xOpen */ + kvvfsDelete, /* xDelete */ + kvvfsAccess, /* xAccess */ + kvvfsFullPathname, /* xFullPathname */ + kvvfsDlOpen, /* xDlOpen */ + 0, /* xDlError */ + 0, /* xDlSym */ + 0, /* xDlClose */ + kvvfsRandomness, /* xRandomness */ + kvvfsSleep, /* xSleep */ + kvvfsCurrentTime, /* xCurrentTime */ + 0, /* xGetLastError */ + kvvfsCurrentTimeInt64 /* xCurrentTimeInt64 */ }; /* Methods for sqlite3_file objects referencing a database file @@ -198,27 +177,16 @@ static sqlite3_io_methods kvvfs_jrnl_io_methods = { /****** Storage subsystem **************************************************/ -/* Allocate a new storage subsystem. -** Return NULL if OOM -*/ -static KVStorage *kvstorageOpen(void){ - KVStorage *pStore; - pStore = sqlite3_malloc64( sizeof(*pStore) ); - if( pStore==0 ) return 0; - memset(pStore, 0, sizeof(*pStore)); - return pStore; -} - -/* Free all resources associated with the storage subsystem */ -static void kvstorageClose(KVStorage *pStore){ - sqlite3_free(pStore); -} /* Expand the key name with an appropriate prefix and put the result ** in pStore->zKey[] */ -static void kvstorageMakeKey(KVStorage *pStore, const char *zKey){ - sqlite3_snprintf(sizeof(pStore->zKey), pStore->zKey, "kvvfs-%s", zKey); +static void kvstorageMakeKey( + const char *zClass, + const char *zKeyIn, + char *zKeyOut +){ + sqlite3_snprintf(KVSTORAGE_KEY_SZ, zKeyOut, "%s-%s", zClass, zKeyIn); } /* Write content into a key. zKey is of limited size. zData should be @@ -227,15 +195,16 @@ static void kvstorageMakeKey(KVStorage *pStore, const char *zKey){ ** Return the number of errors. */ static int kvstorageWrite( - KVStorage *pStore, + const char *zClass, const char *zKey, const char *zData ){ FILE *fd; - kvstorageMakeKey(pStore, zKey); - fd = fopen(pStore->zKey, "wb"); + char zXKey[KVSTORAGE_KEY_SZ]; + kvstorageMakeKey(zClass, zKey, zXKey); + fd = fopen(zXKey, "wb"); if( fd ){ - KVVFS_TRACE(("KVVFS-WRITE %-10s (%d) %.50s%s\n", pStore->zKey, + KVVFS_TRACE(("KVVFS-WRITE %-15s (%d) %.50s%s\n", zXKey, (int)strlen(zData), zData, strlen(zData)>50 ? "..." : "")); fputs(zData, fd); @@ -248,10 +217,11 @@ static int kvstorageWrite( /* Delete a key */ -static int kvstorageDelete(KVStorage *pStore, const char *zKey){ - kvstorageMakeKey(pStore, zKey); - unlink(pStore->zKey); - KVVFS_TRACE(("KVVFS-DELETE %-10s\n", pStore->zKey)); +static int kvstorageDelete(const char *zClass, const char *zKey){ + char zXKey[KVSTORAGE_KEY_SZ]; + kvstorageMakeKey(zClass, zKey, zXKey); + unlink(zXKey); + KVVFS_TRACE(("KVVFS-DELETE %-15s\n", zXKey)); return 0; } @@ -268,41 +238,42 @@ static int kvstorageDelete(KVStorage *pStore, const char *zKey){ ** actually reading it. */ static int kvstorageRead( - KVStorage *pStore, + const char *zClass, const char *zKey, char *zBuf, int nBuf ){ FILE *fd; struct stat buf; - kvstorageMakeKey(pStore, zKey); - if( access(pStore->zKey, R_OK)!=0 - || stat(pStore->zKey, &buf)!=0 + char zXKey[KVSTORAGE_KEY_SZ]; + kvstorageMakeKey(zClass, zKey, zXKey); + if( access(zXKey, R_OK)!=0 + || stat(zXKey, &buf)!=0 || !S_ISREG(buf.st_mode) ){ - KVVFS_TRACE(("KVVFS-READ %-10s (-1)\n", pStore->zKey)); + KVVFS_TRACE(("KVVFS-READ %-15s (-1)\n", zXKey)); return -1; } if( nBuf<0 ){ return (int)buf.st_size; }else if( nBuf==1 ){ zBuf[0] = 0; - KVVFS_TRACE(("KVVFS-READ %-10s (%d)\n", pStore->zKey, + KVVFS_TRACE(("KVVFS-READ %-15s (%d)\n", zXKey, (int)buf.st_size)); return (int)buf.st_size; } - if( nBuf-1 > buf.st_size ){ + if( nBuf > buf.st_size + 1 ){ nBuf = buf.st_size + 1; } - fd = fopen(pStore->zKey, "rb"); + fd = fopen(zXKey, "rb"); if( fd==0 ){ - KVVFS_TRACE(("KVVFS-READ %-10s (-1)\n", pStore->zKey)); + KVVFS_TRACE(("KVVFS-READ %-15s (-1)\n", zXKey)); return -1; }else{ sqlite3_int64 n = fread(zBuf, 1, nBuf-1, fd); fclose(fd); zBuf[n] = 0; - KVVFS_TRACE(("KVVFS-READ %-10s (%lld) %.50s%s\n", pStore->zKey, + KVVFS_TRACE(("KVVFS-READ %-15s (%lld) %.50s%s\n", zXKey, n, zBuf, n>50 ? "..." : "")); return (int)n; } @@ -445,42 +416,25 @@ static void kvvfsDecodeJournal( static sqlite3_int64 kvvfsReadFileSize(KVVfsFile *pFile){ char zData[50]; zData[0] = 0; - kvstorageRead(pFile->pVfs->pStore, "sz", zData, sizeof(zData)-1); + kvstorageRead(pFile->zClass, "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); + kvstorageWrite(pFile->zClass, "sz", zData); } -/****** VFS methods ********************************************************/ +/****** sqlite3_io_methods 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; - } - } + KVVFS_LOG(("xClose %s %s\n", pFile->zClass, + pFile->isJournal ? "journal" : "db")); sqlite3_free(pFile->aJrnl); return SQLITE_OK; } @@ -496,16 +450,16 @@ static int kvvfsReadJrnl( ){ KVVfsFile *pFile = (KVVfsFile*)pProtoFile; assert( pFile->isJournal ); - KVVFS_LOG(("xRead('journal',%d,%lld)\n", iAmt, iOfst)); + KVVFS_LOG(("xRead('%s-journal',%d,%lld)\n", pFile->zClass, iAmt, iOfst)); if( pFile->aJrnl==0 ){ - int szTxt = kvstorageRead(pFile->pVfs->pStore, "jrnl", 0, 0); + int szTxt = kvstorageRead(pFile->zClass, "jrnl", 0, -1); char *aTxt; if( szTxt<=4 ){ return SQLITE_IOERR; } aTxt = sqlite3_malloc64( szTxt+1 ); if( aTxt==0 ) return SQLITE_NOMEM; - kvstorageRead(pFile->pVfs->pStore, "jrnl", aTxt, szTxt+1); + kvstorageRead(pFile->zClass, "jrnl", aTxt, szTxt+1); kvvfsDecodeJournal(pFile, aTxt, szTxt); sqlite3_free(aTxt); if( pFile->aJrnl==0 ) return SQLITE_IOERR; @@ -533,7 +487,7 @@ static int kvvfsReadDb( char aData[131073]; assert( iOfst>=0 ); assert( iAmt>=0 ); - KVVFS_LOG(("xRead('db',%d,%lld)\n", iAmt, iOfst)); + KVVFS_LOG(("xRead('%s-db',%d,%lld)\n", pFile->zClass, iAmt, iOfst)); if( iOfst+iAmt>=512 ){ if( (iOfst % iAmt)!=0 ){ return SQLITE_IOERR_READ; @@ -547,7 +501,7 @@ static int kvvfsReadDb( pgno = 1; } sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno); - got = kvstorageRead(pFile->pVfs->pStore, zKey, aData, sizeof(aData)-1); + got = kvstorageRead(pFile->zClass, zKey, aData, sizeof(aData)-1); if( got<0 ){ n = 0; }else{ @@ -583,7 +537,7 @@ static int kvvfsWriteJrnl( ){ KVVfsFile *pFile = (KVVfsFile*)pProtoFile; sqlite3_int64 iEnd = iOfst+iAmt; - KVVFS_LOG(("xWrite('journal',%d,%lld)\n", iAmt, iOfst)); + KVVFS_LOG(("xWrite('%s-journal',%d,%lld)\n", pFile->zClass, iAmt, iOfst)); if( iEnd>=0x10000000 ) return SQLITE_FULL; if( pFile->aJrnl==0 || pFile->nJrnlaJrnl, iEnd); @@ -613,13 +567,13 @@ static int kvvfsWriteDb( unsigned int pgno; char zKey[30]; char aData[131073]; - KVVFS_LOG(("xWrite('db',%d,%lld)\n", iAmt, iOfst)); + KVVFS_LOG(("xWrite('%s-db',%d,%lld)\n", pFile->zClass, iAmt, iOfst)); assert( iAmt>=512 && iAmt<=65536 ); assert( (iAmt & (iAmt-1))==0 ); pgno = 1 + iOfst/iAmt; sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno); kvvfsEncode(zBuf, iAmt, aData); - kvstorageWrite(pFile->pVfs->pStore, zKey, aData); + kvstorageWrite(pFile->zClass, zKey, aData); if( iOfst+iAmt > pFile->szDb ){ pFile->szDb = iOfst + iAmt; } @@ -631,9 +585,9 @@ static int kvvfsWriteDb( */ static int kvvfsTruncateJrnl(sqlite3_file *pProtoFile, sqlite_int64 size){ KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - KVVFS_LOG(("xTruncate('journal',%lld)\n", size)); + KVVFS_LOG(("xTruncate('%s-journal',%lld)\n", pFile->zClass, size)); assert( size==0 ); - kvstorageDelete(pFile->pVfs->pStore, "jrnl"); + kvstorageDelete(pFile->zClass, "jrnl"); sqlite3_free(pFile->aJrnl); pFile->aJrnl = 0; pFile->nJrnl = 0; @@ -647,12 +601,12 @@ static int kvvfsTruncateDb(sqlite3_file *pProtoFile, sqlite_int64 size){ ){ char zKey[50]; unsigned int pgno, pgnoMax; - KVVFS_LOG(("xTruncate('db',%lld)\n", size)); + KVVFS_LOG(("xTruncate('%s-db',%lld)\n", pFile->zClass, size)); pgno = 1 + size/pFile->szPage; pgnoMax = 2 + pFile->szDb/pFile->szPage; while( pgno<=pgnoMax ){ sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno); - kvstorageDelete(pFile->pVfs->pStore, zKey); + kvstorageDelete(pFile->zClass, zKey); pgno++; } pFile->szDb = size; @@ -669,7 +623,7 @@ static int kvvfsSyncJrnl(sqlite3_file *pProtoFile, int flags){ int i, n; KVVfsFile *pFile = (KVVfsFile *)pProtoFile; char *zOut; - KVVFS_LOG(("xSync('journal')\n")); + KVVFS_LOG(("xSync('%s-journal')\n", pFile->zClass)); if( pFile->nJrnl<=0 ){ return kvvfsTruncateJrnl(pProtoFile, 0); } @@ -685,13 +639,13 @@ static int kvvfsSyncJrnl(sqlite3_file *pProtoFile, int flags){ }while( n>0 ); zOut[i++] = ' '; kvvfsEncode(pFile->aJrnl, pFile->nJrnl, &zOut[i]); - kvstorageWrite(pFile->pVfs->pStore, "jrnl", zOut); + kvstorageWrite(pFile->zClass, "jrnl", zOut); sqlite3_free(zOut); return SQLITE_OK; } static int kvvfsSyncDb(sqlite3_file *pProtoFile, int flags){ KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - KVVFS_LOG(("xSync('db')\n")); + KVVFS_LOG(("xSync('%s-db')\n", pFile->zClass)); if( pFile->szDb>0 ){ kvvfsWriteFileSize(pFile, pFile->szDb); } @@ -703,13 +657,13 @@ static int kvvfsSyncDb(sqlite3_file *pProtoFile, int flags){ */ static int kvvfsFileSizeJrnl(sqlite3_file *pProtoFile, sqlite_int64 *pSize){ KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - KVVFS_LOG(("xFileSize('journal')\n")); + KVVFS_LOG(("xFileSize('%s-journal')\n", pFile->zClass)); *pSize = pFile->nJrnl; return SQLITE_OK; } static int kvvfsFileSizeDb(sqlite3_file *pProtoFile, sqlite_int64 *pSize){ KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - KVVFS_LOG(("xFileSize('db')\n")); + KVVFS_LOG(("xFileSize('%s-db')\n", pFile->zClass)); if( pFile->szDb>=0 ){ *pSize = pFile->szDb; }else{ @@ -724,7 +678,7 @@ static int kvvfsFileSizeDb(sqlite3_file *pProtoFile, sqlite_int64 *pSize){ static int kvvfsLock(sqlite3_file *pProtoFile, int eLock){ KVVfsFile *pFile = (KVVfsFile *)pProtoFile; assert( !pFile->isJournal ); - KVVFS_LOG(("xLock(%d)\n", eLock)); + KVVFS_LOG(("xLock(%s,%d)\n", pFile->zClass, eLock)); if( eLock!=SQLITE_LOCK_NONE ){ pFile->szDb = kvvfsReadFileSize(pFile); @@ -738,7 +692,7 @@ static int kvvfsLock(sqlite3_file *pProtoFile, int eLock){ static int kvvfsUnlock(sqlite3_file *pProtoFile, int eLock){ KVVfsFile *pFile = (KVVfsFile *)pProtoFile; assert( !pFile->isJournal ); - KVVFS_LOG(("xUnlock(%d)\n", eLock)); + KVVFS_LOG(("xUnlock(%s,%d)\n", pFile->zClass, eLock)); if( eLock==SQLITE_LOCK_NONE ){ pFile->szDb = -1; } @@ -775,6 +729,7 @@ static int kvvfsDeviceCharacteristics(sqlite3_file *pProtoFile){ return 0; } +/****** sqlite3_vfs methods *************************************************/ /* ** Open an kvvfs file handle. @@ -787,25 +742,26 @@ static int kvvfsOpen( int *pOutFlags ){ KVVfsFile *pFile = (KVVfsFile*)pProtoFile; - KVVfsVfs *pVfs = (KVVfsVfs*)pProtoVfs; KVVFS_LOG(("xOpen(\"%s\")\n", zName)); - pFile->aJrnl = 0; - pFile->nJrnl = 0; - if( sqlite3_strglob("*-journal", zName)==0 ){ + if( strcmp(zName, "local")==0 + || strcmp(zName, "session")==0 + ){ + pFile->isJournal = 0; + pFile->base.pMethods = &kvvfs_db_io_methods; + }else + if( strcmp(zName, "local-journal")==0 + || strcmp(zName, "session-journal")==0 + ){ pFile->isJournal = 1; pFile->base.pMethods = &kvvfs_jrnl_io_methods; }else{ - pFile->isJournal = 0; - pFile->base.pMethods = &kvvfs_db_io_methods; + return SQLITE_CANTOPEN; } + pFile->zClass = zName[0]=='s' ? "kvvfs-ses" : "kvvfs-loc"; + pFile->aJrnl = 0; + pFile->nJrnl = 0; pFile->szPage = -1; pFile->szDb = -1; - pFile->pVfs = pVfs; - if( pVfs->pFiles==0 ){ - pVfs->pStore = kvstorageOpen(); - } - pFile->pNext = pVfs->pFiles; - pVfs->pFiles = pFile; return SQLITE_OK; } @@ -815,9 +771,11 @@ static int kvvfsOpen( ** returning. */ static int kvvfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ - KVVfsVfs *p = (KVVfsVfs*)pVfs; - if( sqlite3_strglob("*-journal",zPath)==0 ){ - kvstorageDelete(p->pStore, "jrnl"); + if( strcmp(zPath, "local-journal")==0 ){ + kvstorageDelete("kvvfs-loc", "jrnl"); + }else + if( strcmp(zPath, "session-journal")==0 ){ + kvstorageDelete("kvvfs-ses", "jrnl"); } return SQLITE_OK; } @@ -832,14 +790,21 @@ static int kvvfsAccess( int flags, int *pResOut ){ - KVVfsVfs *pVfs = (KVVfsVfs*)pProtoVfs; KVVFS_LOG(("xAccess(\"%s\")\n", zPath)); - if( sqlite3_strglob("*-journal", zPath)==0 ){ - *pResOut = kvstorageRead(pVfs->pStore, "jrnl", 0, 0)>0; - }else if( sqlite3_strglob("*-wal", zPath)==0 ){ + if( strcmp(zPath, "local-journal")==0 ){ + *pResOut = kvstorageRead("kvvfs-loc", "jrnl", 0, -1)>0; + }else + if( strcmp(zPath, "session-journal")==0 ){ + *pResOut = kvstorageRead("kvvfs-ses", "jrnl", 0, -1)>0; + }else + if( strcmp(zPath, "local")==0 ){ + *pResOut = kvstorageRead("kvvfs-loc", "sz", 0, -1)>0; + }else + if( strcmp(zPath, "session")==0 ){ + *pResOut = kvstorageRead("kvvfs-ses", "sz", 0, -1)>0; + }else + { *pResOut = 0; - }else{ - *pResOut = 1; } KVVFS_LOG(("xAccess returns %d\n",*pResOut)); return SQLITE_OK; @@ -915,6 +880,6 @@ int sqlite3_vfskv_init( const sqlite3_api_routines *pApi ){ SQLITE_EXTENSION_INIT2(pApi); - sqlite3_vfs_register(&kvvfs_vfs.base, 1); + sqlite3_vfs_register(&kvvfs_vfs, 1); return SQLITE_OK_LOAD_PERMANENTLY; } diff --git a/manifest b/manifest index 0a3a992338..fb9682d0f2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Separate\ssqlite3_io_methods\sobjects\sfor\sdatabase\sfiles\sand\sjournals. -D 2022-09-09T14:22:41.989 +C Database\smust\sbe\snamed\seither\s"local"\sor\s"session".\s\sEach\shas\sa\sdistinct\nnamespace. +D 2022-09-09T16:16:33.749 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -335,7 +335,7 @@ F ext/misc/uint.c 053fed3bce2e89583afcd4bf804d75d659879bbcedac74d0fa9ed548839a03 F ext/misc/unionvtab.c 36237f0607ca954ac13a4a0e2d2ac40c33bc6e032a5f55f431713061ef1625f9 F ext/misc/urifuncs.c f71360d14fa9e7626b563f1f781c6148109462741c5235ac63ae0f8917b9c751 F ext/misc/uuid.c 5bb2264c1b64d163efa46509544fd7500cb8769cb7c16dd52052da8d961505cf -F ext/misc/vfskv.c 7b2fa888cd33f41a7a3821eec10ed258fe029af41ad788a43856958c4d216432 +F ext/misc/vfskv.c f154254c7585a0434d50d1b0fa0bb27b03ae4231a9045961e58a046dc5ea40ab F ext/misc/vfslog.c 3932ab932eeb2601dbc4447cb14d445aaa9fbe43b863ef5f014401c3420afd20 F ext/misc/vfsstat.c 474d08efc697b8eba300082cb1eb74a5f0f3df31ed257db1cb07e72ab0e53dfb 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.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 00845ac9ef2616e90f5f6a20da3dd040fa8bdcfe73f72fe9c06039561150a82d -R 460848ff6f3cd63ef5eccab59824c77b +P 74fbf6c2a97729e481d5562344e960d0c237aeb1f07240262d32a24fb1f4b5a3 +R ef722c3c17f5bd16a7c59b26dec45e05 U drh -Z 26961af5f4b759d7a43ac0a5cf8d117b +Z c4e335313d89d964aa7abb0331378ddc # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 581c44b250..8a58829e44 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -74fbf6c2a97729e481d5562344e960d0c237aeb1f07240262d32a24fb1f4b5a3 \ No newline at end of file +c8e41279294ea7c2f041c7d4cbbd85fce47d55f2f56180ca837316f7dfd75237 \ No newline at end of file From 7585f49a0a5b134297c5f9cfebf9428743edfbea Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 10 Sep 2022 18:20:59 +0000 Subject: [PATCH 08/13] Move the vfskv.c extension to src/os_kv.c and make it part of the amalgamation, activated if and only if SQLITE_OS_KV is true. FossilOrigin-Name: f6632e69c2ec1a7ddc4e51f3567e3bc082ee94a6dd51fdafdc0c3bf386a32d4c --- Makefile.in | 7 +- main.mk | 4 +- manifest | 24 +++--- manifest.uuid | 2 +- src/main.c | 2 +- ext/misc/vfskv.c => src/os_kv.c | 132 +++++++++++++++----------------- src/os_setup.h | 86 ++++++++++++++------- src/sqliteInt.h | 2 +- tool/mksqlite3c.tcl | 1 + 9 files changed, 146 insertions(+), 114 deletions(-) rename ext/misc/vfskv.c => src/os_kv.c (89%) diff --git a/Makefile.in b/Makefile.in index cc4943f2c4..d4d42c6b18 100644 --- a/Makefile.in +++ b/Makefile.in @@ -184,7 +184,7 @@ LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \ main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \ memdb.lo memjournal.lo \ mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \ - notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \ + notify.lo opcodes.lo os.lo os_kv.lo os_unix.lo os_win.lo \ pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \ random.lo resolve.lo rowset.lo rtree.lo \ sqlite3session.lo select.lo sqlite3rbu.lo status.lo stmt.lo \ @@ -257,6 +257,7 @@ SRC = \ $(TOP)/src/os.h \ $(TOP)/src/os_common.h \ $(TOP)/src/os_setup.h \ + $(TOP)/src/os_kv.c \ $(TOP)/src/os_unix.c \ $(TOP)/src/os_win.c \ $(TOP)/src/os_win.h \ @@ -492,6 +493,7 @@ TESTSRC2 = \ $(TOP)/src/main.c \ $(TOP)/src/mem5.c \ $(TOP)/src/os.c \ + $(TOP)/src/os_kv.c \ $(TOP)/src/os_unix.c \ $(TOP)/src/os_win.c \ $(TOP)/src/pager.c \ @@ -938,6 +940,9 @@ pcache1.lo: $(TOP)/src/pcache1.c $(HDR) $(TOP)/src/pcache.h os.lo: $(TOP)/src/os.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/os.c +os_kv.lo: $(TOP)/src/os_kv.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/os_kv.c + os_unix.lo: $(TOP)/src/os_unix.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/os_unix.c diff --git a/main.mk b/main.mk index 3d8a07494d..49f4fbf90e 100644 --- a/main.mk +++ b/main.mk @@ -68,7 +68,7 @@ LIBOBJ+= vdbe.o parse.o \ main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \ memdb.o memjournal.o \ mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \ - notify.o opcodes.o os.o os_unix.o os_win.o \ + notify.o opcodes.o os.o os_kv.o os_unix.o os_win.o \ pager.o pcache.o pcache1.o pragma.o prepare.o printf.o \ random.o resolve.o rowset.o rtree.o \ select.o sqlite3rbu.o status.o stmt.o \ @@ -134,6 +134,7 @@ SRC = \ $(TOP)/src/os.h \ $(TOP)/src/os_common.h \ $(TOP)/src/os_setup.h \ + $(TOP)/src/os_kv.c \ $(TOP)/src/os_unix.c \ $(TOP)/src/os_win.c \ $(TOP)/src/os_win.h \ @@ -411,6 +412,7 @@ TESTSRC2 = \ $(TOP)/src/main.c \ $(TOP)/src/mem5.c \ $(TOP)/src/os.c \ + $(TOP)/src/os_kv.c \ $(TOP)/src/os_unix.c \ $(TOP)/src/os_win.c \ $(TOP)/src/pager.c \ diff --git a/manifest b/manifest index fb9682d0f2..a139582803 100644 --- a/manifest +++ b/manifest @@ -1,9 +1,9 @@ -C Database\smust\sbe\snamed\seither\s"local"\sor\s"session".\s\sEach\shas\sa\sdistinct\nnamespace. -D 2022-09-09T16:16:33.749 +C Move\sthe\svfskv.c\sextension\sto\ssrc/os_kv.c\sand\smake\sit\spart\sof\sthe\samalgamation,\nactivated\sif\sand\sonly\sif\sSQLITE_OS_KV\sis\strue. +D 2022-09-10T18:20:59.146 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 -F Makefile.in 525bccb89e36a927f9312a231f054a2dc029f6af75901c7fc1a781d51b260323 +F Makefile.in ee179f405fd5f8845473f888517c4ada46099306c33ae1f27dd1aef53fe8e867 F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241 F Makefile.msc d547a2fdba38a1c6cd1954977d0b0cc017f5f8fbfbc65287bf8d335808938016 F README.md 8b8df9ca852aeac4864eb1e400002633ee6db84065bd01b78c33817f97d31f5e @@ -335,7 +335,6 @@ F ext/misc/uint.c 053fed3bce2e89583afcd4bf804d75d659879bbcedac74d0fa9ed548839a03 F ext/misc/unionvtab.c 36237f0607ca954ac13a4a0e2d2ac40c33bc6e032a5f55f431713061ef1625f9 F ext/misc/urifuncs.c f71360d14fa9e7626b563f1f781c6148109462741c5235ac63ae0f8917b9c751 F ext/misc/uuid.c 5bb2264c1b64d163efa46509544fd7500cb8769cb7c16dd52052da8d961505cf -F ext/misc/vfskv.c f154254c7585a0434d50d1b0fa0bb27b03ae4231a9045961e58a046dc5ea40ab F ext/misc/vfslog.c 3932ab932eeb2601dbc4447cb14d445aaa9fbe43b863ef5f014401c3420afd20 F ext/misc/vfsstat.c 474d08efc697b8eba300082cb1eb74a5f0f3df31ed257db1cb07e72ab0e53dfb F ext/misc/vtablog.c 5538acd0c8ddaae372331bee11608d76973436b77d6a91e8635cfc9432fba5ae @@ -510,7 +509,7 @@ F ext/wasm/testing2.js d37433c601f88ed275712c1cfc92d3fb36c7c22e1ed8c7396fb2359e4 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk 20801eed419dc58936ff9449b04041edbbbc0488a9fc683e72471dded050e0bb +F main.mk b1b02927b2e0b73d025f93e388f2f7fba07614e972453983bddc65cd2bf33bb1 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 @@ -553,7 +552,7 @@ F src/insert.c aea5361767817f917b0f0f647a1f0b1621bd858938ae6ae545c3b6b9814b798f F src/json.c 7749b98c62f691697c7ee536b570c744c0583cab4a89200fdd0fc2aa8cc8cbd6 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 853385cc7a604157e137585097949252d5d0c731768e16b044608e5c95c3614b -F src/main.c 8983b4a316d7e09946dd731913aa41712f02e2b55cb5c6c92126ccfe2473244a +F src/main.c e11267cdd380be68d95d4292666636a7f1dff5f17a395f3d55be910d7e9350fb F src/malloc.c b7a3430cbe91d3e8e04fc10c2041b3a19794e63556ad2441a13d8dadd9b2bafc F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de @@ -572,7 +571,8 @@ F src/notify.c 89a97dc854c3aa62ad5f384ef50c5a4a11d70fcc69f86de3e991573421130ed6 F src/os.c 0eb831ba3575af5277e47f4edd14fdfc90025c67eb25ce5cda634518d308d4e9 F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 -F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 +F src/os_kv.c dc409476c3e533def81d022849726f2892e69e6529d4a40a637224cfb3f5df68 w ext/misc/vfskv.c +F src/os_setup.h 0711dbc4678f3ac52d7fe736951b6384a0615387c4ba5135a4764e4e31f4b6a6 F src/os_unix.c 102f7e5c5b59c18ea3dbc929dc3be8acb3afc0e0b6ad572e032335c9c27f44f1 F src/os_win.c e9454cb141908e8eef2102180bad353a36480612d5b736e4c2bd5777d9b25a34 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a @@ -594,7 +594,7 @@ F src/shell.c.in e7e7c2c69ae86c5ee9e8ad66227203d46ff6dce8700a1b1dababff01c71d33d F src/sqlite.h.in b9b7fd73239d94db20332bb6e504688001e5564b655e1318a4427a1caef4b99e F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h a988810c9b21c0dc36dc7a62735012339dc76fc7ab448fb0792721d30eacb69d -F src/sqliteInt.h 94e7fc2a5f0fa5d1f0af84513fd2d1c70a9f6e772556b9dfef16feee63291eae +F src/sqliteInt.h 44eb45c25d379361ee1bd7fc49205471c6cb8a3727aed42372cf4716f653ebf2 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -1938,7 +1938,7 @@ F tool/mkshellc.tcl df5d249617f9cc94d5c48eb0401673eb3f31f383ecbc54e8a13ca3dd97e8 F tool/mksourceid.c 36aa8020014aed0836fd13c51d6dc9219b0df1761d6b5f58ff5b616211b079b9 F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 F tool/mksqlite3c-noext.tcl 4f7cfef5152b0c91920355cbfc1d608a4ad242cb819f1aea07f6d0274f584a7f -F tool/mksqlite3c.tcl eee7e9d9c58abb1045f6ed74ad95ad26e8d22be29fdc431deea5267fb3fa049c +F tool/mksqlite3c.tcl 4fc26a9bfa0c4505b203d7ca0cf086e75ebcd4d63eb719c82f37e3fecdf23d37 F tool/mksqlite3h.tcl 1f5e4a1dbbbc43c83cc6e74fe32c6c620502240b66c7c0f33a51378e78fc4edf F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b F tool/mkvsix.tcl b9e0777a213c23156b6542842c238479e496ebf5 @@ -2001,8 +2001,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 74fbf6c2a97729e481d5562344e960d0c237aeb1f07240262d32a24fb1f4b5a3 -R ef722c3c17f5bd16a7c59b26dec45e05 +P c8e41279294ea7c2f041c7d4cbbd85fce47d55f2f56180ca837316f7dfd75237 +R 781601077fda92ceda7382ba24a16664 U drh -Z c4e335313d89d964aa7abb0331378ddc +Z b2ad663d300b47ac24999ede7b88d1e7 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 8a58829e44..4bfd8ba9c2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c8e41279294ea7c2f041c7d4cbbd85fce47d55f2f56180ca837316f7dfd75237 \ No newline at end of file +f6632e69c2ec1a7ddc4e51f3567e3bc082ee94a6dd51fdafdc0c3bf386a32d4c \ No newline at end of file diff --git a/src/main.c b/src/main.c index b5ef703287..efa5fc3681 100644 --- a/src/main.c +++ b/src/main.c @@ -4781,8 +4781,8 @@ int sqlite3_snapshot_open( */ int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb){ int rc = SQLITE_ERROR; - int iDb; #ifndef SQLITE_OMIT_WAL + int iDb; #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ diff --git a/ext/misc/vfskv.c b/src/os_kv.c similarity index 89% rename from ext/misc/vfskv.c rename to src/os_kv.c index fee190f256..8ae1a65c59 100644 --- a/ext/misc/vfskv.c +++ b/src/os_kv.c @@ -14,45 +14,28 @@ ** Key/Value storage engine where both keys and values must be pure ** text. */ -#include -SQLITE_EXTENSION_INIT1 -#include -#include -#include -#include -#include -#include -#include -#include +#include +#if SQLITE_OS_KV /***************************************************************************** ** Debugging logic */ -/* KVVFS_TRACE() is used for tracing calls to kvstorage routines. */ +/* SQLITE_KV_TRACE() is used for tracing calls to kvstorage routines. */ #if 0 -#define KVVFS_TRACE(X) printf X; +#define SQLITE_KV_TRACE(X) printf X; #else -#define KVVFS_TRACE(X) +#define SQLITE_KV_TRACE(X) #endif -/* KVVFS_LOG() is used for tracing calls to the VFS interface */ +/* SQLITE_KV_LOG() is used for tracing calls to the VFS interface */ #if 0 -#define KVVFS_LOG(X) printf X; +#define SQLITE_KV_LOG(X) printf X; #else -#define KVVFS_LOG(X) +#define SQLITE_KV_LOG(X) #endif -/***************************************************************************** -** The low-level storage engine -*/ -#define KVSTORAGE_KEY_SZ 24 -static int kvstorageWrite(const char*, const char *zKey, const char *zData); -static int kvstorageDelete(const char*, const char *zKey); -static int kvstorageRead(const char*, const char *zKey, char *zBuf, int nBuf); - - /* ** Forward declaration of objects used by this VFS implementation */ @@ -176,6 +159,17 @@ static sqlite3_io_methods kvvfs_jrnl_io_methods = { }; /****** Storage subsystem **************************************************/ +#include +#include +#include + +/* Forward declarations for the low-level storage engine +*/ +#define KVSTORAGE_KEY_SZ 24 +#define KVSTORAGE_KEY_PREFIX "kvvfs-" +static int kvstorageWrite(const char*, const char *zKey, const char *zData); +static int kvstorageDelete(const char*, const char *zKey); +static int kvstorageRead(const char*, const char *zKey, char *zBuf, int nBuf); /* Expand the key name with an appropriate prefix and put the result @@ -204,7 +198,7 @@ static int kvstorageWrite( kvstorageMakeKey(zClass, zKey, zXKey); fd = fopen(zXKey, "wb"); if( fd ){ - KVVFS_TRACE(("KVVFS-WRITE %-15s (%d) %.50s%s\n", zXKey, + SQLITE_KV_TRACE(("KVVFS-WRITE %-15s (%d) %.50s%s\n", zXKey, (int)strlen(zData), zData, strlen(zData)>50 ? "..." : "")); fputs(zData, fd); @@ -221,7 +215,7 @@ static int kvstorageDelete(const char *zClass, const char *zKey){ char zXKey[KVSTORAGE_KEY_SZ]; kvstorageMakeKey(zClass, zKey, zXKey); unlink(zXKey); - KVVFS_TRACE(("KVVFS-DELETE %-15s\n", zXKey)); + SQLITE_KV_TRACE(("KVVFS-DELETE %-15s\n", zXKey)); return 0; } @@ -251,14 +245,14 @@ static int kvstorageRead( || stat(zXKey, &buf)!=0 || !S_ISREG(buf.st_mode) ){ - KVVFS_TRACE(("KVVFS-READ %-15s (-1)\n", zXKey)); + SQLITE_KV_TRACE(("KVVFS-READ %-15s (-1)\n", zXKey)); return -1; } if( nBuf<0 ){ return (int)buf.st_size; }else if( nBuf==1 ){ zBuf[0] = 0; - KVVFS_TRACE(("KVVFS-READ %-15s (%d)\n", zXKey, + SQLITE_KV_TRACE(("KVVFS-READ %-15s (%d)\n", zXKey, (int)buf.st_size)); return (int)buf.st_size; } @@ -267,13 +261,13 @@ static int kvstorageRead( } fd = fopen(zXKey, "rb"); if( fd==0 ){ - KVVFS_TRACE(("KVVFS-READ %-15s (-1)\n", zXKey)); + SQLITE_KV_TRACE(("KVVFS-READ %-15s (-1)\n", zXKey)); return -1; }else{ sqlite3_int64 n = fread(zBuf, 1, nBuf-1, fd); fclose(fd); zBuf[n] = 0; - KVVFS_TRACE(("KVVFS-READ %-15s (%lld) %.50s%s\n", zXKey, + SQLITE_KV_TRACE(("KVVFS-READ %-15s (%lld) %.50s%s\n", zXKey, n, zBuf, n>50 ? "..." : "")); return (int)n; } @@ -433,7 +427,7 @@ static void kvvfsWriteFileSize(KVVfsFile *pFile, sqlite3_int64 sz){ static int kvvfsClose(sqlite3_file *pProtoFile){ KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - KVVFS_LOG(("xClose %s %s\n", pFile->zClass, + SQLITE_KV_LOG(("xClose %s %s\n", pFile->zClass, pFile->isJournal ? "journal" : "db")); sqlite3_free(pFile->aJrnl); return SQLITE_OK; @@ -450,7 +444,7 @@ static int kvvfsReadJrnl( ){ KVVfsFile *pFile = (KVVfsFile*)pProtoFile; assert( pFile->isJournal ); - KVVFS_LOG(("xRead('%s-journal',%d,%lld)\n", pFile->zClass, iAmt, iOfst)); + SQLITE_KV_LOG(("xRead('%s-journal',%d,%lld)\n", pFile->zClass, iAmt, iOfst)); if( pFile->aJrnl==0 ){ int szTxt = kvstorageRead(pFile->zClass, "jrnl", 0, -1); char *aTxt; @@ -487,7 +481,7 @@ static int kvvfsReadDb( char aData[131073]; assert( iOfst>=0 ); assert( iAmt>=0 ); - KVVFS_LOG(("xRead('%s-db',%d,%lld)\n", pFile->zClass, iAmt, iOfst)); + SQLITE_KV_LOG(("xRead('%s-db',%d,%lld)\n", pFile->zClass, iAmt, iOfst)); if( iOfst+iAmt>=512 ){ if( (iOfst % iAmt)!=0 ){ return SQLITE_IOERR_READ; @@ -537,7 +531,7 @@ static int kvvfsWriteJrnl( ){ KVVfsFile *pFile = (KVVfsFile*)pProtoFile; sqlite3_int64 iEnd = iOfst+iAmt; - KVVFS_LOG(("xWrite('%s-journal',%d,%lld)\n", pFile->zClass, iAmt, iOfst)); + SQLITE_KV_LOG(("xWrite('%s-journal',%d,%lld)\n", pFile->zClass, iAmt, iOfst)); if( iEnd>=0x10000000 ) return SQLITE_FULL; if( pFile->aJrnl==0 || pFile->nJrnlaJrnl, iEnd); @@ -567,7 +561,7 @@ static int kvvfsWriteDb( unsigned int pgno; char zKey[30]; char aData[131073]; - KVVFS_LOG(("xWrite('%s-db',%d,%lld)\n", pFile->zClass, iAmt, iOfst)); + SQLITE_KV_LOG(("xWrite('%s-db',%d,%lld)\n", pFile->zClass, iAmt, iOfst)); assert( iAmt>=512 && iAmt<=65536 ); assert( (iAmt & (iAmt-1))==0 ); pgno = 1 + iOfst/iAmt; @@ -585,7 +579,7 @@ static int kvvfsWriteDb( */ static int kvvfsTruncateJrnl(sqlite3_file *pProtoFile, sqlite_int64 size){ KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - KVVFS_LOG(("xTruncate('%s-journal',%lld)\n", pFile->zClass, size)); + SQLITE_KV_LOG(("xTruncate('%s-journal',%lld)\n", pFile->zClass, size)); assert( size==0 ); kvstorageDelete(pFile->zClass, "jrnl"); sqlite3_free(pFile->aJrnl); @@ -601,7 +595,7 @@ static int kvvfsTruncateDb(sqlite3_file *pProtoFile, sqlite_int64 size){ ){ char zKey[50]; unsigned int pgno, pgnoMax; - KVVFS_LOG(("xTruncate('%s-db',%lld)\n", pFile->zClass, size)); + SQLITE_KV_LOG(("xTruncate('%s-db',%lld)\n", pFile->zClass, size)); pgno = 1 + size/pFile->szPage; pgnoMax = 2 + pFile->szDb/pFile->szPage; while( pgno<=pgnoMax ){ @@ -623,7 +617,7 @@ static int kvvfsSyncJrnl(sqlite3_file *pProtoFile, int flags){ int i, n; KVVfsFile *pFile = (KVVfsFile *)pProtoFile; char *zOut; - KVVFS_LOG(("xSync('%s-journal')\n", pFile->zClass)); + SQLITE_KV_LOG(("xSync('%s-journal')\n", pFile->zClass)); if( pFile->nJrnl<=0 ){ return kvvfsTruncateJrnl(pProtoFile, 0); } @@ -645,7 +639,7 @@ static int kvvfsSyncJrnl(sqlite3_file *pProtoFile, int flags){ } static int kvvfsSyncDb(sqlite3_file *pProtoFile, int flags){ KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - KVVFS_LOG(("xSync('%s-db')\n", pFile->zClass)); + SQLITE_KV_LOG(("xSync('%s-db')\n", pFile->zClass)); if( pFile->szDb>0 ){ kvvfsWriteFileSize(pFile, pFile->szDb); } @@ -657,13 +651,13 @@ static int kvvfsSyncDb(sqlite3_file *pProtoFile, int flags){ */ static int kvvfsFileSizeJrnl(sqlite3_file *pProtoFile, sqlite_int64 *pSize){ KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - KVVFS_LOG(("xFileSize('%s-journal')\n", pFile->zClass)); + SQLITE_KV_LOG(("xFileSize('%s-journal')\n", pFile->zClass)); *pSize = pFile->nJrnl; return SQLITE_OK; } static int kvvfsFileSizeDb(sqlite3_file *pProtoFile, sqlite_int64 *pSize){ KVVfsFile *pFile = (KVVfsFile *)pProtoFile; - KVVFS_LOG(("xFileSize('%s-db')\n", pFile->zClass)); + SQLITE_KV_LOG(("xFileSize('%s-db')\n", pFile->zClass)); if( pFile->szDb>=0 ){ *pSize = pFile->szDb; }else{ @@ -678,7 +672,7 @@ static int kvvfsFileSizeDb(sqlite3_file *pProtoFile, sqlite_int64 *pSize){ static int kvvfsLock(sqlite3_file *pProtoFile, int eLock){ KVVfsFile *pFile = (KVVfsFile *)pProtoFile; assert( !pFile->isJournal ); - KVVFS_LOG(("xLock(%s,%d)\n", pFile->zClass, eLock)); + SQLITE_KV_LOG(("xLock(%s,%d)\n", pFile->zClass, eLock)); if( eLock!=SQLITE_LOCK_NONE ){ pFile->szDb = kvvfsReadFileSize(pFile); @@ -692,7 +686,7 @@ static int kvvfsLock(sqlite3_file *pProtoFile, int eLock){ static int kvvfsUnlock(sqlite3_file *pProtoFile, int eLock){ KVVfsFile *pFile = (KVVfsFile *)pProtoFile; assert( !pFile->isJournal ); - KVVFS_LOG(("xUnlock(%s,%d)\n", pFile->zClass, eLock)); + SQLITE_KV_LOG(("xUnlock(%s,%d)\n", pFile->zClass, eLock)); if( eLock==SQLITE_LOCK_NONE ){ pFile->szDb = -1; } @@ -703,7 +697,7 @@ static int kvvfsUnlock(sqlite3_file *pProtoFile, int eLock){ ** Check if another file-handle holds a RESERVED lock on an kvvfs-file. */ static int kvvfsCheckReservedLock(sqlite3_file *pProtoFile, int *pResOut){ - KVVFS_LOG(("xCheckReservedLock\n")); + SQLITE_KV_LOG(("xCheckReservedLock\n")); *pResOut = 0; return SQLITE_OK; } @@ -742,7 +736,7 @@ static int kvvfsOpen( int *pOutFlags ){ KVVfsFile *pFile = (KVVfsFile*)pProtoFile; - KVVFS_LOG(("xOpen(\"%s\")\n", zName)); + SQLITE_KV_LOG(("xOpen(\"%s\")\n", zName)); if( strcmp(zName, "local")==0 || strcmp(zName, "session")==0 ){ @@ -757,7 +751,11 @@ static int kvvfsOpen( }else{ return SQLITE_CANTOPEN; } - pFile->zClass = zName[0]=='s' ? "kvvfs-ses" : "kvvfs-loc"; + if( zName[0]=='s' ){ + pFile->zClass = KVSTORAGE_KEY_PREFIX "ses"; + }else{ + pFile->zClass = KVSTORAGE_KEY_PREFIX "loc"; + } pFile->aJrnl = 0; pFile->nJrnl = 0; pFile->szPage = -1; @@ -772,10 +770,10 @@ static int kvvfsOpen( */ static int kvvfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ if( strcmp(zPath, "local-journal")==0 ){ - kvstorageDelete("kvvfs-loc", "jrnl"); + kvstorageDelete(KVSTORAGE_KEY_PREFIX "loc", "jrnl"); }else if( strcmp(zPath, "session-journal")==0 ){ - kvstorageDelete("kvvfs-ses", "jrnl"); + kvstorageDelete(KVSTORAGE_KEY_PREFIX "ses", "jrnl"); } return SQLITE_OK; } @@ -790,23 +788,23 @@ static int kvvfsAccess( int flags, int *pResOut ){ - KVVFS_LOG(("xAccess(\"%s\")\n", zPath)); + SQLITE_KV_LOG(("xAccess(\"%s\")\n", zPath)); if( strcmp(zPath, "local-journal")==0 ){ - *pResOut = kvstorageRead("kvvfs-loc", "jrnl", 0, -1)>0; + *pResOut = kvstorageRead(KVSTORAGE_KEY_PREFIX "loc", "jrnl", 0, -1)>0; }else if( strcmp(zPath, "session-journal")==0 ){ - *pResOut = kvstorageRead("kvvfs-ses", "jrnl", 0, -1)>0; + *pResOut = kvstorageRead(KVSTORAGE_KEY_PREFIX "ses", "jrnl", 0, -1)>0; }else if( strcmp(zPath, "local")==0 ){ - *pResOut = kvstorageRead("kvvfs-loc", "sz", 0, -1)>0; + *pResOut = kvstorageRead(KVSTORAGE_KEY_PREFIX "loc", "sz", 0, -1)>0; }else if( strcmp(zPath, "session")==0 ){ - *pResOut = kvstorageRead("kvvfs-ses", "sz", 0, -1)>0; + *pResOut = kvstorageRead(KVSTORAGE_KEY_PREFIX "ses", "sz", 0, -1)>0; }else { *pResOut = 0; } - KVVFS_LOG(("xAccess returns %d\n",*pResOut)); + SQLITE_KV_LOG(("xAccess returns %d\n",*pResOut)); return SQLITE_OK; } @@ -822,7 +820,7 @@ static int kvvfsFullPathname( char *zOut ){ size_t nPath = strlen(zPath); - KVVFS_LOG(("xFullPathname(\"%s\")\n", zPath)); + SQLITE_KV_LOG(("xFullPathname(\"%s\")\n", zPath)); if( nOut1 +# undef SQLITE_OS_KV +# define SQLITE_OS_KV 0 +# undef SQLITE_OS_UNIX +# define SQLITE_OS_UNIX 0 +# undef SQLITE_OS_WIN +# define SQLITE_OS_WIN 0 +#endif +#if SQLITE_OS_KV+1>1 +# undef SQLITE_OS_OTHER # define SQLITE_OS_OTHER 0 -# ifndef SQLITE_OS_WIN -# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \ - defined(__MINGW32__) || defined(__BORLANDC__) -# define SQLITE_OS_WIN 1 -# define SQLITE_OS_UNIX 0 -# else -# define SQLITE_OS_WIN 0 -# define SQLITE_OS_UNIX 1 -# endif -# else -# define SQLITE_OS_UNIX 0 -# endif -#else -# ifndef SQLITE_OS_WIN -# define SQLITE_OS_WIN 0 -# endif +# undef SQLITE_OS_UNIX +# define SQLITE_OS_UNIX 0 +# undef SQLITE_OS_WIN +# define SQLITE_OS_WIN 0 +# define SQLITE_OMIT_LOAD_EXTENSION 1 +# define SQLITE_OMIT_WAL 1 +# define SQLITE_OMIT DEPRECATED 1 +# undef SQLITE_TEMP_STORE +# define SQLITE_TEMP_STORE 3 /* Always use memory for temporary storage */ +# define SQLITE_DQS 0 +# define SQLITE_OMIT_SHARED_CACHE 1 +# define SQLITE_OMIT_AUTOINIT 1 +#endif +#if SQLITE_OS_UNIX+1>1 +# undef SQLITE_OS_KV +# define SQLITE_OS_KV 0 +# undef SQLITE_OS_OTHER +# define SQLITE_OS_OTHER 0 +# undef SQLITE_OS_WIN +# define SQLITE_OS_WIN 0 +#endif +#if SQLITE_OS_WIN+1>1 +# undef SQLITE_OS_KV +# define SQLITE_OS_KV 0 +# undef SQLITE_OS_OTHER +# define SQLITE_OS_OTHER 0 +# undef SQLITE_OS_UNIX +# define SQLITE_OS_UNIX 0 #endif + #endif /* SQLITE_OS_SETUP_H */ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 148ba75949..63e3583c8c 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1268,11 +1268,11 @@ typedef int VList; ** "BusyHandler" typedefs. vdbe.h also requires a few of the opaque ** pointer types (i.e. FuncDef) defined above. */ +#include "os.h" #include "pager.h" #include "btree.h" #include "vdbe.h" #include "pcache.h" -#include "os.h" #include "mutex.h" /* The SQLITE_EXTRA_DURABLE compile-time option used to set the default diff --git a/tool/mksqlite3c.tcl b/tool/mksqlite3c.tcl index 595fc4c602..0cdf514e44 100644 --- a/tool/mksqlite3c.tcl +++ b/tool/mksqlite3c.tcl @@ -355,6 +355,7 @@ foreach file { hash.c opcodes.c + os_kv.c os_unix.c os_win.c memdb.c From c6c9c6aad0a8652d3daf0298fe9d411b03c79c41 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 10 Sep 2022 18:38:21 +0000 Subject: [PATCH 09/13] Improved comments in os_kv.c. Better names for the key/value name spaces. FossilOrigin-Name: 8e1652a3856765c9146cc2a7e3b598a2dc7dc84c556b35eab9a35184514384b9 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/os_kv.c | 48 ++++++++++++++++++++++++++---------------------- 3 files changed, 33 insertions(+), 29 deletions(-) diff --git a/manifest b/manifest index a139582803..23b98932b2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Move\sthe\svfskv.c\sextension\sto\ssrc/os_kv.c\sand\smake\sit\spart\sof\sthe\samalgamation,\nactivated\sif\sand\sonly\sif\sSQLITE_OS_KV\sis\strue. -D 2022-09-10T18:20:59.146 +C Improved\scomments\sin\sos_kv.c.\s\sBetter\snames\sfor\sthe\skey/value\sname\sspaces. +D 2022-09-10T18:38:21.976 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -571,7 +571,7 @@ F src/notify.c 89a97dc854c3aa62ad5f384ef50c5a4a11d70fcc69f86de3e991573421130ed6 F src/os.c 0eb831ba3575af5277e47f4edd14fdfc90025c67eb25ce5cda634518d308d4e9 F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 -F src/os_kv.c dc409476c3e533def81d022849726f2892e69e6529d4a40a637224cfb3f5df68 w ext/misc/vfskv.c +F src/os_kv.c c658ddfb433b982afb3d12d133117e8db9eee11af33db41c30a6f30375f9b99a F src/os_setup.h 0711dbc4678f3ac52d7fe736951b6384a0615387c4ba5135a4764e4e31f4b6a6 F src/os_unix.c 102f7e5c5b59c18ea3dbc929dc3be8acb3afc0e0b6ad572e032335c9c27f44f1 F src/os_win.c e9454cb141908e8eef2102180bad353a36480612d5b736e4c2bd5777d9b25a34 @@ -2001,8 +2001,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P c8e41279294ea7c2f041c7d4cbbd85fce47d55f2f56180ca837316f7dfd75237 -R 781601077fda92ceda7382ba24a16664 +P f6632e69c2ec1a7ddc4e51f3567e3bc082ee94a6dd51fdafdc0c3bf386a32d4c +R 8cd4482ba17a8f6c143ea61b8462f46c U drh -Z b2ad663d300b47ac24999ede7b88d1e7 +Z 81846bec91bdcab04bc60c9c032d039e # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 4bfd8ba9c2..c114a26d08 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f6632e69c2ec1a7ddc4e51f3567e3bc082ee94a6dd51fdafdc0c3bf386a32d4c \ No newline at end of file +8e1652a3856765c9146cc2a7e3b598a2dc7dc84c556b35eab9a35184514384b9 \ No newline at end of file diff --git a/src/os_kv.c b/src/os_kv.c index 8ae1a65c59..1412de8122 100644 --- a/src/os_kv.c +++ b/src/os_kv.c @@ -165,26 +165,28 @@ static sqlite3_io_methods kvvfs_jrnl_io_methods = { /* Forward declarations for the low-level storage engine */ -#define KVSTORAGE_KEY_SZ 24 -#define KVSTORAGE_KEY_PREFIX "kvvfs-" +#define KVSTORAGE_KEY_SZ 32 static int kvstorageWrite(const char*, const char *zKey, const char *zData); static int kvstorageDelete(const char*, const char *zKey); static int kvstorageRead(const char*, const char *zKey, char *zBuf, int nBuf); /* Expand the key name with an appropriate prefix and put the result -** in pStore->zKey[] +** zKeyOut[]. The zKeyOut[] buffer is assumed to hold at least +** KVSTORAGE_KEY_SZ bytes. */ static void kvstorageMakeKey( const char *zClass, const char *zKeyIn, char *zKeyOut ){ - sqlite3_snprintf(KVSTORAGE_KEY_SZ, zKeyOut, "%s-%s", zClass, zKeyIn); + sqlite3_snprintf(KVSTORAGE_KEY_SZ, zKeyOut, "kvvfs-%s-%s", zClass, zKeyIn); } -/* Write content into a key. zKey is of limited size. zData should be -** pure text. In other words, zData has already been encoded. +/* Write content into a key. zClass is the particular namespace of the +** underlying key/value store to use - either "local" or "session". +** +** Both zKey and zData are zero-terminated pure text strings. ** ** Return the number of errors. */ @@ -209,7 +211,9 @@ static int kvstorageWrite( } } -/* Delete a key +/* Delete a key (with its corresponding data) from the key/value +** namespace given by zClass. If the key does not previously exist, +** this routine is a no-op. */ static int kvstorageDelete(const char *zClass, const char *zKey){ char zXKey[KVSTORAGE_KEY_SZ]; @@ -219,16 +223,17 @@ static int kvstorageDelete(const char *zClass, const char *zKey){ return 0; } -/* Read the value associated with a key and put the result in the first +/* Read the value associated with a zKey from the key/value namespace given +** by zClass and put the text data associated with that key in the first ** nBuf bytes of zBuf[]. The value might be truncated if zBuf is not large -** enough to hold it all. The value put into zBuf will always be zero -** terminated. +** enough to hold it all. The value put into zBuf must always be zero +** terminated, even if it gets truncated because nBuf is not large enough. ** ** Return the total number of bytes in the data, without truncation, and ** not counting the final zero terminator. Return -1 if the key does ** not exist. ** -** If nBuf==0 then this routine simply returns the size of the data without +** If nBuf<=0 then this routine simply returns the size of the data without ** actually reading it. */ static int kvstorageRead( @@ -248,7 +253,7 @@ static int kvstorageRead( SQLITE_KV_TRACE(("KVVFS-READ %-15s (-1)\n", zXKey)); return -1; } - if( nBuf<0 ){ + if( nBuf<=0 ){ return (int)buf.st_size; }else if( nBuf==1 ){ zBuf[0] = 0; @@ -275,7 +280,6 @@ static int kvstorageRead( /****** Utility subroutines ************************************************/ - /* ** Encode binary into the text encoded used to persist on disk. ** The output text is stored in aOut[], which must be at least @@ -446,7 +450,7 @@ static int kvvfsReadJrnl( assert( pFile->isJournal ); SQLITE_KV_LOG(("xRead('%s-journal',%d,%lld)\n", pFile->zClass, iAmt, iOfst)); if( pFile->aJrnl==0 ){ - int szTxt = kvstorageRead(pFile->zClass, "jrnl", 0, -1); + int szTxt = kvstorageRead(pFile->zClass, "jrnl", 0, 0); char *aTxt; if( szTxt<=4 ){ return SQLITE_IOERR; @@ -752,9 +756,9 @@ static int kvvfsOpen( return SQLITE_CANTOPEN; } if( zName[0]=='s' ){ - pFile->zClass = KVSTORAGE_KEY_PREFIX "ses"; + pFile->zClass = "session"; }else{ - pFile->zClass = KVSTORAGE_KEY_PREFIX "loc"; + pFile->zClass = "local"; } pFile->aJrnl = 0; pFile->nJrnl = 0; @@ -770,10 +774,10 @@ static int kvvfsOpen( */ static int kvvfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ if( strcmp(zPath, "local-journal")==0 ){ - kvstorageDelete(KVSTORAGE_KEY_PREFIX "loc", "jrnl"); + kvstorageDelete("local", "jrnl"); }else if( strcmp(zPath, "session-journal")==0 ){ - kvstorageDelete(KVSTORAGE_KEY_PREFIX "ses", "jrnl"); + kvstorageDelete("session", "jrnl"); } return SQLITE_OK; } @@ -790,16 +794,16 @@ static int kvvfsAccess( ){ SQLITE_KV_LOG(("xAccess(\"%s\")\n", zPath)); if( strcmp(zPath, "local-journal")==0 ){ - *pResOut = kvstorageRead(KVSTORAGE_KEY_PREFIX "loc", "jrnl", 0, -1)>0; + *pResOut = kvstorageRead("local", "jrnl", 0, 0)>0; }else if( strcmp(zPath, "session-journal")==0 ){ - *pResOut = kvstorageRead(KVSTORAGE_KEY_PREFIX "ses", "jrnl", 0, -1)>0; + *pResOut = kvstorageRead("session", "jrnl", 0, 0)>0; }else if( strcmp(zPath, "local")==0 ){ - *pResOut = kvstorageRead(KVSTORAGE_KEY_PREFIX "loc", "sz", 0, -1)>0; + *pResOut = kvstorageRead("local", "sz", 0, 0)>0; }else if( strcmp(zPath, "session")==0 ){ - *pResOut = kvstorageRead(KVSTORAGE_KEY_PREFIX "ses", "sz", 0, -1)>0; + *pResOut = kvstorageRead("session", "sz", 0, 0)>0; }else { *pResOut = 0; From ad5125a624f22d8d18989287437f50a69ca8ff2b Mon Sep 17 00:00:00 2001 From: stephan Date: Mon, 12 Sep 2022 12:39:28 +0000 Subject: [PATCH 10/13] Initial build of kvvfs in wasm. It loads but cannot find the VFS for as-yet-unknown reasons (sqlite3 shell works fine), and most APIs throw "null function or function signature mismatch" from deep within wasm, presumably as a side effect of the "missing" VFS. FossilOrigin-Name: 1a2f24a0bdfc6eaae478916b8f4f9c6b63ead9964534fc2951fb4e995ffe61f1 --- ext/wasm/GNUmakefile | 1 + ext/wasm/kvvfs.make | 82 +++++++++++++++++ ext/wasm/kvvfs1.html | 34 +++++++ ext/wasm/kvvfs1.js | 52 +++++++++++ manifest | 19 ++-- manifest.uuid | 2 +- src/os_kv.c | 206 ++++++++++++++++++++++++++++++++++++++++++- 7 files changed, 383 insertions(+), 13 deletions(-) create mode 100644 ext/wasm/kvvfs.make create mode 100644 ext/wasm/kvvfs1.html create mode 100644 ext/wasm/kvvfs1.js diff --git a/ext/wasm/GNUmakefile b/ext/wasm/GNUmakefile index ee8ade74a3..3133d1230b 100644 --- a/ext/wasm/GNUmakefile +++ b/ext/wasm/GNUmakefile @@ -262,6 +262,7 @@ all: $(sqlite3.js) # End main Emscripten-based module build ######################################################################## +include kvvfs.make ######################################################################## # fiddle_remote is the remote destination for the fiddle app. It diff --git a/ext/wasm/kvvfs.make b/ext/wasm/kvvfs.make new file mode 100644 index 0000000000..83a2691370 --- /dev/null +++ b/ext/wasm/kvvfs.make @@ -0,0 +1,82 @@ +#!/usr/bin/make +#^^^^ help emacs select makefile mode +# +# This is a sub-make for building a standalone kvvfs-based +# sqlite3.wasm. It is intended to be "include"d from the main +# GNUMakefile. +# +# Notable potential TODOs: +# +# - Trim down a custom sqlite3-api.js for this build. We can elimate +# the jaccwabyt dependency, for example, because this build won't +# make use of the VFS bits. Similarly, we can eliminate or replace +# parts of the OO1 API, or provide a related API which manages +# singletons of the localStorage/sessionStorage instances. +# +######################################################################## +MAKEFILE.kvvfs := $(lastword $(MAKEFILE_LIST)) + +kvvfs.js := sqlite3-kvvfs.js +kvvfs.wasm := sqlite3-kvvfs.wasm +kvvfs.wasm.c := $(dir.api)/sqlite3-wasm.c + +CLEAN_FILES += $(kvvfs.js) $(kvvfs.wasm) + +######################################################################## +# emcc flags for .c/.o/.wasm. +kvvfs.flags = +#kvvfs.flags += -v # _very_ loud but also informative about what it's doing + +######################################################################## +# emcc flags for .c/.o. +kvvfs.cflags := +kvvfs.cflags += -std=c99 -fPIC +kvvfs.cflags += -I. -I$(dir.top) +kvvfs.cflags += -DSQLITE_OS_KV=1 $(SQLITE_OPT) + +######################################################################## +# emcc flags specific to building the final .js/.wasm file... +kvvfs.jsflags := -fPIC +kvvfs.jsflags += --no-entry +kvvfs.jsflags += -sENVIRONMENT=web +kvvfs.jsflags += -sMODULARIZE +kvvfs.jsflags += -sSTRICT_JS +kvvfs.jsflags += -sDYNAMIC_EXECUTION=0 +kvvfs.jsflags += -sNO_POLYFILL +kvvfs.jsflags += -sEXPORTED_FUNCTIONS=@$(dir.api)/EXPORTED_FUNCTIONS.sqlite3-api +kvvfs.jsflags += -sEXPORTED_RUNTIME_METHODS=FS,wasmMemory,allocateUTF8OnStack + # wasmMemory ==> for -sIMPORTED_MEMORY + # allocateUTF8OnStack ==> kvvfs internals +kvvfs.jsflags += -sUSE_CLOSURE_COMPILER=0 +kvvfs.jsflags += -sIMPORTED_MEMORY +#kvvfs.jsflags += -sINITIAL_MEMORY=13107200 +#kvvfs.jsflags += -sTOTAL_STACK=4194304 +kvvfs.jsflags += -sEXPORT_NAME=sqlite3InitModule +kvvfs.jsflags += -sGLOBAL_BASE=4096 # HYPOTHETICALLY keep func table indexes from overlapping w/ heap addr. +kvvfs.jsflags += --post-js=$(post-js.js) +#kvvfs.jsflags += -sFILESYSTEM=0 # only for experimentation. sqlite3 needs the FS API +# Perhaps the kvvfs build doesn't? +#kvvfs.jsflags += -sABORTING_MALLOC +kvvfs.jsflags += -sALLOW_MEMORY_GROWTH +kvvfs.jsflags += -sALLOW_TABLE_GROWTH +kvvfs.jsflags += -Wno-limited-postlink-optimizations +# ^^^^^ it likes to warn when we have "limited optimizations" via the -g3 flag. +kvvfs.jsflags += -sERROR_ON_UNDEFINED_SYMBOLS=0 +kvvfs.jsflags += -sLLD_REPORT_UNDEFINED +#kvvfs.jsflags += --import-undefined +kvvfs.jsflags += -sMEMORY64=0 +ifneq (0,$(enable_bigint)) +kvvfs.jsflags += -sWASM_BIGINT +endif + +$(kvvfs.js): $(MAKEFILE) $(MAKEFILE.kvvfs) $(kvvfs.wasm.c) \ + EXPORTED_FUNCTIONS.api \ + $(post-js.js) + $(emcc.bin) -o $@ $(emcc_opt) $(emcc.flags) $(kvvfs.cflags) $(kvvfs.jsflags) $(kvvfs.wasm.c) + chmod -x $(kvvfs.wasm) +ifneq (,$(wasm-strip)) + $(wasm-strip) $(kvvfs.wasm) +endif + @ls -la $@ $(kvvfs.wasm) + +kvvfs: $(kvvfs.js) diff --git a/ext/wasm/kvvfs1.html b/ext/wasm/kvvfs1.html new file mode 100644 index 0000000000..0657920c53 --- /dev/null +++ b/ext/wasm/kvvfs1.html @@ -0,0 +1,34 @@ + + + + + + + + + sqlite3-kvvfs.js tests + + +
sqlite3-kvvfs.js tests
+ +
+
+
Initializing app...
+
+ On a slow internet connection this may take a moment. If this + message displays for "a long time", intialization may have + failed and the JavaScript console may contain clues as to why. +
+
+
Downloading...
+
+ +
+
Everything on this page happens in the dev console.
+
+
+ + + + + diff --git a/ext/wasm/kvvfs1.js b/ext/wasm/kvvfs1.js new file mode 100644 index 0000000000..a9737a565b --- /dev/null +++ b/ext/wasm/kvvfs1.js @@ -0,0 +1,52 @@ +/* + 2022-09-12 + + 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. + + *********************************************************************** + + A basic test script for sqlite3-kvvfs.wasm. This file must be run in + main JS thread and sqlite3-kvvfs.js must have been loaded before it. +*/ +'use strict'; +(function(){ + const T = self.SqliteTestUtil; + const toss = function(...args){throw new Error(args.join(' '))}; + const debug = console.debug.bind(console); + const eOutput = document.querySelector('#test-output'); + const log = console.log.bind(console) + const logHtml = function(...args){ + log.apply(this, args); + const ln = document.createElement('div'); + ln.append(document.createTextNode(args.join(' '))); + eOutput.append(ln); + }; + + const runTests = function(Module){ + //log("Module",Module); + const sqlite3 = Module.sqlite3, + capi = sqlite3.capi, + oo = sqlite3.oo1, + wasm = capi.wasm; + log("Loaded module:",capi.sqlite3_libversion(), capi.sqlite3_sourceid()); + log("Build options:",wasm.compileOptionUsed()); + self.S = sqlite3; + + log("vfs(null) =",capi.sqlite3_vfs_find(null)) + log("vfs('kvvfs') =",capi.sqlite3_vfs_find('kvvfs')) + //const db = new oo.DB("session"); + + log("Init done. Proceed from the dev console."); + }; + + sqlite3InitModule(self.sqlite3TestModule).then(function(theModule){ + console.warn("Installing Emscripten module as global EM for dev console access."); + self.EM = theModule; + runTests(theModule); + }); +})(); diff --git a/manifest b/manifest index 23b98932b2..9ebf8cf89c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\scomments\sin\sos_kv.c.\s\sBetter\snames\sfor\sthe\skey/value\sname\sspaces. -D 2022-09-10T18:38:21.976 +C Initial\sbuild\sof\skvvfs\sin\swasm.\sIt\sloads\sbut\scannot\sfind\sthe\sVFS\sfor\sas-yet-unknown\sreasons\s(sqlite3\sshell\sworks\sfine),\sand\smost\sAPIs\sthrow\s"null\sfunction\sor\sfunction\ssignature\smismatch"\sfrom\sdeep\swithin\swasm,\spresumably\sas\sa\sside\seffect\sof\sthe\s"missing"\sVFS. +D 2022-09-12T12:39:28.819 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -474,7 +474,7 @@ F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04 F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb F ext/wasm/EXPORTED_FUNCTIONS.fiddle 7fb73f7150ab79d83bb45a67d257553c905c78cd3d693101699243f36c5ae6c3 F ext/wasm/EXPORTED_RUNTIME_METHODS.fiddle a004bd5eeeda6d3b28d16779b7f1a80305bfe009dfc7f0721b042967f0d39d02 -F ext/wasm/GNUmakefile 5359a37fc13b68fad2259228590450339a0c59687744edd0db7bb93d3b1ae2b1 +F ext/wasm/GNUmakefile 12a672ab9125dc860457c2853f7651b98517e424d7a0e9714c89b28c5ff73800 F ext/wasm/README.md 4b00ae7c7d93c4591251245f0996a319e2651361013c98d2efb0b026771b7331 F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api c5eaceabb9e759aaae7d3101a4a3e542f96ab2c99d89a80ce20ec18c23115f33 F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287 @@ -502,6 +502,9 @@ F ext/wasm/jaccwabyt/jaccwabyt.js 99b424b4d467d4544e82615b58e2fe07532a898540bf9d F ext/wasm/jaccwabyt/jaccwabyt.md 447cc02b598f7792edaa8ae6853a7847b8178a18ed356afacbdbf312b2588106 F ext/wasm/jaccwabyt/jaccwabyt_test.c 39e4b865a33548f943e2eb9dd0dc8d619a80de05d5300668e9960fff30d0d36f F ext/wasm/jaccwabyt/jaccwabyt_test.exports 5ff001ef975c426ffe88d7d8a6e96ec725e568d2c2307c416902059339c06f19 +F ext/wasm/kvvfs.make 7cc9cf10e744c3ba523c3eaf5c4af47028f3a5bb76db304ea8044a9b2a9d496f +F ext/wasm/kvvfs1.html 2acb241a6110a4ec581adbf07a23d5fc2ef9c7142aa9d60856732a102abc5016 +F ext/wasm/kvvfs1.js 461d571234244bd682725f1dd73195b1d9a7eabdd57c0181ff41dc7c55252313 F ext/wasm/testing1.html 0bf3ff224628c1f1e3ed22a2dc1837c6c73722ad8c0ad9c8e6fb9e6047667231 F ext/wasm/testing1.js cba7134901a965743fa9289d82447ab71de4690b1ee5d06f6cb83e8b569d7943 F ext/wasm/testing2.html 73e5048e666fd6fb28b6e635677a9810e1e139c599ddcf28d687c982134b92b8 @@ -571,7 +574,7 @@ F src/notify.c 89a97dc854c3aa62ad5f384ef50c5a4a11d70fcc69f86de3e991573421130ed6 F src/os.c 0eb831ba3575af5277e47f4edd14fdfc90025c67eb25ce5cda634518d308d4e9 F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 -F src/os_kv.c c658ddfb433b982afb3d12d133117e8db9eee11af33db41c30a6f30375f9b99a +F src/os_kv.c a188e92dac693b1c1b512d93b0c4dc85c1baad11e322b01121f87057996e4d11 F src/os_setup.h 0711dbc4678f3ac52d7fe736951b6384a0615387c4ba5135a4764e4e31f4b6a6 F src/os_unix.c 102f7e5c5b59c18ea3dbc929dc3be8acb3afc0e0b6ad572e032335c9c27f44f1 F src/os_win.c e9454cb141908e8eef2102180bad353a36480612d5b736e4c2bd5777d9b25a34 @@ -2001,8 +2004,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P f6632e69c2ec1a7ddc4e51f3567e3bc082ee94a6dd51fdafdc0c3bf386a32d4c -R 8cd4482ba17a8f6c143ea61b8462f46c -U drh -Z 81846bec91bdcab04bc60c9c032d039e +P 8e1652a3856765c9146cc2a7e3b598a2dc7dc84c556b35eab9a35184514384b9 +R 87fbf09a4dec22281b7328e04378fb76 +U stephan +Z bc0b4e3041260a10b10ef1c5f11f1ba3 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index c114a26d08..6d9a377576 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8e1652a3856765c9146cc2a7e3b598a2dc7dc84c556b35eab9a35184514384b9 \ No newline at end of file +1a2f24a0bdfc6eaae478916b8f4f9c6b63ead9964534fc2951fb4e995ffe61f1 \ No newline at end of file diff --git a/src/os_kv.c b/src/os_kv.c index 1412de8122..a14dc5c543 100644 --- a/src/os_kv.c +++ b/src/os_kv.c @@ -166,10 +166,6 @@ static sqlite3_io_methods kvvfs_jrnl_io_methods = { /* Forward declarations for the low-level storage engine */ #define KVSTORAGE_KEY_SZ 32 -static int kvstorageWrite(const char*, const char *zKey, const char *zData); -static int kvstorageDelete(const char*, const char *zKey); -static int kvstorageRead(const char*, const char *zKey, char *zBuf, int nBuf); - /* Expand the key name with an appropriate prefix and put the result ** zKeyOut[]. The zKeyOut[] buffer is assumed to hold at least @@ -183,6 +179,207 @@ static void kvstorageMakeKey( sqlite3_snprintf(KVSTORAGE_KEY_SZ, zKeyOut, "kvvfs-%s-%s", zClass, zKeyIn); } +#ifdef __EMSCRIPTEN__ +/* Provide Emscripten-based impls of kvstorageWrite/Read/Delete()... */ +#include +#include + +/* +** WASM_KEEP is identical to EMSCRIPTEN_KEEPALIVE but is not +** Emscripten-specific. It explicitly includes marked functions for +** export into the target wasm file without requiring explicit listing +** of those functions in Emscripten's -sEXPORTED_FUNCTIONS=... list +** (or equivalent in other build platforms). Any function with neither +** this attribute nor which is listed as an explicit export will not +** be exported from the wasm file (but may still be used internally +** within the wasm file). +** +** The functions in this file (sqlite3-wasm.c) which require exporting +** are marked with this flag. They may also be added to any explicit +** build-time export list but need not be. All of these APIs are +** intended for use only within the project's own JS/WASM code, and +** not by client code, so an argument can be made for reducing their +** visibility by not including them in any build-time export lists. +** +** 2022-09-11: it's not yet _proven_ that this approach works in +** non-Emscripten builds. If not, such builds will need to export +** those using the --export=... wasm-ld flag (or equivalent). As of +** this writing we are tied to Emscripten for various reasons +** and cannot test the library with other build environments. +*/ +#define WASM_KEEP __attribute__((used,visibility("default"))) +/* +** An internal level of indirection for accessing the static +** kvstorageMakeKey() from EM_JS()-generated functions. This must be +** made available for export via Emscripten but is not intended to be +** used from client code. If called with a NULL zKeyOut it is a no-op. +** It returns KVSTORAGE_KEY_SZ, so JS code (which cannot see that +** constant) may call it with NULL arguments to get the size of the +** allocation they'll need for a kvvfs key. +** +** Maintenance reminder: Emscripten will install this in the Module +** init scope and will prefix its name with "_". +*/ +WASM_KEEP +int sqlite3_wasm__kvvfsMakeKey(const char *zClass, const char *zKeyIn, + char *zKeyOut){ + if( 0!=zKeyOut ) kvstorageMakeKey(zClass, zKeyIn, zKeyOut); + return KVSTORAGE_KEY_SZ; +} +/* +** Internal helper for kvstorageWrite/Read/Delete() which creates a +** storage key for the given zClass/zKeyIn combination. Returns a +** pointer to the key: a C string allocated on the WASM stack, or 0 if +** allocation fails. It is up to the caller to save/restore the stack +** before/after this operation. +*/ +EM_JS(const char *, kvstorageMakeKeyOnJSStack, + (const char *zClass, const char *zKeyIn),{ + if( 0==zClass || 0==zKeyIn) return 0; + const zXKey = stackAlloc(_sqlite3_wasm__kvvfsMakeKey(0,0,0)); + if(zXKey) _sqlite3_wasm__kvvfsMakeKey(zClass, zKeyIn, zXKey); + return zXKey; +}); + +/* +** JS impl of kvstorageWrite(). Main docs are in the C impl. This impl +** writes zData to the global sessionStorage (if zClass starts with +** 's') or localStorage, using a storage key derived from zClass and +** zKey. +*/ +EM_JS(int, kvstorageWrite, + (const char *zClass, const char *zKey, const char *zData),{ + const stack = stackSave(); + try { + const zXKey = kvstorageMakeKeyOnJSStack(zClass,zKey); + if(!zXKey) return 1/*OOM*/; + const jKey = UTF8ToString(zXKey); + /** + We could simplify this function and eliminate the + kvstorageMakeKey() symbol acrobatics if we'd simply hard-code + the key algo into the 3 functions which need it: + + const jKey = "kvvfs-"+UTF8ToString(zClass)+"-"+UTF8ToString(zKey); + */ + ((115/*=='s'*/===getValue(zClass)) + ? sessionStorage : localStorage).setItem(jKey, UTF8ToString(zData)); + }catch(e){ + console.error("kvstorageWrite()",e); + return 1; // Can't access SQLITE_xxx from here + }finally{ + stackRestore(stack); + } + return 0; +}); + +/* +** JS impl of kvstorageDelete(). Main docs are in the C impl. This +** impl generates a key derived from zClass and zKey, and removes the +** matching entry (if any) from global sessionStorage (if zClass +** starts with 's') or localStorage. +*/ +EM_JS(int, kvstorageDelete, + (const char *zClass, const char *zKey),{ + const stack = stackSave(); + try { + const zXKey = kvstorageMakeKeyOnJSStack(zClass,zKey); + if(!zXKey) return 1/*OOM*/; + _sqlite3_wasm__kvvfsMakeKey(zClass, zKey, zXKey); + const jKey = UTF8ToString(zXKey); + ((115/*=='s'*/===getValue(zClass)) + ? sessionStorage : localStorage).removeItem(jKey); + }catch(e){ + console.error("kvstorageDelete()",e); + return 1; + }finally{ + stackRestore(stack); + } + return 0; +}); + +/* +** JS impl of kvstorageRead(). Main docs are in the C impl. This impl +** reads its data from the global sessionStorage (if zClass starts +** with 's') or localStorage, using a storage key derived from zClass +** and zKey. +*/ +EM_JS(int, kvstorageRead, + (const char *zClass, const char *zKey, char *zBuf, int nBuf),{ + const stack = stackSave(); + try { + const zXKey = kvstorageMakeKeyOnJSStack(zClass,zKey); + if(!zXKey) return -3/*OOM*/; + const jKey = UTF8ToString(zXKey); + const jV = ((115/*=='s'*/===getValue(zClass)) + ? sessionStorage : localStorage).getItem(jKey); + if(!jV) return -1; + const nV = jV.length /* Note that we are relying 100% on v being + ASCII so that jV.length is equal to the + C-string's byte length. */; + if(nBuf<=0) return nV; + else if(1===nBuf){ + setValue(zBuf, 0); + return nV; + } + const zV = allocateUTF8OnStack(jV); + if(nBuf > nV + 1) nBuf = nV + 1; + HEAPU8.copyWithin(zBuf, zV, zV + nBuf - 1); + setValue( zBuf + nBuf - 1, 0 ); + return nBuf - 1; + }catch(e){ + console.error("kvstorageRead()",e); + return -2; + }finally{ + stackRestore(stack); + } +}); + +/* +** This function exists for (1) WASM testing purposes and (2) as a +** hook to get Emscripten to export several EM_JS()-generated +** functions (if we don't reference them from exported C functions +** then they get stripped away at build time). It is not part of the +** public API and its signature and semantics may change at any time. +** It's not even part of the private API, for that matter - it's part +** of the Emscripten C/JS/WASM glue. +*/ +WASM_KEEP +int sqlite3__wasm_emjs_kvvfs(int whichOp){ + int rc = 0; + const char * zClass = + "sezzion" /*don't collide with "session" records!*/; + const char * zKey = "hello"; + switch( whichOp ){ + case 0: break; + case 1: + kvstorageWrite(zClass, zKey, "world"); + break; + case 2: { + char buffer[128] = {0}; + char * zBuf = &buffer[0]; + rc = kvstorageRead(zClass, zKey, zBuf, (int)sizeof(buffer)); + emscripten_console_logf("kvstorageRead()=%d %s\n", rc, zBuf); + break; + } + case 3: + kvstorageDelete(zClass, zKey); + break; + case 4: + kvstorageMakeKeyOnJSStack(0,0); + break; + default: break; + } + return rc; +} + +#undef WASM_KEEP +#else /* end ifdef __EMSCRIPTEN__ */ +/* Forward declarations for the low-level storage engine +*/ +static int kvstorageWrite(const char*, const char *zKey, const char *zData); +static int kvstorageDelete(const char*, const char *zKey); +static int kvstorageRead(const char*, const char *zKey, char *zBuf, int nBuf); + /* Write content into a key. zClass is the particular namespace of the ** underlying key/value store to use - either "local" or "session". ** @@ -277,6 +474,7 @@ static int kvstorageRead( return (int)n; } } +#endif /* ifdef __EMSCRIPTEN__ */ /****** Utility subroutines ************************************************/ From 6b013afb8880da7f755433ffd3387722d2b92a10 Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 12 Sep 2022 12:41:07 +0000 Subject: [PATCH 11/13] Fix the amalgamation so that it builds with the standard unix backend again. FossilOrigin-Name: 0adf158f4e5791339988185cc29347c75056b062e0db65b5999fdfa1f433c1ed --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/os_unix.c | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 9ebf8cf89c..3bb098086d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Initial\sbuild\sof\skvvfs\sin\swasm.\sIt\sloads\sbut\scannot\sfind\sthe\sVFS\sfor\sas-yet-unknown\sreasons\s(sqlite3\sshell\sworks\sfine),\sand\smost\sAPIs\sthrow\s"null\sfunction\sor\sfunction\ssignature\smismatch"\sfrom\sdeep\swithin\swasm,\spresumably\sas\sa\sside\seffect\sof\sthe\s"missing"\sVFS. -D 2022-09-12T12:39:28.819 +C Fix\sthe\samalgamation\sso\sthat\sit\sbuilds\swith\sthe\sstandard\sunix\sbackend\sagain. +D 2022-09-12T12:41:07.918 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -576,7 +576,7 @@ F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_kv.c a188e92dac693b1c1b512d93b0c4dc85c1baad11e322b01121f87057996e4d11 F src/os_setup.h 0711dbc4678f3ac52d7fe736951b6384a0615387c4ba5135a4764e4e31f4b6a6 -F src/os_unix.c 102f7e5c5b59c18ea3dbc929dc3be8acb3afc0e0b6ad572e032335c9c27f44f1 +F src/os_unix.c d6322b78130d995160bb9cfb7850678ad6838b08c1d13915461b33326a406c04 F src/os_win.c e9454cb141908e8eef2102180bad353a36480612d5b736e4c2bd5777d9b25a34 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c 6176d9752eb580419e8fef4592dc417a6b00ddfd43ee22f818819bf8840ceee8 @@ -2004,8 +2004,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 8e1652a3856765c9146cc2a7e3b598a2dc7dc84c556b35eab9a35184514384b9 -R 87fbf09a4dec22281b7328e04378fb76 -U stephan -Z bc0b4e3041260a10b10ef1c5f11f1ba3 +P 1a2f24a0bdfc6eaae478916b8f4f9c6b63ead9964534fc2951fb4e995ffe61f1 +R fe9e8080b230bfa064abaa9f8e686ee1 +U drh +Z 78a6c00935086fa910a2a1532a85cf90 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 6d9a377576..b4f4bbf88d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1a2f24a0bdfc6eaae478916b8f4f9c6b63ead9964534fc2951fb4e995ffe61f1 \ No newline at end of file +0adf158f4e5791339988185cc29347c75056b062e0db65b5999fdfa1f433c1ed \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index fd7a50dcdb..422fb25ed1 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -87,11 +87,11 @@ /* ** standard include files. */ -#include -#include +#include /* amalgamator: keep */ +#include /* amalgamator: keep */ #include #include -#include +#include /* amalgamator: keep */ #include #include #include From 2811759d5ee88008e7e05134204c859d5f6838ca Mon Sep 17 00:00:00 2001 From: stephan Date: Mon, 12 Sep 2022 13:05:54 +0000 Subject: [PATCH 12/13] Resolve missing kvvfs JS test: sqlite3_initialize() must be called by the client in this build. Add basic sanity test of kvvfs using sessionStorage(). FossilOrigin-Name: 250a935aeb94d3fadec0d3fe22de85de4e658e2fdb3be3aa9a8bbc8f7b7d8414 --- ext/wasm/kvvfs1.js | 40 ++++++++++++++++++++++++++++++++++++---- manifest | 14 +++++++------- manifest.uuid | 2 +- 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/ext/wasm/kvvfs1.js b/ext/wasm/kvvfs1.js index a9737a565b..f56f4874e0 100644 --- a/ext/wasm/kvvfs1.js +++ b/ext/wasm/kvvfs1.js @@ -36,10 +36,42 @@ log("Loaded module:",capi.sqlite3_libversion(), capi.sqlite3_sourceid()); log("Build options:",wasm.compileOptionUsed()); self.S = sqlite3; - - log("vfs(null) =",capi.sqlite3_vfs_find(null)) - log("vfs('kvvfs') =",capi.sqlite3_vfs_find('kvvfs')) - //const db = new oo.DB("session"); + T.assert(0 === capi.sqlite3_vfs_find(null)); + S.capi.sqlite3_initialize(); + T.assert( Number.isFinite( capi.sqlite3_vfs_find(null) ) ); + const stores = { + local: localStorage, + session: sessionStorage + }; + const cleanupStore = function(n){ + const s = stores[n]; + const isKv = (key)=>key.startsWith('kvvfs-'+n); + let i, k, toRemove = []; + for( i = 0; (k = s.key(i)); ++i) { + if(isKv(k)) toRemove.push(k); + } + toRemove.forEach((k)=>s.removeItem(k)); + }; + const dbStorage = 1 ? 'session' : 'local'; + const db = new oo.DB(dbStorage); + try { + db.exec("create table if not exists t(a)"); + if(undefined===db.selectValue("select a from t limit 1")){ + log("New db. Populating.."); + db.exec("insert into t(a) values(1),(2),(3)"); + }else{ + log("Found existing table data:"); + db.exec({ + sql: "select * from t order by a", + rowMode: 0, + callback: function(v){log(v)} + }); + } + }finally{ + const n = db.filename; + db.close(); + //cleanupStore(n); + } log("Init done. Proceed from the dev console."); }; diff --git a/manifest b/manifest index 3bb098086d..23b3e750c1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sthe\samalgamation\sso\sthat\sit\sbuilds\swith\sthe\sstandard\sunix\sbackend\sagain. -D 2022-09-12T12:41:07.918 +C Resolve\smissing\skvvfs\sJS\stest:\ssqlite3_initialize()\smust\sbe\scalled\sby\sthe\sclient\sin\sthis\sbuild.\sAdd\sbasic\ssanity\stest\sof\skvvfs\susing\ssessionStorage(). +D 2022-09-12T13:05:54.108 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -504,7 +504,7 @@ F ext/wasm/jaccwabyt/jaccwabyt_test.c 39e4b865a33548f943e2eb9dd0dc8d619a80de05d5 F ext/wasm/jaccwabyt/jaccwabyt_test.exports 5ff001ef975c426ffe88d7d8a6e96ec725e568d2c2307c416902059339c06f19 F ext/wasm/kvvfs.make 7cc9cf10e744c3ba523c3eaf5c4af47028f3a5bb76db304ea8044a9b2a9d496f F ext/wasm/kvvfs1.html 2acb241a6110a4ec581adbf07a23d5fc2ef9c7142aa9d60856732a102abc5016 -F ext/wasm/kvvfs1.js 461d571234244bd682725f1dd73195b1d9a7eabdd57c0181ff41dc7c55252313 +F ext/wasm/kvvfs1.js 46afaf4faba041bf938355627bc529854295e561f49db3a240c914e75a529338 F ext/wasm/testing1.html 0bf3ff224628c1f1e3ed22a2dc1837c6c73722ad8c0ad9c8e6fb9e6047667231 F ext/wasm/testing1.js cba7134901a965743fa9289d82447ab71de4690b1ee5d06f6cb83e8b569d7943 F ext/wasm/testing2.html 73e5048e666fd6fb28b6e635677a9810e1e139c599ddcf28d687c982134b92b8 @@ -2004,8 +2004,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 1a2f24a0bdfc6eaae478916b8f4f9c6b63ead9964534fc2951fb4e995ffe61f1 -R fe9e8080b230bfa064abaa9f8e686ee1 -U drh -Z 78a6c00935086fa910a2a1532a85cf90 +P 0adf158f4e5791339988185cc29347c75056b062e0db65b5999fdfa1f433c1ed +R 034fe3ea9e2b85698d729ef37913abeb +U stephan +Z 428f2bf7fe12828b5f66501dd0945c6a # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index b4f4bbf88d..50486e9917 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0adf158f4e5791339988185cc29347c75056b062e0db65b5999fdfa1f433c1ed \ No newline at end of file +250a935aeb94d3fadec0d3fe22de85de4e658e2fdb3be3aa9a8bbc8f7b7d8414 \ No newline at end of file From 1ad51ffe21adb0924f4ad7375d94fb5e2e7cbbee Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 12 Sep 2022 15:59:35 +0000 Subject: [PATCH 13/13] Fix uninitialized variable in rollback-journal processing in os_kv.c FossilOrigin-Name: e49682c5eac91958f143e639c5656ca54560d14f5805d514bf4aa0c206e63844 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/os_kv.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 23b3e750c1..601e86a73d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Resolve\smissing\skvvfs\sJS\stest:\ssqlite3_initialize()\smust\sbe\scalled\sby\sthe\sclient\sin\sthis\sbuild.\sAdd\sbasic\ssanity\stest\sof\skvvfs\susing\ssessionStorage(). -D 2022-09-12T13:05:54.108 +C Fix\suninitialized\svariable\sin\srollback-journal\sprocessing\sin\sos_kv.c +D 2022-09-12T15:59:35.676 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -574,7 +574,7 @@ F src/notify.c 89a97dc854c3aa62ad5f384ef50c5a4a11d70fcc69f86de3e991573421130ed6 F src/os.c 0eb831ba3575af5277e47f4edd14fdfc90025c67eb25ce5cda634518d308d4e9 F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 -F src/os_kv.c a188e92dac693b1c1b512d93b0c4dc85c1baad11e322b01121f87057996e4d11 +F src/os_kv.c 2b4c04a470c05fe95a84d2ba3a5eb4874f0dbaa12da3a47f221ee3beec7eeda0 F src/os_setup.h 0711dbc4678f3ac52d7fe736951b6384a0615387c4ba5135a4764e4e31f4b6a6 F src/os_unix.c d6322b78130d995160bb9cfb7850678ad6838b08c1d13915461b33326a406c04 F src/os_win.c e9454cb141908e8eef2102180bad353a36480612d5b736e4c2bd5777d9b25a34 @@ -2004,8 +2004,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 0adf158f4e5791339988185cc29347c75056b062e0db65b5999fdfa1f433c1ed -R 034fe3ea9e2b85698d729ef37913abeb -U stephan -Z 428f2bf7fe12828b5f66501dd0945c6a +P 250a935aeb94d3fadec0d3fe22de85de4e658e2fdb3be3aa9a8bbc8f7b7d8414 +R b0d44b8764d44e0d25567b7049186ee6 +U drh +Z b805cc7ee3bf0477637e784d78058472 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 50486e9917..3839586165 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -250a935aeb94d3fadec0d3fe22de85de4e658e2fdb3be3aa9a8bbc8f7b7d8414 \ No newline at end of file +e49682c5eac91958f143e639c5656ca54560d14f5805d514bf4aa0c206e63844 \ No newline at end of file diff --git a/src/os_kv.c b/src/os_kv.c index a14dc5c543..9260852dbe 100644 --- a/src/os_kv.c +++ b/src/os_kv.c @@ -583,7 +583,7 @@ static void kvvfsDecodeJournal( const char *zTxt, /* Text encoding. Zero-terminated */ int nTxt /* Bytes in zTxt, excluding zero terminator */ ){ - unsigned int n; + unsigned int n = 0; int c, i, mult; i = 0; mult = 1;