Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add a logfile option to test_osinst.c. (CVS 4994) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
f97d89458259978b7b1b5c5e5a0d19ca |
User & Date: | danielk1977 2008-04-12 10:53:11.000 |
Context
2008-04-12
| ||
11:30 | Modify test_osinst.c so that it only uses public interfaces. (CVS 4995) (check-in: 3866a5da2b user: danielk1977 tags: trunk) | |
10:53 | Add a logfile option to test_osinst.c. (CVS 4994) (check-in: f97d894582 user: danielk1977 tags: trunk) | |
2008-04-11
| ||
21:20 | Add the speedtest8inst1.c program for running speed tests with an instrumented VFS. (CVS 4993) (check-in: baa8056c67 user: drh tags: trunk) | |
Changes
Changes to src/test_osinst.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ****************************************************************************** ** ** This file contains the implementation of an SQLite vfs wrapper that ** adds instrumentation to all vfs and file methods. C and Tcl interfaces ** are provided to control the instrumentation. */ | < | > > | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | ** ****************************************************************************** ** ** This file contains the implementation of an SQLite vfs wrapper that ** adds instrumentation to all vfs and file methods. C and Tcl interfaces ** are provided to control the instrumentation. */ /* ** C interface: ** ** sqlite3_instvfs_create() ** sqlite3_instvfs_destroy() ** sqlite3_instvfs_configure() ** ** sqlite3_instvfs_reset() ** sqlite3_instvfs_get() ** ** sqlite3_instvfs_binarylog ** ** Tcl interface (omitted if SQLITE_TEST is not set): ** ** sqlite3_instvfs create NAME ?PARENT? ** ** Create and register new vfs called $NAME, which is a wrapper around ** the existing vfs $PARENT. If the PARENT argument is omitted, the ** new vfs is a wrapper around the current default vfs. ** |
︙ | ︙ | |||
87 88 89 90 91 92 93 | /* ** Maximum pathname length supported by the inst backend. */ #define INST_MAX_PATHNAME 512 /* File methods */ | > > > | | | | | | > > | | | | | | < < | | | | < < < < | > | 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | /* ** Maximum pathname length supported by the inst backend. */ #define INST_MAX_PATHNAME 512 /* File methods */ /* Vfs methods */ #define OS_ACCESS 1 #define OS_CHECKRESERVEDLOCK 2 #define OS_CLOSE 3 #define OS_CURRENTTIME 4 #define OS_DELETE 5 #define OS_DEVCHAR 6 #define OS_FILECONTROL 7 #define OS_FILESIZE 8 #define OS_FULLPATHNAME 9 #define OS_GETTEMPNAME 10 #define OS_LOCK 11 #define OS_OPEN 12 #define OS_RANDOMNESS 13 #define OS_READ 14 #define OS_SECTORSIZE 15 #define OS_SLEEP 16 #define OS_SYNC 17 #define OS_TRUNCATE 18 #define OS_UNLOCK 19 #define OS_WRITE 20 #define OS_NUMEVENTS 21 struct InstVfs { sqlite3_vfs base; sqlite3_vfs *pVfs; void *pClient; void (*xDel)(void *); void (*xCall)(void *, int, sqlite3_int64, const char *, int, int, sqlite3_int64); /* Counters */ i64 aTime[OS_NUMEVENTS]; int aCount[OS_NUMEVENTS]; }; typedef struct InstVfs InstVfs; #define REALVFS(p) (((InstVfs *)(p))->pVfs) typedef struct inst_file inst_file; struct inst_file { sqlite3_file base; sqlite3_file *pReal; InstVfs *pInstVfs; const char *zName; int flags; }; /* ** Method declarations for inst_file. */ static int instClose(sqlite3_file*); static int instRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); |
︙ | ︙ | |||
213 214 215 216 217 218 219 | ** The following routine only works on pentium-class processors. ** It uses the RDTSC opcode to read the cycle count value out of the ** processor and returns that value. This can be used for high-res ** profiling. */ #if defined(i386) || defined(__i386__) || defined(_M_IX86) __inline__ unsigned long long int hwtime(void){ | | > | < < | | | | 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 | ** The following routine only works on pentium-class processors. ** It uses the RDTSC opcode to read the cycle count value out of the ** processor and returns that value. This can be used for high-res ** profiling. */ #if defined(i386) || defined(__i386__) || defined(_M_IX86) __inline__ unsigned long long int hwtime(void){ unsigned int lo, hi; /* We cannot use "=A", since this would use %rax on x86_64 */ __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); return (unsigned long long int)hi << 32 | lo; } #else static unsigned long long int hwtime(void){ return 0; } #endif #define OS_TIME_IO(eEvent, A, B, Call) { \ inst_file *p = (inst_file *)pFile; \ InstVfs *pInstVfs = p->pInstVfs; \ int rc; \ i64 t = hwtime(); \ rc = Call; \ t = hwtime() - t; \ pInstVfs->aTime[eEvent] += t; \ pInstVfs->aCount[eEvent] += 1; \ if( pInstVfs->xCall ){ \ pInstVfs->xCall(pInstVfs->pClient, eEvent, t, p->zName, p->flags, A, B); \ } \ return rc; \ } #define OS_TIME_VFS(eEvent, Z, A, B, Call) { \ InstVfs *pInstVfs = (InstVfs *)pVfs; \ int rc; \ i64 t = hwtime(); \ rc = Call; \ t = hwtime() - t; \ pInstVfs->aTime[eEvent] += t; \ pInstVfs->aCount[eEvent] += 1; \ if( pInstVfs->xCall ){ \ pInstVfs->xCall(pInstVfs->pClient, eEvent, t, Z, 0, A, B); \ } \ return rc; \ } /* ** Close an inst-file. */ |
︙ | ︙ | |||
361 362 363 364 365 366 367 368 369 370 371 372 373 374 | int *pOutFlags ){ inst_file *p = (inst_file *)pFile; pFile->pMethods = &inst_io_methods; p->pReal = (sqlite3_file *)&p[1]; p->pInstVfs = (InstVfs *)pVfs; p->zName = zName; OS_TIME_VFS(OS_OPEN, zName, flags, 0, sqlite3OsOpen(REALVFS(pVfs), zName, p->pReal, flags, pOutFlags) ); } /* | > | 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 | int *pOutFlags ){ inst_file *p = (inst_file *)pFile; pFile->pMethods = &inst_io_methods; p->pReal = (sqlite3_file *)&p[1]; p->pInstVfs = (InstVfs *)pVfs; p->zName = zName; p->flags = flags; OS_TIME_VFS(OS_OPEN, zName, flags, 0, sqlite3OsOpen(REALVFS(pVfs), zName, p->pReal, flags, pOutFlags) ); } /* |
︙ | ︙ | |||
474 475 476 477 478 479 480 | */ static int instCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ OS_TIME_VFS( OS_CURRENTTIME, 0, 0, 0, sqlite3OsCurrentTime(REALVFS(pVfs), pTimeOut) ); } | | | 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 | */ static int instCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ OS_TIME_VFS( OS_CURRENTTIME, 0, 0, 0, sqlite3OsCurrentTime(REALVFS(pVfs), pTimeOut) ); } sqlite3_vfs *sqlite3_instvfs_create(const char *zName, const char *zParent){ int nByte; InstVfs *p; sqlite3_vfs *pParent; pParent = sqlite3_vfs_find(zParent); if( !pParent ){ return 0; |
︙ | ︙ | |||
502 503 504 505 506 507 508 | } return (sqlite3_vfs *)p; } void sqlite3_instvfs_configure( sqlite3_vfs *pVfs, | | | 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 | } return (sqlite3_vfs *)p; } void sqlite3_instvfs_configure( sqlite3_vfs *pVfs, void (*xCall)(void*, int, sqlite3_int64, const char*, int, int, i64), void *pClient, void (*xDel)(void *) ){ InstVfs *p = (InstVfs *)pVfs; assert( pVfs->xOpen==instOpen ); if( p->xDel ){ p->xDel(p->pClient); |
︙ | ︙ | |||
578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 | return; } *pzEvent = sqlite3_instvfs_name(eEvent); *pnClick = p->aTime[eEvent]; *pnCall = p->aCount[eEvent]; } /************************************************************************** *************************************************************************** ** Tcl interface starts here. */ #include <tcl.h> struct InstVfsCall { Tcl_Interp *interp; Tcl_Obj *pScript; }; typedef struct InstVfsCall InstVfsCall; static void test_instvfs_xcall( void *p, int eEvent, sqlite3_int64 nClick, const char *zName, int nByte, sqlite3_int64 iOffset ){ int rc; InstVfsCall *pCall = (InstVfsCall *)p; Tcl_Obj *pObj = Tcl_DuplicateObj( pCall->pScript); const char *zEvent = sqlite3_instvfs_name(eEvent); | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 | return; } *pzEvent = sqlite3_instvfs_name(eEvent); *pnClick = p->aTime[eEvent]; *pnCall = p->aCount[eEvent]; } #define BINARYLOG_BUFFERSIZE 1024 struct InstVfsBinaryLog { int nBuf; char *zBuf; sqlite3_int64 iOffset; sqlite3_file *pOut; }; typedef struct InstVfsBinaryLog InstVfsBinaryLog; static void put32bits(unsigned char *p, u32 v){ p[0] = v>>24; p[1] = v>>16; p[2] = v>>8; p[3] = v; } static void binarylog_xcall( void *p, int eEvent, sqlite3_int64 nClick, const char *zName, int flags, int nByte, sqlite3_int64 iOffset ){ InstVfsBinaryLog *pLog = (InstVfsBinaryLog *)p; unsigned char *zRec; if( (20+pLog->nBuf)>BINARYLOG_BUFFERSIZE ){ sqlite3_file *pFile = pLog->pOut; pFile->pMethods->xWrite(pFile, pLog->zBuf, pLog->nBuf, pLog->iOffset); pLog->iOffset += pLog->nBuf; pLog->nBuf = 0; } zRec = (unsigned char *)&pLog->zBuf[pLog->nBuf]; put32bits(&zRec[0], eEvent); put32bits(&zRec[4], (int)nClick); put32bits(&zRec[8], flags); put32bits(&zRec[12], nByte); put32bits(&zRec[16], (int)iOffset); pLog->nBuf += 20; } static void binarylog_xdel(void *p){ /* Close the log file and free the memory allocated for the ** InstVfsBinaryLog structure. */ InstVfsBinaryLog *pLog = (InstVfsBinaryLog *)p; sqlite3_file *pFile = pLog->pOut; if( pLog->nBuf ){ pFile->pMethods->xWrite(pFile, pLog->zBuf, pLog->nBuf, pLog->iOffset); } pFile->pMethods->xClose(pFile); sqlite3_free(pLog->zBuf); sqlite3_free(pLog); } sqlite3_vfs *sqlite3_instvfs_binarylog( const char *zVfs, const char *zParentVfs, const char *zLog ){ InstVfsBinaryLog *p; sqlite3_vfs *pVfs; sqlite3_vfs *pParent; int nByte; int flags; int rc; pParent = sqlite3_vfs_find(zParentVfs); if( !pParent ){ return 0; } nByte = sizeof(InstVfsBinaryLog) + pParent->szOsFile; p = (InstVfsBinaryLog *)sqlite3_malloc(nByte); memset(p, 0, nByte); p->zBuf = sqlite3_malloc(BINARYLOG_BUFFERSIZE); p->pOut = (sqlite3_file *)&p[1]; flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MASTER_JOURNAL; rc = pParent->xOpen(pParent, zLog, p->pOut, flags, &flags); if( rc==SQLITE_OK ){ rc = p->pOut->pMethods->xWrite(p->pOut, "sqlite_ostrace1.....", 20, 0); p->iOffset = 20; } if( rc ){ binarylog_xdel(p); return 0; } pVfs = sqlite3_instvfs_create(zVfs, zParentVfs); if( pVfs ){ sqlite3_instvfs_configure(pVfs, binarylog_xcall, p, binarylog_xdel); } return pVfs; } /************************************************************************** *************************************************************************** ** Tcl interface starts here. */ #if SQLITE_TEST #include <tcl.h> struct InstVfsCall { Tcl_Interp *interp; Tcl_Obj *pScript; }; typedef struct InstVfsCall InstVfsCall; static void test_instvfs_xcall( void *p, int eEvent, sqlite3_int64 nClick, const char *zName, int flags, int nByte, sqlite3_int64 iOffset ){ int rc; InstVfsCall *pCall = (InstVfsCall *)p; Tcl_Obj *pObj = Tcl_DuplicateObj( pCall->pScript); const char *zEvent = sqlite3_instvfs_name(eEvent); |
︙ | ︙ | |||
632 633 634 635 636 637 638 | static int test_sqlite3_instvfs( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ static const char *IV_strs[] = | | | | 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 | static int test_sqlite3_instvfs( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ static const char *IV_strs[] = { "create", "destroy", "reset", "report", "configure", "binarylog", 0 }; enum IV_enum { IV_CREATE, IV_DESTROY, IV_RESET, IV_REPORT, IV_CONFIGURE, IV_BINARYLOG }; int iSub; if( objc<2 ){ Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND ..."); } if( Tcl_GetIndexFromObj(interp, objv[1], IV_strs, "sub-command", 0, &iSub) ){ return TCL_ERROR; |
︙ | ︙ | |||
659 660 661 662 663 664 665 666 667 668 669 670 671 672 | Tcl_WrongNumArgs(interp, 2, objv, "?-default? NAME ?PARENT-VFS?"); return TCL_ERROR; } if( objc==(4+isDefault) ){ zParent = Tcl_GetString(objv[3+isDefault]); } p = sqlite3_instvfs_create(Tcl_GetString(objv[2+isDefault]), zParent); if( !p ){ Tcl_AppendResult(interp, "error creating vfs ", 0); return TCL_ERROR; } if( isDefault ){ sqlite3_vfs_register(p, 1); } | > > > > > > > > > > > > > > > > > > > > > > > > > | 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 | Tcl_WrongNumArgs(interp, 2, objv, "?-default? NAME ?PARENT-VFS?"); return TCL_ERROR; } if( objc==(4+isDefault) ){ zParent = Tcl_GetString(objv[3+isDefault]); } p = sqlite3_instvfs_create(Tcl_GetString(objv[2+isDefault]), zParent); if( !p ){ Tcl_AppendResult(interp, "error creating vfs ", 0); return TCL_ERROR; } if( isDefault ){ sqlite3_vfs_register(p, 1); } Tcl_SetObjResult(interp, objv[2]); break; } case IV_BINARYLOG: { char *zName = 0; char *zLog = 0; sqlite3_vfs *p; int isDefault = 0; if( objc>2 && 0==strcmp("-default", Tcl_GetString(objv[2])) ){ isDefault = 1; } if( (objc-isDefault)!=4 ){ Tcl_WrongNumArgs(interp, 2, objv, "?-default? NAME LOGFILE"); return TCL_ERROR; } zName = Tcl_GetString(objv[2+isDefault]); zLog = Tcl_GetString(objv[3+isDefault]); p = sqlite3_instvfs_binarylog(zName, 0, zLog); if( !p ){ Tcl_AppendResult(interp, "error creating vfs ", 0); return TCL_ERROR; } if( isDefault ){ sqlite3_vfs_register(p, 1); } |
︙ | ︙ |