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

Side by Side Diff: third_party/sqlite/src/test_osinst.c

Issue 3108030: Move bundled copy of sqlite one level deeper to better separate it... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 10 years, 4 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 | Annotate | Revision Log
« no previous file with comments | « third_party/sqlite/src/test_onefile.c ('k') | third_party/sqlite/src/test_pcache.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 ** 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 ** $Id: test_osinst.c,v 1.19 2009/01/08 17:57:32 danielk1977 Exp $
18 */
19
20 #ifdef SQLITE_ENABLE_INSTVFS
21 /*
22 ** C interface:
23 **
24 ** sqlite3_instvfs_create()
25 ** sqlite3_instvfs_destroy()
26 ** sqlite3_instvfs_configure()
27 **
28 ** sqlite3_instvfs_reset()
29 ** sqlite3_instvfs_get()
30 **
31 ** sqlite3_instvfs_binarylog
32 ** sqlite3_instvfs_binarylog_marker
33 **
34 ** Tcl interface (omitted if SQLITE_TEST is not set):
35 **
36 ** sqlite3_instvfs create NAME ?PARENT?
37 **
38 ** Create and register new vfs called $NAME, which is a wrapper around
39 ** the existing vfs $PARENT. If the PARENT argument is omitted, the
40 ** new vfs is a wrapper around the current default vfs.
41 **
42 ** sqlite3_instvfs destroy NAME
43 **
44 ** Deregister and destroy the vfs named $NAME, which must have been
45 ** created by an earlier invocation of [sqlite3_instvfs create].
46 **
47 ** sqlite3_instvfs configure NAME SCRIPT
48 **
49 ** Configure the callback script for the vfs $NAME, which much have
50 ** been created by an earlier invocation of [sqlite3_instvfs create].
51 ** After a callback script has been configured, it is invoked each
52 ** time a vfs or file method is called by SQLite. Before invoking
53 ** the callback script, five arguments are appended to it:
54 **
55 ** * The name of the invoked method - i.e. "xRead".
56 **
57 ** * The time consumed by the method call as measured by
58 ** sqlite3Hwtime() (an integer value)
59 **
60 ** * A string value with a different meaning for different calls.
61 ** For file methods, the name of the file being operated on. For
62 ** other methods it is the filename argument, if any.
63 **
64 ** * A 32-bit integer value with a call-specific meaning.
65 **
66 ** * A 64-bit integer value. For xRead() and xWrite() calls this
67 ** is the file offset being written to or read from. Unused by
68 ** all other calls.
69 **
70 ** sqlite3_instvfs reset NAME
71 **
72 ** Zero the internal event counters associated with vfs $NAME,
73 ** which must have been created by an earlier invocation of
74 ** [sqlite3_instvfs create].
75 **
76 ** sqlite3_instvfs report NAME
77 **
78 ** Return the values of the internal event counters associated
79 ** with vfs $NAME. The report format is a list with one element
80 ** for each method call (xWrite, xRead etc.). Each element is
81 ** itself a list with three elements:
82 **
83 ** * The name of the method call - i.e. "xWrite",
84 ** * The total number of calls to the method (an integer).
85 ** * The aggregate time consumed by all calls to the method as
86 ** measured by sqlite3Hwtime() (an integer).
87 */
88
89 #include "sqlite3.h"
90 #include <string.h>
91 #include <assert.h>
92
93 /*
94 ** Maximum pathname length supported by the inst backend.
95 */
96 #define INST_MAX_PATHNAME 512
97
98
99 /* File methods */
100 /* Vfs methods */
101 #define OS_ACCESS 1
102 #define OS_CHECKRESERVEDLOCK 2
103 #define OS_CLOSE 3
104 #define OS_CURRENTTIME 4
105 #define OS_DELETE 5
106 #define OS_DEVCHAR 6
107 #define OS_FILECONTROL 7
108 #define OS_FILESIZE 8
109 #define OS_FULLPATHNAME 9
110 #define OS_LOCK 11
111 #define OS_OPEN 12
112 #define OS_RANDOMNESS 13
113 #define OS_READ 14
114 #define OS_SECTORSIZE 15
115 #define OS_SLEEP 16
116 #define OS_SYNC 17
117 #define OS_TRUNCATE 18
118 #define OS_UNLOCK 19
119 #define OS_WRITE 20
120
121 #define OS_NUMEVENTS 21
122
123 #define BINARYLOG_STRING 30
124 #define BINARYLOG_MARKER 31
125
126 #define BINARYLOG_PREPARE_V2 64
127 #define BINARYLOG_STEP 65
128 #define BINARYLOG_FINALIZE 66
129
130 struct InstVfs {
131 sqlite3_vfs base;
132 sqlite3_vfs *pVfs;
133
134 void *pClient;
135 void (*xDel)(void *);
136 void (*xCall)(void *, int, int, sqlite3_int64, int, const char *, int, int, sq lite3_int64);
137
138 /* Counters */
139 sqlite3_int64 aTime[OS_NUMEVENTS];
140 int aCount[OS_NUMEVENTS];
141
142 int iNextFileId;
143 };
144 typedef struct InstVfs InstVfs;
145
146 #define REALVFS(p) (((InstVfs *)(p))->pVfs)
147
148 typedef struct inst_file inst_file;
149 struct inst_file {
150 sqlite3_file base;
151 sqlite3_file *pReal;
152 InstVfs *pInstVfs;
153 const char *zName;
154 int iFileId; /* File id number */
155 int flags;
156 };
157
158 /*
159 ** Method declarations for inst_file.
160 */
161 static int instClose(sqlite3_file*);
162 static int instRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
163 static int instWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
164 static int instTruncate(sqlite3_file*, sqlite3_int64 size);
165 static int instSync(sqlite3_file*, int flags);
166 static int instFileSize(sqlite3_file*, sqlite3_int64 *pSize);
167 static int instLock(sqlite3_file*, int);
168 static int instUnlock(sqlite3_file*, int);
169 static int instCheckReservedLock(sqlite3_file*, int *pResOut);
170 static int instFileControl(sqlite3_file*, int op, void *pArg);
171 static int instSectorSize(sqlite3_file*);
172 static int instDeviceCharacteristics(sqlite3_file*);
173
174 /*
175 ** Method declarations for inst_vfs.
176 */
177 static int instOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
178 static int instDelete(sqlite3_vfs*, const char *zName, int syncDir);
179 static int instAccess(sqlite3_vfs*, const char *zName, int flags, int *);
180 static int instFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
181 static void *instDlOpen(sqlite3_vfs*, const char *zFilename);
182 static void instDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
183 static void (*instDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
184 static void instDlClose(sqlite3_vfs*, void*);
185 static int instRandomness(sqlite3_vfs*, int nByte, char *zOut);
186 static int instSleep(sqlite3_vfs*, int microseconds);
187 static int instCurrentTime(sqlite3_vfs*, double*);
188
189 static void binarylog_blob(sqlite3_vfs *, const char *, int, int);
190
191 static sqlite3_vfs inst_vfs = {
192 1, /* iVersion */
193 sizeof(inst_file), /* szOsFile */
194 INST_MAX_PATHNAME, /* mxPathname */
195 0, /* pNext */
196 0, /* zName */
197 0, /* pAppData */
198 instOpen, /* xOpen */
199 instDelete, /* xDelete */
200 instAccess, /* xAccess */
201 instFullPathname, /* xFullPathname */
202 instDlOpen, /* xDlOpen */
203 instDlError, /* xDlError */
204 instDlSym, /* xDlSym */
205 instDlClose, /* xDlClose */
206 instRandomness, /* xRandomness */
207 instSleep, /* xSleep */
208 instCurrentTime /* xCurrentTime */
209 };
210
211 static sqlite3_io_methods inst_io_methods = {
212 1, /* iVersion */
213 instClose, /* xClose */
214 instRead, /* xRead */
215 instWrite, /* xWrite */
216 instTruncate, /* xTruncate */
217 instSync, /* xSync */
218 instFileSize, /* xFileSize */
219 instLock, /* xLock */
220 instUnlock, /* xUnlock */
221 instCheckReservedLock, /* xCheckReservedLock */
222 instFileControl, /* xFileControl */
223 instSectorSize, /* xSectorSize */
224 instDeviceCharacteristics /* xDeviceCharacteristics */
225 };
226
227 /*
228 ** hwtime.h contains inline assembler code for implementing
229 ** high-performance timing routines.
230 */
231 #include "hwtime.h"
232
233 #define OS_TIME_IO(eEvent, A, B, Call) { \
234 inst_file *p = (inst_file *)pFile; \
235 InstVfs *pInstVfs = p->pInstVfs; \
236 int rc; \
237 sqlite_uint64 t = sqlite3Hwtime(); \
238 rc = Call; \
239 t = sqlite3Hwtime() - t; \
240 pInstVfs->aTime[eEvent] += t; \
241 pInstVfs->aCount[eEvent] += 1; \
242 if( pInstVfs->xCall ){ \
243 pInstVfs->xCall( \
244 pInstVfs->pClient,eEvent,p->iFileId,t,rc,p->zName,p->flags,A,B \
245 ); \
246 } \
247 return rc; \
248 }
249
250 #define OS_TIME_VFS(eEvent, Z, flags, A, B, Call) { \
251 InstVfs *pInstVfs = (InstVfs *)pVfs; \
252 int rc; \
253 sqlite_uint64 t = sqlite3Hwtime(); \
254 rc = Call; \
255 t = sqlite3Hwtime() - t; \
256 pInstVfs->aTime[eEvent] += t; \
257 pInstVfs->aCount[eEvent] += 1; \
258 if( pInstVfs->xCall ){ \
259 pInstVfs->xCall(pInstVfs->pClient,eEvent,0, t, rc, Z, flags, A, B); \
260 } \
261 return rc; \
262 }
263
264 /*
265 ** Close an inst-file.
266 */
267 static int instClose(sqlite3_file *pFile){
268 OS_TIME_IO(OS_CLOSE, 0, 0,
269 (p->pReal->pMethods ? p->pReal->pMethods->xClose(p->pReal) : SQLITE_OK)
270 );
271 }
272
273 /*
274 ** Read data from an inst-file.
275 */
276 static int instRead(
277 sqlite3_file *pFile,
278 void *zBuf,
279 int iAmt,
280 sqlite_int64 iOfst
281 ){
282 sqlite3_vfs *pVfs = (sqlite3_vfs *)(((inst_file *)pFile)->pInstVfs);
283 OS_TIME_IO(OS_READ, iAmt, (binarylog_blob(pVfs, zBuf, iAmt, 1), iOfst),
284 p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst)
285 );
286 }
287
288 /*
289 ** Write data to an inst-file.
290 */
291 static int instWrite(
292 sqlite3_file *pFile,
293 const void *z,
294 int iAmt,
295 sqlite_int64 iOfst
296 ){
297 sqlite3_vfs *pVfs = (sqlite3_vfs *)(((inst_file *)pFile)->pInstVfs);
298 binarylog_blob(pVfs, z, iAmt, 1);
299 OS_TIME_IO(OS_WRITE, iAmt, iOfst,
300 p->pReal->pMethods->xWrite(p->pReal, z, iAmt, iOfst)
301 );
302 }
303
304 /*
305 ** Truncate an inst-file.
306 */
307 static int instTruncate(sqlite3_file *pFile, sqlite_int64 size){
308 OS_TIME_IO(OS_TRUNCATE, 0, (int)size,
309 p->pReal->pMethods->xTruncate(p->pReal, size)
310 );
311 }
312
313 /*
314 ** Sync an inst-file.
315 */
316 static int instSync(sqlite3_file *pFile, int flags){
317 OS_TIME_IO(OS_SYNC, flags, 0, p->pReal->pMethods->xSync(p->pReal, flags));
318 }
319
320 /*
321 ** Return the current file-size of an inst-file.
322 */
323 static int instFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
324 OS_TIME_IO(OS_FILESIZE, (int)(*pSize), 0,
325 p->pReal->pMethods->xFileSize(p->pReal, pSize)
326 );
327 }
328
329 /*
330 ** Lock an inst-file.
331 */
332 static int instLock(sqlite3_file *pFile, int eLock){
333 OS_TIME_IO(OS_LOCK, eLock, 0, p->pReal->pMethods->xLock(p->pReal, eLock));
334 }
335
336 /*
337 ** Unlock an inst-file.
338 */
339 static int instUnlock(sqlite3_file *pFile, int eLock){
340 OS_TIME_IO(OS_UNLOCK, eLock, 0, p->pReal->pMethods->xUnlock(p->pReal, eLock));
341 }
342
343 /*
344 ** Check if another file-handle holds a RESERVED lock on an inst-file.
345 */
346 static int instCheckReservedLock(sqlite3_file *pFile, int *pResOut){
347 OS_TIME_IO(OS_CHECKRESERVEDLOCK, 0, 0,
348 p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut)
349 );
350 }
351
352 /*
353 ** File control method. For custom operations on an inst-file.
354 */
355 static int instFileControl(sqlite3_file *pFile, int op, void *pArg){
356 OS_TIME_IO(OS_FILECONTROL, 0, 0, p->pReal->pMethods->xFileControl(p->pReal, op , pArg));
357 }
358
359 /*
360 ** Return the sector-size in bytes for an inst-file.
361 */
362 static int instSectorSize(sqlite3_file *pFile){
363 OS_TIME_IO(OS_SECTORSIZE, 0, 0, p->pReal->pMethods->xSectorSize(p->pReal));
364 }
365
366 /*
367 ** Return the device characteristic flags supported by an inst-file.
368 */
369 static int instDeviceCharacteristics(sqlite3_file *pFile){
370 OS_TIME_IO(OS_DEVCHAR, 0, 0, p->pReal->pMethods->xDeviceCharacteristics(p->pRe al));
371 }
372
373 /*
374 ** Open an inst file handle.
375 */
376 static int instOpen(
377 sqlite3_vfs *pVfs,
378 const char *zName,
379 sqlite3_file *pFile,
380 int flags,
381 int *pOutFlags
382 ){
383 inst_file *p = (inst_file *)pFile;
384 pFile->pMethods = &inst_io_methods;
385 p->pReal = (sqlite3_file *)&p[1];
386 p->pInstVfs = (InstVfs *)pVfs;
387 p->zName = zName;
388 p->flags = flags;
389 p->iFileId = ++p->pInstVfs->iNextFileId;
390
391 binarylog_blob(pVfs, zName, -1, 0);
392 OS_TIME_VFS(OS_OPEN, zName, flags, p->iFileId, 0,
393 REALVFS(pVfs)->xOpen(REALVFS(pVfs), zName, p->pReal, flags, pOutFlags)
394 );
395 }
396
397 /*
398 ** Delete the file located at zPath. If the dirSync argument is true,
399 ** ensure the file-system modifications are synced to disk before
400 ** returning.
401 */
402 static int instDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
403 binarylog_blob(pVfs, zPath, -1, 0);
404 OS_TIME_VFS(OS_DELETE, zPath, 0, dirSync, 0,
405 REALVFS(pVfs)->xDelete(REALVFS(pVfs), zPath, dirSync)
406 );
407 }
408
409 /*
410 ** Test for access permissions. Return true if the requested permission
411 ** is available, or false otherwise.
412 */
413 static int instAccess(
414 sqlite3_vfs *pVfs,
415 const char *zPath,
416 int flags,
417 int *pResOut
418 ){
419 binarylog_blob(pVfs, zPath, -1, 0);
420 OS_TIME_VFS(OS_ACCESS, zPath, 0, flags, *pResOut,
421 REALVFS(pVfs)->xAccess(REALVFS(pVfs), zPath, flags, pResOut)
422 );
423 }
424
425 /*
426 ** Populate buffer zOut with the full canonical pathname corresponding
427 ** to the pathname in zPath. zOut is guaranteed to point to a buffer
428 ** of at least (INST_MAX_PATHNAME+1) bytes.
429 */
430 static int instFullPathname(
431 sqlite3_vfs *pVfs,
432 const char *zPath,
433 int nOut,
434 char *zOut
435 ){
436 OS_TIME_VFS( OS_FULLPATHNAME, zPath, 0, 0, 0,
437 REALVFS(pVfs)->xFullPathname(REALVFS(pVfs), zPath, nOut, zOut);
438 );
439 }
440
441 /*
442 ** Open the dynamic library located at zPath and return a handle.
443 */
444 static void *instDlOpen(sqlite3_vfs *pVfs, const char *zPath){
445 return REALVFS(pVfs)->xDlOpen(REALVFS(pVfs), zPath);
446 }
447
448 /*
449 ** Populate the buffer zErrMsg (size nByte bytes) with a human readable
450 ** utf-8 string describing the most recent error encountered associated
451 ** with dynamic libraries.
452 */
453 static void instDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
454 REALVFS(pVfs)->xDlError(REALVFS(pVfs), nByte, zErrMsg);
455 }
456
457 /*
458 ** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
459 */
460 static void (*instDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
461 return REALVFS(pVfs)->xDlSym(REALVFS(pVfs), p, zSym);
462 }
463
464 /*
465 ** Close the dynamic library handle pHandle.
466 */
467 static void instDlClose(sqlite3_vfs *pVfs, void *pHandle){
468 REALVFS(pVfs)->xDlClose(REALVFS(pVfs), pHandle);
469 }
470
471 /*
472 ** Populate the buffer pointed to by zBufOut with nByte bytes of
473 ** random data.
474 */
475 static int instRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
476 OS_TIME_VFS( OS_RANDOMNESS, 0, 0, nByte, 0,
477 REALVFS(pVfs)->xRandomness(REALVFS(pVfs), nByte, zBufOut);
478 );
479 }
480
481 /*
482 ** Sleep for nMicro microseconds. Return the number of microseconds
483 ** actually slept.
484 */
485 static int instSleep(sqlite3_vfs *pVfs, int nMicro){
486 OS_TIME_VFS( OS_SLEEP, 0, 0, nMicro, 0,
487 REALVFS(pVfs)->xSleep(REALVFS(pVfs), nMicro)
488 );
489 }
490
491 /*
492 ** Return the current time as a Julian Day number in *pTimeOut.
493 */
494 static int instCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
495 OS_TIME_VFS( OS_CURRENTTIME, 0, 0, 0, 0,
496 REALVFS(pVfs)->xCurrentTime(REALVFS(pVfs), pTimeOut)
497 );
498 }
499
500 sqlite3_vfs *sqlite3_instvfs_create(const char *zName, const char *zParent){
501 int nByte;
502 InstVfs *p;
503 sqlite3_vfs *pParent;
504
505 pParent = sqlite3_vfs_find(zParent);
506 if( !pParent ){
507 return 0;
508 }
509
510 nByte = strlen(zName) + 1 + sizeof(InstVfs);
511 p = (InstVfs *)sqlite3_malloc(nByte);
512 if( p ){
513 char *zCopy = (char *)&p[1];
514 memset(p, 0, nByte);
515 memcpy(p, &inst_vfs, sizeof(sqlite3_vfs));
516 p->pVfs = pParent;
517 memcpy(zCopy, zName, strlen(zName));
518 p->base.zName = (const char *)zCopy;
519 p->base.szOsFile += pParent->szOsFile;
520 sqlite3_vfs_register((sqlite3_vfs *)p, 0);
521 }
522
523 return (sqlite3_vfs *)p;
524 }
525
526 void sqlite3_instvfs_configure(
527 sqlite3_vfs *pVfs,
528 void (*xCall)(
529 void*,
530 int, /* File id */
531 int, /* Event code */
532 sqlite3_int64,
533 int, /* Return code */
534 const char*, /* File name */
535 int,
536 int,
537 sqlite3_int64
538 ),
539 void *pClient,
540 void (*xDel)(void *)
541 ){
542 InstVfs *p = (InstVfs *)pVfs;
543 assert( pVfs->xOpen==instOpen );
544 if( p->xDel ){
545 p->xDel(p->pClient);
546 }
547 p->xCall = xCall;
548 p->xDel = xDel;
549 p->pClient = pClient;
550 }
551
552 void sqlite3_instvfs_destroy(sqlite3_vfs *pVfs){
553 if( pVfs ){
554 sqlite3_vfs_unregister(pVfs);
555 sqlite3_instvfs_configure(pVfs, 0, 0, 0);
556 sqlite3_free(pVfs);
557 }
558 }
559
560 void sqlite3_instvfs_reset(sqlite3_vfs *pVfs){
561 InstVfs *p = (InstVfs *)pVfs;
562 assert( pVfs->xOpen==instOpen );
563 memset(p->aTime, 0, sizeof(sqlite3_int64)*OS_NUMEVENTS);
564 memset(p->aCount, 0, sizeof(int)*OS_NUMEVENTS);
565 }
566
567 const char *sqlite3_instvfs_name(int eEvent){
568 const char *zEvent = 0;
569
570 switch( eEvent ){
571 case OS_CLOSE: zEvent = "xClose"; break;
572 case OS_READ: zEvent = "xRead"; break;
573 case OS_WRITE: zEvent = "xWrite"; break;
574 case OS_TRUNCATE: zEvent = "xTruncate"; break;
575 case OS_SYNC: zEvent = "xSync"; break;
576 case OS_FILESIZE: zEvent = "xFilesize"; break;
577 case OS_LOCK: zEvent = "xLock"; break;
578 case OS_UNLOCK: zEvent = "xUnlock"; break;
579 case OS_CHECKRESERVEDLOCK: zEvent = "xCheckReservedLock"; break;
580 case OS_FILECONTROL: zEvent = "xFileControl"; break;
581 case OS_SECTORSIZE: zEvent = "xSectorSize"; break;
582 case OS_DEVCHAR: zEvent = "xDeviceCharacteristics"; break;
583 case OS_OPEN: zEvent = "xOpen"; break;
584 case OS_DELETE: zEvent = "xDelete"; break;
585 case OS_ACCESS: zEvent = "xAccess"; break;
586 case OS_FULLPATHNAME: zEvent = "xFullPathname"; break;
587 case OS_RANDOMNESS: zEvent = "xRandomness"; break;
588 case OS_SLEEP: zEvent = "xSleep"; break;
589 case OS_CURRENTTIME: zEvent = "xCurrentTime"; break;
590 }
591
592 return zEvent;
593 }
594
595 void sqlite3_instvfs_get(
596 sqlite3_vfs *pVfs,
597 int eEvent,
598 const char **pzEvent,
599 sqlite3_int64 *pnClick,
600 int *pnCall
601 ){
602 InstVfs *p = (InstVfs *)pVfs;
603 assert( pVfs->xOpen==instOpen );
604 if( eEvent<1 || eEvent>=OS_NUMEVENTS ){
605 *pzEvent = 0;
606 *pnClick = 0;
607 *pnCall = 0;
608 return;
609 }
610
611 *pzEvent = sqlite3_instvfs_name(eEvent);
612 *pnClick = p->aTime[eEvent];
613 *pnCall = p->aCount[eEvent];
614 }
615
616 #define BINARYLOG_BUFFERSIZE 8192
617
618 struct InstVfsBinaryLog {
619 int nBuf;
620 char *zBuf;
621 sqlite3_int64 iOffset;
622 int log_data;
623 sqlite3_file *pOut;
624 char *zOut; /* Log file name */
625 };
626 typedef struct InstVfsBinaryLog InstVfsBinaryLog;
627
628 static void put32bits(unsigned char *p, unsigned int v){
629 p[0] = v>>24;
630 p[1] = v>>16;
631 p[2] = v>>8;
632 p[3] = v;
633 }
634
635 static void binarylog_flush(InstVfsBinaryLog *pLog){
636 sqlite3_file *pFile = pLog->pOut;
637
638 #ifdef SQLITE_TEST
639 extern int sqlite3_io_error_pending;
640 extern int sqlite3_io_error_persist;
641 extern int sqlite3_diskfull_pending;
642
643 int pending = sqlite3_io_error_pending;
644 int persist = sqlite3_io_error_persist;
645 int diskfull = sqlite3_diskfull_pending;
646
647 sqlite3_io_error_pending = 0;
648 sqlite3_io_error_persist = 0;
649 sqlite3_diskfull_pending = 0;
650 #endif
651
652 pFile->pMethods->xWrite(pFile, pLog->zBuf, pLog->nBuf, pLog->iOffset);
653 pLog->iOffset += pLog->nBuf;
654 pLog->nBuf = 0;
655
656 #ifdef SQLITE_TEST
657 sqlite3_io_error_pending = pending;
658 sqlite3_io_error_persist = persist;
659 sqlite3_diskfull_pending = diskfull;
660 #endif
661 }
662
663 static void binarylog_xcall(
664 void *p,
665 int eEvent,
666 int iFileId,
667 sqlite3_int64 nClick,
668 int return_code,
669 const char *zName,
670 int flags,
671 int nByte,
672 sqlite3_int64 iOffset
673 ){
674 InstVfsBinaryLog *pLog = (InstVfsBinaryLog *)p;
675 unsigned char *zRec;
676 if( (28+pLog->nBuf)>BINARYLOG_BUFFERSIZE ){
677 binarylog_flush(pLog);
678 }
679 zRec = (unsigned char *)&pLog->zBuf[pLog->nBuf];
680 put32bits(&zRec[0], eEvent);
681 put32bits(&zRec[4], (int)iFileId);
682 put32bits(&zRec[8], (int)nClick);
683 put32bits(&zRec[12], return_code);
684 put32bits(&zRec[16], flags);
685 put32bits(&zRec[20], nByte);
686 put32bits(&zRec[24], (int)iOffset);
687 pLog->nBuf += 28;
688 }
689
690 static void binarylog_xdel(void *p){
691 /* Close the log file and free the memory allocated for the
692 ** InstVfsBinaryLog structure.
693 */
694 InstVfsBinaryLog *pLog = (InstVfsBinaryLog *)p;
695 sqlite3_file *pFile = pLog->pOut;
696 if( pLog->nBuf ){
697 binarylog_flush(pLog);
698 }
699 pFile->pMethods->xClose(pFile);
700 sqlite3_free(pLog->pOut);
701 sqlite3_free(pLog->zBuf);
702 sqlite3_free(pLog);
703 }
704
705 static void binarylog_blob(
706 sqlite3_vfs *pVfs,
707 const char *zBlob,
708 int nBlob,
709 int isBinary
710 ){
711 InstVfsBinaryLog *pLog;
712 InstVfs *pInstVfs = (InstVfs *)pVfs;
713
714 if( pVfs->xOpen!=instOpen || pInstVfs->xCall!=binarylog_xcall ){
715 return;
716 }
717 pLog = (InstVfsBinaryLog *)pInstVfs->pClient;
718 if( zBlob && (!isBinary || pLog->log_data) ){
719 unsigned char *zRec;
720 int nWrite;
721
722 if( nBlob<0 ){
723 nBlob = strlen(zBlob);
724 }
725 nWrite = nBlob + 28;
726
727 if( (nWrite+pLog->nBuf)>BINARYLOG_BUFFERSIZE ){
728 binarylog_flush(pLog);
729 }
730
731 zRec = (unsigned char *)&pLog->zBuf[pLog->nBuf];
732 memset(zRec, 0, nWrite);
733 put32bits(&zRec[0], BINARYLOG_STRING);
734 put32bits(&zRec[4], (int)nBlob);
735 put32bits(&zRec[8], (int)isBinary);
736 memcpy(&zRec[28], zBlob, nBlob);
737 pLog->nBuf += nWrite;
738 }
739 }
740
741 void sqlite3_instvfs_binarylog_call(
742 sqlite3_vfs *pVfs,
743 int eEvent,
744 sqlite3_int64 nClick,
745 int return_code,
746 const char *zString
747 ){
748 InstVfs *pInstVfs = (InstVfs *)pVfs;
749 InstVfsBinaryLog *pLog = (InstVfsBinaryLog *)pInstVfs->pClient;
750
751 if( zString ){
752 binarylog_blob(pVfs, zString, -1, 0);
753 }
754 binarylog_xcall(pLog, eEvent, 0, nClick, return_code, 0, 0, 0, 0);
755 }
756
757 void sqlite3_instvfs_binarylog_marker(
758 sqlite3_vfs *pVfs,
759 const char *zMarker
760 ){
761 InstVfs *pInstVfs = (InstVfs *)pVfs;
762 InstVfsBinaryLog *pLog = (InstVfsBinaryLog *)pInstVfs->pClient;
763 binarylog_blob(pVfs, zMarker, -1, 0);
764 binarylog_xcall(pLog, BINARYLOG_MARKER, 0, 0, 0, 0, 0, 0, 0);
765 }
766
767 sqlite3_vfs *sqlite3_instvfs_binarylog(
768 const char *zVfs,
769 const char *zParentVfs,
770 const char *zLog,
771 int log_data
772 ){
773 InstVfsBinaryLog *p;
774 sqlite3_vfs *pVfs;
775 sqlite3_vfs *pParent;
776 int nByte;
777 int flags;
778 int rc;
779
780 pParent = sqlite3_vfs_find(zParentVfs);
781 if( !pParent ){
782 return 0;
783 }
784
785 nByte = sizeof(InstVfsBinaryLog) + pParent->mxPathname+1;
786 p = (InstVfsBinaryLog *)sqlite3_malloc(nByte);
787 memset(p, 0, nByte);
788 p->zBuf = sqlite3_malloc(BINARYLOG_BUFFERSIZE);
789 p->zOut = (char *)&p[1];
790 p->pOut = (sqlite3_file *)sqlite3_malloc(pParent->szOsFile);
791 p->log_data = log_data;
792 pParent->xFullPathname(pParent, zLog, pParent->mxPathname, p->zOut);
793 flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MASTER_JOURNAL;
794 pParent->xDelete(pParent, p->zOut, 0);
795 rc = pParent->xOpen(pParent, p->zOut, p->pOut, flags, &flags);
796 if( rc==SQLITE_OK ){
797 memcpy(p->zBuf, "sqlite_ostrace1.....", 20);
798 p->iOffset = 0;
799 p->nBuf = 20;
800 }
801 if( rc ){
802 binarylog_xdel(p);
803 return 0;
804 }
805
806 pVfs = sqlite3_instvfs_create(zVfs, zParentVfs);
807 if( pVfs ){
808 sqlite3_instvfs_configure(pVfs, binarylog_xcall, p, binarylog_xdel);
809 }
810
811 return pVfs;
812 }
813 #endif /* SQLITE_ENABLE_INSTVFS */
814
815 /**************************************************************************
816 ***************************************************************************
817 ** Tcl interface starts here.
818 */
819 #if SQLITE_TEST
820
821 #include <tcl.h>
822
823 #ifdef SQLITE_ENABLE_INSTVFS
824 struct InstVfsCall {
825 Tcl_Interp *interp;
826 Tcl_Obj *pScript;
827 };
828 typedef struct InstVfsCall InstVfsCall;
829
830 static void test_instvfs_xcall(
831 void *p,
832 int eEvent,
833 int iFileId,
834 sqlite3_int64 nClick,
835 int return_code,
836 const char *zName,
837 int flags,
838 int nByte,
839 sqlite3_int64 iOffset
840 ){
841 int rc;
842 InstVfsCall *pCall = (InstVfsCall *)p;
843 Tcl_Obj *pObj = Tcl_DuplicateObj( pCall->pScript);
844 const char *zEvent = sqlite3_instvfs_name(eEvent);
845
846 Tcl_IncrRefCount(pObj);
847 Tcl_ListObjAppendElement(0, pObj, Tcl_NewStringObj(zEvent, -1));
848 Tcl_ListObjAppendElement(0, pObj, Tcl_NewWideIntObj(nClick));
849 Tcl_ListObjAppendElement(0, pObj, Tcl_NewStringObj(zName, -1));
850 Tcl_ListObjAppendElement(0, pObj, Tcl_NewIntObj(nByte));
851 Tcl_ListObjAppendElement(0, pObj, Tcl_NewWideIntObj(iOffset));
852
853 rc = Tcl_EvalObjEx(pCall->interp, pObj, TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT);
854 if( rc ){
855 Tcl_BackgroundError(pCall->interp);
856 }
857 Tcl_DecrRefCount(pObj);
858 }
859
860 static void test_instvfs_xdel(void *p){
861 InstVfsCall *pCall = (InstVfsCall *)p;
862 Tcl_DecrRefCount(pCall->pScript);
863 sqlite3_free(pCall);
864 }
865
866 static int test_sqlite3_instvfs(
867 void * clientData,
868 Tcl_Interp *interp,
869 int objc,
870 Tcl_Obj *CONST objv[]
871 ){
872 static const char *IV_strs[] =
873 { "create", "destroy", "reset", "report", "configure", "binary log", "marker", 0 };
874 enum IV_enum { IV_CREATE, IV_DESTROY, IV_RESET, IV_REPORT, IV_CONFIGURE, IV_BI NARYLOG, IV_MARKER };
875 int iSub;
876
877 if( objc<2 ){
878 Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND ...");
879 }
880 if( Tcl_GetIndexFromObj(interp, objv[1], IV_strs, "sub-command", 0, &iSub) ){
881 return TCL_ERROR;
882 }
883
884 switch( (enum IV_enum)iSub ){
885 case IV_CREATE: {
886 char *zParent = 0;
887 sqlite3_vfs *p;
888 int isDefault = 0;
889 if( objc>2 && 0==strcmp("-default", Tcl_GetString(objv[2])) ){
890 isDefault = 1;
891 }
892 if( (objc-isDefault)!=4 && (objc-isDefault)!=3 ){
893 Tcl_WrongNumArgs(interp, 2, objv, "?-default? NAME ?PARENT-VFS?");
894 return TCL_ERROR;
895 }
896 if( objc==(4+isDefault) ){
897 zParent = Tcl_GetString(objv[3+isDefault]);
898 }
899 p = sqlite3_instvfs_create(Tcl_GetString(objv[2+isDefault]), zParent);
900 if( !p ){
901 Tcl_AppendResult(interp, "error creating vfs ", 0);
902 return TCL_ERROR;
903 }
904 if( isDefault ){
905 sqlite3_vfs_register(p, 1);
906 }
907 Tcl_SetObjResult(interp, objv[2]);
908 break;
909 }
910 case IV_BINARYLOG: {
911 char *zName = 0;
912 char *zLog = 0;
913 char *zParent = 0;
914 sqlite3_vfs *p;
915 int isDefault = 0;
916 int isLogdata = 0;
917 int argbase = 2;
918
919 for(argbase=2; argbase<(objc-2); argbase++){
920 if( 0==strcmp("-default", Tcl_GetString(objv[argbase])) ){
921 isDefault = 1;
922 }
923 else if( 0==strcmp("-parent", Tcl_GetString(objv[argbase])) ){
924 argbase++;
925 zParent = Tcl_GetString(objv[argbase]);
926 }
927 else if( 0==strcmp("-logdata", Tcl_GetString(objv[argbase])) ){
928 isLogdata = 1;
929 }else{
930 break;
931 }
932 }
933
934 if( (objc-argbase)!=2 ){
935 Tcl_WrongNumArgs(
936 interp, 2, objv, "?-default? ?-parent VFS? ?-logdata? NAME LOGFILE"
937 );
938 return TCL_ERROR;
939 }
940 zName = Tcl_GetString(objv[argbase]);
941 zLog = Tcl_GetString(objv[argbase+1]);
942 p = sqlite3_instvfs_binarylog(zName, zParent, zLog, isLogdata);
943 if( !p ){
944 Tcl_AppendResult(interp, "error creating vfs ", 0);
945 return TCL_ERROR;
946 }
947 if( isDefault ){
948 sqlite3_vfs_register(p, 1);
949 }
950 Tcl_SetObjResult(interp, objv[2]);
951 break;
952 }
953
954 case IV_MARKER: {
955 sqlite3_vfs *p;
956 if( objc!=4 ){
957 Tcl_WrongNumArgs(interp, 2, objv, "VFS MARKER");
958 return TCL_ERROR;
959 }
960 p = sqlite3_vfs_find(Tcl_GetString(objv[2]));
961 if( !p || p->xOpen!=instOpen ){
962 Tcl_AppendResult(interp, "no such vfs: ", Tcl_GetString(objv[2]), 0);
963 return TCL_ERROR;
964 }
965 sqlite3_instvfs_binarylog_marker(p, Tcl_GetString(objv[3]));
966 Tcl_ResetResult(interp);
967 break;
968 }
969
970 case IV_CONFIGURE: {
971 InstVfsCall *pCall;
972
973 sqlite3_vfs *p;
974 if( objc!=4 ){
975 Tcl_WrongNumArgs(interp, 2, objv, "NAME SCRIPT");
976 return TCL_ERROR;
977 }
978 p = sqlite3_vfs_find(Tcl_GetString(objv[2]));
979 if( !p || p->xOpen!=instOpen ){
980 Tcl_AppendResult(interp, "no such vfs: ", Tcl_GetString(objv[2]), 0);
981 return TCL_ERROR;
982 }
983
984 if( strlen(Tcl_GetString(objv[3])) ){
985 pCall = (InstVfsCall *)sqlite3_malloc(sizeof(InstVfsCall));
986 pCall->interp = interp;
987 pCall->pScript = Tcl_DuplicateObj(objv[3]);
988 Tcl_IncrRefCount(pCall->pScript);
989 sqlite3_instvfs_configure(p,
990 test_instvfs_xcall, (void *)pCall, test_instvfs_xdel
991 );
992 }else{
993 sqlite3_instvfs_configure(p, 0, 0, 0);
994 }
995 break;
996 }
997
998 case IV_REPORT:
999 case IV_DESTROY:
1000 case IV_RESET: {
1001 sqlite3_vfs *p;
1002 if( objc!=3 ){
1003 Tcl_WrongNumArgs(interp, 2, objv, "NAME");
1004 return TCL_ERROR;
1005 }
1006 p = sqlite3_vfs_find(Tcl_GetString(objv[2]));
1007 if( !p || p->xOpen!=instOpen ){
1008 Tcl_AppendResult(interp, "no such vfs: ", Tcl_GetString(objv[2]), 0);
1009 return TCL_ERROR;
1010 }
1011
1012 if( ((enum IV_enum)iSub)==IV_DESTROY ){
1013 sqlite3_instvfs_destroy(p);
1014 }
1015 if( ((enum IV_enum)iSub)==IV_RESET ){
1016 sqlite3_instvfs_reset(p);
1017 }
1018 if( ((enum IV_enum)iSub)==IV_REPORT ){
1019 int ii;
1020 Tcl_Obj *pRet = Tcl_NewObj();
1021
1022 const char *zName = (char *)1;
1023 sqlite3_int64 nClick;
1024 int nCall;
1025 for(ii=1; zName; ii++){
1026 sqlite3_instvfs_get(p, ii, &zName, &nClick, &nCall);
1027 if( zName ){
1028 Tcl_Obj *pElem = Tcl_NewObj();
1029 Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj(zName, -1));
1030 Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(nCall));
1031 Tcl_ListObjAppendElement(0, pElem, Tcl_NewWideIntObj(nClick));
1032 Tcl_ListObjAppendElement(0, pRet, pElem);
1033 }
1034 }
1035
1036 Tcl_SetObjResult(interp, pRet);
1037 }
1038
1039 break;
1040 }
1041 }
1042
1043 return TCL_OK;
1044 }
1045 #endif /* SQLITE_ENABLE_INSTVFS */
1046
1047 /* Alternative implementation of sqlite3_instvfs when the real
1048 ** implementation is unavailable.
1049 */
1050 #ifndef SQLITE_ENABLE_INSTVFS
1051 static int test_sqlite3_instvfs(
1052 void * clientData,
1053 Tcl_Interp *interp,
1054 int objc,
1055 Tcl_Obj *CONST objv[]
1056 ){
1057 Tcl_AppendResult(interp,
1058 "not compiled with -DSQLITE_ENABLE_INSTVFS; sqlite3_instvfs is "
1059 "unavailable", (char*)0);
1060 return TCL_ERROR;
1061 }
1062 #endif /* !defined(SQLITE_ENABLE_INSTVFS) */
1063
1064 int SqlitetestOsinst_Init(Tcl_Interp *interp){
1065 Tcl_CreateObjCommand(interp, "sqlite3_instvfs", test_sqlite3_instvfs, 0, 0);
1066 return TCL_OK;
1067 }
1068
1069 #endif /* SQLITE_TEST */
OLDNEW
« no previous file with comments | « third_party/sqlite/src/test_onefile.c ('k') | third_party/sqlite/src/test_pcache.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698