summaryrefslogtreecommitdiffstats
path: root/ext/misc/pcachetrace.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 14:07:11 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 14:07:11 +0000
commit63847496f14c813a5d80efd5b7de0f1294ffe1e3 (patch)
tree01c7571c7c762ceee70638549a99834fdd7c411b /ext/misc/pcachetrace.c
parentInitial commit. (diff)
downloadsqlite3-63847496f14c813a5d80efd5b7de0f1294ffe1e3.tar.xz
sqlite3-63847496f14c813a5d80efd5b7de0f1294ffe1e3.zip
Adding upstream version 3.45.1.upstream/3.45.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ext/misc/pcachetrace.c')
-rw-r--r--ext/misc/pcachetrace.c179
1 files changed, 179 insertions, 0 deletions
diff --git a/ext/misc/pcachetrace.c b/ext/misc/pcachetrace.c
new file mode 100644
index 0000000..3757d8d
--- /dev/null
+++ b/ext/misc/pcachetrace.c
@@ -0,0 +1,179 @@
+/*
+** 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;
+}