test_osinst.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215
  1. /*
  2. ** 2008 April 10
  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 that
  14. ** adds instrumentation to all vfs and file methods. C and Tcl interfaces
  15. ** are provided to control the instrumentation.
  16. */
  17. /*
  18. ** This module contains code for a wrapper VFS that causes a log of
  19. ** most VFS calls to be written into a nominated file on disk. The log
  20. ** is stored in a compressed binary format to reduce the amount of IO
  21. ** overhead introduced into the application by logging.
  22. **
  23. ** All calls on sqlite3_file objects except xFileControl() are logged.
  24. ** Additionally, calls to the xAccess(), xOpen(), and xDelete()
  25. ** methods are logged. The other sqlite3_vfs object methods (xDlXXX,
  26. ** xRandomness, xSleep, xCurrentTime, xGetLastError and xCurrentTimeInt64)
  27. ** are not logged.
  28. **
  29. ** The binary log files are read using a virtual table implementation
  30. ** also contained in this file.
  31. **
  32. ** CREATING LOG FILES:
  33. **
  34. ** int sqlite3_vfslog_new(
  35. ** const char *zVfs, // Name of new VFS
  36. ** const char *zParentVfs, // Name of parent VFS (or NULL)
  37. ** const char *zLog // Name of log file to write to
  38. ** );
  39. **
  40. ** int sqlite3_vfslog_finalize(const char *zVfs);
  41. **
  42. ** ANNOTATING LOG FILES:
  43. **
  44. ** To write an arbitrary message into a log file:
  45. **
  46. ** int sqlite3_vfslog_annotate(const char *zVfs, const char *zMsg);
  47. **
  48. ** READING LOG FILES:
  49. **
  50. ** Log files are read using the "vfslog" virtual table implementation
  51. ** in this file. To register the virtual table with SQLite, use:
  52. **
  53. ** int sqlite3_vfslog_register(sqlite3 *db);
  54. **
  55. ** Then, if the log file is named "vfs.log", the following SQL command:
  56. **
  57. ** CREATE VIRTUAL TABLE v USING vfslog('vfs.log');
  58. **
  59. ** creates a virtual table with 6 columns, as follows:
  60. **
  61. ** CREATE TABLE v(
  62. ** event TEXT, // "xOpen", "xRead" etc.
  63. ** file TEXT, // Name of file this call applies to
  64. ** clicks INTEGER, // Time spent in call
  65. ** rc INTEGER, // Return value
  66. ** size INTEGER, // Bytes read or written
  67. ** offset INTEGER // File offset read or written
  68. ** );
  69. */
  70. #include "sqlite3.h"
  71. #include <string.h>
  72. #include <assert.h>
  73. /*
  74. ** Maximum pathname length supported by the vfslog backend.
  75. */
  76. #define INST_MAX_PATHNAME 512
  77. #define OS_ACCESS 1
  78. #define OS_CHECKRESERVEDLOCK 2
  79. #define OS_CLOSE 3
  80. #define OS_CURRENTTIME 4
  81. #define OS_DELETE 5
  82. #define OS_DEVCHAR 6
  83. #define OS_FILECONTROL 7
  84. #define OS_FILESIZE 8
  85. #define OS_FULLPATHNAME 9
  86. #define OS_LOCK 11
  87. #define OS_OPEN 12
  88. #define OS_RANDOMNESS 13
  89. #define OS_READ 14
  90. #define OS_SECTORSIZE 15
  91. #define OS_SLEEP 16
  92. #define OS_SYNC 17
  93. #define OS_TRUNCATE 18
  94. #define OS_UNLOCK 19
  95. #define OS_WRITE 20
  96. #define OS_SHMUNMAP 22
  97. #define OS_SHMMAP 23
  98. #define OS_SHMLOCK 25
  99. #define OS_SHMBARRIER 26
  100. #define OS_ANNOTATE 28
  101. #define OS_NUMEVENTS 29
  102. #define VFSLOG_BUFFERSIZE 8192
  103. typedef struct VfslogVfs VfslogVfs;
  104. typedef struct VfslogFile VfslogFile;
  105. struct VfslogVfs {
  106. sqlite3_vfs base; /* VFS methods */
  107. sqlite3_vfs *pVfs; /* Parent VFS */
  108. int iNextFileId; /* Next file id */
  109. sqlite3_file *pLog; /* Log file handle */
  110. sqlite3_int64 iOffset; /* Log file offset of start of write buffer */
  111. int nBuf; /* Number of valid bytes in aBuf[] */
  112. char aBuf[VFSLOG_BUFFERSIZE]; /* Write buffer */
  113. };
  114. struct VfslogFile {
  115. sqlite3_file base; /* IO methods */
  116. sqlite3_file *pReal; /* Underlying file handle */
  117. sqlite3_vfs *pVfslog; /* Associated VsflogVfs object */
  118. int iFileId; /* File id number */
  119. };
  120. #define REALVFS(p) (((VfslogVfs *)(p))->pVfs)
  121. /*
  122. ** Method declarations for vfslog_file.
  123. */
  124. static int vfslogClose(sqlite3_file*);
  125. static int vfslogRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
  126. static int vfslogWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
  127. static int vfslogTruncate(sqlite3_file*, sqlite3_int64 size);
  128. static int vfslogSync(sqlite3_file*, int flags);
  129. static int vfslogFileSize(sqlite3_file*, sqlite3_int64 *pSize);
  130. static int vfslogLock(sqlite3_file*, int);
  131. static int vfslogUnlock(sqlite3_file*, int);
  132. static int vfslogCheckReservedLock(sqlite3_file*, int *pResOut);
  133. static int vfslogFileControl(sqlite3_file*, int op, void *pArg);
  134. static int vfslogSectorSize(sqlite3_file*);
  135. static int vfslogDeviceCharacteristics(sqlite3_file*);
  136. static int vfslogShmLock(sqlite3_file *pFile, int ofst, int n, int flags);
  137. static int vfslogShmMap(sqlite3_file *pFile,int,int,int,volatile void **);
  138. static void vfslogShmBarrier(sqlite3_file*);
  139. static int vfslogShmUnmap(sqlite3_file *pFile, int deleteFlag);
  140. /*
  141. ** Method declarations for vfslog_vfs.
  142. */
  143. static int vfslogOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
  144. static int vfslogDelete(sqlite3_vfs*, const char *zName, int syncDir);
  145. static int vfslogAccess(sqlite3_vfs*, const char *zName, int flags, int *);
  146. static int vfslogFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
  147. static void *vfslogDlOpen(sqlite3_vfs*, const char *zFilename);
  148. static void vfslogDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
  149. static void (*vfslogDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
  150. static void vfslogDlClose(sqlite3_vfs*, void*);
  151. static int vfslogRandomness(sqlite3_vfs*, int nByte, char *zOut);
  152. static int vfslogSleep(sqlite3_vfs*, int microseconds);
  153. static int vfslogCurrentTime(sqlite3_vfs*, double*);
  154. static int vfslogGetLastError(sqlite3_vfs*, int, char *);
  155. static int vfslogCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
  156. static sqlite3_vfs vfslog_vfs = {
  157. 1, /* iVersion */
  158. sizeof(VfslogFile), /* szOsFile */
  159. INST_MAX_PATHNAME, /* mxPathname */
  160. 0, /* pNext */
  161. 0, /* zName */
  162. 0, /* pAppData */
  163. vfslogOpen, /* xOpen */
  164. vfslogDelete, /* xDelete */
  165. vfslogAccess, /* xAccess */
  166. vfslogFullPathname, /* xFullPathname */
  167. vfslogDlOpen, /* xDlOpen */
  168. vfslogDlError, /* xDlError */
  169. vfslogDlSym, /* xDlSym */
  170. vfslogDlClose, /* xDlClose */
  171. vfslogRandomness, /* xRandomness */
  172. vfslogSleep, /* xSleep */
  173. vfslogCurrentTime, /* xCurrentTime */
  174. vfslogGetLastError, /* xGetLastError */
  175. vfslogCurrentTimeInt64 /* xCurrentTime */
  176. };
  177. static sqlite3_io_methods vfslog_io_methods = {
  178. 2, /* iVersion */
  179. vfslogClose, /* xClose */
  180. vfslogRead, /* xRead */
  181. vfslogWrite, /* xWrite */
  182. vfslogTruncate, /* xTruncate */
  183. vfslogSync, /* xSync */
  184. vfslogFileSize, /* xFileSize */
  185. vfslogLock, /* xLock */
  186. vfslogUnlock, /* xUnlock */
  187. vfslogCheckReservedLock, /* xCheckReservedLock */
  188. vfslogFileControl, /* xFileControl */
  189. vfslogSectorSize, /* xSectorSize */
  190. vfslogDeviceCharacteristics, /* xDeviceCharacteristics */
  191. vfslogShmMap, /* xShmMap */
  192. vfslogShmLock, /* xShmLock */
  193. vfslogShmBarrier, /* xShmBarrier */
  194. vfslogShmUnmap /* xShmUnmap */
  195. };
  196. #if SQLITE_OS_UNIX && !defined(NO_GETTOD)
  197. #include <sys/time.h>
  198. static sqlite3_uint64 vfslog_time(){
  199. struct timeval sTime;
  200. gettimeofday(&sTime, 0);
  201. return sTime.tv_usec + (sqlite3_uint64)sTime.tv_sec * 1000000;
  202. }
  203. #elif SQLITE_OS_WIN
  204. #include <windows.h>
  205. #include <time.h>
  206. static sqlite3_uint64 vfslog_time(){
  207. FILETIME ft;
  208. sqlite3_uint64 u64time = 0;
  209. GetSystemTimeAsFileTime(&ft);
  210. u64time |= ft.dwHighDateTime;
  211. u64time <<= 32;
  212. u64time |= ft.dwLowDateTime;
  213. /* ft is 100-nanosecond intervals, we want microseconds */
  214. return u64time /(sqlite3_uint64)10;
  215. }
  216. #else
  217. static sqlite3_uint64 vfslog_time(){
  218. return 0;
  219. }
  220. #endif
  221. static void vfslog_call(sqlite3_vfs *, int, int, sqlite3_int64, int, int, int);
  222. static void vfslog_string(sqlite3_vfs *, const char *);
  223. /*
  224. ** Close an vfslog-file.
  225. */
  226. static int vfslogClose(sqlite3_file *pFile){
  227. sqlite3_uint64 t;
  228. int rc = SQLITE_OK;
  229. VfslogFile *p = (VfslogFile *)pFile;
  230. t = vfslog_time();
  231. if( p->pReal->pMethods ){
  232. rc = p->pReal->pMethods->xClose(p->pReal);
  233. }
  234. t = vfslog_time() - t;
  235. vfslog_call(p->pVfslog, OS_CLOSE, p->iFileId, t, rc, 0, 0);
  236. return rc;
  237. }
  238. /*
  239. ** Read data from an vfslog-file.
  240. */
  241. static int vfslogRead(
  242. sqlite3_file *pFile,
  243. void *zBuf,
  244. int iAmt,
  245. sqlite_int64 iOfst
  246. ){
  247. int rc;
  248. sqlite3_uint64 t;
  249. VfslogFile *p = (VfslogFile *)pFile;
  250. t = vfslog_time();
  251. rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst);
  252. t = vfslog_time() - t;
  253. vfslog_call(p->pVfslog, OS_READ, p->iFileId, t, rc, iAmt, (int)iOfst);
  254. return rc;
  255. }
  256. /*
  257. ** Write data to an vfslog-file.
  258. */
  259. static int vfslogWrite(
  260. sqlite3_file *pFile,
  261. const void *z,
  262. int iAmt,
  263. sqlite_int64 iOfst
  264. ){
  265. int rc;
  266. sqlite3_uint64 t;
  267. VfslogFile *p = (VfslogFile *)pFile;
  268. t = vfslog_time();
  269. rc = p->pReal->pMethods->xWrite(p->pReal, z, iAmt, iOfst);
  270. t = vfslog_time() - t;
  271. vfslog_call(p->pVfslog, OS_WRITE, p->iFileId, t, rc, iAmt, (int)iOfst);
  272. return rc;
  273. }
  274. /*
  275. ** Truncate an vfslog-file.
  276. */
  277. static int vfslogTruncate(sqlite3_file *pFile, sqlite_int64 size){
  278. int rc;
  279. sqlite3_uint64 t;
  280. VfslogFile *p = (VfslogFile *)pFile;
  281. t = vfslog_time();
  282. rc = p->pReal->pMethods->xTruncate(p->pReal, size);
  283. t = vfslog_time() - t;
  284. vfslog_call(p->pVfslog, OS_TRUNCATE, p->iFileId, t, rc, 0, (int)size);
  285. return rc;
  286. }
  287. /*
  288. ** Sync an vfslog-file.
  289. */
  290. static int vfslogSync(sqlite3_file *pFile, int flags){
  291. int rc;
  292. sqlite3_uint64 t;
  293. VfslogFile *p = (VfslogFile *)pFile;
  294. t = vfslog_time();
  295. rc = p->pReal->pMethods->xSync(p->pReal, flags);
  296. t = vfslog_time() - t;
  297. vfslog_call(p->pVfslog, OS_SYNC, p->iFileId, t, rc, flags, 0);
  298. return rc;
  299. }
  300. /*
  301. ** Return the current file-size of an vfslog-file.
  302. */
  303. static int vfslogFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
  304. int rc;
  305. sqlite3_uint64 t;
  306. VfslogFile *p = (VfslogFile *)pFile;
  307. t = vfslog_time();
  308. rc = p->pReal->pMethods->xFileSize(p->pReal, pSize);
  309. t = vfslog_time() - t;
  310. vfslog_call(p->pVfslog, OS_FILESIZE, p->iFileId, t, rc, 0, (int)*pSize);
  311. return rc;
  312. }
  313. /*
  314. ** Lock an vfslog-file.
  315. */
  316. static int vfslogLock(sqlite3_file *pFile, int eLock){
  317. int rc;
  318. sqlite3_uint64 t;
  319. VfslogFile *p = (VfslogFile *)pFile;
  320. t = vfslog_time();
  321. rc = p->pReal->pMethods->xLock(p->pReal, eLock);
  322. t = vfslog_time() - t;
  323. vfslog_call(p->pVfslog, OS_LOCK, p->iFileId, t, rc, eLock, 0);
  324. return rc;
  325. }
  326. /*
  327. ** Unlock an vfslog-file.
  328. */
  329. static int vfslogUnlock(sqlite3_file *pFile, int eLock){
  330. int rc;
  331. sqlite3_uint64 t;
  332. VfslogFile *p = (VfslogFile *)pFile;
  333. t = vfslog_time();
  334. rc = p->pReal->pMethods->xUnlock(p->pReal, eLock);
  335. t = vfslog_time() - t;
  336. vfslog_call(p->pVfslog, OS_UNLOCK, p->iFileId, t, rc, eLock, 0);
  337. return rc;
  338. }
  339. /*
  340. ** Check if another file-handle holds a RESERVED lock on an vfslog-file.
  341. */
  342. static int vfslogCheckReservedLock(sqlite3_file *pFile, int *pResOut){
  343. int rc;
  344. sqlite3_uint64 t;
  345. VfslogFile *p = (VfslogFile *)pFile;
  346. t = vfslog_time();
  347. rc = p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut);
  348. t = vfslog_time() - t;
  349. vfslog_call(p->pVfslog, OS_CHECKRESERVEDLOCK, p->iFileId, t, rc, *pResOut, 0);
  350. return rc;
  351. }
  352. /*
  353. ** File control method. For custom operations on an vfslog-file.
  354. */
  355. static int vfslogFileControl(sqlite3_file *pFile, int op, void *pArg){
  356. VfslogFile *p = (VfslogFile *)pFile;
  357. int rc = p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
  358. if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){
  359. *(char**)pArg = sqlite3_mprintf("vfslog/%z", *(char**)pArg);
  360. }
  361. return rc;
  362. }
  363. /*
  364. ** Return the sector-size in bytes for an vfslog-file.
  365. */
  366. static int vfslogSectorSize(sqlite3_file *pFile){
  367. int rc;
  368. sqlite3_uint64 t;
  369. VfslogFile *p = (VfslogFile *)pFile;
  370. t = vfslog_time();
  371. rc = p->pReal->pMethods->xSectorSize(p->pReal);
  372. t = vfslog_time() - t;
  373. vfslog_call(p->pVfslog, OS_SECTORSIZE, p->iFileId, t, rc, 0, 0);
  374. return rc;
  375. }
  376. /*
  377. ** Return the device characteristic flags supported by an vfslog-file.
  378. */
  379. static int vfslogDeviceCharacteristics(sqlite3_file *pFile){
  380. int rc;
  381. sqlite3_uint64 t;
  382. VfslogFile *p = (VfslogFile *)pFile;
  383. t = vfslog_time();
  384. rc = p->pReal->pMethods->xDeviceCharacteristics(p->pReal);
  385. t = vfslog_time() - t;
  386. vfslog_call(p->pVfslog, OS_DEVCHAR, p->iFileId, t, rc, 0, 0);
  387. return rc;
  388. }
  389. static int vfslogShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
  390. int rc;
  391. sqlite3_uint64 t;
  392. VfslogFile *p = (VfslogFile *)pFile;
  393. t = vfslog_time();
  394. rc = p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags);
  395. t = vfslog_time() - t;
  396. vfslog_call(p->pVfslog, OS_SHMLOCK, p->iFileId, t, rc, 0, 0);
  397. return rc;
  398. }
  399. static int vfslogShmMap(
  400. sqlite3_file *pFile,
  401. int iRegion,
  402. int szRegion,
  403. int isWrite,
  404. volatile void **pp
  405. ){
  406. int rc;
  407. sqlite3_uint64 t;
  408. VfslogFile *p = (VfslogFile *)pFile;
  409. t = vfslog_time();
  410. rc = p->pReal->pMethods->xShmMap(p->pReal, iRegion, szRegion, isWrite, pp);
  411. t = vfslog_time() - t;
  412. vfslog_call(p->pVfslog, OS_SHMMAP, p->iFileId, t, rc, 0, 0);
  413. return rc;
  414. }
  415. static void vfslogShmBarrier(sqlite3_file *pFile){
  416. sqlite3_uint64 t;
  417. VfslogFile *p = (VfslogFile *)pFile;
  418. t = vfslog_time();
  419. p->pReal->pMethods->xShmBarrier(p->pReal);
  420. t = vfslog_time() - t;
  421. vfslog_call(p->pVfslog, OS_SHMBARRIER, p->iFileId, t, SQLITE_OK, 0, 0);
  422. }
  423. static int vfslogShmUnmap(sqlite3_file *pFile, int deleteFlag){
  424. int rc;
  425. sqlite3_uint64 t;
  426. VfslogFile *p = (VfslogFile *)pFile;
  427. t = vfslog_time();
  428. rc = p->pReal->pMethods->xShmUnmap(p->pReal, deleteFlag);
  429. t = vfslog_time() - t;
  430. vfslog_call(p->pVfslog, OS_SHMUNMAP, p->iFileId, t, rc, 0, 0);
  431. return rc;
  432. }
  433. /*
  434. ** Open an vfslog file handle.
  435. */
  436. static int vfslogOpen(
  437. sqlite3_vfs *pVfs,
  438. const char *zName,
  439. sqlite3_file *pFile,
  440. int flags,
  441. int *pOutFlags
  442. ){
  443. int rc;
  444. sqlite3_uint64 t;
  445. VfslogFile *p = (VfslogFile *)pFile;
  446. VfslogVfs *pLog = (VfslogVfs *)pVfs;
  447. pFile->pMethods = &vfslog_io_methods;
  448. p->pReal = (sqlite3_file *)&p[1];
  449. p->pVfslog = pVfs;
  450. p->iFileId = ++pLog->iNextFileId;
  451. t = vfslog_time();
  452. rc = REALVFS(pVfs)->xOpen(REALVFS(pVfs), zName, p->pReal, flags, pOutFlags);
  453. t = vfslog_time() - t;
  454. vfslog_call(pVfs, OS_OPEN, p->iFileId, t, rc, 0, 0);
  455. vfslog_string(pVfs, zName);
  456. return rc;
  457. }
  458. /*
  459. ** Delete the file located at zPath. If the dirSync argument is true,
  460. ** ensure the file-system modifications are synced to disk before
  461. ** returning.
  462. */
  463. static int vfslogDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
  464. int rc;
  465. sqlite3_uint64 t;
  466. t = vfslog_time();
  467. rc = REALVFS(pVfs)->xDelete(REALVFS(pVfs), zPath, dirSync);
  468. t = vfslog_time() - t;
  469. vfslog_call(pVfs, OS_DELETE, 0, t, rc, dirSync, 0);
  470. vfslog_string(pVfs, zPath);
  471. return rc;
  472. }
  473. /*
  474. ** Test for access permissions. Return true if the requested permission
  475. ** is available, or false otherwise.
  476. */
  477. static int vfslogAccess(
  478. sqlite3_vfs *pVfs,
  479. const char *zPath,
  480. int flags,
  481. int *pResOut
  482. ){
  483. int rc;
  484. sqlite3_uint64 t;
  485. t = vfslog_time();
  486. rc = REALVFS(pVfs)->xAccess(REALVFS(pVfs), zPath, flags, pResOut);
  487. t = vfslog_time() - t;
  488. vfslog_call(pVfs, OS_ACCESS, 0, t, rc, flags, *pResOut);
  489. vfslog_string(pVfs, zPath);
  490. return rc;
  491. }
  492. /*
  493. ** Populate buffer zOut with the full canonical pathname corresponding
  494. ** to the pathname in zPath. zOut is guaranteed to point to a buffer
  495. ** of at least (INST_MAX_PATHNAME+1) bytes.
  496. */
  497. static int vfslogFullPathname(
  498. sqlite3_vfs *pVfs,
  499. const char *zPath,
  500. int nOut,
  501. char *zOut
  502. ){
  503. return REALVFS(pVfs)->xFullPathname(REALVFS(pVfs), zPath, nOut, zOut);
  504. }
  505. /*
  506. ** Open the dynamic library located at zPath and return a handle.
  507. */
  508. static void *vfslogDlOpen(sqlite3_vfs *pVfs, const char *zPath){
  509. return REALVFS(pVfs)->xDlOpen(REALVFS(pVfs), zPath);
  510. }
  511. /*
  512. ** Populate the buffer zErrMsg (size nByte bytes) with a human readable
  513. ** utf-8 string describing the most recent error encountered associated
  514. ** with dynamic libraries.
  515. */
  516. static void vfslogDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
  517. REALVFS(pVfs)->xDlError(REALVFS(pVfs), nByte, zErrMsg);
  518. }
  519. /*
  520. ** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
  521. */
  522. static void (*vfslogDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
  523. return REALVFS(pVfs)->xDlSym(REALVFS(pVfs), p, zSym);
  524. }
  525. /*
  526. ** Close the dynamic library handle pHandle.
  527. */
  528. static void vfslogDlClose(sqlite3_vfs *pVfs, void *pHandle){
  529. REALVFS(pVfs)->xDlClose(REALVFS(pVfs), pHandle);
  530. }
  531. /*
  532. ** Populate the buffer pointed to by zBufOut with nByte bytes of
  533. ** random data.
  534. */
  535. static int vfslogRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
  536. return REALVFS(pVfs)->xRandomness(REALVFS(pVfs), nByte, zBufOut);
  537. }
  538. /*
  539. ** Sleep for nMicro microseconds. Return the number of microseconds
  540. ** actually slept.
  541. */
  542. static int vfslogSleep(sqlite3_vfs *pVfs, int nMicro){
  543. return REALVFS(pVfs)->xSleep(REALVFS(pVfs), nMicro);
  544. }
  545. /*
  546. ** Return the current time as a Julian Day number in *pTimeOut.
  547. */
  548. static int vfslogCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
  549. return REALVFS(pVfs)->xCurrentTime(REALVFS(pVfs), pTimeOut);
  550. }
  551. static int vfslogGetLastError(sqlite3_vfs *pVfs, int a, char *b){
  552. return REALVFS(pVfs)->xGetLastError(REALVFS(pVfs), a, b);
  553. }
  554. static int vfslogCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
  555. return REALVFS(pVfs)->xCurrentTimeInt64(REALVFS(pVfs), p);
  556. }
  557. static void vfslog_flush(VfslogVfs *p){
  558. #ifdef SQLITE_TEST
  559. extern int sqlite3_io_error_pending;
  560. extern int sqlite3_io_error_persist;
  561. extern int sqlite3_diskfull_pending;
  562. int pending = sqlite3_io_error_pending;
  563. int persist = sqlite3_io_error_persist;
  564. int diskfull = sqlite3_diskfull_pending;
  565. sqlite3_io_error_pending = 0;
  566. sqlite3_io_error_persist = 0;
  567. sqlite3_diskfull_pending = 0;
  568. #endif
  569. if( p->nBuf ){
  570. p->pLog->pMethods->xWrite(p->pLog, p->aBuf, p->nBuf, p->iOffset);
  571. p->iOffset += p->nBuf;
  572. p->nBuf = 0;
  573. }
  574. #ifdef SQLITE_TEST
  575. sqlite3_io_error_pending = pending;
  576. sqlite3_io_error_persist = persist;
  577. sqlite3_diskfull_pending = diskfull;
  578. #endif
  579. }
  580. static void put32bits(unsigned char *p, unsigned int v){
  581. p[0] = v>>24;
  582. p[1] = v>>16;
  583. p[2] = v>>8;
  584. p[3] = v;
  585. }
  586. static void vfslog_call(
  587. sqlite3_vfs *pVfs,
  588. int eEvent,
  589. int iFileid,
  590. sqlite3_int64 nClick,
  591. int return_code,
  592. int size,
  593. int offset
  594. ){
  595. VfslogVfs *p = (VfslogVfs *)pVfs;
  596. unsigned char *zRec;
  597. if( (24+p->nBuf)>sizeof(p->aBuf) ){
  598. vfslog_flush(p);
  599. }
  600. zRec = (unsigned char *)&p->aBuf[p->nBuf];
  601. put32bits(&zRec[0], eEvent);
  602. put32bits(&zRec[4], iFileid);
  603. put32bits(&zRec[8], (unsigned int)(nClick&0xffff));
  604. put32bits(&zRec[12], return_code);
  605. put32bits(&zRec[16], size);
  606. put32bits(&zRec[20], offset);
  607. p->nBuf += 24;
  608. }
  609. static void vfslog_string(sqlite3_vfs *pVfs, const char *zStr){
  610. VfslogVfs *p = (VfslogVfs *)pVfs;
  611. unsigned char *zRec;
  612. int nStr = zStr ? (int)strlen(zStr) : 0;
  613. if( (4+nStr+p->nBuf)>sizeof(p->aBuf) ){
  614. vfslog_flush(p);
  615. }
  616. zRec = (unsigned char *)&p->aBuf[p->nBuf];
  617. put32bits(&zRec[0], nStr);
  618. if( zStr ){
  619. memcpy(&zRec[4], zStr, nStr);
  620. }
  621. p->nBuf += (4 + nStr);
  622. }
  623. static void vfslog_finalize(VfslogVfs *p){
  624. if( p->pLog->pMethods ){
  625. vfslog_flush(p);
  626. p->pLog->pMethods->xClose(p->pLog);
  627. }
  628. sqlite3_free(p);
  629. }
  630. int sqlite3_vfslog_finalize(const char *zVfs){
  631. sqlite3_vfs *pVfs;
  632. pVfs = sqlite3_vfs_find(zVfs);
  633. if( !pVfs || pVfs->xOpen!=vfslogOpen ){
  634. return SQLITE_ERROR;
  635. }
  636. sqlite3_vfs_unregister(pVfs);
  637. vfslog_finalize((VfslogVfs *)pVfs);
  638. return SQLITE_OK;
  639. }
  640. int sqlite3_vfslog_new(
  641. const char *zVfs, /* New VFS name */
  642. const char *zParentVfs, /* Parent VFS name (or NULL) */
  643. const char *zLog /* Log file name */
  644. ){
  645. VfslogVfs *p;
  646. sqlite3_vfs *pParent;
  647. int nByte;
  648. int flags;
  649. int rc;
  650. char *zFile;
  651. int nVfs;
  652. pParent = sqlite3_vfs_find(zParentVfs);
  653. if( !pParent ){
  654. return SQLITE_ERROR;
  655. }
  656. nVfs = (int)strlen(zVfs);
  657. nByte = sizeof(VfslogVfs) + pParent->szOsFile + nVfs+1+pParent->mxPathname+1;
  658. p = (VfslogVfs *)sqlite3_malloc(nByte);
  659. memset(p, 0, nByte);
  660. p->pVfs = pParent;
  661. p->pLog = (sqlite3_file *)&p[1];
  662. memcpy(&p->base, &vfslog_vfs, sizeof(sqlite3_vfs));
  663. p->base.zName = &((char *)p->pLog)[pParent->szOsFile];
  664. p->base.szOsFile += pParent->szOsFile;
  665. memcpy((char *)p->base.zName, zVfs, nVfs);
  666. zFile = (char *)&p->base.zName[nVfs+1];
  667. pParent->xFullPathname(pParent, zLog, pParent->mxPathname, zFile);
  668. flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MASTER_JOURNAL;
  669. pParent->xDelete(pParent, zFile, 0);
  670. rc = pParent->xOpen(pParent, zFile, p->pLog, flags, &flags);
  671. if( rc==SQLITE_OK ){
  672. memcpy(p->aBuf, "sqlite_ostrace1.....", 20);
  673. p->iOffset = 0;
  674. p->nBuf = 20;
  675. rc = sqlite3_vfs_register((sqlite3_vfs *)p, 1);
  676. }
  677. if( rc ){
  678. vfslog_finalize(p);
  679. }
  680. return rc;
  681. }
  682. int sqlite3_vfslog_annotate(const char *zVfs, const char *zMsg){
  683. sqlite3_vfs *pVfs;
  684. pVfs = sqlite3_vfs_find(zVfs);
  685. if( !pVfs || pVfs->xOpen!=vfslogOpen ){
  686. return SQLITE_ERROR;
  687. }
  688. vfslog_call(pVfs, OS_ANNOTATE, 0, 0, 0, 0, 0);
  689. vfslog_string(pVfs, zMsg);
  690. return SQLITE_OK;
  691. }
  692. static const char *vfslog_eventname(int eEvent){
  693. const char *zEvent = 0;
  694. switch( eEvent ){
  695. case OS_CLOSE: zEvent = "xClose"; break;
  696. case OS_READ: zEvent = "xRead"; break;
  697. case OS_WRITE: zEvent = "xWrite"; break;
  698. case OS_TRUNCATE: zEvent = "xTruncate"; break;
  699. case OS_SYNC: zEvent = "xSync"; break;
  700. case OS_FILESIZE: zEvent = "xFilesize"; break;
  701. case OS_LOCK: zEvent = "xLock"; break;
  702. case OS_UNLOCK: zEvent = "xUnlock"; break;
  703. case OS_CHECKRESERVEDLOCK: zEvent = "xCheckResLock"; break;
  704. case OS_FILECONTROL: zEvent = "xFileControl"; break;
  705. case OS_SECTORSIZE: zEvent = "xSectorSize"; break;
  706. case OS_DEVCHAR: zEvent = "xDeviceChar"; break;
  707. case OS_OPEN: zEvent = "xOpen"; break;
  708. case OS_DELETE: zEvent = "xDelete"; break;
  709. case OS_ACCESS: zEvent = "xAccess"; break;
  710. case OS_FULLPATHNAME: zEvent = "xFullPathname"; break;
  711. case OS_RANDOMNESS: zEvent = "xRandomness"; break;
  712. case OS_SLEEP: zEvent = "xSleep"; break;
  713. case OS_CURRENTTIME: zEvent = "xCurrentTime"; break;
  714. case OS_SHMUNMAP: zEvent = "xShmUnmap"; break;
  715. case OS_SHMLOCK: zEvent = "xShmLock"; break;
  716. case OS_SHMBARRIER: zEvent = "xShmBarrier"; break;
  717. case OS_SHMMAP: zEvent = "xShmMap"; break;
  718. case OS_ANNOTATE: zEvent = "annotation"; break;
  719. }
  720. return zEvent;
  721. }
  722. typedef struct VfslogVtab VfslogVtab;
  723. typedef struct VfslogCsr VfslogCsr;
  724. /*
  725. ** Virtual table type for the vfslog reader module.
  726. */
  727. struct VfslogVtab {
  728. sqlite3_vtab base; /* Base class */
  729. sqlite3_file *pFd; /* File descriptor open on vfslog file */
  730. sqlite3_int64 nByte; /* Size of file in bytes */
  731. char *zFile; /* File name for pFd */
  732. };
  733. /*
  734. ** Virtual table cursor type for the vfslog reader module.
  735. */
  736. struct VfslogCsr {
  737. sqlite3_vtab_cursor base; /* Base class */
  738. sqlite3_int64 iRowid; /* Current rowid. */
  739. sqlite3_int64 iOffset; /* Offset of next record in file */
  740. char *zTransient; /* Transient 'file' string */
  741. int nFile; /* Size of array azFile[] */
  742. char **azFile; /* File strings */
  743. unsigned char aBuf[1024]; /* Current vfs log entry (read from file) */
  744. };
  745. static unsigned int get32bits(unsigned char *p){
  746. return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3];
  747. }
  748. /*
  749. ** The argument must point to a buffer containing a nul-terminated string.
  750. ** If the string begins with an SQL quote character it is overwritten by
  751. ** the dequoted version. Otherwise the buffer is left unmodified.
  752. */
  753. static void dequote(char *z){
  754. char quote; /* Quote character (if any ) */
  755. quote = z[0];
  756. if( quote=='[' || quote=='\'' || quote=='"' || quote=='`' ){
  757. int iIn = 1; /* Index of next byte to read from input */
  758. int iOut = 0; /* Index of next byte to write to output */
  759. if( quote=='[' ) quote = ']';
  760. while( z[iIn] ){
  761. if( z[iIn]==quote ){
  762. if( z[iIn+1]!=quote ) break;
  763. z[iOut++] = quote;
  764. iIn += 2;
  765. }else{
  766. z[iOut++] = z[iIn++];
  767. }
  768. }
  769. z[iOut] = '\0';
  770. }
  771. }
  772. #ifndef SQLITE_OMIT_VIRTUALTABLE
  773. /*
  774. ** Connect to or create a vfslog virtual table.
  775. */
  776. static int vlogConnect(
  777. sqlite3 *db,
  778. void *pAux,
  779. int argc, const char *const*argv,
  780. sqlite3_vtab **ppVtab,
  781. char **pzErr
  782. ){
  783. sqlite3_vfs *pVfs; /* VFS used to read log file */
  784. int flags; /* flags passed to pVfs->xOpen() */
  785. VfslogVtab *p;
  786. int rc;
  787. int nByte;
  788. char *zFile;
  789. *ppVtab = 0;
  790. pVfs = sqlite3_vfs_find(0);
  791. nByte = sizeof(VfslogVtab) + pVfs->szOsFile + pVfs->mxPathname;
  792. p = sqlite3_malloc(nByte);
  793. if( p==0 ) return SQLITE_NOMEM;
  794. memset(p, 0, nByte);
  795. p->pFd = (sqlite3_file *)&p[1];
  796. p->zFile = &((char *)p->pFd)[pVfs->szOsFile];
  797. zFile = sqlite3_mprintf("%s", argv[3]);
  798. if( !zFile ){
  799. sqlite3_free(p);
  800. return SQLITE_NOMEM;
  801. }
  802. dequote(zFile);
  803. pVfs->xFullPathname(pVfs, zFile, pVfs->mxPathname, p->zFile);
  804. sqlite3_free(zFile);
  805. flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MASTER_JOURNAL;
  806. rc = pVfs->xOpen(pVfs, p->zFile, p->pFd, flags, &flags);
  807. if( rc==SQLITE_OK ){
  808. p->pFd->pMethods->xFileSize(p->pFd, &p->nByte);
  809. sqlite3_declare_vtab(db,
  810. "CREATE TABLE xxx(event, file, click, rc, size, offset)"
  811. );
  812. *ppVtab = &p->base;
  813. }else{
  814. sqlite3_free(p);
  815. }
  816. return rc;
  817. }
  818. /*
  819. ** There is no "best-index". This virtual table always does a linear
  820. ** scan of the binary VFS log file.
  821. */
  822. static int vlogBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
  823. pIdxInfo->estimatedCost = 10.0;
  824. return SQLITE_OK;
  825. }
  826. /*
  827. ** Disconnect from or destroy a vfslog virtual table.
  828. */
  829. static int vlogDisconnect(sqlite3_vtab *pVtab){
  830. VfslogVtab *p = (VfslogVtab *)pVtab;
  831. if( p->pFd->pMethods ){
  832. p->pFd->pMethods->xClose(p->pFd);
  833. p->pFd->pMethods = 0;
  834. }
  835. sqlite3_free(p);
  836. return SQLITE_OK;
  837. }
  838. /*
  839. ** Open a new vfslog cursor.
  840. */
  841. static int vlogOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
  842. VfslogCsr *pCsr; /* Newly allocated cursor object */
  843. pCsr = sqlite3_malloc(sizeof(VfslogCsr));
  844. if( !pCsr ) return SQLITE_NOMEM;
  845. memset(pCsr, 0, sizeof(VfslogCsr));
  846. *ppCursor = &pCsr->base;
  847. return SQLITE_OK;
  848. }
  849. /*
  850. ** Close a vfslog cursor.
  851. */
  852. static int vlogClose(sqlite3_vtab_cursor *pCursor){
  853. VfslogCsr *p = (VfslogCsr *)pCursor;
  854. int i;
  855. for(i=0; i<p->nFile; i++){
  856. sqlite3_free(p->azFile[i]);
  857. }
  858. sqlite3_free(p->azFile);
  859. sqlite3_free(p->zTransient);
  860. sqlite3_free(p);
  861. return SQLITE_OK;
  862. }
  863. /*
  864. ** Move a vfslog cursor to the next entry in the file.
  865. */
  866. static int vlogNext(sqlite3_vtab_cursor *pCursor){
  867. VfslogCsr *pCsr = (VfslogCsr *)pCursor;
  868. VfslogVtab *p = (VfslogVtab *)pCursor->pVtab;
  869. int rc = SQLITE_OK;
  870. int nRead;
  871. sqlite3_free(pCsr->zTransient);
  872. pCsr->zTransient = 0;
  873. nRead = 24;
  874. if( pCsr->iOffset+nRead<=p->nByte ){
  875. int eEvent;
  876. rc = p->pFd->pMethods->xRead(p->pFd, pCsr->aBuf, nRead, pCsr->iOffset);
  877. eEvent = get32bits(pCsr->aBuf);
  878. if( (rc==SQLITE_OK)
  879. && (eEvent==OS_OPEN || eEvent==OS_DELETE || eEvent==OS_ACCESS)
  880. ){
  881. char buf[4];
  882. rc = p->pFd->pMethods->xRead(p->pFd, buf, 4, pCsr->iOffset+nRead);
  883. nRead += 4;
  884. if( rc==SQLITE_OK ){
  885. int nStr = get32bits((unsigned char *)buf);
  886. char *zStr = sqlite3_malloc(nStr+1);
  887. rc = p->pFd->pMethods->xRead(p->pFd, zStr, nStr, pCsr->iOffset+nRead);
  888. zStr[nStr] = '\0';
  889. nRead += nStr;
  890. if( eEvent==OS_OPEN ){
  891. int iFileid = get32bits(&pCsr->aBuf[4]);
  892. if( iFileid>=pCsr->nFile ){
  893. int nNew = sizeof(pCsr->azFile[0])*(iFileid+1);
  894. pCsr->azFile = (char **)sqlite3_realloc(pCsr->azFile, nNew);
  895. nNew -= sizeof(pCsr->azFile[0])*pCsr->nFile;
  896. memset(&pCsr->azFile[pCsr->nFile], 0, nNew);
  897. pCsr->nFile = iFileid+1;
  898. }
  899. sqlite3_free(pCsr->azFile[iFileid]);
  900. pCsr->azFile[iFileid] = zStr;
  901. }else{
  902. pCsr->zTransient = zStr;
  903. }
  904. }
  905. }
  906. }
  907. pCsr->iRowid += 1;
  908. pCsr->iOffset += nRead;
  909. return rc;
  910. }
  911. static int vlogEof(sqlite3_vtab_cursor *pCursor){
  912. VfslogCsr *pCsr = (VfslogCsr *)pCursor;
  913. VfslogVtab *p = (VfslogVtab *)pCursor->pVtab;
  914. return (pCsr->iOffset>=p->nByte);
  915. }
  916. static int vlogFilter(
  917. sqlite3_vtab_cursor *pCursor,
  918. int idxNum, const char *idxStr,
  919. int argc, sqlite3_value **argv
  920. ){
  921. VfslogCsr *pCsr = (VfslogCsr *)pCursor;
  922. pCsr->iRowid = 0;
  923. pCsr->iOffset = 20;
  924. return vlogNext(pCursor);
  925. }
  926. static int vlogColumn(
  927. sqlite3_vtab_cursor *pCursor,
  928. sqlite3_context *ctx,
  929. int i
  930. ){
  931. unsigned int val;
  932. VfslogCsr *pCsr = (VfslogCsr *)pCursor;
  933. assert( i<7 );
  934. val = get32bits(&pCsr->aBuf[4*i]);
  935. switch( i ){
  936. case 0: {
  937. sqlite3_result_text(ctx, vfslog_eventname(val), -1, SQLITE_STATIC);
  938. break;
  939. }
  940. case 1: {
  941. char *zStr = pCsr->zTransient;
  942. if( val!=0 && val<(unsigned)pCsr->nFile ){
  943. zStr = pCsr->azFile[val];
  944. }
  945. sqlite3_result_text(ctx, zStr, -1, SQLITE_TRANSIENT);
  946. break;
  947. }
  948. default:
  949. sqlite3_result_int(ctx, val);
  950. break;
  951. }
  952. return SQLITE_OK;
  953. }
  954. static int vlogRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
  955. VfslogCsr *pCsr = (VfslogCsr *)pCursor;
  956. *pRowid = pCsr->iRowid;
  957. return SQLITE_OK;
  958. }
  959. int sqlite3_vfslog_register(sqlite3 *db){
  960. static sqlite3_module vfslog_module = {
  961. 0, /* iVersion */
  962. vlogConnect, /* xCreate */
  963. vlogConnect, /* xConnect */
  964. vlogBestIndex, /* xBestIndex */
  965. vlogDisconnect, /* xDisconnect */
  966. vlogDisconnect, /* xDestroy */
  967. vlogOpen, /* xOpen - open a cursor */
  968. vlogClose, /* xClose - close a cursor */
  969. vlogFilter, /* xFilter - configure scan constraints */
  970. vlogNext, /* xNext - advance a cursor */
  971. vlogEof, /* xEof - check for end of scan */
  972. vlogColumn, /* xColumn - read data */
  973. vlogRowid, /* xRowid - read data */
  974. 0, /* xUpdate */
  975. 0, /* xBegin */
  976. 0, /* xSync */
  977. 0, /* xCommit */
  978. 0, /* xRollback */
  979. 0, /* xFindMethod */
  980. 0, /* xRename */
  981. };
  982. sqlite3_create_module(db, "vfslog", &vfslog_module, 0);
  983. return SQLITE_OK;
  984. }
  985. #endif /* SQLITE_OMIT_VIRTUALTABLE */
  986. /**************************************************************************
  987. ***************************************************************************
  988. ** Tcl interface starts here.
  989. */
  990. #if defined(SQLITE_TEST) || defined(TCLSH)
  991. #include <tcl.h>
  992. static int test_vfslog(
  993. void *clientData,
  994. Tcl_Interp *interp,
  995. int objc,
  996. Tcl_Obj *CONST objv[]
  997. ){
  998. struct SqliteDb { sqlite3 *db; };
  999. sqlite3 *db;
  1000. Tcl_CmdInfo cmdInfo;
  1001. int rc = SQLITE_ERROR;
  1002. static const char *strs[] = { "annotate", "finalize", "new", "register", 0 };
  1003. enum VL_enum { VL_ANNOTATE, VL_FINALIZE, VL_NEW, VL_REGISTER };
  1004. int iSub;
  1005. if( objc<2 ){
  1006. Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND ...");
  1007. return TCL_ERROR;
  1008. }
  1009. if( Tcl_GetIndexFromObj(interp, objv[1], strs, "sub-command", 0, &iSub) ){
  1010. return TCL_ERROR;
  1011. }
  1012. switch( (enum VL_enum)iSub ){
  1013. case VL_ANNOTATE: {
  1014. int rc;
  1015. char *zVfs;
  1016. char *zMsg;
  1017. if( objc!=4 ){
  1018. Tcl_WrongNumArgs(interp, 3, objv, "VFS");
  1019. return TCL_ERROR;
  1020. }
  1021. zVfs = Tcl_GetString(objv[2]);
  1022. zMsg = Tcl_GetString(objv[3]);
  1023. rc = sqlite3_vfslog_annotate(zVfs, zMsg);
  1024. if( rc!=SQLITE_OK ){
  1025. Tcl_AppendResult(interp, "failed", 0);
  1026. return TCL_ERROR;
  1027. }
  1028. break;
  1029. }
  1030. case VL_FINALIZE: {
  1031. int rc;
  1032. char *zVfs;
  1033. if( objc!=3 ){
  1034. Tcl_WrongNumArgs(interp, 2, objv, "VFS");
  1035. return TCL_ERROR;
  1036. }
  1037. zVfs = Tcl_GetString(objv[2]);
  1038. rc = sqlite3_vfslog_finalize(zVfs);
  1039. if( rc!=SQLITE_OK ){
  1040. Tcl_AppendResult(interp, "failed", 0);
  1041. return TCL_ERROR;
  1042. }
  1043. break;
  1044. };
  1045. case VL_NEW: {
  1046. int rc;
  1047. char *zVfs;
  1048. char *zParent;
  1049. char *zLog;
  1050. if( objc!=5 ){
  1051. Tcl_WrongNumArgs(interp, 2, objv, "VFS PARENT LOGFILE");
  1052. return TCL_ERROR;
  1053. }
  1054. zVfs = Tcl_GetString(objv[2]);
  1055. zParent = Tcl_GetString(objv[3]);
  1056. zLog = Tcl_GetString(objv[4]);
  1057. if( *zParent=='\0' ) zParent = 0;
  1058. rc = sqlite3_vfslog_new(zVfs, zParent, zLog);
  1059. if( rc!=SQLITE_OK ){
  1060. Tcl_AppendResult(interp, "failed", 0);
  1061. return TCL_ERROR;
  1062. }
  1063. break;
  1064. };
  1065. case VL_REGISTER: {
  1066. char *zDb;
  1067. if( objc!=3 ){
  1068. Tcl_WrongNumArgs(interp, 2, objv, "DB");
  1069. return TCL_ERROR;
  1070. }
  1071. #ifdef SQLITE_OMIT_VIRTUALTABLE
  1072. Tcl_AppendResult(interp, "vfslog not available because of "
  1073. "SQLITE_OMIT_VIRTUALTABLE", (void*)0);
  1074. return TCL_ERROR;
  1075. #else
  1076. zDb = Tcl_GetString(objv[2]);
  1077. if( Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
  1078. db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
  1079. rc = sqlite3_vfslog_register(db);
  1080. }
  1081. if( rc!=SQLITE_OK ){
  1082. Tcl_AppendResult(interp, "bad sqlite3 handle: ", zDb, (void*)0);
  1083. return TCL_ERROR;
  1084. }
  1085. break;
  1086. #endif
  1087. }
  1088. }
  1089. return TCL_OK;
  1090. }
  1091. int SqlitetestOsinst_Init(Tcl_Interp *interp){
  1092. Tcl_CreateObjCommand(interp, "vfslog", test_vfslog, 0, 0);
  1093. return TCL_OK;
  1094. }
  1095. #endif /* SQLITE_TEST */