| Index: third_party/sqlite/src/test_osinst.c
 | 
| ===================================================================
 | 
| --- third_party/sqlite/src/test_osinst.c	(revision 56608)
 | 
| +++ third_party/sqlite/src/test_osinst.c	(working copy)
 | 
| @@ -1,1069 +0,0 @@
 | 
| -/*
 | 
| -** 2008 April 10
 | 
| -**
 | 
| -** The author disclaims copyright to this source code.  In place of
 | 
| -** a legal notice, here is a blessing:
 | 
| -**
 | 
| -**    May you do good and not evil.
 | 
| -**    May you find forgiveness for yourself and forgive others.
 | 
| -**    May you share freely, never taking more than you give.
 | 
| -**
 | 
| -******************************************************************************
 | 
| -**
 | 
| -** This file contains the implementation of an SQLite vfs wrapper 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?
 | 
| -**
 | 
| -**       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.
 | 
| -**
 | 
| -**   sqlite3_instvfs destroy NAME
 | 
| -**
 | 
| -**       Deregister and destroy the vfs named $NAME, which must have been
 | 
| -**       created by an earlier invocation of [sqlite3_instvfs create].
 | 
| -**
 | 
| -**   sqlite3_instvfs configure NAME SCRIPT
 | 
| -**
 | 
| -**       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:
 | 
| -**
 | 
| -**         * The name of the invoked method - i.e. "xRead".
 | 
| -**
 | 
| -**         * The time consumed by the method call as measured by 
 | 
| -**           sqlite3Hwtime() (an integer value)
 | 
| -**
 | 
| -**         * 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.
 | 
| -**
 | 
| -**         * A 32-bit integer value with a call-specific meaning.
 | 
| -**
 | 
| -**         * 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.
 | 
| -**
 | 
| -**   sqlite3_instvfs reset NAME
 | 
| -**
 | 
| -**       Zero the internal event counters associated with vfs $NAME, 
 | 
| -**       which must have been created by an earlier invocation of 
 | 
| -**       [sqlite3_instvfs create].
 | 
| -**
 | 
| -**   sqlite3_instvfs report NAME
 | 
| -**
 | 
| -**       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:
 | 
| -**
 | 
| -**         * 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).
 | 
| -*/
 | 
| -
 | 
| -#include "sqlite3.h"
 | 
| -#include <string.h>
 | 
| -#include <assert.h>
 | 
| -
 | 
| -/*
 | 
| -** Maximum pathname length supported by the inst backend.
 | 
| -*/
 | 
| -#define INST_MAX_PATHNAME 512
 | 
| -
 | 
| -
 | 
| -/* File methods */
 | 
| -/* Vfs methods */
 | 
| -#define OS_ACCESS            1
 | 
| -#define OS_CHECKRESERVEDLOCK 2
 | 
| -#define OS_CLOSE             3
 | 
| -#define OS_CURRENTTIME       4
 | 
| -#define OS_DELETE            5
 | 
| -#define OS_DEVCHAR           6
 | 
| -#define OS_FILECONTROL       7
 | 
| -#define OS_FILESIZE          8
 | 
| -#define OS_FULLPATHNAME      9
 | 
| -#define OS_LOCK              11
 | 
| -#define OS_OPEN              12
 | 
| -#define OS_RANDOMNESS        13
 | 
| -#define OS_READ              14 
 | 
| -#define OS_SECTORSIZE        15
 | 
| -#define OS_SLEEP             16
 | 
| -#define OS_SYNC              17
 | 
| -#define OS_TRUNCATE          18
 | 
| -#define OS_UNLOCK            19
 | 
| -#define OS_WRITE             20
 | 
| -
 | 
| -#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;
 | 
| -};
 | 
| -typedef struct InstVfs InstVfs;
 | 
| -
 | 
| -#define REALVFS(p) (((InstVfs *)(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.
 | 
| -*/
 | 
| -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*);
 | 
| -
 | 
| -/*
 | 
| -** Method declarations for inst_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 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 */
 | 
| -};
 | 
| -
 | 
| -/* 
 | 
| -** 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;                                 \
 | 
| -}
 | 
| -
 | 
| -#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;                             \
 | 
| -}
 | 
| -
 | 
| -/*
 | 
| -** Close an inst-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)
 | 
| -  );
 | 
| -}
 | 
| -
 | 
| -/*
 | 
| -** Read data from an inst-file.
 | 
| -*/
 | 
| -static int instRead(
 | 
| -  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)
 | 
| -  );
 | 
| -}
 | 
| -
 | 
| -/*
 | 
| -** Write data to an inst-file.
 | 
| -*/
 | 
| -static int instWrite(
 | 
| -  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)
 | 
| -  );
 | 
| -}
 | 
| -
 | 
| -/*
 | 
| -** Truncate an inst-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)
 | 
| -  );
 | 
| -}
 | 
| -
 | 
| -/*
 | 
| -** Sync an inst-file.
 | 
| -*/
 | 
| -static int instSync(sqlite3_file *pFile, int flags){
 | 
| -  OS_TIME_IO(OS_SYNC, flags, 0, p->pReal->pMethods->xSync(p->pReal, flags));
 | 
| -}
 | 
| -
 | 
| -/*
 | 
| -** Return the current file-size of an inst-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)
 | 
| -  );
 | 
| -}
 | 
| -
 | 
| -/*
 | 
| -** Lock an inst-file.
 | 
| -*/
 | 
| -static int instLock(sqlite3_file *pFile, int eLock){
 | 
| -  OS_TIME_IO(OS_LOCK, eLock, 0, p->pReal->pMethods->xLock(p->pReal, eLock));
 | 
| -}
 | 
| -
 | 
| -/*
 | 
| -** Unlock an inst-file.
 | 
| -*/
 | 
| -static int instUnlock(sqlite3_file *pFile, int eLock){
 | 
| -  OS_TIME_IO(OS_UNLOCK, eLock, 0, p->pReal->pMethods->xUnlock(p->pReal, eLock));
 | 
| -}
 | 
| -
 | 
| -/*
 | 
| -** Check if another file-handle holds a RESERVED lock on an inst-file.
 | 
| -*/
 | 
| -static int instCheckReservedLock(sqlite3_file *pFile, int *pResOut){
 | 
| -  OS_TIME_IO(OS_CHECKRESERVEDLOCK, 0, 0, 
 | 
| -      p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut)
 | 
| -  );
 | 
| -}
 | 
| -
 | 
| -/*
 | 
| -** File control method. For custom operations on an inst-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));
 | 
| -}
 | 
| -
 | 
| -/*
 | 
| -** Return the sector-size in bytes for an inst-file.
 | 
| -*/
 | 
| -static int instSectorSize(sqlite3_file *pFile){
 | 
| -  OS_TIME_IO(OS_SECTORSIZE, 0, 0, p->pReal->pMethods->xSectorSize(p->pReal));
 | 
| -}
 | 
| -
 | 
| -/*
 | 
| -** Return the device characteristic flags supported by an inst-file.
 | 
| -*/
 | 
| -static int instDeviceCharacteristics(sqlite3_file *pFile){
 | 
| -  OS_TIME_IO(OS_DEVCHAR, 0, 0, p->pReal->pMethods->xDeviceCharacteristics(p->pReal));
 | 
| -}
 | 
| -
 | 
| -/*
 | 
| -** Open an inst file handle.
 | 
| -*/
 | 
| -static int instOpen(
 | 
| -  sqlite3_vfs *pVfs,
 | 
| -  const char *zName,
 | 
| -  sqlite3_file *pFile,
 | 
| -  int flags,
 | 
| -  int *pOutFlags
 | 
| -){
 | 
| -  inst_file *p = (inst_file *)pFile;
 | 
| -  pFile->pMethods = &inst_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)
 | 
| -  );
 | 
| -}
 | 
| -
 | 
| -/*
 | 
| -** Delete the file located at zPath. If the dirSync argument is true,
 | 
| -** ensure the file-system modifications are synced to disk before
 | 
| -** returning.
 | 
| -*/
 | 
| -static int 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) 
 | 
| -  );
 | 
| -}
 | 
| -
 | 
| -/*
 | 
| -** Test for access permissions. Return true if the requested permission
 | 
| -** is available, or false otherwise.
 | 
| -*/
 | 
| -static int instAccess(
 | 
| -  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) 
 | 
| -  );
 | 
| -}
 | 
| -
 | 
| -/*
 | 
| -** Populate buffer zOut with the full canonical pathname corresponding
 | 
| -** to the pathname in zPath. zOut is guaranteed to point to a buffer
 | 
| -** of at least (INST_MAX_PATHNAME+1) bytes.
 | 
| -*/
 | 
| -static int instFullPathname(
 | 
| -  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);
 | 
| -  );
 | 
| -}
 | 
| -
 | 
| -/*
 | 
| -** Open the dynamic library located at zPath and return a handle.
 | 
| -*/
 | 
| -static void *instDlOpen(sqlite3_vfs *pVfs, const char *zPath){
 | 
| -  return REALVFS(pVfs)->xDlOpen(REALVFS(pVfs), zPath);
 | 
| -}
 | 
| -
 | 
| -/*
 | 
| -** Populate the buffer zErrMsg (size nByte bytes) with a human readable
 | 
| -** utf-8 string describing the most recent error encountered associated 
 | 
| -** with dynamic libraries.
 | 
| -*/
 | 
| -static void instDlError(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){
 | 
| -  return REALVFS(pVfs)->xDlSym(REALVFS(pVfs), p, zSym);
 | 
| -}
 | 
| -
 | 
| -/*
 | 
| -** Close the dynamic library handle pHandle.
 | 
| -*/
 | 
| -static void instDlClose(sqlite3_vfs *pVfs, void *pHandle){
 | 
| -  REALVFS(pVfs)->xDlClose(REALVFS(pVfs), pHandle);
 | 
| -}
 | 
| -
 | 
| -/*
 | 
| -** Populate the buffer pointed to by zBufOut with nByte bytes of 
 | 
| -** random data.
 | 
| -*/
 | 
| -static int instRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
 | 
| -  OS_TIME_VFS( OS_RANDOMNESS, 0, 0, nByte, 0,
 | 
| -    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) 
 | 
| -  );
 | 
| -}
 | 
| -
 | 
| -/*
 | 
| -** 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) 
 | 
| -  );
 | 
| -}
 | 
| -
 | 
| -sqlite3_vfs *sqlite3_instvfs_create(const char *zName, const char *zParent){
 | 
| -  int nByte;
 | 
| -  InstVfs *p;
 | 
| -  sqlite3_vfs *pParent;
 | 
| -
 | 
| -  pParent = sqlite3_vfs_find(zParent);
 | 
| -  if( !pParent ){
 | 
| -    return 0;
 | 
| -  }
 | 
| -
 | 
| -  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);
 | 
| -  }
 | 
| -
 | 
| -  return (sqlite3_vfs *)p;
 | 
| -}
 | 
| -
 | 
| -void sqlite3_instvfs_configure(
 | 
| -  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 *)
 | 
| -){
 | 
| -  InstVfs *p = (InstVfs *)pVfs;
 | 
| -  assert( pVfs->xOpen==instOpen );
 | 
| -  if( p->xDel ){
 | 
| -    p->xDel(p->pClient);
 | 
| -  }
 | 
| -  p->xCall = xCall;
 | 
| -  p->xDel = xDel;
 | 
| -  p->pClient = pClient;
 | 
| -}
 | 
| -
 | 
| -void sqlite3_instvfs_destroy(sqlite3_vfs *pVfs){
 | 
| -  if( pVfs ){
 | 
| -    sqlite3_vfs_unregister(pVfs);
 | 
| -    sqlite3_instvfs_configure(pVfs, 0, 0, 0);
 | 
| -    sqlite3_free(pVfs);
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -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);
 | 
| -}
 | 
| -
 | 
| -const char *sqlite3_instvfs_name(int eEvent){
 | 
| -  const char *zEvent = 0;
 | 
| -
 | 
| -  switch( eEvent ){
 | 
| -    case OS_CLOSE:             zEvent = "xClose"; break;
 | 
| -    case OS_READ:              zEvent = "xRead"; break;
 | 
| -    case OS_WRITE:             zEvent = "xWrite"; break;
 | 
| -    case OS_TRUNCATE:          zEvent = "xTruncate"; break;
 | 
| -    case OS_SYNC:              zEvent = "xSync"; break;
 | 
| -    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_FILECONTROL:       zEvent = "xFileControl"; break;
 | 
| -    case OS_SECTORSIZE:        zEvent = "xSectorSize"; break;
 | 
| -    case OS_DEVCHAR:           zEvent = "xDeviceCharacteristics"; break;
 | 
| -    case OS_OPEN:              zEvent = "xOpen"; break;
 | 
| -    case OS_DELETE:            zEvent = "xDelete"; break;
 | 
| -    case OS_ACCESS:            zEvent = "xAccess"; break;
 | 
| -    case OS_FULLPATHNAME:      zEvent = "xFullPathname"; break;
 | 
| -    case OS_RANDOMNESS:        zEvent = "xRandomness"; break;
 | 
| -    case OS_SLEEP:             zEvent = "xSleep"; break;
 | 
| -    case OS_CURRENTTIME:       zEvent = "xCurrentTime"; break;
 | 
| -  }
 | 
| -
 | 
| -  return zEvent;
 | 
| -}
 | 
| -
 | 
| -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;
 | 
| -  }
 | 
| -
 | 
| -  *pzEvent = sqlite3_instvfs_name(eEvent);
 | 
| -  *pnClick = p->aTime[eEvent];
 | 
| -  *pnCall = p->aCount[eEvent];
 | 
| -}
 | 
| -
 | 
| -#define BINARYLOG_BUFFERSIZE 8192
 | 
| -
 | 
| -struct InstVfsBinaryLog {
 | 
| -  int nBuf;
 | 
| -  char *zBuf;
 | 
| -  sqlite3_int64 iOffset;
 | 
| -  int log_data;
 | 
| -  sqlite3_file *pOut;
 | 
| -  char *zOut;                       /* Log file name */
 | 
| -};
 | 
| -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;
 | 
| -}
 | 
| -
 | 
| -static void binarylog_flush(InstVfsBinaryLog *pLog){
 | 
| -  sqlite3_file *pFile = pLog->pOut;
 | 
| -
 | 
| -#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;
 | 
| -
 | 
| -  sqlite3_io_error_pending = 0;
 | 
| -  sqlite3_io_error_persist = 0;
 | 
| -  sqlite3_diskfull_pending = 0;
 | 
| -#endif
 | 
| -
 | 
| -  pFile->pMethods->xWrite(pFile, pLog->zBuf, pLog->nBuf, pLog->iOffset);
 | 
| -  pLog->iOffset += pLog->nBuf;
 | 
| -  pLog->nBuf = 0;
 | 
| -
 | 
| -#ifdef SQLITE_TEST
 | 
| -  sqlite3_io_error_pending = pending;
 | 
| -  sqlite3_io_error_persist = persist;
 | 
| -  sqlite3_diskfull_pending = diskfull;
 | 
| -#endif
 | 
| -}
 | 
| -
 | 
| -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);
 | 
| -  }
 | 
| -  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;
 | 
| -}
 | 
| -
 | 
| -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);
 | 
| -  }
 | 
| -  pFile->pMethods->xClose(pFile);
 | 
| -  sqlite3_free(pLog->pOut);
 | 
| -  sqlite3_free(pLog->zBuf);
 | 
| -  sqlite3_free(pLog);
 | 
| -}
 | 
| -
 | 
| -static void binarylog_blob(
 | 
| -  sqlite3_vfs *pVfs,
 | 
| -  const char *zBlob,
 | 
| -  int nBlob,
 | 
| -  int isBinary
 | 
| -){
 | 
| -  InstVfsBinaryLog *pLog;
 | 
| -  InstVfs *pInstVfs = (InstVfs *)pVfs;
 | 
| -
 | 
| -  if( pVfs->xOpen!=instOpen || pInstVfs->xCall!=binarylog_xcall ){
 | 
| -    return;
 | 
| -  }
 | 
| -  pLog = (InstVfsBinaryLog *)pInstVfs->pClient;
 | 
| -  if( zBlob && (!isBinary || pLog->log_data) ){
 | 
| -    unsigned char *zRec;
 | 
| -    int nWrite;
 | 
| -
 | 
| -    if( nBlob<0 ){
 | 
| -      nBlob = strlen(zBlob);
 | 
| -    }
 | 
| -    nWrite = nBlob + 28;
 | 
| -  
 | 
| -    if( (nWrite+pLog->nBuf)>BINARYLOG_BUFFERSIZE ){
 | 
| -      binarylog_flush(pLog);
 | 
| -    }
 | 
| -  
 | 
| -    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;
 | 
| -
 | 
| -  if( zString ){
 | 
| -    binarylog_blob(pVfs, zString, -1, 0);
 | 
| -  }
 | 
| -  binarylog_xcall(pLog, eEvent, 0, nClick, return_code, 0, 0, 0, 0);
 | 
| -}
 | 
| -
 | 
| -void sqlite3_instvfs_binarylog_marker(
 | 
| -  sqlite3_vfs *pVfs,
 | 
| -  const char *zMarker
 | 
| -){
 | 
| -  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);
 | 
| -}
 | 
| -
 | 
| -sqlite3_vfs *sqlite3_instvfs_binarylog(
 | 
| -  const char *zVfs,
 | 
| -  const char *zParentVfs, 
 | 
| -  const char *zLog,
 | 
| -  int log_data
 | 
| -){
 | 
| -  InstVfsBinaryLog *p;
 | 
| -  sqlite3_vfs *pVfs;
 | 
| -  sqlite3_vfs *pParent;
 | 
| -  int nByte;
 | 
| -  int flags;
 | 
| -  int rc;
 | 
| -
 | 
| -  pParent = sqlite3_vfs_find(zParentVfs);
 | 
| -  if( !pParent ){
 | 
| -    return 0;
 | 
| -  }
 | 
| -
 | 
| -  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;
 | 
| -  }
 | 
| -
 | 
| -  pVfs = sqlite3_instvfs_create(zVfs, zParentVfs);
 | 
| -  if( pVfs ){
 | 
| -    sqlite3_instvfs_configure(pVfs, binarylog_xcall, p, binarylog_xdel);
 | 
| -  }
 | 
| -
 | 
| -  return pVfs;
 | 
| -}
 | 
| -#endif /* SQLITE_ENABLE_INSTVFS */
 | 
| -
 | 
| -/**************************************************************************
 | 
| -***************************************************************************
 | 
| -** Tcl interface starts here.
 | 
| -*/
 | 
| -#if SQLITE_TEST
 | 
| -
 | 
| -#include <tcl.h>
 | 
| -
 | 
| -#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);
 | 
| -}
 | 
| -
 | 
| -static int test_sqlite3_instvfs(
 | 
| -  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 };
 | 
| -  int iSub;
 | 
| -
 | 
| -  if( objc<2 ){
 | 
| -    Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND ...");
 | 
| -  }
 | 
| -  if( Tcl_GetIndexFromObj(interp, objv[1], IV_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"
 | 
| -        );
 | 
| -        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);
 | 
| -        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");
 | 
| -        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);
 | 
| -        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");
 | 
| -        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);
 | 
| -        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;
 | 
| -      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);
 | 
| -        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);
 | 
| -      }
 | 
| -      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);
 | 
| -      }
 | 
| -
 | 
| -      break;
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  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);
 | 
| -  return TCL_OK;
 | 
| -}
 | 
| -
 | 
| -#endif /* SQLITE_TEST */
 | 
| 
 |