mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +03:00
Add ext/misc/vfslog.c, a VFS shim for unix that keeps a log of method calls made by SQLite.
FossilOrigin-Name: 24a827b87666670c56d68a18685f4f712852fa92
This commit is contained in:
664
ext/misc/vfslog.c
Normal file
664
ext/misc/vfslog.c
Normal file
@ -0,0 +1,664 @@
|
|||||||
|
/*
|
||||||
|
** 2013-10-09
|
||||||
|
**
|
||||||
|
** 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 for
|
||||||
|
** unix that generates per-database log files of all disk activity.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
** This module contains code for a wrapper VFS that causes a log of
|
||||||
|
** most VFS calls to be written into a file on disk. The log
|
||||||
|
** is stored as comma-separated variables.
|
||||||
|
**
|
||||||
|
** All calls on sqlite3_file objects 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "sqlite3.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Forward declaration of objects used by this utility
|
||||||
|
*/
|
||||||
|
typedef struct VLogLog VLogLog;
|
||||||
|
typedef struct VLogVfs VLogVfs;
|
||||||
|
typedef struct VLogFile VLogFile;
|
||||||
|
|
||||||
|
/* There is a pair (an array of size 2) of the following objects for
|
||||||
|
** each database file being logged. The first contains the filename
|
||||||
|
** and is used to log I/O with the main database. The second has
|
||||||
|
** a NULL filename and is used to log I/O for the journal. Both
|
||||||
|
** out pointers are the same.
|
||||||
|
*/
|
||||||
|
struct VLogLog {
|
||||||
|
VLogLog *pNext; /* Next in a list of all active logs */
|
||||||
|
VLogLog **ppPrev; /* Pointer to this in the list */
|
||||||
|
int nRef; /* Number of references to this object */
|
||||||
|
int nFilename; /* Length of zFilename in bytes */
|
||||||
|
char *zFilename; /* Name of database file. NULL for journal */
|
||||||
|
FILE *out; /* Write information here */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VLogVfs {
|
||||||
|
sqlite3_vfs base; /* VFS methods */
|
||||||
|
sqlite3_vfs *pVfs; /* Parent VFS */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VLogFile {
|
||||||
|
sqlite3_file base; /* IO methods */
|
||||||
|
sqlite3_file *pReal; /* Underlying file handle */
|
||||||
|
VLogLog *pLog; /* The log file for this file */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define REALVFS(p) (((VLogVfs*)(p))->pVfs)
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Methods for VLogFile
|
||||||
|
*/
|
||||||
|
static int vlogClose(sqlite3_file*);
|
||||||
|
static int vlogRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
|
||||||
|
static int vlogWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
|
||||||
|
static int vlogTruncate(sqlite3_file*, sqlite3_int64 size);
|
||||||
|
static int vlogSync(sqlite3_file*, int flags);
|
||||||
|
static int vlogFileSize(sqlite3_file*, sqlite3_int64 *pSize);
|
||||||
|
static int vlogLock(sqlite3_file*, int);
|
||||||
|
static int vlogUnlock(sqlite3_file*, int);
|
||||||
|
static int vlogCheckReservedLock(sqlite3_file*, int *pResOut);
|
||||||
|
static int vlogFileControl(sqlite3_file*, int op, void *pArg);
|
||||||
|
static int vlogSectorSize(sqlite3_file*);
|
||||||
|
static int vlogDeviceCharacteristics(sqlite3_file*);
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Methods for VLogVfs
|
||||||
|
*/
|
||||||
|
static int vlogOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
|
||||||
|
static int vlogDelete(sqlite3_vfs*, const char *zName, int syncDir);
|
||||||
|
static int vlogAccess(sqlite3_vfs*, const char *zName, int flags, int *);
|
||||||
|
static int vlogFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
|
||||||
|
static void *vlogDlOpen(sqlite3_vfs*, const char *zFilename);
|
||||||
|
static void vlogDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
|
||||||
|
static void (*vlogDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
|
||||||
|
static void vlogDlClose(sqlite3_vfs*, void*);
|
||||||
|
static int vlogRandomness(sqlite3_vfs*, int nByte, char *zOut);
|
||||||
|
static int vlogSleep(sqlite3_vfs*, int microseconds);
|
||||||
|
static int vlogCurrentTime(sqlite3_vfs*, double*);
|
||||||
|
static int vlogGetLastError(sqlite3_vfs*, int, char *);
|
||||||
|
static int vlogCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
|
||||||
|
|
||||||
|
static VLogVfs vlog_vfs = {
|
||||||
|
{
|
||||||
|
1, /* iVersion */
|
||||||
|
0, /* szOsFile (set by register_vlog()) */
|
||||||
|
1024, /* mxPathname */
|
||||||
|
0, /* pNext */
|
||||||
|
"vfslog", /* zName */
|
||||||
|
0, /* pAppData */
|
||||||
|
vlogOpen, /* xOpen */
|
||||||
|
vlogDelete, /* xDelete */
|
||||||
|
vlogAccess, /* xAccess */
|
||||||
|
vlogFullPathname, /* xFullPathname */
|
||||||
|
vlogDlOpen, /* xDlOpen */
|
||||||
|
vlogDlError, /* xDlError */
|
||||||
|
vlogDlSym, /* xDlSym */
|
||||||
|
vlogDlClose, /* xDlClose */
|
||||||
|
vlogRandomness, /* xRandomness */
|
||||||
|
vlogSleep, /* xSleep */
|
||||||
|
vlogCurrentTime, /* xCurrentTime */
|
||||||
|
vlogGetLastError, /* xGetLastError */
|
||||||
|
vlogCurrentTimeInt64 /* xCurrentTimeInt64 */
|
||||||
|
},
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
static sqlite3_io_methods vlog_io_methods = {
|
||||||
|
1, /* iVersion */
|
||||||
|
vlogClose, /* xClose */
|
||||||
|
vlogRead, /* xRead */
|
||||||
|
vlogWrite, /* xWrite */
|
||||||
|
vlogTruncate, /* xTruncate */
|
||||||
|
vlogSync, /* xSync */
|
||||||
|
vlogFileSize, /* xFileSize */
|
||||||
|
vlogLock, /* xLock */
|
||||||
|
vlogUnlock, /* xUnlock */
|
||||||
|
vlogCheckReservedLock, /* xCheckReservedLock */
|
||||||
|
vlogFileControl, /* xFileControl */
|
||||||
|
vlogSectorSize, /* xSectorSize */
|
||||||
|
vlogDeviceCharacteristics, /* xDeviceCharacteristics */
|
||||||
|
0, /* xShmMap */
|
||||||
|
0, /* xShmLock */
|
||||||
|
0, /* xShmBarrier */
|
||||||
|
0 /* xShmUnmap */
|
||||||
|
};
|
||||||
|
|
||||||
|
#if SQLITE_OS_UNIX && !defined(NO_GETTOD)
|
||||||
|
#include <sys/time.h>
|
||||||
|
static sqlite3_uint64 vlog_time(){
|
||||||
|
struct timeval sTime;
|
||||||
|
gettimeofday(&sTime, 0);
|
||||||
|
return sTime.tv_usec + (sqlite3_uint64)sTime.tv_sec * 1000000;
|
||||||
|
}
|
||||||
|
#elif SQLITE_OS_WIN
|
||||||
|
#include <windows.h>
|
||||||
|
#include <time.h>
|
||||||
|
static sqlite3_uint64 vlog_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 vlog_time(){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Write a message to the log file
|
||||||
|
*/
|
||||||
|
static void vlogLogPrint(
|
||||||
|
VLogLog *pLog, /* The log file to write into */
|
||||||
|
sqlite3_int64 tStart, /* Start time of system call */
|
||||||
|
sqlite3_int64 tElapse, /* Elapse time of system call */
|
||||||
|
const char *zOp, /* Type of system call */
|
||||||
|
sqlite3_int64 iArg1, /* First argument */
|
||||||
|
sqlite3_int64 iArg2, /* Second argument */
|
||||||
|
const char *zArg3, /* Third argument */
|
||||||
|
int iRes /* Result */
|
||||||
|
){
|
||||||
|
char z1[40], z2[40], z3[70];
|
||||||
|
if( pLog==0 ) return;
|
||||||
|
if( iArg1>=0 ){
|
||||||
|
sqlite3_snprintf(sizeof(z1), z1, "%lld", iArg1);
|
||||||
|
}else{
|
||||||
|
z1[0] = 0;
|
||||||
|
}
|
||||||
|
if( iArg2>=0 ){
|
||||||
|
sqlite3_snprintf(sizeof(z2), z2, "%lld", iArg2);
|
||||||
|
}else{
|
||||||
|
z2[0] = 0;
|
||||||
|
}
|
||||||
|
if( zArg3 ){
|
||||||
|
sqlite3_snprintf(sizeof(z3), z3, "\"%s\"", zArg3);
|
||||||
|
}else{
|
||||||
|
z3[0] = 0;
|
||||||
|
}
|
||||||
|
fprintf(pLog->out,"%lld,%lld,%s,%d,%s,%s,%s,%d\n",
|
||||||
|
tStart, tElapse, zOp, pLog->zFilename==0, z1, z2, z3, iRes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** List of all active log connections. Protected by the master mutex.
|
||||||
|
*/
|
||||||
|
static VLogLog *allLogs = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Close a VLogLog object
|
||||||
|
*/
|
||||||
|
static void vlogLogClose(VLogLog *p){
|
||||||
|
if( p ){
|
||||||
|
sqlite3_mutex *pMutex;
|
||||||
|
p->nRef--;
|
||||||
|
if( p->nRef>0 || p->zFilename==0 ) return;
|
||||||
|
pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
|
||||||
|
sqlite3_mutex_enter(pMutex);
|
||||||
|
*p->ppPrev = p->pNext;
|
||||||
|
if( p->pNext ) p->pNext->ppPrev = p->ppPrev;
|
||||||
|
sqlite3_mutex_leave(pMutex);
|
||||||
|
fclose(p->out);
|
||||||
|
sqlite3_free(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Open a VLogLog object on the given file
|
||||||
|
*/
|
||||||
|
static VLogLog *vlogLogOpen(const char *zFilename){
|
||||||
|
int nName = (int)strlen(zFilename);
|
||||||
|
int isJournal = 0;
|
||||||
|
sqlite3_mutex *pMutex;
|
||||||
|
VLogLog *pLog, *pTemp;
|
||||||
|
if( nName>4 && strcmp(zFilename+nName-4,"-wal")==0 ){
|
||||||
|
return 0; /* Do not log wal files */
|
||||||
|
}else
|
||||||
|
if( nName>8 && strcmp(zFilename+nName-8,"-journal")==0 ){
|
||||||
|
nName -= 8;
|
||||||
|
isJournal = 1;
|
||||||
|
}else if( nName>12
|
||||||
|
&& sqlite3_strglob("-mj??????9??", zFilename+nName-12)==0 ){
|
||||||
|
return 0; /* Do not log master journal files */
|
||||||
|
}
|
||||||
|
pTemp = sqlite3_malloc( sizeof(*pLog)*2 + nName + 60 );
|
||||||
|
if( pTemp==0 ) return 0;
|
||||||
|
pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
|
||||||
|
sqlite3_mutex_enter(pMutex);
|
||||||
|
for(pLog=allLogs; pLog; pLog=pLog->pNext){
|
||||||
|
if( pLog->nFilename==nName && !memcmp(pLog->zFilename, zFilename, nName) ){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( pLog==0 ){
|
||||||
|
pLog = pTemp;
|
||||||
|
pTemp = 0;
|
||||||
|
memset(pLog, 0, sizeof(*pLog)*2);
|
||||||
|
pLog->zFilename = (char*)&pLog[2];
|
||||||
|
sqlite3_snprintf(nName+60, pLog->zFilename, "%.*s-debuglog-%lld",
|
||||||
|
nName, zFilename, vlog_time());
|
||||||
|
pLog->out = fopen(pLog->zFilename, "a");
|
||||||
|
if( pLog->out==0 ){
|
||||||
|
sqlite3_mutex_leave(pMutex);
|
||||||
|
sqlite3_free(pLog);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
pLog->nFilename = nName;
|
||||||
|
pLog[1].out = pLog[0].out;
|
||||||
|
pLog->ppPrev = &allLogs;
|
||||||
|
if( allLogs ) allLogs->ppPrev = &pLog->pNext;
|
||||||
|
pLog->pNext = allLogs;
|
||||||
|
allLogs = pLog;
|
||||||
|
}
|
||||||
|
sqlite3_mutex_leave(pMutex);
|
||||||
|
sqlite3_free(pTemp);
|
||||||
|
if( pLog && isJournal ) pLog++;
|
||||||
|
pLog->nRef++;
|
||||||
|
return pLog;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Close an vlog-file.
|
||||||
|
*/
|
||||||
|
static int vlogClose(sqlite3_file *pFile){
|
||||||
|
sqlite3_uint64 tStart, tElapse;
|
||||||
|
int rc = SQLITE_OK;
|
||||||
|
VLogFile *p = (VLogFile *)pFile;
|
||||||
|
|
||||||
|
tStart = vlog_time();
|
||||||
|
if( p->pReal->pMethods ){
|
||||||
|
rc = p->pReal->pMethods->xClose(p->pReal);
|
||||||
|
}
|
||||||
|
tElapse = vlog_time() - tStart;
|
||||||
|
vlogLogPrint(p->pLog, tStart, tElapse, "CLOSE", -1, -1, 0, rc);
|
||||||
|
vlogLogClose(p->pLog);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Compute signature for a block of content.
|
||||||
|
**
|
||||||
|
** The signature is a hex dump of the first 8 bytes of the block
|
||||||
|
** followed by a 64bit hash (expressed in hex) of the entire content.
|
||||||
|
*/
|
||||||
|
static void vlogSignature(unsigned char *p, int n, char *zCksum){
|
||||||
|
unsigned int s0 = 0, s1 = 0;
|
||||||
|
unsigned int *pI;
|
||||||
|
int i;
|
||||||
|
pI = (unsigned int*)p;
|
||||||
|
for(i=0; i<n-7; i+=8){
|
||||||
|
s0 += pI[0] + s1;
|
||||||
|
s1 += pI[1] + s0;
|
||||||
|
pI += 2;
|
||||||
|
}
|
||||||
|
for(i=0; i<8 && i<n; i++) sqlite3_snprintf(3, zCksum+i, "%02x", p[i]);
|
||||||
|
if( n>8 ) sqlite3_snprintf(18, zCksum+i, "-%08x08x", s0, s1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Read data from an vlog-file.
|
||||||
|
*/
|
||||||
|
static int vlogRead(
|
||||||
|
sqlite3_file *pFile,
|
||||||
|
void *zBuf,
|
||||||
|
int iAmt,
|
||||||
|
sqlite_int64 iOfst
|
||||||
|
){
|
||||||
|
int rc;
|
||||||
|
sqlite3_uint64 tStart, tElapse;
|
||||||
|
VLogFile *p = (VLogFile *)pFile;
|
||||||
|
char zSig[40];
|
||||||
|
|
||||||
|
tStart = vlog_time();
|
||||||
|
rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst);
|
||||||
|
tElapse = vlog_time() - tStart;
|
||||||
|
if( rc==SQLITE_OK ){
|
||||||
|
vlogSignature(zBuf, iAmt, zSig);
|
||||||
|
}else{
|
||||||
|
zSig[0] = 0;
|
||||||
|
}
|
||||||
|
vlogLogPrint(p->pLog, tStart, tElapse, "READ", iAmt, iOfst, zSig, rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Write data to an vlog-file.
|
||||||
|
*/
|
||||||
|
static int vlogWrite(
|
||||||
|
sqlite3_file *pFile,
|
||||||
|
const void *z,
|
||||||
|
int iAmt,
|
||||||
|
sqlite_int64 iOfst
|
||||||
|
){
|
||||||
|
int rc;
|
||||||
|
sqlite3_uint64 tStart, tElapse;
|
||||||
|
VLogFile *p = (VLogFile *)pFile;
|
||||||
|
char zSig[40];
|
||||||
|
|
||||||
|
tStart = vlog_time();
|
||||||
|
vlogSignature((unsigned char*)z, iAmt, zSig);
|
||||||
|
rc = p->pReal->pMethods->xWrite(p->pReal, z, iAmt, iOfst);
|
||||||
|
tElapse = vlog_time() - tStart;
|
||||||
|
vlogLogPrint(p->pLog, tStart, tElapse, "WRITE", iAmt, iOfst, zSig, rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Truncate an vlog-file.
|
||||||
|
*/
|
||||||
|
static int vlogTruncate(sqlite3_file *pFile, sqlite_int64 size){
|
||||||
|
int rc;
|
||||||
|
sqlite3_uint64 tStart, tElapse;
|
||||||
|
VLogFile *p = (VLogFile *)pFile;
|
||||||
|
tStart = vlog_time();
|
||||||
|
rc = p->pReal->pMethods->xTruncate(p->pReal, size);
|
||||||
|
tElapse = vlog_time() - tStart;
|
||||||
|
vlogLogPrint(p->pLog, tStart, tElapse, "TRUNCATE", size, -1, 0, rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Sync an vlog-file.
|
||||||
|
*/
|
||||||
|
static int vlogSync(sqlite3_file *pFile, int flags){
|
||||||
|
int rc;
|
||||||
|
sqlite3_uint64 tStart, tElapse;
|
||||||
|
VLogFile *p = (VLogFile *)pFile;
|
||||||
|
tStart = vlog_time();
|
||||||
|
rc = p->pReal->pMethods->xSync(p->pReal, flags);
|
||||||
|
tElapse = vlog_time() - tStart;
|
||||||
|
vlogLogPrint(p->pLog, tStart, tElapse, "SYNC", flags, -1, 0, rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Return the current file-size of an vlog-file.
|
||||||
|
*/
|
||||||
|
static int vlogFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
|
||||||
|
int rc;
|
||||||
|
sqlite3_uint64 tStart, tElapse;
|
||||||
|
VLogFile *p = (VLogFile *)pFile;
|
||||||
|
tStart = vlog_time();
|
||||||
|
rc = p->pReal->pMethods->xFileSize(p->pReal, pSize);
|
||||||
|
tElapse = vlog_time() - tStart;
|
||||||
|
vlogLogPrint(p->pLog, tStart, tElapse, "FILESIZE", *pSize, -1, 0, rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Lock an vlog-file.
|
||||||
|
*/
|
||||||
|
static int vlogLock(sqlite3_file *pFile, int eLock){
|
||||||
|
int rc;
|
||||||
|
sqlite3_uint64 tStart, tElapse;
|
||||||
|
VLogFile *p = (VLogFile *)pFile;
|
||||||
|
tStart = vlog_time();
|
||||||
|
rc = p->pReal->pMethods->xLock(p->pReal, eLock);
|
||||||
|
tElapse = vlog_time() - tStart;
|
||||||
|
vlogLogPrint(p->pLog, tStart, tElapse, "LOCK", eLock, -1, 0, rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Unlock an vlog-file.
|
||||||
|
*/
|
||||||
|
static int vlogUnlock(sqlite3_file *pFile, int eLock){
|
||||||
|
int rc;
|
||||||
|
sqlite3_uint64 tStart, tElapse;
|
||||||
|
VLogFile *p = (VLogFile *)pFile;
|
||||||
|
tStart = vlog_time();
|
||||||
|
rc = p->pReal->pMethods->xUnlock(p->pReal, eLock);
|
||||||
|
tElapse = vlog_time() - tStart;
|
||||||
|
vlogLogPrint(p->pLog, tStart, tElapse, "UNLOCK", eLock, -1, 0, rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Check if another file-handle holds a RESERVED lock on an vlog-file.
|
||||||
|
*/
|
||||||
|
static int vlogCheckReservedLock(sqlite3_file *pFile, int *pResOut){
|
||||||
|
int rc;
|
||||||
|
sqlite3_uint64 tStart, tElapse;
|
||||||
|
VLogFile *p = (VLogFile *)pFile;
|
||||||
|
tStart = vlog_time();
|
||||||
|
rc = p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut);
|
||||||
|
tElapse = vlog_time() - tStart;
|
||||||
|
vlogLogPrint(p->pLog, tStart, tElapse, "CHECKRESERVEDLOCK",
|
||||||
|
*pResOut, -1, "", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** File control method. For custom operations on an vlog-file.
|
||||||
|
*/
|
||||||
|
static int vlogFileControl(sqlite3_file *pFile, int op, void *pArg){
|
||||||
|
VLogFile *p = (VLogFile *)pFile;
|
||||||
|
sqlite3_uint64 tStart, tElapse;
|
||||||
|
int rc;
|
||||||
|
tStart = vlog_time();
|
||||||
|
rc = p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
|
||||||
|
if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){
|
||||||
|
*(char**)pArg = sqlite3_mprintf("vlog/%z", *(char**)pArg);
|
||||||
|
}
|
||||||
|
tElapse = vlog_time() - tStart;
|
||||||
|
vlogLogPrint(p->pLog, tStart, tElapse, "FILECONTROL", op, -1, 0, rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Return the sector-size in bytes for an vlog-file.
|
||||||
|
*/
|
||||||
|
static int vlogSectorSize(sqlite3_file *pFile){
|
||||||
|
int rc;
|
||||||
|
sqlite3_uint64 tStart, tElapse;
|
||||||
|
VLogFile *p = (VLogFile *)pFile;
|
||||||
|
tStart = vlog_time();
|
||||||
|
rc = p->pReal->pMethods->xSectorSize(p->pReal);
|
||||||
|
tElapse = vlog_time() - tStart;
|
||||||
|
vlogLogPrint(p->pLog, tStart, tElapse, "SECTORSIZE", -1, -1, 0, rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Return the device characteristic flags supported by an vlog-file.
|
||||||
|
*/
|
||||||
|
static int vlogDeviceCharacteristics(sqlite3_file *pFile){
|
||||||
|
int rc;
|
||||||
|
sqlite3_uint64 tStart, tElapse;
|
||||||
|
VLogFile *p = (VLogFile *)pFile;
|
||||||
|
tStart = vlog_time();
|
||||||
|
rc = p->pReal->pMethods->xDeviceCharacteristics(p->pReal);
|
||||||
|
tElapse = vlog_time() - tStart;
|
||||||
|
vlogLogPrint(p->pLog, tStart, tElapse, "DEVCHAR", -1, -1, 0, rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Open an vlog file handle.
|
||||||
|
*/
|
||||||
|
static int vlogOpen(
|
||||||
|
sqlite3_vfs *pVfs,
|
||||||
|
const char *zName,
|
||||||
|
sqlite3_file *pFile,
|
||||||
|
int flags,
|
||||||
|
int *pOutFlags
|
||||||
|
){
|
||||||
|
int rc;
|
||||||
|
sqlite3_uint64 tStart, tElapse;
|
||||||
|
sqlite3_int64 iArg2;
|
||||||
|
VLogFile *p = (VLogFile*)pFile;
|
||||||
|
|
||||||
|
p->pReal = (sqlite3_file*)&p[1];
|
||||||
|
if( (flags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_MAIN_JOURNAL))!=0 ){
|
||||||
|
p->pLog = vlogLogOpen(zName);
|
||||||
|
}else{
|
||||||
|
p->pLog = 0;
|
||||||
|
}
|
||||||
|
tStart = vlog_time();
|
||||||
|
rc = REALVFS(pVfs)->xOpen(REALVFS(pVfs), zName, p->pReal, flags, pOutFlags);
|
||||||
|
tElapse = vlog_time() - tStart;
|
||||||
|
iArg2 = pOutFlags ? *pOutFlags : -1;
|
||||||
|
vlogLogPrint(p->pLog, tStart, tElapse, "OPEN", flags, iArg2, 0, rc);
|
||||||
|
if( rc==SQLITE_OK ){
|
||||||
|
pFile->pMethods = &vlog_io_methods;
|
||||||
|
}else{
|
||||||
|
if( p->pLog ) vlogLogClose(p->pLog);
|
||||||
|
p->pLog = 0;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** 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 vlogDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
|
||||||
|
int rc;
|
||||||
|
sqlite3_uint64 tStart, tElapse;
|
||||||
|
VLogLog *pLog;
|
||||||
|
tStart = vlog_time();
|
||||||
|
rc = REALVFS(pVfs)->xDelete(REALVFS(pVfs), zPath, dirSync);
|
||||||
|
tElapse = vlog_time() - tStart;
|
||||||
|
pLog = vlogLogOpen(zPath);
|
||||||
|
vlogLogPrint(pLog, tStart, tElapse, "DELETE", dirSync, -1, 0, rc);
|
||||||
|
vlogLogClose(pLog);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Test for access permissions. Return true if the requested permission
|
||||||
|
** is available, or false otherwise.
|
||||||
|
*/
|
||||||
|
static int vlogAccess(
|
||||||
|
sqlite3_vfs *pVfs,
|
||||||
|
const char *zPath,
|
||||||
|
int flags,
|
||||||
|
int *pResOut
|
||||||
|
){
|
||||||
|
int rc;
|
||||||
|
sqlite3_uint64 tStart, tElapse;
|
||||||
|
VLogLog *pLog;
|
||||||
|
tStart = vlog_time();
|
||||||
|
rc = REALVFS(pVfs)->xAccess(REALVFS(pVfs), zPath, flags, pResOut);
|
||||||
|
tElapse = vlog_time() - tStart;
|
||||||
|
pLog = vlogLogOpen(zPath);
|
||||||
|
vlogLogPrint(pLog, tStart, tElapse, "ACCESS", flags, *pResOut, 0, rc);
|
||||||
|
vlogLogClose(pLog);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** 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 vlogFullPathname(
|
||||||
|
sqlite3_vfs *pVfs,
|
||||||
|
const char *zPath,
|
||||||
|
int nOut,
|
||||||
|
char *zOut
|
||||||
|
){
|
||||||
|
return REALVFS(pVfs)->xFullPathname(REALVFS(pVfs), zPath, nOut, zOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Open the dynamic library located at zPath and return a handle.
|
||||||
|
*/
|
||||||
|
static void *vlogDlOpen(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 vlogDlError(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 (*vlogDlSym(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 vlogDlClose(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 vlogRandomness(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 vlogSleep(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 vlogCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
|
||||||
|
return REALVFS(pVfs)->xCurrentTime(REALVFS(pVfs), pTimeOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vlogGetLastError(sqlite3_vfs *pVfs, int a, char *b){
|
||||||
|
return REALVFS(pVfs)->xGetLastError(REALVFS(pVfs), a, b);
|
||||||
|
}
|
||||||
|
static int vlogCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
|
||||||
|
return REALVFS(pVfs)->xCurrentTimeInt64(REALVFS(pVfs), p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Register debugvfs as the default VFS for this process.
|
||||||
|
*/
|
||||||
|
int sqlite3_register_vfslog(const char *zArg){
|
||||||
|
vlog_vfs.pVfs = sqlite3_vfs_find(0);
|
||||||
|
vlog_vfs.base.szOsFile = sizeof(VLogFile) + vlog_vfs.pVfs->szOsFile;
|
||||||
|
return sqlite3_vfs_register(&vlog_vfs.base, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
3
main.mk
3
main.mk
@ -279,7 +279,8 @@ TESTSRC += \
|
|||||||
$(TOP)/ext/misc/percentile.c \
|
$(TOP)/ext/misc/percentile.c \
|
||||||
$(TOP)/ext/misc/regexp.c \
|
$(TOP)/ext/misc/regexp.c \
|
||||||
$(TOP)/ext/misc/spellfix.c \
|
$(TOP)/ext/misc/spellfix.c \
|
||||||
$(TOP)/ext/misc/wholenumber.c
|
$(TOP)/ext/misc/wholenumber.c \
|
||||||
|
$(TOP)/ext/misc/vfslog.c
|
||||||
|
|
||||||
|
|
||||||
#TESTSRC += $(TOP)/ext/fts2/fts2_tokenizer.c
|
#TESTSRC += $(TOP)/ext/fts2/fts2_tokenizer.c
|
||||||
|
17
manifest
17
manifest
@ -1,5 +1,5 @@
|
|||||||
C Estimate\srow\ssizes\sfor\stables\sand\sindices\sand\suse\sthose\sestimates\sduring\nquery\splanning.\s\sEnhance\sthe\sindex_info\spragma\sto\sshow\sthe\sestimated\srow\nsizes\sand\sto\sshow\sthe\sestimated\srow\ssize\sfor\sthe\smain\stable\sas\swell.\s\sAllow\nan\salternative\srow\ssize\sestimate\sto\sbe\sspecified\sin\sthe\ssqlite_stat1\stable.
|
C Add\sext/misc/vfslog.c,\sa\sVFS\sshim\sfor\sunix\sthat\skeeps\sa\slog\sof\smethod\scalls\smade\sby\sSQLite.
|
||||||
D 2013-10-10T12:38:11.216
|
D 2013-10-10T13:04:46.705
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e
|
F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
@ -115,6 +115,7 @@ F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63
|
|||||||
F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc
|
F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc
|
||||||
F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a
|
F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a
|
||||||
F ext/misc/spellfix.c 5e1d547e9a2aed13897fa91bac924333f62fd2d9
|
F ext/misc/spellfix.c 5e1d547e9a2aed13897fa91bac924333f62fd2d9
|
||||||
|
F ext/misc/vfslog.c 64f8ff0605ba36fd3e71c5e3b2ea00c55448cbbe
|
||||||
F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e
|
F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e
|
||||||
F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
|
F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
|
||||||
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
|
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
|
||||||
@ -139,7 +140,7 @@ F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
|
|||||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||||
F magic.txt f2b23a6bde8f1c6e86b957e4d94eab0add520b0d
|
F magic.txt f2b23a6bde8f1c6e86b957e4d94eab0add520b0d
|
||||||
F main.mk a10f1925ae3bb545a045d1f1867506f49bee972f
|
F main.mk 4a086a18f38cd6ffec33be54dc56ade76d3a29a2
|
||||||
F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a
|
F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a
|
||||||
F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f
|
F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f
|
||||||
F mkextw.sh d2a981497b404d6498f5ff3e3b1f3816bdfcb338
|
F mkextw.sh d2a981497b404d6498f5ff3e3b1f3816bdfcb338
|
||||||
@ -723,7 +724,7 @@ F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0
|
|||||||
F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d
|
F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d
|
||||||
F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
|
F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
|
||||||
F test/percentile.test b98fc868d71eb5619d42a1702e9ab91718cbed54
|
F test/percentile.test b98fc868d71eb5619d42a1702e9ab91718cbed54
|
||||||
F test/permutations.test 72f4f8881d388163ddbbeec0a6ed812e863ea2e6
|
F test/permutations.test e154f5ed66d4d4913a99a110e870c9407f75b055
|
||||||
F test/pragma.test 5c6e8ae9eaa9a505cc1035b51f7f0da9805092c7
|
F test/pragma.test 5c6e8ae9eaa9a505cc1035b51f7f0da9805092c7
|
||||||
F test/pragma2.test 224f0381f9411a78ae685cac24c13656a62021b7
|
F test/pragma2.test 224f0381f9411a78ae685cac24c13656a62021b7
|
||||||
F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
|
F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
|
||||||
@ -1121,7 +1122,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
|
|||||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||||
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
||||||
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
||||||
P 36d64dc36f18c166b2c93c43579fa3bbb5cd545f e97d7d3044aa6c5e21d1faab7d5e709d92faa261
|
P d27b88b8c2705f444f794096c719e6f38a792165
|
||||||
R 57860f2afd769aeffdd11c615e695d0a
|
R 5f38dde3b9e8f121e53417dc6f4fda25
|
||||||
U drh
|
U dan
|
||||||
Z 2546d871db6bcc36ea3db39835f90b3e
|
Z f43e38212326572373f5c91a1aac8a3a
|
||||||
|
@ -1 +1 @@
|
|||||||
d27b88b8c2705f444f794096c719e6f38a792165
|
24a827b87666670c56d68a18685f4f712852fa92
|
@ -289,6 +289,17 @@ test_suite "queryplanner" -prefix "" -description {
|
|||||||
where.test
|
where.test
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test_suite "vfslog" -prefix "" -description {
|
||||||
|
"Vfslog" quick test suite. Like "veryquick" except does not omits
|
||||||
|
a few tests that do not work with a version 1 VFS. And the quota* tests,
|
||||||
|
which do not work with a VFS that uses the pVfs argument passed to
|
||||||
|
sqlite3_vfs methods.
|
||||||
|
} -files [
|
||||||
|
test_set $allquicktests -exclude *malloc* *ioerr* *fault* oserror.test \
|
||||||
|
pager1.test syscall.test sysfault.test tkt3457.test quota* superlock* \
|
||||||
|
wal* mmap*
|
||||||
|
]
|
||||||
|
|
||||||
lappend ::testsuitelist xxx
|
lappend ::testsuitelist xxx
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
# Define the coverage related test suites:
|
# Define the coverage related test suites:
|
||||||
|
Reference in New Issue
Block a user