Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(275)

Side by Side Diff: third_party/sqlite/src/ext/misc/vfsstat.c

Issue 2751253002: [sql] Import SQLite 3.17.0. (Closed)
Patch Set: also clang on Linux i386 Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/sqlite/src/ext/misc/spellfix.c ('k') | third_party/sqlite/src/ext/misc/vtshim.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 ** 2016-05-27
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 shim that
14 ** tracks I/O. Access to the accumulated status counts is provided using
15 ** an eponymous virtual table.
16 */
17 #include <sqlite3ext.h>
18 SQLITE_EXTENSION_INIT1
19
20 /*
21 ** This module contains code for a wrapper VFS that cause stats for
22 ** most VFS calls to be recorded.
23 **
24 ** To use this module, first compile it as a loadable extension. See
25 ** https://www.sqlite.org/loadext.html#build for compilations instructions.
26 **
27 ** After compliing, load this extension, then open database connections to be
28 ** measured. Query usages status using the vfsstat virtual table:
29 **
30 ** SELECT * FROM vfsstat;
31 **
32 ** Reset counters using UPDATE statements against vfsstat:
33 **
34 ** UPDATE vfsstat SET count=0;
35 **
36 ** EXAMPLE SCRIPT:
37 **
38 ** .load ./vfsstat
39 ** .open test.db
40 ** DROP TABLE IF EXISTS t1;
41 ** CREATE TABLE t1(x,y);
42 ** INSERT INTO t1 VALUES(123, randomblob(5000));
43 ** CREATE INDEX t1x ON t1(x);
44 ** DROP TABLE t1;
45 ** VACUUM;
46 ** SELECT * FROM vfsstat WHERE count>0;
47 **
48 ** LIMITATIONS:
49 **
50 ** This module increments counters without using mutex protection. So if
51 ** two or more threads try to use this module at the same time, race conditions
52 ** may occur which mess up the counts. This is harmless, other than giving
53 ** incorrect statistics.
54 */
55 #include <string.h>
56 #include <stdlib.h>
57 #include <assert.h>
58
59 /*
60 ** File types
61 */
62 #define VFSSTAT_MAIN 0 /* Main database file */
63 #define VFSSTAT_JOURNAL 1 /* Rollback journal */
64 #define VFSSTAT_WAL 2 /* Write-ahead log file */
65 #define VFSSTAT_MASTERJRNL 3 /* Master journal */
66 #define VFSSTAT_SUBJRNL 4 /* Subjournal */
67 #define VFSSTAT_TEMPDB 5 /* TEMP database */
68 #define VFSSTAT_TEMPJRNL 6 /* Journal for TEMP database */
69 #define VFSSTAT_TRANSIENT 7 /* Transient database */
70 #define VFSSTAT_ANY 8 /* Unspecified file type */
71 #define VFSSTAT_nFile 9 /* This many file types */
72
73 /* Names of the file types. These are allowed values for the
74 ** first column of the vfsstat virtual table.
75 */
76 static const char *azFile[] = {
77 "database", "journal", "wal", "master-journal", "sub-journal",
78 "temp-database", "temp-journal", "transient-db", "*"
79 };
80
81 /*
82 ** Stat types
83 */
84 #define VFSSTAT_BYTESIN 0 /* Bytes read in */
85 #define VFSSTAT_BYTESOUT 1 /* Bytes written out */
86 #define VFSSTAT_READ 2 /* Read requests */
87 #define VFSSTAT_WRITE 3 /* Write requests */
88 #define VFSSTAT_SYNC 4 /* Syncs */
89 #define VFSSTAT_OPEN 5 /* File opens */
90 #define VFSSTAT_LOCK 6 /* Lock requests */
91 #define VFSSTAT_ACCESS 0 /* xAccess calls. filetype==ANY only */
92 #define VFSSTAT_DELETE 1 /* xDelete calls. filetype==ANY only */
93 #define VFSSTAT_FULLPATH 2 /* xFullPathname calls. ANY only */
94 #define VFSSTAT_RANDOM 3 /* xRandomness calls. ANY only */
95 #define VFSSTAT_SLEEP 4 /* xSleep calls. ANY only */
96 #define VFSSTAT_CURTIME 5 /* xCurrentTime calls. ANY only */
97 #define VFSSTAT_nStat 7 /* This many stat types */
98
99
100 /* Names for the second column of the vfsstat virtual table for all
101 ** cases except when the first column is "*" or VFSSTAT_ANY. */
102 static const char *azStat[] = {
103 "bytes-in", "bytes-out", "read", "write", "sync", "open", "lock",
104 };
105 static const char *azStatAny[] = {
106 "access", "delete", "fullpathname", "randomness", "sleep", "currenttimestamp",
107 "not-used"
108 };
109
110 /* Total number of counters */
111 #define VFSSTAT_MXCNT (VFSSTAT_nStat*VFSSTAT_nFile)
112
113 /*
114 ** Performance stats are collected in an instance of the following
115 ** global array.
116 */
117 static sqlite3_uint64 aVfsCnt[VFSSTAT_MXCNT];
118
119 /*
120 ** Access to a specific counter
121 */
122 #define STATCNT(filetype,stat) (aVfsCnt[(filetype)*VFSSTAT_nStat+(stat)])
123
124 /*
125 ** Forward declaration of objects used by this utility
126 */
127 typedef struct VStatVfs VStatVfs;
128 typedef struct VStatFile VStatFile;
129
130 /* An instance of the VFS */
131 struct VStatVfs {
132 sqlite3_vfs base; /* VFS methods */
133 sqlite3_vfs *pVfs; /* Parent VFS */
134 };
135
136 /* An open file */
137 struct VStatFile {
138 sqlite3_file base; /* IO methods */
139 sqlite3_file *pReal; /* Underlying file handle */
140 unsigned char eFiletype; /* What type of file is this */
141 };
142
143 #define REALVFS(p) (((VStatVfs*)(p))->pVfs)
144
145 /*
146 ** Methods for VStatFile
147 */
148 static int vstatClose(sqlite3_file*);
149 static int vstatRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
150 static int vstatWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
151 static int vstatTruncate(sqlite3_file*, sqlite3_int64 size);
152 static int vstatSync(sqlite3_file*, int flags);
153 static int vstatFileSize(sqlite3_file*, sqlite3_int64 *pSize);
154 static int vstatLock(sqlite3_file*, int);
155 static int vstatUnlock(sqlite3_file*, int);
156 static int vstatCheckReservedLock(sqlite3_file*, int *pResOut);
157 static int vstatFileControl(sqlite3_file*, int op, void *pArg);
158 static int vstatSectorSize(sqlite3_file*);
159 static int vstatDeviceCharacteristics(sqlite3_file*);
160 static int vstatShmMap(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
161 static int vstatShmLock(sqlite3_file*, int offset, int n, int flags);
162 static void vstatShmBarrier(sqlite3_file*);
163 static int vstatShmUnmap(sqlite3_file*, int deleteFlag);
164 static int vstatFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
165 static int vstatUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p);
166
167 /*
168 ** Methods for VStatVfs
169 */
170 static int vstatOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
171 static int vstatDelete(sqlite3_vfs*, const char *zName, int syncDir);
172 static int vstatAccess(sqlite3_vfs*, const char *zName, int flags, int *);
173 static int vstatFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
174 static void *vstatDlOpen(sqlite3_vfs*, const char *zFilename);
175 static void vstatDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
176 static void (*vstatDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
177 static void vstatDlClose(sqlite3_vfs*, void*);
178 static int vstatRandomness(sqlite3_vfs*, int nByte, char *zOut);
179 static int vstatSleep(sqlite3_vfs*, int microseconds);
180 static int vstatCurrentTime(sqlite3_vfs*, double*);
181 static int vstatGetLastError(sqlite3_vfs*, int, char *);
182 static int vstatCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
183
184 static VStatVfs vstat_vfs = {
185 {
186 2, /* iVersion */
187 0, /* szOsFile (set by register_vstat()) */
188 1024, /* mxPathname */
189 0, /* pNext */
190 "vfslog", /* zName */
191 0, /* pAppData */
192 vstatOpen, /* xOpen */
193 vstatDelete, /* xDelete */
194 vstatAccess, /* xAccess */
195 vstatFullPathname, /* xFullPathname */
196 vstatDlOpen, /* xDlOpen */
197 vstatDlError, /* xDlError */
198 vstatDlSym, /* xDlSym */
199 vstatDlClose, /* xDlClose */
200 vstatRandomness, /* xRandomness */
201 vstatSleep, /* xSleep */
202 vstatCurrentTime, /* xCurrentTime */
203 vstatGetLastError, /* xGetLastError */
204 vstatCurrentTimeInt64 /* xCurrentTimeInt64 */
205 },
206 0
207 };
208
209 static const sqlite3_io_methods vstat_io_methods = {
210 3, /* iVersion */
211 vstatClose, /* xClose */
212 vstatRead, /* xRead */
213 vstatWrite, /* xWrite */
214 vstatTruncate, /* xTruncate */
215 vstatSync, /* xSync */
216 vstatFileSize, /* xFileSize */
217 vstatLock, /* xLock */
218 vstatUnlock, /* xUnlock */
219 vstatCheckReservedLock, /* xCheckReservedLock */
220 vstatFileControl, /* xFileControl */
221 vstatSectorSize, /* xSectorSize */
222 vstatDeviceCharacteristics, /* xDeviceCharacteristics */
223 vstatShmMap, /* xShmMap */
224 vstatShmLock, /* xShmLock */
225 vstatShmBarrier, /* xShmBarrier */
226 vstatShmUnmap, /* xShmUnmap */
227 vstatFetch, /* xFetch */
228 vstatUnfetch /* xUnfetch */
229 };
230
231
232
233 /*
234 ** Close an vstat-file.
235 */
236 static int vstatClose(sqlite3_file *pFile){
237 VStatFile *p = (VStatFile *)pFile;
238 int rc = SQLITE_OK;
239
240 if( p->pReal->pMethods ){
241 rc = p->pReal->pMethods->xClose(p->pReal);
242 }
243 return rc;
244 }
245
246
247 /*
248 ** Read data from an vstat-file.
249 */
250 static int vstatRead(
251 sqlite3_file *pFile,
252 void *zBuf,
253 int iAmt,
254 sqlite_int64 iOfst
255 ){
256 int rc;
257 VStatFile *p = (VStatFile *)pFile;
258
259 rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst);
260 STATCNT(p->eFiletype,VFSSTAT_READ)++;
261 if( rc==SQLITE_OK ){
262 STATCNT(p->eFiletype,VFSSTAT_BYTESIN) += iAmt;
263 }
264 return rc;
265 }
266
267 /*
268 ** Write data to an vstat-file.
269 */
270 static int vstatWrite(
271 sqlite3_file *pFile,
272 const void *z,
273 int iAmt,
274 sqlite_int64 iOfst
275 ){
276 int rc;
277 VStatFile *p = (VStatFile *)pFile;
278
279 rc = p->pReal->pMethods->xWrite(p->pReal, z, iAmt, iOfst);
280 STATCNT(p->eFiletype,VFSSTAT_WRITE)++;
281 if( rc==SQLITE_OK ){
282 STATCNT(p->eFiletype,VFSSTAT_BYTESOUT) += iAmt;
283 }
284 return rc;
285 }
286
287 /*
288 ** Truncate an vstat-file.
289 */
290 static int vstatTruncate(sqlite3_file *pFile, sqlite_int64 size){
291 int rc;
292 VStatFile *p = (VStatFile *)pFile;
293 rc = p->pReal->pMethods->xTruncate(p->pReal, size);
294 return rc;
295 }
296
297 /*
298 ** Sync an vstat-file.
299 */
300 static int vstatSync(sqlite3_file *pFile, int flags){
301 int rc;
302 VStatFile *p = (VStatFile *)pFile;
303 rc = p->pReal->pMethods->xSync(p->pReal, flags);
304 STATCNT(p->eFiletype,VFSSTAT_SYNC)++;
305 return rc;
306 }
307
308 /*
309 ** Return the current file-size of an vstat-file.
310 */
311 static int vstatFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
312 int rc;
313 VStatFile *p = (VStatFile *)pFile;
314 rc = p->pReal->pMethods->xFileSize(p->pReal, pSize);
315 return rc;
316 }
317
318 /*
319 ** Lock an vstat-file.
320 */
321 static int vstatLock(sqlite3_file *pFile, int eLock){
322 int rc;
323 VStatFile *p = (VStatFile *)pFile;
324 rc = p->pReal->pMethods->xLock(p->pReal, eLock);
325 STATCNT(p->eFiletype,VFSSTAT_LOCK)++;
326 return rc;
327 }
328
329 /*
330 ** Unlock an vstat-file.
331 */
332 static int vstatUnlock(sqlite3_file *pFile, int eLock){
333 int rc;
334 VStatFile *p = (VStatFile *)pFile;
335 rc = p->pReal->pMethods->xUnlock(p->pReal, eLock);
336 STATCNT(p->eFiletype,VFSSTAT_LOCK)++;
337 return rc;
338 }
339
340 /*
341 ** Check if another file-handle holds a RESERVED lock on an vstat-file.
342 */
343 static int vstatCheckReservedLock(sqlite3_file *pFile, int *pResOut){
344 int rc;
345 VStatFile *p = (VStatFile *)pFile;
346 rc = p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut);
347 STATCNT(p->eFiletype,VFSSTAT_LOCK)++;
348 return rc;
349 }
350
351 /*
352 ** File control method. For custom operations on an vstat-file.
353 */
354 static int vstatFileControl(sqlite3_file *pFile, int op, void *pArg){
355 VStatFile *p = (VStatFile *)pFile;
356 int rc;
357 rc = p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
358 if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){
359 *(char**)pArg = sqlite3_mprintf("vstat/%z", *(char**)pArg);
360 }
361 return rc;
362 }
363
364 /*
365 ** Return the sector-size in bytes for an vstat-file.
366 */
367 static int vstatSectorSize(sqlite3_file *pFile){
368 int rc;
369 VStatFile *p = (VStatFile *)pFile;
370 rc = p->pReal->pMethods->xSectorSize(p->pReal);
371 return rc;
372 }
373
374 /*
375 ** Return the device characteristic flags supported by an vstat-file.
376 */
377 static int vstatDeviceCharacteristics(sqlite3_file *pFile){
378 int rc;
379 VStatFile *p = (VStatFile *)pFile;
380 rc = p->pReal->pMethods->xDeviceCharacteristics(p->pReal);
381 return rc;
382 }
383
384 /* Create a shared memory file mapping */
385 static int vstatShmMap(
386 sqlite3_file *pFile,
387 int iPg,
388 int pgsz,
389 int bExtend,
390 void volatile **pp
391 ){
392 VStatFile *p = (VStatFile *)pFile;
393 return p->pReal->pMethods->xShmMap(p->pReal, iPg, pgsz, bExtend, pp);
394 }
395
396 /* Perform locking on a shared-memory segment */
397 static int vstatShmLock(sqlite3_file *pFile, int offset, int n, int flags){
398 VStatFile *p = (VStatFile *)pFile;
399 return p->pReal->pMethods->xShmLock(p->pReal, offset, n, flags);
400 }
401
402 /* Memory barrier operation on shared memory */
403 static void vstatShmBarrier(sqlite3_file *pFile){
404 VStatFile *p = (VStatFile *)pFile;
405 p->pReal->pMethods->xShmBarrier(p->pReal);
406 }
407
408 /* Unmap a shared memory segment */
409 static int vstatShmUnmap(sqlite3_file *pFile, int deleteFlag){
410 VStatFile *p = (VStatFile *)pFile;
411 return p->pReal->pMethods->xShmUnmap(p->pReal, deleteFlag);
412 }
413
414 /* Fetch a page of a memory-mapped file */
415 static int vstatFetch(
416 sqlite3_file *pFile,
417 sqlite3_int64 iOfst,
418 int iAmt,
419 void **pp
420 ){
421 VStatFile *p = (VStatFile *)pFile;
422 return p->pReal->pMethods->xFetch(p->pReal, iOfst, iAmt, pp);
423 }
424
425 /* Release a memory-mapped page */
426 static int vstatUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
427 VStatFile *p = (VStatFile *)pFile;
428 return p->pReal->pMethods->xUnfetch(p->pReal, iOfst, pPage);
429 }
430
431 /*
432 ** Open an vstat file handle.
433 */
434 static int vstatOpen(
435 sqlite3_vfs *pVfs,
436 const char *zName,
437 sqlite3_file *pFile,
438 int flags,
439 int *pOutFlags
440 ){
441 int rc;
442 VStatFile *p = (VStatFile*)pFile;
443
444 p->pReal = (sqlite3_file*)&p[1];
445 rc = REALVFS(pVfs)->xOpen(REALVFS(pVfs), zName, p->pReal, flags, pOutFlags);
446 if( flags & SQLITE_OPEN_MAIN_DB ){
447 p->eFiletype = VFSSTAT_MAIN;
448 }else if( flags & SQLITE_OPEN_MAIN_JOURNAL ){
449 p->eFiletype = VFSSTAT_JOURNAL;
450 }else if( flags & SQLITE_OPEN_WAL ){
451 p->eFiletype = VFSSTAT_WAL;
452 }else if( flags & SQLITE_OPEN_MASTER_JOURNAL ){
453 p->eFiletype = VFSSTAT_MASTERJRNL;
454 }else if( flags & SQLITE_OPEN_SUBJOURNAL ){
455 p->eFiletype = VFSSTAT_SUBJRNL;
456 }else if( flags & SQLITE_OPEN_TEMP_DB ){
457 p->eFiletype = VFSSTAT_TEMPDB;
458 }else if( flags & SQLITE_OPEN_TEMP_JOURNAL ){
459 p->eFiletype = VFSSTAT_TEMPJRNL;
460 }else{
461 p->eFiletype = VFSSTAT_TRANSIENT;
462 }
463 STATCNT(p->eFiletype,VFSSTAT_OPEN)++;
464 pFile->pMethods = rc ? 0 : &vstat_io_methods;
465 return rc;
466 }
467
468 /*
469 ** Delete the file located at zPath. If the dirSync argument is true,
470 ** ensure the file-system modifications are synced to disk before
471 ** returning.
472 */
473 static int vstatDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
474 int rc;
475 rc = REALVFS(pVfs)->xDelete(REALVFS(pVfs), zPath, dirSync);
476 STATCNT(VFSSTAT_ANY,VFSSTAT_DELETE)++;
477 return rc;
478 }
479
480 /*
481 ** Test for access permissions. Return true if the requested permission
482 ** is available, or false otherwise.
483 */
484 static int vstatAccess(
485 sqlite3_vfs *pVfs,
486 const char *zPath,
487 int flags,
488 int *pResOut
489 ){
490 int rc;
491 rc = REALVFS(pVfs)->xAccess(REALVFS(pVfs), zPath, flags, pResOut);
492 STATCNT(VFSSTAT_ANY,VFSSTAT_ACCESS)++;
493 return rc;
494 }
495
496 /*
497 ** Populate buffer zOut with the full canonical pathname corresponding
498 ** to the pathname in zPath. zOut is guaranteed to point to a buffer
499 ** of at least (INST_MAX_PATHNAME+1) bytes.
500 */
501 static int vstatFullPathname(
502 sqlite3_vfs *pVfs,
503 const char *zPath,
504 int nOut,
505 char *zOut
506 ){
507 STATCNT(VFSSTAT_ANY,VFSSTAT_FULLPATH)++;
508 return REALVFS(pVfs)->xFullPathname(REALVFS(pVfs), zPath, nOut, zOut);
509 }
510
511 /*
512 ** Open the dynamic library located at zPath and return a handle.
513 */
514 static void *vstatDlOpen(sqlite3_vfs *pVfs, const char *zPath){
515 return REALVFS(pVfs)->xDlOpen(REALVFS(pVfs), zPath);
516 }
517
518 /*
519 ** Populate the buffer zErrMsg (size nByte bytes) with a human readable
520 ** utf-8 string describing the most recent error encountered associated
521 ** with dynamic libraries.
522 */
523 static void vstatDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
524 REALVFS(pVfs)->xDlError(REALVFS(pVfs), nByte, zErrMsg);
525 }
526
527 /*
528 ** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
529 */
530 static void (*vstatDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
531 return REALVFS(pVfs)->xDlSym(REALVFS(pVfs), p, zSym);
532 }
533
534 /*
535 ** Close the dynamic library handle pHandle.
536 */
537 static void vstatDlClose(sqlite3_vfs *pVfs, void *pHandle){
538 REALVFS(pVfs)->xDlClose(REALVFS(pVfs), pHandle);
539 }
540
541 /*
542 ** Populate the buffer pointed to by zBufOut with nByte bytes of
543 ** random data.
544 */
545 static int vstatRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
546 STATCNT(VFSSTAT_ANY,VFSSTAT_RANDOM)++;
547 return REALVFS(pVfs)->xRandomness(REALVFS(pVfs), nByte, zBufOut);
548 }
549
550 /*
551 ** Sleep for nMicro microseconds. Return the number of microseconds
552 ** actually slept.
553 */
554 static int vstatSleep(sqlite3_vfs *pVfs, int nMicro){
555 STATCNT(VFSSTAT_ANY,VFSSTAT_SLEEP)++;
556 return REALVFS(pVfs)->xSleep(REALVFS(pVfs), nMicro);
557 }
558
559 /*
560 ** Return the current time as a Julian Day number in *pTimeOut.
561 */
562 static int vstatCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
563 STATCNT(VFSSTAT_ANY,VFSSTAT_CURTIME)++;
564 return REALVFS(pVfs)->xCurrentTime(REALVFS(pVfs), pTimeOut);
565 }
566
567 static int vstatGetLastError(sqlite3_vfs *pVfs, int a, char *b){
568 return REALVFS(pVfs)->xGetLastError(REALVFS(pVfs), a, b);
569 }
570 static int vstatCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
571 STATCNT(VFSSTAT_ANY,VFSSTAT_CURTIME)++;
572 return REALVFS(pVfs)->xCurrentTimeInt64(REALVFS(pVfs), p);
573 }
574
575 /*
576 ** A virtual table for accessing the stats collected by this VFS shim
577 */
578 static int vstattabConnect(sqlite3*, void*, int, const char*const*,
579 sqlite3_vtab**,char**);
580 static int vstattabBestIndex(sqlite3_vtab*,sqlite3_index_info*);
581 static int vstattabDisconnect(sqlite3_vtab*);
582 static int vstattabOpen(sqlite3_vtab*, sqlite3_vtab_cursor**);
583 static int vstattabClose(sqlite3_vtab_cursor*);
584 static int vstattabFilter(sqlite3_vtab_cursor*, int idxNum, const char *idxStr,
585 int argc, sqlite3_value **argv);
586 static int vstattabNext(sqlite3_vtab_cursor*);
587 static int vstattabEof(sqlite3_vtab_cursor*);
588 static int vstattabColumn(sqlite3_vtab_cursor*,sqlite3_context*,int);
589 static int vstattabRowid(sqlite3_vtab_cursor*,sqlite3_int64*);
590 static int vstattabUpdate(sqlite3_vtab*,int,sqlite3_value**,sqlite3_int64*);
591
592 /* A cursor for the vfsstat virtual table */
593 typedef struct VfsStatCursor {
594 sqlite3_vtab_cursor base; /* Base class. Must be first */
595 int i; /* Pointing to this aVfsCnt[] value */
596 } VfsStatCursor;
597
598
599 static int vstattabConnect(
600 sqlite3 *db,
601 void *pAux,
602 int argc, const char *const*argv,
603 sqlite3_vtab **ppVtab,
604 char **pzErr
605 ){
606 sqlite3_vtab *pNew;
607 int rc;
608
609 /* Column numbers */
610 #define VSTAT_COLUMN_FILE 0
611 #define VSTAT_COLUMN_STAT 1
612 #define VSTAT_COLUMN_COUNT 2
613
614 rc = sqlite3_declare_vtab(db,"CREATE TABLE x(file,stat,count)");
615 if( rc==SQLITE_OK ){
616 pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) );
617 if( pNew==0 ) return SQLITE_NOMEM;
618 memset(pNew, 0, sizeof(*pNew));
619 }
620 return rc;
621 }
622
623 /*
624 ** This method is the destructor for vstat table object.
625 */
626 static int vstattabDisconnect(sqlite3_vtab *pVtab){
627 sqlite3_free(pVtab);
628 return SQLITE_OK;
629 }
630
631 /*
632 ** Constructor for a new vstat table cursor object.
633 */
634 static int vstattabOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
635 VfsStatCursor *pCur;
636 pCur = sqlite3_malloc( sizeof(*pCur) );
637 if( pCur==0 ) return SQLITE_NOMEM;
638 memset(pCur, 0, sizeof(*pCur));
639 *ppCursor = &pCur->base;
640 return SQLITE_OK;
641 }
642
643
644 /*
645 ** Destructor for a VfsStatCursor.
646 */
647 static int vstattabClose(sqlite3_vtab_cursor *cur){
648 sqlite3_free(cur);
649 return SQLITE_OK;
650 }
651
652
653 /*
654 ** Advance a VfsStatCursor to its next row of output.
655 */
656 static int vstattabNext(sqlite3_vtab_cursor *cur){
657 ((VfsStatCursor*)cur)->i++;
658 return SQLITE_OK;
659 }
660
661 /*
662 ** Return values of columns for the row at which the VfsStatCursor
663 ** is currently pointing.
664 */
665 static int vstattabColumn(
666 sqlite3_vtab_cursor *cur, /* The cursor */
667 sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
668 int i /* Which column to return */
669 ){
670 VfsStatCursor *pCur = (VfsStatCursor*)cur;
671 switch( i ){
672 case VSTAT_COLUMN_FILE: {
673 sqlite3_result_text(ctx, azFile[pCur->i/VFSSTAT_nStat], -1, SQLITE_STATIC) ;
674 break;
675 }
676 case VSTAT_COLUMN_STAT: {
677 const char **az;
678 az = (pCur->i/VFSSTAT_nStat)==VFSSTAT_ANY ? azStatAny : azStat;
679 sqlite3_result_text(ctx, az[pCur->i%VFSSTAT_nStat], -1, SQLITE_STATIC);
680 break;
681 }
682 case VSTAT_COLUMN_COUNT: {
683 sqlite3_result_int64(ctx, aVfsCnt[pCur->i]);
684 break;
685 }
686 }
687 return SQLITE_OK;
688 }
689
690 /*
691 ** Return the rowid for the current row.
692 */
693 static int vstattabRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
694 VfsStatCursor *pCur = (VfsStatCursor*)cur;
695 *pRowid = pCur->i;
696 return SQLITE_OK;
697 }
698
699 /*
700 ** Return TRUE if the cursor has been moved off of the last
701 ** row of output.
702 */
703 static int vstattabEof(sqlite3_vtab_cursor *cur){
704 VfsStatCursor *pCur = (VfsStatCursor*)cur;
705 return pCur->i >= VFSSTAT_MXCNT;
706 }
707
708 /*
709 ** Only a full table scan is supported. So xFilter simply rewinds to
710 ** the beginning.
711 */
712 static int vstattabFilter(
713 sqlite3_vtab_cursor *pVtabCursor,
714 int idxNum, const char *idxStr,
715 int argc, sqlite3_value **argv
716 ){
717 VfsStatCursor *pCur = (VfsStatCursor*)pVtabCursor;
718 pCur->i = 0;
719 return SQLITE_OK;
720 }
721
722 /*
723 ** Only a forwards full table scan is supported. xBestIndex is a no-op.
724 */
725 static int vstattabBestIndex(
726 sqlite3_vtab *tab,
727 sqlite3_index_info *pIdxInfo
728 ){
729 return SQLITE_OK;
730 }
731
732 /*
733 ** Any VSTAT_COLUMN_COUNT can be changed to a positive integer.
734 ** No deletions or insertions are allowed. No changes to other
735 ** columns are allowed.
736 */
737 static int vstattabUpdate(
738 sqlite3_vtab *tab,
739 int argc, sqlite3_value **argv,
740 sqlite3_int64 *pRowid
741 ){
742 sqlite3_int64 iRowid, x;
743 if( argc==1 ) return SQLITE_ERROR;
744 if( sqlite3_value_type(argv[0])!=SQLITE_INTEGER ) return SQLITE_ERROR;
745 iRowid = sqlite3_value_int64(argv[0]);
746 if( iRowid!=sqlite3_value_int64(argv[1]) ) return SQLITE_ERROR;
747 if( iRowid<0 || iRowid>=VFSSTAT_MXCNT ) return SQLITE_ERROR;
748 if( sqlite3_value_type(argv[VSTAT_COLUMN_COUNT+2])!=SQLITE_INTEGER ){
749 return SQLITE_ERROR;
750 }
751 x = sqlite3_value_int64(argv[VSTAT_COLUMN_COUNT+2]);
752 if( x<0 ) return SQLITE_ERROR;
753 aVfsCnt[iRowid] = x;
754 return SQLITE_OK;
755 }
756
757 static sqlite3_module VfsStatModule = {
758 0, /* iVersion */
759 0, /* xCreate */
760 vstattabConnect, /* xConnect */
761 vstattabBestIndex, /* xBestIndex */
762 vstattabDisconnect, /* xDisconnect */
763 0, /* xDestroy */
764 vstattabOpen, /* xOpen - open a cursor */
765 vstattabClose, /* xClose - close a cursor */
766 vstattabFilter, /* xFilter - configure scan constraints */
767 vstattabNext, /* xNext - advance a cursor */
768 vstattabEof, /* xEof - check for end of scan */
769 vstattabColumn, /* xColumn - read data */
770 vstattabRowid, /* xRowid - read data */
771 vstattabUpdate, /* xUpdate */
772 0, /* xBegin */
773 0, /* xSync */
774 0, /* xCommit */
775 0, /* xRollback */
776 0, /* xFindMethod */
777 0, /* xRename */
778 };
779
780 /*
781 ** This routine is an sqlite3_auto_extension() callback, invoked to register
782 ** the vfsstat virtual table for all new database connections.
783 */
784 static int vstatRegister(
785 sqlite3 *db,
786 const char **pzErrMsg,
787 const struct sqlite3_api_routines *pThunk
788 ){
789 return sqlite3_create_module(db, "vfsstat", &VfsStatModule, 0);
790 }
791
792 #ifdef _WIN32
793 __declspec(dllexport)
794 #endif
795 /*
796 ** This routine is called when the extension is loaded.
797 **
798 ** Register the new VFS. Make arrangement to register the virtual table
799 ** for each new database connection.
800 */
801 int sqlite3_vfsstat_init(
802 sqlite3 *db,
803 char **pzErrMsg,
804 const sqlite3_api_routines *pApi
805 ){
806 int rc = SQLITE_OK;
807 SQLITE_EXTENSION_INIT2(pApi);
808 vstat_vfs.pVfs = sqlite3_vfs_find(0);
809 vstat_vfs.base.szOsFile = sizeof(VStatFile) + vstat_vfs.pVfs->szOsFile;
810 rc = sqlite3_vfs_register(&vstat_vfs.base, 1);
811 if( rc==SQLITE_OK ){
812 rc = sqlite3_auto_extension(vstatRegister);
813 }
814 if( rc==SQLITE_OK ) rc = SQLITE_OK_LOAD_PERMANENTLY;
815 return rc;
816 }
OLDNEW
« no previous file with comments | « third_party/sqlite/src/ext/misc/spellfix.c ('k') | third_party/sqlite/src/ext/misc/vtshim.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698