]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add ext/misc/vfslog.c, a VFS shim for unix that keeps a log of method calls made...
authordan <dan@noemail.net>
Thu, 10 Oct 2013 13:04:46 +0000 (13:04 +0000)
committerdan <dan@noemail.net>
Thu, 10 Oct 2013 13:04:46 +0000 (13:04 +0000)
FossilOrigin-Name: 24a827b87666670c56d68a18685f4f712852fa92

ext/misc/vfslog.c [new file with mode: 0644]
main.mk
manifest
manifest.uuid
test/permutations.test

diff --git a/ext/misc/vfslog.c b/ext/misc/vfslog.c
new file mode 100644 (file)
index 0000000..83fcff0
--- /dev/null
@@ -0,0 +1,664 @@
+/*
+** 2013-10-09
+**
+** 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 the implementation of an SQLite vfs wrapper for
+** unix that generates per-database log files of all disk activity.
+*/
+
+/*
+** This module contains code for a wrapper VFS that causes a log of
+** most VFS calls to be written into a file on disk. The log 
+** is stored as comma-separated variables.
+**
+** All calls on sqlite3_file objects are logged.
+** Additionally, calls to the xAccess(), xOpen(), and xDelete()
+** methods are logged. The other sqlite3_vfs object methods (xDlXXX,
+** xRandomness, xSleep, xCurrentTime, xGetLastError and xCurrentTimeInt64) 
+** are not logged.
+*/
+
+#include "sqlite3.h"
+#include <string.h>
+#include <assert.h>
+#include <stdio.h>
+
+/*
+** Forward declaration of objects used by this utility
+*/
+typedef struct VLogLog VLogLog;
+typedef struct VLogVfs VLogVfs;
+typedef struct VLogFile VLogFile;
+
+/* There is a pair (an array of size 2) of the following objects for
+** each database file being logged.  The first contains the filename
+** and is used to log I/O with the main database.  The second has
+** a NULL filename and is used to log I/O for the journal.  Both
+** out pointers are the same.
+*/
+struct VLogLog {
+  VLogLog *pNext;                 /* Next in a list of all active logs */
+  VLogLog **ppPrev;               /* Pointer to this in the list */
+  int nRef;                       /* Number of references to this object */
+  int nFilename;                  /* Length of zFilename in bytes */
+  char *zFilename;                /* Name of database file.  NULL for journal */
+  FILE *out;                      /* Write information here */
+};
+
+struct VLogVfs {
+  sqlite3_vfs base;               /* VFS methods */
+  sqlite3_vfs *pVfs;              /* Parent VFS */
+};
+
+struct VLogFile {
+  sqlite3_file base;              /* IO methods */
+  sqlite3_file *pReal;            /* Underlying file handle */
+  VLogLog *pLog;                  /* The log file for this file */
+};
+
+#define REALVFS(p) (((VLogVfs*)(p))->pVfs)
+
+/*
+** Methods for VLogFile
+*/
+static int vlogClose(sqlite3_file*);
+static int vlogRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
+static int vlogWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
+static int vlogTruncate(sqlite3_file*, sqlite3_int64 size);
+static int vlogSync(sqlite3_file*, int flags);
+static int vlogFileSize(sqlite3_file*, sqlite3_int64 *pSize);
+static int vlogLock(sqlite3_file*, int);
+static int vlogUnlock(sqlite3_file*, int);
+static int vlogCheckReservedLock(sqlite3_file*, int *pResOut);
+static int vlogFileControl(sqlite3_file*, int op, void *pArg);
+static int vlogSectorSize(sqlite3_file*);
+static int vlogDeviceCharacteristics(sqlite3_file*);
+
+/*
+** Methods for VLogVfs
+*/
+static int vlogOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
+static int vlogDelete(sqlite3_vfs*, const char *zName, int syncDir);
+static int vlogAccess(sqlite3_vfs*, const char *zName, int flags, int *);
+static int vlogFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
+static void *vlogDlOpen(sqlite3_vfs*, const char *zFilename);
+static void vlogDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
+static void (*vlogDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
+static void vlogDlClose(sqlite3_vfs*, void*);
+static int vlogRandomness(sqlite3_vfs*, int nByte, char *zOut);
+static int vlogSleep(sqlite3_vfs*, int microseconds);
+static int vlogCurrentTime(sqlite3_vfs*, double*);
+static int vlogGetLastError(sqlite3_vfs*, int, char *);
+static int vlogCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
+
+static VLogVfs vlog_vfs = {
+  {
+    1,                            /* iVersion */
+    0,                            /* szOsFile (set by register_vlog()) */
+    1024,                         /* mxPathname */
+    0,                            /* pNext */
+    "vfslog",                     /* zName */
+    0,                            /* pAppData */
+    vlogOpen,                     /* xOpen */
+    vlogDelete,                   /* xDelete */
+    vlogAccess,                   /* xAccess */
+    vlogFullPathname,             /* xFullPathname */
+    vlogDlOpen,                   /* xDlOpen */
+    vlogDlError,                  /* xDlError */
+    vlogDlSym,                    /* xDlSym */
+    vlogDlClose,                  /* xDlClose */
+    vlogRandomness,               /* xRandomness */
+    vlogSleep,                    /* xSleep */
+    vlogCurrentTime,              /* xCurrentTime */
+    vlogGetLastError,             /* xGetLastError */
+    vlogCurrentTimeInt64          /* xCurrentTimeInt64 */
+  },
+  0
+};
+
+static sqlite3_io_methods vlog_io_methods = {
+  1,                              /* iVersion */
+  vlogClose,                      /* xClose */
+  vlogRead,                       /* xRead */
+  vlogWrite,                      /* xWrite */
+  vlogTruncate,                   /* xTruncate */
+  vlogSync,                       /* xSync */
+  vlogFileSize,                   /* xFileSize */
+  vlogLock,                       /* xLock */
+  vlogUnlock,                     /* xUnlock */
+  vlogCheckReservedLock,          /* xCheckReservedLock */
+  vlogFileControl,                /* xFileControl */
+  vlogSectorSize,                 /* xSectorSize */
+  vlogDeviceCharacteristics,      /* xDeviceCharacteristics */
+  0,                              /* xShmMap */
+  0,                              /* xShmLock */
+  0,                              /* xShmBarrier */
+  0                               /* xShmUnmap */
+};
+
+#if SQLITE_OS_UNIX && !defined(NO_GETTOD)
+#include <sys/time.h>
+static sqlite3_uint64 vlog_time(){
+  struct timeval sTime;
+  gettimeofday(&sTime, 0);
+  return sTime.tv_usec + (sqlite3_uint64)sTime.tv_sec * 1000000;
+}
+#elif SQLITE_OS_WIN
+#include <windows.h>
+#include <time.h>
+static sqlite3_uint64 vlog_time(){
+  FILETIME ft;
+  sqlite3_uint64 u64time = 0;
+  GetSystemTimeAsFileTime(&ft);
+
+  u64time |= ft.dwHighDateTime;
+  u64time <<= 32;
+  u64time |= ft.dwLowDateTime;
+
+  /* ft is 100-nanosecond intervals, we want microseconds */
+  return u64time /(sqlite3_uint64)10;
+}
+#else
+static sqlite3_uint64 vlog_time(){
+  return 0;
+}
+#endif
+
+
+/*
+** Write a message to the log file
+*/
+static void vlogLogPrint(
+  VLogLog *pLog,                 /* The log file to write into */
+  sqlite3_int64 tStart,            /* Start time of system call */
+  sqlite3_int64 tElapse,           /* Elapse time of system call */
+  const char *zOp,                 /* Type of system call */
+  sqlite3_int64 iArg1,             /* First argument */
+  sqlite3_int64 iArg2,             /* Second argument */
+  const char *zArg3,               /* Third argument */
+  int iRes                         /* Result */
+){
+  char z1[40], z2[40], z3[70];
+  if( pLog==0 ) return;
+  if( iArg1>=0 ){
+    sqlite3_snprintf(sizeof(z1), z1, "%lld", iArg1);
+  }else{
+    z1[0] = 0;
+  }
+  if( iArg2>=0 ){
+    sqlite3_snprintf(sizeof(z2), z2, "%lld", iArg2);
+  }else{
+    z2[0] = 0;
+  }
+  if( zArg3 ){
+    sqlite3_snprintf(sizeof(z3), z3, "\"%s\"", zArg3);
+  }else{
+    z3[0] = 0;
+  }
+  fprintf(pLog->out,"%lld,%lld,%s,%d,%s,%s,%s,%d\n",
+      tStart, tElapse, zOp, pLog->zFilename==0, z1, z2, z3, iRes);
+}
+
+/*
+** List of all active log connections.  Protected by the master mutex.
+*/
+static VLogLog *allLogs = 0;
+
+/*
+** Close a VLogLog object
+*/
+static void vlogLogClose(VLogLog *p){
+  if( p ){
+    sqlite3_mutex *pMutex;
+    p->nRef--;
+    if( p->nRef>0 || p->zFilename==0 ) return;
+    pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
+    sqlite3_mutex_enter(pMutex);
+    *p->ppPrev = p->pNext;
+    if( p->pNext ) p->pNext->ppPrev = p->ppPrev;
+    sqlite3_mutex_leave(pMutex);
+    fclose(p->out);
+    sqlite3_free(p);
+  }
+}
+
+/*
+** Open a VLogLog object on the given file
+*/
+static VLogLog *vlogLogOpen(const char *zFilename){
+  int nName = (int)strlen(zFilename);
+  int isJournal = 0;
+  sqlite3_mutex *pMutex;
+  VLogLog *pLog, *pTemp;
+  if( nName>4 && strcmp(zFilename+nName-4,"-wal")==0 ){
+    return 0;  /* Do not log wal files */
+  }else
+  if( nName>8 && strcmp(zFilename+nName-8,"-journal")==0 ){
+    nName -= 8;
+    isJournal = 1;
+  }else if( nName>12 
+         && sqlite3_strglob("-mj??????9??", zFilename+nName-12)==0 ){
+    return 0;  /* Do not log master journal files */
+  }
+  pTemp = sqlite3_malloc( sizeof(*pLog)*2 + nName + 60 );
+  if( pTemp==0 ) return 0;
+  pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
+  sqlite3_mutex_enter(pMutex);
+  for(pLog=allLogs; pLog; pLog=pLog->pNext){
+    if( pLog->nFilename==nName && !memcmp(pLog->zFilename, zFilename, nName) ){
+      break;
+    }
+  }
+  if( pLog==0 ){
+    pLog = pTemp;
+    pTemp = 0;
+    memset(pLog, 0, sizeof(*pLog)*2);
+    pLog->zFilename = (char*)&pLog[2];
+    sqlite3_snprintf(nName+60, pLog->zFilename, "%.*s-debuglog-%lld",
+                     nName, zFilename, vlog_time());
+    pLog->out = fopen(pLog->zFilename, "a");
+    if( pLog->out==0 ){
+      sqlite3_mutex_leave(pMutex);
+      sqlite3_free(pLog);
+      return 0;
+    }
+    pLog->nFilename = nName;
+    pLog[1].out = pLog[0].out;
+    pLog->ppPrev = &allLogs;
+    if( allLogs ) allLogs->ppPrev = &pLog->pNext;
+    pLog->pNext = allLogs;
+    allLogs = pLog;
+  }
+  sqlite3_mutex_leave(pMutex);
+  sqlite3_free(pTemp);
+  if( pLog && isJournal ) pLog++;
+  pLog->nRef++;
+  return pLog;
+}
+
+
+/*
+** Close an vlog-file.
+*/
+static int vlogClose(sqlite3_file *pFile){
+  sqlite3_uint64 tStart, tElapse;
+  int rc = SQLITE_OK;
+  VLogFile *p = (VLogFile *)pFile;
+
+  tStart = vlog_time();
+  if( p->pReal->pMethods ){
+    rc = p->pReal->pMethods->xClose(p->pReal);
+  }
+  tElapse = vlog_time() - tStart;
+  vlogLogPrint(p->pLog, tStart, tElapse, "CLOSE", -1, -1, 0, rc);
+  vlogLogClose(p->pLog);
+  return rc;
+}
+
+/*
+** Compute signature for a block of content.
+**
+** The signature is a hex dump of the first 8 bytes of the block
+** followed by a 64bit hash (expressed in hex) of the entire content.
+*/
+static void vlogSignature(unsigned char *p, int n, char *zCksum){
+  unsigned int s0 = 0, s1 = 0;
+  unsigned int *pI;
+  int i;
+  pI = (unsigned int*)p;
+  for(i=0; i<n-7; i+=8){
+    s0 += pI[0] + s1;
+    s1 += pI[1] + s0;
+    pI += 2;
+  }
+  for(i=0; i<8 && i<n; i++) sqlite3_snprintf(3, zCksum+i, "%02x", p[i]);
+  if( n>8 ) sqlite3_snprintf(18, zCksum+i, "-%08x08x", s0, s1);
+}
+
+/*
+** Read data from an vlog-file.
+*/
+static int vlogRead(
+  sqlite3_file *pFile, 
+  void *zBuf, 
+  int iAmt, 
+  sqlite_int64 iOfst
+){
+  int rc;
+  sqlite3_uint64 tStart, tElapse;
+  VLogFile *p = (VLogFile *)pFile;
+  char zSig[40];
+
+  tStart = vlog_time();
+  rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst);
+  tElapse = vlog_time() - tStart;
+  if( rc==SQLITE_OK ){
+    vlogSignature(zBuf, iAmt, zSig);
+  }else{
+    zSig[0] = 0;
+  }
+  vlogLogPrint(p->pLog, tStart, tElapse, "READ", iAmt, iOfst, zSig, rc);
+  return rc;
+}
+
+/*
+** Write data to an vlog-file.
+*/
+static int vlogWrite(
+  sqlite3_file *pFile,
+  const void *z,
+  int iAmt,
+  sqlite_int64 iOfst
+){
+  int rc;
+  sqlite3_uint64 tStart, tElapse;
+  VLogFile *p = (VLogFile *)pFile;
+  char zSig[40];
+
+  tStart = vlog_time();
+  vlogSignature((unsigned char*)z, iAmt, zSig);
+  rc = p->pReal->pMethods->xWrite(p->pReal, z, iAmt, iOfst);
+  tElapse = vlog_time() - tStart;
+  vlogLogPrint(p->pLog, tStart, tElapse, "WRITE", iAmt, iOfst, zSig, rc);
+  return rc;
+}
+
+/*
+** Truncate an vlog-file.
+*/
+static int vlogTruncate(sqlite3_file *pFile, sqlite_int64 size){
+  int rc;
+  sqlite3_uint64 tStart, tElapse;
+  VLogFile *p = (VLogFile *)pFile;
+  tStart = vlog_time();
+  rc = p->pReal->pMethods->xTruncate(p->pReal, size);
+  tElapse = vlog_time() - tStart;
+  vlogLogPrint(p->pLog, tStart, tElapse, "TRUNCATE", size, -1, 0, rc);
+  return rc;
+}
+
+/*
+** Sync an vlog-file.
+*/
+static int vlogSync(sqlite3_file *pFile, int flags){
+  int rc;
+  sqlite3_uint64 tStart, tElapse;
+  VLogFile *p = (VLogFile *)pFile;
+  tStart = vlog_time();
+  rc = p->pReal->pMethods->xSync(p->pReal, flags);
+  tElapse = vlog_time() - tStart;
+  vlogLogPrint(p->pLog, tStart, tElapse, "SYNC", flags, -1, 0, rc);
+  return rc;
+}
+
+/*
+** Return the current file-size of an vlog-file.
+*/
+static int vlogFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
+  int rc;
+  sqlite3_uint64 tStart, tElapse;
+  VLogFile *p = (VLogFile *)pFile;
+  tStart = vlog_time();
+  rc = p->pReal->pMethods->xFileSize(p->pReal, pSize);
+  tElapse = vlog_time() - tStart;
+  vlogLogPrint(p->pLog, tStart, tElapse, "FILESIZE", *pSize, -1, 0, rc);
+  return rc;
+}
+
+/*
+** Lock an vlog-file.
+*/
+static int vlogLock(sqlite3_file *pFile, int eLock){
+  int rc;
+  sqlite3_uint64 tStart, tElapse;
+  VLogFile *p = (VLogFile *)pFile;
+  tStart = vlog_time();
+  rc = p->pReal->pMethods->xLock(p->pReal, eLock);
+  tElapse = vlog_time() - tStart;
+  vlogLogPrint(p->pLog, tStart, tElapse, "LOCK", eLock, -1, 0, rc);
+  return rc;
+}
+
+/*
+** Unlock an vlog-file.
+*/
+static int vlogUnlock(sqlite3_file *pFile, int eLock){
+  int rc;
+  sqlite3_uint64 tStart, tElapse;
+  VLogFile *p = (VLogFile *)pFile;
+  tStart = vlog_time();
+  rc = p->pReal->pMethods->xUnlock(p->pReal, eLock);
+  tElapse = vlog_time() - tStart;
+  vlogLogPrint(p->pLog, tStart, tElapse, "UNLOCK", eLock, -1, 0, rc);
+  return rc;
+}
+
+/*
+** Check if another file-handle holds a RESERVED lock on an vlog-file.
+*/
+static int vlogCheckReservedLock(sqlite3_file *pFile, int *pResOut){
+  int rc;
+  sqlite3_uint64 tStart, tElapse;
+  VLogFile *p = (VLogFile *)pFile;
+  tStart = vlog_time();
+  rc = p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut);
+  tElapse = vlog_time() - tStart;
+  vlogLogPrint(p->pLog, tStart, tElapse, "CHECKRESERVEDLOCK",
+                 *pResOut, -1, "", rc);
+  return rc;
+}
+
+/*
+** File control method. For custom operations on an vlog-file.
+*/
+static int vlogFileControl(sqlite3_file *pFile, int op, void *pArg){
+  VLogFile *p = (VLogFile *)pFile;
+  sqlite3_uint64 tStart, tElapse;
+  int rc;
+  tStart = vlog_time();
+  rc = p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
+  if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){
+    *(char**)pArg = sqlite3_mprintf("vlog/%z", *(char**)pArg);
+  }
+  tElapse = vlog_time() - tStart;
+  vlogLogPrint(p->pLog, tStart, tElapse, "FILECONTROL", op, -1, 0, rc);
+  return rc;
+}
+
+/*
+** Return the sector-size in bytes for an vlog-file.
+*/
+static int vlogSectorSize(sqlite3_file *pFile){
+  int rc;
+  sqlite3_uint64 tStart, tElapse;
+  VLogFile *p = (VLogFile *)pFile;
+  tStart = vlog_time();
+  rc = p->pReal->pMethods->xSectorSize(p->pReal);
+  tElapse = vlog_time() - tStart;
+  vlogLogPrint(p->pLog, tStart, tElapse, "SECTORSIZE", -1, -1, 0, rc);
+  return rc;
+}
+
+/*
+** Return the device characteristic flags supported by an vlog-file.
+*/
+static int vlogDeviceCharacteristics(sqlite3_file *pFile){
+  int rc;
+  sqlite3_uint64 tStart, tElapse;
+  VLogFile *p = (VLogFile *)pFile;
+  tStart = vlog_time();
+  rc = p->pReal->pMethods->xDeviceCharacteristics(p->pReal);
+  tElapse = vlog_time() - tStart;
+  vlogLogPrint(p->pLog, tStart, tElapse, "DEVCHAR", -1, -1, 0, rc);
+  return rc;
+}
+
+
+/*
+** Open an vlog file handle.
+*/
+static int vlogOpen(
+  sqlite3_vfs *pVfs,
+  const char *zName,
+  sqlite3_file *pFile,
+  int flags,
+  int *pOutFlags
+){
+  int rc;
+  sqlite3_uint64 tStart, tElapse;
+  sqlite3_int64 iArg2;
+  VLogFile *p = (VLogFile*)pFile;
+
+  p->pReal = (sqlite3_file*)&p[1];
+  if( (flags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_MAIN_JOURNAL))!=0 ){
+    p->pLog = vlogLogOpen(zName);
+  }else{
+    p->pLog = 0;
+  }
+  tStart = vlog_time();
+  rc = REALVFS(pVfs)->xOpen(REALVFS(pVfs), zName, p->pReal, flags, pOutFlags);
+  tElapse = vlog_time() - tStart;
+  iArg2 = pOutFlags ? *pOutFlags : -1;
+  vlogLogPrint(p->pLog, tStart, tElapse, "OPEN", flags, iArg2, 0, rc);
+  if( rc==SQLITE_OK ){
+    pFile->pMethods = &vlog_io_methods;
+  }else{
+    if( p->pLog ) vlogLogClose(p->pLog);
+    p->pLog = 0;
+  }
+  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 vlogDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
+  int rc;
+  sqlite3_uint64 tStart, tElapse;
+  VLogLog *pLog;
+  tStart = vlog_time();
+  rc = REALVFS(pVfs)->xDelete(REALVFS(pVfs), zPath, dirSync);
+  tElapse = vlog_time() - tStart;
+  pLog = vlogLogOpen(zPath);
+  vlogLogPrint(pLog, tStart, tElapse, "DELETE", dirSync, -1, 0, rc);
+  vlogLogClose(pLog);
+  return rc;
+}
+
+/*
+** Test for access permissions. Return true if the requested permission
+** is available, or false otherwise.
+*/
+static int vlogAccess(
+  sqlite3_vfs *pVfs, 
+  const char *zPath, 
+  int flags, 
+  int *pResOut
+){
+  int rc;
+  sqlite3_uint64 tStart, tElapse;
+  VLogLog *pLog;
+  tStart = vlog_time();
+  rc = REALVFS(pVfs)->xAccess(REALVFS(pVfs), zPath, flags, pResOut);
+  tElapse = vlog_time() - tStart;
+  pLog = vlogLogOpen(zPath);
+  vlogLogPrint(pLog, tStart, tElapse, "ACCESS", flags, *pResOut, 0, rc);
+  vlogLogClose(pLog);
+  return rc;
+}
+
+/*
+** 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 vlogFullPathname(
+  sqlite3_vfs *pVfs, 
+  const char *zPath, 
+  int nOut, 
+  char *zOut
+){
+  return REALVFS(pVfs)->xFullPathname(REALVFS(pVfs), zPath, nOut, zOut);
+}
+
+/*
+** Open the dynamic library located at zPath and return a handle.
+*/
+static void *vlogDlOpen(sqlite3_vfs *pVfs, const char *zPath){
+  return REALVFS(pVfs)->xDlOpen(REALVFS(pVfs), zPath);
+}
+
+/*
+** Populate the buffer zErrMsg (size nByte bytes) with a human readable
+** utf-8 string describing the most recent error encountered associated 
+** with dynamic libraries.
+*/
+static void vlogDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
+  REALVFS(pVfs)->xDlError(REALVFS(pVfs), nByte, zErrMsg);
+}
+
+/*
+** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
+*/
+static void (*vlogDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
+  return REALVFS(pVfs)->xDlSym(REALVFS(pVfs), p, zSym);
+}
+
+/*
+** Close the dynamic library handle pHandle.
+*/
+static void vlogDlClose(sqlite3_vfs *pVfs, void *pHandle){
+  REALVFS(pVfs)->xDlClose(REALVFS(pVfs), pHandle);
+}
+
+/*
+** Populate the buffer pointed to by zBufOut with nByte bytes of 
+** random data.
+*/
+static int vlogRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
+  return REALVFS(pVfs)->xRandomness(REALVFS(pVfs), nByte, zBufOut);
+}
+
+/*
+** Sleep for nMicro microseconds. Return the number of microseconds 
+** actually slept.
+*/
+static int vlogSleep(sqlite3_vfs *pVfs, int nMicro){
+  return REALVFS(pVfs)->xSleep(REALVFS(pVfs), nMicro);
+}
+
+/*
+** Return the current time as a Julian Day number in *pTimeOut.
+*/
+static int vlogCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
+  return REALVFS(pVfs)->xCurrentTime(REALVFS(pVfs), pTimeOut);
+}
+
+static int vlogGetLastError(sqlite3_vfs *pVfs, int a, char *b){
+  return REALVFS(pVfs)->xGetLastError(REALVFS(pVfs), a, b);
+}
+static int vlogCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
+  return REALVFS(pVfs)->xCurrentTimeInt64(REALVFS(pVfs), p);
+}
+
+/*
+** Register debugvfs as the default VFS for this process.
+*/
+int sqlite3_register_vfslog(const char *zArg){
+  vlog_vfs.pVfs = sqlite3_vfs_find(0);
+  vlog_vfs.base.szOsFile = sizeof(VLogFile) + vlog_vfs.pVfs->szOsFile;
+  return sqlite3_vfs_register(&vlog_vfs.base, 1);
+}
+
+
diff --git a/main.mk b/main.mk
index 1d9dd105c55d428a37d841db97d8dd779179bb4f..0197bc1bd8d12ebfc89e75124d587448f345407e 100644 (file)
--- a/main.mk
+++ b/main.mk
@@ -279,7 +279,8 @@ TESTSRC += \
   $(TOP)/ext/misc/percentile.c \
   $(TOP)/ext/misc/regexp.c \
   $(TOP)/ext/misc/spellfix.c \
-  $(TOP)/ext/misc/wholenumber.c
+  $(TOP)/ext/misc/wholenumber.c \
+  $(TOP)/ext/misc/vfslog.c
 
 
 #TESTSRC += $(TOP)/ext/fts2/fts2_tokenizer.c
index bd8d2796c4f3bd9a0a8b55ab01e7a2bb53d49c5a..368a4585dc20c90b3d564634cfedc12b783085ff 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Estimate\srow\ssizes\sfor\stables\sand\sindices\sand\suse\sthose\sestimates\sduring\nquery\splanning.\s\sEnhance\sthe\sindex_info\spragma\sto\sshow\sthe\sestimated\srow\nsizes\sand\sto\sshow\sthe\sestimated\srow\ssize\sfor\sthe\smain\stable\sas\swell.\s\sAllow\nan\salternative\srow\ssize\sestimate\sto\sbe\sspecified\sin\sthe\ssqlite_stat1\stable.
-D 2013-10-10T12:38:11.216
+C Add\sext/misc/vfslog.c,\sa\sVFS\sshim\sfor\sunix\sthat\skeeps\sa\slog\sof\smethod\scalls\smade\sby\sSQLite.
+D 2013-10-10T13:04:46.705
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -115,6 +115,7 @@ F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63
 F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc
 F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a
 F ext/misc/spellfix.c 5e1d547e9a2aed13897fa91bac924333f62fd2d9
+F ext/misc/vfslog.c 64f8ff0605ba36fd3e71c5e3b2ea00c55448cbbe
 F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e
 F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
@@ -139,7 +140,7 @@ F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
 F magic.txt f2b23a6bde8f1c6e86b957e4d94eab0add520b0d
-F main.mk a10f1925ae3bb545a045d1f1867506f49bee972f
+F main.mk 4a086a18f38cd6ffec33be54dc56ade76d3a29a2
 F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a
 F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f
 F mkextw.sh d2a981497b404d6498f5ff3e3b1f3816bdfcb338
@@ -723,7 +724,7 @@ F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0
 F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d
 F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
 F test/percentile.test b98fc868d71eb5619d42a1702e9ab91718cbed54
-F test/permutations.test 72f4f8881d388163ddbbeec0a6ed812e863ea2e6
+F test/permutations.test e154f5ed66d4d4913a99a110e870c9407f75b055
 F test/pragma.test 5c6e8ae9eaa9a505cc1035b51f7f0da9805092c7
 F test/pragma2.test 224f0381f9411a78ae685cac24c13656a62021b7
 F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
@@ -1121,7 +1122,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
-P 36d64dc36f18c166b2c93c43579fa3bbb5cd545f e97d7d3044aa6c5e21d1faab7d5e709d92faa261
-R 57860f2afd769aeffdd11c615e695d0a
-U drh
-Z 2546d871db6bcc36ea3db39835f90b3e
+P d27b88b8c2705f444f794096c719e6f38a792165
+R 5f38dde3b9e8f121e53417dc6f4fda25
+U dan
+Z f43e38212326572373f5c91a1aac8a3a
index 64bac1a9fc055aefd9736c66ca033beb64a22b74..bd77f508ccabfa3556b0fcb8f45c6bbfa30cf6c9 100644 (file)
@@ -1 +1 @@
-d27b88b8c2705f444f794096c719e6f38a792165
\ No newline at end of file
+24a827b87666670c56d68a18685f4f712852fa92
\ No newline at end of file
index 7468b89673bb28116f4221fbf2e17c8ef7f75ac8..54e9ede0be5bae157757956ae1dbeb163be0e40b 100644 (file)
@@ -289,6 +289,17 @@ test_suite "queryplanner" -prefix "" -description {
   where.test
 }
 
+test_suite "vfslog" -prefix "" -description {
+  "Vfslog" quick test suite. Like "veryquick" except does not omits
+  a few tests that do not work with a version 1 VFS. And the quota* tests,
+  which do not work with a VFS that uses the pVfs argument passed to
+  sqlite3_vfs methods.
+} -files [
+  test_set $allquicktests -exclude *malloc* *ioerr* *fault* oserror.test \
+  pager1.test syscall.test sysfault.test tkt3457.test quota* superlock* \
+  wal* mmap*
+]
+
 lappend ::testsuitelist xxx
 #-------------------------------------------------------------------------
 # Define the coverage related test suites: