📄 test_osinst.c
字号:
/*** 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.18 2008/07/25 13:32:45 drh 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 66struct 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*,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 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 *pHandle, const char *zSymbol){ return REALVFS(pVfs)->xDlSym(REALVFS(pVfs), pHandle, zSymbol);}/*** 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,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -