]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Improvements to logging. Better log-file names. Log files are in a
authordrh <>
Wed, 7 Jan 2026 18:45:23 +0000 (18:45 +0000)
committerdrh <>
Wed, 7 Jan 2026 18:45:23 +0000 (18:45 +0000)
subdirectory named after the database.  Only connections that write to
the database create logs.  Better documentation in the header comment.

FossilOrigin-Name: 5b1cf0fe73ba1a40fe4cd8f5f6e8ee5b471f96b60aff52c03c045ad6514c363a

ext/misc/tmstmpvfs.c
manifest
manifest.uuid

index 1d52c0e95816aa5533f999373d47ac7df113d75f..739c3e614d175b6ab813e984c63acb08263619c8 100644 (file)
 ** the WAL file for databases in WAL mode, or as the database file itself
 ** is modified in rollback modes.
 **
-** The VFS also generates log-files with names of the form:
+** The VFS also tries to generate log-files with names of the form:
 **
-**         $(DATABASE)-$(TIME)$(PID)$(ID).tmstmp
+**         $(DATABASE)-tmstmp/$(TIME)-$(PID)-$(ID)
 **
-** In the same directory as the database file.  This log file contain one
-** 16-byte record for various events, such as opening or close of the
-** database or WAL file, writes to the WAL file, checkpoints, and similar.
-** There is one log file for each open database connection.
+** Log files are only generated if directory $(DATABASE)-tmstmp exists.
+** The name of each log file is the current unix-epoch time in millisecond,
+** the process ID, and a random 32-bit value (to disambiguate multiple
+** connections from the same process) separated by spaces.  The log file
+** contains one 16-byte record for various events, such as opening or close
+** of the database or WAL file, writes to the WAL file, checkpoints, and
+** similar.   The logfile is only generated if the connection attempts to
+** modify the database.  There is a separate log file for each open database
+** connection.
 **
 ** COMPILING
 **
 ** correct order so that it sequences itself into the default VFS
 ** Shim stack in the right order.
 **
+** An application can see if the tmstmpvfs is being used by examining
+** the results from SQLITE_FCNTL_VFSNAME (or the .vfsname command in
+** the CLI).  If the answer include "tmstmp", then this VFS is being
+** used.
+**
 ** USING
 **
 ** Open database connections using the sqlite3_open() or 
 **
 ** LOGGING
 **
-** Every open VFS creates a log file.  The Database connection and the
-** WAL connection are both logged to the same file.  If the name of the
-** database file is BASE then the logfile is named something like:
+** An open database connection that attempts to write to the database
+** will create a log file if a directory name $(DATABASE)-tmstmp exists.
+** The name of the log file is:
 **
-**     $(DATABASE)-$(TIMESTAMP)$(PID)$(RANDOM)
+**         $(TIME)-$(PID)-$(RANDOM)
 **
-** Where DATABASE is the database filename, TIMESTAMP is the millisecond
-** resolution timestamp of when the database connection was opened, PID
-** is the process ID of the process that opened the database connection,
-** and RANDOM is 32-bits of randomness used to distinguish between multiple
-** connections being opened on the same database from the same process.
-** The last three values are all expressed in hexadecimal and are joined
-** together without punctuation.
+** Where TIME is the number of milliseconds since 1970, PID is the process
+** ID, and RANDOM is a 32-bit random number.  All values are expressed
+** in hexadecimal.
 **
 ** The log consists of 16-byte records.  Each record consists of five
 ** unsigned integers:
 ** in milliseconds since 1970-01-01.  (6 bytes is sufficient for timestamps
 ** for almost 9000 years.) Opcodes are defined by the ELOG_* #defines
 ** below.
+**
+**   ELOG_OPEN_DB         "Open a connection to the database file"
+**                        op = 0x01
+**                        a2 = process-ID
+**
+**   ELOG_OPEN_WAL        "Open a connection to the -wal file"
+**                        op = 0x02
+**                        a2 = process-ID
+**
+**   ELOG_WAL_PAGE        "New page added to the WAL file"
+**                        op = 0x03
+**                        a1 = 1 if last page of a txn.  0 otherwise.
+**                        a2 = page number in the DB file
+**                        a3 = frame number in the WAL file
+**
+**   ELOG_DB_PAGE         "Database page updated using rollback mode"
+**                        op = 0x04
+**                        a2 = page number in the DB file
+**
+**   ELOG_CKPT_START      "Start of a checkpoint operation"
+**                        op = 0x05
+**
+**   ELOG_CKPT_PAGE       "Page xfer from WAL to database"
+**                        op = 0x06
+**                        a2 = database page number
+**
+**   ELOG_CKPT_END        "Start of a checkpoint operation"
+**                        op = 0x07
+**
+**   ELOG_WAL_RESET       "WAL file header overwritten"
+**                        op = 0x08
+**                        a3 = Salt1 value
+**
+**   ELOG_CLOSE_WAL       "Close the WAL file connection"
+**                        op = 0x0e
+**
+**   ELOG_CLOSE_DB        "Close the DB connection"
+**                        op = 0x0f
 */
 #if defined(SQLITE_AMALGAMATION) && !defined(SQLITE_TMSTMPVFS_STATIC)
 # define SQLITE_TMSTMPVFS_STATIC
 */
 typedef struct sqlite3_vfs TmstmpVfs;
 typedef struct TmstmpFile TmstmpFile;
+typedef struct TmstmpLog TmstmpLog;
 
 /*
 ** Bytes of reserved space used by this extension
@@ -196,6 +241,14 @@ typedef struct TmstmpFile TmstmpFile;
 #define ORIGVFS(p)  ((sqlite3_vfs*)((p)->pAppData))
 #define ORIGFILE(p) ((sqlite3_file*)(((TmstmpFile*)(p))+1))
 
+/* Information for the tmstmp log file. */
+struct  TmstmpLog {
+  char *zLogname;        /* Log filename */
+  FILE *log;             /* Open log file */
+  int n;                 /* Bytes of a[] used */
+  unsigned char a[16*6]; /* Buffered header for the log */
+};
+
 /* An open WAL file */
 struct TmstmpFile {
   sqlite3_file base;     /* IO methods */
@@ -209,7 +262,7 @@ struct TmstmpFile {
   u8 isCommit;           /* Last WAL frame header was a transaction commit */
   u8 hasCorrectReserve;  /* File has the correct reserve size */
   u8 inCkpt;             /* True if in a checkpoint */
-  FILE *log;             /* Write logging records on this file.  DB only */
+  TmstmpLog *pLog;       /* Log file */
   TmstmpFile *pPartner;  /* DB->WAL or WAL->DB mapping */
   sqlite3_int64 iOfst;   /* Offset of last WAL frame header */
   sqlite3_vfs *pSubVfs;  /* Underlying VFS */
@@ -323,7 +376,7 @@ static const sqlite3_io_methods tmstmp_io_methods = {
 */
 static void tmstmpPutTS(TmstmpFile *p, unsigned char *aOut){
   sqlite3_uint64 tm = 0;
-  p->pSubVfs->xCurrentTimeInt64(p->pSubVfs, &tm);
+  p->pSubVfs->xCurrentTimeInt64(p->pSubVfs, (sqlite3_int64*)&tm);
   aOut[0] = (tm>>40)&0xff;
   aOut[1] = (tm>>32)&0xff;
   aOut[2] = (tm>>24)&0xff;
@@ -348,6 +401,30 @@ static void tmstmpPutU32(u32 v, unsigned char *a){
   a[3] = v & 0xff;
 }
 
+/* Free a TmstmpLog object */
+static void tmstmpLogFree(TmstmpLog *pLog){
+  if( pLog==0 ) return;
+  sqlite3_free(pLog->zLogname);
+  sqlite3_free(pLog);
+}
+
+/* Flush log content.  Open the file if necessary. Return the
+** number of errors. */
+static int tmstmpLogFlush(TmstmpFile *p){
+  TmstmpLog *pLog = p->pLog;
+  assert( pLog!=0 );
+  if( pLog->log==0 ){
+    pLog->log = fopen(pLog->zLogname, "wb");
+    if( pLog->log==0 ){
+      tmstmpLogFree(pLog);
+      p->pLog = 0;
+      return 1;
+    }
+  }
+  (void)fwrite(pLog->a, pLog->n, 1, pLog->log);
+  pLog->n = 0;
+  return 0;
+}
 
 /*
 ** Write a record onto the event log
@@ -359,19 +436,28 @@ static void tmstmpEvent(
   u32 a2,
   u32 a3
 ){
-  unsigned char a[16];
+  unsigned char *a;
+  TmstmpLog *pLog;
   if( p->isWal ){
     p = p->pPartner;
     assert( p!=0 );
     assert( p->isDb );
   }
-  if( p->log==0 ) return;
+  pLog = p->pLog;
+  if( pLog==0 ) return;
+  if( pLog->n >= (int)sizeof(pLog->a) ){
+    if( tmstmpLogFlush(p) ) return;
+  }
+  a = pLog->a + pLog->n;
   a[0] = op;
   a[1] = a1;
   tmstmpPutTS(p, a+2);
   tmstmpPutU32(a2, a+8);
   tmstmpPutU32(a3, a+12);
-  (void)fwrite(a, sizeof(a), 1, p->log);
+  pLog->n += 16;
+  if( pLog->log || (op>=ELOG_WAL_PAGE && op<=ELOG_WAL_RESET) ){
+    (void)tmstmpLogFlush(p);
+  }
 }
 
 /*
@@ -382,7 +468,7 @@ static int tmstmpClose(sqlite3_file *pFile){
   if( p->hasCorrectReserve ){
     tmstmpEvent(p, p->isDb ? ELOG_CLOSE_DB : ELOG_CLOSE_WAL, 0, 0, 0);
   }
-  if( p->log ) fclose(p->log);
+  tmstmpLogFree(p->pLog);
   if( p->pPartner ){
     assert( p->pPartner->pPartner==p );
     p->pPartner->pPartner = 0;
@@ -643,10 +729,6 @@ static int tmstmpOpen(
   sqlite3_file *pSubFile;
   sqlite3_vfs *pSubVfs;
   int rc;
-  sqlite3_uint64 r1;
-  u32 r2;
-  u32 pid;
-  char *zLogName;
   
   pSubVfs = ORIGVFS(pVfs);
   if( (flags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_WAL))==0 ){
@@ -679,16 +761,24 @@ static int tmstmpOpen(
     p->pPartner = pDb;
     pDb->pPartner = p;
   }else{
+    sqlite3_uint64 r1;
+    u32 r2;
+    u32 pid;
+    TmstmpLog *pLog;
+
     p->isDb = 1;
     r1 = 0;
-    p->pSubVfs->xCurrentTimeInt64(p->pSubVfs, &r1);
+    pLog = sqlite3_malloc64( sizeof(TmstmpLog) );
+    if( pLog==0 ){
+      return SQLITE_NOMEM;
+    }
+    memset(pLog, 0, sizeof(pLog[0]));
+    p->pLog = pLog;
+    p->pSubVfs->xCurrentTimeInt64(p->pSubVfs, (sqlite3_int64*)&r1);
     sqlite3_randomness(sizeof(r2), &r2);
     pid = GETPID;
-    zLogName = sqlite3_mprintf("%s-%llx%08x%08x.tmstmp", zName, r1, pid, r2);
-    if( zLogName ){
-      p->log = fopen(zLogName, "wb");
-      sqlite3_free(zLogName);
-    }
+    pLog->zLogname = sqlite3_mprintf("%s-tmstmp/%llx-%08x-%08x",
+                                     zName, r1, pid, r2);
   }
   tmstmpEvent(p, p->isWal ? ELOG_OPEN_WAL : ELOG_OPEN_DB, 0, GETPID, 0);
 
@@ -813,6 +903,7 @@ int sqlite3_tmstmpvfs_init(
   int rc;
   SQLITE_EXTENSION_INIT2(pApi);
   (void)pzErrMsg; /* not used */
+  (void)db;       /* not used */
   rc = tmstmpRegisterVfs();
   if( rc==SQLITE_OK ) rc = SQLITE_OK_LOAD_PERMANENTLY;
   return rc;
index 4fd87e8e0765b70d725620c7a427623522dcbb70..3591bb9662cf990b75e490c4e6676d1c49acb06a 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Documentation\stweaks.
-D 2026-01-06T21:18:42.496
+C Improvements\sto\slogging.\s\sBetter\slog-file\snames.\s\sLog\sfiles\sare\sin\sa\nsubdirectory\snamed\safter\sthe\sdatabase.\s\sOnly\sconnections\sthat\swrite\sto\nthe\sdatabase\screate\slogs.\s\sBetter\sdocumentation\sin\sthe\sheader\scomment.
+D 2026-01-07T18:45:23.292
 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -402,7 +402,7 @@ F ext/misc/sqlite3_stdio.h 27a4ecea47e61bc9574ccdf2806f468afe23af2f95028c9b689bf
 F ext/misc/stmt.c b090086cd6bd6281c21271d38d576eeffe662f0e6b67536352ce32bbaa438321
 F ext/misc/stmtrand.c 59cffa5d8e158943ff1ce078956d8e208e8c04e67307e8f249dece2436dcb7fc
 F ext/misc/templatevtab.c 10f15b165b95423ddef593bc5dcb915ec4eb5e0f1066d585e5435a368b8bc22b
-F ext/misc/tmstmpvfs.c 05e80557222c648bc676e599343d8d33f9e2d4801476592271ffb580cebbab69
+F ext/misc/tmstmpvfs.c 2d2f92a85e9a55ae3abd9d66d1638096fad30ebc0bfcf9431f3370e34b550a0b
 F ext/misc/totype.c ba11aac3c0b52c685bd25aa4e0f80c41c624fb1cc5ab763250e09ddc762bc3a8
 F ext/misc/uint.c 327afc166058acf566f33a15bf47c869d2d3564612644d9ff81a23efc8b36039
 F ext/misc/unionvtab.c 716d385256d5fb4beea31b0efede640807e423e85c9784d21d22f0cce010a785
@@ -2190,8 +2190,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
 F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
 F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
-P f087c6c0cdd542ec24b4668fff9cb434f46caf554f8856a49fd062ab3f72014e
-R 877edad71f16bed2b67db9da4be832cc
+P b10b0aa7658a04b9354ca09a2dcb807eecd9421451537f3230ba5f47269ec5c1
+R be812e8a766a17494547e7727dd97033
 U drh
-Z ee16842ec8595f9621e28d3f57b47daa
+Z 8f9cae05ac0b26a0b4ebaaea59bfec9f
 # Remove this line to create a well-formed Fossil manifest.
index 3eb40871042b81e70d3ea6b49198ca0fe85d7979..3ee21c9f490cbcc8858e550afc8d4f528672123e 100644 (file)
@@ -1 +1 @@
-b10b0aa7658a04b9354ca09a2dcb807eecd9421451537f3230ba5f47269ec5c1
+5b1cf0fe73ba1a40fe4cd8f5f6e8ee5b471f96b60aff52c03c045ad6514c363a