Add source file test_osinst.c. A wrapper vfs with instrumentation capabilities. (CVS 4977)
FossilOrigin-Name: d9a6b653d3cb608610f13d2492fe9b3887acb3b9
This commit is contained in:
parent
b5df14486d
commit
5d1f5aa6ef
1
main.mk
1
main.mk
@ -222,6 +222,7 @@ TESTSRC = \
|
||||
$(TOP)/src/test_malloc.c \
|
||||
$(TOP)/src/test_md5.c \
|
||||
$(TOP)/src/test_onefile.c \
|
||||
$(TOP)/src/test_osinst.c \
|
||||
$(TOP)/src/test_schema.c \
|
||||
$(TOP)/src/test_server.c \
|
||||
$(TOP)/src/test_tclvar.c \
|
||||
|
17
manifest
17
manifest
@ -1,5 +1,5 @@
|
||||
C Make\ssure\schanges\sto\svirtual\stables\sare\scounted\sthe\ssame\sas\sreal\stables.\nTicket\s#3038.\s(CVS\s4976)
|
||||
D 2008-04-10T14:00:10
|
||||
C Add\ssource\sfile\stest_osinst.c.\sA\swrapper\svfs\swith\sinstrumentation\scapabilities.\s(CVS\s4977)
|
||||
D 2008-04-10T14:51:01
|
||||
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
|
||||
F Makefile.in b861627d91df5ee422c54237aa38296954dc0151
|
||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||
@ -66,7 +66,7 @@ F ext/icu/README.txt 3b130aa66e7a681136f6add198b076a2f90d1e33
|
||||
F ext/icu/icu.c 12e763d288d23b5a49de37caa30737b971a2f1e2
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
|
||||
F ltmain.sh 56abb507100ed2d4261f6dd1653dec3cf4066387
|
||||
F main.mk fb8589de4dff06de85d456ba9d6191447111a61b
|
||||
F main.mk bab1f708404c928af4769336aa97931062cfe987
|
||||
F mkdll.sh 712e74f3efe08a6ba12b2945d018a29a89d7fe3b
|
||||
F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f
|
||||
F mkextw.sh 1a866b53637dab137191341cc875575a5ca110fb
|
||||
@ -143,7 +143,7 @@ F src/sqlite3ext.h faacd0e6a81aabee0861c6d7883c9172e74ef5b3
|
||||
F src/sqliteInt.h 52c381c2f15054a5199e5359cf5deb6d48624ede
|
||||
F src/sqliteLimit.h f435e728c6b620ef7312814d660a81f9356eb5c8
|
||||
F src/table.c 2c48c575dd59b3a6c5c306bc55f51a9402cf429a
|
||||
F src/tclsqlite.c 0d53336f1fc3c8a019adb56fb8daeb0f5b5238aa
|
||||
F src/tclsqlite.c c4892f48927cb3db19faeb448ea8abddfd4846a8
|
||||
F src/test1.c aada95d7a7229366e51c71055d5764c920d3364c
|
||||
F src/test2.c f0808cc643528b9620e4059ca9bda8346f526121
|
||||
F src/test3.c c715b5a8a6415d7b2c67f97c394eef488b6f7e63
|
||||
@ -164,6 +164,7 @@ F src/test_loadext.c 22065d601a18878e5542191001f0eaa5d77c0ed8
|
||||
F src/test_malloc.c c92a65e8f9b31bb2b332448d92d2016c000a963d
|
||||
F src/test_md5.c bca40b727c57462ddb415e57c5323445a1bb1a40
|
||||
F src/test_onefile.c 2fea6d22f13f5f286356c80c77ffd41f995f2b7a
|
||||
F src/test_osinst.c b6ef38b4b363a83597f9228d8bf9f63d7dc1f801
|
||||
F src/test_schema.c 12c9de7661d6294eec2d57afbb52e2af1128084f
|
||||
F src/test_server.c a6ece6c835e7eae835054124e09e947e422b1ac5
|
||||
F src/test_tclvar.c b2d1115e4d489179d3f029e765211b2ad527ba59
|
||||
@ -625,7 +626,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
|
||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
||||
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
||||
P 6f07968ec4c9d773a852ecc8343df416d17af2a4
|
||||
R bd0175fc475a5bdf6485d3176fb40c11
|
||||
U drh
|
||||
Z 0137cb2b33b517f6dae0cbba0b9baee6
|
||||
P 55591fc49c8ab8146c1f3eff733e637501bff627
|
||||
R eb917bb84cf56955a047ec767653c982
|
||||
U danielk1977
|
||||
Z 1f007475942ab467fd58433a4982bf4d
|
||||
|
@ -1 +1 @@
|
||||
55591fc49c8ab8146c1f3eff733e637501bff627
|
||||
d9a6b653d3cb608610f13d2492fe9b3887acb3b9
|
@ -12,7 +12,7 @@
|
||||
** A TCL Interface to SQLite. Append this file to sqlite3.c and
|
||||
** compile the whole thing to build a TCL-enabled version of SQLite.
|
||||
**
|
||||
** $Id: tclsqlite.c,v 1.214 2008/04/10 13:42:56 drh Exp $
|
||||
** $Id: tclsqlite.c,v 1.215 2008/04/10 14:51:01 danielk1977 Exp $
|
||||
*/
|
||||
#include "tcl.h"
|
||||
#include <errno.h>
|
||||
@ -2531,6 +2531,7 @@ int TCLSH_MAIN(int argc, char **argv){
|
||||
extern int Sqlitetesttclvar_Init(Tcl_Interp*);
|
||||
extern int SqlitetestThread_Init(Tcl_Interp*);
|
||||
extern int SqlitetestOnefile_Init();
|
||||
extern int SqlitetestOsinst_Init(Tcl_Interp*);
|
||||
|
||||
Md5_Init(interp);
|
||||
Sqliteconfig_Init(interp);
|
||||
@ -2552,6 +2553,7 @@ int TCLSH_MAIN(int argc, char **argv){
|
||||
Sqlitetesttclvar_Init(interp);
|
||||
SqlitetestThread_Init(interp);
|
||||
SqlitetestOnefile_Init(interp);
|
||||
SqlitetestOsinst_Init(interp);
|
||||
|
||||
#ifdef SQLITE_SSE
|
||||
Sqlitetestsse_Init(interp);
|
||||
|
746
src/test_osinst.c
Normal file
746
src/test_osinst.c
Normal file
@ -0,0 +1,746 @@
|
||||
/*
|
||||
** 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.
|
||||
*/
|
||||
#if SQLITE_TEST /* This file is used for testing only */
|
||||
|
||||
/*
|
||||
** Public interface:
|
||||
**
|
||||
** sqlite3_instvfs_create()
|
||||
** sqlite3_instvfs_destroy()
|
||||
** sqlite3_instvfs_configure()
|
||||
**
|
||||
** sqlite3_instvfs_reset()
|
||||
** sqlite3_instvfs_get()
|
||||
**
|
||||
** Tcl interface:
|
||||
**
|
||||
** 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 hwtime() (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 hwtime() (an integer).
|
||||
*/
|
||||
|
||||
#include "sqlite3.h"
|
||||
#include "sqliteInt.h"
|
||||
|
||||
/*
|
||||
** Maximum pathname length supported by the inst backend.
|
||||
*/
|
||||
#define INST_MAX_PATHNAME 512
|
||||
|
||||
|
||||
/* File methods */
|
||||
#define OS_CLOSE 1
|
||||
#define OS_READ 2
|
||||
#define OS_WRITE 3
|
||||
#define OS_TRUNCATE 4
|
||||
#define OS_SYNC 5
|
||||
#define OS_FILESIZE 6
|
||||
#define OS_LOCK 7
|
||||
#define OS_UNLOCK 8
|
||||
#define OS_CHECKRESERVEDLOCK 9
|
||||
#define OS_FILECONTROL 10
|
||||
#define OS_SECTORSIZE 11
|
||||
#define OS_DEVCHAR 12
|
||||
|
||||
/* Vfs methods */
|
||||
#define OS_OPEN 13
|
||||
#define OS_DELETE 14
|
||||
#define OS_ACCESS 15
|
||||
#define OS_GETTEMPNAME 16
|
||||
#define OS_FULLPATHNAME 17
|
||||
#define OS_RANDOMNESS 18
|
||||
#define OS_SLEEP 19
|
||||
#define OS_CURRENTTIME 20
|
||||
|
||||
#define OS_NUMEVENTS 21
|
||||
|
||||
struct InstVfs {
|
||||
sqlite3_vfs base;
|
||||
sqlite3_vfs *pVfs;
|
||||
|
||||
void *pClient;
|
||||
void (*xDel)(void *);
|
||||
void (*xCall)(void *, int, sqlite3_int64, const char *, int, sqlite3_int64);
|
||||
|
||||
/* Counters */
|
||||
i64 aTime[OS_NUMEVENTS];
|
||||
int aCount[OS_NUMEVENTS];
|
||||
};
|
||||
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;
|
||||
};
|
||||
|
||||
/*
|
||||
** 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*);
|
||||
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);
|
||||
static int instGetTempName(sqlite3_vfs*, int nOut, char *zOut);
|
||||
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*,void*, const char *zSymbol);
|
||||
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 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 */
|
||||
instGetTempName, /* xGetTempName */
|
||||
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 */
|
||||
};
|
||||
|
||||
/*
|
||||
** The following routine only works on pentium-class processors.
|
||||
** It uses the RDTSC opcode to read the cycle count value out of the
|
||||
** processor and returns that value. This can be used for high-res
|
||||
** profiling.
|
||||
*/
|
||||
__inline__ unsigned long long int hwtime(void){
|
||||
unsigned long long int x;
|
||||
__asm__("rdtsc\n\t"
|
||||
"mov %%edx, %%ecx\n\t"
|
||||
:"=A" (x));
|
||||
return x;
|
||||
}
|
||||
|
||||
#define OS_TIME_IO(eEvent, A, B, Call) { \
|
||||
inst_file *p = (inst_file *)pFile; \
|
||||
InstVfs *pInstVfs = p->pInstVfs; \
|
||||
int rc; \
|
||||
i64 t = hwtime(); \
|
||||
rc = Call; \
|
||||
t = hwtime() - t; \
|
||||
pInstVfs->aTime[eEvent] += t; \
|
||||
pInstVfs->aCount[eEvent] += 1; \
|
||||
if( pInstVfs->xCall ){ \
|
||||
pInstVfs->xCall(pInstVfs->pClient, eEvent, t, p->zName, A, B); \
|
||||
} \
|
||||
return rc; \
|
||||
}
|
||||
|
||||
#define OS_TIME_VFS(eEvent, Z, A, B, Call) { \
|
||||
InstVfs *pInstVfs = (InstVfs *)pVfs; \
|
||||
int rc; \
|
||||
i64 t = hwtime(); \
|
||||
rc = Call; \
|
||||
t = hwtime() - t; \
|
||||
pInstVfs->aTime[eEvent] += t; \
|
||||
pInstVfs->aCount[eEvent] += 1; \
|
||||
if( pInstVfs->xCall ){ \
|
||||
pInstVfs->xCall(pInstVfs->pClient, eEvent, t, Z, A, B); \
|
||||
} \
|
||||
return rc; \
|
||||
}
|
||||
|
||||
/*
|
||||
** Close an inst-file.
|
||||
*/
|
||||
static int instClose(sqlite3_file *pFile){
|
||||
OS_TIME_IO(OS_CLOSE, 0, 0, sqlite3OsClose(p->pReal));
|
||||
}
|
||||
|
||||
/*
|
||||
** Read data from an inst-file.
|
||||
*/
|
||||
static int instRead(
|
||||
sqlite3_file *pFile,
|
||||
void *zBuf,
|
||||
int iAmt,
|
||||
sqlite_int64 iOfst
|
||||
){
|
||||
OS_TIME_IO(OS_READ, iAmt, iOfst, sqlite3OsRead(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
|
||||
){
|
||||
OS_TIME_IO(OS_WRITE, iAmt, iOfst, sqlite3OsWrite(p->pReal, z, iAmt, iOfst));
|
||||
}
|
||||
|
||||
/*
|
||||
** Truncate an inst-file.
|
||||
*/
|
||||
static int instTruncate(sqlite3_file *pFile, sqlite_int64 size){
|
||||
OS_TIME_IO(OS_TRUNCATE, 0, size, sqlite3OsTruncate(p->pReal, size));
|
||||
}
|
||||
|
||||
/*
|
||||
** Sync an inst-file.
|
||||
*/
|
||||
static int instSync(sqlite3_file *pFile, int flags){
|
||||
OS_TIME_IO(OS_SYNC, flags, 0, sqlite3OsSync(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, 0, 0, sqlite3OsFileSize(p->pReal, pSize));
|
||||
}
|
||||
|
||||
/*
|
||||
** Lock an inst-file.
|
||||
*/
|
||||
static int instLock(sqlite3_file *pFile, int eLock){
|
||||
OS_TIME_IO(OS_LOCK, eLock, 0, sqlite3OsLock(p->pReal, eLock));
|
||||
}
|
||||
|
||||
/*
|
||||
** Unlock an inst-file.
|
||||
*/
|
||||
static int instUnlock(sqlite3_file *pFile, int eLock){
|
||||
OS_TIME_IO(OS_UNLOCK, eLock, 0, sqlite3OsUnlock(p->pReal, eLock));
|
||||
}
|
||||
|
||||
/*
|
||||
** Check if another file-handle holds a RESERVED lock on an inst-file.
|
||||
*/
|
||||
static int instCheckReservedLock(sqlite3_file *pFile){
|
||||
OS_TIME_IO(OS_CHECKRESERVEDLOCK, 0, 0, sqlite3OsCheckReservedLock(p->pReal));
|
||||
}
|
||||
|
||||
/*
|
||||
** 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, sqlite3OsFileControl(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, sqlite3OsSectorSize(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, sqlite3OsDeviceCharacteristics(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;
|
||||
|
||||
OS_TIME_VFS(OS_OPEN, zName, flags, 0,
|
||||
sqlite3OsOpen(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){
|
||||
OS_TIME_VFS(OS_DELETE, zPath, dirSync, 0,
|
||||
sqlite3OsDelete(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){
|
||||
OS_TIME_VFS(OS_ACCESS, zPath, flags, 0,
|
||||
sqlite3OsAccess(REALVFS(pVfs), zPath, flags)
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
** Populate buffer zBufOut with a pathname suitable for use as a
|
||||
** temporary file. zBufOut is guaranteed to point to a buffer of
|
||||
** at least (INST_MAX_PATHNAME+1) bytes.
|
||||
*/
|
||||
static int instGetTempName(sqlite3_vfs *pVfs, int nOut, char *zBufOut){
|
||||
OS_TIME_VFS( OS_GETTEMPNAME, 0, 0, 0,
|
||||
sqlite3OsGetTempname(REALVFS(pVfs), nOut, zBufOut);
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
** 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,
|
||||
sqlite3OsFullPathname(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 sqlite3OsDlOpen(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){
|
||||
sqlite3OsDlError(REALVFS(pVfs), nByte, zErrMsg);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
|
||||
*/
|
||||
static void *instDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){
|
||||
return sqlite3OsDlSym(REALVFS(pVfs), pHandle, zSymbol);
|
||||
}
|
||||
|
||||
/*
|
||||
** Close the dynamic library handle pHandle.
|
||||
*/
|
||||
static void instDlClose(sqlite3_vfs *pVfs, void *pHandle){
|
||||
sqlite3OsDlClose(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, nByte, 0,
|
||||
sqlite3OsRandomness(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, nMicro, 0,
|
||||
sqlite3OsSleep(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,
|
||||
sqlite3OsCurrentTime(REALVFS(pVfs), pTimeOut)
|
||||
);
|
||||
}
|
||||
|
||||
sqlite3_vfs *sqlite3_instvfs_create(char *zName, 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, sqlite3_int64, const char *, 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){
|
||||
sqlite3_vfs_unregister(pVfs);
|
||||
sqlite3_free(pVfs);
|
||||
}
|
||||
|
||||
void sqlite3_instvfs_reset(sqlite3_vfs *pVfs){
|
||||
InstVfs *p = (InstVfs *)pVfs;
|
||||
assert( pVfs->xOpen==instOpen );
|
||||
memset(p->aTime, 0, sizeof(i64)*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_GETTEMPNAME: zEvent = "xGetTempName"; 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];
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
***************************************************************************
|
||||
** Tcl interface starts here.
|
||||
*/
|
||||
|
||||
#include <tcl.h>
|
||||
|
||||
struct InstVfsCall {
|
||||
Tcl_Interp *interp;
|
||||
Tcl_Obj *pScript;
|
||||
};
|
||||
typedef struct InstVfsCall InstVfsCall;
|
||||
|
||||
static void test_instvfs_xcall(
|
||||
void *p,
|
||||
int eEvent,
|
||||
sqlite3_int64 nClick,
|
||||
const char *zName,
|
||||
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", 0 };
|
||||
enum IV_enum { IV_CREATE, IV_DESTROY, IV_RESET, IV_REPORT, IV_CONFIGURE };
|
||||
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;
|
||||
if( objc!=4 && objc!=3 ){
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "NAME ?PARENT-VFS?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( objc==4 ){
|
||||
zParent = Tcl_GetString(objv[3]);
|
||||
}
|
||||
p = sqlite3_instvfs_create(Tcl_GetString(objv[2]), zParent);
|
||||
if( !p ){
|
||||
Tcl_AppendResult(interp, "error creating vfs ", 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_SetObjResult(interp, objv[2]);
|
||||
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;
|
||||
i64 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;
|
||||
}
|
||||
|
||||
int SqlitetestOsinst_Init(Tcl_Interp *interp){
|
||||
Tcl_CreateObjCommand(interp, "sqlite3_instvfs", test_sqlite3_instvfs, 0, 0);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user