/ Check-in [3866a5da]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Modify test_osinst.c so that it only uses public interfaces. (CVS 4995)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:3866a5da2bdcfafe956e1a9bf117f3277207de05
User & Date: danielk1977 2008-04-12 11:30:13
Context
2008-04-12
13:06
Remove all instances of sprintf() from the FTS modules. Ticket #3049. (CVS 4996) check-in: 062bf5d4 user: drh tags: trunk
11:30
Modify test_osinst.c so that it only uses public interfaces. (CVS 4995) check-in: 3866a5da user: danielk1977 tags: trunk
10:53
Add a logfile option to test_osinst.c. (CVS 4994) check-in: f97d8945 user: danielk1977 tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/test_osinst.c.

79
80
81
82
83
84
85
86

87
88
89
90
91
92
93
...
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
...
213
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
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
...
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
...
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
...
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
...
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
...
587
588
589
590
591
592
593

594
595
596
597
598
599
600
601
602
603
604
...
654
655
656
657
658
659
660
661
662
663
664
665

666

667
668
669
670
671
672
673
674
675
676
...
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
**         * The name of the method call - i.e. "xWrite",
**         * The total number of calls to the method (an integer).
**         * The aggregate time consumed by all calls to the method as
**           measured by hwtime() (an integer).
*/

#include "sqlite3.h"
#include "sqliteInt.h"


/*
** Maximum pathname length supported by the inst backend.
*/
#define INST_MAX_PATHNAME 512


................................................................................
  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;
................................................................................
/*
** 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.
*/
static int instClose(sqlite3_file *pFile){
  OS_TIME_IO(OS_CLOSE, 0, 0, sqlite3OsClose(p->pReal));
}

/*
** Read data from an inst-file.
*/
static int instRead(
  sqlite3_file *pFile, 
  void *zBuf, 
  int iAmt, 
  sqlite_int64 iOfst
){
  OS_TIME_IO(OS_READ, iAmt, iOfst, sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst));
}

/*
** Write data to an inst-file.
*/
static int instWrite(
  sqlite3_file *pFile,
  const void *z,
  int iAmt,
  sqlite_int64 iOfst
){
  OS_TIME_IO(OS_WRITE, iAmt, iOfst, sqlite3OsWrite(p->pReal, z, iAmt, iOfst));
}

/*
** Truncate an inst-file.
*/
static int instTruncate(sqlite3_file *pFile, sqlite_int64 size){
  OS_TIME_IO(OS_TRUNCATE, 0, size, sqlite3OsTruncate(p->pReal, size));
}

/*
** Sync an inst-file.
*/
static int instSync(sqlite3_file *pFile, int flags){
  OS_TIME_IO(OS_SYNC, flags, 0, sqlite3OsSync(p->pReal, flags));
}

/*
** Return the current file-size of an inst-file.
*/
static int instFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
  OS_TIME_IO(OS_FILESIZE, 0, 0, sqlite3OsFileSize(p->pReal, pSize));
}

/*
** Lock an inst-file.
*/
static int instLock(sqlite3_file *pFile, int eLock){
  OS_TIME_IO(OS_LOCK, eLock, 0, sqlite3OsLock(p->pReal, eLock));
}

/*
** Unlock an inst-file.
*/
static int instUnlock(sqlite3_file *pFile, int eLock){
  OS_TIME_IO(OS_UNLOCK, eLock, 0, sqlite3OsUnlock(p->pReal, eLock));
}

/*
** Check if another file-handle holds a RESERVED lock on an inst-file.
*/
static int instCheckReservedLock(sqlite3_file *pFile){
  OS_TIME_IO(OS_CHECKRESERVEDLOCK, 0, 0, sqlite3OsCheckReservedLock(p->pReal));
}

/*
** File control method. For custom operations on an inst-file.
*/
static int instFileControl(sqlite3_file *pFile, int op, void *pArg){
  OS_TIME_IO(OS_FILECONTROL, 0, 0, sqlite3OsFileControl(p->pReal, op, pArg));
}

/*
** Return the sector-size in bytes for an inst-file.
*/
static int instSectorSize(sqlite3_file *pFile){
  OS_TIME_IO(OS_SECTORSIZE, 0, 0, sqlite3OsSectorSize(p->pReal));
}

/*
** Return the device characteristic flags supported by an inst-file.
*/
static int instDeviceCharacteristics(sqlite3_file *pFile){
  OS_TIME_IO(OS_DEVCHAR, 0, 0, sqlite3OsDeviceCharacteristics(p->pReal));
}

/*
** Open an inst file handle.
*/
static int instOpen(
  sqlite3_vfs *pVfs,
................................................................................
  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)
  );
}

/*
** Delete the file located at zPath. If the dirSync argument is true,
** ensure the file-system modifications are synced to disk before
** returning.
*/
static int instDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
  OS_TIME_VFS(OS_DELETE, zPath, dirSync, 0,
    sqlite3OsDelete(REALVFS(pVfs), zPath, dirSync) 
  );
}

/*
** Test for access permissions. Return true if the requested permission
** is available, or false otherwise.
*/
static int instAccess(sqlite3_vfs *pVfs, const char *zPath, int flags){
  OS_TIME_VFS(OS_ACCESS, zPath, flags, 0, 
    sqlite3OsAccess(REALVFS(pVfs), zPath, flags) 
  );
}

/*
** Populate buffer zBufOut with a pathname suitable for use as a 
** temporary file. zBufOut is guaranteed to point to a buffer of 
** at least (INST_MAX_PATHNAME+1) bytes.
*/
static int instGetTempName(sqlite3_vfs *pVfs, int nOut, char *zBufOut){
  OS_TIME_VFS( OS_GETTEMPNAME, 0, 0, 0,
    sqlite3OsGetTempname(REALVFS(pVfs), nOut, zBufOut);
  );
}

/*
** Populate buffer zOut with the full canonical pathname corresponding
** to the pathname in zPath. zOut is guaranteed to point to a buffer
** of at least (INST_MAX_PATHNAME+1) bytes.
................................................................................
static int instFullPathname(
  sqlite3_vfs *pVfs, 
  const char *zPath, 
  int nOut, 
  char *zOut
){
  OS_TIME_VFS( OS_FULLPATHNAME, zPath, 0, 0,
    sqlite3OsFullPathname(REALVFS(pVfs), zPath, nOut, zOut);
  );
}

/*
** Open the dynamic library located at zPath and return a handle.
*/
static void *instDlOpen(sqlite3_vfs *pVfs, const char *zPath){
  return sqlite3OsDlOpen(REALVFS(pVfs), zPath);
}

/*
** Populate the buffer zErrMsg (size nByte bytes) with a human readable
** utf-8 string describing the most recent error encountered associated 
** with dynamic libraries.
*/
static void instDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
  sqlite3OsDlError(REALVFS(pVfs), nByte, zErrMsg);
}

/*
** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
*/
static void *instDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){
  return sqlite3OsDlSym(REALVFS(pVfs), pHandle, zSymbol);
}

/*
** Close the dynamic library handle pHandle.
*/
static void instDlClose(sqlite3_vfs *pVfs, void *pHandle){
  sqlite3OsDlClose(REALVFS(pVfs), pHandle);
}

/*
** Populate the buffer pointed to by zBufOut with nByte bytes of 
** random data.
*/
static int instRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
  OS_TIME_VFS( OS_RANDOMNESS, 0, nByte, 0,
    sqlite3OsRandomness(REALVFS(pVfs), nByte, zBufOut);
  );
}

/*
** Sleep for nMicro microseconds. Return the number of microseconds 
** actually slept.
*/
static int instSleep(sqlite3_vfs *pVfs, int nMicro){
  OS_TIME_VFS( OS_SLEEP, 0, nMicro, 0, 
    sqlite3OsSleep(REALVFS(pVfs), nMicro) 
  );
}

/*
** Return the current time as a Julian Day number in *pTimeOut.
*/
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;
................................................................................
  }

  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);
................................................................................
  sqlite3_instvfs_configure(pVfs, 0, 0, 0);
  sqlite3_free(pVfs);
}

void sqlite3_instvfs_reset(sqlite3_vfs *pVfs){
  InstVfs *p = (InstVfs *)pVfs;
  assert( pVfs->xOpen==instOpen );
  memset(p->aTime, 0, sizeof(i64)*OS_NUMEVENTS);
  memset(p->aCount, 0, sizeof(int)*OS_NUMEVENTS);
}

const char *sqlite3_instvfs_name(int eEvent){
  const char *zEvent = 0;

  switch( 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(
................................................................................
  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;
................................................................................
        sqlite3_instvfs_reset(p);
      }
      if( ((enum IV_enum)iSub)==IV_REPORT ){
        int ii;
        Tcl_Obj *pRet = Tcl_NewObj();

        const char *zName = (char *)1;
        i64 nClick;
        int nCall;
        for(ii=1; zName; ii++){
          sqlite3_instvfs_get(p, ii, &zName, &nClick, &nCall);
          if( zName ){
            Tcl_Obj *pElem = Tcl_NewObj();
            Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj(zName, -1));
            Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(nCall));







|
>







 







|







 







|






|






|

|











|







 







|











|











|






|






|






|






|






|






|






|






|






|







 







|










|









|










|







 







|







|








|






|






|








|









|








|







 







|







 







|







 







>



|







 







|




>
|
>


|







 







|







79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
...
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
...
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
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
...
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
...
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
...
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
...
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
...
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
...
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
...
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
**         * The name of the method call - i.e. "xWrite",
**         * The total number of calls to the method (an integer).
**         * The aggregate time consumed by all calls to the method as
**           measured by hwtime() (an integer).
*/

#include "sqlite3.h"
#include <string.h>
#include <assert.h>

/*
** Maximum pathname length supported by the inst backend.
*/
#define INST_MAX_PATHNAME 512


................................................................................
  sqlite3_vfs *pVfs;
  
  void *pClient;
  void (*xDel)(void *);
  void (*xCall)(void *, int, sqlite3_int64, const char *, int, int, sqlite3_int64);

  /* Counters */
  sqlite3_int64 aTime[OS_NUMEVENTS];
  int aCount[OS_NUMEVENTS];
};
typedef struct InstVfs InstVfs;

#define REALVFS(p) (((InstVfs *)(p))->pVfs)

typedef struct inst_file inst_file;
................................................................................
/*
** 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 osinst_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 osinst_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;                                    \
  sqlite3_int64 t = osinst_hwtime();         \
  rc = Call;                                 \
  t = osinst_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;                                \
  sqlite3_int64 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.
*/
static int instClose(sqlite3_file *pFile){
  OS_TIME_IO(OS_CLOSE, 0, 0, p->pReal->pMethods->xClose(p->pReal));
}

/*
** Read data from an inst-file.
*/
static int instRead(
  sqlite3_file *pFile, 
  void *zBuf, 
  int iAmt, 
  sqlite_int64 iOfst
){
  OS_TIME_IO(OS_READ, iAmt, iOfst, p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst));
}

/*
** Write data to an inst-file.
*/
static int instWrite(
  sqlite3_file *pFile,
  const void *z,
  int iAmt,
  sqlite_int64 iOfst
){
  OS_TIME_IO(OS_WRITE, iAmt, iOfst, p->pReal->pMethods->xWrite(p->pReal, z, iAmt, iOfst));
}

/*
** Truncate an inst-file.
*/
static int instTruncate(sqlite3_file *pFile, sqlite_int64 size){
  OS_TIME_IO(OS_TRUNCATE, 0, size, p->pReal->pMethods->xTruncate(p->pReal, size));
}

/*
** Sync an inst-file.
*/
static int instSync(sqlite3_file *pFile, int flags){
  OS_TIME_IO(OS_SYNC, flags, 0, p->pReal->pMethods->xSync(p->pReal, flags));
}

/*
** Return the current file-size of an inst-file.
*/
static int instFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
  OS_TIME_IO(OS_FILESIZE, 0, 0, p->pReal->pMethods->xFileSize(p->pReal, pSize));
}

/*
** Lock an inst-file.
*/
static int instLock(sqlite3_file *pFile, int eLock){
  OS_TIME_IO(OS_LOCK, eLock, 0, p->pReal->pMethods->xLock(p->pReal, eLock));
}

/*
** Unlock an inst-file.
*/
static int instUnlock(sqlite3_file *pFile, int eLock){
  OS_TIME_IO(OS_UNLOCK, eLock, 0, p->pReal->pMethods->xUnlock(p->pReal, eLock));
}

/*
** Check if another file-handle holds a RESERVED lock on an inst-file.
*/
static int instCheckReservedLock(sqlite3_file *pFile){
  OS_TIME_IO(OS_CHECKRESERVEDLOCK, 0, 0, p->pReal->pMethods->xCheckReservedLock(p->pReal));
}

/*
** File control method. For custom operations on an inst-file.
*/
static int instFileControl(sqlite3_file *pFile, int op, void *pArg){
  OS_TIME_IO(OS_FILECONTROL, 0, 0, p->pReal->pMethods->xFileControl(p->pReal, op, pArg));
}

/*
** Return the sector-size in bytes for an inst-file.
*/
static int instSectorSize(sqlite3_file *pFile){
  OS_TIME_IO(OS_SECTORSIZE, 0, 0, p->pReal->pMethods->xSectorSize(p->pReal));
}

/*
** Return the device characteristic flags supported by an inst-file.
*/
static int instDeviceCharacteristics(sqlite3_file *pFile){
  OS_TIME_IO(OS_DEVCHAR, 0, 0, p->pReal->pMethods->xDeviceCharacteristics(p->pReal));
}

/*
** Open an inst file handle.
*/
static int instOpen(
  sqlite3_vfs *pVfs,
................................................................................
  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,
    REALVFS(pVfs)->xOpen(REALVFS(pVfs), zName, p->pReal, flags, pOutFlags)
  );
}

/*
** Delete the file located at zPath. If the dirSync argument is true,
** ensure the file-system modifications are synced to disk before
** returning.
*/
static int instDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
  OS_TIME_VFS(OS_DELETE, zPath, dirSync, 0,
    REALVFS(pVfs)->xDelete(REALVFS(pVfs), zPath, dirSync) 
  );
}

/*
** Test for access permissions. Return true if the requested permission
** is available, or false otherwise.
*/
static int instAccess(sqlite3_vfs *pVfs, const char *zPath, int flags){
  OS_TIME_VFS(OS_ACCESS, zPath, flags, 0, 
    REALVFS(pVfs)->xAccess(REALVFS(pVfs), zPath, flags) 
  );
}

/*
** Populate buffer zBufOut with a pathname suitable for use as a 
** temporary file. zBufOut is guaranteed to point to a buffer of 
** at least (INST_MAX_PATHNAME+1) bytes.
*/
static int instGetTempName(sqlite3_vfs *pVfs, int nOut, char *zBufOut){
  OS_TIME_VFS( OS_GETTEMPNAME, 0, 0, 0,
    REALVFS(pVfs)->xGetTempname(REALVFS(pVfs), nOut, zBufOut);
  );
}

/*
** Populate buffer zOut with the full canonical pathname corresponding
** to the pathname in zPath. zOut is guaranteed to point to a buffer
** of at least (INST_MAX_PATHNAME+1) bytes.
................................................................................
static int instFullPathname(
  sqlite3_vfs *pVfs, 
  const char *zPath, 
  int nOut, 
  char *zOut
){
  OS_TIME_VFS( OS_FULLPATHNAME, zPath, 0, 0,
    REALVFS(pVfs)->xFullPathname(REALVFS(pVfs), zPath, nOut, zOut);
  );
}

/*
** Open the dynamic library located at zPath and return a handle.
*/
static void *instDlOpen(sqlite3_vfs *pVfs, const char *zPath){
  return REALVFS(pVfs)->xDlOpen(REALVFS(pVfs), zPath);
}

/*
** Populate the buffer zErrMsg (size nByte bytes) with a human readable
** utf-8 string describing the most recent error encountered associated 
** with dynamic libraries.
*/
static void instDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
  REALVFS(pVfs)->xDlError(REALVFS(pVfs), nByte, zErrMsg);
}

/*
** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
*/
static void *instDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){
  return REALVFS(pVfs)->xDlSym(REALVFS(pVfs), pHandle, zSymbol);
}

/*
** Close the dynamic library handle pHandle.
*/
static void instDlClose(sqlite3_vfs *pVfs, void *pHandle){
  REALVFS(pVfs)->xDlClose(REALVFS(pVfs), pHandle);
}

/*
** Populate the buffer pointed to by zBufOut with nByte bytes of 
** random data.
*/
static int instRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
  OS_TIME_VFS( OS_RANDOMNESS, 0, nByte, 0,
    REALVFS(pVfs)->xRandomness(REALVFS(pVfs), nByte, zBufOut);
  );
}

/*
** Sleep for nMicro microseconds. Return the number of microseconds 
** actually slept.
*/
static int instSleep(sqlite3_vfs *pVfs, int nMicro){
  OS_TIME_VFS( OS_SLEEP, 0, nMicro, 0, 
    REALVFS(pVfs)->xSleep(REALVFS(pVfs), nMicro) 
  );
}

/*
** Return the current time as a Julian Day number in *pTimeOut.
*/
static int instCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
  OS_TIME_VFS( OS_CURRENTTIME, 0, 0, 0,
    REALVFS(pVfs)->xCurrentTime(REALVFS(pVfs), pTimeOut) 
  );
}

sqlite3_vfs *sqlite3_instvfs_create(const char *zName, const char *zParent){
  int nByte;
  InstVfs *p;
  sqlite3_vfs *pParent;
................................................................................
  }

  return (sqlite3_vfs *)p;
}

void sqlite3_instvfs_configure(
  sqlite3_vfs *pVfs,
  void (*xCall)(void*, int, sqlite3_int64, const char*, int, int, sqlite3_int64),
  void *pClient,
  void (*xDel)(void *)
){
  InstVfs *p = (InstVfs *)pVfs;
  assert( pVfs->xOpen==instOpen );
  if( p->xDel ){
    p->xDel(p->pClient);
................................................................................
  sqlite3_instvfs_configure(pVfs, 0, 0, 0);
  sqlite3_free(pVfs);
}

void sqlite3_instvfs_reset(sqlite3_vfs *pVfs){
  InstVfs *p = (InstVfs *)pVfs;
  assert( pVfs->xOpen==instOpen );
  memset(p->aTime, 0, sizeof(sqlite3_int64)*OS_NUMEVENTS);
  memset(p->aCount, 0, sizeof(int)*OS_NUMEVENTS);
}

const char *sqlite3_instvfs_name(int eEvent){
  const char *zEvent = 0;

  switch( eEvent ){
................................................................................
#define BINARYLOG_BUFFERSIZE 1024

struct InstVfsBinaryLog {
  int nBuf;
  char *zBuf;
  sqlite3_int64 iOffset;
  sqlite3_file *pOut;
  char *zOut;                       /* Log file name */
};
typedef struct InstVfsBinaryLog InstVfsBinaryLog;

static void put32bits(unsigned char *p, unsigned int v){
  p[0] = v>>24;
  p[1] = v>>16;
  p[2] = v>>8;
  p[3] = v;
}

static void binarylog_xcall(
................................................................................
  int rc;

  pParent = sqlite3_vfs_find(zParentVfs);
  if( !pParent ){
    return 0;
  }

  nByte = sizeof(InstVfsBinaryLog) + pParent->szOsFile + pParent->mxPathname+1;

  p = (InstVfsBinaryLog *)sqlite3_malloc(nByte);
  memset(p, 0, nByte);
  p->zBuf = sqlite3_malloc(BINARYLOG_BUFFERSIZE);
  p->zOut = (char *)&p[1];
  p->pOut = (sqlite3_file *)&p->zOut[pParent->mxPathname+1];
  pParent->xFullPathname(pParent, zLog, pParent->mxPathname, p->zOut);

  flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MASTER_JOURNAL;
  rc = pParent->xOpen(pParent, p->zOut, 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;
................................................................................
        sqlite3_instvfs_reset(p);
      }
      if( ((enum IV_enum)iSub)==IV_REPORT ){
        int ii;
        Tcl_Obj *pRet = Tcl_NewObj();

        const char *zName = (char *)1;
        sqlite3_int64 nClick;
        int nCall;
        for(ii=1; zName; ii++){
          sqlite3_instvfs_get(p, ii, &zName, &nClick, &nCall);
          if( zName ){
            Tcl_Obj *pElem = Tcl_NewObj();
            Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj(zName, -1));
            Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(nCall));