15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 2008 April 10
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The author disclaims copyright to this source code.  In place of
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** a legal notice, here is a blessing:
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    May you do good and not evil.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    May you find forgiveness for yourself and forgive others.
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    May you share freely, never taking more than you give.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)******************************************************************************
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This file contains the implementation of an SQLite vfs wrapper that
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** adds instrumentation to all vfs and file methods. C and Tcl interfaces
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** are provided to control the instrumentation.
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This module contains code for a wrapper VFS that causes a log of
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** most VFS calls to be written into a nominated file on disk. The log
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is stored in a compressed binary format to reduce the amount of IO
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** overhead introduced into the application by logging.
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** All calls on sqlite3_file objects except xFileControl() are logged.
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Additionally, calls to the xAccess(), xOpen(), and xDelete()
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** methods are logged. The other sqlite3_vfs object methods (xDlXXX,
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** xRandomness, xSleep, xCurrentTime, xGetLastError and xCurrentTimeInt64)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** are not logged.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The binary log files are read using a virtual table implementation
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** also contained in this file.
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** CREATING LOG FILES:
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**       int sqlite3_vfslog_new(
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**         const char *zVfs,          // Name of new VFS
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**         const char *zParentVfs,    // Name of parent VFS (or NULL)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**         const char *zLog           // Name of log file to write to
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**       );
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**       int sqlite3_vfslog_finalize(const char *zVfs);
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** ANNOTATING LOG FILES:
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   To write an arbitrary message into a log file:
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**       int sqlite3_vfslog_annotate(const char *zVfs, const char *zMsg);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** READING LOG FILES:
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   Log files are read using the "vfslog" virtual table implementation
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   in this file. To register the virtual table with SQLite, use:
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**       int sqlite3_vfslog_register(sqlite3 *db);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   Then, if the log file is named "vfs.log", the following SQL command:
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**       CREATE VIRTUAL TABLE v USING vfslog('vfs.log');
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   creates a virtual table with 6 columns, as follows:
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**       CREATE TABLE v(
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**         event    TEXT,             // "xOpen", "xRead" etc.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**         file     TEXT,             // Name of file this call applies to
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**         clicks   INTEGER,          // Time spent in call
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**         rc       INTEGER,          // Return value
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**         size     INTEGER,          // Bytes read or written
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**         offset   INTEGER           // File offset read or written
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**       );
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sqlite3.h"
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <assert.h>
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Maximum pathname length supported by the vfslog backend.
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define INST_MAX_PATHNAME 512
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OS_ACCESS            1
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OS_CHECKRESERVEDLOCK 2
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OS_CLOSE             3
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OS_CURRENTTIME       4
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OS_DELETE            5
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OS_DEVCHAR           6
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OS_FILECONTROL       7
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OS_FILESIZE          8
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OS_FULLPATHNAME      9
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OS_LOCK              11
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OS_OPEN              12
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OS_RANDOMNESS        13
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OS_READ              14
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OS_SECTORSIZE        15
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OS_SLEEP             16
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OS_SYNC              17
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OS_TRUNCATE          18
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OS_UNLOCK            19
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OS_WRITE             20
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OS_SHMUNMAP          22
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OS_SHMMAP            23
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OS_SHMLOCK           25
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OS_SHMBARRIER        26
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OS_ANNOTATE          28
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OS_NUMEVENTS         29
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VFSLOG_BUFFERSIZE 8192
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct VfslogVfs VfslogVfs;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct VfslogFile VfslogFile;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct VfslogVfs {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs base;               /* VFS methods */
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pVfs;              /* Parent VFS */
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iNextFileId;                /* Next file id */
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *pLog;             /* Log file handle */
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_int64 iOffset;          /* Log file offset of start of write buffer */
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nBuf;                       /* Number of valid bytes in aBuf[] */
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char aBuf[VFSLOG_BUFFERSIZE];   /* Write buffer */
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct VfslogFile {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file base;              /* IO methods */
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *pReal;            /* Underlying file handle */
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pVfslog;           /* Associated VsflogVfs object */
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iFileId;                    /* File id number */
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define REALVFS(p) (((VfslogVfs *)(p))->pVfs)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Method declarations for vfslog_file.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogClose(sqlite3_file*);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogTruncate(sqlite3_file*, sqlite3_int64 size);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogSync(sqlite3_file*, int flags);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogFileSize(sqlite3_file*, sqlite3_int64 *pSize);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogLock(sqlite3_file*, int);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogUnlock(sqlite3_file*, int);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogCheckReservedLock(sqlite3_file*, int *pResOut);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogFileControl(sqlite3_file*, int op, void *pArg);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogSectorSize(sqlite3_file*);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogDeviceCharacteristics(sqlite3_file*);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogShmLock(sqlite3_file *pFile, int ofst, int n, int flags);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogShmMap(sqlite3_file *pFile,int,int,int,volatile void **);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void vfslogShmBarrier(sqlite3_file*);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogShmUnmap(sqlite3_file *pFile, int deleteFlag);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Method declarations for vfslog_vfs.
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogDelete(sqlite3_vfs*, const char *zName, int syncDir);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogAccess(sqlite3_vfs*, const char *zName, int flags, int *);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void *vfslogDlOpen(sqlite3_vfs*, const char *zFilename);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void vfslogDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void (*vfslogDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void vfslogDlClose(sqlite3_vfs*, void*);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogRandomness(sqlite3_vfs*, int nByte, char *zOut);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogSleep(sqlite3_vfs*, int microseconds);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogCurrentTime(sqlite3_vfs*, double*);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogGetLastError(sqlite3_vfs*, int, char *);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static sqlite3_vfs vfslog_vfs = {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  1,                              /* iVersion */
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sizeof(VfslogFile),             /* szOsFile */
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  INST_MAX_PATHNAME,              /* mxPathname */
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,                              /* pNext */
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,                              /* zName */
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,                              /* pAppData */
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslogOpen,                     /* xOpen */
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslogDelete,                   /* xDelete */
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslogAccess,                   /* xAccess */
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslogFullPathname,             /* xFullPathname */
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslogDlOpen,                   /* xDlOpen */
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslogDlError,                  /* xDlError */
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslogDlSym,                    /* xDlSym */
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslogDlClose,                  /* xDlClose */
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslogRandomness,               /* xRandomness */
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslogSleep,                    /* xSleep */
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslogCurrentTime,              /* xCurrentTime */
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslogGetLastError,             /* xGetLastError */
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslogCurrentTimeInt64          /* xCurrentTime */
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static sqlite3_io_methods vfslog_io_methods = {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  2,                              /* iVersion */
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslogClose,                    /* xClose */
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslogRead,                     /* xRead */
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslogWrite,                    /* xWrite */
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslogTruncate,                 /* xTruncate */
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslogSync,                     /* xSync */
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslogFileSize,                 /* xFileSize */
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslogLock,                     /* xLock */
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslogUnlock,                   /* xUnlock */
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslogCheckReservedLock,        /* xCheckReservedLock */
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslogFileControl,              /* xFileControl */
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslogSectorSize,               /* xSectorSize */
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslogDeviceCharacteristics,    /* xDeviceCharacteristics */
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslogShmMap,                   /* xShmMap */
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslogShmLock,                  /* xShmLock */
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslogShmBarrier,               /* xShmBarrier */
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslogShmUnmap                  /* xShmUnmap */
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_UNIX && !defined(NO_GETTOD)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/time.h>
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static sqlite3_uint64 vfslog_time(){
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct timeval sTime;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gettimeofday(&sTime, 0);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sTime.tv_usec + (sqlite3_uint64)sTime.tv_sec * 1000000;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif SQLITE_OS_WIN
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h>
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <time.h>
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static sqlite3_uint64 vfslog_time(){
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FILETIME ft;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_uint64 u64time = 0;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetSystemTimeAsFileTime(&ft);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u64time |= ft.dwHighDateTime;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u64time <<= 32;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u64time |= ft.dwLowDateTime;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* ft is 100-nanosecond intervals, we want microseconds */
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return u64time /(sqlite3_uint64)10;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static sqlite3_uint64 vfslog_time(){
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void vfslog_call(sqlite3_vfs *, int, int, int, int, int, int);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void vfslog_string(sqlite3_vfs *, const char *);
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Close an vfslog-file.
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogClose(sqlite3_file *pFile){
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_uint64 t;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VfslogFile *p = (VfslogFile *)pFile;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time();
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->pReal->pMethods ){
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = p->pReal->pMethods->xClose(p->pReal);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time() - t;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslog_call(p->pVfslog, OS_CLOSE, p->iFileId, t, rc, 0, 0);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Read data from an vfslog-file.
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogRead(
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *pFile,
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *zBuf,
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iAmt,
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite_int64 iOfst
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_uint64 t;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VfslogFile *p = (VfslogFile *)pFile;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time();
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time() - t;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslog_call(p->pVfslog, OS_READ, p->iFileId, t, rc, iAmt, (int)iOfst);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Write data to an vfslog-file.
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogWrite(
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *pFile,
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void *z,
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iAmt,
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite_int64 iOfst
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_uint64 t;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VfslogFile *p = (VfslogFile *)pFile;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time();
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = p->pReal->pMethods->xWrite(p->pReal, z, iAmt, iOfst);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time() - t;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslog_call(p->pVfslog, OS_WRITE, p->iFileId, t, rc, iAmt, (int)iOfst);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Truncate an vfslog-file.
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogTruncate(sqlite3_file *pFile, sqlite_int64 size){
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_uint64 t;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VfslogFile *p = (VfslogFile *)pFile;
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time();
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = p->pReal->pMethods->xTruncate(p->pReal, size);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time() - t;
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslog_call(p->pVfslog, OS_TRUNCATE, p->iFileId, t, rc, 0, (int)size);
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Sync an vfslog-file.
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogSync(sqlite3_file *pFile, int flags){
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_uint64 t;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VfslogFile *p = (VfslogFile *)pFile;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time();
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = p->pReal->pMethods->xSync(p->pReal, flags);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time() - t;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslog_call(p->pVfslog, OS_SYNC, p->iFileId, t, rc, flags, 0);
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return the current file-size of an vfslog-file.
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_uint64 t;
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VfslogFile *p = (VfslogFile *)pFile;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time();
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = p->pReal->pMethods->xFileSize(p->pReal, pSize);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time() - t;
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslog_call(p->pVfslog, OS_FILESIZE, p->iFileId, t, rc, 0, (int)*pSize);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Lock an vfslog-file.
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogLock(sqlite3_file *pFile, int eLock){
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_uint64 t;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VfslogFile *p = (VfslogFile *)pFile;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time();
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = p->pReal->pMethods->xLock(p->pReal, eLock);
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time() - t;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslog_call(p->pVfslog, OS_LOCK, p->iFileId, t, rc, eLock, 0);
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Unlock an vfslog-file.
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogUnlock(sqlite3_file *pFile, int eLock){
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_uint64 t;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VfslogFile *p = (VfslogFile *)pFile;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time();
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = p->pReal->pMethods->xUnlock(p->pReal, eLock);
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time() - t;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslog_call(p->pVfslog, OS_UNLOCK, p->iFileId, t, rc, eLock, 0);
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Check if another file-handle holds a RESERVED lock on an vfslog-file.
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogCheckReservedLock(sqlite3_file *pFile, int *pResOut){
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_uint64 t;
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VfslogFile *p = (VfslogFile *)pFile;
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time();
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time() - t;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslog_call(p->pVfslog, OS_CHECKRESERVEDLOCK, p->iFileId, t, rc, *pResOut, 0);
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** File control method. For custom operations on an vfslog-file.
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogFileControl(sqlite3_file *pFile, int op, void *pArg){
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VfslogFile *p = (VfslogFile *)pFile;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return the sector-size in bytes for an vfslog-file.
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogSectorSize(sqlite3_file *pFile){
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_uint64 t;
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VfslogFile *p = (VfslogFile *)pFile;
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time();
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = p->pReal->pMethods->xSectorSize(p->pReal);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time() - t;
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslog_call(p->pVfslog, OS_SECTORSIZE, p->iFileId, t, rc, 0, 0);
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return the device characteristic flags supported by an vfslog-file.
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogDeviceCharacteristics(sqlite3_file *pFile){
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_uint64 t;
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VfslogFile *p = (VfslogFile *)pFile;
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time();
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = p->pReal->pMethods->xDeviceCharacteristics(p->pReal);
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time() - t;
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslog_call(p->pVfslog, OS_DEVCHAR, p->iFileId, t, rc, 0, 0);
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_uint64 t;
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VfslogFile *p = (VfslogFile *)pFile;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time();
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags);
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time() - t;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslog_call(p->pVfslog, OS_SHMLOCK, p->iFileId, t, rc, 0, 0);
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogShmMap(
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *pFile,
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iRegion,
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int szRegion,
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int isWrite,
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  volatile void **pp
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_uint64 t;
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VfslogFile *p = (VfslogFile *)pFile;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time();
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = p->pReal->pMethods->xShmMap(p->pReal, iRegion, szRegion, isWrite, pp);
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time() - t;
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslog_call(p->pVfslog, OS_SHMMAP, p->iFileId, t, rc, 0, 0);
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void vfslogShmBarrier(sqlite3_file *pFile){
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_uint64 t;
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VfslogFile *p = (VfslogFile *)pFile;
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time();
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->pReal->pMethods->xShmBarrier(p->pReal);
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time() - t;
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslog_call(p->pVfslog, OS_SHMBARRIER, p->iFileId, t, SQLITE_OK, 0, 0);
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogShmUnmap(sqlite3_file *pFile, int deleteFlag){
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_uint64 t;
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VfslogFile *p = (VfslogFile *)pFile;
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time();
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = p->pReal->pMethods->xShmUnmap(p->pReal, deleteFlag);
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time() - t;
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslog_call(p->pVfslog, OS_SHMUNMAP, p->iFileId, t, rc, 0, 0);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Open an vfslog file handle.
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogOpen(
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pVfs,
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zName,
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *pFile,
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags,
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int *pOutFlags
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_uint64 t;
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VfslogFile *p = (VfslogFile *)pFile;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VfslogVfs *pLog = (VfslogVfs *)pVfs;
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pFile->pMethods = &vfslog_io_methods;
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->pReal = (sqlite3_file *)&p[1];
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->pVfslog = pVfs;
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->iFileId = ++pLog->iNextFileId;
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time();
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = REALVFS(pVfs)->xOpen(REALVFS(pVfs), zName, p->pReal, flags, pOutFlags);
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time() - t;
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslog_call(pVfs, OS_OPEN, p->iFileId, t, rc, 0, 0);
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslog_string(pVfs, zName);
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Delete the file located at zPath. If the dirSync argument is true,
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** ensure the file-system modifications are synced to disk before
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** returning.
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_uint64 t;
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time();
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = REALVFS(pVfs)->xDelete(REALVFS(pVfs), zPath, dirSync);
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time() - t;
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslog_call(pVfs, OS_DELETE, 0, t, rc, dirSync, 0);
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslog_string(pVfs, zPath);
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Test for access permissions. Return true if the requested permission
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is available, or false otherwise.
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogAccess(
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pVfs,
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zPath,
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags,
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int *pResOut
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_uint64 t;
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time();
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = REALVFS(pVfs)->xAccess(REALVFS(pVfs), zPath, flags, pResOut);
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t = vfslog_time() - t;
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslog_call(pVfs, OS_ACCESS, 0, t, rc, flags, *pResOut);
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslog_string(pVfs, zPath);
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Populate buffer zOut with the full canonical pathname corresponding
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to the pathname in zPath. zOut is guaranteed to point to a buffer
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** of at least (INST_MAX_PATHNAME+1) bytes.
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogFullPathname(
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pVfs,
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zPath,
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nOut,
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zOut
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return REALVFS(pVfs)->xFullPathname(REALVFS(pVfs), zPath, nOut, zOut);
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Open the dynamic library located at zPath and return a handle.
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void *vfslogDlOpen(sqlite3_vfs *pVfs, const char *zPath){
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return REALVFS(pVfs)->xDlOpen(REALVFS(pVfs), zPath);
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Populate the buffer zErrMsg (size nByte bytes) with a human readable
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** utf-8 string describing the most recent error encountered associated
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** with dynamic libraries.
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void vfslogDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  REALVFS(pVfs)->xDlError(REALVFS(pVfs), nByte, zErrMsg);
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void (*vfslogDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return REALVFS(pVfs)->xDlSym(REALVFS(pVfs), p, zSym);
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Close the dynamic library handle pHandle.
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void vfslogDlClose(sqlite3_vfs *pVfs, void *pHandle){
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  REALVFS(pVfs)->xDlClose(REALVFS(pVfs), pHandle);
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Populate the buffer pointed to by zBufOut with nByte bytes of
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** random data.
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return REALVFS(pVfs)->xRandomness(REALVFS(pVfs), nByte, zBufOut);
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Sleep for nMicro microseconds. Return the number of microseconds
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** actually slept.
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogSleep(sqlite3_vfs *pVfs, int nMicro){
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return REALVFS(pVfs)->xSleep(REALVFS(pVfs), nMicro);
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return the current time as a Julian Day number in *pTimeOut.
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return REALVFS(pVfs)->xCurrentTime(REALVFS(pVfs), pTimeOut);
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogGetLastError(sqlite3_vfs *pVfs, int a, char *b){
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return REALVFS(pVfs)->xGetLastError(REALVFS(pVfs), a, b);
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vfslogCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return REALVFS(pVfs)->xCurrentTimeInt64(REALVFS(pVfs), p);
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void vfslog_flush(VfslogVfs *p){
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_TEST
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extern int sqlite3_io_error_pending;
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extern int sqlite3_io_error_persist;
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extern int sqlite3_diskfull_pending;
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int pending = sqlite3_io_error_pending;
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int persist = sqlite3_io_error_persist;
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int diskfull = sqlite3_diskfull_pending;
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_io_error_pending = 0;
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_io_error_persist = 0;
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_diskfull_pending = 0;
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->nBuf ){
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->pLog->pMethods->xWrite(p->pLog, p->aBuf, p->nBuf, p->iOffset);
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->iOffset += p->nBuf;
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->nBuf = 0;
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_TEST
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_io_error_pending = pending;
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_io_error_persist = persist;
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_diskfull_pending = diskfull;
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void put32bits(unsigned char *p, unsigned int v){
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p[0] = v>>24;
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p[1] = v>>16;
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p[2] = v>>8;
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p[3] = v;
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void vfslog_call(
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pVfs,
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int eEvent,
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iFileid,
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nClick,
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int return_code,
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int size,
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int offset
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VfslogVfs *p = (VfslogVfs *)pVfs;
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned char *zRec;
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( (24+p->nBuf)>sizeof(p->aBuf) ){
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vfslog_flush(p);
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zRec = (unsigned char *)&p->aBuf[p->nBuf];
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  put32bits(&zRec[0], eEvent);
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  put32bits(&zRec[4], iFileid);
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  put32bits(&zRec[8], nClick);
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  put32bits(&zRec[12], return_code);
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  put32bits(&zRec[16], size);
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  put32bits(&zRec[20], offset);
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->nBuf += 24;
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void vfslog_string(sqlite3_vfs *pVfs, const char *zStr){
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VfslogVfs *p = (VfslogVfs *)pVfs;
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned char *zRec;
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nStr = zStr ? strlen(zStr) : 0;
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( (4+nStr+p->nBuf)>sizeof(p->aBuf) ){
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vfslog_flush(p);
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zRec = (unsigned char *)&p->aBuf[p->nBuf];
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  put32bits(&zRec[0], nStr);
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( zStr ){
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(&zRec[4], zStr, nStr);
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->nBuf += (4 + nStr);
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void vfslog_finalize(VfslogVfs *p){
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->pLog->pMethods ){
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vfslog_flush(p);
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->pLog->pMethods->xClose(p->pLog);
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(p);
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_vfslog_finalize(const char *zVfs){
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pVfs;
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pVfs = sqlite3_vfs_find(zVfs);
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !pVfs || pVfs->xOpen!=vfslogOpen ){
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_ERROR;
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs_unregister(pVfs);
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslog_finalize((VfslogVfs *)pVfs);
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_vfslog_new(
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zVfs,               /* New VFS name */
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zParentVfs,         /* Parent VFS name (or NULL) */
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zLog                /* Log file name */
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VfslogVfs *p;
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pParent;
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nByte;
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags;
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zFile;
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nVfs;
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pParent = sqlite3_vfs_find(zParentVfs);
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !pParent ){
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_ERROR;
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nVfs = strlen(zVfs);
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nByte = sizeof(VfslogVfs) + pParent->szOsFile + nVfs+1+pParent->mxPathname+1;
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p = (VfslogVfs *)sqlite3_malloc(nByte);
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(p, 0, nByte);
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->pVfs = pParent;
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->pLog = (sqlite3_file *)&p[1];
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(&p->base, &vfslog_vfs, sizeof(sqlite3_vfs));
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->base.zName = &((char *)p->pLog)[pParent->szOsFile];
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->base.szOsFile += pParent->szOsFile;
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy((char *)p->base.zName, zVfs, nVfs);
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zFile = (char *)&p->base.zName[nVfs+1];
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pParent->xFullPathname(pParent, zLog, pParent->mxPathname, zFile);
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MASTER_JOURNAL;
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pParent->xDelete(pParent, zFile, 0);
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = pParent->xOpen(pParent, zFile, p->pLog, flags, &flags);
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ){
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(p->aBuf, "sqlite_ostrace1.....", 20);
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->iOffset = 0;
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->nBuf = 20;
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = sqlite3_vfs_register((sqlite3_vfs *)p, 1);
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc ){
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vfslog_finalize(p);
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_vfslog_annotate(const char *zVfs, const char *zMsg){
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pVfs;
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pVfs = sqlite3_vfs_find(zVfs);
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !pVfs || pVfs->xOpen!=vfslogOpen ){
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_ERROR;
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslog_call(pVfs, OS_ANNOTATE, 0, 0, 0, 0, 0);
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfslog_string(pVfs, zMsg);
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char *vfslog_eventname(int eEvent){
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zEvent = 0;
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch( eEvent ){
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OS_CLOSE:             zEvent = "xClose"; break;
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OS_READ:              zEvent = "xRead"; break;
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OS_WRITE:             zEvent = "xWrite"; break;
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OS_TRUNCATE:          zEvent = "xTruncate"; break;
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OS_SYNC:              zEvent = "xSync"; break;
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OS_FILESIZE:          zEvent = "xFilesize"; break;
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OS_LOCK:              zEvent = "xLock"; break;
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OS_UNLOCK:            zEvent = "xUnlock"; break;
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OS_CHECKRESERVEDLOCK: zEvent = "xCheckResLock"; break;
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OS_FILECONTROL:       zEvent = "xFileControl"; break;
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OS_SECTORSIZE:        zEvent = "xSectorSize"; break;
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OS_DEVCHAR:           zEvent = "xDeviceChar"; break;
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OS_OPEN:              zEvent = "xOpen"; break;
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OS_DELETE:            zEvent = "xDelete"; break;
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OS_ACCESS:            zEvent = "xAccess"; break;
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OS_FULLPATHNAME:      zEvent = "xFullPathname"; break;
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OS_RANDOMNESS:        zEvent = "xRandomness"; break;
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OS_SLEEP:             zEvent = "xSleep"; break;
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OS_CURRENTTIME:       zEvent = "xCurrentTime"; break;
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OS_SHMUNMAP:          zEvent = "xShmUnmap"; break;
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OS_SHMLOCK:           zEvent = "xShmLock"; break;
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OS_SHMBARRIER:        zEvent = "xShmBarrier"; break;
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OS_SHMMAP:            zEvent = "xShmMap"; break;
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case OS_ANNOTATE:          zEvent = "annotation"; break;
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return zEvent;
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct VfslogVtab VfslogVtab;
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct VfslogCsr VfslogCsr;
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Virtual table type for the vfslog reader module.
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct VfslogVtab {
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vtab base;              /* Base class */
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *pFd;              /* File descriptor open on vfslog file */
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_int64 nByte;            /* Size of file in bytes */
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zFile;                    /* File name for pFd */
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Virtual table cursor type for the vfslog reader module.
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct VfslogCsr {
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vtab_cursor base;       /* Base class */
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_int64 iRowid;           /* Current rowid. */
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_int64 iOffset;          /* Offset of next record in file */
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zTransient;               /* Transient 'file' string */
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nFile;                      /* Size of array azFile[] */
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char **azFile;                  /* File strings */
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned char aBuf[1024];       /* Current vfs log entry (read from file) */
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static unsigned int get32bits(unsigned char *p){
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3];
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The argument must point to a buffer containing a nul-terminated string.
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If the string begins with an SQL quote character it is overwritten by
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the dequoted version. Otherwise the buffer is left unmodified.
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void dequote(char *z){
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char quote;                     /* Quote character (if any ) */
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  quote = z[0];
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( quote=='[' || quote=='\'' || quote=='"' || quote=='`' ){
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int iIn = 1;                  /* Index of next byte to read from input */
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int iOut = 0;                 /* Index of next byte to write to output */
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( quote=='[' ) quote = ']';
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while( z[iIn] ){
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( z[iIn]==quote ){
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( z[iIn+1]!=quote ) break;
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        z[iOut++] = quote;
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iIn += 2;
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }else{
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        z[iOut++] = z[iIn++];
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    z[iOut] = '\0';
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_OMIT_VIRTUALTABLE
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Connect to or create a vfslog virtual table.
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vlogConnect(
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3 *db,
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *pAux,
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int argc, const char *const*argv,
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vtab **ppVtab,
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char **pzErr
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pVfs;              /* VFS used to read log file */
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags;                      /* flags passed to pVfs->xOpen() */
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VfslogVtab *p;
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nByte;
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zFile;
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *ppVtab = 0;
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pVfs = sqlite3_vfs_find(0);
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nByte = sizeof(VfslogVtab) + pVfs->szOsFile + pVfs->mxPathname;
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p = sqlite3_malloc(nByte);
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p==0 ) return SQLITE_NOMEM;
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(p, 0, nByte);
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->pFd = (sqlite3_file *)&p[1];
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->zFile = &((char *)p->pFd)[pVfs->szOsFile];
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zFile = sqlite3_mprintf("%s", argv[3]);
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !zFile ){
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_free(p);
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_NOMEM;
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dequote(zFile);
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pVfs->xFullPathname(pVfs, zFile, pVfs->mxPathname, p->zFile);
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(zFile);
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MASTER_JOURNAL;
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = pVfs->xOpen(pVfs, p->zFile, p->pFd, flags, &flags);
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ){
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->pFd->pMethods->xFileSize(p->pFd, &p->nByte);
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_declare_vtab(db,
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "CREATE TABLE xxx(event, file, click, rc, size, offset)"
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    );
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *ppVtab = &p->base;
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_free(p);
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** There is no "best-index". This virtual table always does a linear
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** scan of the binary VFS log file.
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vlogBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pIdxInfo->estimatedCost = 10.0;
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Disconnect from or destroy a vfslog virtual table.
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vlogDisconnect(sqlite3_vtab *pVtab){
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VfslogVtab *p = (VfslogVtab *)pVtab;
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->pFd->pMethods ){
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->pFd->pMethods->xClose(p->pFd);
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->pFd->pMethods = 0;
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(p);
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Open a new vfslog cursor.
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vlogOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VfslogCsr *pCsr;                /* Newly allocated cursor object */
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pCsr = sqlite3_malloc(sizeof(VfslogCsr));
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !pCsr ) return SQLITE_NOMEM;
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(pCsr, 0, sizeof(VfslogCsr));
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *ppCursor = &pCsr->base;
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Close a vfslog cursor.
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vlogClose(sqlite3_vtab_cursor *pCursor){
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VfslogCsr *p = (VfslogCsr *)pCursor;
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(i=0; i<p->nFile; i++){
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_free(p->azFile[i]);
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(p->azFile);
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(p->zTransient);
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(p);
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Move a vfslog cursor to the next entry in the file.
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vlogNext(sqlite3_vtab_cursor *pCursor){
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VfslogCsr *pCsr = (VfslogCsr *)pCursor;
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VfslogVtab *p = (VfslogVtab *)pCursor->pVtab;
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nRead;
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(pCsr->zTransient);
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pCsr->zTransient = 0;
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nRead = 24;
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pCsr->iOffset+nRead<=p->nByte ){
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int eEvent;
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = p->pFd->pMethods->xRead(p->pFd, pCsr->aBuf, nRead, pCsr->iOffset);
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    eEvent = get32bits(pCsr->aBuf);
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( (rc==SQLITE_OK)
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     && (eEvent==OS_OPEN || eEvent==OS_DELETE || eEvent==OS_ACCESS)
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ){
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      char buf[4];
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = p->pFd->pMethods->xRead(p->pFd, buf, 4, pCsr->iOffset+nRead);
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nRead += 4;
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc==SQLITE_OK ){
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int nStr = get32bits((unsigned char *)buf);
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        char *zStr = sqlite3_malloc(nStr+1);
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = p->pFd->pMethods->xRead(p->pFd, zStr, nStr, pCsr->iOffset+nRead);
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        zStr[nStr] = '\0';
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        nRead += nStr;
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( eEvent==OS_OPEN ){
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          int iFileid = get32bits(&pCsr->aBuf[4]);
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if( iFileid>=pCsr->nFile ){
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            int nNew = sizeof(pCsr->azFile[0])*(iFileid+1);
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            pCsr->azFile = (char **)sqlite3_realloc(pCsr->azFile, nNew);
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            nNew -= sizeof(pCsr->azFile[0])*pCsr->nFile;
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            memset(&pCsr->azFile[pCsr->nFile], 0, nNew);
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            pCsr->nFile = iFileid+1;
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          sqlite3_free(pCsr->azFile[iFileid]);
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          pCsr->azFile[iFileid] = zStr;
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }else{
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          pCsr->zTransient = zStr;
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pCsr->iRowid += 1;
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pCsr->iOffset += nRead;
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vlogEof(sqlite3_vtab_cursor *pCursor){
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VfslogCsr *pCsr = (VfslogCsr *)pCursor;
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VfslogVtab *p = (VfslogVtab *)pCursor->pVtab;
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (pCsr->iOffset>=p->nByte);
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vlogFilter(
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vtab_cursor *pCursor,
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int idxNum, const char *idxStr,
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int argc, sqlite3_value **argv
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VfslogCsr *pCsr = (VfslogCsr *)pCursor;
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pCsr->iRowid = 0;
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pCsr->iOffset = 20;
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return vlogNext(pCursor);
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vlogColumn(
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vtab_cursor *pCursor,
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_context *ctx,
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int val;
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VfslogCsr *pCsr = (VfslogCsr *)pCursor;
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( i<7 );
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  val = get32bits(&pCsr->aBuf[4*i]);
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch( i ){
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 0: {
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_result_text(ctx, vfslog_eventname(val), -1, SQLITE_STATIC);
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 1: {
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      char *zStr = pCsr->zTransient;
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( val!=0 && val<pCsr->nFile ){
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        zStr = pCsr->azFile[val];
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_result_text(ctx, zStr, -1, SQLITE_TRANSIENT);
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_result_int(ctx, val);
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vlogRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VfslogCsr *pCsr = (VfslogCsr *)pCursor;
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pRowid = pCsr->iRowid;
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_vfslog_register(sqlite3 *db){
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static sqlite3_module vfslog_module = {
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                            /* iVersion */
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vlogConnect,                /* xCreate */
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vlogConnect,                /* xConnect */
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vlogBestIndex,              /* xBestIndex */
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vlogDisconnect,             /* xDisconnect */
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vlogDisconnect,             /* xDestroy */
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vlogOpen,                   /* xOpen - open a cursor */
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vlogClose,                  /* xClose - close a cursor */
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vlogFilter,                 /* xFilter - configure scan constraints */
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vlogNext,                   /* xNext - advance a cursor */
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vlogEof,                    /* xEof - check for end of scan */
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vlogColumn,                 /* xColumn - read data */
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vlogRowid,                  /* xRowid - read data */
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                            /* xUpdate */
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                            /* xBegin */
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                            /* xSync */
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                            /* xCommit */
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                            /* xRollback */
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                            /* xFindMethod */
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                            /* xRename */
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_create_module(db, "vfslog", &vfslog_module, 0);
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* SQLITE_OMIT_VIRTUALTABLE */
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**************************************************************************
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)***************************************************************************
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Tcl interface starts here.
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(SQLITE_TEST) || defined(TCLSH)
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <tcl.h>
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int test_vfslog(
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *clientData,
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Interp *interp,
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int objc,
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Obj *CONST objv[]
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct SqliteDb { sqlite3 *db; };
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3 *db;
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_CmdInfo cmdInfo;
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_ERROR;
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char *strs[] = { "annotate", "finalize", "new",  "register", 0 };
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum VL_enum { VL_ANNOTATE, VL_FINALIZE, VL_NEW, VL_REGISTER };
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iSub;
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( objc<2 ){
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND ...");
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( Tcl_GetIndexFromObj(interp, objv[1], strs, "sub-command", 0, &iSub) ){
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch( (enum VL_enum)iSub ){
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VL_ANNOTATE: {
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int rc;
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      char *zVfs;
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      char *zMsg;
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( objc!=4 ){
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Tcl_WrongNumArgs(interp, 3, objv, "VFS");
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return TCL_ERROR;
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      zVfs = Tcl_GetString(objv[2]);
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      zMsg = Tcl_GetString(objv[3]);
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = sqlite3_vfslog_annotate(zVfs, zMsg);
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc!=SQLITE_OK ){
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Tcl_AppendResult(interp, "failed", 0);
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return TCL_ERROR;
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VL_FINALIZE: {
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int rc;
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      char *zVfs;
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( objc!=3 ){
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Tcl_WrongNumArgs(interp, 2, objv, "VFS");
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return TCL_ERROR;
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      zVfs = Tcl_GetString(objv[2]);
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = sqlite3_vfslog_finalize(zVfs);
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc!=SQLITE_OK ){
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Tcl_AppendResult(interp, "failed", 0);
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return TCL_ERROR;
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VL_NEW: {
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int rc;
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      char *zVfs;
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      char *zParent;
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      char *zLog;
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( objc!=5 ){
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Tcl_WrongNumArgs(interp, 2, objv, "VFS PARENT LOGFILE");
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return TCL_ERROR;
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      zVfs = Tcl_GetString(objv[2]);
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      zParent = Tcl_GetString(objv[3]);
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      zLog = Tcl_GetString(objv[4]);
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( *zParent=='\0' ) zParent = 0;
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = sqlite3_vfslog_new(zVfs, zParent, zLog);
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc!=SQLITE_OK ){
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Tcl_AppendResult(interp, "failed", 0);
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return TCL_ERROR;
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VL_REGISTER: {
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      char *zDb;
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( objc!=3 ){
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Tcl_WrongNumArgs(interp, 2, objv, "DB");
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return TCL_ERROR;
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_OMIT_VIRTUALTABLE
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Tcl_AppendResult(interp, "vfslog not available because of "
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               "SQLITE_OMIT_VIRTUALTABLE", (void*)0);
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return TCL_ERROR;
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      zDb = Tcl_GetString(objv[2]);
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = sqlite3_vfslog_register(db);
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc!=SQLITE_OK ){
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Tcl_AppendResult(interp, "bad sqlite3 handle: ", zDb, (void*)0);
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return TCL_ERROR;
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TCL_OK;
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SqlitetestOsinst_Init(Tcl_Interp *interp){
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_CreateObjCommand(interp, "vfslog", test_vfslog, 0, 0);
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TCL_OK;
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* SQLITE_TEST */
1212