/ Check-in [3bc221b9]
Login

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

Overview
Comment:Adjust the page recycling algorithm so that the number of pages allocated to each connection does not exceed its cache_size limit. (CVS 5701)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:3bc221b940565133ae8d95f59b3b120e57df0124
User & Date: drh 2008-09-15 15:36:58
Context
2008-09-15
15:49
Minor comment change to test_async.c. No code changes. (CVS 5702) check-in: b1341060 user: danielk1977 tags: trunk
15:36
Adjust the page recycling algorithm so that the number of pages allocated to each connection does not exceed its cache_size limit. (CVS 5701) check-in: 3bc221b9 user: drh tags: trunk
14:47
Fix the async.test test script so that it invokes (finish_test) even if the asynchronous backend is not included in the build (and no tests are run). (CVS 5700) check-in: 5c954b40 user: danielk1977 tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/pcache.c.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566

567
568
569
570
571
572
573
...
582
583
584
585
586
587
588
589



590
591
592
593
594
595
596
597
....
1263
1264
1265
1266
1267
1268
1269
1270
**    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.
**
*************************************************************************
** This file implements that page cache.
**
** @(#) $Id: pcache.c,v 1.26 2008/09/02 09:38:07 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** A complete page cache is an instance of this structure.
**
** A cache may only be deleted by its owner and while holding the
................................................................................
  int szExtra = pCache->szExtra;

  assert( pcache_g.isInit );
  assert( sqlite3_mutex_held(pcache_g.mutex) );

  *ppPage = 0;

  /* If we have reached the limit for pinned/dirty pages, and there is at
  ** least one dirty page, invoke the xStress callback to cause a page to
  ** become clean.
  */
  expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) );
  expensive_assert( pcacheCheckSynced(pCache) );
  if( pCache->xStress
   && pCache->pDirty
   && pCache->nPinned>=(pcache_g.nMaxPage+pCache->nMin-pcache_g.nMinPage)

  ){
    PgHdr *pPg;
    assert(pCache->pDirtyTail);

    for(pPg=pCache->pSynced; 
        pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC)); 
        pPg=pPg->pPrev
................................................................................
      pcacheEnterMutex();
      if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
        return rc;
      }
    }
  }

  /* If the global page limit has been reached, try to recycle a page. */



  if( pCache->bPurgeable && pcache_g.nCurrentPage>=pcache_g.nMaxPage ){
    p = pcacheRecyclePage();
  }

  /* If a page has been recycled but it is the wrong size, free it. */
  if( p && (p->pCache->szPage!=szPage || p->pCache->szPage!=szExtra) ){
    pcachePageFree(p);
    p = 0;
................................................................................

  *pnCurrent = pcache_g.nCurrentPage;
  *pnMax = pcache_g.nMaxPage;
  *pnMin = pcache_g.nMinPage;
  *pnRecyclable = nRecyclable;
}
#endif








|







 







|
|
|





|
>







 







|
>
>
>
|







 







<
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
...
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
....
1267
1268
1269
1270
1271
1272
1273

**    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.
**
*************************************************************************
** This file implements that page cache.
**
** @(#) $Id: pcache.c,v 1.27 2008/09/15 15:36:58 drh Exp $
*/
#include "sqliteInt.h"

/*
** A complete page cache is an instance of this structure.
**
** A cache may only be deleted by its owner and while holding the
................................................................................
  int szExtra = pCache->szExtra;

  assert( pcache_g.isInit );
  assert( sqlite3_mutex_held(pcache_g.mutex) );

  *ppPage = 0;

  /* If we have reached either the global or the local limit for 
  ** pinned+dirty pages, and there is at least one dirty page,
  ** invoke the xStress callback to cause a page to become clean.
  */
  expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) );
  expensive_assert( pcacheCheckSynced(pCache) );
  if( pCache->xStress
   && pCache->pDirty
   && (pCache->nPinned>=(pcache_g.nMaxPage+pCache->nMin-pcache_g.nMinPage)
           || pCache->nPinned>=pCache->nMax)
  ){
    PgHdr *pPg;
    assert(pCache->pDirtyTail);

    for(pPg=pCache->pSynced; 
        pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC)); 
        pPg=pPg->pPrev
................................................................................
      pcacheEnterMutex();
      if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
        return rc;
      }
    }
  }

  /* If either the local or the global page limit has been reached, 
  ** try to recycle a page. 
  */
  if( pCache->bPurgeable && (pCache->nPage>=pCache->nMax-1 ||
                             pcache_g.nCurrentPage>=pcache_g.nMaxPage) ){
    p = pcacheRecyclePage();
  }

  /* If a page has been recycled but it is the wrong size, free it. */
  if( p && (p->pCache->szPage!=szPage || p->pCache->szPage!=szExtra) ){
    pcachePageFree(p);
    p = 0;
................................................................................

  *pnCurrent = pcache_g.nCurrentPage;
  *pnMax = pcache_g.nMaxPage;
  *pnMin = pcache_g.nMinPage;
  *pnRecyclable = nRecyclable;
}
#endif

Added test/pcache2.test.













































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# 2008 September 15
#
# 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.
#
#***********************************************************************
#
# This file is focused on testing the pcache module.
#
# $Id: pcache2.test,v 1.1 2008/09/15 15:36:58 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl


# Set up a pcache memory pool so that we can easily track how many
# pages are being used for cache.
#
do_test pcache2-1.1 {
  db close
  sqlite3_shutdown
  sqlite3_config_pagecache 6000 100
  sqlite3_initialize
  sqlite3_status SQLITE_STATUS_PAGECACHE_USED 1
  sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0
} {0 0 0}

# Open up two database connections to separate files.
#
do_test pcache2-1.2 {
  file delete -force test.db test.db-journal
  sqlite3 db test.db
  db eval {PRAGMA cache_size=10}
  lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 1
} {2}
do_test pcache2-1.3 {
  file delete -force test2.db test2.db-journal
  sqlite3 db2 test2.db
  db2 eval {PRAGMA cache_size=50}
  lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 1
} {4}

# Make lots of changes on the first connection.  Verify that the
# page cache usage does not grow to consume the page space set aside
# for the second connection.
#
do_test pcache2-1.4 {
  db eval {
     CREATE TABLE t1(a,b);
     CREATE TABLE t2(x,y);
     INSERT INTO t1 VALUES(1, zeroblob(800));
     INSERT INTO t1 VALUES(2, zeroblob(800));
     INSERT INTO t2 SELECT * FROM t1;
     INSERT INTO t1 SELECT x+2, y FROM t2;
     INSERT INTO t2 SELECT a+10, b FROM t1;
     INSERT INTO t1 SELECT x+10, y FROM t2;
     INSERT INTO t2 SELECT a+100, b FROM t1;
     INSERT INTO t1 SELECT x+100, y FROM t2;
     INSERT INTO t2 SELECT a+1000, b FROM t1;
     INSERT INTO t1 SELECT x+1000, y FROM t2;
  }
  sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0
} {0 13 13}

catch {db2 close}
finish_test