modernc.org/cc@v1.0.1/v2/testdata/_sqlite/ext/misc/mmapwarm.c (about)

     1  /*
     2  ** 2017-09-18
     3  **
     4  ** The author disclaims copyright to this source code.  In place of
     5  ** a legal notice, here is a blessing:
     6  **
     7  **    May you do good and not evil.
     8  **    May you find forgiveness for yourself and forgive others.
     9  **    May you share freely, never taking more than you give.
    10  **
    11  *************************************************************************
    12  **
    13  */
    14  
    15  #include "sqlite3.h"
    16  
    17  
    18  /*
    19  ** This function is used to touch each page of a mapping of a memory
    20  ** mapped SQLite database. Assuming that the system has sufficient free
    21  ** memory and supports sufficiently large mappings, this causes the OS 
    22  ** to cache the entire database in main memory, making subsequent 
    23  ** database accesses faster.
    24  **
    25  ** If the second parameter to this function is not NULL, it is the name of
    26  ** the specific database to operate on (i.e. "main" or the name of an
    27  ** attached database).
    28  **
    29  ** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
    30  ** It is not considered an error if the file is not memory-mapped, or if
    31  ** the mapping does not span the entire file. If an error does occur, a
    32  ** transaction may be left open on the database file.
    33  **
    34  ** It is illegal to call this function when the database handle has an 
    35  ** open transaction. SQLITE_MISUSE is returned in this case.
    36  */
    37  int sqlite3_mmap_warm(sqlite3 *db, const char *zDb){
    38    int rc = SQLITE_OK;
    39    char *zSql = 0;
    40    int pgsz = 0;
    41    int nTotal = 0;
    42  
    43    if( 0==sqlite3_get_autocommit(db) ) return SQLITE_MISUSE;
    44  
    45    /* Open a read-only transaction on the file in question */
    46    zSql = sqlite3_mprintf("BEGIN; SELECT * FROM %s%q%ssqlite_master", 
    47        (zDb ? "'" : ""), (zDb ? zDb : ""), (zDb ? "'." : "")
    48    );
    49    if( zSql==0 ) return SQLITE_NOMEM;
    50    rc = sqlite3_exec(db, zSql, 0, 0, 0);
    51    sqlite3_free(zSql);
    52  
    53    /* Find the SQLite page size of the file */
    54    if( rc==SQLITE_OK ){
    55      zSql = sqlite3_mprintf("PRAGMA %s%q%spage_size", 
    56          (zDb ? "'" : ""), (zDb ? zDb : ""), (zDb ? "'." : "")
    57      );
    58      if( zSql==0 ){
    59        rc = SQLITE_NOMEM;
    60      }else{
    61        sqlite3_stmt *pPgsz = 0;
    62        rc = sqlite3_prepare_v2(db, zSql, -1, &pPgsz, 0);
    63        sqlite3_free(zSql);
    64        if( rc==SQLITE_OK ){
    65          if( sqlite3_step(pPgsz)==SQLITE_ROW ){
    66            pgsz = sqlite3_column_int(pPgsz, 0);
    67          }
    68          rc = sqlite3_finalize(pPgsz);
    69        }
    70        if( rc==SQLITE_OK && pgsz==0 ){
    71          rc = SQLITE_ERROR;
    72        }
    73      }
    74    }
    75  
    76    /* Touch each mmap'd page of the file */
    77    if( rc==SQLITE_OK ){
    78      int rc2;
    79      sqlite3_file *pFd = 0;
    80      rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_FILE_POINTER, &pFd);
    81      if( rc==SQLITE_OK && pFd->pMethods->iVersion>=3 ){
    82        sqlite3_int64 iPg = 1;
    83        sqlite3_io_methods const *p = pFd->pMethods;
    84        while( 1 ){
    85          unsigned char *pMap;
    86          rc = p->xFetch(pFd, pgsz*iPg, pgsz, (void**)&pMap);
    87          if( rc!=SQLITE_OK || pMap==0 ) break;
    88  
    89          nTotal += pMap[0];
    90          nTotal += pMap[pgsz-1];
    91  
    92          rc = p->xUnfetch(pFd, pgsz*iPg, (void*)pMap);
    93          if( rc!=SQLITE_OK ) break;
    94          iPg++;
    95        }
    96        sqlite3_log(SQLITE_OK, 
    97            "sqlite3_mmap_warm_cache: Warmed up %d pages of %s", iPg==1?0:iPg,
    98            sqlite3_db_filename(db, zDb)
    99        );
   100      }
   101  
   102      rc2 = sqlite3_exec(db, "END", 0, 0, 0);
   103      if( rc==SQLITE_OK ) rc = rc2;
   104    }
   105  
   106    return rc;
   107  }
   108