mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-29 08:01:23 +03:00
Add extension "mmapwarm.c". Provides function sqlite3_mmap_warm(), used to
"warm up" the memory mapping used by SQLite in mmap mode to access db file content. FossilOrigin-Name: d4a30b91f9aad93510baead8c04ee51b82c98763be5a224ed4873298214c963a
This commit is contained in:
108
ext/misc/mmapwarm.c
Normal file
108
ext/misc/mmapwarm.c
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
** 2017-09-18
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
*************************************************************************
|
||||
**
|
||||
*/
|
||||
|
||||
#include "sqlite3.h"
|
||||
|
||||
|
||||
/*
|
||||
** This function is used to touch each page of a mapping of a memory
|
||||
** mapped SQLite database. Assuming that the system has sufficient free
|
||||
** memory and supports sufficiently large mappings, this causes the OS
|
||||
** to cache the entire database in main memory, making subsequent
|
||||
** database accesses faster.
|
||||
**
|
||||
** If the second parameter to this function is not NULL, it is the name of
|
||||
** the specific database to operate on (i.e. "main" or the name of an
|
||||
** attached database).
|
||||
**
|
||||
** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
|
||||
** It is not considered an error if the file is not memory-mapped, or if
|
||||
** the mapping does not span the entire file. If an error does occur, a
|
||||
** transaction may be left open on the database file.
|
||||
**
|
||||
** It is illegal to call this function when the database handle has an
|
||||
** open transaction. SQLITE_MISUSE is returned in this case.
|
||||
*/
|
||||
int sqlite3_mmap_warm(sqlite3 *db, const char *zDb){
|
||||
int rc = SQLITE_OK;
|
||||
char *zSql = 0;
|
||||
int pgsz = 0;
|
||||
int nTotal = 0;
|
||||
|
||||
if( 0==sqlite3_get_autocommit(db) ) return SQLITE_MISUSE;
|
||||
|
||||
/* Open a read-only transaction on the file in question */
|
||||
zSql = sqlite3_mprintf("BEGIN; SELECT * FROM %s%q%ssqlite_master",
|
||||
(zDb ? "'" : ""), (zDb ? zDb : ""), (zDb ? "'." : "")
|
||||
);
|
||||
if( zSql==0 ) return SQLITE_NOMEM;
|
||||
rc = sqlite3_exec(db, zSql, 0, 0, 0);
|
||||
sqlite3_free(zSql);
|
||||
|
||||
/* Find the SQLite page size of the file */
|
||||
if( rc==SQLITE_OK ){
|
||||
zSql = sqlite3_mprintf("PRAGMA %s%q%spage_size",
|
||||
(zDb ? "'" : ""), (zDb ? zDb : ""), (zDb ? "'." : "")
|
||||
);
|
||||
if( zSql==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
sqlite3_stmt *pPgsz = 0;
|
||||
rc = sqlite3_prepare_v2(db, zSql, -1, &pPgsz, 0);
|
||||
sqlite3_free(zSql);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( sqlite3_step(pPgsz)==SQLITE_ROW ){
|
||||
pgsz = sqlite3_column_int(pPgsz, 0);
|
||||
}
|
||||
rc = sqlite3_finalize(pPgsz);
|
||||
}
|
||||
if( rc==SQLITE_OK && pgsz==0 ){
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Touch each mmap'd page of the file */
|
||||
if( rc==SQLITE_OK ){
|
||||
int rc2;
|
||||
sqlite3_file *pFd = 0;
|
||||
rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_FILE_POINTER, &pFd);
|
||||
if( rc==SQLITE_OK && pFd->pMethods->iVersion>=3 ){
|
||||
sqlite3_int64 iPg = 1;
|
||||
sqlite3_io_methods const *p = pFd->pMethods;
|
||||
while( 1 ){
|
||||
unsigned char *pMap;
|
||||
rc = p->xFetch(pFd, pgsz*iPg, pgsz, (void**)&pMap);
|
||||
if( rc!=SQLITE_OK || pMap==0 ) break;
|
||||
|
||||
nTotal += pMap[0];
|
||||
nTotal += pMap[pgsz-1];
|
||||
|
||||
rc = p->xUnfetch(pFd, pgsz*iPg, (void*)pMap);
|
||||
if( rc!=SQLITE_OK ) break;
|
||||
iPg++;
|
||||
}
|
||||
sqlite3_log(SQLITE_OK,
|
||||
"sqlite3_mmap_warm_cache: Warmed up %d pages of %s", iPg==1?0:iPg,
|
||||
sqlite3_db_filename(db, zDb)
|
||||
);
|
||||
}
|
||||
|
||||
rc2 = sqlite3_exec(db, "END", 0, 0, 0);
|
||||
if( rc==SQLITE_OK ) rc = rc2;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
Reference in New Issue
Block a user