Index: third_party/sqlite/src/src/test_osinst.c |
diff --git a/third_party/sqlite/src/src/test_osinst.c b/third_party/sqlite/src/src/test_osinst.c |
index b60664a338decd9dc459a3226f113a890a22e442..50d6250e6c31fd0dc512f6849d23c90e99fa3dd2 100644 |
--- a/third_party/sqlite/src/src/test_osinst.c |
+++ b/third_party/sqlite/src/src/test_osinst.c |
@@ -13,91 +13,72 @@ |
** This file contains the implementation of an SQLite vfs wrapper that |
** adds instrumentation to all vfs and file methods. C and Tcl interfaces |
** are provided to control the instrumentation. |
-** |
-** $Id: test_osinst.c,v 1.19 2009/01/08 17:57:32 danielk1977 Exp $ |
*/ |
-#ifdef SQLITE_ENABLE_INSTVFS |
/* |
-** C interface: |
-** |
-** sqlite3_instvfs_create() |
-** sqlite3_instvfs_destroy() |
-** sqlite3_instvfs_configure() |
-** |
-** sqlite3_instvfs_reset() |
-** sqlite3_instvfs_get() |
-** |
-** sqlite3_instvfs_binarylog |
-** sqlite3_instvfs_binarylog_marker |
-** |
-** Tcl interface (omitted if SQLITE_TEST is not set): |
-** |
-** sqlite3_instvfs create NAME ?PARENT? |
+** This module contains code for a wrapper VFS that causes a log of |
+** most VFS calls to be written into a nominated file on disk. The log |
+** is stored in a compressed binary format to reduce the amount of IO |
+** overhead introduced into the application by logging. |
** |
-** Create and register new vfs called $NAME, which is a wrapper around |
-** the existing vfs $PARENT. If the PARENT argument is omitted, the |
-** new vfs is a wrapper around the current default vfs. |
+** All calls on sqlite3_file objects except xFileControl() are logged. |
+** Additionally, calls to the xAccess(), xOpen(), and xDelete() |
+** methods are logged. The other sqlite3_vfs object methods (xDlXXX, |
+** xRandomness, xSleep, xCurrentTime, xGetLastError and xCurrentTimeInt64) |
+** are not logged. |
** |
-** sqlite3_instvfs destroy NAME |
+** The binary log files are read using a virtual table implementation |
+** also contained in this file. |
** |
-** Deregister and destroy the vfs named $NAME, which must have been |
-** created by an earlier invocation of [sqlite3_instvfs create]. |
+** CREATING LOG FILES: |
** |
-** sqlite3_instvfs configure NAME SCRIPT |
+** int sqlite3_vfslog_new( |
+** const char *zVfs, // Name of new VFS |
+** const char *zParentVfs, // Name of parent VFS (or NULL) |
+** const char *zLog // Name of log file to write to |
+** ); |
** |
-** Configure the callback script for the vfs $NAME, which much have |
-** been created by an earlier invocation of [sqlite3_instvfs create]. |
-** After a callback script has been configured, it is invoked each |
-** time a vfs or file method is called by SQLite. Before invoking |
-** the callback script, five arguments are appended to it: |
+** int sqlite3_vfslog_finalize(const char *zVfs); |
** |
-** * The name of the invoked method - i.e. "xRead". |
+** ANNOTATING LOG FILES: |
** |
-** * The time consumed by the method call as measured by |
-** sqlite3Hwtime() (an integer value) |
+** To write an arbitrary message into a log file: |
** |
-** * A string value with a different meaning for different calls. |
-** For file methods, the name of the file being operated on. For |
-** other methods it is the filename argument, if any. |
+** int sqlite3_vfslog_annotate(const char *zVfs, const char *zMsg); |
** |
-** * A 32-bit integer value with a call-specific meaning. |
+** READING LOG FILES: |
** |
-** * A 64-bit integer value. For xRead() and xWrite() calls this |
-** is the file offset being written to or read from. Unused by |
-** all other calls. |
+** Log files are read using the "vfslog" virtual table implementation |
+** in this file. To register the virtual table with SQLite, use: |
** |
-** sqlite3_instvfs reset NAME |
+** int sqlite3_vfslog_register(sqlite3 *db); |
** |
-** Zero the internal event counters associated with vfs $NAME, |
-** which must have been created by an earlier invocation of |
-** [sqlite3_instvfs create]. |
+** Then, if the log file is named "vfs.log", the following SQL command: |
** |
-** sqlite3_instvfs report NAME |
+** CREATE VIRTUAL TABLE v USING vfslog('vfs.log'); |
** |
-** Return the values of the internal event counters associated |
-** with vfs $NAME. The report format is a list with one element |
-** for each method call (xWrite, xRead etc.). Each element is |
-** itself a list with three elements: |
+** creates a virtual table with 6 columns, as follows: |
** |
-** * The name of the method call - i.e. "xWrite", |
-** * The total number of calls to the method (an integer). |
-** * The aggregate time consumed by all calls to the method as |
-** measured by sqlite3Hwtime() (an integer). |
+** CREATE TABLE v( |
+** event TEXT, // "xOpen", "xRead" etc. |
+** file TEXT, // Name of file this call applies to |
+** clicks INTEGER, // Time spent in call |
+** rc INTEGER, // Return value |
+** size INTEGER, // Bytes read or written |
+** offset INTEGER // File offset read or written |
+** ); |
*/ |
#include "sqlite3.h" |
#include <string.h> |
#include <assert.h> |
+ |
/* |
-** Maximum pathname length supported by the inst backend. |
+** Maximum pathname length supported by the vfslog backend. |
*/ |
#define INST_MAX_PATHNAME 512 |
- |
-/* File methods */ |
-/* Vfs methods */ |
#define OS_ACCESS 1 |
#define OS_CHECKRESERVEDLOCK 2 |
#define OS_CLOSE 3 |
@@ -117,281 +98,401 @@ |
#define OS_TRUNCATE 18 |
#define OS_UNLOCK 19 |
#define OS_WRITE 20 |
+#define OS_SHMUNMAP 22 |
+#define OS_SHMMAP 23 |
+#define OS_SHMLOCK 25 |
+#define OS_SHMBARRIER 26 |
+#define OS_ANNOTATE 28 |
+ |
+#define OS_NUMEVENTS 29 |
+ |
+#define VFSLOG_BUFFERSIZE 8192 |
+ |
+typedef struct VfslogVfs VfslogVfs; |
+typedef struct VfslogFile VfslogFile; |
+ |
+struct VfslogVfs { |
+ sqlite3_vfs base; /* VFS methods */ |
+ sqlite3_vfs *pVfs; /* Parent VFS */ |
+ int iNextFileId; /* Next file id */ |
+ sqlite3_file *pLog; /* Log file handle */ |
+ sqlite3_int64 iOffset; /* Log file offset of start of write buffer */ |
+ int nBuf; /* Number of valid bytes in aBuf[] */ |
+ char aBuf[VFSLOG_BUFFERSIZE]; /* Write buffer */ |
+}; |
-#define OS_NUMEVENTS 21 |
- |
-#define BINARYLOG_STRING 30 |
-#define BINARYLOG_MARKER 31 |
- |
-#define BINARYLOG_PREPARE_V2 64 |
-#define BINARYLOG_STEP 65 |
-#define BINARYLOG_FINALIZE 66 |
- |
-struct InstVfs { |
- sqlite3_vfs base; |
- sqlite3_vfs *pVfs; |
- |
- void *pClient; |
- void (*xDel)(void *); |
- void (*xCall)(void *, int, int, sqlite3_int64, int, const char *, int, int, sqlite3_int64); |
- |
- /* Counters */ |
- sqlite3_int64 aTime[OS_NUMEVENTS]; |
- int aCount[OS_NUMEVENTS]; |
- |
- int iNextFileId; |
+struct VfslogFile { |
+ sqlite3_file base; /* IO methods */ |
+ sqlite3_file *pReal; /* Underlying file handle */ |
+ sqlite3_vfs *pVfslog; /* Associated VsflogVfs object */ |
+ int iFileId; /* File id number */ |
}; |
-typedef struct InstVfs InstVfs; |
-#define REALVFS(p) (((InstVfs *)(p))->pVfs) |
+#define REALVFS(p) (((VfslogVfs *)(p))->pVfs) |
+ |
-typedef struct inst_file inst_file; |
-struct inst_file { |
- sqlite3_file base; |
- sqlite3_file *pReal; |
- InstVfs *pInstVfs; |
- const char *zName; |
- int iFileId; /* File id number */ |
- int flags; |
-}; |
/* |
-** Method declarations for inst_file. |
+** Method declarations for vfslog_file. |
*/ |
-static int instClose(sqlite3_file*); |
-static int instRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); |
-static int instWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst); |
-static int instTruncate(sqlite3_file*, sqlite3_int64 size); |
-static int instSync(sqlite3_file*, int flags); |
-static int instFileSize(sqlite3_file*, sqlite3_int64 *pSize); |
-static int instLock(sqlite3_file*, int); |
-static int instUnlock(sqlite3_file*, int); |
-static int instCheckReservedLock(sqlite3_file*, int *pResOut); |
-static int instFileControl(sqlite3_file*, int op, void *pArg); |
-static int instSectorSize(sqlite3_file*); |
-static int instDeviceCharacteristics(sqlite3_file*); |
+static int vfslogClose(sqlite3_file*); |
+static int vfslogRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); |
+static int vfslogWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst); |
+static int vfslogTruncate(sqlite3_file*, sqlite3_int64 size); |
+static int vfslogSync(sqlite3_file*, int flags); |
+static int vfslogFileSize(sqlite3_file*, sqlite3_int64 *pSize); |
+static int vfslogLock(sqlite3_file*, int); |
+static int vfslogUnlock(sqlite3_file*, int); |
+static int vfslogCheckReservedLock(sqlite3_file*, int *pResOut); |
+static int vfslogFileControl(sqlite3_file*, int op, void *pArg); |
+static int vfslogSectorSize(sqlite3_file*); |
+static int vfslogDeviceCharacteristics(sqlite3_file*); |
+ |
+static int vfslogShmLock(sqlite3_file *pFile, int ofst, int n, int flags); |
+static int vfslogShmMap(sqlite3_file *pFile,int,int,int,volatile void **); |
+static void vfslogShmBarrier(sqlite3_file*); |
+static int vfslogShmUnmap(sqlite3_file *pFile, int deleteFlag); |
/* |
-** Method declarations for inst_vfs. |
+** Method declarations for vfslog_vfs. |
*/ |
-static int instOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *); |
-static int instDelete(sqlite3_vfs*, const char *zName, int syncDir); |
-static int instAccess(sqlite3_vfs*, const char *zName, int flags, int *); |
-static int instFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut); |
-static void *instDlOpen(sqlite3_vfs*, const char *zFilename); |
-static void instDlError(sqlite3_vfs*, int nByte, char *zErrMsg); |
-static void (*instDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void); |
-static void instDlClose(sqlite3_vfs*, void*); |
-static int instRandomness(sqlite3_vfs*, int nByte, char *zOut); |
-static int instSleep(sqlite3_vfs*, int microseconds); |
-static int instCurrentTime(sqlite3_vfs*, double*); |
- |
-static void binarylog_blob(sqlite3_vfs *, const char *, int, int); |
- |
-static sqlite3_vfs inst_vfs = { |
- 1, /* iVersion */ |
- sizeof(inst_file), /* szOsFile */ |
- INST_MAX_PATHNAME, /* mxPathname */ |
- 0, /* pNext */ |
- 0, /* zName */ |
- 0, /* pAppData */ |
- instOpen, /* xOpen */ |
- instDelete, /* xDelete */ |
- instAccess, /* xAccess */ |
- instFullPathname, /* xFullPathname */ |
- instDlOpen, /* xDlOpen */ |
- instDlError, /* xDlError */ |
- instDlSym, /* xDlSym */ |
- instDlClose, /* xDlClose */ |
- instRandomness, /* xRandomness */ |
- instSleep, /* xSleep */ |
- instCurrentTime /* xCurrentTime */ |
+static int vfslogOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *); |
+static int vfslogDelete(sqlite3_vfs*, const char *zName, int syncDir); |
+static int vfslogAccess(sqlite3_vfs*, const char *zName, int flags, int *); |
+static int vfslogFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut); |
+static void *vfslogDlOpen(sqlite3_vfs*, const char *zFilename); |
+static void vfslogDlError(sqlite3_vfs*, int nByte, char *zErrMsg); |
+static void (*vfslogDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void); |
+static void vfslogDlClose(sqlite3_vfs*, void*); |
+static int vfslogRandomness(sqlite3_vfs*, int nByte, char *zOut); |
+static int vfslogSleep(sqlite3_vfs*, int microseconds); |
+static int vfslogCurrentTime(sqlite3_vfs*, double*); |
+ |
+static int vfslogGetLastError(sqlite3_vfs*, int, char *); |
+static int vfslogCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*); |
+ |
+static sqlite3_vfs vfslog_vfs = { |
+ 1, /* iVersion */ |
+ sizeof(VfslogFile), /* szOsFile */ |
+ INST_MAX_PATHNAME, /* mxPathname */ |
+ 0, /* pNext */ |
+ 0, /* zName */ |
+ 0, /* pAppData */ |
+ vfslogOpen, /* xOpen */ |
+ vfslogDelete, /* xDelete */ |
+ vfslogAccess, /* xAccess */ |
+ vfslogFullPathname, /* xFullPathname */ |
+ vfslogDlOpen, /* xDlOpen */ |
+ vfslogDlError, /* xDlError */ |
+ vfslogDlSym, /* xDlSym */ |
+ vfslogDlClose, /* xDlClose */ |
+ vfslogRandomness, /* xRandomness */ |
+ vfslogSleep, /* xSleep */ |
+ vfslogCurrentTime, /* xCurrentTime */ |
+ vfslogGetLastError, /* xGetLastError */ |
+ vfslogCurrentTimeInt64 /* xCurrentTime */ |
}; |
-static sqlite3_io_methods inst_io_methods = { |
- 1, /* iVersion */ |
- instClose, /* xClose */ |
- instRead, /* xRead */ |
- instWrite, /* xWrite */ |
- instTruncate, /* xTruncate */ |
- instSync, /* xSync */ |
- instFileSize, /* xFileSize */ |
- instLock, /* xLock */ |
- instUnlock, /* xUnlock */ |
- instCheckReservedLock, /* xCheckReservedLock */ |
- instFileControl, /* xFileControl */ |
- instSectorSize, /* xSectorSize */ |
- instDeviceCharacteristics /* xDeviceCharacteristics */ |
+static sqlite3_io_methods vfslog_io_methods = { |
+ 2, /* iVersion */ |
+ vfslogClose, /* xClose */ |
+ vfslogRead, /* xRead */ |
+ vfslogWrite, /* xWrite */ |
+ vfslogTruncate, /* xTruncate */ |
+ vfslogSync, /* xSync */ |
+ vfslogFileSize, /* xFileSize */ |
+ vfslogLock, /* xLock */ |
+ vfslogUnlock, /* xUnlock */ |
+ vfslogCheckReservedLock, /* xCheckReservedLock */ |
+ vfslogFileControl, /* xFileControl */ |
+ vfslogSectorSize, /* xSectorSize */ |
+ vfslogDeviceCharacteristics, /* xDeviceCharacteristics */ |
+ vfslogShmMap, /* xShmMap */ |
+ vfslogShmLock, /* xShmLock */ |
+ vfslogShmBarrier, /* xShmBarrier */ |
+ vfslogShmUnmap /* xShmUnmap */ |
}; |
-/* |
-** hwtime.h contains inline assembler code for implementing |
-** high-performance timing routines. |
-*/ |
-#include "hwtime.h" |
- |
-#define OS_TIME_IO(eEvent, A, B, Call) { \ |
- inst_file *p = (inst_file *)pFile; \ |
- InstVfs *pInstVfs = p->pInstVfs; \ |
- int rc; \ |
- sqlite_uint64 t = sqlite3Hwtime(); \ |
- rc = Call; \ |
- t = sqlite3Hwtime() - t; \ |
- pInstVfs->aTime[eEvent] += t; \ |
- pInstVfs->aCount[eEvent] += 1; \ |
- if( pInstVfs->xCall ){ \ |
- pInstVfs->xCall( \ |
- pInstVfs->pClient,eEvent,p->iFileId,t,rc,p->zName,p->flags,A,B \ |
- ); \ |
- } \ |
- return rc; \ |
+#if SQLITE_OS_UNIX && !defined(NO_GETTOD) |
+#include <sys/time.h> |
+static sqlite3_uint64 vfslog_time(){ |
+ struct timeval sTime; |
+ gettimeofday(&sTime, 0); |
+ return sTime.tv_usec + (sqlite3_uint64)sTime.tv_sec * 1000000; |
} |
- |
-#define OS_TIME_VFS(eEvent, Z, flags, A, B, Call) { \ |
- InstVfs *pInstVfs = (InstVfs *)pVfs; \ |
- int rc; \ |
- sqlite_uint64 t = sqlite3Hwtime(); \ |
- rc = Call; \ |
- t = sqlite3Hwtime() - t; \ |
- pInstVfs->aTime[eEvent] += t; \ |
- pInstVfs->aCount[eEvent] += 1; \ |
- if( pInstVfs->xCall ){ \ |
- pInstVfs->xCall(pInstVfs->pClient,eEvent,0, t, rc, Z, flags, A, B); \ |
- } \ |
- return rc; \ |
+#elif SQLITE_OS_WIN |
+#include <windows.h> |
+#include <time.h> |
+static sqlite3_uint64 vfslog_time(){ |
+ FILETIME ft; |
+ sqlite3_uint64 u64time = 0; |
+ |
+ GetSystemTimeAsFileTime(&ft); |
+ |
+ u64time |= ft.dwHighDateTime; |
+ u64time <<= 32; |
+ u64time |= ft.dwLowDateTime; |
+ |
+ /* ft is 100-nanosecond intervals, we want microseconds */ |
+ return u64time /(sqlite3_uint64)10; |
+} |
+#else |
+static sqlite3_uint64 vfslog_time(){ |
+ return 0; |
} |
+#endif |
+ |
+static void vfslog_call(sqlite3_vfs *, int, int, int, int, int, int); |
+static void vfslog_string(sqlite3_vfs *, const char *); |
/* |
-** Close an inst-file. |
+** Close an vfslog-file. |
*/ |
-static int instClose(sqlite3_file *pFile){ |
- OS_TIME_IO(OS_CLOSE, 0, 0, |
- (p->pReal->pMethods ? p->pReal->pMethods->xClose(p->pReal) : SQLITE_OK) |
- ); |
+static int vfslogClose(sqlite3_file *pFile){ |
+ sqlite3_uint64 t; |
+ int rc = SQLITE_OK; |
+ VfslogFile *p = (VfslogFile *)pFile; |
+ |
+ t = vfslog_time(); |
+ if( p->pReal->pMethods ){ |
+ rc = p->pReal->pMethods->xClose(p->pReal); |
+ } |
+ t = vfslog_time() - t; |
+ vfslog_call(p->pVfslog, OS_CLOSE, p->iFileId, t, rc, 0, 0); |
+ return rc; |
} |
/* |
-** Read data from an inst-file. |
+** Read data from an vfslog-file. |
*/ |
-static int instRead( |
+static int vfslogRead( |
sqlite3_file *pFile, |
void *zBuf, |
int iAmt, |
sqlite_int64 iOfst |
){ |
- sqlite3_vfs *pVfs = (sqlite3_vfs *)(((inst_file *)pFile)->pInstVfs); |
- OS_TIME_IO(OS_READ, iAmt, (binarylog_blob(pVfs, zBuf, iAmt, 1), iOfst), |
- p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst) |
- ); |
+ int rc; |
+ sqlite3_uint64 t; |
+ VfslogFile *p = (VfslogFile *)pFile; |
+ t = vfslog_time(); |
+ rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst); |
+ t = vfslog_time() - t; |
+ vfslog_call(p->pVfslog, OS_READ, p->iFileId, t, rc, iAmt, (int)iOfst); |
+ return rc; |
} |
/* |
-** Write data to an inst-file. |
+** Write data to an vfslog-file. |
*/ |
-static int instWrite( |
+static int vfslogWrite( |
sqlite3_file *pFile, |
const void *z, |
int iAmt, |
sqlite_int64 iOfst |
){ |
- sqlite3_vfs *pVfs = (sqlite3_vfs *)(((inst_file *)pFile)->pInstVfs); |
- binarylog_blob(pVfs, z, iAmt, 1); |
- OS_TIME_IO(OS_WRITE, iAmt, iOfst, |
- p->pReal->pMethods->xWrite(p->pReal, z, iAmt, iOfst) |
- ); |
+ int rc; |
+ sqlite3_uint64 t; |
+ VfslogFile *p = (VfslogFile *)pFile; |
+ t = vfslog_time(); |
+ rc = p->pReal->pMethods->xWrite(p->pReal, z, iAmt, iOfst); |
+ t = vfslog_time() - t; |
+ vfslog_call(p->pVfslog, OS_WRITE, p->iFileId, t, rc, iAmt, (int)iOfst); |
+ return rc; |
} |
/* |
-** Truncate an inst-file. |
+** Truncate an vfslog-file. |
*/ |
-static int instTruncate(sqlite3_file *pFile, sqlite_int64 size){ |
- OS_TIME_IO(OS_TRUNCATE, 0, (int)size, |
- p->pReal->pMethods->xTruncate(p->pReal, size) |
- ); |
+static int vfslogTruncate(sqlite3_file *pFile, sqlite_int64 size){ |
+ int rc; |
+ sqlite3_uint64 t; |
+ VfslogFile *p = (VfslogFile *)pFile; |
+ t = vfslog_time(); |
+ rc = p->pReal->pMethods->xTruncate(p->pReal, size); |
+ t = vfslog_time() - t; |
+ vfslog_call(p->pVfslog, OS_TRUNCATE, p->iFileId, t, rc, 0, (int)size); |
+ return rc; |
} |
/* |
-** Sync an inst-file. |
+** Sync an vfslog-file. |
*/ |
-static int instSync(sqlite3_file *pFile, int flags){ |
- OS_TIME_IO(OS_SYNC, flags, 0, p->pReal->pMethods->xSync(p->pReal, flags)); |
+static int vfslogSync(sqlite3_file *pFile, int flags){ |
+ int rc; |
+ sqlite3_uint64 t; |
+ VfslogFile *p = (VfslogFile *)pFile; |
+ t = vfslog_time(); |
+ rc = p->pReal->pMethods->xSync(p->pReal, flags); |
+ t = vfslog_time() - t; |
+ vfslog_call(p->pVfslog, OS_SYNC, p->iFileId, t, rc, flags, 0); |
+ return rc; |
} |
/* |
-** Return the current file-size of an inst-file. |
+** Return the current file-size of an vfslog-file. |
*/ |
-static int instFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ |
- OS_TIME_IO(OS_FILESIZE, (int)(*pSize), 0, |
- p->pReal->pMethods->xFileSize(p->pReal, pSize) |
- ); |
+static int vfslogFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ |
+ int rc; |
+ sqlite3_uint64 t; |
+ VfslogFile *p = (VfslogFile *)pFile; |
+ t = vfslog_time(); |
+ rc = p->pReal->pMethods->xFileSize(p->pReal, pSize); |
+ t = vfslog_time() - t; |
+ vfslog_call(p->pVfslog, OS_FILESIZE, p->iFileId, t, rc, 0, (int)*pSize); |
+ return rc; |
} |
/* |
-** Lock an inst-file. |
+** Lock an vfslog-file. |
*/ |
-static int instLock(sqlite3_file *pFile, int eLock){ |
- OS_TIME_IO(OS_LOCK, eLock, 0, p->pReal->pMethods->xLock(p->pReal, eLock)); |
+static int vfslogLock(sqlite3_file *pFile, int eLock){ |
+ int rc; |
+ sqlite3_uint64 t; |
+ VfslogFile *p = (VfslogFile *)pFile; |
+ t = vfslog_time(); |
+ rc = p->pReal->pMethods->xLock(p->pReal, eLock); |
+ t = vfslog_time() - t; |
+ vfslog_call(p->pVfslog, OS_LOCK, p->iFileId, t, rc, eLock, 0); |
+ return rc; |
} |
/* |
-** Unlock an inst-file. |
+** Unlock an vfslog-file. |
*/ |
-static int instUnlock(sqlite3_file *pFile, int eLock){ |
- OS_TIME_IO(OS_UNLOCK, eLock, 0, p->pReal->pMethods->xUnlock(p->pReal, eLock)); |
+static int vfslogUnlock(sqlite3_file *pFile, int eLock){ |
+ int rc; |
+ sqlite3_uint64 t; |
+ VfslogFile *p = (VfslogFile *)pFile; |
+ t = vfslog_time(); |
+ rc = p->pReal->pMethods->xUnlock(p->pReal, eLock); |
+ t = vfslog_time() - t; |
+ vfslog_call(p->pVfslog, OS_UNLOCK, p->iFileId, t, rc, eLock, 0); |
+ return rc; |
} |
/* |
-** Check if another file-handle holds a RESERVED lock on an inst-file. |
+** Check if another file-handle holds a RESERVED lock on an vfslog-file. |
*/ |
-static int instCheckReservedLock(sqlite3_file *pFile, int *pResOut){ |
- OS_TIME_IO(OS_CHECKRESERVEDLOCK, 0, 0, |
- p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut) |
- ); |
+static int vfslogCheckReservedLock(sqlite3_file *pFile, int *pResOut){ |
+ int rc; |
+ sqlite3_uint64 t; |
+ VfslogFile *p = (VfslogFile *)pFile; |
+ t = vfslog_time(); |
+ rc = p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut); |
+ t = vfslog_time() - t; |
+ vfslog_call(p->pVfslog, OS_CHECKRESERVEDLOCK, p->iFileId, t, rc, *pResOut, 0); |
+ return rc; |
} |
/* |
-** File control method. For custom operations on an inst-file. |
+** File control method. For custom operations on an vfslog-file. |
*/ |
-static int instFileControl(sqlite3_file *pFile, int op, void *pArg){ |
- OS_TIME_IO(OS_FILECONTROL, 0, 0, p->pReal->pMethods->xFileControl(p->pReal, op, pArg)); |
+static int vfslogFileControl(sqlite3_file *pFile, int op, void *pArg){ |
+ VfslogFile *p = (VfslogFile *)pFile; |
+ return p->pReal->pMethods->xFileControl(p->pReal, op, pArg); |
} |
/* |
-** Return the sector-size in bytes for an inst-file. |
+** Return the sector-size in bytes for an vfslog-file. |
*/ |
-static int instSectorSize(sqlite3_file *pFile){ |
- OS_TIME_IO(OS_SECTORSIZE, 0, 0, p->pReal->pMethods->xSectorSize(p->pReal)); |
+static int vfslogSectorSize(sqlite3_file *pFile){ |
+ int rc; |
+ sqlite3_uint64 t; |
+ VfslogFile *p = (VfslogFile *)pFile; |
+ t = vfslog_time(); |
+ rc = p->pReal->pMethods->xSectorSize(p->pReal); |
+ t = vfslog_time() - t; |
+ vfslog_call(p->pVfslog, OS_SECTORSIZE, p->iFileId, t, rc, 0, 0); |
+ return rc; |
} |
/* |
-** Return the device characteristic flags supported by an inst-file. |
+** Return the device characteristic flags supported by an vfslog-file. |
*/ |
-static int instDeviceCharacteristics(sqlite3_file *pFile){ |
- OS_TIME_IO(OS_DEVCHAR, 0, 0, p->pReal->pMethods->xDeviceCharacteristics(p->pReal)); |
+static int vfslogDeviceCharacteristics(sqlite3_file *pFile){ |
+ int rc; |
+ sqlite3_uint64 t; |
+ VfslogFile *p = (VfslogFile *)pFile; |
+ t = vfslog_time(); |
+ rc = p->pReal->pMethods->xDeviceCharacteristics(p->pReal); |
+ t = vfslog_time() - t; |
+ vfslog_call(p->pVfslog, OS_DEVCHAR, p->iFileId, t, rc, 0, 0); |
+ return rc; |
+} |
+ |
+static int vfslogShmLock(sqlite3_file *pFile, int ofst, int n, int flags){ |
+ int rc; |
+ sqlite3_uint64 t; |
+ VfslogFile *p = (VfslogFile *)pFile; |
+ t = vfslog_time(); |
+ rc = p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags); |
+ t = vfslog_time() - t; |
+ vfslog_call(p->pVfslog, OS_SHMLOCK, p->iFileId, t, rc, 0, 0); |
+ return rc; |
} |
+static int vfslogShmMap( |
+ sqlite3_file *pFile, |
+ int iRegion, |
+ int szRegion, |
+ int isWrite, |
+ volatile void **pp |
+){ |
+ int rc; |
+ sqlite3_uint64 t; |
+ VfslogFile *p = (VfslogFile *)pFile; |
+ t = vfslog_time(); |
+ rc = p->pReal->pMethods->xShmMap(p->pReal, iRegion, szRegion, isWrite, pp); |
+ t = vfslog_time() - t; |
+ vfslog_call(p->pVfslog, OS_SHMMAP, p->iFileId, t, rc, 0, 0); |
+ return rc; |
+} |
+static void vfslogShmBarrier(sqlite3_file *pFile){ |
+ sqlite3_uint64 t; |
+ VfslogFile *p = (VfslogFile *)pFile; |
+ t = vfslog_time(); |
+ p->pReal->pMethods->xShmBarrier(p->pReal); |
+ t = vfslog_time() - t; |
+ vfslog_call(p->pVfslog, OS_SHMBARRIER, p->iFileId, t, SQLITE_OK, 0, 0); |
+} |
+static int vfslogShmUnmap(sqlite3_file *pFile, int deleteFlag){ |
+ int rc; |
+ sqlite3_uint64 t; |
+ VfslogFile *p = (VfslogFile *)pFile; |
+ t = vfslog_time(); |
+ rc = p->pReal->pMethods->xShmUnmap(p->pReal, deleteFlag); |
+ t = vfslog_time() - t; |
+ vfslog_call(p->pVfslog, OS_SHMUNMAP, p->iFileId, t, rc, 0, 0); |
+ return rc; |
+} |
+ |
/* |
-** Open an inst file handle. |
+** Open an vfslog file handle. |
*/ |
-static int instOpen( |
+static int vfslogOpen( |
sqlite3_vfs *pVfs, |
const char *zName, |
sqlite3_file *pFile, |
int flags, |
int *pOutFlags |
){ |
- inst_file *p = (inst_file *)pFile; |
- pFile->pMethods = &inst_io_methods; |
+ int rc; |
+ sqlite3_uint64 t; |
+ VfslogFile *p = (VfslogFile *)pFile; |
+ VfslogVfs *pLog = (VfslogVfs *)pVfs; |
+ |
+ pFile->pMethods = &vfslog_io_methods; |
p->pReal = (sqlite3_file *)&p[1]; |
- p->pInstVfs = (InstVfs *)pVfs; |
- p->zName = zName; |
- p->flags = flags; |
- p->iFileId = ++p->pInstVfs->iNextFileId; |
- |
- binarylog_blob(pVfs, zName, -1, 0); |
- OS_TIME_VFS(OS_OPEN, zName, flags, p->iFileId, 0, |
- REALVFS(pVfs)->xOpen(REALVFS(pVfs), zName, p->pReal, flags, pOutFlags) |
- ); |
+ p->pVfslog = pVfs; |
+ p->iFileId = ++pLog->iNextFileId; |
+ |
+ t = vfslog_time(); |
+ rc = REALVFS(pVfs)->xOpen(REALVFS(pVfs), zName, p->pReal, flags, pOutFlags); |
+ t = vfslog_time() - t; |
+ |
+ vfslog_call(pVfs, OS_OPEN, p->iFileId, t, rc, 0, 0); |
+ vfslog_string(pVfs, zName); |
+ return rc; |
} |
/* |
@@ -399,27 +500,35 @@ static int instOpen( |
** ensure the file-system modifications are synced to disk before |
** returning. |
*/ |
-static int instDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ |
- binarylog_blob(pVfs, zPath, -1, 0); |
- OS_TIME_VFS(OS_DELETE, zPath, 0, dirSync, 0, |
- REALVFS(pVfs)->xDelete(REALVFS(pVfs), zPath, dirSync) |
- ); |
+static int vfslogDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ |
+ int rc; |
+ sqlite3_uint64 t; |
+ t = vfslog_time(); |
+ rc = REALVFS(pVfs)->xDelete(REALVFS(pVfs), zPath, dirSync); |
+ t = vfslog_time() - t; |
+ vfslog_call(pVfs, OS_DELETE, 0, t, rc, dirSync, 0); |
+ vfslog_string(pVfs, zPath); |
+ return rc; |
} |
/* |
** Test for access permissions. Return true if the requested permission |
** is available, or false otherwise. |
*/ |
-static int instAccess( |
+static int vfslogAccess( |
sqlite3_vfs *pVfs, |
const char *zPath, |
int flags, |
int *pResOut |
){ |
- binarylog_blob(pVfs, zPath, -1, 0); |
- OS_TIME_VFS(OS_ACCESS, zPath, 0, flags, *pResOut, |
- REALVFS(pVfs)->xAccess(REALVFS(pVfs), zPath, flags, pResOut) |
- ); |
+ int rc; |
+ sqlite3_uint64 t; |
+ t = vfslog_time(); |
+ rc = REALVFS(pVfs)->xAccess(REALVFS(pVfs), zPath, flags, pResOut); |
+ t = vfslog_time() - t; |
+ vfslog_call(pVfs, OS_ACCESS, 0, t, rc, flags, *pResOut); |
+ vfslog_string(pVfs, zPath); |
+ return rc; |
} |
/* |
@@ -427,21 +536,19 @@ static int instAccess( |
** to the pathname in zPath. zOut is guaranteed to point to a buffer |
** of at least (INST_MAX_PATHNAME+1) bytes. |
*/ |
-static int instFullPathname( |
+static int vfslogFullPathname( |
sqlite3_vfs *pVfs, |
const char *zPath, |
int nOut, |
char *zOut |
){ |
- OS_TIME_VFS( OS_FULLPATHNAME, zPath, 0, 0, 0, |
- REALVFS(pVfs)->xFullPathname(REALVFS(pVfs), zPath, nOut, zOut); |
- ); |
+ return REALVFS(pVfs)->xFullPathname(REALVFS(pVfs), zPath, nOut, zOut); |
} |
/* |
** Open the dynamic library located at zPath and return a handle. |
*/ |
-static void *instDlOpen(sqlite3_vfs *pVfs, const char *zPath){ |
+static void *vfslogDlOpen(sqlite3_vfs *pVfs, const char *zPath){ |
return REALVFS(pVfs)->xDlOpen(REALVFS(pVfs), zPath); |
} |
@@ -450,21 +557,21 @@ static void *instDlOpen(sqlite3_vfs *pVfs, const char *zPath){ |
** utf-8 string describing the most recent error encountered associated |
** with dynamic libraries. |
*/ |
-static void instDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){ |
+static void vfslogDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){ |
REALVFS(pVfs)->xDlError(REALVFS(pVfs), nByte, zErrMsg); |
} |
/* |
** Return a pointer to the symbol zSymbol in the dynamic library pHandle. |
*/ |
-static void (*instDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){ |
+static void (*vfslogDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){ |
return REALVFS(pVfs)->xDlSym(REALVFS(pVfs), p, zSym); |
} |
/* |
** Close the dynamic library handle pHandle. |
*/ |
-static void instDlClose(sqlite3_vfs *pVfs, void *pHandle){ |
+static void vfslogDlClose(sqlite3_vfs *pVfs, void *pHandle){ |
REALVFS(pVfs)->xDlClose(REALVFS(pVfs), pHandle); |
} |
@@ -472,99 +579,185 @@ static void instDlClose(sqlite3_vfs *pVfs, void *pHandle){ |
** Populate the buffer pointed to by zBufOut with nByte bytes of |
** random data. |
*/ |
-static int instRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ |
- OS_TIME_VFS( OS_RANDOMNESS, 0, 0, nByte, 0, |
- REALVFS(pVfs)->xRandomness(REALVFS(pVfs), nByte, zBufOut); |
- ); |
+static int vfslogRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ |
+ return REALVFS(pVfs)->xRandomness(REALVFS(pVfs), nByte, zBufOut); |
} |
/* |
** Sleep for nMicro microseconds. Return the number of microseconds |
** actually slept. |
*/ |
-static int instSleep(sqlite3_vfs *pVfs, int nMicro){ |
- OS_TIME_VFS( OS_SLEEP, 0, 0, nMicro, 0, |
- REALVFS(pVfs)->xSleep(REALVFS(pVfs), nMicro) |
- ); |
+static int vfslogSleep(sqlite3_vfs *pVfs, int nMicro){ |
+ return REALVFS(pVfs)->xSleep(REALVFS(pVfs), nMicro); |
} |
/* |
** Return the current time as a Julian Day number in *pTimeOut. |
*/ |
-static int instCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ |
- OS_TIME_VFS( OS_CURRENTTIME, 0, 0, 0, 0, |
- REALVFS(pVfs)->xCurrentTime(REALVFS(pVfs), pTimeOut) |
- ); |
+static int vfslogCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ |
+ return REALVFS(pVfs)->xCurrentTime(REALVFS(pVfs), pTimeOut); |
} |
-sqlite3_vfs *sqlite3_instvfs_create(const char *zName, const char *zParent){ |
- int nByte; |
- InstVfs *p; |
- sqlite3_vfs *pParent; |
+static int vfslogGetLastError(sqlite3_vfs *pVfs, int a, char *b){ |
+ return REALVFS(pVfs)->xGetLastError(REALVFS(pVfs), a, b); |
+} |
+static int vfslogCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){ |
+ return REALVFS(pVfs)->xCurrentTimeInt64(REALVFS(pVfs), p); |
+} |
- pParent = sqlite3_vfs_find(zParent); |
- if( !pParent ){ |
- return 0; |
- } |
+static void vfslog_flush(VfslogVfs *p){ |
+#ifdef SQLITE_TEST |
+ extern int sqlite3_io_error_pending; |
+ extern int sqlite3_io_error_persist; |
+ extern int sqlite3_diskfull_pending; |
+ |
+ int pending = sqlite3_io_error_pending; |
+ int persist = sqlite3_io_error_persist; |
+ int diskfull = sqlite3_diskfull_pending; |
- nByte = strlen(zName) + 1 + sizeof(InstVfs); |
- p = (InstVfs *)sqlite3_malloc(nByte); |
- if( p ){ |
- char *zCopy = (char *)&p[1]; |
- memset(p, 0, nByte); |
- memcpy(p, &inst_vfs, sizeof(sqlite3_vfs)); |
- p->pVfs = pParent; |
- memcpy(zCopy, zName, strlen(zName)); |
- p->base.zName = (const char *)zCopy; |
- p->base.szOsFile += pParent->szOsFile; |
- sqlite3_vfs_register((sqlite3_vfs *)p, 0); |
+ sqlite3_io_error_pending = 0; |
+ sqlite3_io_error_persist = 0; |
+ sqlite3_diskfull_pending = 0; |
+#endif |
+ |
+ if( p->nBuf ){ |
+ p->pLog->pMethods->xWrite(p->pLog, p->aBuf, p->nBuf, p->iOffset); |
+ p->iOffset += p->nBuf; |
+ p->nBuf = 0; |
} |
- return (sqlite3_vfs *)p; |
+#ifdef SQLITE_TEST |
+ sqlite3_io_error_pending = pending; |
+ sqlite3_io_error_persist = persist; |
+ sqlite3_diskfull_pending = diskfull; |
+#endif |
+} |
+ |
+static void put32bits(unsigned char *p, unsigned int v){ |
+ p[0] = v>>24; |
+ p[1] = v>>16; |
+ p[2] = v>>8; |
+ p[3] = v; |
} |
-void sqlite3_instvfs_configure( |
+static void vfslog_call( |
sqlite3_vfs *pVfs, |
- void (*xCall)( |
- void*, |
- int, /* File id */ |
- int, /* Event code */ |
- sqlite3_int64, |
- int, /* Return code */ |
- const char*, /* File name */ |
- int, |
- int, |
- sqlite3_int64 |
- ), |
- void *pClient, |
- void (*xDel)(void *) |
+ int eEvent, |
+ int iFileid, |
+ int nClick, |
+ int return_code, |
+ int size, |
+ int offset |
){ |
- InstVfs *p = (InstVfs *)pVfs; |
- assert( pVfs->xOpen==instOpen ); |
- if( p->xDel ){ |
- p->xDel(p->pClient); |
+ VfslogVfs *p = (VfslogVfs *)pVfs; |
+ unsigned char *zRec; |
+ if( (24+p->nBuf)>sizeof(p->aBuf) ){ |
+ vfslog_flush(p); |
} |
- p->xCall = xCall; |
- p->xDel = xDel; |
- p->pClient = pClient; |
+ zRec = (unsigned char *)&p->aBuf[p->nBuf]; |
+ put32bits(&zRec[0], eEvent); |
+ put32bits(&zRec[4], iFileid); |
+ put32bits(&zRec[8], nClick); |
+ put32bits(&zRec[12], return_code); |
+ put32bits(&zRec[16], size); |
+ put32bits(&zRec[20], offset); |
+ p->nBuf += 24; |
} |
-void sqlite3_instvfs_destroy(sqlite3_vfs *pVfs){ |
- if( pVfs ){ |
- sqlite3_vfs_unregister(pVfs); |
- sqlite3_instvfs_configure(pVfs, 0, 0, 0); |
- sqlite3_free(pVfs); |
+static void vfslog_string(sqlite3_vfs *pVfs, const char *zStr){ |
+ VfslogVfs *p = (VfslogVfs *)pVfs; |
+ unsigned char *zRec; |
+ int nStr = zStr ? strlen(zStr) : 0; |
+ if( (4+nStr+p->nBuf)>sizeof(p->aBuf) ){ |
+ vfslog_flush(p); |
+ } |
+ zRec = (unsigned char *)&p->aBuf[p->nBuf]; |
+ put32bits(&zRec[0], nStr); |
+ if( zStr ){ |
+ memcpy(&zRec[4], zStr, nStr); |
} |
+ p->nBuf += (4 + nStr); |
} |
-void sqlite3_instvfs_reset(sqlite3_vfs *pVfs){ |
- InstVfs *p = (InstVfs *)pVfs; |
- assert( pVfs->xOpen==instOpen ); |
- memset(p->aTime, 0, sizeof(sqlite3_int64)*OS_NUMEVENTS); |
- memset(p->aCount, 0, sizeof(int)*OS_NUMEVENTS); |
+static void vfslog_finalize(VfslogVfs *p){ |
+ if( p->pLog->pMethods ){ |
+ vfslog_flush(p); |
+ p->pLog->pMethods->xClose(p->pLog); |
+ } |
+ sqlite3_free(p); |
+} |
+ |
+int sqlite3_vfslog_finalize(const char *zVfs){ |
+ sqlite3_vfs *pVfs; |
+ pVfs = sqlite3_vfs_find(zVfs); |
+ if( !pVfs || pVfs->xOpen!=vfslogOpen ){ |
+ return SQLITE_ERROR; |
+ } |
+ sqlite3_vfs_unregister(pVfs); |
+ vfslog_finalize((VfslogVfs *)pVfs); |
+ return SQLITE_OK; |
} |
-const char *sqlite3_instvfs_name(int eEvent){ |
+int sqlite3_vfslog_new( |
+ const char *zVfs, /* New VFS name */ |
+ const char *zParentVfs, /* Parent VFS name (or NULL) */ |
+ const char *zLog /* Log file name */ |
+){ |
+ VfslogVfs *p; |
+ sqlite3_vfs *pParent; |
+ int nByte; |
+ int flags; |
+ int rc; |
+ char *zFile; |
+ int nVfs; |
+ |
+ pParent = sqlite3_vfs_find(zParentVfs); |
+ if( !pParent ){ |
+ return SQLITE_ERROR; |
+ } |
+ |
+ nVfs = strlen(zVfs); |
+ nByte = sizeof(VfslogVfs) + pParent->szOsFile + nVfs+1+pParent->mxPathname+1; |
+ p = (VfslogVfs *)sqlite3_malloc(nByte); |
+ memset(p, 0, nByte); |
+ |
+ p->pVfs = pParent; |
+ p->pLog = (sqlite3_file *)&p[1]; |
+ memcpy(&p->base, &vfslog_vfs, sizeof(sqlite3_vfs)); |
+ p->base.zName = &((char *)p->pLog)[pParent->szOsFile]; |
+ p->base.szOsFile += pParent->szOsFile; |
+ memcpy((char *)p->base.zName, zVfs, nVfs); |
+ |
+ zFile = (char *)&p->base.zName[nVfs+1]; |
+ pParent->xFullPathname(pParent, zLog, pParent->mxPathname, zFile); |
+ |
+ flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MASTER_JOURNAL; |
+ pParent->xDelete(pParent, zFile, 0); |
+ rc = pParent->xOpen(pParent, zFile, p->pLog, flags, &flags); |
+ if( rc==SQLITE_OK ){ |
+ memcpy(p->aBuf, "sqlite_ostrace1.....", 20); |
+ p->iOffset = 0; |
+ p->nBuf = 20; |
+ rc = sqlite3_vfs_register((sqlite3_vfs *)p, 1); |
+ } |
+ if( rc ){ |
+ vfslog_finalize(p); |
+ } |
+ return rc; |
+} |
+ |
+int sqlite3_vfslog_annotate(const char *zVfs, const char *zMsg){ |
+ sqlite3_vfs *pVfs; |
+ pVfs = sqlite3_vfs_find(zVfs); |
+ if( !pVfs || pVfs->xOpen!=vfslogOpen ){ |
+ return SQLITE_ERROR; |
+ } |
+ vfslog_call(pVfs, OS_ANNOTATE, 0, 0, 0, 0, 0); |
+ vfslog_string(pVfs, zMsg); |
+ return SQLITE_OK; |
+} |
+ |
+static const char *vfslog_eventname(int eEvent){ |
const char *zEvent = 0; |
switch( eEvent ){ |
@@ -576,10 +769,10 @@ const char *sqlite3_instvfs_name(int eEvent){ |
case OS_FILESIZE: zEvent = "xFilesize"; break; |
case OS_LOCK: zEvent = "xLock"; break; |
case OS_UNLOCK: zEvent = "xUnlock"; break; |
- case OS_CHECKRESERVEDLOCK: zEvent = "xCheckReservedLock"; break; |
+ case OS_CHECKRESERVEDLOCK: zEvent = "xCheckResLock"; break; |
case OS_FILECONTROL: zEvent = "xFileControl"; break; |
case OS_SECTORSIZE: zEvent = "xSectorSize"; break; |
- case OS_DEVCHAR: zEvent = "xDeviceCharacteristics"; break; |
+ case OS_DEVCHAR: zEvent = "xDeviceChar"; break; |
case OS_OPEN: zEvent = "xOpen"; break; |
case OS_DELETE: zEvent = "xDelete"; break; |
case OS_ACCESS: zEvent = "xAccess"; break; |
@@ -587,482 +780,431 @@ const char *sqlite3_instvfs_name(int eEvent){ |
case OS_RANDOMNESS: zEvent = "xRandomness"; break; |
case OS_SLEEP: zEvent = "xSleep"; break; |
case OS_CURRENTTIME: zEvent = "xCurrentTime"; break; |
- } |
- return zEvent; |
-} |
+ case OS_SHMUNMAP: zEvent = "xShmUnmap"; break; |
+ case OS_SHMLOCK: zEvent = "xShmLock"; break; |
+ case OS_SHMBARRIER: zEvent = "xShmBarrier"; break; |
+ case OS_SHMMAP: zEvent = "xShmMap"; break; |
-void sqlite3_instvfs_get( |
- sqlite3_vfs *pVfs, |
- int eEvent, |
- const char **pzEvent, |
- sqlite3_int64 *pnClick, |
- int *pnCall |
-){ |
- InstVfs *p = (InstVfs *)pVfs; |
- assert( pVfs->xOpen==instOpen ); |
- if( eEvent<1 || eEvent>=OS_NUMEVENTS ){ |
- *pzEvent = 0; |
- *pnClick = 0; |
- *pnCall = 0; |
- return; |
+ case OS_ANNOTATE: zEvent = "annotation"; break; |
} |
- *pzEvent = sqlite3_instvfs_name(eEvent); |
- *pnClick = p->aTime[eEvent]; |
- *pnCall = p->aCount[eEvent]; |
+ return zEvent; |
} |
-#define BINARYLOG_BUFFERSIZE 8192 |
+typedef struct VfslogVtab VfslogVtab; |
+typedef struct VfslogCsr VfslogCsr; |
-struct InstVfsBinaryLog { |
- int nBuf; |
- char *zBuf; |
- sqlite3_int64 iOffset; |
- int log_data; |
- sqlite3_file *pOut; |
- char *zOut; /* Log file name */ |
+/* |
+** Virtual table type for the vfslog reader module. |
+*/ |
+struct VfslogVtab { |
+ sqlite3_vtab base; /* Base class */ |
+ sqlite3_file *pFd; /* File descriptor open on vfslog file */ |
+ sqlite3_int64 nByte; /* Size of file in bytes */ |
+ char *zFile; /* File name for pFd */ |
}; |
-typedef struct InstVfsBinaryLog InstVfsBinaryLog; |
-static void put32bits(unsigned char *p, unsigned int v){ |
- p[0] = v>>24; |
- p[1] = v>>16; |
- p[2] = v>>8; |
- p[3] = v; |
+/* |
+** Virtual table cursor type for the vfslog reader module. |
+*/ |
+struct VfslogCsr { |
+ sqlite3_vtab_cursor base; /* Base class */ |
+ sqlite3_int64 iRowid; /* Current rowid. */ |
+ sqlite3_int64 iOffset; /* Offset of next record in file */ |
+ char *zTransient; /* Transient 'file' string */ |
+ int nFile; /* Size of array azFile[] */ |
+ char **azFile; /* File strings */ |
+ unsigned char aBuf[1024]; /* Current vfs log entry (read from file) */ |
+}; |
+ |
+static unsigned int get32bits(unsigned char *p){ |
+ return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; |
} |
-static void binarylog_flush(InstVfsBinaryLog *pLog){ |
- sqlite3_file *pFile = pLog->pOut; |
+/* |
+** The argument must point to a buffer containing a nul-terminated string. |
+** If the string begins with an SQL quote character it is overwritten by |
+** the dequoted version. Otherwise the buffer is left unmodified. |
+*/ |
+static void dequote(char *z){ |
+ char quote; /* Quote character (if any ) */ |
+ quote = z[0]; |
+ if( quote=='[' || quote=='\'' || quote=='"' || quote=='`' ){ |
+ int iIn = 1; /* Index of next byte to read from input */ |
+ int iOut = 0; /* Index of next byte to write to output */ |
+ if( quote=='[' ) quote = ']'; |
+ while( z[iIn] ){ |
+ if( z[iIn]==quote ){ |
+ if( z[iIn+1]!=quote ) break; |
+ z[iOut++] = quote; |
+ iIn += 2; |
+ }else{ |
+ z[iOut++] = z[iIn++]; |
+ } |
+ } |
+ z[iOut] = '\0'; |
+ } |
+} |
-#ifdef SQLITE_TEST |
- extern int sqlite3_io_error_pending; |
- extern int sqlite3_io_error_persist; |
- extern int sqlite3_diskfull_pending; |
+#ifndef SQLITE_OMIT_VIRTUALTABLE |
+/* |
+** Connect to or create a vfslog virtual table. |
+*/ |
+static int vlogConnect( |
+ sqlite3 *db, |
+ void *pAux, |
+ int argc, const char *const*argv, |
+ sqlite3_vtab **ppVtab, |
+ char **pzErr |
+){ |
+ sqlite3_vfs *pVfs; /* VFS used to read log file */ |
+ int flags; /* flags passed to pVfs->xOpen() */ |
+ VfslogVtab *p; |
+ int rc; |
+ int nByte; |
+ char *zFile; |
- int pending = sqlite3_io_error_pending; |
- int persist = sqlite3_io_error_persist; |
- int diskfull = sqlite3_diskfull_pending; |
+ *ppVtab = 0; |
+ pVfs = sqlite3_vfs_find(0); |
+ nByte = sizeof(VfslogVtab) + pVfs->szOsFile + pVfs->mxPathname; |
+ p = sqlite3_malloc(nByte); |
+ if( p==0 ) return SQLITE_NOMEM; |
+ memset(p, 0, nByte); |
- sqlite3_io_error_pending = 0; |
- sqlite3_io_error_persist = 0; |
- sqlite3_diskfull_pending = 0; |
-#endif |
+ p->pFd = (sqlite3_file *)&p[1]; |
+ p->zFile = &((char *)p->pFd)[pVfs->szOsFile]; |
- pFile->pMethods->xWrite(pFile, pLog->zBuf, pLog->nBuf, pLog->iOffset); |
- pLog->iOffset += pLog->nBuf; |
- pLog->nBuf = 0; |
+ zFile = sqlite3_mprintf("%s", argv[3]); |
+ if( !zFile ){ |
+ sqlite3_free(p); |
+ return SQLITE_NOMEM; |
+ } |
+ dequote(zFile); |
+ pVfs->xFullPathname(pVfs, zFile, pVfs->mxPathname, p->zFile); |
+ sqlite3_free(zFile); |
-#ifdef SQLITE_TEST |
- sqlite3_io_error_pending = pending; |
- sqlite3_io_error_persist = persist; |
- sqlite3_diskfull_pending = diskfull; |
-#endif |
-} |
+ flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MASTER_JOURNAL; |
+ rc = pVfs->xOpen(pVfs, p->zFile, p->pFd, flags, &flags); |
-static void binarylog_xcall( |
- void *p, |
- int eEvent, |
- int iFileId, |
- sqlite3_int64 nClick, |
- int return_code, |
- const char *zName, |
- int flags, |
- int nByte, |
- sqlite3_int64 iOffset |
-){ |
- InstVfsBinaryLog *pLog = (InstVfsBinaryLog *)p; |
- unsigned char *zRec; |
- if( (28+pLog->nBuf)>BINARYLOG_BUFFERSIZE ){ |
- binarylog_flush(pLog); |
+ if( rc==SQLITE_OK ){ |
+ p->pFd->pMethods->xFileSize(p->pFd, &p->nByte); |
+ sqlite3_declare_vtab(db, |
+ "CREATE TABLE xxx(event, file, click, rc, size, offset)" |
+ ); |
+ *ppVtab = &p->base; |
+ }else{ |
+ sqlite3_free(p); |
} |
- zRec = (unsigned char *)&pLog->zBuf[pLog->nBuf]; |
- put32bits(&zRec[0], eEvent); |
- put32bits(&zRec[4], (int)iFileId); |
- put32bits(&zRec[8], (int)nClick); |
- put32bits(&zRec[12], return_code); |
- put32bits(&zRec[16], flags); |
- put32bits(&zRec[20], nByte); |
- put32bits(&zRec[24], (int)iOffset); |
- pLog->nBuf += 28; |
+ |
+ return rc; |
} |
-static void binarylog_xdel(void *p){ |
- /* Close the log file and free the memory allocated for the |
- ** InstVfsBinaryLog structure. |
- */ |
- InstVfsBinaryLog *pLog = (InstVfsBinaryLog *)p; |
- sqlite3_file *pFile = pLog->pOut; |
- if( pLog->nBuf ){ |
- binarylog_flush(pLog); |
+/* |
+** There is no "best-index". This virtual table always does a linear |
+** scan of the binary VFS log file. |
+*/ |
+static int vlogBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ |
+ pIdxInfo->estimatedCost = 10.0; |
+ return SQLITE_OK; |
+} |
+ |
+/* |
+** Disconnect from or destroy a vfslog virtual table. |
+*/ |
+static int vlogDisconnect(sqlite3_vtab *pVtab){ |
+ VfslogVtab *p = (VfslogVtab *)pVtab; |
+ if( p->pFd->pMethods ){ |
+ p->pFd->pMethods->xClose(p->pFd); |
+ p->pFd->pMethods = 0; |
} |
- pFile->pMethods->xClose(pFile); |
- sqlite3_free(pLog->pOut); |
- sqlite3_free(pLog->zBuf); |
- sqlite3_free(pLog); |
+ sqlite3_free(p); |
+ return SQLITE_OK; |
} |
-static void binarylog_blob( |
- sqlite3_vfs *pVfs, |
- const char *zBlob, |
- int nBlob, |
- int isBinary |
-){ |
- InstVfsBinaryLog *pLog; |
- InstVfs *pInstVfs = (InstVfs *)pVfs; |
+/* |
+** Open a new vfslog cursor. |
+*/ |
+static int vlogOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ |
+ VfslogCsr *pCsr; /* Newly allocated cursor object */ |
+ |
+ pCsr = sqlite3_malloc(sizeof(VfslogCsr)); |
+ if( !pCsr ) return SQLITE_NOMEM; |
+ memset(pCsr, 0, sizeof(VfslogCsr)); |
+ *ppCursor = &pCsr->base; |
+ return SQLITE_OK; |
+} |
- if( pVfs->xOpen!=instOpen || pInstVfs->xCall!=binarylog_xcall ){ |
- return; |
+/* |
+** Close a vfslog cursor. |
+*/ |
+static int vlogClose(sqlite3_vtab_cursor *pCursor){ |
+ VfslogCsr *p = (VfslogCsr *)pCursor; |
+ int i; |
+ for(i=0; i<p->nFile; i++){ |
+ sqlite3_free(p->azFile[i]); |
} |
- pLog = (InstVfsBinaryLog *)pInstVfs->pClient; |
- if( zBlob && (!isBinary || pLog->log_data) ){ |
- unsigned char *zRec; |
- int nWrite; |
+ sqlite3_free(p->azFile); |
+ sqlite3_free(p->zTransient); |
+ sqlite3_free(p); |
+ return SQLITE_OK; |
+} |
- if( nBlob<0 ){ |
- nBlob = strlen(zBlob); |
- } |
- nWrite = nBlob + 28; |
- |
- if( (nWrite+pLog->nBuf)>BINARYLOG_BUFFERSIZE ){ |
- binarylog_flush(pLog); |
+/* |
+** Move a vfslog cursor to the next entry in the file. |
+*/ |
+static int vlogNext(sqlite3_vtab_cursor *pCursor){ |
+ VfslogCsr *pCsr = (VfslogCsr *)pCursor; |
+ VfslogVtab *p = (VfslogVtab *)pCursor->pVtab; |
+ int rc = SQLITE_OK; |
+ int nRead; |
+ |
+ sqlite3_free(pCsr->zTransient); |
+ pCsr->zTransient = 0; |
+ |
+ nRead = 24; |
+ if( pCsr->iOffset+nRead<=p->nByte ){ |
+ int eEvent; |
+ rc = p->pFd->pMethods->xRead(p->pFd, pCsr->aBuf, nRead, pCsr->iOffset); |
+ |
+ eEvent = get32bits(pCsr->aBuf); |
+ if( (rc==SQLITE_OK) |
+ && (eEvent==OS_OPEN || eEvent==OS_DELETE || eEvent==OS_ACCESS) |
+ ){ |
+ char buf[4]; |
+ rc = p->pFd->pMethods->xRead(p->pFd, buf, 4, pCsr->iOffset+nRead); |
+ nRead += 4; |
+ if( rc==SQLITE_OK ){ |
+ int nStr = get32bits((unsigned char *)buf); |
+ char *zStr = sqlite3_malloc(nStr+1); |
+ rc = p->pFd->pMethods->xRead(p->pFd, zStr, nStr, pCsr->iOffset+nRead); |
+ zStr[nStr] = '\0'; |
+ nRead += nStr; |
+ |
+ if( eEvent==OS_OPEN ){ |
+ int iFileid = get32bits(&pCsr->aBuf[4]); |
+ if( iFileid>=pCsr->nFile ){ |
+ int nNew = sizeof(pCsr->azFile[0])*(iFileid+1); |
+ pCsr->azFile = (char **)sqlite3_realloc(pCsr->azFile, nNew); |
+ nNew -= sizeof(pCsr->azFile[0])*pCsr->nFile; |
+ memset(&pCsr->azFile[pCsr->nFile], 0, nNew); |
+ pCsr->nFile = iFileid+1; |
+ } |
+ sqlite3_free(pCsr->azFile[iFileid]); |
+ pCsr->azFile[iFileid] = zStr; |
+ }else{ |
+ pCsr->zTransient = zStr; |
+ } |
+ } |
} |
- |
- zRec = (unsigned char *)&pLog->zBuf[pLog->nBuf]; |
- memset(zRec, 0, nWrite); |
- put32bits(&zRec[0], BINARYLOG_STRING); |
- put32bits(&zRec[4], (int)nBlob); |
- put32bits(&zRec[8], (int)isBinary); |
- memcpy(&zRec[28], zBlob, nBlob); |
- pLog->nBuf += nWrite; |
} |
-} |
-void sqlite3_instvfs_binarylog_call( |
- sqlite3_vfs *pVfs, |
- int eEvent, |
- sqlite3_int64 nClick, |
- int return_code, |
- const char *zString |
-){ |
- InstVfs *pInstVfs = (InstVfs *)pVfs; |
- InstVfsBinaryLog *pLog = (InstVfsBinaryLog *)pInstVfs->pClient; |
+ pCsr->iRowid += 1; |
+ pCsr->iOffset += nRead; |
+ return rc; |
+} |
- if( zString ){ |
- binarylog_blob(pVfs, zString, -1, 0); |
- } |
- binarylog_xcall(pLog, eEvent, 0, nClick, return_code, 0, 0, 0, 0); |
+static int vlogEof(sqlite3_vtab_cursor *pCursor){ |
+ VfslogCsr *pCsr = (VfslogCsr *)pCursor; |
+ VfslogVtab *p = (VfslogVtab *)pCursor->pVtab; |
+ return (pCsr->iOffset>=p->nByte); |
} |
-void sqlite3_instvfs_binarylog_marker( |
- sqlite3_vfs *pVfs, |
- const char *zMarker |
+static int vlogFilter( |
+ sqlite3_vtab_cursor *pCursor, |
+ int idxNum, const char *idxStr, |
+ int argc, sqlite3_value **argv |
){ |
- InstVfs *pInstVfs = (InstVfs *)pVfs; |
- InstVfsBinaryLog *pLog = (InstVfsBinaryLog *)pInstVfs->pClient; |
- binarylog_blob(pVfs, zMarker, -1, 0); |
- binarylog_xcall(pLog, BINARYLOG_MARKER, 0, 0, 0, 0, 0, 0, 0); |
+ VfslogCsr *pCsr = (VfslogCsr *)pCursor; |
+ pCsr->iRowid = 0; |
+ pCsr->iOffset = 20; |
+ return vlogNext(pCursor); |
} |
-sqlite3_vfs *sqlite3_instvfs_binarylog( |
- const char *zVfs, |
- const char *zParentVfs, |
- const char *zLog, |
- int log_data |
+static int vlogColumn( |
+ sqlite3_vtab_cursor *pCursor, |
+ sqlite3_context *ctx, |
+ int i |
){ |
- InstVfsBinaryLog *p; |
- sqlite3_vfs *pVfs; |
- sqlite3_vfs *pParent; |
- int nByte; |
- int flags; |
- int rc; |
+ unsigned int val; |
+ VfslogCsr *pCsr = (VfslogCsr *)pCursor; |
- pParent = sqlite3_vfs_find(zParentVfs); |
- if( !pParent ){ |
- return 0; |
- } |
+ assert( i<7 ); |
+ val = get32bits(&pCsr->aBuf[4*i]); |
- nByte = sizeof(InstVfsBinaryLog) + pParent->mxPathname+1; |
- p = (InstVfsBinaryLog *)sqlite3_malloc(nByte); |
- memset(p, 0, nByte); |
- p->zBuf = sqlite3_malloc(BINARYLOG_BUFFERSIZE); |
- p->zOut = (char *)&p[1]; |
- p->pOut = (sqlite3_file *)sqlite3_malloc(pParent->szOsFile); |
- p->log_data = log_data; |
- pParent->xFullPathname(pParent, zLog, pParent->mxPathname, p->zOut); |
- flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MASTER_JOURNAL; |
- pParent->xDelete(pParent, p->zOut, 0); |
- rc = pParent->xOpen(pParent, p->zOut, p->pOut, flags, &flags); |
- if( rc==SQLITE_OK ){ |
- memcpy(p->zBuf, "sqlite_ostrace1.....", 20); |
- p->iOffset = 0; |
- p->nBuf = 20; |
- } |
- if( rc ){ |
- binarylog_xdel(p); |
- return 0; |
+ switch( i ){ |
+ case 0: { |
+ sqlite3_result_text(ctx, vfslog_eventname(val), -1, SQLITE_STATIC); |
+ break; |
+ } |
+ case 1: { |
+ char *zStr = pCsr->zTransient; |
+ if( val!=0 && val<pCsr->nFile ){ |
+ zStr = pCsr->azFile[val]; |
+ } |
+ sqlite3_result_text(ctx, zStr, -1, SQLITE_TRANSIENT); |
+ break; |
+ } |
+ default: |
+ sqlite3_result_int(ctx, val); |
+ break; |
} |
- pVfs = sqlite3_instvfs_create(zVfs, zParentVfs); |
- if( pVfs ){ |
- sqlite3_instvfs_configure(pVfs, binarylog_xcall, p, binarylog_xdel); |
- } |
+ return SQLITE_OK; |
+} |
- return pVfs; |
+static int vlogRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){ |
+ VfslogCsr *pCsr = (VfslogCsr *)pCursor; |
+ *pRowid = pCsr->iRowid; |
+ return SQLITE_OK; |
} |
-#endif /* SQLITE_ENABLE_INSTVFS */ |
+ |
+int sqlite3_vfslog_register(sqlite3 *db){ |
+ static sqlite3_module vfslog_module = { |
+ 0, /* iVersion */ |
+ vlogConnect, /* xCreate */ |
+ vlogConnect, /* xConnect */ |
+ vlogBestIndex, /* xBestIndex */ |
+ vlogDisconnect, /* xDisconnect */ |
+ vlogDisconnect, /* xDestroy */ |
+ vlogOpen, /* xOpen - open a cursor */ |
+ vlogClose, /* xClose - close a cursor */ |
+ vlogFilter, /* xFilter - configure scan constraints */ |
+ vlogNext, /* xNext - advance a cursor */ |
+ vlogEof, /* xEof - check for end of scan */ |
+ vlogColumn, /* xColumn - read data */ |
+ vlogRowid, /* xRowid - read data */ |
+ 0, /* xUpdate */ |
+ 0, /* xBegin */ |
+ 0, /* xSync */ |
+ 0, /* xCommit */ |
+ 0, /* xRollback */ |
+ 0, /* xFindMethod */ |
+ 0, /* xRename */ |
+ }; |
+ |
+ sqlite3_create_module(db, "vfslog", &vfslog_module, 0); |
+ return SQLITE_OK; |
+} |
+#endif /* SQLITE_OMIT_VIRTUALTABLE */ |
/************************************************************************** |
*************************************************************************** |
** Tcl interface starts here. |
*/ |
-#if SQLITE_TEST |
-#include <tcl.h> |
+#if defined(SQLITE_TEST) || defined(TCLSH) |
-#ifdef SQLITE_ENABLE_INSTVFS |
-struct InstVfsCall { |
- Tcl_Interp *interp; |
- Tcl_Obj *pScript; |
-}; |
-typedef struct InstVfsCall InstVfsCall; |
- |
-static void test_instvfs_xcall( |
- void *p, |
- int eEvent, |
- int iFileId, |
- sqlite3_int64 nClick, |
- int return_code, |
- const char *zName, |
- int flags, |
- int nByte, |
- sqlite3_int64 iOffset |
-){ |
- int rc; |
- InstVfsCall *pCall = (InstVfsCall *)p; |
- Tcl_Obj *pObj = Tcl_DuplicateObj( pCall->pScript); |
- const char *zEvent = sqlite3_instvfs_name(eEvent); |
- |
- Tcl_IncrRefCount(pObj); |
- Tcl_ListObjAppendElement(0, pObj, Tcl_NewStringObj(zEvent, -1)); |
- Tcl_ListObjAppendElement(0, pObj, Tcl_NewWideIntObj(nClick)); |
- Tcl_ListObjAppendElement(0, pObj, Tcl_NewStringObj(zName, -1)); |
- Tcl_ListObjAppendElement(0, pObj, Tcl_NewIntObj(nByte)); |
- Tcl_ListObjAppendElement(0, pObj, Tcl_NewWideIntObj(iOffset)); |
- |
- rc = Tcl_EvalObjEx(pCall->interp, pObj, TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT); |
- if( rc ){ |
- Tcl_BackgroundError(pCall->interp); |
- } |
- Tcl_DecrRefCount(pObj); |
-} |
- |
-static void test_instvfs_xdel(void *p){ |
- InstVfsCall *pCall = (InstVfsCall *)p; |
- Tcl_DecrRefCount(pCall->pScript); |
- sqlite3_free(pCall); |
-} |
+#include <tcl.h> |
-static int test_sqlite3_instvfs( |
- void * clientData, |
+static int test_vfslog( |
+ void *clientData, |
Tcl_Interp *interp, |
int objc, |
Tcl_Obj *CONST objv[] |
){ |
- static const char *IV_strs[] = |
- { "create", "destroy", "reset", "report", "configure", "binarylog", "marker", 0 }; |
- enum IV_enum { IV_CREATE, IV_DESTROY, IV_RESET, IV_REPORT, IV_CONFIGURE, IV_BINARYLOG, IV_MARKER }; |
+ struct SqliteDb { sqlite3 *db; }; |
+ sqlite3 *db; |
+ Tcl_CmdInfo cmdInfo; |
+ int rc = SQLITE_ERROR; |
+ |
+ static const char *strs[] = { "annotate", "finalize", "new", "register", 0 }; |
+ enum VL_enum { VL_ANNOTATE, VL_FINALIZE, VL_NEW, VL_REGISTER }; |
int iSub; |
if( objc<2 ){ |
Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND ..."); |
+ return TCL_ERROR; |
} |
- if( Tcl_GetIndexFromObj(interp, objv[1], IV_strs, "sub-command", 0, &iSub) ){ |
+ if( Tcl_GetIndexFromObj(interp, objv[1], strs, "sub-command", 0, &iSub) ){ |
return TCL_ERROR; |
} |
- switch( (enum IV_enum)iSub ){ |
- case IV_CREATE: { |
- char *zParent = 0; |
- sqlite3_vfs *p; |
- int isDefault = 0; |
- if( objc>2 && 0==strcmp("-default", Tcl_GetString(objv[2])) ){ |
- isDefault = 1; |
- } |
- if( (objc-isDefault)!=4 && (objc-isDefault)!=3 ){ |
- Tcl_WrongNumArgs(interp, 2, objv, "?-default? NAME ?PARENT-VFS?"); |
- return TCL_ERROR; |
- } |
- if( objc==(4+isDefault) ){ |
- zParent = Tcl_GetString(objv[3+isDefault]); |
- } |
- p = sqlite3_instvfs_create(Tcl_GetString(objv[2+isDefault]), zParent); |
- if( !p ){ |
- Tcl_AppendResult(interp, "error creating vfs ", 0); |
- return TCL_ERROR; |
- } |
- if( isDefault ){ |
- sqlite3_vfs_register(p, 1); |
- } |
- Tcl_SetObjResult(interp, objv[2]); |
- break; |
- } |
- case IV_BINARYLOG: { |
- char *zName = 0; |
- char *zLog = 0; |
- char *zParent = 0; |
- sqlite3_vfs *p; |
- int isDefault = 0; |
- int isLogdata = 0; |
- int argbase = 2; |
- |
- for(argbase=2; argbase<(objc-2); argbase++){ |
- if( 0==strcmp("-default", Tcl_GetString(objv[argbase])) ){ |
- isDefault = 1; |
- } |
- else if( 0==strcmp("-parent", Tcl_GetString(objv[argbase])) ){ |
- argbase++; |
- zParent = Tcl_GetString(objv[argbase]); |
- } |
- else if( 0==strcmp("-logdata", Tcl_GetString(objv[argbase])) ){ |
- isLogdata = 1; |
- }else{ |
- break; |
- } |
- } |
- |
- if( (objc-argbase)!=2 ){ |
- Tcl_WrongNumArgs( |
- interp, 2, objv, "?-default? ?-parent VFS? ?-logdata? NAME LOGFILE" |
- ); |
+ switch( (enum VL_enum)iSub ){ |
+ case VL_ANNOTATE: { |
+ int rc; |
+ char *zVfs; |
+ char *zMsg; |
+ if( objc!=4 ){ |
+ Tcl_WrongNumArgs(interp, 3, objv, "VFS"); |
return TCL_ERROR; |
} |
- zName = Tcl_GetString(objv[argbase]); |
- zLog = Tcl_GetString(objv[argbase+1]); |
- p = sqlite3_instvfs_binarylog(zName, zParent, zLog, isLogdata); |
- if( !p ){ |
- Tcl_AppendResult(interp, "error creating vfs ", 0); |
+ zVfs = Tcl_GetString(objv[2]); |
+ zMsg = Tcl_GetString(objv[3]); |
+ rc = sqlite3_vfslog_annotate(zVfs, zMsg); |
+ if( rc!=SQLITE_OK ){ |
+ Tcl_AppendResult(interp, "failed", 0); |
return TCL_ERROR; |
} |
- if( isDefault ){ |
- sqlite3_vfs_register(p, 1); |
- } |
- Tcl_SetObjResult(interp, objv[2]); |
break; |
} |
- |
- case IV_MARKER: { |
- sqlite3_vfs *p; |
- if( objc!=4 ){ |
- Tcl_WrongNumArgs(interp, 2, objv, "VFS MARKER"); |
+ case VL_FINALIZE: { |
+ int rc; |
+ char *zVfs; |
+ if( objc!=3 ){ |
+ Tcl_WrongNumArgs(interp, 2, objv, "VFS"); |
return TCL_ERROR; |
} |
- p = sqlite3_vfs_find(Tcl_GetString(objv[2])); |
- if( !p || p->xOpen!=instOpen ){ |
- Tcl_AppendResult(interp, "no such vfs: ", Tcl_GetString(objv[2]), 0); |
+ zVfs = Tcl_GetString(objv[2]); |
+ rc = sqlite3_vfslog_finalize(zVfs); |
+ if( rc!=SQLITE_OK ){ |
+ Tcl_AppendResult(interp, "failed", 0); |
return TCL_ERROR; |
} |
- sqlite3_instvfs_binarylog_marker(p, Tcl_GetString(objv[3])); |
- Tcl_ResetResult(interp); |
break; |
- } |
- |
- case IV_CONFIGURE: { |
- InstVfsCall *pCall; |
- |
- sqlite3_vfs *p; |
- if( objc!=4 ){ |
- Tcl_WrongNumArgs(interp, 2, objv, "NAME SCRIPT"); |
+ }; |
+ |
+ case VL_NEW: { |
+ int rc; |
+ char *zVfs; |
+ char *zParent; |
+ char *zLog; |
+ if( objc!=5 ){ |
+ Tcl_WrongNumArgs(interp, 2, objv, "VFS PARENT LOGFILE"); |
return TCL_ERROR; |
} |
- p = sqlite3_vfs_find(Tcl_GetString(objv[2])); |
- if( !p || p->xOpen!=instOpen ){ |
- Tcl_AppendResult(interp, "no such vfs: ", Tcl_GetString(objv[2]), 0); |
+ zVfs = Tcl_GetString(objv[2]); |
+ zParent = Tcl_GetString(objv[3]); |
+ zLog = Tcl_GetString(objv[4]); |
+ if( *zParent=='\0' ) zParent = 0; |
+ rc = sqlite3_vfslog_new(zVfs, zParent, zLog); |
+ if( rc!=SQLITE_OK ){ |
+ Tcl_AppendResult(interp, "failed", 0); |
return TCL_ERROR; |
} |
- |
- if( strlen(Tcl_GetString(objv[3])) ){ |
- pCall = (InstVfsCall *)sqlite3_malloc(sizeof(InstVfsCall)); |
- pCall->interp = interp; |
- pCall->pScript = Tcl_DuplicateObj(objv[3]); |
- Tcl_IncrRefCount(pCall->pScript); |
- sqlite3_instvfs_configure(p, |
- test_instvfs_xcall, (void *)pCall, test_instvfs_xdel |
- ); |
- }else{ |
- sqlite3_instvfs_configure(p, 0, 0, 0); |
- } |
break; |
- } |
+ }; |
- case IV_REPORT: |
- case IV_DESTROY: |
- case IV_RESET: { |
- sqlite3_vfs *p; |
+ case VL_REGISTER: { |
+ char *zDb; |
if( objc!=3 ){ |
- Tcl_WrongNumArgs(interp, 2, objv, "NAME"); |
- return TCL_ERROR; |
- } |
- p = sqlite3_vfs_find(Tcl_GetString(objv[2])); |
- if( !p || p->xOpen!=instOpen ){ |
- Tcl_AppendResult(interp, "no such vfs: ", Tcl_GetString(objv[2]), 0); |
+ Tcl_WrongNumArgs(interp, 2, objv, "DB"); |
return TCL_ERROR; |
} |
- |
- if( ((enum IV_enum)iSub)==IV_DESTROY ){ |
- sqlite3_instvfs_destroy(p); |
- } |
- if( ((enum IV_enum)iSub)==IV_RESET ){ |
- sqlite3_instvfs_reset(p); |
+#ifdef SQLITE_OMIT_VIRTUALTABLE |
+ Tcl_AppendResult(interp, "vfslog not available because of " |
+ "SQLITE_OMIT_VIRTUALTABLE", (void*)0); |
+ return TCL_ERROR; |
+#else |
+ zDb = Tcl_GetString(objv[2]); |
+ if( Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){ |
+ db = ((struct SqliteDb*)cmdInfo.objClientData)->db; |
+ rc = sqlite3_vfslog_register(db); |
} |
- if( ((enum IV_enum)iSub)==IV_REPORT ){ |
- int ii; |
- Tcl_Obj *pRet = Tcl_NewObj(); |
- |
- const char *zName = (char *)1; |
- sqlite3_int64 nClick; |
- int nCall; |
- for(ii=1; zName; ii++){ |
- sqlite3_instvfs_get(p, ii, &zName, &nClick, &nCall); |
- if( zName ){ |
- Tcl_Obj *pElem = Tcl_NewObj(); |
- Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj(zName, -1)); |
- Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(nCall)); |
- Tcl_ListObjAppendElement(0, pElem, Tcl_NewWideIntObj(nClick)); |
- Tcl_ListObjAppendElement(0, pRet, pElem); |
- } |
- } |
- |
- Tcl_SetObjResult(interp, pRet); |
+ if( rc!=SQLITE_OK ){ |
+ Tcl_AppendResult(interp, "bad sqlite3 handle: ", zDb, (void*)0); |
+ return TCL_ERROR; |
} |
- |
break; |
+#endif |
} |
} |
return TCL_OK; |
} |
-#endif /* SQLITE_ENABLE_INSTVFS */ |
- |
-/* Alternative implementation of sqlite3_instvfs when the real |
-** implementation is unavailable. |
-*/ |
-#ifndef SQLITE_ENABLE_INSTVFS |
-static int test_sqlite3_instvfs( |
- void * clientData, |
- Tcl_Interp *interp, |
- int objc, |
- Tcl_Obj *CONST objv[] |
-){ |
- Tcl_AppendResult(interp, |
- "not compiled with -DSQLITE_ENABLE_INSTVFS; sqlite3_instvfs is " |
- "unavailable", (char*)0); |
- return TCL_ERROR; |
-} |
-#endif /* !defined(SQLITE_ENABLE_INSTVFS) */ |
int SqlitetestOsinst_Init(Tcl_Interp *interp){ |
- Tcl_CreateObjCommand(interp, "sqlite3_instvfs", test_sqlite3_instvfs, 0, 0); |
+ Tcl_CreateObjCommand(interp, "vfslog", test_vfslog, 0, 0); |
return TCL_OK; |
} |