| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_MEMSTATVTAB) |
| | #if !defined(SQLITEINT_H) |
| | #include "sqlite3ext.h" |
| | #endif |
| | SQLITE_EXTENSION_INIT1 |
| | #include <assert.h> |
| | #include <string.h> |
| |
|
| | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| |
|
| | |
| | |
| | |
| | typedef struct memstat_vtab memstat_vtab; |
| | struct memstat_vtab { |
| | sqlite3_vtab base; |
| | sqlite3 *db; |
| | }; |
| |
|
| | |
| | |
| | |
| | |
| | typedef struct memstat_cursor memstat_cursor; |
| | struct memstat_cursor { |
| | sqlite3_vtab_cursor base; |
| | sqlite3 *db; |
| | int iRowid; |
| | int iDb; |
| | int nDb; |
| | char **azDb; |
| | sqlite3_int64 aVal[2]; |
| | }; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | static int memstatConnect( |
| | sqlite3 *db, |
| | void *pAux, |
| | int argc, const char *const*argv, |
| | sqlite3_vtab **ppVtab, |
| | char **pzErr |
| | ){ |
| | memstat_vtab *pNew; |
| | int rc; |
| |
|
| | |
| | #define MSV_COLUMN_NAME 0 |
| | #define MSV_COLUMN_SCHEMA 1 |
| | #define MSV_COLUMN_VALUE 2 |
| | #define MSV_COLUMN_HIWTR 3 |
| |
|
| | 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; |
| | if( pNew==0 ) return SQLITE_NOMEM; |
| | memset(pNew, 0, sizeof(*pNew)); |
| | pNew->db = db; |
| | } |
| | return rc; |
| | } |
| |
|
| | |
| | |
| | |
| | static int memstatDisconnect(sqlite3_vtab *pVtab){ |
| | sqlite3_free(pVtab); |
| | return SQLITE_OK; |
| | } |
| |
|
| | |
| | |
| | |
| | static int memstatOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ |
| | memstat_cursor *pCur; |
| | pCur = sqlite3_malloc( sizeof(*pCur) ); |
| | if( pCur==0 ) return SQLITE_NOMEM; |
| | memset(pCur, 0, sizeof(*pCur)); |
| | pCur->db = ((memstat_vtab*)p)->db; |
| | *ppCursor = &pCur->base; |
| | return SQLITE_OK; |
| | } |
| |
|
| | |
| | |
| | |
| | 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; |
| | } |
| |
|
| | |
| | |
| | |
| | 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_realloc64(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; |
| | } |
| |
|
| |
|
| | |
| | |
| | |
| | static int memstatClose(sqlite3_vtab_cursor *cur){ |
| | memstat_cursor *pCur = (memstat_cursor*)cur; |
| | memstatClearSchema(pCur); |
| | sqlite3_free(cur); |
| | return SQLITE_OK; |
| | } |
| |
|
| |
|
| | |
| | |
| | |
| | #define MSV_GSTAT 0 |
| | #define MSV_DB 1 |
| | #define MSV_ZIPVFS 2 |
| |
|
| | |
| | |
| | |
| | |
| | static const struct MemstatColumns { |
| | const char *zName; |
| | unsigned char eType; |
| | unsigned char mNull; |
| | |
| | int eOp; |
| | } aMemstatColumn[] = { |
| | {"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 }, |
| | #if SQLITE_VERSION_NUMBER >= 3140000 |
| | {"DB_CACHE_USED_SHARED", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_USED_SHARED }, |
| | #endif |
| | {"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 }, |
| | #if SQLITE_VERSION_NUMBER >= 3230000 |
| | {"DB_CACHE_SPILL", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_SPILL }, |
| | #endif |
| | {"DB_DEFERRED_FKS", MSV_DB, 10, SQLITE_DBSTATUS_DEFERRED_FKS }, |
| | #ifdef SQLITE_ENABLE_ZIPVFS |
| | {"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 |
| | }; |
| | #define MSV_NROW (sizeof(aMemstatColumn)/sizeof(aMemstatColumn[0])) |
| |
|
| | |
| | |
| | |
| | static int memstatNext(sqlite3_vtab_cursor *cur){ |
| | memstat_cursor *pCur = (memstat_cursor*)cur; |
| | int i; |
| | assert( pCur->iRowid<=MSV_NROW ); |
| | while(1){ |
| | i = (int)pCur->iRowid - 1; |
| | if( i<0 || (aMemstatColumn[i].mNull & 2)!=0 || (++pCur->iDb)>=pCur->nDb ){ |
| | pCur->iRowid++; |
| | if( pCur->iRowid>MSV_NROW ) return SQLITE_OK; |
| | pCur->iDb = 0; |
| | i++; |
| | } |
| | pCur->aVal[0] = 0; |
| | pCur->aVal[1] = 0; |
| | switch( aMemstatColumn[i].eType ){ |
| | case MSV_GSTAT: { |
| | if( sqlite3_libversion_number()>=3010000 ){ |
| | sqlite3_status64(aMemstatColumn[i].eOp, |
| | &pCur->aVal[0], &pCur->aVal[1],0); |
| | }else{ |
| | int xCur, xHiwtr; |
| | sqlite3_status(aMemstatColumn[i].eOp, &xCur, &xHiwtr, 0); |
| | pCur->aVal[0] = xCur; |
| | pCur->aVal[1] = xHiwtr; |
| | } |
| | 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; |
| | } |
| | |
| |
|
| | |
| | |
| | |
| | |
| | static int memstatColumn( |
| | sqlite3_vtab_cursor *cur, |
| | sqlite3_context *ctx, |
| | int iCol |
| | ){ |
| | memstat_cursor *pCur = (memstat_cursor*)cur; |
| | int i; |
| | assert( pCur->iRowid>0 && pCur->iRowid<=MSV_NROW ); |
| | i = (int)pCur->iRowid - 1; |
| | if( (aMemstatColumn[i].mNull & (1<<iCol))!=0 ){ |
| | return SQLITE_OK; |
| | } |
| | switch( iCol ){ |
| | case MSV_COLUMN_NAME: { |
| | sqlite3_result_text(ctx, aMemstatColumn[i].zName, -1, SQLITE_STATIC); |
| | break; |
| | } |
| | case MSV_COLUMN_SCHEMA: { |
| | sqlite3_result_text(ctx, pCur->azDb[pCur->iDb], -1, 0); |
| | break; |
| | } |
| | case MSV_COLUMN_VALUE: { |
| | sqlite3_result_int64(ctx, pCur->aVal[0]); |
| | break; |
| | } |
| | case MSV_COLUMN_HIWTR: { |
| | sqlite3_result_int64(ctx, pCur->aVal[1]); |
| | break; |
| | } |
| | } |
| | return SQLITE_OK; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | static int memstatRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ |
| | memstat_cursor *pCur = (memstat_cursor*)cur; |
| | *pRowid = pCur->iRowid*1000 + pCur->iDb; |
| | return SQLITE_OK; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | static int memstatEof(sqlite3_vtab_cursor *cur){ |
| | memstat_cursor *pCur = (memstat_cursor*)cur; |
| | return pCur->iRowid>MSV_NROW; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | static int memstatFilter( |
| | sqlite3_vtab_cursor *pVtabCursor, |
| | int idxNum, const char *idxStr, |
| | int argc, sqlite3_value **argv |
| | ){ |
| | memstat_cursor *pCur = (memstat_cursor *)pVtabCursor; |
| | int rc = memstatFindSchemas(pCur); |
| | if( rc ) return rc; |
| | pCur->iRowid = 0; |
| | pCur->iDb = 0; |
| | return memstatNext(pVtabCursor); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | static int memstatBestIndex( |
| | sqlite3_vtab *tab, |
| | sqlite3_index_info *pIdxInfo |
| | ){ |
| | pIdxInfo->estimatedCost = (double)500; |
| | pIdxInfo->estimatedRows = 500; |
| | return SQLITE_OK; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | static sqlite3_module memstatModule = { |
| | 0, |
| | 0, |
| | memstatConnect, |
| | memstatBestIndex, |
| | memstatDisconnect, |
| | 0, |
| | memstatOpen, |
| | memstatClose, |
| | memstatFilter, |
| | memstatNext, |
| | memstatEof, |
| | memstatColumn, |
| | memstatRowid, |
| | 0, |
| | 0, |
| | 0, |
| | 0, |
| | 0, |
| | 0, |
| | 0, |
| | 0, |
| | 0, |
| | 0, |
| | 0, |
| | 0 |
| | }; |
| |
|
| | #endif |
| |
|
| | int sqlite3MemstatVtabInit( |
| | sqlite3 *db, |
| | char **NotUsed1, |
| | const sqlite3_api_routines *NotUsed2 |
| | ){ |
| | int rc = SQLITE_OK; |
| | (void)NotUsed1; |
| | (void)NotUsed2; |
| | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| | rc = sqlite3_create_module(db, "sqlite_memstat", &memstatModule, 0); |
| | #endif |
| | return rc; |
| | } |
| |
|
| | #ifndef SQLITE_CORE |
| | #ifdef _WIN32 |
| | __declspec(dllexport) |
| | #endif |
| | int sqlite3_memstat_init( |
| | sqlite3 *db, |
| | char **pzErrMsg, |
| | const sqlite3_api_routines *pApi |
| | ){ |
| | int rc = SQLITE_OK; |
| | SQLITE_EXTENSION_INIT2(pApi); |
| | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| | rc = sqlite3MemstatVtabInit(db, 0, 0); |
| | #endif |
| | return rc; |
| | } |
| | #endif |
| | #endif |
| |
|