]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Comment and stylistic changes to the appendvfs.c implementation. appendvfs_fix
authordrh <>
Tue, 16 Mar 2021 14:12:26 +0000 (14:12 +0000)
committerdrh <>
Tue, 16 Mar 2021 14:12:26 +0000 (14:12 +0000)
FossilOrigin-Name: 25c3186aa143328157fb506a29802e87099cd14be4fa218230484a3212f20621

ext/misc/appendvfs.c
manifest
manifest.uuid

index 477e1eafc62b599a2517cbe315a90de16e43072c..6975a6abff4e447129904bc4433ba72f57d13bac 100644 (file)
@@ -38,8 +38,8 @@
 **  (5)  Otherwise, SQLITE_CANTOPEN is returned.
 **
 ** To avoid unnecessary complications with the PENDING_BYTE, the size of
-** the file containing the database is limited to 1GB. (1000013824 bytes)
-** This VFS will not read or write past the 1GB mark.  This restriction
+** the file containing the database is limited to 1GiB. (1073741824 bytes)
+** This VFS will not read or write past the 1GiB mark.  This restriction
 ** might be lifted in future versions.  For now, if you need a larger
 ** database, then keep it in a separate file.
 **
@@ -68,14 +68,16 @@ SQLITE_EXTENSION_INIT1
 ** Maximum size of the combined prefix + database + append-mark.  This
 ** must be less than 0x40000000 to avoid locking issues on Windows.
 */
-#define APND_MAX_SIZE  (65536*15259)
+#define APND_MAX_SIZE  (0x40000000)
 
 /*
-** Size of storage page upon which to align appendvfs portion.
+** Try to align the database to an even multiple of APND_ROUNDUP bytes.
 */
-#ifndef APND_ROUNDUP_BITS
-#define APND_ROUNDUP_BITS 12
+#ifndef APND_ROUNDUP
+#define APND_ROUNDUP 4096
 #endif
+#define APND_ALIGN_MASK         ((sqlite3_int64)(APND_ROUNDUP-1))
+#define APND_START_ROUNDUP(fsz) (((fsz)+APND_ALIGN_MASK) & ~APND_ALIGN_MASK)
 
 /*
 ** Forward declaration of objects used by this utility
@@ -89,43 +91,45 @@ typedef struct ApndFile ApndFile;
 #define ORIGVFS(p)  ((sqlite3_vfs*)((p)->pAppData))
 #define ORIGFILE(p) ((sqlite3_file*)(((ApndFile*)(p))+1))
 
-/* Invariants for an open appendvfs file:
- * Once an appendvfs file is opened, it will be in one of three states:
- * State 0: Never written. Underlying file (if any) is unaltered.
- * State 1: Append mark is persisted, content write is in progress.
- * State 2: Append mark is persisted, content writes are complete.
- * 
- * State 0 is persistent in the sense that nothing will have been done
- * to the underlying file, including any attempt to convert it to an
- * appendvfs file.
- *
- * State 1 is normally transitory. However, if a write operation ends
- * abnormally (disk full, power loss, process kill, etc.), then State 1
- * may be persistent on disk with an incomplete content write-out. This
- * is logically equivalent to an interrupted write to an ordinary file,
- * where some unknown portion of to-be-written data is persisted while
- * the remainder is not. Database integrity in such cases is maintained
- * (or not) by the same measures available for ordinary file access.
- *
- * State 2 is persistent under normal circumstances (when there is no
- * abnormal termination of a write operation such that data provided
- * to the underlying VFS write method has not yet reached storage.)
- *
- * In order to maintain the state invariant, the append mark is written
- * in advance of content writes where any part of such content would
- * overwrite an existing (or yet to be written) append mark.
- */
+/* An open appendvfs file
+**
+** An instance of this structure describes the appended database file.
+** A separate sqlite3_file object is always appended. The appended
+** sqlite3_file object (which can be accessed using ORIGFILE()) describes
+** the entire file, including the prefix, the database, and the
+** append-mark.
+**
+** The structure of an AppendVFS database is like this:
+**
+**   +-------------+---------+----------+-------------+
+**   | prefix-file | padding | database | append-mark |
+**   +-------------+---------+----------+-------------+
+**                           ^          ^
+**                           |          |
+**                         iPgOne      iMark
+**
+**
+** "prefix file" -  file onto which the database has been appended.
+** "padding"     -  zero or more bytes inserted so that "database"
+**                  starts on an APND_ROUNDUP boundary
+** "database"    -  The SQLite database file
+** "append-mark" -  The 25-byte "Start-Of-SQLite3-NNNNNNNN" that indicates
+**                  the offset from the start of prefix-file to the start
+**                  of "database".
+**
+** The size of the database is iMark - iPgOne.
+**
+** The NNNNNNNN in the "Start-Of-SQLite3-NNNNNNNN" suffix is the value
+** of iPgOne stored as a big-ending 64-bit integer.
+**
+** iMark will be the size of the underlying file minus 25 (APND_MARKSIZE).
+** Or, iMark is -1 to indicate that it has not yet been written.
+*/
 struct ApndFile {
-  /* Access to IO methods of the underlying file */
-  sqlite3_file base;
-  /* File offset to beginning of appended content (unchanging) */
-  sqlite3_int64 iPgOne;
-  /* File offset of written append-mark, or -1 if unwritten */
-  sqlite3_int64 iMark;
-  /* Whenever file is open and .iMark >= 0, and file size changes are
-   * not in progress, .iMark + sizeof(append mark) == base file size,
-   * and append file size == .iMark - .iPgOne .
-   */
+  sqlite3_file base;        /* Subclass.  MUST BE FIRST! */
+  sqlite3_int64 iPgOne;     /* Offset to the start of the database */
+  sqlite3_int64 iMark;      /* Offset of the append mark.  -1 if unwritten */
+  /* Always followed by another sqlite3_file that describes the whole file */
 };
 
 /*
@@ -221,7 +225,6 @@ static const sqlite3_io_methods apnd_io_methods = {
 ** Close an apnd-file.
 */
 static int apndClose(sqlite3_file *pFile){
-  assert((ApndFile*)pFile == ORIGFILE(pFile));
   pFile = ORIGFILE(pFile);
   return pFile->pMethods->xClose(pFile);
 }
@@ -255,9 +258,8 @@ static int apndWriteMark(
   int i = APND_MARK_FOS_SZ;
   int rc;
   assert(pFile == ORIGFILE(paf));
-  /* assert(pFile == paf->base); */
   memcpy(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ);
-  while (--i >= 0) {
+  while( --i >= 0 ){
     a[APND_MARK_PREFIX_SZ+i] = (unsigned char)(iPgOne & 0xff);
     iPgOne >>= 8;
   }
@@ -282,12 +284,10 @@ static int apndWrite(
   sqlite_int64 iWriteEnd = iOfst + iAmt;
   if( iWriteEnd>=APND_MAX_SIZE ) return SQLITE_FULL;
   pFile = ORIGFILE(pFile);
-  /* assert(pFile == paf->base); */
   /* If append-mark is absent or will be overwritten, write it. */
   if( paf->iMark < 0 || paf->iPgOne + iWriteEnd > paf->iMark ){
     int rc = apndWriteMark(paf, pFile, iWriteEnd);
-    if( SQLITE_OK!=rc )
-      return rc;
+    if( SQLITE_OK!=rc ) return rc;
   }
   return pFile->pMethods->xWrite(pFile, zBuf, iAmt, paf->iPgOne+iOfst);
 }
@@ -299,8 +299,7 @@ static int apndTruncate(sqlite3_file *pFile, sqlite_int64 size){
   ApndFile *paf = (ApndFile *)pFile;
   pFile = ORIGFILE(pFile);
   /* The append mark goes out first so truncate failure does not lose it. */
-  if( SQLITE_OK!=apndWriteMark(paf, pFile, size) )
-    return SQLITE_IOERR;
+  if( SQLITE_OK!=apndWriteMark(paf, pFile, size) ) return SQLITE_IOERR;
   /* Truncate underlying file just past append mark */
   return pFile->pMethods->xTruncate(pFile, paf->iMark+APND_MARK_SIZE);
 }
@@ -416,8 +415,9 @@ static int apndFetch(
   void **pp
 ){
   ApndFile *p = (ApndFile *)pFile;
-  if( p->iMark < 0 || iOfst+iAmt > p->iMark)
+  if( p->iMark < 0 || iOfst+iAmt > p->iMark ){
     return SQLITE_IOERR; /* Cannot read what is not yet there. */
+  }
   pFile = ORIGFILE(pFile);
   return pFile->pMethods->xFetch(pFile, iOfst+p->iPgOne, iAmt, pp);
 }
@@ -468,14 +468,18 @@ static int apndIsAppendvfsDatabase(sqlite3_int64 sz, sqlite3_file *pFile){
   char zHdr[16];
   sqlite3_int64 iMark = apndReadMark(sz, pFile);
   if( iMark>=0 ){
-    /* If file has right end-marker, the expected odd size, and the
-     * SQLite DB type marker where the end-marker puts it, then it
-     * is an appendvfs database (to be treated as such.)
-     */
+    /* If file has the correct end-marker, the expected odd size, and the
+    ** SQLite DB type marker where the end-marker puts it, then it
+    ** is an appendvfs database.
+    */
     rc = pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), iMark);
-    if( SQLITE_OK==rc && memcmp(zHdr, apvfsSqliteHdr, sizeof(zHdr))==0
-        && (sz & 0x1ff)== APND_MARK_SIZE && sz>=512+APND_MARK_SIZE )
+    if( SQLITE_OK==rc
+     && memcmp(zHdr, apvfsSqliteHdr, sizeof(zHdr))==0
+     && (sz & 0x1ff) == APND_MARK_SIZE
+     && sz>=512+APND_MARK_SIZE
+    ){
       return 1; /* It's an appendvfs database */
+    }
   }
   return 0;
 }
@@ -497,11 +501,6 @@ static int apndIsOrdinaryDatabaseFile(sqlite3_int64 sz, sqlite3_file *pFile){
   }
 }
 
-/* Round-up used to get appendvfs portion to begin at a page boundary. */
-#define APND_ALIGN_MASK(nbits) ((1<<nbits)-1)
-#define APND_START_ROUNDUP(fsz, nbits) \
- ( ((fsz)+APND_ALIGN_MASK(nbits)) & ~(sqlite3_int64)APND_ALIGN_MASK(nbits) )
-
 /*
 ** Open an apnd file handle.
 */
@@ -519,49 +518,48 @@ static int apndOpen(
   sqlite3_int64 sz;
   if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){
     /* The appendvfs is not to be used for transient or temporary databases.
-     * Just use the base VFS open to initialize the given file object and
-     * open the underlying file. (Appendvfs is then unused for this file.)
-     */
+    ** Just use the base VFS open to initialize the given file object and
+    ** open the underlying file. (Appendvfs is then unused for this file.)
+    */
     return pBaseVfs->xOpen(pBaseVfs, zName, pFile, flags, pOutFlags);
   }
   memset(pApndFile, 0, sizeof(ApndFile));
   pFile->pMethods = &apnd_io_methods;
-  /* Record that append mark has not been written until seen otherwise. */
-  pApndFile->iMark = -1;
+  pApndFile->iMark = -1;    /* Append mark not yet written */
 
   rc = pBaseVfs->xOpen(pBaseVfs, zName, pBaseFile, flags, pOutFlags);
-  if( rc ) goto apnd_open_done;
-  rc = pBaseFile->pMethods->xFileSize(pBaseFile, &sz);
+  if( rc==SQLITE_OK ){
+    rc = pBaseFile->pMethods->xFileSize(pBaseFile, &sz);
+  }
   if( rc ){
     pBaseFile->pMethods->xClose(pBaseFile);
-    goto apnd_open_done;
+    pFile->pMethods = 0;
+    return rc;
   }
   if( apndIsOrdinaryDatabaseFile(sz, pBaseFile) ){
     /* The file being opened appears to be just an ordinary DB. Copy
-     * the base dispatch-table so this instance mimics the base VFS. 
-     */
+    ** the base dispatch-table so this instance mimics the base VFS. 
+    */
     memmove(pApndFile, pBaseFile, pBaseVfs->szOsFile);
     return SQLITE_OK;
   }
   pApndFile->iPgOne = apndReadMark(sz, pFile);
   if( pApndFile->iPgOne>=0 ){
-    /* Append mark was found, infer its offset */
-    pApndFile->iMark = sz - APND_MARK_SIZE;
-    /* pApndFile->base = pBaseFile; */
+    pApndFile->iMark = sz - APND_MARK_SIZE; /* Append mark found */
     return SQLITE_OK;
   }
   if( (flags & SQLITE_OPEN_CREATE)==0 ){
     pBaseFile->pMethods->xClose(pBaseFile);
     rc = SQLITE_CANTOPEN;
+    pFile->pMethods = 0;
+  }else{
+    /* Round newly added appendvfs location to #define'd page boundary. 
+    ** Note that nothing has yet been written to the underlying file.
+    ** The append mark will be written along with first content write.
+    ** Until then, paf->iMark value indicates it is not yet written.
+    */
+    pApndFile->iPgOne = APND_START_ROUNDUP(sz);
   }
-  /* Round newly added appendvfs location to #define'd page boundary. 
-   * Note that nothing has yet been written to the underlying file.
-   * The append mark will be written along with first content write.
-   * Until then, paf->iMark value indicates it is not yet written.
-   */
-  pApndFile->iPgOne = APND_START_ROUNDUP(sz, APND_ROUNDUP_BITS);
-apnd_open_done:
-  if( rc ) pFile->pMethods = 0;
   return rc;
 }
 
index 8697813227bf8316cd0cbd79a6743d9b512a3a1e..57975f75a1507959e12cf436b4c8f520b4b81c36 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sassert\stypo.
-D 2021-03-16T07:06:29.878
+C Comment\sand\sstylistic\schanges\sto\sthe\sappendvfs.c\simplementation.
+D 2021-03-16T14:12:26.803
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -286,7 +286,7 @@ F ext/lsm1/tool/mklsm1c.tcl f31561bbee5349f0a554d1ad7236ac1991fc09176626f529f607
 F ext/misc/README.md d6dd0fe1d8af77040216798a6a2b0c46c73054d2f0ea544fbbcdccf6f238c240
 F ext/misc/amatch.c e3ad5532799cee9a97647f483f67f43b38796b84b5a8c60594fe782a4338f358
 F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
-F ext/misc/appendvfs.c 1dad6e7dc162ad36367513c1f985a1b474c3f3517f53ba22a6a89ce980843098
+F ext/misc/appendvfs.c 390c411f14e66abb2f30b9023ebc57334288780c9388cdc6e0a25deb5d40e3b2
 F ext/misc/blobio.c a867c4c4617f6ec223a307ebfe0eabb45e0992f74dd47722b96f3e631c0edb2a
 F ext/misc/btreeinfo.c d28ce349b40054eaa9473e835837bad7a71deec33ba13e39f963d50933bfa0f9
 F ext/misc/carray.c b75a0f207391038bf1540d3372f482a95c3613511c7c474db51ede1196321c7c
@@ -1910,7 +1910,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P eae8236f3b9bc326648d1c8fca61cb3c38f821d06fe915fd0978cffeb1f6152b
-R 32b396e0e85126b3386d72e2bc6e8e4c
-U larrybr
-Z f8d4366505c35a746a63af41266ec4f5
+P 3aedf818c1cfc88ee1103abd8b20e787f6be1bcc4c9350963f0cd52f5ac04154
+R d4d0d407c45719772ccdc3772a06a769
+U drh
+Z 2e9ac8f611b5ac99207230cf538d46c9
index b9d2df6bbf29b66845afb1ed84a108d0d4c85c01..283bb8a43534bc1f80a46a1def774a5e7a61e75a 100644 (file)
@@ -1 +1 @@
-3aedf818c1cfc88ee1103abd8b20e787f6be1bcc4c9350963f0cd52f5ac04154
\ No newline at end of file
+25c3186aa143328157fb506a29802e87099cd14be4fa218230484a3212f20621
\ No newline at end of file