/ Check-in [d025866b]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix the functionality associated with sqlite3_release_memory() and sqlite3_soft_heap_limit(). It is automatically disabled if the SQLITE_CONFIG_PAGECACHE option is used. (CVS 5576)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: d025866b09352b32a6d35b97144eaad2fafb7165
User & Date: danielk1977 2008-08-21 12:19:44
Context
2008-08-21
12:32
Patch to mkfunction to try and detect miscompiles. Add an unimportant assert back to pcache.c. (CVS 5577) check-in: a2f375ff user: drh tags: trunk
12:19
Fix the functionality associated with sqlite3_release_memory() and sqlite3_soft_heap_limit(). It is automatically disabled if the SQLITE_CONFIG_PAGECACHE option is used. (CVS 5576) check-in: d025866b user: danielk1977 tags: trunk
04:41
Move an assert() in sqlite3PcacheDirtyPage() so that it does not occur before local variable declarations. Ticket #3325. (CVS 5575) check-in: 899fa19d user: danielk1977 tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/malloc.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   **
    13     13   ** Memory allocation functions used throughout sqlite.
    14     14   **
    15         -** $Id: malloc.c,v 1.35 2008/08/20 14:49:24 danielk1977 Exp $
           15  +** $Id: malloc.c,v 1.36 2008/08/21 12:19:44 danielk1977 Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   #include <stdarg.h>
    19     19   #include <ctype.h>
    20     20   
    21     21   /*
    22     22   ** This routine runs when the memory allocator sees that the
................................................................................
    58     58   /*
    59     59   ** Attempt to release up to n bytes of non-essential memory currently
    60     60   ** held by SQLite. An example of non-essential memory is memory used to
    61     61   ** cache database pages that are not currently in use.
    62     62   */
    63     63   int sqlite3_release_memory(int n){
    64     64   #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
    65         -  int nRet = sqlite3VdbeReleaseMemory(n);
    66         -  nRet += sqlite3PagerReleaseMemory(n-nRet);
           65  +  int nRet = 0;
           66  +#if 0
           67  +  nRet += sqlite3VdbeReleaseMemory(n);
           68  +#endif
           69  +  nRet += sqlite3PcacheReleaseMemory(n-nRet);
    67     70     return nRet;
    68     71   #else
    69     72     return SQLITE_OK;
    70     73   #endif
    71     74   }
    72     75   
    73     76   /*

Changes to src/pager.c.

    14     14   ** The pager is used to access a database disk file.  It implements
    15     15   ** atomic commit and rollback through the use of a journal file that
    16     16   ** is separate from the database file.  The pager also implements file
    17     17   ** locking to prevent two processes from writing the same database
    18     18   ** file simultaneously, or one process from reading the database while
    19     19   ** another is writing.
    20     20   **
    21         -** @(#) $Id: pager.c,v 1.472 2008/08/21 04:35:19 danielk1977 Exp $
           21  +** @(#) $Id: pager.c,v 1.473 2008/08/21 12:19:44 danielk1977 Exp $
    22     22   */
    23     23   #ifndef SQLITE_OMIT_DISKIO
    24     24   #include "sqliteInt.h"
    25     25   
    26     26   /*
    27     27   ** Macros for troubleshooting.  Normally turned off
    28     28   */
................................................................................
  2449   2449   ** by the pcache layer.
  2450   2450   */
  2451   2451   static int pagerStress(void *p){
  2452   2452     Pager *pPager = (Pager *)p;
  2453   2453     PgHdr *pPg = sqlite3PcacheDirtyPage(pPager->pPCache);
  2454   2454     int rc = SQLITE_OK;
  2455   2455   
  2456         -  if( pPg && pPager->errCode==SQLITE_OK ){
         2456  +  if( pPg ){
  2457   2457       assert( pPg->flags&PGHDR_DIRTY );
  2458         -    if( pPg->flags&PGHDR_NEED_SYNC ){
  2459         -      rc = syncJournal(pPager);
  2460         -      if( rc==SQLITE_OK && pPager->fullSync 
  2461         -       && !(sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND)
  2462         -      ){
  2463         -        pPager->nRec = 0;
  2464         -        rc = writeJournalHdr(pPager);
         2458  +    if( pPager->errCode==SQLITE_OK ){
         2459  +      if( pPg->flags&PGHDR_NEED_SYNC ){
         2460  +        rc = syncJournal(pPager);
         2461  +        if( rc==SQLITE_OK && pPager->fullSync && 
         2462  +          !(sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND)
         2463  +        ){
         2464  +          pPager->nRec = 0;
         2465  +          rc = writeJournalHdr(pPager);
         2466  +        }
  2465   2467         }
  2466         -    }
  2467         -    if( rc==SQLITE_OK ){
  2468         -      rc = pager_write_pagelist(pPg);
  2469         -    }
  2470         -    if( rc!=SQLITE_OK ){
  2471         -      pager_error(pPager, rc);
         2468  +      if( rc==SQLITE_OK ){
         2469  +        rc = pager_write_pagelist(pPg);
         2470  +      }
         2471  +      if( rc!=SQLITE_OK ){
         2472  +        pager_error(pPager, rc);
         2473  +      }
         2474  +    }else{
         2475  +      sqlite3PcacheMakeClean(pPg);
  2472   2476       }
  2473   2477     }
  2474   2478     return rc;
  2475   2479   }
  2476   2480   
  2477   2481   
  2478   2482   /*
................................................................................
  2519   2523         }
  2520   2524       }
  2521   2525     }
  2522   2526   
  2523   2527     return rc;
  2524   2528   }
  2525   2529   
  2526         -#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  2527         -/*
  2528         -** This function is called to free superfluous dynamically allocated memory
  2529         -** held by the pager system. Memory in use by any SQLite pager allocated
  2530         -** by the current thread may be sqlite3_free()ed.
  2531         -**
  2532         -** nReq is the number of bytes of memory required. Once this much has
  2533         -** been released, the function returns. The return value is the total number 
  2534         -** of bytes of memory released.
  2535         -*/
  2536         -int sqlite3PagerReleaseMemory(int nReq){
  2537         -  return 0;
  2538         -}
  2539         -#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
  2540         -
  2541   2530   /*
  2542   2531   ** Read the content of page pPg out of the database file.
  2543   2532   */
  2544   2533   static int readDbPage(Pager *pPager, PgHdr *pPg, Pgno pgno){
  2545   2534     int rc;
  2546   2535     i64 offset;
  2547   2536     assert( MEMDB==0 );

Changes to src/pager.h.

     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This header file defines the interface that the sqlite page cache
    13     13   ** subsystem.  The page cache subsystem reads and writes a file a page
    14     14   ** at a time and provides a journal for rollback.
    15     15   **
    16         -** @(#) $Id: pager.h,v 1.78 2008/08/20 14:49:25 danielk1977 Exp $
           16  +** @(#) $Id: pager.h,v 1.79 2008/08/21 12:19:44 danielk1977 Exp $
    17     17   */
    18     18   
    19     19   #ifndef _PAGER_H_
    20     20   #define _PAGER_H_
    21     21   
    22     22   /*
    23     23   ** If defined as non-zero, auto-vacuum is enabled by default. Otherwise
................................................................................
   111    111   int sqlite3PagerLockingMode(Pager *, int);
   112    112   int sqlite3PagerJournalMode(Pager *, int);
   113    113   i64 sqlite3PagerJournalSizeLimit(Pager *, i64);
   114    114   void *sqlite3PagerTempSpace(Pager*);
   115    115   int sqlite3PagerSync(Pager *pPager);
   116    116   void sqlite3PagerAlwaysRollback(Pager *pPager);
   117    117   
   118         -#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO)
   119         -  int sqlite3PagerReleaseMemory(int);
   120         -#endif
   121         -
   122    118   #ifdef SQLITE_HAS_CODEC
   123    119     void sqlite3PagerSetCodec(Pager*,void*(*)(void*,void*,Pgno,int),void*);
   124    120   #endif
   125    121   
   126    122   #if !defined(NDEBUG) || defined(SQLITE_TEST)
   127    123     Pgno sqlite3PagerPagenumber(DbPage*);
   128    124     int sqlite3PagerIswriteable(DbPage*);

Changes to src/pcache.c.

     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file implements that page cache.
    13     13   **
    14         -** @(#) $Id: pcache.c,v 1.3 2008/08/21 04:41:02 danielk1977 Exp $
           14  +** @(#) $Id: pcache.c,v 1.4 2008/08/21 12:19:44 danielk1977 Exp $
    15     15   */
    16     16   #include "sqliteInt.h"
    17     17   
    18     18   /*
    19     19   ** A complete page cache is an instance of this structure.
    20     20   */
    21     21   struct PCache {
................................................................................
   327    327     if( sz<=pcache.szSlot && pcache.pFree ){
   328    328       PgFreeslot *p = pcache.pFree;
   329    329       pcache.pFree = p->pNext;
   330    330       sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, sz);
   331    331       sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1);
   332    332       return (void*)p;
   333    333     }else{
   334         -    void *p = sqlite3Malloc(sz);
          334  +    void *p;
          335  +    pcacheExitGlobal();
          336  +    p = sqlite3Malloc(sz);
          337  +    pcacheEnterGlobal();
   335    338       if( p ){
   336    339         sz = sqlite3MallocSize(p);
   337    340         sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
   338    341       }
   339    342       return p;
   340    343     }
   341    344   }
................................................................................
   401    404     if( p->pCache->bPurgeable ){
   402    405       pcache.nPurgeable--;
   403    406     }
   404    407     pcacheFree(p->apSave[0]);
   405    408     pcacheFree(p->apSave[1]);
   406    409     pcacheFree(p);
   407    410   }
          411  +
          412  +/*
          413  +** Return the number of bytes that will be returned to the heap when
          414  +** the argument is passed to pcachePageFree().
          415  +*/
          416  +static int pcachePageSize(PgHdr *p){
          417  +  assert( sqlite3_mutex_held(pcache.mutex_lru) );
          418  +  assert( !pcache.pStart );
          419  +  assert( p->apSave[0]==0 );
          420  +  assert( p->apSave[1]==0 );
          421  +  assert( p && p->pCache );
          422  +  return sqlite3MallocSize(p);
          423  +}
          424  +
          425  +static PgHdr *pcacheRecycle(PCache *pCache){
          426  +  PCache *pCsr;
          427  +  PgHdr *p = 0;
          428  +
          429  +  assert( pcache.isInit );
          430  +  assert( sqlite3_mutex_held(pcache.mutex_lru) );
          431  +
          432  +  if( !pcache.pLruTail && SQLITE_OK==sqlite3_mutex_try(pcache.mutex_mem2) ){
          433  +
          434  +    /* Invoke xStress() callbacks until the LRU list contains at least one
          435  +    ** page that can be reused or until the xStress() callback of all
          436  +    ** caches has been invoked.
          437  +    */
          438  +    for(pCsr=pcache.pAll; pCsr&&!pcache.pLruTail; pCsr=pCsr->pNextAll){
          439  +      assert( pCsr->iInUseMM==0 );
          440  +      pCsr->iInUseMM = 1;
          441  +      if( pCsr->xStress && (pCsr->iInUseDB==0 || pCache==pCsr) ){
          442  +        pcacheExitGlobal();
          443  +        pCsr->xStress(pCsr->pStress);
          444  +        pcacheEnterGlobal();
          445  +      }
          446  +      pCsr->iInUseMM = 0;
          447  +    }
          448  +
          449  +    sqlite3_mutex_leave(pcache.mutex_mem2);
          450  +  }
          451  +
          452  +  p = pcache.pLruTail;
          453  +
          454  +  if( p ){
          455  +    pcacheRemoveFromLruList(p);
          456  +    pcacheRemoveFromHash(p);
          457  +    pcacheRemoveFromList(&p->pCache->pClean, p);
          458  +
          459  +    /* If the always-rollback flag is set on the page being recycled, set 
          460  +    ** the always-rollback flag on the corresponding pager.
          461  +    */
          462  +    if( p->flags&PGHDR_ALWAYS_ROLLBACK ){
          463  +      assert(p->pPager);
          464  +      sqlite3PagerAlwaysRollback(p->pPager);
          465  +    }
          466  +  }
          467  +
          468  +  return p;
          469  +}
   408    470   
   409    471   /*
   410    472   ** Obtain space for a page. Try to recycle an old page if the limit on the 
   411    473   ** number of pages has been reached. If the limit has not been reached or
   412    474   ** there are no pages eligible for recycling, allocate a new page.
   413    475   **
   414    476   ** Return a pointer to the new page, or NULL if an OOM condition occurs.
................................................................................
   424    486     assert( sqlite3_mutex_notheld(pcache.mutex_lru) );
   425    487   
   426    488     pcacheEnterGlobal();
   427    489   
   428    490     if( (pcache.mxPage && pcache.nPage>=pcache.mxPage) 
   429    491      || (!pcache.mxPage && bPurg && pcache.nPurgeable>=pcache.mxPagePurgeable)
   430    492     ){
   431         -    PCache *pCsr;
   432         -
   433         -    /* If the above test succeeds, then a page will be obtained by recycling
   434         -    ** an existing page.
   435         -    */
   436         -    if( !pcache.pLruTail && SQLITE_OK==sqlite3_mutex_try(pcache.mutex_mem2) ){
   437         -
   438         -      /* Invoke xStress() callbacks until the LRU list contains at least one
   439         -      ** page that can be reused or until the xStress() callback of all
   440         -      ** caches has been invoked.
   441         -      */
   442         -      for(pCsr=pcache.pAll; pCsr&&!pcache.pLruTail; pCsr=pCsr->pNextAll){
   443         -        assert( pCsr->iInUseMM==0 );
   444         -        pCsr->iInUseMM = 1;
   445         -        if( pCsr->xStress && (pCsr->iInUseDB==0 || pCache==pCsr) ){
   446         -          pcacheExitGlobal();
   447         -          pCsr->xStress(pCsr->pStress);
   448         -          pcacheEnterGlobal();
   449         -        }
   450         -        pCsr->iInUseMM = 0;
   451         -      }
   452         -
   453         -      sqlite3_mutex_leave(pcache.mutex_mem2);
   454         -    }
   455         -
   456         -    p = pcache.pLruTail;
          493  +    /* If the above test succeeds, then try to obtain a buffer by recycling
          494  +    ** an existing page. */
          495  +    p = pcacheRecycle(pCache);
   457    496     }
   458    497   
   459         -  if( p ){
   460         -    pcacheRemoveFromLruList(p);
   461         -    pcacheRemoveFromHash(p);
   462         -    pcacheRemoveFromList(&p->pCache->pClean, p);
   463         -
   464         -    /* If the always-rollback flag is set on the page being recycled, set 
   465         -    ** the always-rollback flag on the corresponding pager.
   466         -    */
   467         -    if( p->flags&PGHDR_ALWAYS_ROLLBACK ){
   468         -      assert(p->pPager);
   469         -      sqlite3PagerAlwaysRollback(p->pPager);
   470         -    }
   471         -
   472         -    if( p->pCache->szPage!=szPage || p->pCache->szExtra!=szExtra ){
   473         -      pcachePageFree(p);
   474         -      p = 0;
   475         -    }
          498  +  if( p && (p->pCache->szPage!=szPage || p->pCache->szExtra!=szExtra) ){
          499  +    pcachePageFree(p);
          500  +    p = 0;
   476    501     }
   477    502   
   478    503     if( !p ){
   479    504       /* Allocate a new page object. */
   480    505       p = pcachePageAlloc(szPage, szExtra, bPurg);
   481    506     }
   482    507   
................................................................................
  1137   1162   /*
  1138   1163   ** Unlock a pager-cache.
  1139   1164   */
  1140   1165   void sqlite3PcacheUnlock(PCache *pCache){
  1141   1166     pCache->iInUseDB--;
  1142   1167     assert( pCache->iInUseDB>=0 );
  1143   1168   }
         1169  +
         1170  +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
         1171  +/*
         1172  +** This function is called to free superfluous dynamically allocated memory
         1173  +** held by the pager system. Memory in use by any SQLite pager allocated
         1174  +** by the current thread may be sqlite3_free()ed.
         1175  +**
         1176  +** nReq is the number of bytes of memory required. Once this much has
         1177  +** been released, the function returns. The return value is the total number 
         1178  +** of bytes of memory released.
         1179  +*/
         1180  +int sqlite3PcacheReleaseMemory(int nReq){
         1181  +  int nFree = 0;
         1182  +  if( pcache.pStart==0 ){
         1183  +    PgHdr *p;
         1184  +    pcacheEnterGlobal();
         1185  +    while( (nReq<0 || nFree<nReq) && (p=pcacheRecycle(0)) ){
         1186  +      nFree += pcachePageSize(p);
         1187  +      pcachePageFree(p);
         1188  +    }
         1189  +    pcacheExitGlobal();
         1190  +  }
         1191  +  return nFree;
         1192  +}
         1193  +#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
         1194  +

Changes to src/pcache.h.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This header file defines the interface that the sqlite page cache
    13     13   ** subsystem. 
    14     14   **
    15         -** @(#) $Id: pcache.h,v 1.1 2008/08/20 14:49:25 danielk1977 Exp $
           15  +** @(#) $Id: pcache.h,v 1.2 2008/08/21 12:19:44 danielk1977 Exp $
    16     16   */
    17     17   
    18     18   #ifndef _PCACHE_H_
    19     19   
    20     20   typedef struct PgHdr PgHdr;
    21     21   typedef struct PCache PCache;
    22     22   
................................................................................
   166    166   /* Lock and unlock a pager-cache object. The PcacheLock() function may 
   167    167   ** block if the lock is temporarily available. While a pager-cache is locked,
   168    168   ** the system guarantees that any configured xStress() callback will not
   169    169   ** be invoked by any thread other than the one holding the lock.
   170    170   */
   171    171   void sqlite3PcacheLock(PCache *);
   172    172   void sqlite3PcacheUnlock(PCache *);
          173  +
          174  +int sqlite3PcacheReleaseMemory(int);
   173    175   
   174    176   #endif /* _PCACHE_H_ */
   175    177   

Changes to src/vdbeapi.c.

     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   **
    13     13   ** This file contains code use to implement APIs that are part of the
    14     14   ** VDBE.
    15     15   **
    16         -** $Id: vdbeapi.c,v 1.139 2008/08/11 18:44:58 drh Exp $
           16  +** $Id: vdbeapi.c,v 1.140 2008/08/21 12:19:44 danielk1977 Exp $
    17     17   */
    18     18   #include "sqliteInt.h"
    19     19   #include "vdbeInt.h"
    20     20   
    21         -#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
           21  +#if 0 && defined(SQLITE_ENABLE_MEMORY_MANAGEMENT)
    22     22   /*
    23     23   ** The following structure contains pointers to the end points of a
    24     24   ** doubly-linked list of all compiled SQL statements that may be holding
    25     25   ** buffers eligible for release when the sqlite3_release_memory() interface is
    26     26   ** invoked. Access to this list is protected by the SQLITE_MUTEX_STATIC_LRU2
    27     27   ** mutex.
    28     28   **

Changes to test/mutex1.test.

     5      5   #
     6      6   #    May you do good and not evil.
     7      7   #    May you find forgiveness for yourself and forgive others.
     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   #
    12         -# $Id: mutex1.test,v 1.11 2008/08/20 14:49:25 danielk1977 Exp $
           12  +# $Id: mutex1.test,v 1.12 2008/08/21 12:19:44 danielk1977 Exp $
    13     13   
    14     14   set testdir [file dirname $argv0]
    15     15   source $testdir/tester.tcl
    16     16   
    17     17   if {[info exists tester_do_binarylog]} {
    18     18     finish_test
    19     19     return
................................................................................
    95     95   set enable_shared_cache [sqlite3_enable_shared_cache 1]
    96     96   ifcapable threadsafe {
    97     97     foreach {mode mutexes} {
    98     98       singlethread {}
    99     99       multithread  {fast static_lru static_master static_mem static_mem2 static_prng }
   100    100       serialized   {fast recursive static_lru static_master static_mem static_mem2 static_prng }
   101    101     } {
   102         -    ifcapable memorymanage {
   103         -      if {$mode ne "singlethread"} {
   104         -        lappend mutexes static_lru static_lru2 static_mem2
   105         -      }
   106         -    }
   107    102   
   108    103       do_test mutex1.2.$mode.1 {
   109    104         catch {db close}
   110    105         sqlite3_shutdown
   111    106         sqlite3_config $mode
   112    107       } SQLITE_OK
   113    108