]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Code snapshot. Completely untested. Probably does not compile.
authordrh <>
Thu, 8 Sep 2022 15:48:01 +0000 (15:48 +0000)
committerdrh <>
Thu, 8 Sep 2022 15:48:01 +0000 (15:48 +0000)
FossilOrigin-Name: 51e267696d25f2f83b5bb847d5254ab15573ef1a16ea3d7dd8279c73c0bee539

ext/misc/vfskv.c
manifest
manifest.uuid

index 4d8d797a4f83d3f51001817bdf6d068b12c639bc..0773f7094523ed4006b08da60f311e92ae55accd 100644 (file)
@@ -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<nData; k++){}
@@ -316,6 +324,8 @@ static char kvvfsHexToBinary(char c){
 /*
 ** Decode the text encoding back to binary.  The binary content is
 ** written into pOut, which must be at least nOut bytes in length.
+**
+** The return value is the number of bytes actually written into aOut[].
 */
 static int kvvfsDecode(const char *aIn, char *aOut, int nOut){
   char *aOut;
@@ -326,8 +336,10 @@ static int kvvfsDecode(const char *aIn, char *aOut, int nOut){
   while( (c = aIn[i])!=0 ){
     if( c>='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( n<pFile->nJrnl ){
+    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( n<iAmt ){
+    memset(zBuf+n, 0, iAmt-n);
+    return SQLITE_IOERR_SHORT_READ;
+  }
+  return SQLITE_OK;
 }
 
 
@@ -407,6 +486,21 @@ static int kvvfsRead(
   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.
 */
@@ -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->nJrnl<iEnd ){
+    char *aNew = sqlite3_realloc(pFile->aJrnl, iEnd);
+    if( aNew==0 ){
+      return SQLITE_IOERR_NOMEM;
+    }
+    pFile->aJrnl = aNew;
+    if( pFile->nJrnl<iOfst ){
+      memset(pFile->aJrnl+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;
 }
 
index dfddb1fb37a6f5af44b1ffeea6bee82057c16707..f872ac33492c34693525b33c60d6d56860db51ae 100644 (file)
--- 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.
index d9d59da7ca291da93c129ef58bd92a9c30c6c102..8e900ee9c5080f6d11f463b97a57fe8431a9a5da 100644 (file)
@@ -1 +1 @@
-f9c89ee8d5ef46342bea78fa8d4da058d9ea628183ec985642bbda1cdfeacd5f
\ No newline at end of file
+51e267696d25f2f83b5bb847d5254ab15573ef1a16ea3d7dd8279c73c0bee539
\ No newline at end of file