1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-29 08:01:23 +03:00

Enhancements to sqlite_memstat:

(1) Add an extra "schema" column to show the schema name for ZIPVFS stats.
(2) Only show ZIPVFS stats to schema that use ZIPVFS
(3) Put a NULL in unused columns of the output.

FossilOrigin-Name: 9351135b4331107be2f2bda7b6adbd5436381f4f9a68340e8a172b6517ec3f12
This commit is contained in:
drh
2018-09-27 16:57:42 +00:00
parent 7c5577acdc
commit d7134fe0c1
3 changed files with 148 additions and 63 deletions

View File

@ -20,7 +20,7 @@
** .header on
** SELECT * FROM memstat;
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB)
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_MEMSTATVTAB)
#if !defined(SQLITEINT_H)
#include "sqlite3ext.h"
#endif
@ -47,9 +47,11 @@ typedef struct memstat_cursor memstat_cursor;
struct memstat_cursor {
sqlite3_vtab_cursor base; /* Base class - must be first */
sqlite3 *db; /* Database connection for this cursor */
sqlite3_int64 iRowid; /* The rowid */
sqlite3_int64 iCur; /* Current value */
sqlite3_int64 iHiwtr; /* High-water mark */
int iRowid; /* Current row in aMemstatColumn[] */
int iDb; /* Which schema we are looking at */
int nDb; /* Number of schemas */
char **azDb; /* Names of all schemas */
sqlite3_int64 aVal[2]; /* Result values */
};
/*
@ -77,10 +79,11 @@ static int memstatConnect(
/* Column numbers */
#define MSV_COLUMN_NAME 0 /* Name of quantity being measured */
#define MSV_COLUMN_CURRENT 1 /* Current value */
#define MSV_COLUMN_HIWTR 2 /* Highwater mark */
#define MSV_COLUMN_SCHEMA 1 /* schema name */
#define MSV_COLUMN_VALUE 2 /* Current value */
#define MSV_COLUMN_HIWTR 3 /* Highwater mark */
rc = sqlite3_declare_vtab(db,"CREATE TABLE x(name,current,hiwtr)");
rc = sqlite3_declare_vtab(db,"CREATE TABLE x(name,schema,value,hiwtr)");
if( rc==SQLITE_OK ){
pNew = sqlite3_malloc( sizeof(*pNew) );
*ppVtab = (sqlite3_vtab*)pNew;
@ -112,10 +115,59 @@ static int memstatOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
return SQLITE_OK;
}
/*
** Clear all the schema names from a cursor
*/
static void memstatClearSchema(memstat_cursor *pCur){
int i;
if( pCur->azDb==0 ) return;
for(i=0; i<pCur->nDb; i++){
sqlite3_free(pCur->azDb[i]);
}
sqlite3_free(pCur->azDb);
pCur->azDb = 0;
pCur->nDb = 0;
}
/*
** Fill in the azDb[] array for the cursor.
*/
static int memstatFindSchemas(memstat_cursor *pCur){
sqlite3_stmt *pStmt = 0;
int rc;
if( pCur->nDb ) return SQLITE_OK;
rc = sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pStmt, 0);
if( rc ){
sqlite3_finalize(pStmt);
return rc;
}
while( sqlite3_step(pStmt)==SQLITE_ROW ){
char **az, *z;
az = sqlite3_realloc(pCur->azDb, sizeof(char*)*(pCur->nDb+1));
if( az==0 ){
memstatClearSchema(pCur);
return SQLITE_NOMEM;
}
pCur->azDb = az;
z = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
if( z==0 ){
memstatClearSchema(pCur);
return SQLITE_NOMEM;
}
pCur->azDb[pCur->nDb] = z;
pCur->nDb++;
}
sqlite3_finalize(pStmt);
return SQLITE_OK;
}
/*
** Destructor for a memstat_cursor.
*/
static int memstatClose(sqlite3_vtab_cursor *cur){
memstat_cursor *pCur = (memstat_cursor*)cur;
memstatClearSchema(pCur);
sqlite3_free(cur);
return SQLITE_OK;
}
@ -125,7 +177,7 @@ static int memstatClose(sqlite3_vtab_cursor *cur){
** Allowed values for aMemstatColumn[].eType
*/
#define MSV_GSTAT 0 /* sqlite3_status64() information */
#define MSV_DBSTAT 1 /* sqlite3_db_status() information */
#define MSV_DB 1 /* sqlite3_db_status() information */
#define MSV_ZIPVFS 2 /* ZIPVFS file-control with 64-bit return */
/*
@ -134,36 +186,38 @@ static int memstatClose(sqlite3_vtab_cursor *cur){
*/
static const struct MemstatColumns {
const char *zName; /* Symbolic name */
int eType; /* Type of interface */
unsigned char eType; /* Type of interface */
unsigned char mNull; /* Bitmask of which columns are NULL */
/* 2: dbname, 4: current, 8: hiwtr */
int eOp; /* Opcode */
} aMemstatColumn[] = {
{ "MEMORY_USED", MSV_GSTAT, SQLITE_STATUS_MEMORY_USED },
{ "MALLOC_SIZE", MSV_GSTAT, SQLITE_STATUS_MALLOC_SIZE },
{ "MALLOC_COUNT", MSV_GSTAT, SQLITE_STATUS_MALLOC_COUNT },
{ "PAGECACHE_USED", MSV_GSTAT, SQLITE_STATUS_PAGECACHE_USED },
{ "PAGECACHE_OVERFLOW", MSV_GSTAT, SQLITE_STATUS_PAGECACHE_OVERFLOW },
{ "PAGECACHE_SIZE", MSV_GSTAT, SQLITE_STATUS_PAGECACHE_SIZE },
{ "PARSER_STACK", MSV_GSTAT, SQLITE_STATUS_PARSER_STACK },
{ "DB_LOOKASIDE_USED", MSV_DBSTAT, SQLITE_DBSTATUS_LOOKASIDE_USED },
{ "DB_CACHE_USED", MSV_DBSTAT, SQLITE_DBSTATUS_CACHE_USED },
{ "DB_SCHEMA_USED", MSV_DBSTAT, SQLITE_DBSTATUS_SCHEMA_USED },
{ "DB_STMT_USED", MSV_DBSTAT, SQLITE_DBSTATUS_STMT_USED },
{ "DB_LOOKASIDE_HIT", MSV_DBSTAT, SQLITE_DBSTATUS_LOOKASIDE_HIT },
{ "DB_LOOKASIDE_MISS_SIZE", MSV_DBSTAT, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE },
{ "DB_LOOKASIDE_MISS_FULL", MSV_DBSTAT, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL },
{ "DB_CACHE_HIT", MSV_DBSTAT, SQLITE_DBSTATUS_CACHE_HIT },
{ "DB_CACHE_MISS", MSV_DBSTAT, SQLITE_DBSTATUS_CACHE_MISS },
{ "DB_CACHE_WRITE", MSV_DBSTAT, SQLITE_DBSTATUS_CACHE_WRITE },
{ "DB_DEFERRED_FKS", MSV_DBSTAT, SQLITE_DBSTATUS_DEFERRED_FKS },
{ "DB_CACHE_USED_SHARED", MSV_DBSTAT, SQLITE_DBSTATUS_CACHE_USED_SHARED },
{ "DB_CACHE_SPILL", MSV_DBSTAT, SQLITE_DBSTATUS_CACHE_SPILL },
{"MEMORY_USED", MSV_GSTAT, 2, SQLITE_STATUS_MEMORY_USED },
{"MALLOC_SIZE", MSV_GSTAT, 6, SQLITE_STATUS_MALLOC_SIZE },
{"MALLOC_COUNT", MSV_GSTAT, 2, SQLITE_STATUS_MALLOC_COUNT },
{"PAGECACHE_USED", MSV_GSTAT, 2, SQLITE_STATUS_PAGECACHE_USED },
{"PAGECACHE_OVERFLOW", MSV_GSTAT, 2, SQLITE_STATUS_PAGECACHE_OVERFLOW },
{"PAGECACHE_SIZE", MSV_GSTAT, 6, SQLITE_STATUS_PAGECACHE_SIZE },
{"PARSER_STACK", MSV_GSTAT, 6, SQLITE_STATUS_PARSER_STACK },
{"DB_LOOKASIDE_USED", MSV_DB, 2, SQLITE_DBSTATUS_LOOKASIDE_USED },
{"DB_LOOKASIDE_HIT", MSV_DB, 6, SQLITE_DBSTATUS_LOOKASIDE_HIT },
{"DB_LOOKASIDE_MISS_SIZE", MSV_DB, 6, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE},
{"DB_LOOKASIDE_MISS_FULL", MSV_DB, 6, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL},
{"DB_CACHE_USED", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_USED },
{"DB_CACHE_USED_SHARED", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_USED_SHARED },
{"DB_SCHEMA_USED", MSV_DB, 10, SQLITE_DBSTATUS_SCHEMA_USED },
{"DB_STMT_USED", MSV_DB, 10, SQLITE_DBSTATUS_STMT_USED },
{"DB_CACHE_HIT", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_HIT },
{"DB_CACHE_MISS", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_MISS },
{"DB_CACHE_WRITE", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_WRITE },
{"DB_CACHE_SPILL", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_SPILL },
{"DB_DEFERRED_FKS", MSV_DB, 10, SQLITE_DBSTATUS_DEFERRED_FKS },
#ifdef SQLITE_ENABLE_ZIPVFS
{ "ZIPVFS_CACHE_USED", MSV_ZIPVFS, 231454 },
{ "ZIPVFS_CACHE_HIT", MSV_ZIPVFS, 231455 },
{ "ZIPVFS_CACHE_MISS", MSV_ZIPVFS, 231456 },
{ "ZIPVFS_CACHE_WRITE", MSV_ZIPVFS, 231457 },
{ "ZIPVFS_DIRECT_READ", MSV_ZIPVFS, 231458 },
{ "ZIPVFS_DIRECT_BYTES", MSV_ZIPVFS, 231459 },
{"ZIPVFS_CACHE_USED", MSV_ZIPVFS, 8, 231454 },
{"ZIPVFS_CACHE_HIT", MSV_ZIPVFS, 8, 231455 },
{"ZIPVFS_CACHE_MISS", MSV_ZIPVFS, 8, 231456 },
{"ZIPVFS_CACHE_WRITE", MSV_ZIPVFS, 8, 231457 },
{"ZIPVFS_DIRECT_READ", MSV_ZIPVFS, 8, 231458 },
{"ZIPVFS_DIRECT_BYTES", MSV_ZIPVFS, 8, 231459 },
#endif /* SQLITE_ENABLE_ZIPVFS */
};
#define MSV_NROW (sizeof(aMemstatColumn)/sizeof(aMemstatColumn[0]))
@ -173,7 +227,41 @@ static const struct MemstatColumns {
*/
static int memstatNext(sqlite3_vtab_cursor *cur){
memstat_cursor *pCur = (memstat_cursor*)cur;
pCur->iRowid++;
int i;
assert( pCur->iRowid<=MSV_NROW );
while(1){
i = (int)pCur->iRowid - 1;
if( (aMemstatColumn[i].mNull & 2)!=0 || (++pCur->iDb)>=pCur->nDb ){
pCur->iRowid++;
if( pCur->iRowid>MSV_NROW ) return SQLITE_OK; /* End of the table */
pCur->iDb = 0;
i++;
}
pCur->aVal[0] = 0;
pCur->aVal[1] = 0;
switch( aMemstatColumn[i].eType ){
case MSV_GSTAT: {
sqlite3_status64(aMemstatColumn[i].eOp,
&pCur->aVal[0], &pCur->aVal[1],0);
break;
}
case MSV_DB: {
int xCur, xHiwtr;
sqlite3_db_status(pCur->db, aMemstatColumn[i].eOp, &xCur, &xHiwtr, 0);
pCur->aVal[0] = xCur;
pCur->aVal[1] = xHiwtr;
break;
}
case MSV_ZIPVFS: {
int rc;
rc = sqlite3_file_control(pCur->db, pCur->azDb[pCur->iDb],
aMemstatColumn[i].eOp, (void*)&pCur->aVal[0]);
if( rc!=SQLITE_OK ) continue;
break;
}
}
break;
}
return SQLITE_OK;
}
@ -189,33 +277,29 @@ static int memstatColumn(
){
memstat_cursor *pCur = (memstat_cursor*)cur;
int i;
sqlite3_int64 iCur = 0, iHiwtr = 0;
assert( pCur->iRowid>0 && pCur->iRowid<=MSV_NROW );
i = (int)pCur->iRowid - 1;
if( iCol==MSV_COLUMN_NAME ){
sqlite3_result_text(ctx, aMemstatColumn[i].zName, -1, SQLITE_STATIC);
if( (aMemstatColumn[i].mNull & (1<<iCol))!=0 ){
return SQLITE_OK;
}
switch( aMemstatColumn[i].eType ){
case MSV_GSTAT: {
sqlite3_status64(aMemstatColumn[i].eOp, &iCur, &iHiwtr, 0);
switch( iCol ){
case MSV_COLUMN_NAME: {
sqlite3_result_text(ctx, aMemstatColumn[i].zName, -1, SQLITE_STATIC);
break;
}
case MSV_DBSTAT: {
int xCur, xHiwtr;
sqlite3_db_status(pCur->db, aMemstatColumn[i].eOp, &xCur, &xHiwtr, 0);
iCur = xCur;
iHiwtr = xHiwtr;
case MSV_COLUMN_SCHEMA: {
sqlite3_result_text(ctx, pCur->azDb[pCur->iDb], -1, 0);
break;
}
case MSV_ZIPVFS: {
sqlite3_file_control(pCur->db, 0, aMemstatColumn[i].eOp, (void*)&iCur);
case MSV_COLUMN_VALUE: {
sqlite3_result_int64(ctx, pCur->aVal[0]);
break;
}
case MSV_COLUMN_HIWTR: {
sqlite3_result_int64(ctx, pCur->aVal[1]);
break;
}
}
if( iCol==MSV_COLUMN_HIWTR ) iCur = iHiwtr;
sqlite3_result_int64(ctx, iCur);
return SQLITE_OK;
}
@ -225,7 +309,7 @@ static int memstatColumn(
*/
static int memstatRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
memstat_cursor *pCur = (memstat_cursor*)cur;
*pRowid = pCur->iRowid;
*pRowid = pCur->iRowid*1000 + pCur->iDb;
return SQLITE_OK;
}
@ -250,8 +334,9 @@ static int memstatFilter(
int argc, sqlite3_value **argv
){
memstat_cursor *pCur = (memstat_cursor *)pVtabCursor;
pCur->iRowid = 0;
return memstatNext(pVtabCursor);
pCur->iRowid = 1;
pCur->iDb = 0;
return memstatFindSchemas(pCur);
}
/*
@ -326,4 +411,4 @@ int sqlite3_memstat_init(
return rc;
}
#endif /* SQLITE_CORE */
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_MEMSTATVTAB) */