123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- /*
- ** 2023-06-21
- **
- ** The author disclaims copyright to this source code. In place of
- ** a legal notice, here is a blessing:
- **
- ** May you do good and not evil.
- ** May you find forgiveness for yourself and forgive others.
- ** May you share freely, never taking more than you give.
- **
- *************************************************************************
- **
- ** This file implements an extension that uses the SQLITE_CONFIG_PCACHE2
- ** mechanism to add a tracing layer on top of pluggable page cache of
- ** SQLite. If this extension is registered prior to sqlite3_initialize(),
- ** it will cause all page cache activities to be logged on standard output,
- ** or to some other FILE specified by the initializer.
- **
- ** This file needs to be compiled into the application that uses it.
- **
- ** This extension is used to implement the --pcachetrace option of the
- ** command-line shell.
- */
- #include <assert.h>
- #include <string.h>
- #include <stdio.h>
- /* The original page cache routines */
- static sqlite3_pcache_methods2 pcacheBase;
- static FILE *pcachetraceOut;
- /* Methods that trace pcache activity */
- static int pcachetraceInit(void *pArg){
- int nRes;
- if( pcachetraceOut ){
- fprintf(pcachetraceOut, "PCACHETRACE: xInit(%p)\n", pArg);
- }
- nRes = pcacheBase.xInit(pArg);
- if( pcachetraceOut ){
- fprintf(pcachetraceOut, "PCACHETRACE: xInit(%p) -> %d\n", pArg, nRes);
- }
- return nRes;
- }
- static void pcachetraceShutdown(void *pArg){
- if( pcachetraceOut ){
- fprintf(pcachetraceOut, "PCACHETRACE: xShutdown(%p)\n", pArg);
- }
- pcacheBase.xShutdown(pArg);
- }
- static sqlite3_pcache *pcachetraceCreate(int szPage, int szExtra, int bPurge){
- sqlite3_pcache *pRes;
- if( pcachetraceOut ){
- fprintf(pcachetraceOut, "PCACHETRACE: xCreate(%d,%d,%d)\n",
- szPage, szExtra, bPurge);
- }
- pRes = pcacheBase.xCreate(szPage, szExtra, bPurge);
- if( pcachetraceOut ){
- fprintf(pcachetraceOut, "PCACHETRACE: xCreate(%d,%d,%d) -> %p\n",
- szPage, szExtra, bPurge, pRes);
- }
- return pRes;
- }
- static void pcachetraceCachesize(sqlite3_pcache *p, int nCachesize){
- if( pcachetraceOut ){
- fprintf(pcachetraceOut, "PCACHETRACE: xCachesize(%p, %d)\n", p, nCachesize);
- }
- pcacheBase.xCachesize(p, nCachesize);
- }
- static int pcachetracePagecount(sqlite3_pcache *p){
- int nRes;
- if( pcachetraceOut ){
- fprintf(pcachetraceOut, "PCACHETRACE: xPagecount(%p)\n", p);
- }
- nRes = pcacheBase.xPagecount(p);
- if( pcachetraceOut ){
- fprintf(pcachetraceOut, "PCACHETRACE: xPagecount(%p) -> %d\n", p, nRes);
- }
- return nRes;
- }
- static sqlite3_pcache_page *pcachetraceFetch(
- sqlite3_pcache *p,
- unsigned key,
- int crFg
- ){
- sqlite3_pcache_page *pRes;
- if( pcachetraceOut ){
- fprintf(pcachetraceOut, "PCACHETRACE: xFetch(%p,%u,%d)\n", p, key, crFg);
- }
- pRes = pcacheBase.xFetch(p, key, crFg);
- if( pcachetraceOut ){
- fprintf(pcachetraceOut, "PCACHETRACE: xFetch(%p,%u,%d) -> %p\n",
- p, key, crFg, pRes);
- }
- return pRes;
- }
- static void pcachetraceUnpin(
- sqlite3_pcache *p,
- sqlite3_pcache_page *pPg,
- int bDiscard
- ){
- if( pcachetraceOut ){
- fprintf(pcachetraceOut, "PCACHETRACE: xUnpin(%p, %p, %d)\n",
- p, pPg, bDiscard);
- }
- pcacheBase.xUnpin(p, pPg, bDiscard);
- }
- static void pcachetraceRekey(
- sqlite3_pcache *p,
- sqlite3_pcache_page *pPg,
- unsigned oldKey,
- unsigned newKey
- ){
- if( pcachetraceOut ){
- fprintf(pcachetraceOut, "PCACHETRACE: xRekey(%p, %p, %u, %u)\n",
- p, pPg, oldKey, newKey);
- }
- pcacheBase.xRekey(p, pPg, oldKey, newKey);
- }
- static void pcachetraceTruncate(sqlite3_pcache *p, unsigned n){
- if( pcachetraceOut ){
- fprintf(pcachetraceOut, "PCACHETRACE: xTruncate(%p, %u)\n", p, n);
- }
- pcacheBase.xTruncate(p, n);
- }
- static void pcachetraceDestroy(sqlite3_pcache *p){
- if( pcachetraceOut ){
- fprintf(pcachetraceOut, "PCACHETRACE: xDestroy(%p)\n", p);
- }
- pcacheBase.xDestroy(p);
- }
- static void pcachetraceShrink(sqlite3_pcache *p){
- if( pcachetraceOut ){
- fprintf(pcachetraceOut, "PCACHETRACE: xShrink(%p)\n", p);
- }
- pcacheBase.xShrink(p);
- }
- /* The substitute pcache methods */
- static sqlite3_pcache_methods2 ersaztPcacheMethods = {
- 0,
- 0,
- pcachetraceInit,
- pcachetraceShutdown,
- pcachetraceCreate,
- pcachetraceCachesize,
- pcachetracePagecount,
- pcachetraceFetch,
- pcachetraceUnpin,
- pcachetraceRekey,
- pcachetraceTruncate,
- pcachetraceDestroy,
- pcachetraceShrink
- };
- /* Begin tracing memory allocations to out. */
- int sqlite3PcacheTraceActivate(FILE *out){
- int rc = SQLITE_OK;
- if( pcacheBase.xFetch==0 ){
- rc = sqlite3_config(SQLITE_CONFIG_GETPCACHE2, &pcacheBase);
- if( rc==SQLITE_OK ){
- rc = sqlite3_config(SQLITE_CONFIG_PCACHE2, &ersaztPcacheMethods);
- }
- }
- pcachetraceOut = out;
- return rc;
- }
- /* Deactivate memory tracing */
- int sqlite3PcacheTraceDeactivate(void){
- int rc = SQLITE_OK;
- if( pcacheBase.xFetch!=0 ){
- rc = sqlite3_config(SQLITE_CONFIG_PCACHE2, &pcacheBase);
- if( rc==SQLITE_OK ){
- memset(&pcacheBase, 0, sizeof(pcacheBase));
- }
- }
- pcachetraceOut = 0;
- return rc;
- }
|