vfslog.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  1. /*
  2. ** 2013-10-09
  3. **
  4. ** The author disclaims copyright to this source code. In place of
  5. ** a legal notice, here is a blessing:
  6. **
  7. ** May you do good and not evil.
  8. ** May you find forgiveness for yourself and forgive others.
  9. ** May you share freely, never taking more than you give.
  10. **
  11. ******************************************************************************
  12. **
  13. ** This file contains the implementation of an SQLite vfs wrapper for
  14. ** unix that generates per-database log files of all disk activity.
  15. */
  16. /*
  17. ** This module contains code for a wrapper VFS that causes a log of
  18. ** most VFS calls to be written into a file on disk. The log
  19. ** is stored as comma-separated variables.
  20. **
  21. ** All calls on sqlite3_file objects are logged.
  22. ** Additionally, calls to the xAccess(), xOpen(), and xDelete()
  23. ** methods are logged. The other sqlite3_vfs object methods (xDlXXX,
  24. ** xRandomness, xSleep, xCurrentTime, xGetLastError and xCurrentTimeInt64)
  25. ** are not logged.
  26. */
  27. #include "sqlite3.h"
  28. #include <string.h>
  29. #include <assert.h>
  30. #include <stdio.h>
  31. #if SQLITE_OS_UNIX
  32. # include <unistd.h>
  33. #endif
  34. /*
  35. ** Forward declaration of objects used by this utility
  36. */
  37. typedef struct VLogLog VLogLog;
  38. typedef struct VLogVfs VLogVfs;
  39. typedef struct VLogFile VLogFile;
  40. /* There is a pair (an array of size 2) of the following objects for
  41. ** each database file being logged. The first contains the filename
  42. ** and is used to log I/O with the main database. The second has
  43. ** a NULL filename and is used to log I/O for the journal. Both
  44. ** out pointers are the same.
  45. */
  46. struct VLogLog {
  47. VLogLog *pNext; /* Next in a list of all active logs */
  48. VLogLog **ppPrev; /* Pointer to this in the list */
  49. int nRef; /* Number of references to this object */
  50. int nFilename; /* Length of zFilename in bytes */
  51. char *zFilename; /* Name of database file. NULL for journal */
  52. FILE *out; /* Write information here */
  53. };
  54. struct VLogVfs {
  55. sqlite3_vfs base; /* VFS methods */
  56. sqlite3_vfs *pVfs; /* Parent VFS */
  57. };
  58. struct VLogFile {
  59. sqlite3_file base; /* IO methods */
  60. sqlite3_file *pReal; /* Underlying file handle */
  61. VLogLog *pLog; /* The log file for this file */
  62. };
  63. #define REALVFS(p) (((VLogVfs*)(p))->pVfs)
  64. /*
  65. ** Methods for VLogFile
  66. */
  67. static int vlogClose(sqlite3_file*);
  68. static int vlogRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
  69. static int vlogWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
  70. static int vlogTruncate(sqlite3_file*, sqlite3_int64 size);
  71. static int vlogSync(sqlite3_file*, int flags);
  72. static int vlogFileSize(sqlite3_file*, sqlite3_int64 *pSize);
  73. static int vlogLock(sqlite3_file*, int);
  74. static int vlogUnlock(sqlite3_file*, int);
  75. static int vlogCheckReservedLock(sqlite3_file*, int *pResOut);
  76. static int vlogFileControl(sqlite3_file*, int op, void *pArg);
  77. static int vlogSectorSize(sqlite3_file*);
  78. static int vlogDeviceCharacteristics(sqlite3_file*);
  79. /*
  80. ** Methods for VLogVfs
  81. */
  82. static int vlogOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
  83. static int vlogDelete(sqlite3_vfs*, const char *zName, int syncDir);
  84. static int vlogAccess(sqlite3_vfs*, const char *zName, int flags, int *);
  85. static int vlogFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
  86. static void *vlogDlOpen(sqlite3_vfs*, const char *zFilename);
  87. static void vlogDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
  88. static void (*vlogDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
  89. static void vlogDlClose(sqlite3_vfs*, void*);
  90. static int vlogRandomness(sqlite3_vfs*, int nByte, char *zOut);
  91. static int vlogSleep(sqlite3_vfs*, int microseconds);
  92. static int vlogCurrentTime(sqlite3_vfs*, double*);
  93. static int vlogGetLastError(sqlite3_vfs*, int, char *);
  94. static int vlogCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
  95. static VLogVfs vlog_vfs = {
  96. {
  97. 1, /* iVersion */
  98. 0, /* szOsFile (set by register_vlog()) */
  99. 1024, /* mxPathname */
  100. 0, /* pNext */
  101. "vfslog", /* zName */
  102. 0, /* pAppData */
  103. vlogOpen, /* xOpen */
  104. vlogDelete, /* xDelete */
  105. vlogAccess, /* xAccess */
  106. vlogFullPathname, /* xFullPathname */
  107. vlogDlOpen, /* xDlOpen */
  108. vlogDlError, /* xDlError */
  109. vlogDlSym, /* xDlSym */
  110. vlogDlClose, /* xDlClose */
  111. vlogRandomness, /* xRandomness */
  112. vlogSleep, /* xSleep */
  113. vlogCurrentTime, /* xCurrentTime */
  114. vlogGetLastError, /* xGetLastError */
  115. vlogCurrentTimeInt64 /* xCurrentTimeInt64 */
  116. },
  117. 0
  118. };
  119. static sqlite3_io_methods vlog_io_methods = {
  120. 1, /* iVersion */
  121. vlogClose, /* xClose */
  122. vlogRead, /* xRead */
  123. vlogWrite, /* xWrite */
  124. vlogTruncate, /* xTruncate */
  125. vlogSync, /* xSync */
  126. vlogFileSize, /* xFileSize */
  127. vlogLock, /* xLock */
  128. vlogUnlock, /* xUnlock */
  129. vlogCheckReservedLock, /* xCheckReservedLock */
  130. vlogFileControl, /* xFileControl */
  131. vlogSectorSize, /* xSectorSize */
  132. vlogDeviceCharacteristics, /* xDeviceCharacteristics */
  133. 0, /* xShmMap */
  134. 0, /* xShmLock */
  135. 0, /* xShmBarrier */
  136. 0 /* xShmUnmap */
  137. };
  138. #if SQLITE_OS_UNIX && !defined(NO_GETTOD)
  139. #include <sys/time.h>
  140. static sqlite3_uint64 vlog_time(){
  141. struct timeval sTime;
  142. gettimeofday(&sTime, 0);
  143. return sTime.tv_usec + (sqlite3_uint64)sTime.tv_sec * 1000000;
  144. }
  145. #elif SQLITE_OS_WIN
  146. #include <windows.h>
  147. #include <time.h>
  148. static sqlite3_uint64 vlog_time(){
  149. FILETIME ft;
  150. sqlite3_uint64 u64time = 0;
  151. GetSystemTimeAsFileTime(&ft);
  152. u64time |= ft.dwHighDateTime;
  153. u64time <<= 32;
  154. u64time |= ft.dwLowDateTime;
  155. /* ft is 100-nanosecond intervals, we want microseconds */
  156. return u64time /(sqlite3_uint64)10;
  157. }
  158. #else
  159. static sqlite3_uint64 vlog_time(){
  160. return 0;
  161. }
  162. #endif
  163. /*
  164. ** Write a message to the log file
  165. */
  166. static void vlogLogPrint(
  167. VLogLog *pLog, /* The log file to write into */
  168. sqlite3_int64 tStart, /* Start time of system call */
  169. sqlite3_int64 tElapse, /* Elapse time of system call */
  170. const char *zOp, /* Type of system call */
  171. sqlite3_int64 iArg1, /* First argument */
  172. sqlite3_int64 iArg2, /* Second argument */
  173. const char *zArg3, /* Third argument */
  174. int iRes /* Result */
  175. ){
  176. char z1[40], z2[40], z3[70];
  177. if( pLog==0 ) return;
  178. if( iArg1>=0 ){
  179. sqlite3_snprintf(sizeof(z1), z1, "%lld", iArg1);
  180. }else{
  181. z1[0] = 0;
  182. }
  183. if( iArg2>=0 ){
  184. sqlite3_snprintf(sizeof(z2), z2, "%lld", iArg2);
  185. }else{
  186. z2[0] = 0;
  187. }
  188. if( zArg3 ){
  189. sqlite3_snprintf(sizeof(z3), z3, "\"%s\"", zArg3);
  190. }else{
  191. z3[0] = 0;
  192. }
  193. fprintf(pLog->out,"%lld,%lld,%s,%d,%s,%s,%s,%d\n",
  194. tStart, tElapse, zOp, pLog->zFilename==0, z1, z2, z3, iRes);
  195. }
  196. /*
  197. ** List of all active log connections. Protected by the master mutex.
  198. */
  199. static VLogLog *allLogs = 0;
  200. /*
  201. ** Close a VLogLog object
  202. */
  203. static void vlogLogClose(VLogLog *p){
  204. if( p ){
  205. sqlite3_mutex *pMutex;
  206. p->nRef--;
  207. if( p->nRef>0 || p->zFilename==0 ) return;
  208. pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
  209. sqlite3_mutex_enter(pMutex);
  210. *p->ppPrev = p->pNext;
  211. if( p->pNext ) p->pNext->ppPrev = p->ppPrev;
  212. sqlite3_mutex_leave(pMutex);
  213. fclose(p->out);
  214. sqlite3_free(p);
  215. }
  216. }
  217. /*
  218. ** Open a VLogLog object on the given file
  219. */
  220. static VLogLog *vlogLogOpen(const char *zFilename){
  221. int nName = (int)strlen(zFilename);
  222. int isJournal = 0;
  223. sqlite3_mutex *pMutex;
  224. VLogLog *pLog, *pTemp;
  225. sqlite3_int64 tNow = 0;
  226. if( nName>4 && strcmp(zFilename+nName-4,"-wal")==0 ){
  227. return 0; /* Do not log wal files */
  228. }else
  229. if( nName>8 && strcmp(zFilename+nName-8,"-journal")==0 ){
  230. nName -= 8;
  231. isJournal = 1;
  232. }else if( nName>12
  233. && sqlite3_strglob("-mj??????9??", zFilename+nName-12)==0 ){
  234. return 0; /* Do not log master journal files */
  235. }
  236. pTemp = sqlite3_malloc( sizeof(*pLog)*2 + nName + 60 );
  237. if( pTemp==0 ) return 0;
  238. pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
  239. sqlite3_mutex_enter(pMutex);
  240. for(pLog=allLogs; pLog; pLog=pLog->pNext){
  241. if( pLog->nFilename==nName && !memcmp(pLog->zFilename, zFilename, nName) ){
  242. break;
  243. }
  244. }
  245. if( pLog==0 ){
  246. pLog = pTemp;
  247. pTemp = 0;
  248. memset(pLog, 0, sizeof(*pLog)*2);
  249. pLog->zFilename = (char*)&pLog[2];
  250. tNow = vlog_time();
  251. sqlite3_snprintf(nName+60, pLog->zFilename, "%.*s-debuglog-%lld",
  252. nName, zFilename, tNow);
  253. pLog->out = fopen(pLog->zFilename, "a");
  254. if( pLog->out==0 ){
  255. sqlite3_mutex_leave(pMutex);
  256. sqlite3_free(pLog);
  257. return 0;
  258. }
  259. pLog->nFilename = nName;
  260. pLog[1].out = pLog[0].out;
  261. pLog->ppPrev = &allLogs;
  262. if( allLogs ) allLogs->ppPrev = &pLog->pNext;
  263. pLog->pNext = allLogs;
  264. allLogs = pLog;
  265. }
  266. sqlite3_mutex_leave(pMutex);
  267. if( pTemp ){
  268. sqlite3_free(pTemp);
  269. }else{
  270. #if SQLITE_OS_UNIX
  271. char zHost[200];
  272. zHost[0] = 0;
  273. gethostname(zHost, sizeof(zHost)-1);
  274. zHost[sizeof(zHost)-1] = 0;
  275. vlogLogPrint(pLog, tNow, 0, "IDENT", getpid(), -1, zHost, 0);
  276. #endif
  277. }
  278. if( pLog && isJournal ) pLog++;
  279. pLog->nRef++;
  280. return pLog;
  281. }
  282. /*
  283. ** Close an vlog-file.
  284. */
  285. static int vlogClose(sqlite3_file *pFile){
  286. sqlite3_uint64 tStart, tElapse;
  287. int rc = SQLITE_OK;
  288. VLogFile *p = (VLogFile *)pFile;
  289. tStart = vlog_time();
  290. if( p->pReal->pMethods ){
  291. rc = p->pReal->pMethods->xClose(p->pReal);
  292. }
  293. tElapse = vlog_time() - tStart;
  294. vlogLogPrint(p->pLog, tStart, tElapse, "CLOSE", -1, -1, 0, rc);
  295. vlogLogClose(p->pLog);
  296. return rc;
  297. }
  298. /*
  299. ** Compute signature for a block of content.
  300. **
  301. ** For blocks of 16 or fewer bytes, the signature is just a hex dump of
  302. ** the entire block.
  303. **
  304. ** For blocks of more than 16 bytes, the signature is a hex dump of the
  305. ** first 8 bytes followed by a 64-bit has of the entire block.
  306. */
  307. static void vlogSignature(unsigned char *p, int n, char *zCksum){
  308. unsigned int s0 = 0, s1 = 0;
  309. unsigned int *pI;
  310. int i;
  311. if( n<=16 ){
  312. for(i=0; i<n; i++) sqlite3_snprintf(3, zCksum+i*2, "%02x", p[i]);
  313. }else{
  314. pI = (unsigned int*)p;
  315. for(i=0; i<n-7; i+=8){
  316. s0 += pI[0] + s1;
  317. s1 += pI[1] + s0;
  318. pI += 2;
  319. }
  320. for(i=0; i<8; i++) sqlite3_snprintf(3, zCksum+i*2, "%02x", p[i]);
  321. sqlite3_snprintf(18, zCksum+i*2, "-%08x%08x", s0, s1);
  322. }
  323. }
  324. /*
  325. ** Read data from an vlog-file.
  326. */
  327. static int vlogRead(
  328. sqlite3_file *pFile,
  329. void *zBuf,
  330. int iAmt,
  331. sqlite_int64 iOfst
  332. ){
  333. int rc;
  334. sqlite3_uint64 tStart, tElapse;
  335. VLogFile *p = (VLogFile *)pFile;
  336. char zSig[40];
  337. tStart = vlog_time();
  338. rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst);
  339. tElapse = vlog_time() - tStart;
  340. if( rc==SQLITE_OK ){
  341. vlogSignature(zBuf, iAmt, zSig);
  342. }else{
  343. zSig[0] = 0;
  344. }
  345. vlogLogPrint(p->pLog, tStart, tElapse, "READ", iAmt, iOfst, zSig, rc);
  346. if( rc==SQLITE_OK
  347. && p->pLog
  348. && p->pLog->zFilename
  349. && iOfst<=24
  350. && iOfst+iAmt>=28
  351. ){
  352. unsigned char *x = ((unsigned char*)zBuf)+(24-iOfst);
  353. unsigned iCtr;
  354. iCtr = (x[0]<<24) + (x[1]<<16) + (x[2]<<8) + x[3];
  355. vlogLogPrint(p->pLog, tStart, 0, "CHNGCTR-READ", iCtr, -1, 0, 0);
  356. }
  357. return rc;
  358. }
  359. /*
  360. ** Write data to an vlog-file.
  361. */
  362. static int vlogWrite(
  363. sqlite3_file *pFile,
  364. const void *z,
  365. int iAmt,
  366. sqlite_int64 iOfst
  367. ){
  368. int rc;
  369. sqlite3_uint64 tStart, tElapse;
  370. VLogFile *p = (VLogFile *)pFile;
  371. char zSig[40];
  372. tStart = vlog_time();
  373. vlogSignature((unsigned char*)z, iAmt, zSig);
  374. rc = p->pReal->pMethods->xWrite(p->pReal, z, iAmt, iOfst);
  375. tElapse = vlog_time() - tStart;
  376. vlogLogPrint(p->pLog, tStart, tElapse, "WRITE", iAmt, iOfst, zSig, rc);
  377. if( rc==SQLITE_OK
  378. && p->pLog
  379. && p->pLog->zFilename
  380. && iOfst<=24
  381. && iOfst+iAmt>=28
  382. ){
  383. unsigned char *x = ((unsigned char*)z)+(24-iOfst);
  384. unsigned iCtr;
  385. iCtr = (x[0]<<24) + (x[1]<<16) + (x[2]<<8) + x[3];
  386. vlogLogPrint(p->pLog, tStart, 0, "CHNGCTR-WRITE", iCtr, -1, 0, 0);
  387. }
  388. return rc;
  389. }
  390. /*
  391. ** Truncate an vlog-file.
  392. */
  393. static int vlogTruncate(sqlite3_file *pFile, sqlite_int64 size){
  394. int rc;
  395. sqlite3_uint64 tStart, tElapse;
  396. VLogFile *p = (VLogFile *)pFile;
  397. tStart = vlog_time();
  398. rc = p->pReal->pMethods->xTruncate(p->pReal, size);
  399. tElapse = vlog_time() - tStart;
  400. vlogLogPrint(p->pLog, tStart, tElapse, "TRUNCATE", size, -1, 0, rc);
  401. return rc;
  402. }
  403. /*
  404. ** Sync an vlog-file.
  405. */
  406. static int vlogSync(sqlite3_file *pFile, int flags){
  407. int rc;
  408. sqlite3_uint64 tStart, tElapse;
  409. VLogFile *p = (VLogFile *)pFile;
  410. tStart = vlog_time();
  411. rc = p->pReal->pMethods->xSync(p->pReal, flags);
  412. tElapse = vlog_time() - tStart;
  413. vlogLogPrint(p->pLog, tStart, tElapse, "SYNC", flags, -1, 0, rc);
  414. return rc;
  415. }
  416. /*
  417. ** Return the current file-size of an vlog-file.
  418. */
  419. static int vlogFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
  420. int rc;
  421. sqlite3_uint64 tStart, tElapse;
  422. VLogFile *p = (VLogFile *)pFile;
  423. tStart = vlog_time();
  424. rc = p->pReal->pMethods->xFileSize(p->pReal, pSize);
  425. tElapse = vlog_time() - tStart;
  426. vlogLogPrint(p->pLog, tStart, tElapse, "FILESIZE", *pSize, -1, 0, rc);
  427. return rc;
  428. }
  429. /*
  430. ** Lock an vlog-file.
  431. */
  432. static int vlogLock(sqlite3_file *pFile, int eLock){
  433. int rc;
  434. sqlite3_uint64 tStart, tElapse;
  435. VLogFile *p = (VLogFile *)pFile;
  436. tStart = vlog_time();
  437. rc = p->pReal->pMethods->xLock(p->pReal, eLock);
  438. tElapse = vlog_time() - tStart;
  439. vlogLogPrint(p->pLog, tStart, tElapse, "LOCK", eLock, -1, 0, rc);
  440. return rc;
  441. }
  442. /*
  443. ** Unlock an vlog-file.
  444. */
  445. static int vlogUnlock(sqlite3_file *pFile, int eLock){
  446. int rc;
  447. sqlite3_uint64 tStart, tElapse;
  448. VLogFile *p = (VLogFile *)pFile;
  449. tStart = vlog_time();
  450. rc = p->pReal->pMethods->xUnlock(p->pReal, eLock);
  451. tElapse = vlog_time() - tStart;
  452. vlogLogPrint(p->pLog, tStart, tElapse, "UNLOCK", eLock, -1, 0, rc);
  453. return rc;
  454. }
  455. /*
  456. ** Check if another file-handle holds a RESERVED lock on an vlog-file.
  457. */
  458. static int vlogCheckReservedLock(sqlite3_file *pFile, int *pResOut){
  459. int rc;
  460. sqlite3_uint64 tStart, tElapse;
  461. VLogFile *p = (VLogFile *)pFile;
  462. tStart = vlog_time();
  463. rc = p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut);
  464. tElapse = vlog_time() - tStart;
  465. vlogLogPrint(p->pLog, tStart, tElapse, "CHECKRESERVEDLOCK",
  466. *pResOut, -1, "", rc);
  467. return rc;
  468. }
  469. /*
  470. ** File control method. For custom operations on an vlog-file.
  471. */
  472. static int vlogFileControl(sqlite3_file *pFile, int op, void *pArg){
  473. VLogFile *p = (VLogFile *)pFile;
  474. sqlite3_uint64 tStart, tElapse;
  475. int rc;
  476. tStart = vlog_time();
  477. rc = p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
  478. if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){
  479. *(char**)pArg = sqlite3_mprintf("vlog/%z", *(char**)pArg);
  480. }
  481. tElapse = vlog_time() - tStart;
  482. vlogLogPrint(p->pLog, tStart, tElapse, "FILECONTROL", op, -1, 0, rc);
  483. return rc;
  484. }
  485. /*
  486. ** Return the sector-size in bytes for an vlog-file.
  487. */
  488. static int vlogSectorSize(sqlite3_file *pFile){
  489. int rc;
  490. sqlite3_uint64 tStart, tElapse;
  491. VLogFile *p = (VLogFile *)pFile;
  492. tStart = vlog_time();
  493. rc = p->pReal->pMethods->xSectorSize(p->pReal);
  494. tElapse = vlog_time() - tStart;
  495. vlogLogPrint(p->pLog, tStart, tElapse, "SECTORSIZE", -1, -1, 0, rc);
  496. return rc;
  497. }
  498. /*
  499. ** Return the device characteristic flags supported by an vlog-file.
  500. */
  501. static int vlogDeviceCharacteristics(sqlite3_file *pFile){
  502. int rc;
  503. sqlite3_uint64 tStart, tElapse;
  504. VLogFile *p = (VLogFile *)pFile;
  505. tStart = vlog_time();
  506. rc = p->pReal->pMethods->xDeviceCharacteristics(p->pReal);
  507. tElapse = vlog_time() - tStart;
  508. vlogLogPrint(p->pLog, tStart, tElapse, "DEVCHAR", -1, -1, 0, rc);
  509. return rc;
  510. }
  511. /*
  512. ** Open an vlog file handle.
  513. */
  514. static int vlogOpen(
  515. sqlite3_vfs *pVfs,
  516. const char *zName,
  517. sqlite3_file *pFile,
  518. int flags,
  519. int *pOutFlags
  520. ){
  521. int rc;
  522. sqlite3_uint64 tStart, tElapse;
  523. sqlite3_int64 iArg2;
  524. VLogFile *p = (VLogFile*)pFile;
  525. p->pReal = (sqlite3_file*)&p[1];
  526. if( (flags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_MAIN_JOURNAL))!=0 ){
  527. p->pLog = vlogLogOpen(zName);
  528. }else{
  529. p->pLog = 0;
  530. }
  531. tStart = vlog_time();
  532. rc = REALVFS(pVfs)->xOpen(REALVFS(pVfs), zName, p->pReal, flags, pOutFlags);
  533. tElapse = vlog_time() - tStart;
  534. iArg2 = pOutFlags ? *pOutFlags : -1;
  535. vlogLogPrint(p->pLog, tStart, tElapse, "OPEN", flags, iArg2, 0, rc);
  536. if( rc==SQLITE_OK ){
  537. pFile->pMethods = &vlog_io_methods;
  538. }else{
  539. if( p->pLog ) vlogLogClose(p->pLog);
  540. p->pLog = 0;
  541. }
  542. return rc;
  543. }
  544. /*
  545. ** Delete the file located at zPath. If the dirSync argument is true,
  546. ** ensure the file-system modifications are synced to disk before
  547. ** returning.
  548. */
  549. static int vlogDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
  550. int rc;
  551. sqlite3_uint64 tStart, tElapse;
  552. VLogLog *pLog;
  553. tStart = vlog_time();
  554. rc = REALVFS(pVfs)->xDelete(REALVFS(pVfs), zPath, dirSync);
  555. tElapse = vlog_time() - tStart;
  556. pLog = vlogLogOpen(zPath);
  557. vlogLogPrint(pLog, tStart, tElapse, "DELETE", dirSync, -1, 0, rc);
  558. vlogLogClose(pLog);
  559. return rc;
  560. }
  561. /*
  562. ** Test for access permissions. Return true if the requested permission
  563. ** is available, or false otherwise.
  564. */
  565. static int vlogAccess(
  566. sqlite3_vfs *pVfs,
  567. const char *zPath,
  568. int flags,
  569. int *pResOut
  570. ){
  571. int rc;
  572. sqlite3_uint64 tStart, tElapse;
  573. VLogLog *pLog;
  574. tStart = vlog_time();
  575. rc = REALVFS(pVfs)->xAccess(REALVFS(pVfs), zPath, flags, pResOut);
  576. tElapse = vlog_time() - tStart;
  577. pLog = vlogLogOpen(zPath);
  578. vlogLogPrint(pLog, tStart, tElapse, "ACCESS", flags, *pResOut, 0, rc);
  579. vlogLogClose(pLog);
  580. return rc;
  581. }
  582. /*
  583. ** Populate buffer zOut with the full canonical pathname corresponding
  584. ** to the pathname in zPath. zOut is guaranteed to point to a buffer
  585. ** of at least (INST_MAX_PATHNAME+1) bytes.
  586. */
  587. static int vlogFullPathname(
  588. sqlite3_vfs *pVfs,
  589. const char *zPath,
  590. int nOut,
  591. char *zOut
  592. ){
  593. return REALVFS(pVfs)->xFullPathname(REALVFS(pVfs), zPath, nOut, zOut);
  594. }
  595. /*
  596. ** Open the dynamic library located at zPath and return a handle.
  597. */
  598. static void *vlogDlOpen(sqlite3_vfs *pVfs, const char *zPath){
  599. return REALVFS(pVfs)->xDlOpen(REALVFS(pVfs), zPath);
  600. }
  601. /*
  602. ** Populate the buffer zErrMsg (size nByte bytes) with a human readable
  603. ** utf-8 string describing the most recent error encountered associated
  604. ** with dynamic libraries.
  605. */
  606. static void vlogDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
  607. REALVFS(pVfs)->xDlError(REALVFS(pVfs), nByte, zErrMsg);
  608. }
  609. /*
  610. ** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
  611. */
  612. static void (*vlogDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
  613. return REALVFS(pVfs)->xDlSym(REALVFS(pVfs), p, zSym);
  614. }
  615. /*
  616. ** Close the dynamic library handle pHandle.
  617. */
  618. static void vlogDlClose(sqlite3_vfs *pVfs, void *pHandle){
  619. REALVFS(pVfs)->xDlClose(REALVFS(pVfs), pHandle);
  620. }
  621. /*
  622. ** Populate the buffer pointed to by zBufOut with nByte bytes of
  623. ** random data.
  624. */
  625. static int vlogRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
  626. return REALVFS(pVfs)->xRandomness(REALVFS(pVfs), nByte, zBufOut);
  627. }
  628. /*
  629. ** Sleep for nMicro microseconds. Return the number of microseconds
  630. ** actually slept.
  631. */
  632. static int vlogSleep(sqlite3_vfs *pVfs, int nMicro){
  633. return REALVFS(pVfs)->xSleep(REALVFS(pVfs), nMicro);
  634. }
  635. /*
  636. ** Return the current time as a Julian Day number in *pTimeOut.
  637. */
  638. static int vlogCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
  639. return REALVFS(pVfs)->xCurrentTime(REALVFS(pVfs), pTimeOut);
  640. }
  641. static int vlogGetLastError(sqlite3_vfs *pVfs, int a, char *b){
  642. return REALVFS(pVfs)->xGetLastError(REALVFS(pVfs), a, b);
  643. }
  644. static int vlogCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
  645. return REALVFS(pVfs)->xCurrentTimeInt64(REALVFS(pVfs), p);
  646. }
  647. /*
  648. ** Register debugvfs as the default VFS for this process.
  649. */
  650. int sqlite3_register_vfslog(const char *zArg){
  651. vlog_vfs.pVfs = sqlite3_vfs_find(0);
  652. vlog_vfs.base.szOsFile = sizeof(VLogFile) + vlog_vfs.pVfs->szOsFile;
  653. return sqlite3_vfs_register(&vlog_vfs.base, 1);
  654. }