/ Hex Artifact Content
Login

Artifact 52108517c38bcf023f3977085a66aacb520a5385:


0000: 2f 2a 0a 2a 2a 20 32 30 30 38 20 41 75 67 75 73  /*.** 2008 Augus
0010: 74 20 30 35 0a 2a 2a 0a 2a 2a 20 54 68 65 20 61  t 05.**.** The a
0020: 75 74 68 6f 72 20 64 69 73 63 6c 61 69 6d 73 20  uthor disclaims 
0030: 63 6f 70 79 72 69 67 68 74 20 74 6f 20 74 68 69  copyright to thi
0040: 73 20 73 6f 75 72 63 65 20 63 6f 64 65 2e 20 20  s source code.  
0050: 49 6e 20 70 6c 61 63 65 20 6f 66 0a 2a 2a 20 61  In place of.** a
0060: 20 6c 65 67 61 6c 20 6e 6f 74 69 63 65 2c 20 68   legal notice, h
0070: 65 72 65 20 69 73 20 61 20 62 6c 65 73 73 69 6e  ere is a blessin
0080: 67 3a 0a 2a 2a 0a 2a 2a 20 20 20 20 4d 61 79 20  g:.**.**    May 
0090: 79 6f 75 20 64 6f 20 67 6f 6f 64 20 61 6e 64 20  you do good and 
00a0: 6e 6f 74 20 65 76 69 6c 2e 0a 2a 2a 20 20 20 20  not evil..**    
00b0: 4d 61 79 20 79 6f 75 20 66 69 6e 64 20 66 6f 72  May you find for
00c0: 67 69 76 65 6e 65 73 73 20 66 6f 72 20 79 6f 75  giveness for you
00d0: 72 73 65 6c 66 20 61 6e 64 20 66 6f 72 67 69 76  rself and forgiv
00e0: 65 20 6f 74 68 65 72 73 2e 0a 2a 2a 20 20 20 20  e others..**    
00f0: 4d 61 79 20 79 6f 75 20 73 68 61 72 65 20 66 72  May you share fr
0100: 65 65 6c 79 2c 20 6e 65 76 65 72 20 74 61 6b 69  eely, never taki
0110: 6e 67 20 6d 6f 72 65 20 74 68 61 6e 20 79 6f 75  ng more than you
0120: 20 67 69 76 65 2e 0a 2a 2a 0a 2a 2a 2a 2a 2a 2a   give..**.******
0130: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0140: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0150: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0160: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0170: 2a 2a 2a 0a 2a 2a 20 54 68 69 73 20 66 69 6c 65  ***.** This file
0180: 20 69 6d 70 6c 65 6d 65 6e 74 73 20 74 68 61 74   implements that
0190: 20 70 61 67 65 20 63 61 63 68 65 2e 0a 2a 2a 0a   page cache..**.
01a0: 2a 2a 20 40 28 23 29 20 24 49 64 3a 20 70 63 61  ** @(#) $Id: pca
01b0: 63 68 65 2e 63 2c 76 20 31 2e 33 32 20 32 30 30  che.c,v 1.32 200
01c0: 38 2f 30 39 2f 32 34 20 30 39 3a 31 32 3a 34 37  8/09/24 09:12:47
01d0: 20 64 61 6e 69 65 6c 6b 31 39 37 37 20 45 78 70   danielk1977 Exp
01e0: 20 24 0a 2a 2f 0a 23 69 6e 63 6c 75 64 65 20 22   $.*/.#include "
01f0: 73 71 6c 69 74 65 49 6e 74 2e 68 22 0a 0a 2f 2a  sqliteInt.h"../*
0200: 0a 2a 2a 20 41 20 63 6f 6d 70 6c 65 74 65 20 70  .** A complete p
0210: 61 67 65 20 63 61 63 68 65 20 69 73 20 61 6e 20  age cache is an 
0220: 69 6e 73 74 61 6e 63 65 20 6f 66 20 74 68 69 73  instance of this
0230: 20 73 74 72 75 63 74 75 72 65 2e 0a 2a 2a 0a 2a   structure..**.*
0240: 2a 20 41 20 63 61 63 68 65 20 6d 61 79 20 6f 6e  * A cache may on
0250: 6c 79 20 62 65 20 64 65 6c 65 74 65 64 20 62 79  ly be deleted by
0260: 20 69 74 73 20 6f 77 6e 65 72 20 61 6e 64 20 77   its owner and w
0270: 68 69 6c 65 20 68 6f 6c 64 69 6e 67 20 74 68 65  hile holding the
0280: 0a 2a 2a 20 53 51 4c 49 54 45 5f 4d 55 54 45 58  .** SQLITE_MUTEX
0290: 5f 53 54 41 54 55 53 5f 4c 52 55 20 6d 75 74 65  _STATUS_LRU mute
02a0: 78 2e 0a 2a 2f 0a 73 74 72 75 63 74 20 50 43 61  x..*/.struct PCa
02b0: 63 68 65 20 7b 0a 20 20 2f 2a 2a 2a 2a 2a 2a 2a  che {.  /*******
02c0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
02d0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
02e0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
02f0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 0a 20  **************. 
0300: 20 2a 2a 20 54 68 65 20 66 69 72 73 74 20 67 72   ** The first gr
0310: 6f 75 70 20 6f 66 20 65 6c 65 6d 65 6e 74 73 20  oup of elements 
0320: 6d 61 79 20 62 65 20 72 65 61 64 20 6f 72 20 77  may be read or w
0330: 72 69 74 74 65 6e 20 61 74 20 61 6e 79 20 74 69  ritten at any ti
0340: 6d 65 20 62 79 0a 20 20 2a 2a 20 74 68 65 20 63  me by.  ** the c
0350: 61 63 68 65 20 6f 77 6e 65 72 20 77 69 74 68 6f  ache owner witho
0360: 75 74 20 68 6f 6c 64 69 6e 67 20 74 68 65 20 6d  ut holding the m
0370: 75 74 65 78 2e 20 20 4e 6f 20 74 68 72 65 61 64  utex.  No thread
0380: 20 6f 74 68 65 72 20 74 68 61 6e 20 74 68 65 0a   other than the.
0390: 20 20 2a 2a 20 63 61 63 68 65 20 6f 77 6e 65 72    ** cache owner
03a0: 20 69 73 20 70 65 72 6d 69 74 74 65 64 20 74 6f   is permitted to
03b0: 20 61 63 63 65 73 73 20 74 68 65 73 65 20 65 6c   access these el
03c0: 65 6d 65 6e 74 73 20 61 74 20 61 6e 79 20 74 69  ements at any ti
03d0: 6d 65 2e 0a 20 20 2a 2f 0a 20 20 50 67 48 64 72  me..  */.  PgHdr
03e0: 20 2a 70 44 69 72 74 79 2c 20 2a 70 44 69 72 74   *pDirty, *pDirt
03f0: 79 54 61 69 6c 3b 20 20 20 20 20 20 20 20 20 2f  yTail;         /
0400: 2a 20 4c 69 73 74 20 6f 66 20 64 69 72 74 79 20  * List of dirty 
0410: 70 61 67 65 73 20 69 6e 20 4c 52 55 20 6f 72 64  pages in LRU ord
0420: 65 72 20 2a 2f 0a 20 20 50 67 48 64 72 20 2a 70  er */.  PgHdr *p
0430: 53 79 6e 63 65 64 3b 20 20 20 20 20 20 20 20 20  Synced;         
0440: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4c              /* L
0450: 61 73 74 20 73 79 6e 63 65 64 20 70 61 67 65 20  ast synced page 
0460: 69 6e 20 64 69 72 74 79 20 70 61 67 65 20 6c 69  in dirty page li
0470: 73 74 20 2a 2f 0a 20 20 69 6e 74 20 6e 52 65 66  st */.  int nRef
0480: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ;               
0490: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4e              /* N
04a0: 75 6d 62 65 72 20 6f 66 20 70 69 6e 6e 65 64 20  umber of pinned 
04b0: 70 61 67 65 73 20 2a 2f 0a 20 20 69 6e 74 20 6e  pages */.  int n
04c0: 50 69 6e 6e 65 64 3b 20 20 20 20 20 20 20 20 20  Pinned;         
04d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
04e0: 2a 20 4e 75 6d 62 65 72 20 6f 66 20 70 69 6e 6e  * Number of pinn
04f0: 65 64 20 61 6e 64 2f 6f 72 20 64 69 72 74 79 20  ed and/or dirty 
0500: 70 61 67 65 73 20 2a 2f 0a 20 20 69 6e 74 20 6e  pages */.  int n
0510: 4d 61 78 3b 20 20 20 20 20 20 20 20 20 20 20 20  Max;            
0520: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
0530: 2a 20 43 6f 6e 66 69 67 75 72 65 64 20 63 61 63  * Configured cac
0540: 68 65 20 73 69 7a 65 20 2a 2f 0a 20 20 69 6e 74  he size */.  int
0550: 20 6e 4d 69 6e 3b 20 20 20 20 20 20 20 20 20 20   nMin;          
0560: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0570: 20 2f 2a 20 43 6f 6e 66 69 67 75 72 65 64 20 6d   /* Configured m
0580: 69 6e 69 6d 75 6d 20 63 61 63 68 65 20 73 69 7a  inimum cache siz
0590: 65 20 2a 2f 0a 20 20 2f 2a 2a 2a 2a 2a 2a 2a 2a  e */.  /********
05a0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
05b0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
05c0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
05d0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 0a 20  **************. 
05e0: 20 2a 2a 20 54 68 65 20 6e 65 78 74 20 67 72 6f   ** The next gro
05f0: 75 70 20 6f 66 20 65 6c 65 6d 65 6e 74 73 20 61  up of elements a
0600: 72 65 20 66 69 78 65 64 20 77 68 65 6e 20 74 68  re fixed when th
0610: 65 20 63 61 63 68 65 20 69 73 20 63 72 65 61 74  e cache is creat
0620: 65 64 20 61 6e 64 0a 20 20 2a 2a 20 6d 61 79 20  ed and.  ** may 
0630: 6e 6f 74 20 62 65 20 63 68 61 6e 67 65 64 20 61  not be changed a
0640: 66 74 65 72 77 61 72 64 73 2e 20 20 54 68 65 73  fterwards.  Thes
0650: 65 20 65 6c 65 6d 65 6e 74 73 20 63 61 6e 20 72  e elements can r
0660: 65 61 64 20 61 74 20 61 6e 79 20 74 69 6d 65 20  ead at any time 
0670: 62 79 0a 20 20 2a 2a 20 74 68 65 20 63 61 63 68  by.  ** the cach
0680: 65 20 6f 77 6e 65 72 20 6f 72 20 62 79 20 61 6e  e owner or by an
0690: 79 20 74 68 72 65 61 64 20 68 6f 6c 64 69 6e 67  y thread holding
06a0: 20 74 68 65 20 74 68 65 20 6d 75 74 65 78 2e 20   the the mutex. 
06b0: 20 4e 6f 6e 2d 6f 77 6e 65 72 0a 20 20 2a 2a 20   Non-owner.  ** 
06c0: 74 68 72 65 61 64 73 20 6d 75 73 74 20 68 6f 6c  threads must hol
06d0: 64 20 74 68 65 20 6d 75 74 65 78 20 77 68 65 6e  d the mutex when
06e0: 20 72 65 61 64 69 6e 67 20 74 68 65 73 65 20 65   reading these e
06f0: 6c 65 6d 65 6e 74 73 20 74 6f 20 70 72 65 76 65  lements to preve
0700: 6e 74 0a 20 20 2a 2a 20 74 68 65 20 65 6e 74 69  nt.  ** the enti
0710: 72 65 20 50 43 61 63 68 65 20 6f 62 6a 65 63 74  re PCache object
0720: 20 66 72 6f 6d 20 62 65 69 6e 67 20 64 65 6c 65   from being dele
0730: 74 65 64 20 64 75 72 69 6e 67 20 74 68 65 20 72  ted during the r
0740: 65 61 64 2e 0a 20 20 2a 2f 0a 20 20 69 6e 74 20  ead..  */.  int 
0750: 73 7a 50 61 67 65 3b 20 20 20 20 20 20 20 20 20  szPage;         
0760: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0770: 2f 2a 20 53 69 7a 65 20 6f 66 20 65 76 65 72 79  /* Size of every
0780: 20 70 61 67 65 20 69 6e 20 74 68 69 73 20 63 61   page in this ca
0790: 63 68 65 20 2a 2f 0a 20 20 69 6e 74 20 73 7a 45  che */.  int szE
07a0: 78 74 72 61 3b 20 20 20 20 20 20 20 20 20 20 20  xtra;           
07b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
07c0: 53 69 7a 65 20 6f 66 20 65 78 74 72 61 20 73 70  Size of extra sp
07d0: 61 63 65 20 66 6f 72 20 65 61 63 68 20 70 61 67  ace for each pag
07e0: 65 20 2a 2f 0a 20 20 69 6e 74 20 62 50 75 72 67  e */.  int bPurg
07f0: 65 61 62 6c 65 3b 20 20 20 20 20 20 20 20 20 20  eable;          
0800: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 54 72             /* Tr
0810: 75 65 20 69 66 20 70 61 67 65 73 20 61 72 65 20  ue if pages are 
0820: 6f 6e 20 62 61 63 6b 69 6e 67 20 73 74 6f 72 65  on backing store
0830: 20 2a 2f 0a 20 20 76 6f 69 64 20 28 2a 78 44 65   */.  void (*xDe
0840: 73 74 72 6f 79 29 28 50 67 48 64 72 2a 29 3b 20  stroy)(PgHdr*); 
0850: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 43 61 6c            /* Cal
0860: 6c 65 64 20 77 68 65 6e 20 72 65 66 63 6e 74 20  led when refcnt 
0870: 67 6f 65 73 20 31 2d 3e 30 20 2a 2f 0a 20 20 69  goes 1->0 */.  i
0880: 6e 74 20 28 2a 78 53 74 72 65 73 73 29 28 76 6f  nt (*xStress)(vo
0890: 69 64 2a 2c 50 67 48 64 72 2a 29 3b 20 20 20 20  id*,PgHdr*);    
08a0: 20 20 20 2f 2a 20 43 61 6c 6c 20 74 6f 20 74 72     /* Call to tr
08b0: 79 20 6d 61 6b 65 20 61 20 70 61 67 65 20 63 6c  y make a page cl
08c0: 65 61 6e 20 2a 2f 0a 20 20 76 6f 69 64 20 2a 70  ean */.  void *p
08d0: 53 74 72 65 73 73 3b 20 20 20 20 20 20 20 20 20  Stress;         
08e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
08f0: 41 72 67 75 6d 65 6e 74 20 74 6f 20 78 53 74 72  Argument to xStr
0900: 65 73 73 20 2a 2f 0a 20 20 2f 2a 2a 2a 2a 2a 2a  ess */.  /******
0910: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0920: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0930: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0940: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0950: 0a 20 20 2a 2a 20 54 68 65 20 66 69 6e 61 6c 20  .  ** The final 
0960: 67 72 6f 75 70 20 6f 66 20 65 6c 65 6d 65 6e 74  group of element
0970: 73 20 63 61 6e 20 6f 6e 6c 79 20 62 65 20 61 63  s can only be ac
0980: 63 65 73 73 65 64 20 77 68 69 6c 65 20 68 6f 6c  cessed while hol
0990: 64 69 6e 67 20 74 68 65 0a 20 20 2a 2a 20 6d 75  ding the.  ** mu
09a0: 74 65 78 2e 20 20 42 6f 74 68 20 74 68 65 20 63  tex.  Both the c
09b0: 61 63 68 65 20 6f 77 6e 65 72 20 61 6e 64 20 61  ache owner and a
09c0: 6e 79 20 6f 74 68 65 72 20 74 68 72 65 61 64 20  ny other thread 
09d0: 6d 75 73 74 20 68 6f 6c 64 20 74 68 65 20 6d 75  must hold the mu
09e0: 74 65 78 0a 20 20 2a 2a 20 74 6f 20 72 65 61 64  tex.  ** to read
09f0: 20 6f 72 20 77 72 69 74 65 20 61 6e 79 20 6f 66   or write any of
0a00: 20 74 68 65 73 65 20 65 6c 65 6d 65 6e 74 73 2e   these elements.
0a10: 0a 20 20 2a 2f 0a 20 20 69 6e 74 20 6e 50 61 67  .  */.  int nPag
0a20: 65 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  e;              
0a30: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 54              /* T
0a40: 6f 74 61 6c 20 6e 75 6d 62 65 72 20 6f 66 20 70  otal number of p
0a50: 61 67 65 73 20 69 6e 20 61 70 48 61 73 68 20 2a  ages in apHash *
0a60: 2f 0a 20 20 69 6e 74 20 6e 48 61 73 68 3b 20 20  /.  int nHash;  
0a70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0a80: 20 20 20 20 20 20 20 20 2f 2a 20 4e 75 6d 62 65          /* Numbe
0a90: 72 20 6f 66 20 73 6c 6f 74 73 20 69 6e 20 61 70  r of slots in ap
0aa0: 48 61 73 68 5b 5d 20 2a 2f 0a 20 20 50 67 48 64  Hash[] */.  PgHd
0ab0: 72 20 2a 2a 61 70 48 61 73 68 3b 20 20 20 20 20  r **apHash;     
0ac0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0ad0: 2f 2a 20 48 61 73 68 20 74 61 62 6c 65 20 66 6f  /* Hash table fo
0ae0: 72 20 66 61 73 74 20 6c 6f 6f 6b 75 70 20 62 79  r fast lookup by
0af0: 20 70 67 6e 6f 20 2a 2f 0a 20 20 50 67 48 64 72   pgno */.  PgHdr
0b00: 20 2a 70 43 6c 65 61 6e 3b 20 20 20 20 20 20 20   *pClean;       
0b10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
0b20: 2a 20 4c 69 73 74 20 6f 66 20 63 6c 65 61 6e 20  * List of clean 
0b30: 70 61 67 65 73 20 69 6e 20 75 73 65 20 2a 2f 0a  pages in use */.
0b40: 7d 3b 0a 0a 2f 2a 0a 2a 2a 20 46 72 65 65 20 73  };../*.** Free s
0b50: 6c 6f 74 73 20 69 6e 20 74 68 65 20 70 61 67 65  lots in the page
0b60: 20 62 6c 6f 63 6b 20 61 6c 6c 6f 63 61 74 6f 72   block allocator
0b70: 0a 2a 2f 0a 74 79 70 65 64 65 66 20 73 74 72 75  .*/.typedef stru
0b80: 63 74 20 50 67 46 72 65 65 73 6c 6f 74 20 50 67  ct PgFreeslot Pg
0b90: 46 72 65 65 73 6c 6f 74 3b 0a 73 74 72 75 63 74  Freeslot;.struct
0ba0: 20 50 67 46 72 65 65 73 6c 6f 74 20 7b 0a 20 20   PgFreeslot {.  
0bb0: 50 67 46 72 65 65 73 6c 6f 74 20 2a 70 4e 65 78  PgFreeslot *pNex
0bc0: 74 3b 20 20 2f 2a 20 4e 65 78 74 20 66 72 65 65  t;  /* Next free
0bd0: 20 73 6c 6f 74 20 2a 2f 0a 7d 3b 0a 0a 2f 2a 0a   slot */.};../*.
0be0: 2a 2a 20 47 6c 6f 62 61 6c 20 64 61 74 61 20 66  ** Global data f
0bf0: 6f 72 20 74 68 65 20 70 61 67 65 20 63 61 63 68  or the page cach
0c00: 65 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 53 51 4c  e..*/.static SQL
0c10: 49 54 45 5f 57 53 44 20 73 74 72 75 63 74 20 50  ITE_WSD struct P
0c20: 43 61 63 68 65 47 6c 6f 62 61 6c 20 7b 0a 20 20  CacheGlobal {.  
0c30: 69 6e 74 20 69 73 49 6e 69 74 3b 20 20 20 20 20  int isInit;     
0c40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0c50: 20 20 20 20 2f 2a 20 54 72 75 65 20 77 68 65 6e      /* True when
0c60: 20 69 6e 69 74 69 61 6c 69 7a 65 64 20 2a 2f 0a   initialized */.
0c70: 20 20 73 71 6c 69 74 65 33 5f 6d 75 74 65 78 20    sqlite3_mutex 
0c80: 2a 6d 75 74 65 78 3b 20 20 20 20 20 20 20 20 20  *mutex;         
0c90: 20 20 20 20 20 20 2f 2a 20 73 74 61 74 69 63 20        /* static 
0ca0: 6d 75 74 65 78 20 4d 55 54 45 58 5f 53 54 41 54  mutex MUTEX_STAT
0cb0: 49 43 5f 4c 52 55 20 2a 2f 0a 0a 20 20 69 6e 74  IC_LRU */..  int
0cc0: 20 6e 4d 61 78 50 61 67 65 3b 20 20 20 20 20 20   nMaxPage;      
0cd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0ce0: 20 2f 2a 20 53 75 6d 20 6f 66 20 6e 4d 61 78 50   /* Sum of nMaxP
0cf0: 61 67 65 20 66 6f 72 20 70 75 72 67 65 61 62 6c  age for purgeabl
0d00: 65 20 63 61 63 68 65 73 20 2a 2f 0a 20 20 69 6e  e caches */.  in
0d10: 74 20 6e 4d 69 6e 50 61 67 65 3b 20 20 20 20 20  t nMinPage;     
0d20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0d30: 20 20 2f 2a 20 53 75 6d 20 6f 66 20 6e 4d 69 6e    /* Sum of nMin
0d40: 50 61 67 65 20 66 6f 72 20 70 75 72 67 65 61 62  Page for purgeab
0d50: 6c 65 20 63 61 63 68 65 73 20 2a 2f 0a 20 20 69  le caches */.  i
0d60: 6e 74 20 6e 43 75 72 72 65 6e 74 50 61 67 65 3b  nt nCurrentPage;
0d70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0d80: 20 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f 66 20     /* Number of 
0d90: 70 75 72 67 65 61 62 6c 65 20 70 61 67 65 73 20  purgeable pages 
0da0: 61 6c 6c 6f 63 61 74 65 64 20 2a 2f 0a 20 20 50  allocated */.  P
0db0: 67 48 64 72 20 2a 70 4c 72 75 48 65 61 64 2c 20  gHdr *pLruHead, 
0dc0: 2a 70 4c 72 75 54 61 69 6c 3b 20 20 20 20 20 20  *pLruTail;      
0dd0: 20 20 20 2f 2a 20 4c 52 55 20 6c 69 73 74 20 6f     /* LRU list o
0de0: 66 20 75 6e 75 73 65 64 20 63 6c 65 61 6e 20 70  f unused clean p
0df0: 67 73 20 2a 2f 0a 0a 20 20 2f 2a 20 56 61 72 69  gs */..  /* Vari
0e00: 61 62 6c 65 73 20 72 65 6c 61 74 65 64 20 74 6f  ables related to
0e10: 20 53 51 4c 49 54 45 5f 43 4f 4e 46 49 47 5f 50   SQLITE_CONFIG_P
0e20: 41 47 45 43 41 43 48 45 20 73 65 74 74 69 6e 67  AGECACHE setting
0e30: 73 2e 20 2a 2f 0a 20 20 69 6e 74 20 73 7a 53 6c  s. */.  int szSl
0e40: 6f 74 3b 20 20 20 20 20 20 20 20 20 20 20 20 20  ot;             
0e50: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 53              /* S
0e60: 69 7a 65 20 6f 66 20 65 61 63 68 20 66 72 65 65  ize of each free
0e70: 20 73 6c 6f 74 20 2a 2f 0a 20 20 76 6f 69 64 20   slot */.  void 
0e80: 2a 70 53 74 61 72 74 2c 20 2a 70 45 6e 64 3b 20  *pStart, *pEnd; 
0e90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
0ea0: 2a 20 42 6f 75 6e 64 73 20 6f 66 20 70 61 67 65  * Bounds of page
0eb0: 63 61 63 68 65 20 6d 61 6c 6c 6f 63 20 72 61 6e  cache malloc ran
0ec0: 67 65 20 2a 2f 0a 20 20 50 67 46 72 65 65 73 6c  ge */.  PgFreesl
0ed0: 6f 74 20 2a 70 46 72 65 65 3b 20 20 20 20 20 20  ot *pFree;      
0ee0: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 46              /* F
0ef0: 72 65 65 20 70 61 67 65 20 62 6c 6f 63 6b 73 20  ree page blocks 
0f00: 2a 2f 0a 7d 20 70 63 61 63 68 65 20 3d 20 7b 30  */.} pcache = {0
0f10: 7d 3b 0a 0a 2f 2a 0a 2a 2a 20 41 6c 6c 20 63 6f  };../*.** All co
0f20: 64 65 20 69 6e 20 74 68 69 73 20 66 69 6c 65 20  de in this file 
0f30: 73 68 6f 75 6c 64 20 61 63 63 65 73 73 20 74 68  should access th
0f40: 65 20 67 6c 6f 62 61 6c 20 70 63 61 63 68 65 20  e global pcache 
0f50: 73 74 72 75 63 74 75 72 65 20 76 69 61 20 74 68  structure via th
0f60: 65 0a 2a 2a 20 61 6c 69 61 73 20 22 70 63 61 63  e.** alias "pcac
0f70: 68 65 5f 67 22 2e 20 54 68 69 73 20 65 6e 73 75  he_g". This ensu
0f80: 72 65 73 20 74 68 61 74 20 74 68 65 20 57 53 44  res that the WSD
0f90: 20 65 6d 75 6c 61 74 69 6f 6e 20 69 73 20 75 73   emulation is us
0fa0: 65 64 20 77 68 65 6e 0a 2a 2a 20 63 6f 6d 70 69  ed when.** compi
0fb0: 6c 69 6e 67 20 66 6f 72 20 73 79 73 74 65 6d 73  ling for systems
0fc0: 20 74 68 61 74 20 64 6f 20 6e 6f 74 20 73 75 70   that do not sup
0fd0: 70 6f 72 74 20 72 65 61 6c 20 57 53 44 2e 0a 2a  port real WSD..*
0fe0: 2f 0a 23 64 65 66 69 6e 65 20 70 63 61 63 68 65  /.#define pcache
0ff0: 5f 67 20 28 47 4c 4f 42 41 4c 28 73 74 72 75 63  _g (GLOBAL(struc
1000: 74 20 50 43 61 63 68 65 47 6c 6f 62 61 6c 2c 20  t PCacheGlobal, 
1010: 70 63 61 63 68 65 29 29 0a 0a 2f 2a 0a 2a 2a 20  pcache))../*.** 
1020: 41 6c 6c 20 67 6c 6f 62 61 6c 20 76 61 72 69 61  All global varia
1030: 62 6c 65 73 20 75 73 65 64 20 62 79 20 74 68 69  bles used by thi
1040: 73 20 6d 6f 64 75 6c 65 20 28 61 6c 6c 20 6f 66  s module (all of
1050: 20 77 68 69 63 68 20 61 72 65 20 67 72 6f 75 70   which are group
1060: 65 64 20 0a 2a 2a 20 74 6f 67 65 74 68 65 72 20  ed .** together 
1070: 69 6e 20 67 6c 6f 62 61 6c 20 73 74 72 75 63 74  in global struct
1080: 75 72 65 20 22 70 63 61 63 68 65 22 20 61 62 6f  ure "pcache" abo
1090: 76 65 29 20 61 72 65 20 70 72 6f 74 65 63 74 65  ve) are protecte
10a0: 64 20 62 79 20 74 68 65 20 73 74 61 74 69 63 20  d by the static 
10b0: 0a 2a 2a 20 53 51 4c 49 54 45 5f 4d 55 54 45 58  .** SQLITE_MUTEX
10c0: 5f 53 54 41 54 49 43 5f 4c 52 55 20 6d 75 74 65  _STATIC_LRU mute
10d0: 78 2e 20 41 20 70 6f 69 6e 74 65 72 20 74 6f 20  x. A pointer to 
10e0: 74 68 69 73 20 6d 75 74 65 78 20 69 73 20 73 74  this mutex is st
10f0: 6f 72 65 64 20 69 6e 0a 2a 2a 20 76 61 72 69 61  ored in.** varia
1100: 62 6c 65 20 22 70 63 61 63 68 65 2e 6d 75 74 65  ble "pcache.mute
1110: 78 22 2e 0a 2a 2a 0a 2a 2a 20 53 6f 6d 65 20 65  x"..**.** Some e
1120: 6c 65 6d 65 6e 74 73 20 6f 66 20 74 68 65 20 50  lements of the P
1130: 43 61 63 68 65 20 61 6e 64 20 50 67 48 64 72 20  Cache and PgHdr 
1140: 73 74 72 75 63 74 75 72 65 73 20 61 72 65 20 70  structures are p
1150: 72 6f 74 65 63 74 65 64 20 62 79 20 74 68 65 20  rotected by the 
1160: 0a 2a 2a 20 53 51 4c 49 54 45 5f 4d 55 54 45 58  .** SQLITE_MUTEX
1170: 5f 53 54 41 54 55 53 5f 4c 52 55 20 6d 75 74 65  _STATUS_LRU mute
1180: 78 20 61 6e 64 20 6f 74 68 65 72 20 61 72 65 20  x and other are 
1190: 6e 6f 74 2e 20 20 54 68 65 20 70 72 6f 74 65 63  not.  The protec
11a0: 74 65 64 0a 2a 2a 20 65 6c 65 6d 65 6e 74 73 20  ted.** elements 
11b0: 61 72 65 20 67 72 6f 75 70 65 64 20 61 74 20 74  are grouped at t
11c0: 68 65 20 65 6e 64 20 6f 66 20 74 68 65 20 73 74  he end of the st
11d0: 72 75 63 74 75 72 65 73 20 61 6e 64 20 61 72 65  ructures and are
11e0: 20 63 6c 65 61 72 6c 79 0a 2a 2a 20 6d 61 72 6b   clearly.** mark
11f0: 65 64 2e 0a 2a 2a 0a 2a 2a 20 55 73 65 20 74 68  ed..**.** Use th
1200: 65 20 66 6f 6c 6c 6f 77 69 6e 67 20 6d 61 63 72  e following macr
1210: 6f 73 20 6d 75 73 74 20 73 75 72 72 6f 75 6e 64  os must surround
1220: 20 61 6c 6c 20 61 63 63 65 73 73 20 28 72 65 61   all access (rea
1230: 64 20 6f 72 20 77 72 69 74 65 29 0a 2a 2a 20 6f  d or write).** o
1240: 66 20 70 72 6f 74 65 63 74 65 64 20 65 6c 65 6d  f protected elem
1250: 65 6e 74 73 2e 20 20 54 68 65 20 6d 75 74 65 78  ents.  The mutex
1260: 20 69 73 20 6e 6f 74 20 72 65 63 75 72 73 69 76   is not recursiv
1270: 65 20 61 6e 64 20 6d 61 79 20 6e 6f 74 20 62 65  e and may not be
1280: 0a 2a 2a 20 65 6e 74 65 72 65 64 20 6d 6f 72 65  .** entered more
1290: 20 74 68 61 6e 20 6f 6e 63 65 2e 20 20 54 68 65   than once.  The
12a0: 20 70 63 61 63 68 65 4d 75 74 65 78 48 65 6c 64   pcacheMutexHeld
12b0: 28 29 20 6d 61 63 72 6f 20 73 68 6f 75 6c 64 20  () macro should 
12c0: 6f 6e 6c 79 20 62 65 0a 2a 2a 20 75 73 65 64 20  only be.** used 
12d0: 77 69 74 68 69 6e 20 61 6e 20 61 73 73 65 72 74  within an assert
12e0: 28 29 20 74 6f 20 76 65 72 69 66 79 20 74 68 61  () to verify tha
12f0: 74 20 74 68 65 20 6d 75 74 65 78 20 69 73 20 62  t the mutex is b
1300: 65 69 6e 67 20 68 65 6c 64 2e 0a 2a 2f 0a 23 64  eing held..*/.#d
1310: 65 66 69 6e 65 20 70 63 61 63 68 65 45 6e 74 65  efine pcacheEnte
1320: 72 4d 75 74 65 78 28 29 20 73 71 6c 69 74 65 33  rMutex() sqlite3
1330: 5f 6d 75 74 65 78 5f 65 6e 74 65 72 28 70 63 61  _mutex_enter(pca
1340: 63 68 65 5f 67 2e 6d 75 74 65 78 29 0a 23 64 65  che_g.mutex).#de
1350: 66 69 6e 65 20 70 63 61 63 68 65 45 78 69 74 4d  fine pcacheExitM
1360: 75 74 65 78 28 29 20 20 73 71 6c 69 74 65 33 5f  utex()  sqlite3_
1370: 6d 75 74 65 78 5f 6c 65 61 76 65 28 70 63 61 63  mutex_leave(pcac
1380: 68 65 5f 67 2e 6d 75 74 65 78 29 0a 23 64 65 66  he_g.mutex).#def
1390: 69 6e 65 20 70 63 61 63 68 65 4d 75 74 65 78 48  ine pcacheMutexH
13a0: 65 6c 64 28 29 20 20 73 71 6c 69 74 65 33 5f 6d  eld()  sqlite3_m
13b0: 75 74 65 78 5f 68 65 6c 64 28 70 63 61 63 68 65  utex_held(pcache
13c0: 5f 67 2e 6d 75 74 65 78 29 0a 0a 2f 2a 0a 2a 2a  _g.mutex)../*.**
13d0: 20 53 6f 6d 65 20 6f 66 20 74 68 65 20 61 73 73   Some of the ass
13e0: 65 72 74 28 29 20 6d 61 63 72 6f 73 20 69 6e 20  ert() macros in 
13f0: 74 68 69 73 20 63 6f 64 65 20 61 72 65 20 74 6f  this code are to
1400: 6f 20 65 78 70 65 6e 73 69 76 65 20 74 6f 20 72  o expensive to r
1410: 75 6e 0a 2a 2a 20 65 76 65 6e 20 64 75 72 69 6e  un.** even durin
1420: 67 20 6e 6f 72 6d 61 6c 20 64 65 62 75 67 67 69  g normal debuggi
1430: 6e 67 2e 20 20 55 73 65 20 74 68 65 6d 20 6f 6e  ng.  Use them on
1440: 6c 79 20 72 61 72 65 6c 79 20 6f 6e 20 6c 6f 6e  ly rarely on lon
1450: 67 2d 72 75 6e 6e 69 6e 67 0a 2a 2a 20 74 65 73  g-running.** tes
1460: 74 73 2e 20 20 45 6e 61 62 6c 65 20 74 68 65 20  ts.  Enable the 
1470: 65 78 70 65 6e 73 69 76 65 20 61 73 73 65 72 74  expensive assert
1480: 73 20 75 73 69 6e 67 20 74 68 65 0a 2a 2a 20 2d  s using the.** -
1490: 44 53 51 4c 49 54 45 5f 45 4e 41 42 4c 45 5f 45  DSQLITE_ENABLE_E
14a0: 58 50 45 4e 53 49 56 45 5f 41 53 53 45 52 54 3d  XPENSIVE_ASSERT=
14b0: 31 20 63 6f 6d 70 69 6c 65 2d 74 69 6d 65 20 6f  1 compile-time o
14c0: 70 74 69 6f 6e 2e 0a 2a 2f 0a 23 69 66 64 65 66  ption..*/.#ifdef
14d0: 20 53 51 4c 49 54 45 5f 45 4e 41 42 4c 45 5f 45   SQLITE_ENABLE_E
14e0: 58 50 45 4e 53 49 56 45 5f 41 53 53 45 52 54 0a  XPENSIVE_ASSERT.
14f0: 23 20 64 65 66 69 6e 65 20 65 78 70 65 6e 73 69  # define expensi
1500: 76 65 5f 61 73 73 65 72 74 28 58 29 20 20 61 73  ve_assert(X)  as
1510: 73 65 72 74 28 58 29 0a 23 65 6c 73 65 0a 23 20  sert(X).#else.# 
1520: 64 65 66 69 6e 65 20 65 78 70 65 6e 73 69 76 65  define expensive
1530: 5f 61 73 73 65 72 74 28 58 29 0a 23 65 6e 64 69  _assert(X).#endi
1540: 66 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  f../************
1550: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1560: 2a 2a 2a 2a 2a 2a 20 4c 69 6e 6b 65 64 20 4c 69  ****** Linked Li
1570: 73 74 20 4d 61 6e 61 67 65 6d 65 6e 74 20 2a 2a  st Management **
1580: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1590: 2a 2a 2f 0a 0a 23 69 66 20 21 64 65 66 69 6e 65  **/..#if !define
15a0: 64 28 4e 44 45 42 55 47 29 20 26 26 20 64 65 66  d(NDEBUG) && def
15b0: 69 6e 65 64 28 53 51 4c 49 54 45 5f 45 4e 41 42  ined(SQLITE_ENAB
15c0: 4c 45 5f 45 58 50 45 4e 53 49 56 45 5f 41 53 53  LE_EXPENSIVE_ASS
15d0: 45 52 54 29 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20  ERT)./*.** This 
15e0: 72 6f 75 74 69 6e 65 20 76 65 72 69 66 69 65 73  routine verifies
15f0: 20 74 68 61 74 20 74 68 65 20 6e 75 6d 62 65 72   that the number
1600: 20 6f 66 20 65 6e 74 72 69 65 73 20 69 6e 20 74   of entries in t
1610: 68 65 20 68 61 73 68 20 74 61 62 6c 65 0a 2a 2a  he hash table.**
1620: 20 69 73 20 70 43 61 63 68 65 2d 3e 6e 50 61 67   is pCache->nPag
1630: 65 2e 20 20 54 68 69 73 20 72 6f 75 74 69 6e 65  e.  This routine
1640: 20 69 73 20 75 73 65 64 20 77 69 74 68 69 6e 20   is used within 
1650: 61 73 73 65 72 74 28 29 20 73 74 61 74 65 6d 65  assert() stateme
1660: 6e 74 73 0a 2a 2a 20 6f 6e 6c 79 20 61 6e 64 20  nts.** only and 
1670: 69 73 20 74 68 65 72 65 66 6f 72 65 20 64 69 73  is therefore dis
1680: 61 62 6c 65 64 20 64 75 72 69 6e 67 20 70 72 6f  abled during pro
1690: 64 75 63 74 69 6f 6e 20 62 75 69 6c 64 73 2e 0a  duction builds..
16a0: 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 70 63  */.static int pc
16b0: 61 63 68 65 43 68 65 63 6b 48 61 73 68 43 6f 75  acheCheckHashCou
16c0: 6e 74 28 50 43 61 63 68 65 20 2a 70 43 61 63 68  nt(PCache *pCach
16d0: 65 29 7b 0a 20 20 69 6e 74 20 69 3b 0a 20 20 69  e){.  int i;.  i
16e0: 6e 74 20 6e 50 61 67 65 20 3d 20 30 3b 0a 20 20  nt nPage = 0;.  
16f0: 66 6f 72 28 69 3d 30 3b 20 69 3c 70 43 61 63 68  for(i=0; i<pCach
1700: 65 2d 3e 6e 48 61 73 68 3b 20 69 2b 2b 29 7b 0a  e->nHash; i++){.
1710: 20 20 20 20 50 67 48 64 72 20 2a 70 3b 0a 20 20      PgHdr *p;.  
1720: 20 20 66 6f 72 28 70 3d 70 43 61 63 68 65 2d 3e    for(p=pCache->
1730: 61 70 48 61 73 68 5b 69 5d 3b 20 70 3b 20 70 3d  apHash[i]; p; p=
1740: 70 2d 3e 70 4e 65 78 74 48 61 73 68 29 7b 0a 20  p->pNextHash){. 
1750: 20 20 20 20 20 6e 50 61 67 65 2b 2b 3b 0a 20 20       nPage++;.  
1760: 20 20 7d 0a 20 20 7d 0a 20 20 61 73 73 65 72 74    }.  }.  assert
1770: 28 20 6e 50 61 67 65 3d 3d 70 43 61 63 68 65 2d  ( nPage==pCache-
1780: 3e 6e 50 61 67 65 20 29 3b 0a 20 20 72 65 74 75  >nPage );.  retu
1790: 72 6e 20 31 3b 0a 7d 0a 23 65 6e 64 69 66 20 2f  rn 1;.}.#endif /
17a0: 2a 20 21 4e 44 45 42 55 47 20 26 26 20 53 51 4c  * !NDEBUG && SQL
17b0: 49 54 45 5f 45 4e 41 42 4c 45 5f 45 58 50 45 4e  ITE_ENABLE_EXPEN
17c0: 53 49 56 45 5f 41 53 53 45 52 54 20 2a 2f 0a 0a  SIVE_ASSERT */..
17d0: 0a 23 69 66 20 21 64 65 66 69 6e 65 64 28 4e 44  .#if !defined(ND
17e0: 45 42 55 47 29 20 26 26 20 64 65 66 69 6e 65 64  EBUG) && defined
17f0: 28 53 51 4c 49 54 45 5f 45 4e 41 42 4c 45 5f 45  (SQLITE_ENABLE_E
1800: 58 50 45 4e 53 49 56 45 5f 41 53 53 45 52 54 29  XPENSIVE_ASSERT)
1810: 0a 2f 2a 0a 2a 2a 20 42 61 73 65 64 20 6f 6e 20  ./*.** Based on 
1820: 74 68 65 20 63 75 72 72 65 6e 74 20 76 61 6c 75  the current valu
1830: 65 20 6f 66 20 50 43 61 63 68 65 2e 6e 52 65 66  e of PCache.nRef
1840: 20 61 6e 64 20 74 68 65 20 63 6f 6e 74 65 6e 74   and the content
1850: 73 20 6f 66 20 74 68 65 0a 2a 2a 20 50 43 61 63  s of the.** PCac
1860: 68 65 2e 70 44 69 72 74 79 20 6c 69 73 74 2c 20  he.pDirty list, 
1870: 72 65 74 75 72 6e 20 74 68 65 20 65 78 70 65 63  return the expec
1880: 74 65 64 20 76 61 6c 75 65 20 6f 66 20 74 68 65  ted value of the
1890: 20 50 43 61 63 68 65 2e 6e 50 69 6e 6e 65 64 0a   PCache.nPinned.
18a0: 2a 2a 20 63 6f 75 6e 74 65 72 2e 20 54 68 69 73  ** counter. This
18b0: 20 69 73 20 6f 6e 6c 79 20 75 73 65 64 20 69 6e   is only used in
18c0: 20 64 65 62 75 67 67 69 6e 67 20 62 75 69 6c 64   debugging build
18d0: 73 2c 20 61 73 20 66 6f 6c 6c 6f 77 73 3a 0a 2a  s, as follows:.*
18e0: 2a 0a 2a 2a 20 20 20 65 78 70 65 6e 73 69 76 65  *.**   expensive
18f0: 5f 61 73 73 65 72 74 28 20 70 43 61 63 68 65 2d  _assert( pCache-
1900: 3e 6e 50 69 6e 6e 65 64 3d 3d 70 63 61 63 68 65  >nPinned==pcache
1910: 50 69 6e 6e 65 64 43 6f 75 6e 74 28 70 43 61 63  PinnedCount(pCac
1920: 68 65 29 20 29 3b 0a 2a 2f 0a 73 74 61 74 69 63  he) );.*/.static
1930: 20 69 6e 74 20 70 63 61 63 68 65 50 69 6e 6e 65   int pcachePinne
1940: 64 43 6f 75 6e 74 28 50 43 61 63 68 65 20 2a 70  dCount(PCache *p
1950: 43 61 63 68 65 29 7b 0a 20 20 50 67 48 64 72 20  Cache){.  PgHdr 
1960: 2a 70 3b 0a 20 20 69 6e 74 20 6e 50 69 6e 6e 65  *p;.  int nPinne
1970: 64 20 3d 20 70 43 61 63 68 65 2d 3e 6e 52 65 66  d = pCache->nRef
1980: 3b 0a 20 20 66 6f 72 28 70 3d 70 43 61 63 68 65  ;.  for(p=pCache
1990: 2d 3e 70 44 69 72 74 79 3b 20 70 3b 20 70 3d 70  ->pDirty; p; p=p
19a0: 2d 3e 70 4e 65 78 74 29 7b 0a 20 20 20 20 69 66  ->pNext){.    if
19b0: 28 20 70 2d 3e 6e 52 65 66 3d 3d 30 20 29 7b 0a  ( p->nRef==0 ){.
19c0: 20 20 20 20 20 20 6e 50 69 6e 6e 65 64 2b 2b 3b        nPinned++;
19d0: 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20 72 65 74  .    }.  }.  ret
19e0: 75 72 6e 20 6e 50 69 6e 6e 65 64 3b 0a 7d 0a 23  urn nPinned;.}.#
19f0: 65 6e 64 69 66 20 2f 2a 20 21 4e 44 45 42 55 47  endif /* !NDEBUG
1a00: 20 26 26 20 53 51 4c 49 54 45 5f 45 4e 41 42 4c   && SQLITE_ENABL
1a10: 45 5f 45 58 50 45 4e 53 49 56 45 5f 41 53 53 45  E_EXPENSIVE_ASSE
1a20: 52 54 20 2a 2f 0a 0a 0a 23 69 66 20 21 64 65 66  RT */...#if !def
1a30: 69 6e 65 64 28 4e 44 45 42 55 47 29 20 26 26 20  ined(NDEBUG) && 
1a40: 64 65 66 69 6e 65 64 28 53 51 4c 49 54 45 5f 45  defined(SQLITE_E
1a50: 4e 41 42 4c 45 5f 45 58 50 45 4e 53 49 56 45 5f  NABLE_EXPENSIVE_
1a60: 41 53 53 45 52 54 29 0a 2f 2a 0a 2a 2a 20 43 68  ASSERT)./*.** Ch
1a70: 65 63 6b 20 74 68 61 74 20 74 68 65 20 70 43 61  eck that the pCa
1a80: 63 68 65 2d 3e 70 53 79 6e 63 65 64 20 76 61 72  che->pSynced var
1a90: 69 61 62 6c 65 20 69 73 20 73 65 74 20 63 6f 72  iable is set cor
1aa0: 72 65 63 74 6c 79 2e 20 49 66 20 69 74 0a 2a 2a  rectly. If it.**
1ab0: 20 69 73 20 6e 6f 74 2c 20 65 69 74 68 65 72 20   is not, either 
1ac0: 66 61 69 6c 20 61 6e 20 61 73 73 65 72 74 20 6f  fail an assert o
1ad0: 72 20 72 65 74 75 72 6e 20 7a 65 72 6f 2e 20 4f  r return zero. O
1ae0: 74 68 65 72 77 69 73 65 2c 20 72 65 74 75 72 6e  therwise, return
1af0: 0a 2a 2a 20 6e 6f 6e 2d 7a 65 72 6f 2e 20 54 68  .** non-zero. Th
1b00: 69 73 20 69 73 20 6f 6e 6c 79 20 75 73 65 64 20  is is only used 
1b10: 69 6e 20 64 65 62 75 67 67 69 6e 67 20 62 75 69  in debugging bui
1b20: 6c 64 73 2c 20 61 73 20 66 6f 6c 6c 6f 77 73 3a  lds, as follows:
1b30: 0a 2a 2a 0a 2a 2a 20 20 20 65 78 70 65 6e 73 69  .**.**   expensi
1b40: 76 65 5f 61 73 73 65 72 74 28 20 70 63 61 63 68  ve_assert( pcach
1b50: 65 43 68 65 63 6b 53 79 6e 63 65 64 28 70 43 61  eCheckSynced(pCa
1b60: 63 68 65 29 20 29 3b 0a 2a 2f 0a 73 74 61 74 69  che) );.*/.stati
1b70: 63 20 69 6e 74 20 70 63 61 63 68 65 43 68 65 63  c int pcacheChec
1b80: 6b 53 79 6e 63 65 64 28 50 43 61 63 68 65 20 2a  kSynced(PCache *
1b90: 70 43 61 63 68 65 29 7b 0a 20 20 50 67 48 64 72  pCache){.  PgHdr
1ba0: 20 2a 70 20 3d 20 70 43 61 63 68 65 2d 3e 70 44   *p = pCache->pD
1bb0: 69 72 74 79 54 61 69 6c 3b 0a 20 20 66 6f 72 28  irtyTail;.  for(
1bc0: 70 3d 70 43 61 63 68 65 2d 3e 70 44 69 72 74 79  p=pCache->pDirty
1bd0: 54 61 69 6c 3b 20 70 21 3d 70 43 61 63 68 65 2d  Tail; p!=pCache-
1be0: 3e 70 53 79 6e 63 65 64 3b 20 70 3d 70 2d 3e 70  >pSynced; p=p->p
1bf0: 50 72 65 76 29 7b 0a 20 20 20 20 61 73 73 65 72  Prev){.    asser
1c00: 74 28 20 70 2d 3e 6e 52 65 66 20 7c 7c 20 28 70  t( p->nRef || (p
1c10: 2d 3e 66 6c 61 67 73 26 50 47 48 44 52 5f 4e 45  ->flags&PGHDR_NE
1c20: 45 44 5f 53 59 4e 43 29 20 29 3b 0a 20 20 7d 0a  ED_SYNC) );.  }.
1c30: 20 20 72 65 74 75 72 6e 20 28 70 3d 3d 30 20 7c    return (p==0 |
1c40: 7c 20 70 2d 3e 6e 52 65 66 20 7c 7c 20 28 70 2d  | p->nRef || (p-
1c50: 3e 66 6c 61 67 73 26 50 47 48 44 52 5f 4e 45 45  >flags&PGHDR_NEE
1c60: 44 5f 53 59 4e 43 29 3d 3d 30 29 3b 0a 7d 0a 23  D_SYNC)==0);.}.#
1c70: 65 6e 64 69 66 20 2f 2a 20 21 4e 44 45 42 55 47  endif /* !NDEBUG
1c80: 20 26 26 20 53 51 4c 49 54 45 5f 45 4e 41 42 4c   && SQLITE_ENABL
1c90: 45 5f 45 58 50 45 4e 53 49 56 45 5f 41 53 53 45  E_EXPENSIVE_ASSE
1ca0: 52 54 20 2a 2f 0a 0a 0a 0a 2f 2a 0a 2a 2a 20 52  RT */..../*.** R
1cb0: 65 6d 6f 76 65 20 61 20 70 61 67 65 20 66 72 6f  emove a page fro
1cc0: 6d 20 69 74 73 20 68 61 73 68 20 74 61 62 6c 65  m its hash table
1cd0: 20 28 50 43 61 63 68 65 2e 61 70 48 61 73 68 5b   (PCache.apHash[
1ce0: 5d 29 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 76 6f  ])..*/.static vo
1cf0: 69 64 20 70 63 61 63 68 65 52 65 6d 6f 76 65 46  id pcacheRemoveF
1d00: 72 6f 6d 48 61 73 68 28 50 67 48 64 72 20 2a 70  romHash(PgHdr *p
1d10: 50 61 67 65 29 7b 0a 20 20 61 73 73 65 72 74 28  Page){.  assert(
1d20: 20 70 63 61 63 68 65 4d 75 74 65 78 48 65 6c 64   pcacheMutexHeld
1d30: 28 29 20 29 3b 0a 20 20 69 66 28 20 70 50 61 67  () );.  if( pPag
1d40: 65 2d 3e 70 50 72 65 76 48 61 73 68 20 29 7b 0a  e->pPrevHash ){.
1d50: 20 20 20 20 70 50 61 67 65 2d 3e 70 50 72 65 76      pPage->pPrev
1d60: 48 61 73 68 2d 3e 70 4e 65 78 74 48 61 73 68 20  Hash->pNextHash 
1d70: 3d 20 70 50 61 67 65 2d 3e 70 4e 65 78 74 48 61  = pPage->pNextHa
1d80: 73 68 3b 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20  sh;.  }else{.   
1d90: 20 50 43 61 63 68 65 20 2a 70 43 61 63 68 65 20   PCache *pCache 
1da0: 3d 20 70 50 61 67 65 2d 3e 70 43 61 63 68 65 3b  = pPage->pCache;
1db0: 0a 20 20 20 20 75 33 32 20 68 20 3d 20 70 50 61  .    u32 h = pPa
1dc0: 67 65 2d 3e 70 67 6e 6f 20 25 20 70 43 61 63 68  ge->pgno % pCach
1dd0: 65 2d 3e 6e 48 61 73 68 3b 0a 20 20 20 20 61 73  e->nHash;.    as
1de0: 73 65 72 74 28 20 70 43 61 63 68 65 2d 3e 61 70  sert( pCache->ap
1df0: 48 61 73 68 5b 68 5d 3d 3d 70 50 61 67 65 20 29  Hash[h]==pPage )
1e00: 3b 0a 20 20 20 20 70 43 61 63 68 65 2d 3e 61 70  ;.    pCache->ap
1e10: 48 61 73 68 5b 68 5d 20 3d 20 70 50 61 67 65 2d  Hash[h] = pPage-
1e20: 3e 70 4e 65 78 74 48 61 73 68 3b 0a 20 20 7d 0a  >pNextHash;.  }.
1e30: 20 20 69 66 28 20 70 50 61 67 65 2d 3e 70 4e 65    if( pPage->pNe
1e40: 78 74 48 61 73 68 20 29 7b 0a 20 20 20 20 70 50  xtHash ){.    pP
1e50: 61 67 65 2d 3e 70 4e 65 78 74 48 61 73 68 2d 3e  age->pNextHash->
1e60: 70 50 72 65 76 48 61 73 68 20 3d 20 70 50 61 67  pPrevHash = pPag
1e70: 65 2d 3e 70 50 72 65 76 48 61 73 68 3b 0a 20 20  e->pPrevHash;.  
1e80: 7d 0a 20 20 70 50 61 67 65 2d 3e 70 43 61 63 68  }.  pPage->pCach
1e90: 65 2d 3e 6e 50 61 67 65 2d 2d 3b 0a 20 20 65 78  e->nPage--;.  ex
1ea0: 70 65 6e 73 69 76 65 5f 61 73 73 65 72 74 28 20  pensive_assert( 
1eb0: 70 63 61 63 68 65 43 68 65 63 6b 48 61 73 68 43  pcacheCheckHashC
1ec0: 6f 75 6e 74 28 70 50 61 67 65 2d 3e 70 43 61 63  ount(pPage->pCac
1ed0: 68 65 29 20 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20  he) );.}../*.** 
1ee0: 49 6e 73 65 72 74 20 61 20 70 61 67 65 20 69 6e  Insert a page in
1ef0: 74 6f 20 74 68 65 20 68 61 73 68 20 74 61 62 6c  to the hash tabl
1f00: 65 0a 2a 2a 0a 2a 2a 20 54 68 65 20 6d 75 74 65  e.**.** The mute
1f10: 78 20 6d 75 73 74 20 62 65 20 68 65 6c 64 20 62  x must be held b
1f20: 79 20 74 68 65 20 63 61 6c 6c 65 72 2e 0a 2a 2f  y the caller..*/
1f30: 0a 73 74 61 74 69 63 20 76 6f 69 64 20 70 63 61  .static void pca
1f40: 63 68 65 41 64 64 54 6f 48 61 73 68 28 50 67 48  cheAddToHash(PgH
1f50: 64 72 20 2a 70 50 61 67 65 29 7b 0a 20 20 50 43  dr *pPage){.  PC
1f60: 61 63 68 65 20 2a 70 43 61 63 68 65 20 3d 20 70  ache *pCache = p
1f70: 50 61 67 65 2d 3e 70 43 61 63 68 65 3b 0a 20 20  Page->pCache;.  
1f80: 75 33 32 20 68 20 3d 20 70 50 61 67 65 2d 3e 70  u32 h = pPage->p
1f90: 67 6e 6f 20 25 20 70 43 61 63 68 65 2d 3e 6e 48  gno % pCache->nH
1fa0: 61 73 68 3b 0a 20 20 61 73 73 65 72 74 28 20 70  ash;.  assert( p
1fb0: 63 61 63 68 65 4d 75 74 65 78 48 65 6c 64 28 29  cacheMutexHeld()
1fc0: 20 29 3b 0a 20 20 70 50 61 67 65 2d 3e 70 4e 65   );.  pPage->pNe
1fd0: 78 74 48 61 73 68 20 3d 20 70 43 61 63 68 65 2d  xtHash = pCache-
1fe0: 3e 61 70 48 61 73 68 5b 68 5d 3b 0a 20 20 70 50  >apHash[h];.  pP
1ff0: 61 67 65 2d 3e 70 50 72 65 76 48 61 73 68 20 3d  age->pPrevHash =
2000: 20 30 3b 0a 20 20 69 66 28 20 70 43 61 63 68 65   0;.  if( pCache
2010: 2d 3e 61 70 48 61 73 68 5b 68 5d 20 29 7b 0a 20  ->apHash[h] ){. 
2020: 20 20 20 70 43 61 63 68 65 2d 3e 61 70 48 61 73     pCache->apHas
2030: 68 5b 68 5d 2d 3e 70 50 72 65 76 48 61 73 68 20  h[h]->pPrevHash 
2040: 3d 20 70 50 61 67 65 3b 0a 20 20 7d 0a 20 20 70  = pPage;.  }.  p
2050: 43 61 63 68 65 2d 3e 61 70 48 61 73 68 5b 68 5d  Cache->apHash[h]
2060: 20 3d 20 70 50 61 67 65 3b 0a 20 20 70 43 61 63   = pPage;.  pCac
2070: 68 65 2d 3e 6e 50 61 67 65 2b 2b 3b 0a 20 20 65  he->nPage++;.  e
2080: 78 70 65 6e 73 69 76 65 5f 61 73 73 65 72 74 28  xpensive_assert(
2090: 20 70 63 61 63 68 65 43 68 65 63 6b 48 61 73 68   pcacheCheckHash
20a0: 43 6f 75 6e 74 28 70 43 61 63 68 65 29 20 29 3b  Count(pCache) );
20b0: 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 41 74 74 65 6d 70  .}../*.** Attemp
20c0: 74 20 74 6f 20 69 6e 63 72 65 61 73 65 20 74 68  t to increase th
20d0: 65 20 73 69 7a 65 20 74 68 65 20 68 61 73 68 20  e size the hash 
20e0: 74 61 62 6c 65 20 74 6f 20 63 6f 6e 74 61 69 6e  table to contain
20f0: 0a 2a 2a 20 61 74 20 6c 65 61 73 74 20 6e 48 61  .** at least nHa
2100: 73 68 20 62 75 63 6b 65 74 73 2e 0a 2a 2f 0a 73  sh buckets..*/.s
2110: 74 61 74 69 63 20 69 6e 74 20 70 63 61 63 68 65  tatic int pcache
2120: 52 65 73 69 7a 65 48 61 73 68 28 50 43 61 63 68  ResizeHash(PCach
2130: 65 20 2a 70 43 61 63 68 65 2c 20 69 6e 74 20 6e  e *pCache, int n
2140: 48 61 73 68 29 7b 0a 20 20 50 67 48 64 72 20 2a  Hash){.  PgHdr *
2150: 70 3b 0a 20 20 50 67 48 64 72 20 2a 2a 70 4e 65  p;.  PgHdr **pNe
2160: 77 3b 0a 20 20 61 73 73 65 72 74 28 20 70 63 61  w;.  assert( pca
2170: 63 68 65 4d 75 74 65 78 48 65 6c 64 28 29 20 29  cheMutexHeld() )
2180: 3b 0a 23 69 66 64 65 66 20 53 51 4c 49 54 45 5f  ;.#ifdef SQLITE_
2190: 4d 41 4c 4c 4f 43 5f 53 4f 46 54 5f 4c 49 4d 49  MALLOC_SOFT_LIMI
21a0: 54 0a 20 20 69 66 28 20 6e 48 61 73 68 2a 73 69  T.  if( nHash*si
21b0: 7a 65 6f 66 28 50 67 48 64 72 2a 29 3e 53 51 4c  zeof(PgHdr*)>SQL
21c0: 49 54 45 5f 4d 41 4c 4c 4f 43 5f 53 4f 46 54 5f  ITE_MALLOC_SOFT_
21d0: 4c 49 4d 49 54 20 29 7b 0a 20 20 20 20 6e 48 61  LIMIT ){.    nHa
21e0: 73 68 20 3d 20 53 51 4c 49 54 45 5f 4d 41 4c 4c  sh = SQLITE_MALL
21f0: 4f 43 5f 53 4f 46 54 5f 4c 49 4d 49 54 2f 73 69  OC_SOFT_LIMIT/si
2200: 7a 65 6f 66 28 50 67 48 64 72 20 2a 29 3b 0a 20  zeof(PgHdr *);. 
2210: 20 7d 0a 23 65 6e 64 69 66 0a 20 20 70 63 61 63   }.#endif.  pcac
2220: 68 65 45 78 69 74 4d 75 74 65 78 28 29 3b 0a 20  heExitMutex();. 
2230: 20 70 4e 65 77 20 3d 20 28 50 67 48 64 72 20 2a   pNew = (PgHdr *
2240: 2a 29 73 71 6c 69 74 65 33 4d 61 6c 6c 6f 63 28  *)sqlite3Malloc(
2250: 73 69 7a 65 6f 66 28 50 67 48 64 72 2a 29 2a 6e  sizeof(PgHdr*)*n
2260: 48 61 73 68 29 3b 0a 20 20 70 63 61 63 68 65 45  Hash);.  pcacheE
2270: 6e 74 65 72 4d 75 74 65 78 28 29 3b 0a 20 20 69  nterMutex();.  i
2280: 66 28 20 21 70 4e 65 77 20 29 7b 0a 20 20 20 20  f( !pNew ){.    
2290: 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4e 4f  return SQLITE_NO
22a0: 4d 45 4d 3b 0a 20 20 7d 0a 20 20 6d 65 6d 73 65  MEM;.  }.  memse
22b0: 74 28 70 4e 65 77 2c 20 30 2c 20 73 69 7a 65 6f  t(pNew, 0, sizeo
22c0: 66 28 50 67 48 64 72 20 2a 29 2a 6e 48 61 73 68  f(PgHdr *)*nHash
22d0: 29 3b 0a 20 20 73 71 6c 69 74 65 33 5f 66 72 65  );.  sqlite3_fre
22e0: 65 28 70 43 61 63 68 65 2d 3e 61 70 48 61 73 68  e(pCache->apHash
22f0: 29 3b 0a 20 20 70 43 61 63 68 65 2d 3e 61 70 48  );.  pCache->apH
2300: 61 73 68 20 3d 20 70 4e 65 77 3b 0a 20 20 70 43  ash = pNew;.  pC
2310: 61 63 68 65 2d 3e 6e 48 61 73 68 20 3d 20 6e 48  ache->nHash = nH
2320: 61 73 68 3b 0a 20 20 70 43 61 63 68 65 2d 3e 6e  ash;.  pCache->n
2330: 50 61 67 65 20 3d 20 30 3b 0a 20 0a 20 20 66 6f  Page = 0;. .  fo
2340: 72 28 70 3d 70 43 61 63 68 65 2d 3e 70 43 6c 65  r(p=pCache->pCle
2350: 61 6e 3b 20 70 3b 20 70 3d 70 2d 3e 70 4e 65 78  an; p; p=p->pNex
2360: 74 29 7b 0a 20 20 20 20 70 63 61 63 68 65 41 64  t){.    pcacheAd
2370: 64 54 6f 48 61 73 68 28 70 29 3b 0a 20 20 7d 0a  dToHash(p);.  }.
2380: 20 20 66 6f 72 28 70 3d 70 43 61 63 68 65 2d 3e    for(p=pCache->
2390: 70 44 69 72 74 79 3b 20 70 3b 20 70 3d 70 2d 3e  pDirty; p; p=p->
23a0: 70 4e 65 78 74 29 7b 0a 20 20 20 20 70 63 61 63  pNext){.    pcac
23b0: 68 65 41 64 64 54 6f 48 61 73 68 28 70 29 3b 0a  heAddToHash(p);.
23c0: 20 20 7d 0a 20 20 72 65 74 75 72 6e 20 53 51 4c    }.  return SQL
23d0: 49 54 45 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a  ITE_OK;.}../*.**
23e0: 20 52 65 6d 6f 76 65 20 61 20 70 61 67 65 20 66   Remove a page f
23f0: 72 6f 6d 20 61 20 6c 69 6e 6b 65 64 20 6c 69 73  rom a linked lis
2400: 74 20 74 68 61 74 20 69 73 20 68 65 61 64 65 64  t that is headed
2410: 20 62 79 20 2a 70 70 48 65 61 64 2e 0a 2a 2a 20   by *ppHead..** 
2420: 2a 70 70 48 65 61 64 20 69 73 20 65 69 74 68 65  *ppHead is eithe
2430: 72 20 50 43 61 63 68 65 2e 70 43 6c 65 61 6e 20  r PCache.pClean 
2440: 6f 72 20 50 43 61 63 68 65 2e 70 44 69 72 74 79  or PCache.pDirty
2450: 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 76 6f 69 64  ..*/.static void
2460: 20 70 63 61 63 68 65 52 65 6d 6f 76 65 46 72 6f   pcacheRemoveFro
2470: 6d 4c 69 73 74 28 50 67 48 64 72 20 2a 2a 70 70  mList(PgHdr **pp
2480: 48 65 61 64 2c 20 50 67 48 64 72 20 2a 70 50 61  Head, PgHdr *pPa
2490: 67 65 29 7b 0a 20 20 69 6e 74 20 69 73 44 69 72  ge){.  int isDir
24a0: 74 79 4c 69 73 74 20 3d 20 28 70 70 48 65 61 64  tyList = (ppHead
24b0: 3d 3d 26 70 50 61 67 65 2d 3e 70 43 61 63 68 65  ==&pPage->pCache
24c0: 2d 3e 70 44 69 72 74 79 29 3b 0a 20 20 61 73 73  ->pDirty);.  ass
24d0: 65 72 74 28 20 70 70 48 65 61 64 3d 3d 26 70 50  ert( ppHead==&pP
24e0: 61 67 65 2d 3e 70 43 61 63 68 65 2d 3e 70 43 6c  age->pCache->pCl
24f0: 65 61 6e 20 7c 7c 20 70 70 48 65 61 64 3d 3d 26  ean || ppHead==&
2500: 70 50 61 67 65 2d 3e 70 43 61 63 68 65 2d 3e 70  pPage->pCache->p
2510: 44 69 72 74 79 20 29 3b 0a 20 20 61 73 73 65 72  Dirty );.  asser
2520: 74 28 20 70 63 61 63 68 65 4d 75 74 65 78 48 65  t( pcacheMutexHe
2530: 6c 64 28 29 20 7c 7c 20 70 70 48 65 61 64 21 3d  ld() || ppHead!=
2540: 26 70 50 61 67 65 2d 3e 70 43 61 63 68 65 2d 3e  &pPage->pCache->
2550: 70 43 6c 65 61 6e 20 29 3b 0a 0a 20 20 69 66 28  pClean );..  if(
2560: 20 70 50 61 67 65 2d 3e 70 50 72 65 76 20 29 7b   pPage->pPrev ){
2570: 0a 20 20 20 20 70 50 61 67 65 2d 3e 70 50 72 65  .    pPage->pPre
2580: 76 2d 3e 70 4e 65 78 74 20 3d 20 70 50 61 67 65  v->pNext = pPage
2590: 2d 3e 70 4e 65 78 74 3b 0a 20 20 7d 65 6c 73 65  ->pNext;.  }else
25a0: 7b 0a 20 20 20 20 61 73 73 65 72 74 28 20 2a 70  {.    assert( *p
25b0: 70 48 65 61 64 3d 3d 70 50 61 67 65 20 29 3b 0a  pHead==pPage );.
25c0: 20 20 20 20 2a 70 70 48 65 61 64 20 3d 20 70 50      *ppHead = pP
25d0: 61 67 65 2d 3e 70 4e 65 78 74 3b 0a 20 20 7d 0a  age->pNext;.  }.
25e0: 20 20 69 66 28 20 70 50 61 67 65 2d 3e 70 4e 65    if( pPage->pNe
25f0: 78 74 20 29 7b 0a 20 20 20 20 70 50 61 67 65 2d  xt ){.    pPage-
2600: 3e 70 4e 65 78 74 2d 3e 70 50 72 65 76 20 3d 20  >pNext->pPrev = 
2610: 70 50 61 67 65 2d 3e 70 50 72 65 76 3b 0a 20 20  pPage->pPrev;.  
2620: 7d 0a 0a 20 20 69 66 28 20 69 73 44 69 72 74 79  }..  if( isDirty
2630: 4c 69 73 74 20 29 7b 0a 20 20 20 20 50 43 61 63  List ){.    PCac
2640: 68 65 20 2a 70 43 61 63 68 65 20 3d 20 70 50 61  he *pCache = pPa
2650: 67 65 2d 3e 70 43 61 63 68 65 3b 0a 20 20 20 20  ge->pCache;.    
2660: 61 73 73 65 72 74 28 20 70 50 61 67 65 2d 3e 70  assert( pPage->p
2670: 4e 65 78 74 20 7c 7c 20 70 43 61 63 68 65 2d 3e  Next || pCache->
2680: 70 44 69 72 74 79 54 61 69 6c 3d 3d 70 50 61 67  pDirtyTail==pPag
2690: 65 20 29 3b 0a 20 20 20 20 69 66 28 20 21 70 50  e );.    if( !pP
26a0: 61 67 65 2d 3e 70 4e 65 78 74 20 29 7b 0a 20 20  age->pNext ){.  
26b0: 20 20 20 20 70 43 61 63 68 65 2d 3e 70 44 69 72      pCache->pDir
26c0: 74 79 54 61 69 6c 20 3d 20 70 50 61 67 65 2d 3e  tyTail = pPage->
26d0: 70 50 72 65 76 3b 0a 20 20 20 20 7d 0a 20 20 20  pPrev;.    }.   
26e0: 20 69 66 28 20 70 43 61 63 68 65 2d 3e 70 53 79   if( pCache->pSy
26f0: 6e 63 65 64 3d 3d 70 50 61 67 65 20 29 7b 0a 20  nced==pPage ){. 
2700: 20 20 20 20 20 50 67 48 64 72 20 2a 70 53 79 6e       PgHdr *pSyn
2710: 63 65 64 20 3d 20 70 50 61 67 65 2d 3e 70 50 72  ced = pPage->pPr
2720: 65 76 3b 0a 20 20 20 20 20 20 77 68 69 6c 65 28  ev;.      while(
2730: 20 70 53 79 6e 63 65 64 20 26 26 20 28 70 53 79   pSynced && (pSy
2740: 6e 63 65 64 2d 3e 66 6c 61 67 73 26 50 47 48 44  nced->flags&PGHD
2750: 52 5f 4e 45 45 44 5f 53 59 4e 43 29 20 29 7b 0a  R_NEED_SYNC) ){.
2760: 20 20 20 20 20 20 20 20 70 53 79 6e 63 65 64 20          pSynced 
2770: 3d 20 70 53 79 6e 63 65 64 2d 3e 70 50 72 65 76  = pSynced->pPrev
2780: 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20  ;.      }.      
2790: 70 43 61 63 68 65 2d 3e 70 53 79 6e 63 65 64 20  pCache->pSynced 
27a0: 3d 20 70 53 79 6e 63 65 64 3b 0a 20 20 20 20 7d  = pSynced;.    }
27b0: 0a 20 20 7d 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 41 64  .  }.}../*.** Ad
27c0: 64 20 61 20 70 61 67 65 20 66 72 6f 6d 20 61 20  d a page from a 
27d0: 6c 69 6e 6b 65 64 20 6c 69 73 74 20 74 68 61 74  linked list that
27e0: 20 69 73 20 68 65 61 64 65 64 20 62 79 20 2a 70   is headed by *p
27f0: 70 48 65 61 64 2e 0a 2a 2a 20 2a 70 70 48 65 61  pHead..** *ppHea
2800: 64 20 69 73 20 65 69 74 68 65 72 20 50 43 61 63  d is either PCac
2810: 68 65 2e 70 43 6c 65 61 6e 20 6f 72 20 50 43 61  he.pClean or PCa
2820: 63 68 65 2e 70 44 69 72 74 79 2e 0a 2a 2f 0a 73  che.pDirty..*/.s
2830: 74 61 74 69 63 20 76 6f 69 64 20 70 63 61 63 68  tatic void pcach
2840: 65 41 64 64 54 6f 4c 69 73 74 28 50 67 48 64 72  eAddToList(PgHdr
2850: 20 2a 2a 70 70 48 65 61 64 2c 20 50 67 48 64 72   **ppHead, PgHdr
2860: 20 2a 70 50 61 67 65 29 7b 0a 20 20 69 6e 74 20   *pPage){.  int 
2870: 69 73 44 69 72 74 79 4c 69 73 74 20 3d 20 28 70  isDirtyList = (p
2880: 70 48 65 61 64 3d 3d 26 70 50 61 67 65 2d 3e 70  pHead==&pPage->p
2890: 43 61 63 68 65 2d 3e 70 44 69 72 74 79 29 3b 0a  Cache->pDirty);.
28a0: 20 20 61 73 73 65 72 74 28 20 70 70 48 65 61 64    assert( ppHead
28b0: 3d 3d 26 70 50 61 67 65 2d 3e 70 43 61 63 68 65  ==&pPage->pCache
28c0: 2d 3e 70 43 6c 65 61 6e 20 7c 7c 20 70 70 48 65  ->pClean || ppHe
28d0: 61 64 3d 3d 26 70 50 61 67 65 2d 3e 70 43 61 63  ad==&pPage->pCac
28e0: 68 65 2d 3e 70 44 69 72 74 79 20 29 3b 0a 0a 20  he->pDirty );.. 
28f0: 20 69 66 28 20 28 2a 70 70 48 65 61 64 29 20 29   if( (*ppHead) )
2900: 7b 0a 20 20 20 20 28 2a 70 70 48 65 61 64 29 2d  {.    (*ppHead)-
2910: 3e 70 50 72 65 76 20 3d 20 70 50 61 67 65 3b 0a  >pPrev = pPage;.
2920: 20 20 7d 0a 20 20 70 50 61 67 65 2d 3e 70 4e 65    }.  pPage->pNe
2930: 78 74 20 3d 20 2a 70 70 48 65 61 64 3b 0a 20 20  xt = *ppHead;.  
2940: 70 50 61 67 65 2d 3e 70 50 72 65 76 20 3d 20 30  pPage->pPrev = 0
2950: 3b 0a 20 20 2a 70 70 48 65 61 64 20 3d 20 70 50  ;.  *ppHead = pP
2960: 61 67 65 3b 0a 0a 20 20 69 66 28 20 69 73 44 69  age;..  if( isDi
2970: 72 74 79 4c 69 73 74 20 29 7b 0a 20 20 20 20 50  rtyList ){.    P
2980: 43 61 63 68 65 20 2a 70 43 61 63 68 65 20 3d 20  Cache *pCache = 
2990: 70 50 61 67 65 2d 3e 70 43 61 63 68 65 3b 0a 20  pPage->pCache;. 
29a0: 20 20 20 69 66 28 20 21 70 43 61 63 68 65 2d 3e     if( !pCache->
29b0: 70 44 69 72 74 79 54 61 69 6c 20 29 7b 0a 20 20  pDirtyTail ){.  
29c0: 20 20 20 20 61 73 73 65 72 74 28 20 70 50 61 67      assert( pPag
29d0: 65 2d 3e 70 4e 65 78 74 3d 3d 30 20 29 3b 0a 20  e->pNext==0 );. 
29e0: 20 20 20 20 20 70 43 61 63 68 65 2d 3e 70 44 69       pCache->pDi
29f0: 72 74 79 54 61 69 6c 20 3d 20 70 50 61 67 65 3b  rtyTail = pPage;
2a00: 0a 20 20 20 20 7d 0a 20 20 20 20 69 66 28 20 21  .    }.    if( !
2a10: 70 43 61 63 68 65 2d 3e 70 53 79 6e 63 65 64 20  pCache->pSynced 
2a20: 26 26 20 30 3d 3d 28 70 50 61 67 65 2d 3e 66 6c  && 0==(pPage->fl
2a30: 61 67 73 26 50 47 48 44 52 5f 4e 45 45 44 5f 53  ags&PGHDR_NEED_S
2a40: 59 4e 43 29 20 29 7b 0a 20 20 20 20 20 20 70 43  YNC) ){.      pC
2a50: 61 63 68 65 2d 3e 70 53 79 6e 63 65 64 20 3d 20  ache->pSynced = 
2a60: 70 50 61 67 65 3b 0a 20 20 20 20 7d 0a 20 20 7d  pPage;.    }.  }
2a70: 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 52 65 6d 6f 76 65  .}../*.** Remove
2a80: 20 61 20 70 61 67 65 20 66 72 6f 6d 20 74 68 65   a page from the
2a90: 20 67 6c 6f 62 61 6c 20 4c 52 55 20 6c 69 73 74   global LRU list
2aa0: 0a 2a 2f 0a 73 74 61 74 69 63 20 76 6f 69 64 20  .*/.static void 
2ab0: 70 63 61 63 68 65 52 65 6d 6f 76 65 46 72 6f 6d  pcacheRemoveFrom
2ac0: 4c 72 75 4c 69 73 74 28 50 67 48 64 72 20 2a 70  LruList(PgHdr *p
2ad0: 50 61 67 65 29 7b 0a 20 20 61 73 73 65 72 74 28  Page){.  assert(
2ae0: 20 73 71 6c 69 74 65 33 5f 6d 75 74 65 78 5f 68   sqlite3_mutex_h
2af0: 65 6c 64 28 70 63 61 63 68 65 5f 67 2e 6d 75 74  eld(pcache_g.mut
2b00: 65 78 29 20 29 3b 0a 20 20 61 73 73 65 72 74 28  ex) );.  assert(
2b10: 20 28 70 50 61 67 65 2d 3e 66 6c 61 67 73 26 50   (pPage->flags&P
2b20: 47 48 44 52 5f 44 49 52 54 59 29 3d 3d 30 20 29  GHDR_DIRTY)==0 )
2b30: 3b 0a 20 20 69 66 28 20 70 50 61 67 65 2d 3e 70  ;.  if( pPage->p
2b40: 43 61 63 68 65 2d 3e 62 50 75 72 67 65 61 62 6c  Cache->bPurgeabl
2b50: 65 3d 3d 30 20 29 20 72 65 74 75 72 6e 3b 0a 20  e==0 ) return;. 
2b60: 20 69 66 28 20 70 50 61 67 65 2d 3e 70 4e 65 78   if( pPage->pNex
2b70: 74 4c 72 75 20 29 7b 0a 20 20 20 20 61 73 73 65  tLru ){.    asse
2b80: 72 74 28 20 70 63 61 63 68 65 5f 67 2e 70 4c 72  rt( pcache_g.pLr
2b90: 75 54 61 69 6c 21 3d 70 50 61 67 65 20 29 3b 0a  uTail!=pPage );.
2ba0: 20 20 20 20 70 50 61 67 65 2d 3e 70 4e 65 78 74      pPage->pNext
2bb0: 4c 72 75 2d 3e 70 50 72 65 76 4c 72 75 20 3d 20  Lru->pPrevLru = 
2bc0: 70 50 61 67 65 2d 3e 70 50 72 65 76 4c 72 75 3b  pPage->pPrevLru;
2bd0: 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 61 73  .  }else{.    as
2be0: 73 65 72 74 28 20 70 63 61 63 68 65 5f 67 2e 70  sert( pcache_g.p
2bf0: 4c 72 75 54 61 69 6c 3d 3d 70 50 61 67 65 20 29  LruTail==pPage )
2c00: 3b 0a 20 20 20 20 70 63 61 63 68 65 5f 67 2e 70  ;.    pcache_g.p
2c10: 4c 72 75 54 61 69 6c 20 3d 20 70 50 61 67 65 2d  LruTail = pPage-
2c20: 3e 70 50 72 65 76 4c 72 75 3b 0a 20 20 7d 0a 20  >pPrevLru;.  }. 
2c30: 20 69 66 28 20 70 50 61 67 65 2d 3e 70 50 72 65   if( pPage->pPre
2c40: 76 4c 72 75 20 29 7b 0a 20 20 20 20 61 73 73 65  vLru ){.    asse
2c50: 72 74 28 20 70 63 61 63 68 65 5f 67 2e 70 4c 72  rt( pcache_g.pLr
2c60: 75 48 65 61 64 21 3d 70 50 61 67 65 20 29 3b 0a  uHead!=pPage );.
2c70: 20 20 20 20 70 50 61 67 65 2d 3e 70 50 72 65 76      pPage->pPrev
2c80: 4c 72 75 2d 3e 70 4e 65 78 74 4c 72 75 20 3d 20  Lru->pNextLru = 
2c90: 70 50 61 67 65 2d 3e 70 4e 65 78 74 4c 72 75 3b  pPage->pNextLru;
2ca0: 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 61 73  .  }else{.    as
2cb0: 73 65 72 74 28 20 70 63 61 63 68 65 5f 67 2e 70  sert( pcache_g.p
2cc0: 4c 72 75 48 65 61 64 3d 3d 70 50 61 67 65 20 29  LruHead==pPage )
2cd0: 3b 0a 20 20 20 20 70 63 61 63 68 65 5f 67 2e 70  ;.    pcache_g.p
2ce0: 4c 72 75 48 65 61 64 20 3d 20 70 50 61 67 65 2d  LruHead = pPage-
2cf0: 3e 70 4e 65 78 74 4c 72 75 3b 0a 20 20 7d 0a 7d  >pNextLru;.  }.}
2d00: 0a 0a 2f 2a 0a 2a 2a 20 41 64 64 20 61 20 70 61  ../*.** Add a pa
2d10: 67 65 20 74 6f 20 74 68 65 20 67 6c 6f 62 61 6c  ge to the global
2d20: 20 4c 52 55 20 6c 69 73 74 2e 20 20 54 68 65 20   LRU list.  The 
2d30: 70 61 67 65 20 69 73 20 6e 6f 72 6d 61 6c 6c 79  page is normally
2d40: 20 61 64 64 65 64 0a 2a 2a 20 74 6f 20 74 68 65   added.** to the
2d50: 20 66 72 6f 6e 74 20 6f 66 20 74 68 65 20 6c 69   front of the li
2d60: 73 74 20 73 6f 20 74 68 61 74 20 69 74 20 77 69  st so that it wi
2d70: 6c 6c 20 62 65 20 74 68 65 20 6c 61 73 74 20 70  ll be the last p
2d80: 61 67 65 20 72 65 63 79 63 6c 65 64 2e 0a 2a 2a  age recycled..**
2d90: 20 48 6f 77 65 76 65 72 2c 20 69 66 20 74 68 65   However, if the
2da0: 20 50 47 48 44 52 5f 52 45 55 53 45 5f 55 4e 4c   PGHDR_REUSE_UNL
2db0: 49 4b 45 4c 59 20 62 69 74 20 69 73 20 73 65 74  IKELY bit is set
2dc0: 2c 20 74 68 65 20 70 61 67 65 20 69 73 20 61 64  , the page is ad
2dd0: 64 65 64 0a 2a 2a 20 74 6f 20 74 68 65 20 65 6e  ded.** to the en
2de0: 64 20 6f 66 20 74 68 65 20 4c 52 55 20 6c 69 73  d of the LRU lis
2df0: 74 20 73 6f 20 74 68 61 74 20 69 74 20 77 69 6c  t so that it wil
2e00: 6c 20 62 65 20 74 68 65 20 6e 65 78 74 20 74 6f  l be the next to
2e10: 20 62 65 20 72 65 63 79 63 6c 65 64 2e 0a 2a 2f   be recycled..*/
2e20: 0a 73 74 61 74 69 63 20 76 6f 69 64 20 70 63 61  .static void pca
2e30: 63 68 65 41 64 64 54 6f 4c 72 75 4c 69 73 74 28  cheAddToLruList(
2e40: 50 67 48 64 72 20 2a 70 50 61 67 65 29 7b 0a 20  PgHdr *pPage){. 
2e50: 20 61 73 73 65 72 74 28 20 73 71 6c 69 74 65 33   assert( sqlite3
2e60: 5f 6d 75 74 65 78 5f 68 65 6c 64 28 70 63 61 63  _mutex_held(pcac
2e70: 68 65 5f 67 2e 6d 75 74 65 78 29 20 29 3b 0a 20  he_g.mutex) );. 
2e80: 20 61 73 73 65 72 74 28 20 28 70 50 61 67 65 2d   assert( (pPage-
2e90: 3e 66 6c 61 67 73 26 50 47 48 44 52 5f 44 49 52  >flags&PGHDR_DIR
2ea0: 54 59 29 3d 3d 30 20 29 3b 0a 20 20 69 66 28 20  TY)==0 );.  if( 
2eb0: 70 50 61 67 65 2d 3e 70 43 61 63 68 65 2d 3e 62  pPage->pCache->b
2ec0: 50 75 72 67 65 61 62 6c 65 3d 3d 30 20 29 20 72  Purgeable==0 ) r
2ed0: 65 74 75 72 6e 3b 0a 20 20 69 66 28 20 70 63 61  eturn;.  if( pca
2ee0: 63 68 65 5f 67 2e 70 4c 72 75 54 61 69 6c 20 26  che_g.pLruTail &
2ef0: 26 20 28 70 50 61 67 65 2d 3e 66 6c 61 67 73 20  & (pPage->flags 
2f00: 26 20 50 47 48 44 52 5f 52 45 55 53 45 5f 55 4e  & PGHDR_REUSE_UN
2f10: 4c 49 4b 45 4c 59 29 21 3d 30 20 29 7b 0a 20 20  LIKELY)!=0 ){.  
2f20: 20 20 2f 2a 20 49 66 20 72 65 75 73 65 20 69 73    /* If reuse is
2f30: 20 75 6e 6c 69 6b 65 6c 79 2e 20 20 50 75 74 20   unlikely.  Put 
2f40: 74 68 65 20 70 61 67 65 20 61 74 20 74 68 65 20  the page at the 
2f50: 65 6e 64 20 6f 66 20 74 68 65 20 4c 52 55 20 6c  end of the LRU l
2f60: 69 73 74 0a 20 20 20 20 2a 2a 20 77 68 65 72 65  ist.    ** where
2f70: 20 69 74 20 77 69 6c 6c 20 62 65 20 72 65 63 79   it will be recy
2f80: 63 6c 65 64 20 73 6f 6f 6e 65 72 20 72 61 74 68  cled sooner rath
2f90: 65 72 20 74 68 61 6e 20 6c 61 74 65 72 2e 20 0a  er than later. .
2fa0: 20 20 20 20 2a 2f 0a 20 20 20 20 61 73 73 65 72      */.    asser
2fb0: 74 28 20 70 63 61 63 68 65 5f 67 2e 70 4c 72 75  t( pcache_g.pLru
2fc0: 48 65 61 64 20 29 3b 0a 20 20 20 20 70 50 61 67  Head );.    pPag
2fd0: 65 2d 3e 70 4e 65 78 74 4c 72 75 20 3d 20 30 3b  e->pNextLru = 0;
2fe0: 0a 20 20 20 20 70 50 61 67 65 2d 3e 70 50 72 65  .    pPage->pPre
2ff0: 76 4c 72 75 20 3d 20 70 63 61 63 68 65 5f 67 2e  vLru = pcache_g.
3000: 70 4c 72 75 54 61 69 6c 3b 0a 20 20 20 20 70 63  pLruTail;.    pc
3010: 61 63 68 65 5f 67 2e 70 4c 72 75 54 61 69 6c 2d  ache_g.pLruTail-
3020: 3e 70 4e 65 78 74 4c 72 75 20 3d 20 70 50 61 67  >pNextLru = pPag
3030: 65 3b 0a 20 20 20 20 70 63 61 63 68 65 5f 67 2e  e;.    pcache_g.
3040: 70 4c 72 75 54 61 69 6c 20 3d 20 70 50 61 67 65  pLruTail = pPage
3050: 3b 0a 20 20 20 20 70 50 61 67 65 2d 3e 66 6c 61  ;.    pPage->fla
3060: 67 73 20 26 3d 20 7e 50 47 48 44 52 5f 52 45 55  gs &= ~PGHDR_REU
3070: 53 45 5f 55 4e 4c 49 4b 45 4c 59 3b 0a 20 20 7d  SE_UNLIKELY;.  }
3080: 65 6c 73 65 7b 0a 20 20 20 20 2f 2a 20 49 66 20  else{.    /* If 
3090: 72 65 75 73 65 20 69 73 20 70 6f 73 73 69 62 6c  reuse is possibl
30a0: 65 2e 20 74 68 65 20 70 61 67 65 20 67 6f 65 73  e. the page goes
30b0: 20 61 74 20 74 68 65 20 62 65 67 69 6e 6e 69 6e   at the beginnin
30c0: 67 20 6f 66 20 74 68 65 20 4c 52 55 0a 20 20 20  g of the LRU.   
30d0: 20 2a 2a 20 6c 69 73 74 20 73 6f 20 74 68 61 74   ** list so that
30e0: 20 69 74 20 77 69 6c 6c 20 62 65 20 74 68 65 20   it will be the 
30f0: 6c 61 73 74 20 74 6f 20 62 65 20 72 65 63 79 63  last to be recyc
3100: 6c 65 64 2e 0a 20 20 20 20 2a 2f 0a 20 20 20 20  led..    */.    
3110: 69 66 28 20 70 63 61 63 68 65 5f 67 2e 70 4c 72  if( pcache_g.pLr
3120: 75 48 65 61 64 20 29 7b 0a 20 20 20 20 20 20 70  uHead ){.      p
3130: 63 61 63 68 65 5f 67 2e 70 4c 72 75 48 65 61 64  cache_g.pLruHead
3140: 2d 3e 70 50 72 65 76 4c 72 75 20 3d 20 70 50 61  ->pPrevLru = pPa
3150: 67 65 3b 0a 20 20 20 20 7d 0a 20 20 20 20 70 50  ge;.    }.    pP
3160: 61 67 65 2d 3e 70 4e 65 78 74 4c 72 75 20 3d 20  age->pNextLru = 
3170: 70 63 61 63 68 65 5f 67 2e 70 4c 72 75 48 65 61  pcache_g.pLruHea
3180: 64 3b 0a 20 20 20 20 70 63 61 63 68 65 5f 67 2e  d;.    pcache_g.
3190: 70 4c 72 75 48 65 61 64 20 3d 20 70 50 61 67 65  pLruHead = pPage
31a0: 3b 0a 20 20 20 20 70 50 61 67 65 2d 3e 70 50 72  ;.    pPage->pPr
31b0: 65 76 4c 72 75 20 3d 20 30 3b 0a 20 20 20 20 69  evLru = 0;.    i
31c0: 66 28 20 70 63 61 63 68 65 5f 67 2e 70 4c 72 75  f( pcache_g.pLru
31d0: 54 61 69 6c 3d 3d 30 20 29 7b 0a 20 20 20 20 20  Tail==0 ){.     
31e0: 20 70 63 61 63 68 65 5f 67 2e 70 4c 72 75 54 61   pcache_g.pLruTa
31f0: 69 6c 20 3d 20 70 50 61 67 65 3b 0a 20 20 20 20  il = pPage;.    
3200: 7d 0a 20 20 7d 0a 7d 0a 0a 2f 2a 2a 2a 2a 2a 2a  }.  }.}../******
3210: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
3220: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
3230: 2a 2a 2a 2a 2a 2a 2a 2a 2a 20 4d 65 6d 6f 72 79  ********* Memory
3240: 20 41 6c 6c 6f 63 61 74 69 6f 6e 20 2a 2a 2a 2a   Allocation ****
3250: 2a 2a 2a 2a 2a 2a 2a 0a 2a 2a 0a 2a 2a 20 49 6e  *******.**.** In
3260: 69 74 69 61 6c 69 7a 65 20 74 68 65 20 70 61 67  itialize the pag
3270: 65 20 63 61 63 68 65 20 6d 65 6d 6f 72 79 20 70  e cache memory p
3280: 6f 6f 6c 2e 0a 2a 2a 0a 2a 2a 20 54 68 69 73 20  ool..**.** This 
3290: 6d 75 73 74 20 62 65 20 63 61 6c 6c 65 64 20 61  must be called a
32a0: 74 20 73 74 61 72 74 2d 74 69 6d 65 20 77 68 65  t start-time whe
32b0: 6e 20 6e 6f 20 70 61 67 65 20 63 61 63 68 65 20  n no page cache 
32c0: 6c 69 6e 65 73 20 61 72 65 0a 2a 2a 20 63 68 65  lines are.** che
32d0: 63 6b 65 64 20 6f 75 74 2e 20 54 68 69 73 20 66  cked out. This f
32e0: 75 6e 63 74 69 6f 6e 20 69 73 20 6e 6f 74 20 74  unction is not t
32f0: 68 72 65 61 64 73 61 66 65 2e 0a 2a 2f 0a 76 6f  hreadsafe..*/.vo
3300: 69 64 20 73 71 6c 69 74 65 33 50 43 61 63 68 65  id sqlite3PCache
3310: 42 75 66 66 65 72 53 65 74 75 70 28 76 6f 69 64  BufferSetup(void
3320: 20 2a 70 42 75 66 2c 20 69 6e 74 20 73 7a 2c 20   *pBuf, int sz, 
3330: 69 6e 74 20 6e 29 7b 0a 20 20 50 67 46 72 65 65  int n){.  PgFree
3340: 73 6c 6f 74 20 2a 70 3b 0a 20 20 73 7a 20 26 3d  slot *p;.  sz &=
3350: 20 7e 37 3b 0a 20 20 70 63 61 63 68 65 5f 67 2e   ~7;.  pcache_g.
3360: 73 7a 53 6c 6f 74 20 3d 20 73 7a 3b 0a 20 20 70  szSlot = sz;.  p
3370: 63 61 63 68 65 5f 67 2e 70 53 74 61 72 74 20 3d  cache_g.pStart =
3380: 20 70 42 75 66 3b 0a 20 20 70 63 61 63 68 65 5f   pBuf;.  pcache_
3390: 67 2e 70 46 72 65 65 20 3d 20 30 3b 0a 20 20 77  g.pFree = 0;.  w
33a0: 68 69 6c 65 28 20 6e 2d 2d 20 29 7b 0a 20 20 20  hile( n-- ){.   
33b0: 20 70 20 3d 20 28 50 67 46 72 65 65 73 6c 6f 74   p = (PgFreeslot
33c0: 2a 29 70 42 75 66 3b 0a 20 20 20 20 70 2d 3e 70  *)pBuf;.    p->p
33d0: 4e 65 78 74 20 3d 20 70 63 61 63 68 65 5f 67 2e  Next = pcache_g.
33e0: 70 46 72 65 65 3b 0a 20 20 20 20 70 63 61 63 68  pFree;.    pcach
33f0: 65 5f 67 2e 70 46 72 65 65 20 3d 20 70 3b 0a 20  e_g.pFree = p;. 
3400: 20 20 20 70 42 75 66 20 3d 20 28 76 6f 69 64 2a     pBuf = (void*
3410: 29 26 28 28 63 68 61 72 2a 29 70 42 75 66 29 5b  )&((char*)pBuf)[
3420: 73 7a 5d 3b 0a 20 20 7d 0a 20 20 70 63 61 63 68  sz];.  }.  pcach
3430: 65 5f 67 2e 70 45 6e 64 20 3d 20 70 42 75 66 3b  e_g.pEnd = pBuf;
3440: 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 41 6c 6c 6f 63 61  .}../*.** Alloca
3450: 74 65 20 61 20 70 61 67 65 20 63 61 63 68 65 20  te a page cache 
3460: 6c 69 6e 65 2e 20 20 4c 6f 6f 6b 20 69 6e 20 74  line.  Look in t
3470: 68 65 20 70 61 67 65 20 63 61 63 68 65 20 6d 65  he page cache me
3480: 6d 6f 72 79 20 70 6f 6f 6c 20 66 69 72 73 74 0a  mory pool first.
3490: 2a 2a 20 61 6e 64 20 75 73 65 20 61 6e 20 65 6c  ** and use an el
34a0: 65 6d 65 6e 74 20 66 72 6f 6d 20 69 74 20 66 69  ement from it fi
34b0: 72 73 74 20 69 66 20 61 76 61 69 6c 61 62 6c 65  rst if available
34c0: 2e 20 20 49 66 20 6e 6f 74 68 69 6e 67 20 69 73  .  If nothing is
34d0: 20 61 76 61 69 6c 61 62 6c 65 0a 2a 2a 20 69 6e   available.** in
34e0: 20 74 68 65 20 70 61 67 65 20 63 61 63 68 65 20   the page cache 
34f0: 6d 65 6d 6f 72 79 20 70 6f 6f 6c 2c 20 67 6f 20  memory pool, go 
3500: 74 6f 20 74 68 65 20 67 65 6e 65 72 61 6c 20 70  to the general p
3510: 75 72 70 6f 73 65 20 6d 65 6d 6f 72 79 20 61 6c  urpose memory al
3520: 6c 6f 63 61 74 6f 72 2e 0a 2a 2f 0a 73 74 61 74  locator..*/.stat
3530: 69 63 20 76 6f 69 64 20 2a 70 63 61 63 68 65 4d  ic void *pcacheM
3540: 61 6c 6c 6f 63 28 69 6e 74 20 73 7a 2c 20 50 43  alloc(int sz, PC
3550: 61 63 68 65 20 2a 70 43 61 63 68 65 29 7b 0a 20  ache *pCache){. 
3560: 20 61 73 73 65 72 74 28 20 73 71 6c 69 74 65 33   assert( sqlite3
3570: 5f 6d 75 74 65 78 5f 68 65 6c 64 28 70 63 61 63  _mutex_held(pcac
3580: 68 65 5f 67 2e 6d 75 74 65 78 29 20 29 3b 0a 20  he_g.mutex) );. 
3590: 20 69 66 28 20 73 7a 3c 3d 70 63 61 63 68 65 5f   if( sz<=pcache_
35a0: 67 2e 73 7a 53 6c 6f 74 20 26 26 20 70 63 61 63  g.szSlot && pcac
35b0: 68 65 5f 67 2e 70 46 72 65 65 20 29 7b 0a 20 20  he_g.pFree ){.  
35c0: 20 20 50 67 46 72 65 65 73 6c 6f 74 20 2a 70 20    PgFreeslot *p 
35d0: 3d 20 70 63 61 63 68 65 5f 67 2e 70 46 72 65 65  = pcache_g.pFree
35e0: 3b 0a 20 20 20 20 70 63 61 63 68 65 5f 67 2e 70  ;.    pcache_g.p
35f0: 46 72 65 65 20 3d 20 70 2d 3e 70 4e 65 78 74 3b  Free = p->pNext;
3600: 0a 20 20 20 20 73 71 6c 69 74 65 33 53 74 61 74  .    sqlite3Stat
3610: 75 73 53 65 74 28 53 51 4c 49 54 45 5f 53 54 41  usSet(SQLITE_STA
3620: 54 55 53 5f 50 41 47 45 43 41 43 48 45 5f 53 49  TUS_PAGECACHE_SI
3630: 5a 45 2c 20 73 7a 29 3b 0a 20 20 20 20 73 71 6c  ZE, sz);.    sql
3640: 69 74 65 33 53 74 61 74 75 73 41 64 64 28 53 51  ite3StatusAdd(SQ
3650: 4c 49 54 45 5f 53 54 41 54 55 53 5f 50 41 47 45  LITE_STATUS_PAGE
3660: 43 41 43 48 45 5f 55 53 45 44 2c 20 31 29 3b 0a  CACHE_USED, 1);.
3670: 20 20 20 20 72 65 74 75 72 6e 20 28 76 6f 69 64      return (void
3680: 2a 29 70 3b 0a 20 20 7d 65 6c 73 65 7b 0a 20 20  *)p;.  }else{.  
3690: 20 20 76 6f 69 64 20 2a 70 3b 0a 0a 20 20 20 20    void *p;..    
36a0: 2f 2a 20 41 6c 6c 6f 63 61 74 65 20 61 20 6e 65  /* Allocate a ne
36b0: 77 20 62 75 66 66 65 72 20 75 73 69 6e 67 20 73  w buffer using s
36c0: 71 6c 69 74 65 33 4d 61 6c 6c 6f 63 2e 20 42 65  qlite3Malloc. Be
36d0: 66 6f 72 65 20 64 6f 69 6e 67 20 73 6f 2c 20 65  fore doing so, e
36e0: 78 69 74 20 74 68 65 0a 20 20 20 20 2a 2a 20 67  xit the.    ** g
36f0: 6c 6f 62 61 6c 20 70 63 61 63 68 65 20 6d 75 74  lobal pcache mut
3700: 65 78 20 61 6e 64 20 75 6e 6c 6f 63 6b 20 74 68  ex and unlock th
3710: 65 20 70 61 67 65 72 2d 63 61 63 68 65 20 6f 62  e pager-cache ob
3720: 6a 65 63 74 20 70 43 61 63 68 65 2e 20 54 68 69  ject pCache. Thi
3730: 73 20 69 73 20 0a 20 20 20 20 2a 2a 20 73 6f 20  s is .    ** so 
3740: 74 68 61 74 20 69 66 20 74 68 65 20 61 74 74 65  that if the atte
3750: 6d 70 74 20 74 6f 20 61 6c 6c 6f 63 61 74 65 20  mpt to allocate 
3760: 61 20 6e 65 77 20 62 75 66 66 65 72 20 63 61 75  a new buffer cau
3770: 73 65 73 20 74 68 65 20 74 68 65 20 0a 20 20 20  ses the the .   
3780: 20 2a 2a 20 63 6f 6e 66 69 67 75 72 65 64 20 73   ** configured s
3790: 6f 66 74 2d 68 65 61 70 2d 6c 69 6d 69 74 20 74  oft-heap-limit t
37a0: 6f 20 62 65 20 62 72 65 61 63 68 65 64 2c 20 69  o be breached, i
37b0: 74 20 77 69 6c 6c 20 62 65 20 70 6f 73 73 69 62  t will be possib
37c0: 6c 65 20 74 6f 0a 20 20 20 20 2a 2a 20 72 65 63  le to.    ** rec
37d0: 6c 61 69 6d 20 6d 65 6d 6f 72 79 20 66 72 6f 6d  laim memory from
37e0: 20 74 68 69 73 20 70 61 67 65 72 2d 63 61 63 68   this pager-cach
37f0: 65 2e 0a 20 20 20 20 2a 2f 0a 20 20 20 20 70 63  e..    */.    pc
3800: 61 63 68 65 45 78 69 74 4d 75 74 65 78 28 29 3b  acheExitMutex();
3810: 0a 20 20 20 20 70 20 3d 20 73 71 6c 69 74 65 33  .    p = sqlite3
3820: 4d 61 6c 6c 6f 63 28 73 7a 29 3b 0a 20 20 20 20  Malloc(sz);.    
3830: 70 63 61 63 68 65 45 6e 74 65 72 4d 75 74 65 78  pcacheEnterMutex
3840: 28 29 3b 0a 0a 20 20 20 20 69 66 28 20 70 20 29  ();..    if( p )
3850: 7b 0a 20 20 20 20 20 20 73 7a 20 3d 20 73 71 6c  {.      sz = sql
3860: 69 74 65 33 4d 61 6c 6c 6f 63 53 69 7a 65 28 70  ite3MallocSize(p
3870: 29 3b 0a 20 20 20 20 20 20 73 71 6c 69 74 65 33  );.      sqlite3
3880: 53 74 61 74 75 73 41 64 64 28 53 51 4c 49 54 45  StatusAdd(SQLITE
3890: 5f 53 54 41 54 55 53 5f 50 41 47 45 43 41 43 48  _STATUS_PAGECACH
38a0: 45 5f 4f 56 45 52 46 4c 4f 57 2c 20 73 7a 29 3b  E_OVERFLOW, sz);
38b0: 0a 20 20 20 20 7d 0a 20 20 20 20 72 65 74 75 72  .    }.    retur
38c0: 6e 20 70 3b 0a 20 20 7d 0a 7d 0a 76 6f 69 64 20  n p;.  }.}.void 
38d0: 2a 73 71 6c 69 74 65 33 50 61 67 65 4d 61 6c 6c  *sqlite3PageMall
38e0: 6f 63 28 69 6e 74 20 73 7a 29 7b 0a 20 20 76 6f  oc(int sz){.  vo
38f0: 69 64 20 2a 70 3b 0a 20 20 70 63 61 63 68 65 45  id *p;.  pcacheE
3900: 6e 74 65 72 4d 75 74 65 78 28 29 3b 0a 20 20 70  nterMutex();.  p
3910: 20 3d 20 70 63 61 63 68 65 4d 61 6c 6c 6f 63 28   = pcacheMalloc(
3920: 73 7a 2c 20 30 29 3b 0a 20 20 70 63 61 63 68 65  sz, 0);.  pcache
3930: 45 78 69 74 4d 75 74 65 78 28 29 3b 0a 20 20 72  ExitMutex();.  r
3940: 65 74 75 72 6e 20 70 3b 0a 7d 0a 0a 2f 2a 0a 2a  eturn p;.}../*.*
3950: 2a 20 52 65 6c 65 61 73 65 20 61 20 70 61 67 65  * Release a page
3960: 72 20 6d 65 6d 6f 72 79 20 61 6c 6c 6f 63 61 74  r memory allocat
3970: 69 6f 6e 0a 2a 2f 0a 73 74 61 74 69 63 20 76 6f  ion.*/.static vo
3980: 69 64 20 70 63 61 63 68 65 46 72 65 65 28 76 6f  id pcacheFree(vo
3990: 69 64 20 2a 70 29 7b 0a 20 20 61 73 73 65 72 74  id *p){.  assert
39a0: 28 20 73 71 6c 69 74 65 33 5f 6d 75 74 65 78 5f  ( sqlite3_mutex_
39b0: 68 65 6c 64 28 70 63 61 63 68 65 5f 67 2e 6d 75  held(pcache_g.mu
39c0: 74 65 78 29 20 29 3b 0a 20 20 69 66 28 20 70 3d  tex) );.  if( p=
39d0: 3d 30 20 29 20 72 65 74 75 72 6e 3b 0a 20 20 69  =0 ) return;.  i
39e0: 66 28 20 70 3e 3d 70 63 61 63 68 65 5f 67 2e 70  f( p>=pcache_g.p
39f0: 53 74 61 72 74 20 26 26 20 70 3c 70 63 61 63 68  Start && p<pcach
3a00: 65 5f 67 2e 70 45 6e 64 20 29 7b 0a 20 20 20 20  e_g.pEnd ){.    
3a10: 50 67 46 72 65 65 73 6c 6f 74 20 2a 70 53 6c 6f  PgFreeslot *pSlo
3a20: 74 3b 0a 20 20 20 20 73 71 6c 69 74 65 33 53 74  t;.    sqlite3St
3a30: 61 74 75 73 41 64 64 28 53 51 4c 49 54 45 5f 53  atusAdd(SQLITE_S
3a40: 54 41 54 55 53 5f 50 41 47 45 43 41 43 48 45 5f  TATUS_PAGECACHE_
3a50: 55 53 45 44 2c 20 2d 31 29 3b 0a 20 20 20 20 70  USED, -1);.    p
3a60: 53 6c 6f 74 20 3d 20 28 50 67 46 72 65 65 73 6c  Slot = (PgFreesl
3a70: 6f 74 2a 29 70 3b 0a 20 20 20 20 70 53 6c 6f 74  ot*)p;.    pSlot
3a80: 2d 3e 70 4e 65 78 74 20 3d 20 70 63 61 63 68 65  ->pNext = pcache
3a90: 5f 67 2e 70 46 72 65 65 3b 0a 20 20 20 20 70 63  _g.pFree;.    pc
3aa0: 61 63 68 65 5f 67 2e 70 46 72 65 65 20 3d 20 70  ache_g.pFree = p
3ab0: 53 6c 6f 74 3b 0a 20 20 7d 65 6c 73 65 7b 0a 20  Slot;.  }else{. 
3ac0: 20 20 20 69 6e 74 20 69 53 69 7a 65 20 3d 20 73     int iSize = s
3ad0: 71 6c 69 74 65 33 4d 61 6c 6c 6f 63 53 69 7a 65  qlite3MallocSize
3ae0: 28 70 29 3b 0a 20 20 20 20 73 71 6c 69 74 65 33  (p);.    sqlite3
3af0: 53 74 61 74 75 73 41 64 64 28 53 51 4c 49 54 45  StatusAdd(SQLITE
3b00: 5f 53 54 41 54 55 53 5f 50 41 47 45 43 41 43 48  _STATUS_PAGECACH
3b10: 45 5f 4f 56 45 52 46 4c 4f 57 2c 20 2d 69 53 69  E_OVERFLOW, -iSi
3b20: 7a 65 29 3b 0a 20 20 20 20 73 71 6c 69 74 65 33  ze);.    sqlite3
3b30: 5f 66 72 65 65 28 70 29 3b 0a 20 20 7d 0a 7d 0a  _free(p);.  }.}.
3b40: 76 6f 69 64 20 73 71 6c 69 74 65 33 50 61 67 65  void sqlite3Page
3b50: 46 72 65 65 28 76 6f 69 64 20 2a 70 29 7b 0a 20  Free(void *p){. 
3b60: 20 70 63 61 63 68 65 45 6e 74 65 72 4d 75 74 65   pcacheEnterMute
3b70: 78 28 29 3b 0a 20 20 70 63 61 63 68 65 46 72 65  x();.  pcacheFre
3b80: 65 28 70 29 3b 0a 20 20 70 63 61 63 68 65 45 78  e(p);.  pcacheEx
3b90: 69 74 4d 75 74 65 78 28 29 3b 0a 7d 0a 0a 2f 2a  itMutex();.}../*
3ba0: 0a 2a 2a 20 41 6c 6c 6f 63 61 74 65 20 61 20 6e  .** Allocate a n
3bb0: 65 77 20 70 61 67 65 2e 0a 2a 2f 0a 73 74 61 74  ew page..*/.stat
3bc0: 69 63 20 50 67 48 64 72 20 2a 70 63 61 63 68 65  ic PgHdr *pcache
3bd0: 50 61 67 65 41 6c 6c 6f 63 28 50 43 61 63 68 65  PageAlloc(PCache
3be0: 20 2a 70 43 61 63 68 65 29 7b 0a 20 20 50 67 48   *pCache){.  PgH
3bf0: 64 72 20 2a 70 3b 0a 20 20 69 6e 74 20 73 7a 20  dr *p;.  int sz 
3c00: 3d 20 73 69 7a 65 6f 66 28 2a 70 29 20 2b 20 70  = sizeof(*p) + p
3c10: 43 61 63 68 65 2d 3e 73 7a 50 61 67 65 20 2b 20  Cache->szPage + 
3c20: 70 43 61 63 68 65 2d 3e 73 7a 45 78 74 72 61 3b  pCache->szExtra;
3c30: 0a 20 20 61 73 73 65 72 74 28 20 73 71 6c 69 74  .  assert( sqlit
3c40: 65 33 5f 6d 75 74 65 78 5f 68 65 6c 64 28 70 63  e3_mutex_held(pc
3c50: 61 63 68 65 5f 67 2e 6d 75 74 65 78 29 20 29 3b  ache_g.mutex) );
3c60: 0a 20 20 70 20 3d 20 70 63 61 63 68 65 4d 61 6c  .  p = pcacheMal
3c70: 6c 6f 63 28 73 7a 2c 20 70 43 61 63 68 65 29 3b  loc(sz, pCache);
3c80: 0a 20 20 69 66 28 20 70 3d 3d 30 20 29 20 72 65  .  if( p==0 ) re
3c90: 74 75 72 6e 20 30 3b 0a 20 20 6d 65 6d 73 65 74  turn 0;.  memset
3ca0: 28 70 2c 20 30 2c 20 73 69 7a 65 6f 66 28 50 67  (p, 0, sizeof(Pg
3cb0: 48 64 72 29 29 3b 0a 20 20 70 2d 3e 70 44 61 74  Hdr));.  p->pDat
3cc0: 61 20 3d 20 28 76 6f 69 64 2a 29 26 70 5b 31 5d  a = (void*)&p[1]
3cd0: 3b 0a 20 20 70 2d 3e 70 45 78 74 72 61 20 3d 20  ;.  p->pExtra = 
3ce0: 28 76 6f 69 64 2a 29 26 28 28 63 68 61 72 2a 29  (void*)&((char*)
3cf0: 70 2d 3e 70 44 61 74 61 29 5b 70 43 61 63 68 65  p->pData)[pCache
3d00: 2d 3e 73 7a 50 61 67 65 5d 3b 0a 20 20 69 66 28  ->szPage];.  if(
3d10: 20 70 43 61 63 68 65 2d 3e 62 50 75 72 67 65 61   pCache->bPurgea
3d20: 62 6c 65 20 29 7b 0a 20 20 20 20 70 63 61 63 68  ble ){.    pcach
3d30: 65 5f 67 2e 6e 43 75 72 72 65 6e 74 50 61 67 65  e_g.nCurrentPage
3d40: 2b 2b 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e  ++;.  }.  return
3d50: 20 70 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 44 65 61   p;.}../*.** Dea
3d60: 6c 6c 6f 63 61 74 65 20 61 20 70 61 67 65 0a 2a  llocate a page.*
3d70: 2f 0a 73 74 61 74 69 63 20 76 6f 69 64 20 70 63  /.static void pc
3d80: 61 63 68 65 50 61 67 65 46 72 65 65 28 50 67 48  achePageFree(PgH
3d90: 64 72 20 2a 70 29 7b 0a 20 20 61 73 73 65 72 74  dr *p){.  assert
3da0: 28 20 73 71 6c 69 74 65 33 5f 6d 75 74 65 78 5f  ( sqlite3_mutex_
3db0: 68 65 6c 64 28 70 63 61 63 68 65 5f 67 2e 6d 75  held(pcache_g.mu
3dc0: 74 65 78 29 20 29 3b 0a 20 20 69 66 28 20 70 2d  tex) );.  if( p-
3dd0: 3e 70 43 61 63 68 65 2d 3e 62 50 75 72 67 65 61  >pCache->bPurgea
3de0: 62 6c 65 20 29 7b 0a 20 20 20 20 70 63 61 63 68  ble ){.    pcach
3df0: 65 5f 67 2e 6e 43 75 72 72 65 6e 74 50 61 67 65  e_g.nCurrentPage
3e00: 2d 2d 3b 0a 20 20 7d 0a 20 20 70 63 61 63 68 65  --;.  }.  pcache
3e10: 46 72 65 65 28 70 2d 3e 61 70 53 61 76 65 5b 30  Free(p->apSave[0
3e20: 5d 29 3b 0a 20 20 70 63 61 63 68 65 46 72 65 65  ]);.  pcacheFree
3e30: 28 70 2d 3e 61 70 53 61 76 65 5b 31 5d 29 3b 0a  (p->apSave[1]);.
3e40: 20 20 70 63 61 63 68 65 46 72 65 65 28 70 29 3b    pcacheFree(p);
3e50: 0a 7d 0a 0a 23 69 66 64 65 66 20 53 51 4c 49 54  .}..#ifdef SQLIT
3e60: 45 5f 45 4e 41 42 4c 45 5f 4d 45 4d 4f 52 59 5f  E_ENABLE_MEMORY_
3e70: 4d 41 4e 41 47 45 4d 45 4e 54 0a 2f 2a 0a 2a 2a  MANAGEMENT./*.**
3e80: 20 52 65 74 75 72 6e 20 74 68 65 20 6e 75 6d 62   Return the numb
3e90: 65 72 20 6f 66 20 62 79 74 65 73 20 74 68 61 74  er of bytes that
3ea0: 20 77 69 6c 6c 20 62 65 20 72 65 74 75 72 6e 65   will be returne
3eb0: 64 20 74 6f 20 74 68 65 20 68 65 61 70 20 77 68  d to the heap wh
3ec0: 65 6e 0a 2a 2a 20 74 68 65 20 61 72 67 75 6d 65  en.** the argume
3ed0: 6e 74 20 69 73 20 70 61 73 73 65 64 20 74 6f 20  nt is passed to 
3ee0: 70 63 61 63 68 65 50 61 67 65 46 72 65 65 28 29  pcachePageFree()
3ef0: 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20  ..*/.static int 
3f00: 70 63 61 63 68 65 50 61 67 65 53 69 7a 65 28 50  pcachePageSize(P
3f10: 67 48 64 72 20 2a 70 29 7b 0a 20 20 61 73 73 65  gHdr *p){.  asse
3f20: 72 74 28 20 73 71 6c 69 74 65 33 5f 6d 75 74 65  rt( sqlite3_mute
3f30: 78 5f 68 65 6c 64 28 70 63 61 63 68 65 5f 67 2e  x_held(pcache_g.
3f40: 6d 75 74 65 78 29 20 29 3b 0a 20 20 61 73 73 65  mutex) );.  asse
3f50: 72 74 28 20 21 70 63 61 63 68 65 5f 67 2e 70 53  rt( !pcache_g.pS
3f60: 74 61 72 74 20 29 3b 0a 20 20 61 73 73 65 72 74  tart );.  assert
3f70: 28 20 70 2d 3e 61 70 53 61 76 65 5b 30 5d 3d 3d  ( p->apSave[0]==
3f80: 30 20 29 3b 0a 20 20 61 73 73 65 72 74 28 20 70  0 );.  assert( p
3f90: 2d 3e 61 70 53 61 76 65 5b 31 5d 3d 3d 30 20 29  ->apSave[1]==0 )
3fa0: 3b 0a 20 20 61 73 73 65 72 74 28 20 70 20 26 26  ;.  assert( p &&
3fb0: 20 70 2d 3e 70 43 61 63 68 65 20 29 3b 0a 20 20   p->pCache );.  
3fc0: 72 65 74 75 72 6e 20 73 71 6c 69 74 65 33 4d 61  return sqlite3Ma
3fd0: 6c 6c 6f 63 53 69 7a 65 28 70 29 3b 0a 7d 0a 23  llocSize(p);.}.#
3fe0: 65 6e 64 69 66 0a 0a 2f 2a 0a 2a 2a 20 41 74 74  endif../*.** Att
3ff0: 65 6d 70 74 20 74 6f 20 27 72 65 63 79 63 6c 65  empt to 'recycle
4000: 27 20 61 20 70 61 67 65 20 66 72 6f 6d 20 74 68  ' a page from th
4010: 65 20 67 6c 6f 62 61 6c 20 4c 52 55 20 6c 69 73  e global LRU lis
4020: 74 2e 20 4f 6e 6c 79 20 63 6c 65 61 6e 2c 0a 2a  t. Only clean,.*
4030: 2a 20 75 6e 72 65 66 65 72 65 6e 63 65 64 20 70  * unreferenced p
4040: 61 67 65 73 20 66 72 6f 6d 20 70 75 72 67 65 61  ages from purgea
4050: 62 6c 65 20 63 61 63 68 65 73 20 61 72 65 20 65  ble caches are e
4060: 6c 69 67 69 62 6c 65 20 66 6f 72 20 72 65 63 79  ligible for recy
4070: 63 6c 69 6e 67 2e 0a 2a 2a 0a 2a 2a 20 54 68 69  cling..**.** Thi
4080: 73 20 66 75 6e 63 74 69 6f 6e 20 72 65 6d 6f 76  s function remov
4090: 65 73 20 70 61 67 65 20 70 63 61 63 68 65 2e 70  es page pcache.p
40a0: 4c 72 75 54 61 69 6c 20 66 72 6f 6d 20 74 68 65  LruTail from the
40b0: 20 67 6c 6f 62 61 6c 20 4c 52 55 20 6c 69 73 74   global LRU list
40c0: 2c 0a 2a 2a 20 61 6e 64 20 66 72 6f 6d 20 74 68  ,.** and from th
40d0: 65 20 68 61 73 68 2d 74 61 62 6c 65 20 61 6e 64  e hash-table and
40e0: 20 50 43 61 63 68 65 2e 70 43 6c 65 61 6e 20 6c   PCache.pClean l
40f0: 69 73 74 20 6f 66 20 74 68 65 20 6f 77 6e 65 72  ist of the owner
4100: 20 70 63 61 63 68 65 2e 0a 2a 2a 20 54 68 65 72   pcache..** Ther
4110: 65 20 73 68 6f 75 6c 64 20 62 65 20 6e 6f 20 6f  e should be no o
4120: 74 68 65 72 20 72 65 66 65 72 65 6e 63 65 73 20  ther references 
4130: 74 6f 20 74 68 65 20 70 61 67 65 2e 0a 2a 2a 0a  to the page..**.
4140: 2a 2a 20 41 20 70 6f 69 6e 74 65 72 20 74 6f 20  ** A pointer to 
4150: 74 68 65 20 72 65 63 79 63 6c 65 64 20 70 61 67  the recycled pag
4160: 65 20 69 73 20 72 65 74 75 72 6e 65 64 2c 20 6f  e is returned, o
4170: 72 20 4e 55 4c 4c 20 69 66 20 6e 6f 20 70 61 67  r NULL if no pag
4180: 65 20 69 73 0a 2a 2a 20 65 6c 69 67 69 62 6c 65  e is.** eligible
4190: 20 66 6f 72 20 72 65 63 79 63 6c 69 6e 67 2e 0a   for recycling..
41a0: 2a 2f 0a 73 74 61 74 69 63 20 50 67 48 64 72 20  */.static PgHdr 
41b0: 2a 70 63 61 63 68 65 52 65 63 79 63 6c 65 50 61  *pcacheRecyclePa
41c0: 67 65 28 76 6f 69 64 29 7b 0a 20 20 50 67 48 64  ge(void){.  PgHd
41d0: 72 20 2a 70 20 3d 20 30 3b 0a 20 20 61 73 73 65  r *p = 0;.  asse
41e0: 72 74 28 20 73 71 6c 69 74 65 33 5f 6d 75 74 65  rt( sqlite3_mute
41f0: 78 5f 68 65 6c 64 28 70 63 61 63 68 65 5f 67 2e  x_held(pcache_g.
4200: 6d 75 74 65 78 29 20 29 3b 0a 0a 20 20 69 66 28  mutex) );..  if(
4210: 20 28 70 3d 70 63 61 63 68 65 5f 67 2e 70 4c 72   (p=pcache_g.pLr
4220: 75 54 61 69 6c 29 20 29 7b 0a 20 20 20 20 61 73  uTail) ){.    as
4230: 73 65 72 74 28 20 28 70 2d 3e 66 6c 61 67 73 26  sert( (p->flags&
4240: 50 47 48 44 52 5f 44 49 52 54 59 29 3d 3d 30 20  PGHDR_DIRTY)==0 
4250: 29 3b 0a 20 20 20 20 70 63 61 63 68 65 52 65 6d  );.    pcacheRem
4260: 6f 76 65 46 72 6f 6d 4c 72 75 4c 69 73 74 28 70  oveFromLruList(p
4270: 29 3b 0a 20 20 20 20 70 63 61 63 68 65 52 65 6d  );.    pcacheRem
4280: 6f 76 65 46 72 6f 6d 48 61 73 68 28 70 29 3b 0a  oveFromHash(p);.
4290: 20 20 20 20 70 63 61 63 68 65 52 65 6d 6f 76 65      pcacheRemove
42a0: 46 72 6f 6d 4c 69 73 74 28 26 70 2d 3e 70 43 61  FromList(&p->pCa
42b0: 63 68 65 2d 3e 70 43 6c 65 61 6e 2c 20 70 29 3b  che->pClean, p);
42c0: 0a 20 20 7d 0a 0a 20 20 72 65 74 75 72 6e 20 70  .  }..  return p
42d0: 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 4f 62 74 61 69  ;.}../*.** Obtai
42e0: 6e 20 73 70 61 63 65 20 66 6f 72 20 61 20 70 61  n space for a pa
42f0: 67 65 2e 20 54 72 79 20 74 6f 20 72 65 63 79 63  ge. Try to recyc
4300: 6c 65 20 61 6e 20 6f 6c 64 20 70 61 67 65 20 69  le an old page i
4310: 66 20 74 68 65 20 6c 69 6d 69 74 20 6f 6e 20 74  f the limit on t
4320: 68 65 20 0a 2a 2a 20 6e 75 6d 62 65 72 20 6f 66  he .** number of
4330: 20 70 61 67 65 73 20 68 61 73 20 62 65 65 6e 20   pages has been 
4340: 72 65 61 63 68 65 64 2e 20 49 66 20 74 68 65 20  reached. If the 
4350: 6c 69 6d 69 74 20 68 61 73 20 6e 6f 74 20 62 65  limit has not be
4360: 65 6e 20 72 65 61 63 68 65 64 20 6f 72 0a 2a 2a  en reached or.**
4370: 20 74 68 65 72 65 20 61 72 65 20 6e 6f 20 70 61   there are no pa
4380: 67 65 73 20 65 6c 69 67 69 62 6c 65 20 66 6f 72  ges eligible for
4390: 20 72 65 63 79 63 6c 69 6e 67 2c 20 61 6c 6c 6f   recycling, allo
43a0: 63 61 74 65 20 61 20 6e 65 77 20 70 61 67 65 2e  cate a new page.
43b0: 0a 2a 2a 0a 2a 2a 20 52 65 74 75 72 6e 20 61 20  .**.** Return a 
43c0: 70 6f 69 6e 74 65 72 20 74 6f 20 74 68 65 20 6e  pointer to the n
43d0: 65 77 20 70 61 67 65 2c 20 6f 72 20 4e 55 4c 4c  ew page, or NULL
43e0: 20 69 66 20 61 6e 20 4f 4f 4d 20 63 6f 6e 64 69   if an OOM condi
43f0: 74 69 6f 6e 20 6f 63 63 75 72 73 2e 0a 2a 2f 0a  tion occurs..*/.
4400: 73 74 61 74 69 63 20 69 6e 74 20 70 63 61 63 68  static int pcach
4410: 65 52 65 63 79 63 6c 65 4f 72 41 6c 6c 6f 63 28  eRecycleOrAlloc(
4420: 50 43 61 63 68 65 20 2a 70 43 61 63 68 65 2c 20  PCache *pCache, 
4430: 50 67 48 64 72 20 2a 2a 70 70 50 61 67 65 29 7b  PgHdr **ppPage){
4440: 0a 20 20 50 67 48 64 72 20 2a 70 20 3d 20 30 3b  .  PgHdr *p = 0;
4450: 0a 0a 20 20 69 6e 74 20 73 7a 50 61 67 65 20 3d  ..  int szPage =
4460: 20 70 43 61 63 68 65 2d 3e 73 7a 50 61 67 65 3b   pCache->szPage;
4470: 0a 20 20 69 6e 74 20 73 7a 45 78 74 72 61 20 3d  .  int szExtra =
4480: 20 70 43 61 63 68 65 2d 3e 73 7a 45 78 74 72 61   pCache->szExtra
4490: 3b 0a 0a 20 20 61 73 73 65 72 74 28 20 70 63 61  ;..  assert( pca
44a0: 63 68 65 5f 67 2e 69 73 49 6e 69 74 20 29 3b 0a  che_g.isInit );.
44b0: 20 20 61 73 73 65 72 74 28 20 73 71 6c 69 74 65    assert( sqlite
44c0: 33 5f 6d 75 74 65 78 5f 68 65 6c 64 28 70 63 61  3_mutex_held(pca
44d0: 63 68 65 5f 67 2e 6d 75 74 65 78 29 20 29 3b 0a  che_g.mutex) );.
44e0: 0a 20 20 2a 70 70 50 61 67 65 20 3d 20 30 3b 0a  .  *ppPage = 0;.
44f0: 0a 20 20 2f 2a 20 49 66 20 77 65 20 68 61 76 65  .  /* If we have
4500: 20 72 65 61 63 68 65 64 20 65 69 74 68 65 72 20   reached either 
4510: 74 68 65 20 67 6c 6f 62 61 6c 20 6f 72 20 74 68  the global or th
4520: 65 20 6c 6f 63 61 6c 20 6c 69 6d 69 74 20 66 6f  e local limit fo
4530: 72 20 0a 20 20 2a 2a 20 70 69 6e 6e 65 64 2b 64  r .  ** pinned+d
4540: 69 72 74 79 20 70 61 67 65 73 2c 20 61 6e 64 20  irty pages, and 
4550: 74 68 65 72 65 20 69 73 20 61 74 20 6c 65 61 73  there is at leas
4560: 74 20 6f 6e 65 20 64 69 72 74 79 20 70 61 67 65  t one dirty page
4570: 2c 0a 20 20 2a 2a 20 69 6e 76 6f 6b 65 20 74 68  ,.  ** invoke th
4580: 65 20 78 53 74 72 65 73 73 20 63 61 6c 6c 62 61  e xStress callba
4590: 63 6b 20 74 6f 20 63 61 75 73 65 20 61 20 70 61  ck to cause a pa
45a0: 67 65 20 74 6f 20 62 65 63 6f 6d 65 20 63 6c 65  ge to become cle
45b0: 61 6e 2e 0a 20 20 2a 2f 0a 20 20 65 78 70 65 6e  an..  */.  expen
45c0: 73 69 76 65 5f 61 73 73 65 72 74 28 20 70 43 61  sive_assert( pCa
45d0: 63 68 65 2d 3e 6e 50 69 6e 6e 65 64 3d 3d 70 63  che->nPinned==pc
45e0: 61 63 68 65 50 69 6e 6e 65 64 43 6f 75 6e 74 28  achePinnedCount(
45f0: 70 43 61 63 68 65 29 20 29 3b 0a 20 20 65 78 70  pCache) );.  exp
4600: 65 6e 73 69 76 65 5f 61 73 73 65 72 74 28 20 70  ensive_assert( p
4610: 63 61 63 68 65 43 68 65 63 6b 53 79 6e 63 65 64  cacheCheckSynced
4620: 28 70 43 61 63 68 65 29 20 29 3b 0a 20 20 69 66  (pCache) );.  if
4630: 28 20 70 43 61 63 68 65 2d 3e 78 53 74 72 65 73  ( pCache->xStres
4640: 73 0a 20 20 20 26 26 20 70 43 61 63 68 65 2d 3e  s.   && pCache->
4650: 70 44 69 72 74 79 0a 20 20 20 26 26 20 28 70 43  pDirty.   && (pC
4660: 61 63 68 65 2d 3e 6e 50 69 6e 6e 65 64 3e 3d 28  ache->nPinned>=(
4670: 70 63 61 63 68 65 5f 67 2e 6e 4d 61 78 50 61 67  pcache_g.nMaxPag
4680: 65 2b 70 43 61 63 68 65 2d 3e 6e 4d 69 6e 2d 70  e+pCache->nMin-p
4690: 63 61 63 68 65 5f 67 2e 6e 4d 69 6e 50 61 67 65  cache_g.nMinPage
46a0: 29 0a 20 20 20 20 20 20 20 20 20 20 20 7c 7c 20  ).           || 
46b0: 70 43 61 63 68 65 2d 3e 6e 50 69 6e 6e 65 64 3e  pCache->nPinned>
46c0: 3d 70 43 61 63 68 65 2d 3e 6e 4d 61 78 29 0a 20  =pCache->nMax). 
46d0: 20 29 7b 0a 20 20 20 20 50 67 48 64 72 20 2a 70   ){.    PgHdr *p
46e0: 50 67 3b 0a 20 20 20 20 61 73 73 65 72 74 28 70  Pg;.    assert(p
46f0: 43 61 63 68 65 2d 3e 70 44 69 72 74 79 54 61 69  Cache->pDirtyTai
4700: 6c 29 3b 0a 0a 20 20 20 20 66 6f 72 28 70 50 67  l);..    for(pPg
4710: 3d 70 43 61 63 68 65 2d 3e 70 53 79 6e 63 65 64  =pCache->pSynced
4720: 3b 20 0a 20 20 20 20 20 20 20 20 70 50 67 20 26  ; .        pPg &
4730: 26 20 28 70 50 67 2d 3e 6e 52 65 66 20 7c 7c 20  & (pPg->nRef || 
4740: 28 70 50 67 2d 3e 66 6c 61 67 73 26 50 47 48 44  (pPg->flags&PGHD
4750: 52 5f 4e 45 45 44 5f 53 59 4e 43 29 29 3b 20 0a  R_NEED_SYNC)); .
4760: 20 20 20 20 20 20 20 20 70 50 67 3d 70 50 67 2d          pPg=pPg-
4770: 3e 70 50 72 65 76 0a 20 20 20 20 29 3b 0a 20 20  >pPrev.    );.  
4780: 20 20 69 66 28 20 21 70 50 67 20 29 7b 0a 20 20    if( !pPg ){.  
4790: 20 20 20 20 66 6f 72 28 70 50 67 3d 70 43 61 63      for(pPg=pCac
47a0: 68 65 2d 3e 70 44 69 72 74 79 54 61 69 6c 3b 20  he->pDirtyTail; 
47b0: 70 50 67 20 26 26 20 70 50 67 2d 3e 6e 52 65 66  pPg && pPg->nRef
47c0: 3b 20 70 50 67 3d 70 50 67 2d 3e 70 50 72 65 76  ; pPg=pPg->pPrev
47d0: 29 3b 0a 20 20 20 20 7d 0a 20 20 20 20 69 66 28  );.    }.    if(
47e0: 20 70 50 67 20 29 7b 0a 20 20 20 20 20 20 69 6e   pPg ){.      in
47f0: 74 20 72 63 3b 0a 20 20 20 20 20 20 70 63 61 63  t rc;.      pcac
4800: 68 65 45 78 69 74 4d 75 74 65 78 28 29 3b 0a 20  heExitMutex();. 
4810: 20 20 20 20 20 72 63 20 3d 20 70 43 61 63 68 65       rc = pCache
4820: 2d 3e 78 53 74 72 65 73 73 28 70 43 61 63 68 65  ->xStress(pCache
4830: 2d 3e 70 53 74 72 65 73 73 2c 20 70 50 67 29 3b  ->pStress, pPg);
4840: 0a 20 20 20 20 20 20 70 63 61 63 68 65 45 6e 74  .      pcacheEnt
4850: 65 72 4d 75 74 65 78 28 29 3b 0a 20 20 20 20 20  erMutex();.     
4860: 20 69 66 28 20 72 63 21 3d 53 51 4c 49 54 45 5f   if( rc!=SQLITE_
4870: 4f 4b 20 26 26 20 72 63 21 3d 53 51 4c 49 54 45  OK && rc!=SQLITE
4880: 5f 42 55 53 59 20 29 7b 0a 20 20 20 20 20 20 20  _BUSY ){.       
4890: 20 72 65 74 75 72 6e 20 72 63 3b 0a 20 20 20 20   return rc;.    
48a0: 20 20 7d 0a 20 20 20 20 7d 0a 20 20 7d 0a 0a 20    }.    }.  }.. 
48b0: 20 2f 2a 20 49 66 20 65 69 74 68 65 72 20 74 68   /* If either th
48c0: 65 20 6c 6f 63 61 6c 20 6f 72 20 74 68 65 20 67  e local or the g
48d0: 6c 6f 62 61 6c 20 70 61 67 65 20 6c 69 6d 69 74  lobal page limit
48e0: 20 68 61 73 20 62 65 65 6e 20 72 65 61 63 68 65   has been reache
48f0: 64 2c 20 0a 20 20 2a 2a 20 74 72 79 20 74 6f 20  d, .  ** try to 
4900: 72 65 63 79 63 6c 65 20 61 20 70 61 67 65 2e 20  recycle a page. 
4910: 0a 20 20 2a 2f 0a 20 20 69 66 28 20 70 43 61 63  .  */.  if( pCac
4920: 68 65 2d 3e 62 50 75 72 67 65 61 62 6c 65 20 26  he->bPurgeable &
4930: 26 20 28 70 43 61 63 68 65 2d 3e 6e 50 61 67 65  & (pCache->nPage
4940: 3e 3d 70 43 61 63 68 65 2d 3e 6e 4d 61 78 2d 31  >=pCache->nMax-1
4950: 20 7c 7c 0a 20 20 20 20 20 20 20 20 20 20 20 20   ||.            
4960: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4970: 20 70 63 61 63 68 65 5f 67 2e 6e 43 75 72 72 65   pcache_g.nCurre
4980: 6e 74 50 61 67 65 3e 3d 70 63 61 63 68 65 5f 67  ntPage>=pcache_g
4990: 2e 6e 4d 61 78 50 61 67 65 29 20 29 7b 0a 20 20  .nMaxPage) ){.  
49a0: 20 20 70 20 3d 20 70 63 61 63 68 65 52 65 63 79    p = pcacheRecy
49b0: 63 6c 65 50 61 67 65 28 29 3b 0a 20 20 7d 0a 0a  clePage();.  }..
49c0: 20 20 2f 2a 20 49 66 20 61 20 70 61 67 65 20 68    /* If a page h
49d0: 61 73 20 62 65 65 6e 20 72 65 63 79 63 6c 65 64  as been recycled
49e0: 20 62 75 74 20 69 74 20 69 73 20 74 68 65 20 77   but it is the w
49f0: 72 6f 6e 67 20 73 69 7a 65 2c 20 66 72 65 65 20  rong size, free 
4a00: 69 74 2e 20 2a 2f 0a 20 20 69 66 28 20 70 20 26  it. */.  if( p &
4a10: 26 20 28 70 2d 3e 70 43 61 63 68 65 2d 3e 73 7a  & (p->pCache->sz
4a20: 50 61 67 65 21 3d 73 7a 50 61 67 65 20 7c 7c 20  Page!=szPage || 
4a30: 70 2d 3e 70 43 61 63 68 65 2d 3e 73 7a 50 61 67  p->pCache->szPag
4a40: 65 21 3d 73 7a 45 78 74 72 61 29 20 29 7b 0a 20  e!=szExtra) ){. 
4a50: 20 20 20 70 63 61 63 68 65 50 61 67 65 46 72 65     pcachePageFre
4a60: 65 28 70 29 3b 0a 20 20 20 20 70 20 3d 20 30 3b  e(p);.    p = 0;
4a70: 0a 20 20 7d 0a 0a 20 20 69 66 28 20 21 70 20 29  .  }..  if( !p )
4a80: 7b 0a 20 20 20 20 70 20 3d 20 70 63 61 63 68 65  {.    p = pcache
4a90: 50 61 67 65 41 6c 6c 6f 63 28 70 43 61 63 68 65  PageAlloc(pCache
4aa0: 29 3b 0a 20 20 7d 0a 0a 20 20 2a 70 70 50 61 67  );.  }..  *ppPag
4ab0: 65 20 3d 20 70 3b 0a 20 20 72 65 74 75 72 6e 20  e = p;.  return 
4ac0: 28 70 3f 53 51 4c 49 54 45 5f 4f 4b 3a 53 51 4c  (p?SQLITE_OK:SQL
4ad0: 49 54 45 5f 4e 4f 4d 45 4d 29 3b 0a 7d 0a 0a 2f  ITE_NOMEM);.}../
4ae0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
4af0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
4b00: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
4b10: 2a 2a 2a 20 47 65 6e 65 72 61 6c 20 49 6e 74 65  *** General Inte
4b20: 72 66 61 63 65 73 20 2a 2a 2a 2a 2a 2a 0a 2a 2a  rfaces ******.**
4b30: 0a 2a 2a 20 49 6e 69 74 69 61 6c 69 7a 65 20 61  .** Initialize a
4b40: 6e 64 20 73 68 75 74 64 6f 77 6e 20 74 68 65 20  nd shutdown the 
4b50: 70 61 67 65 20 63 61 63 68 65 20 73 75 62 73 79  page cache subsy
4b60: 73 74 65 6d 2e 20 4e 65 69 74 68 65 72 20 6f 66  stem. Neither of
4b70: 20 74 68 65 73 65 20 0a 2a 2a 20 66 75 6e 63 74   these .** funct
4b80: 69 6f 6e 73 20 61 72 65 20 74 68 72 65 61 64 73  ions are threads
4b90: 61 66 65 2e 0a 2a 2f 0a 69 6e 74 20 73 71 6c 69  afe..*/.int sqli
4ba0: 74 65 33 50 63 61 63 68 65 49 6e 69 74 69 61 6c  te3PcacheInitial
4bb0: 69 7a 65 28 76 6f 69 64 29 7b 0a 20 20 61 73 73  ize(void){.  ass
4bc0: 65 72 74 28 20 70 63 61 63 68 65 5f 67 2e 69 73  ert( pcache_g.is
4bd0: 49 6e 69 74 3d 3d 30 20 29 3b 0a 20 20 6d 65 6d  Init==0 );.  mem
4be0: 73 65 74 28 26 70 63 61 63 68 65 5f 67 2c 20 30  set(&pcache_g, 0
4bf0: 2c 20 73 69 7a 65 6f 66 28 70 63 61 63 68 65 29  , sizeof(pcache)
4c00: 29 3b 0a 20 20 69 66 28 20 73 71 6c 69 74 65 33  );.  if( sqlite3
4c10: 47 6c 6f 62 61 6c 43 6f 6e 66 69 67 2e 62 43 6f  GlobalConfig.bCo
4c20: 72 65 4d 75 74 65 78 20 29 7b 0a 20 20 20 20 2f  reMutex ){.    /
4c30: 2a 20 4e 6f 20 6e 65 65 64 20 74 6f 20 63 68 65  * No need to che
4c40: 63 6b 20 74 68 65 20 72 65 74 75 72 6e 20 76 61  ck the return va
4c50: 6c 75 65 20 6f 66 20 73 71 6c 69 74 65 33 5f 6d  lue of sqlite3_m
4c60: 75 74 65 78 5f 61 6c 6c 6f 63 28 29 2e 20 0a 20  utex_alloc(). . 
4c70: 20 20 20 2a 2a 20 41 6c 6c 6f 63 61 74 69 6e 67     ** Allocating
4c80: 20 61 20 73 74 61 74 69 63 20 6d 75 74 65 78 20   a static mutex 
4c90: 63 61 6e 6e 6f 74 20 66 61 69 6c 2e 0a 20 20 20  cannot fail..   
4ca0: 20 2a 2f 0a 20 20 20 20 70 63 61 63 68 65 5f 67   */.    pcache_g
4cb0: 2e 6d 75 74 65 78 20 3d 20 73 71 6c 69 74 65 33  .mutex = sqlite3
4cc0: 5f 6d 75 74 65 78 5f 61 6c 6c 6f 63 28 53 51 4c  _mutex_alloc(SQL
4cd0: 49 54 45 5f 4d 55 54 45 58 5f 53 54 41 54 49 43  ITE_MUTEX_STATIC
4ce0: 5f 4c 52 55 29 3b 0a 20 20 7d 0a 20 20 70 63 61  _LRU);.  }.  pca
4cf0: 63 68 65 5f 67 2e 69 73 49 6e 69 74 20 3d 20 31  che_g.isInit = 1
4d00: 3b 0a 20 20 72 65 74 75 72 6e 20 53 51 4c 49 54  ;.  return SQLIT
4d10: 45 5f 4f 4b 3b 0a 7d 0a 76 6f 69 64 20 73 71 6c  E_OK;.}.void sql
4d20: 69 74 65 33 50 63 61 63 68 65 53 68 75 74 64 6f  ite3PcacheShutdo
4d30: 77 6e 28 76 6f 69 64 29 7b 0a 20 20 6d 65 6d 73  wn(void){.  mems
4d40: 65 74 28 26 70 63 61 63 68 65 5f 67 2c 20 30 2c  et(&pcache_g, 0,
4d50: 20 73 69 7a 65 6f 66 28 70 63 61 63 68 65 29 29   sizeof(pcache))
4d60: 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 52 65 74 75 72  ;.}../*.** Retur
4d70: 6e 20 74 68 65 20 73 69 7a 65 20 69 6e 20 62 79  n the size in by
4d80: 74 65 73 20 6f 66 20 61 20 50 43 61 63 68 65 20  tes of a PCache 
4d90: 6f 62 6a 65 63 74 2e 0a 2a 2f 0a 69 6e 74 20 73  object..*/.int s
4da0: 71 6c 69 74 65 33 50 63 61 63 68 65 53 69 7a 65  qlite3PcacheSize
4db0: 28 76 6f 69 64 29 7b 20 72 65 74 75 72 6e 20 73  (void){ return s
4dc0: 69 7a 65 6f 66 28 50 43 61 63 68 65 29 3b 20 7d  izeof(PCache); }
4dd0: 0a 0a 2f 2a 0a 2a 2a 20 43 72 65 61 74 65 20 61  ../*.** Create a
4de0: 20 6e 65 77 20 50 43 61 63 68 65 20 6f 62 6a 65   new PCache obje
4df0: 63 74 2e 20 20 53 74 6f 72 61 67 65 20 73 70 61  ct.  Storage spa
4e00: 63 65 20 74 6f 20 68 6f 6c 64 20 74 68 65 20 6f  ce to hold the o
4e10: 62 6a 65 63 74 0a 2a 2a 20 68 61 73 20 61 6c 72  bject.** has alr
4e20: 65 61 64 79 20 62 65 65 6e 20 61 6c 6c 6f 63 61  eady been alloca
4e30: 74 65 64 20 61 6e 64 20 69 73 20 70 61 73 73 65  ted and is passe
4e40: 64 20 69 6e 20 61 73 20 74 68 65 20 70 20 70 6f  d in as the p po
4e50: 69 6e 74 65 72 2e 0a 2a 2f 0a 76 6f 69 64 20 73  inter..*/.void s
4e60: 71 6c 69 74 65 33 50 63 61 63 68 65 4f 70 65 6e  qlite3PcacheOpen
4e70: 28 0a 20 20 69 6e 74 20 73 7a 50 61 67 65 2c 20  (.  int szPage, 
4e80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4e90: 20 2f 2a 20 53 69 7a 65 20 6f 66 20 65 76 65 72   /* Size of ever
4ea0: 79 20 70 61 67 65 20 2a 2f 0a 20 20 69 6e 74 20  y page */.  int 
4eb0: 73 7a 45 78 74 72 61 2c 20 20 20 20 20 20 20 20  szExtra,        
4ec0: 20 20 20 20 20 20 20 20 20 2f 2a 20 45 78 74 72           /* Extr
4ed0: 61 20 73 70 61 63 65 20 61 73 73 6f 63 69 61 74  a space associat
4ee0: 65 64 20 77 69 74 68 20 65 61 63 68 20 70 61 67  ed with each pag
4ef0: 65 20 2a 2f 0a 20 20 69 6e 74 20 62 50 75 72 67  e */.  int bPurg
4f00: 65 61 62 6c 65 2c 20 20 20 20 20 20 20 20 20 20  eable,          
4f10: 20 20 20 20 2f 2a 20 54 72 75 65 20 69 66 20 70      /* True if p
4f20: 61 67 65 73 20 61 72 65 20 6f 6e 20 62 61 63 6b  ages are on back
4f30: 69 6e 67 20 73 74 6f 72 65 20 2a 2f 0a 20 20 76  ing store */.  v
4f40: 6f 69 64 20 28 2a 78 44 65 73 74 72 6f 79 29 28  oid (*xDestroy)(
4f50: 50 67 48 64 72 2a 29 2c 20 20 20 20 2f 2a 20 43  PgHdr*),    /* C
4f60: 61 6c 6c 65 64 20 74 6f 20 64 65 73 74 72 6f 79  alled to destroy
4f70: 20 61 20 70 61 67 65 20 2a 2f 0a 20 20 69 6e 74   a page */.  int
4f80: 20 28 2a 78 53 74 72 65 73 73 29 28 76 6f 69 64   (*xStress)(void
4f90: 2a 2c 50 67 48 64 72 2a 29 2c 2f 2a 20 43 61 6c  *,PgHdr*),/* Cal
4fa0: 6c 20 74 6f 20 74 72 79 20 74 6f 20 6d 61 6b 65  l to try to make
4fb0: 20 70 61 67 65 73 20 63 6c 65 61 6e 20 2a 2f 0a   pages clean */.
4fc0: 20 20 76 6f 69 64 20 2a 70 53 74 72 65 73 73 2c    void *pStress,
4fd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
4fe0: 2a 20 41 72 67 75 6d 65 6e 74 20 74 6f 20 78 53  * Argument to xS
4ff0: 74 72 65 73 73 20 2a 2f 0a 20 20 50 43 61 63 68  tress */.  PCach
5000: 65 20 2a 70 20 20 20 20 20 20 20 20 20 20 20 20  e *p            
5010: 20 20 20 20 20 20 20 20 2f 2a 20 50 72 65 61 6c          /* Preal
5020: 6c 6f 63 61 74 65 64 20 73 70 61 63 65 20 66 6f  located space fo
5030: 72 20 74 68 65 20 50 43 61 63 68 65 20 2a 2f 0a  r the PCache */.
5040: 29 7b 0a 20 20 61 73 73 65 72 74 28 20 70 63 61  ){.  assert( pca
5050: 63 68 65 5f 67 2e 69 73 49 6e 69 74 20 29 3b 0a  che_g.isInit );.
5060: 20 20 6d 65 6d 73 65 74 28 70 2c 20 30 2c 20 73    memset(p, 0, s
5070: 69 7a 65 6f 66 28 50 43 61 63 68 65 29 29 3b 0a  izeof(PCache));.
5080: 20 20 70 2d 3e 73 7a 50 61 67 65 20 3d 20 73 7a    p->szPage = sz
5090: 50 61 67 65 3b 0a 20 20 70 2d 3e 73 7a 45 78 74  Page;.  p->szExt
50a0: 72 61 20 3d 20 73 7a 45 78 74 72 61 3b 0a 20 20  ra = szExtra;.  
50b0: 70 2d 3e 62 50 75 72 67 65 61 62 6c 65 20 3d 20  p->bPurgeable = 
50c0: 62 50 75 72 67 65 61 62 6c 65 3b 0a 20 20 70 2d  bPurgeable;.  p-
50d0: 3e 78 44 65 73 74 72 6f 79 20 3d 20 78 44 65 73  >xDestroy = xDes
50e0: 74 72 6f 79 3b 0a 20 20 70 2d 3e 78 53 74 72 65  troy;.  p->xStre
50f0: 73 73 20 3d 20 78 53 74 72 65 73 73 3b 0a 20 20  ss = xStress;.  
5100: 70 2d 3e 70 53 74 72 65 73 73 20 3d 20 70 53 74  p->pStress = pSt
5110: 72 65 73 73 3b 0a 20 20 70 2d 3e 6e 4d 61 78 20  ress;.  p->nMax 
5120: 3d 20 31 30 30 3b 0a 20 20 70 2d 3e 6e 4d 69 6e  = 100;.  p->nMin
5130: 20 3d 20 31 30 3b 0a 0a 20 20 70 63 61 63 68 65   = 10;..  pcache
5140: 45 6e 74 65 72 4d 75 74 65 78 28 29 3b 0a 20 20  EnterMutex();.  
5150: 69 66 28 20 62 50 75 72 67 65 61 62 6c 65 20 29  if( bPurgeable )
5160: 7b 0a 20 20 20 20 70 63 61 63 68 65 5f 67 2e 6e  {.    pcache_g.n
5170: 4d 61 78 50 61 67 65 20 2b 3d 20 70 2d 3e 6e 4d  MaxPage += p->nM
5180: 61 78 3b 0a 20 20 20 20 70 63 61 63 68 65 5f 67  ax;.    pcache_g
5190: 2e 6e 4d 69 6e 50 61 67 65 20 2b 3d 20 70 2d 3e  .nMinPage += p->
51a0: 6e 4d 69 6e 3b 0a 20 20 7d 0a 0a 20 20 70 63 61  nMin;.  }..  pca
51b0: 63 68 65 45 78 69 74 4d 75 74 65 78 28 29 3b 0a  cheExitMutex();.
51c0: 7d 0a 0a 2f 2a 0a 2a 2a 20 43 68 61 6e 67 65 20  }../*.** Change 
51d0: 74 68 65 20 70 61 67 65 20 73 69 7a 65 20 66 6f  the page size fo
51e0: 72 20 50 43 61 63 68 65 20 6f 62 6a 65 63 74 2e  r PCache object.
51f0: 20 20 54 68 69 73 20 63 61 6e 20 6f 6e 6c 79 20    This can only 
5200: 68 61 70 70 65 6e 0a 2a 2a 20 77 68 65 6e 20 74  happen.** when t
5210: 68 65 20 63 61 63 68 65 20 69 73 20 65 6d 70 74  he cache is empt
5220: 79 2e 0a 2a 2f 0a 76 6f 69 64 20 73 71 6c 69 74  y..*/.void sqlit
5230: 65 33 50 63 61 63 68 65 53 65 74 50 61 67 65 53  e3PcacheSetPageS
5240: 69 7a 65 28 50 43 61 63 68 65 20 2a 70 43 61 63  ize(PCache *pCac
5250: 68 65 2c 20 69 6e 74 20 73 7a 50 61 67 65 29 7b  he, int szPage){
5260: 0a 20 20 61 73 73 65 72 74 28 70 43 61 63 68 65  .  assert(pCache
5270: 2d 3e 6e 50 61 67 65 3d 3d 30 29 3b 0a 20 20 70  ->nPage==0);.  p
5280: 43 61 63 68 65 2d 3e 73 7a 50 61 67 65 20 3d 20  Cache->szPage = 
5290: 73 7a 50 61 67 65 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a  szPage;.}../*.**
52a0: 20 54 72 79 20 74 6f 20 6f 62 74 61 69 6e 20 61   Try to obtain a
52b0: 20 70 61 67 65 20 66 72 6f 6d 20 74 68 65 20 63   page from the c
52c0: 61 63 68 65 2e 0a 2a 2f 0a 69 6e 74 20 73 71 6c  ache..*/.int sql
52d0: 69 74 65 33 50 63 61 63 68 65 46 65 74 63 68 28  ite3PcacheFetch(
52e0: 0a 20 20 50 43 61 63 68 65 20 2a 70 43 61 63 68  .  PCache *pCach
52f0: 65 2c 20 20 20 20 20 20 20 2f 2a 20 4f 62 74 61  e,       /* Obta
5300: 69 6e 20 74 68 65 20 70 61 67 65 20 66 72 6f 6d  in the page from
5310: 20 74 68 69 73 20 63 61 63 68 65 20 2a 2f 0a 20   this cache */. 
5320: 20 50 67 6e 6f 20 70 67 6e 6f 2c 20 20 20 20 20   Pgno pgno,     
5330: 20 20 20 20 20 20 20 2f 2a 20 50 61 67 65 20 6e         /* Page n
5340: 75 6d 62 65 72 20 74 6f 20 6f 62 74 61 69 6e 20  umber to obtain 
5350: 2a 2f 0a 20 20 69 6e 74 20 63 72 65 61 74 65 46  */.  int createF
5360: 6c 61 67 2c 20 20 20 20 20 20 20 2f 2a 20 49 66  lag,       /* If
5370: 20 74 72 75 65 2c 20 63 72 65 61 74 65 20 70 61   true, create pa
5380: 67 65 20 69 66 20 69 74 20 64 6f 65 73 20 6e 6f  ge if it does no
5390: 74 20 65 78 69 73 74 20 61 6c 72 65 61 64 79 20  t exist already 
53a0: 2a 2f 0a 20 20 50 67 48 64 72 20 2a 2a 70 70 50  */.  PgHdr **ppP
53b0: 61 67 65 20 20 20 20 20 20 20 20 2f 2a 20 57 72  age        /* Wr
53c0: 69 74 65 20 74 68 65 20 70 61 67 65 20 68 65 72  ite the page her
53d0: 65 20 2a 2f 0a 29 7b 0a 20 20 69 6e 74 20 72 63  e */.){.  int rc
53e0: 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20   = SQLITE_OK;.  
53f0: 50 67 48 64 72 20 2a 70 50 61 67 65 20 3d 20 30  PgHdr *pPage = 0
5400: 3b 0a 0a 20 20 61 73 73 65 72 74 28 20 70 63 61  ;..  assert( pca
5410: 63 68 65 5f 67 2e 69 73 49 6e 69 74 20 29 3b 0a  che_g.isInit );.
5420: 20 20 61 73 73 65 72 74 28 20 70 43 61 63 68 65    assert( pCache
5430: 21 3d 30 20 29 3b 0a 20 20 61 73 73 65 72 74 28  !=0 );.  assert(
5440: 20 70 67 6e 6f 3e 30 20 29 3b 0a 20 20 65 78 70   pgno>0 );.  exp
5450: 65 6e 73 69 76 65 5f 61 73 73 65 72 74 28 20 70  ensive_assert( p
5460: 43 61 63 68 65 2d 3e 6e 50 69 6e 6e 65 64 3d 3d  Cache->nPinned==
5470: 70 63 61 63 68 65 50 69 6e 6e 65 64 43 6f 75 6e  pcachePinnedCoun
5480: 74 28 70 43 61 63 68 65 29 20 29 3b 0a 0a 20 20  t(pCache) );..  
5490: 70 63 61 63 68 65 45 6e 74 65 72 4d 75 74 65 78  pcacheEnterMutex
54a0: 28 29 3b 0a 0a 20 20 2f 2a 20 53 65 61 72 63 68  ();..  /* Search
54b0: 20 74 68 65 20 68 61 73 68 20 74 61 62 6c 65 20   the hash table 
54c0: 66 6f 72 20 74 68 65 20 72 65 71 75 65 73 74 65  for the requeste
54d0: 64 20 70 61 67 65 2e 20 45 78 69 74 20 65 61 72  d page. Exit ear
54e0: 6c 79 20 69 66 20 69 74 20 69 73 20 66 6f 75 6e  ly if it is foun
54f0: 64 2e 20 2a 2f 0a 20 20 69 66 28 20 70 43 61 63  d. */.  if( pCac
5500: 68 65 2d 3e 61 70 48 61 73 68 20 29 7b 0a 20 20  he->apHash ){.  
5510: 20 20 75 33 32 20 68 20 3d 20 70 67 6e 6f 20 25    u32 h = pgno %
5520: 20 70 43 61 63 68 65 2d 3e 6e 48 61 73 68 3b 0a   pCache->nHash;.
5530: 20 20 20 20 66 6f 72 28 70 50 61 67 65 3d 70 43      for(pPage=pC
5540: 61 63 68 65 2d 3e 61 70 48 61 73 68 5b 68 5d 3b  ache->apHash[h];
5550: 20 70 50 61 67 65 3b 20 70 50 61 67 65 3d 70 50   pPage; pPage=pP
5560: 61 67 65 2d 3e 70 4e 65 78 74 48 61 73 68 29 7b  age->pNextHash){
5570: 0a 20 20 20 20 20 20 69 66 28 20 70 50 61 67 65  .      if( pPage
5580: 2d 3e 70 67 6e 6f 3d 3d 70 67 6e 6f 20 29 7b 0a  ->pgno==pgno ){.
5590: 20 20 20 20 20 20 20 20 69 66 28 20 70 50 61 67          if( pPag
55a0: 65 2d 3e 6e 52 65 66 3d 3d 30 20 29 7b 0a 20 20  e->nRef==0 ){.  
55b0: 20 20 20 20 20 20 20 20 69 66 28 20 30 3d 3d 28          if( 0==(
55c0: 70 50 61 67 65 2d 3e 66 6c 61 67 73 26 50 47 48  pPage->flags&PGH
55d0: 44 52 5f 44 49 52 54 59 29 20 29 7b 0a 20 20 20  DR_DIRTY) ){.   
55e0: 20 20 20 20 20 20 20 20 20 70 63 61 63 68 65 52           pcacheR
55f0: 65 6d 6f 76 65 46 72 6f 6d 4c 72 75 4c 69 73 74  emoveFromLruList
5600: 28 70 50 61 67 65 29 3b 0a 20 20 20 20 20 20 20  (pPage);.       
5610: 20 20 20 20 20 70 43 61 63 68 65 2d 3e 6e 50 69       pCache->nPi
5620: 6e 6e 65 64 2b 2b 3b 0a 20 20 20 20 20 20 20 20  nned++;.        
5630: 20 20 7d 0a 20 20 20 20 20 20 20 20 20 20 70 43    }.          pC
5640: 61 63 68 65 2d 3e 6e 52 65 66 2b 2b 3b 0a 20 20  ache->nRef++;.  
5650: 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 20 20        }.        
5660: 70 50 61 67 65 2d 3e 6e 52 65 66 2b 2b 3b 0a 20  pPage->nRef++;. 
5670: 20 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20 20         break;.  
5680: 20 20 20 20 7d 0a 20 20 20 20 7d 0a 20 20 7d 0a      }.    }.  }.
5690: 0a 20 20 69 66 28 20 21 70 50 61 67 65 20 26 26  .  if( !pPage &&
56a0: 20 63 72 65 61 74 65 46 6c 61 67 20 29 7b 0a 20   createFlag ){. 
56b0: 20 20 20 69 66 28 20 70 43 61 63 68 65 2d 3e 6e     if( pCache->n
56c0: 48 61 73 68 3c 3d 70 43 61 63 68 65 2d 3e 6e 50  Hash<=pCache->nP
56d0: 61 67 65 20 29 7b 0a 20 20 20 20 20 20 72 63 20  age ){.      rc 
56e0: 3d 20 70 63 61 63 68 65 52 65 73 69 7a 65 48 61  = pcacheResizeHa
56f0: 73 68 28 70 43 61 63 68 65 2c 20 70 43 61 63 68  sh(pCache, pCach
5700: 65 2d 3e 6e 48 61 73 68 3c 32 35 36 20 3f 20 32  e->nHash<256 ? 2
5710: 35 36 20 3a 20 70 43 61 63 68 65 2d 3e 6e 48 61  56 : pCache->nHa
5720: 73 68 2a 32 29 3b 0a 20 20 20 20 7d 0a 20 20 20  sh*2);.    }.   
5730: 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f   if( rc==SQLITE_
5740: 4f 4b 20 29 7b 0a 20 20 20 20 20 20 72 63 20 3d  OK ){.      rc =
5750: 20 70 63 61 63 68 65 52 65 63 79 63 6c 65 4f 72   pcacheRecycleOr
5760: 41 6c 6c 6f 63 28 70 43 61 63 68 65 2c 20 26 70  Alloc(pCache, &p
5770: 50 61 67 65 29 3b 0a 20 20 20 20 7d 0a 20 20 20  Page);.    }.   
5780: 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f   if( rc==SQLITE_
5790: 4f 4b 20 29 7b 0a 20 20 20 20 20 20 70 50 61 67  OK ){.      pPag
57a0: 65 2d 3e 70 50 61 67 65 72 20 3d 20 30 3b 0a 20  e->pPager = 0;. 
57b0: 20 20 20 20 20 70 50 61 67 65 2d 3e 66 6c 61 67       pPage->flag
57c0: 73 20 3d 20 30 3b 0a 20 20 20 20 20 20 70 50 61  s = 0;.      pPa
57d0: 67 65 2d 3e 70 44 69 72 74 79 20 3d 20 30 3b 0a  ge->pDirty = 0;.
57e0: 20 20 20 20 20 20 70 50 61 67 65 2d 3e 70 67 6e        pPage->pgn
57f0: 6f 20 3d 20 70 67 6e 6f 3b 0a 20 20 20 20 20 20  o = pgno;.      
5800: 70 50 61 67 65 2d 3e 70 43 61 63 68 65 20 3d 20  pPage->pCache = 
5810: 70 43 61 63 68 65 3b 0a 20 20 20 20 20 20 70 50  pCache;.      pP
5820: 61 67 65 2d 3e 6e 52 65 66 20 3d 20 31 3b 0a 20  age->nRef = 1;. 
5830: 20 20 20 20 20 70 43 61 63 68 65 2d 3e 6e 52 65       pCache->nRe
5840: 66 2b 2b 3b 0a 20 20 20 20 20 20 70 43 61 63 68  f++;.      pCach
5850: 65 2d 3e 6e 50 69 6e 6e 65 64 2b 2b 3b 0a 20 20  e->nPinned++;.  
5860: 20 20 20 20 70 63 61 63 68 65 41 64 64 54 6f 4c      pcacheAddToL
5870: 69 73 74 28 26 70 43 61 63 68 65 2d 3e 70 43 6c  ist(&pCache->pCl
5880: 65 61 6e 2c 20 70 50 61 67 65 29 3b 0a 20 20 20  ean, pPage);.   
5890: 20 20 20 70 63 61 63 68 65 41 64 64 54 6f 48 61     pcacheAddToHa
58a0: 73 68 28 70 50 61 67 65 29 3b 0a 20 20 20 20 7d  sh(pPage);.    }
58b0: 0a 20 20 7d 0a 0a 20 20 70 63 61 63 68 65 45 78  .  }..  pcacheEx
58c0: 69 74 4d 75 74 65 78 28 29 3b 0a 0a 20 20 2a 70  itMutex();..  *p
58d0: 70 50 61 67 65 20 3d 20 70 50 61 67 65 3b 0a 20  pPage = pPage;. 
58e0: 20 65 78 70 65 6e 73 69 76 65 5f 61 73 73 65 72   expensive_asser
58f0: 74 28 20 70 43 61 63 68 65 2d 3e 6e 50 69 6e 6e  t( pCache->nPinn
5900: 65 64 3d 3d 70 63 61 63 68 65 50 69 6e 6e 65 64  ed==pcachePinned
5910: 43 6f 75 6e 74 28 70 43 61 63 68 65 29 20 29 3b  Count(pCache) );
5920: 0a 20 20 61 73 73 65 72 74 28 20 70 50 61 67 65  .  assert( pPage
5930: 20 7c 7c 20 21 63 72 65 61 74 65 46 6c 61 67 20   || !createFlag 
5940: 7c 7c 20 72 63 21 3d 53 51 4c 49 54 45 5f 4f 4b  || rc!=SQLITE_OK
5950: 20 29 3b 0a 20 20 72 65 74 75 72 6e 20 72 63 3b   );.  return rc;
5960: 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 44 65 72 65 66 65  .}../*.** Derefe
5970: 72 65 6e 63 65 20 61 20 70 61 67 65 2e 20 20 57  rence a page.  W
5980: 68 65 6e 20 74 68 65 20 72 65 66 65 72 65 6e 63  hen the referenc
5990: 65 20 63 6f 75 6e 74 20 72 65 61 63 68 65 73 20  e count reaches 
59a0: 7a 65 72 6f 2c 0a 2a 2a 20 6d 6f 76 65 20 74 68  zero,.** move th
59b0: 65 20 70 61 67 65 20 74 6f 20 74 68 65 20 4c 52  e page to the LR
59c0: 55 20 6c 69 73 74 20 69 66 20 69 74 20 69 73 20  U list if it is 
59d0: 63 6c 65 61 6e 2e 0a 2a 2f 0a 76 6f 69 64 20 73  clean..*/.void s
59e0: 71 6c 69 74 65 33 50 63 61 63 68 65 52 65 6c 65  qlite3PcacheRele
59f0: 61 73 65 28 50 67 48 64 72 20 2a 70 29 7b 0a 20  ase(PgHdr *p){. 
5a00: 20 61 73 73 65 72 74 28 20 70 2d 3e 6e 52 65 66   assert( p->nRef
5a10: 3e 30 20 29 3b 0a 20 20 70 2d 3e 6e 52 65 66 2d  >0 );.  p->nRef-
5a20: 2d 3b 0a 20 20 69 66 28 20 70 2d 3e 6e 52 65 66  -;.  if( p->nRef
5a30: 3d 3d 30 20 29 7b 0a 20 20 20 20 50 43 61 63 68  ==0 ){.    PCach
5a40: 65 20 2a 70 43 61 63 68 65 20 3d 20 70 2d 3e 70  e *pCache = p->p
5a50: 43 61 63 68 65 3b 0a 20 20 20 20 69 66 28 20 70  Cache;.    if( p
5a60: 2d 3e 70 43 61 63 68 65 2d 3e 78 44 65 73 74 72  ->pCache->xDestr
5a70: 6f 79 20 29 7b 0a 20 20 20 20 20 20 70 2d 3e 70  oy ){.      p->p
5a80: 43 61 63 68 65 2d 3e 78 44 65 73 74 72 6f 79 28  Cache->xDestroy(
5a90: 70 29 3b 0a 20 20 20 20 7d 0a 20 20 20 20 70 43  p);.    }.    pC
5aa0: 61 63 68 65 2d 3e 6e 52 65 66 2d 2d 3b 0a 20 20  ache->nRef--;.  
5ab0: 20 20 69 66 28 20 28 70 2d 3e 66 6c 61 67 73 26    if( (p->flags&
5ac0: 50 47 48 44 52 5f 44 49 52 54 59 29 3d 3d 30 20  PGHDR_DIRTY)==0 
5ad0: 29 7b 0a 20 20 20 20 20 20 70 43 61 63 68 65 2d  ){.      pCache-
5ae0: 3e 6e 50 69 6e 6e 65 64 2d 2d 3b 0a 20 20 20 20  >nPinned--;.    
5af0: 20 20 70 63 61 63 68 65 45 6e 74 65 72 4d 75 74    pcacheEnterMut
5b00: 65 78 28 29 3b 0a 20 20 20 20 20 20 69 66 28 20  ex();.      if( 
5b10: 70 63 61 63 68 65 5f 67 2e 6e 43 75 72 72 65 6e  pcache_g.nCurren
5b20: 74 50 61 67 65 3e 70 63 61 63 68 65 5f 67 2e 6e  tPage>pcache_g.n
5b30: 4d 61 78 50 61 67 65 20 29 7b 0a 20 20 20 20 20  MaxPage ){.     
5b40: 20 20 20 70 63 61 63 68 65 52 65 6d 6f 76 65 46     pcacheRemoveF
5b50: 72 6f 6d 4c 69 73 74 28 26 70 43 61 63 68 65 2d  romList(&pCache-
5b60: 3e 70 43 6c 65 61 6e 2c 20 70 29 3b 0a 20 20 20  >pClean, p);.   
5b70: 20 20 20 20 20 70 63 61 63 68 65 52 65 6d 6f 76       pcacheRemov
5b80: 65 46 72 6f 6d 48 61 73 68 28 70 29 3b 0a 20 20  eFromHash(p);.  
5b90: 20 20 20 20 20 20 70 63 61 63 68 65 50 61 67 65        pcachePage
5ba0: 46 72 65 65 28 70 29 3b 0a 20 20 20 20 20 20 7d  Free(p);.      }
5bb0: 65 6c 73 65 7b 0a 20 20 20 20 20 20 20 20 70 63  else{.        pc
5bc0: 61 63 68 65 41 64 64 54 6f 4c 72 75 4c 69 73 74  acheAddToLruList
5bd0: 28 70 29 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20  (p);.      }.   
5be0: 20 20 20 70 63 61 63 68 65 45 78 69 74 4d 75 74     pcacheExitMut
5bf0: 65 78 28 29 3b 0a 20 20 20 20 7d 65 6c 73 65 7b  ex();.    }else{
5c00: 0a 20 20 20 20 20 20 2f 2a 20 4d 6f 76 65 20 74  .      /* Move t
5c10: 68 65 20 70 61 67 65 20 74 6f 20 74 68 65 20 68  he page to the h
5c20: 65 61 64 20 6f 66 20 74 68 65 20 63 61 63 68 65  ead of the cache
5c30: 73 20 64 69 72 74 79 20 6c 69 73 74 2e 20 2a 2f  s dirty list. */
5c40: 0a 20 20 20 20 20 20 70 63 61 63 68 65 52 65 6d  .      pcacheRem
5c50: 6f 76 65 46 72 6f 6d 4c 69 73 74 28 26 70 43 61  oveFromList(&pCa
5c60: 63 68 65 2d 3e 70 44 69 72 74 79 2c 20 70 29 3b  che->pDirty, p);
5c70: 0a 20 20 20 20 20 20 70 63 61 63 68 65 41 64 64  .      pcacheAdd
5c80: 54 6f 4c 69 73 74 28 26 70 43 61 63 68 65 2d 3e  ToList(&pCache->
5c90: 70 44 69 72 74 79 2c 20 70 29 3b 0a 20 20 20 20  pDirty, p);.    
5ca0: 7d 0a 20 20 7d 0a 7d 0a 0a 76 6f 69 64 20 73 71  }.  }.}..void sq
5cb0: 6c 69 74 65 33 50 63 61 63 68 65 52 65 66 28 50  lite3PcacheRef(P
5cc0: 67 48 64 72 20 2a 70 29 7b 0a 20 20 61 73 73 65  gHdr *p){.  asse
5cd0: 72 74 28 70 2d 3e 6e 52 65 66 3e 30 29 3b 0a 20  rt(p->nRef>0);. 
5ce0: 20 70 2d 3e 6e 52 65 66 2b 2b 3b 0a 7d 0a 0a 2f   p->nRef++;.}../
5cf0: 2a 0a 2a 2a 20 44 72 6f 70 20 61 20 70 61 67 65  *.** Drop a page
5d00: 20 66 72 6f 6d 20 74 68 65 20 63 61 63 68 65 2e   from the cache.
5d10: 20 54 68 65 72 65 20 6d 75 73 74 20 62 65 20 65   There must be e
5d20: 78 61 63 74 6c 79 20 6f 6e 65 20 72 65 66 65 72  xactly one refer
5d30: 65 6e 63 65 20 74 6f 20 74 68 65 0a 2a 2a 20 70  ence to the.** p
5d40: 61 67 65 2e 20 54 68 69 73 20 66 75 6e 63 74 69  age. This functi
5d50: 6f 6e 20 64 65 6c 65 74 65 73 20 74 68 61 74 20  on deletes that 
5d60: 72 65 66 65 72 65 6e 63 65 2c 20 73 6f 20 61 66  reference, so af
5d70: 74 65 72 20 69 74 20 72 65 74 75 72 6e 73 20 74  ter it returns t
5d80: 68 65 0a 2a 2a 20 70 61 67 65 20 70 6f 69 6e 74  he.** page point
5d90: 65 64 20 74 6f 20 62 79 20 70 20 69 73 20 69 6e  ed to by p is in
5da0: 76 61 6c 69 64 2e 0a 2a 2f 0a 76 6f 69 64 20 73  valid..*/.void s
5db0: 71 6c 69 74 65 33 50 63 61 63 68 65 44 72 6f 70  qlite3PcacheDrop
5dc0: 28 50 67 48 64 72 20 2a 70 29 7b 0a 20 20 50 43  (PgHdr *p){.  PC
5dd0: 61 63 68 65 20 2a 70 43 61 63 68 65 3b 0a 20 20  ache *pCache;.  
5de0: 61 73 73 65 72 74 28 20 70 2d 3e 6e 52 65 66 3d  assert( p->nRef=
5df0: 3d 31 20 29 3b 0a 20 20 61 73 73 65 72 74 28 20  =1 );.  assert( 
5e00: 30 3d 3d 28 70 2d 3e 66 6c 61 67 73 26 50 47 48  0==(p->flags&PGH
5e10: 44 52 5f 44 49 52 54 59 29 20 29 3b 0a 20 20 70  DR_DIRTY) );.  p
5e20: 43 61 63 68 65 20 3d 20 70 2d 3e 70 43 61 63 68  Cache = p->pCach
5e30: 65 3b 0a 20 20 70 43 61 63 68 65 2d 3e 6e 52 65  e;.  pCache->nRe
5e40: 66 2d 2d 3b 0a 20 20 70 43 61 63 68 65 2d 3e 6e  f--;.  pCache->n
5e50: 50 69 6e 6e 65 64 2d 2d 3b 0a 20 20 70 63 61 63  Pinned--;.  pcac
5e60: 68 65 45 6e 74 65 72 4d 75 74 65 78 28 29 3b 0a  heEnterMutex();.
5e70: 20 20 70 63 61 63 68 65 52 65 6d 6f 76 65 46 72    pcacheRemoveFr
5e80: 6f 6d 4c 69 73 74 28 26 70 43 61 63 68 65 2d 3e  omList(&pCache->
5e90: 70 43 6c 65 61 6e 2c 20 70 29 3b 0a 20 20 70 63  pClean, p);.  pc
5ea0: 61 63 68 65 52 65 6d 6f 76 65 46 72 6f 6d 48 61  acheRemoveFromHa
5eb0: 73 68 28 70 29 3b 0a 20 20 70 63 61 63 68 65 50  sh(p);.  pcacheP
5ec0: 61 67 65 46 72 65 65 28 70 29 3b 0a 20 20 70 63  ageFree(p);.  pc
5ed0: 61 63 68 65 45 78 69 74 4d 75 74 65 78 28 29 3b  acheExitMutex();
5ee0: 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 4d 61 6b 65 20 73  .}../*.** Make s
5ef0: 75 72 65 20 74 68 65 20 70 61 67 65 20 69 73 20  ure the page is 
5f00: 6d 61 72 6b 65 64 20 61 73 20 64 69 72 74 79 2e  marked as dirty.
5f10: 20 20 49 66 20 69 74 20 69 73 6e 27 74 20 64 69    If it isn't di
5f20: 72 74 79 20 61 6c 72 65 61 64 79 2c 0a 2a 2a 20  rty already,.** 
5f30: 6d 61 6b 65 20 69 74 20 73 6f 2e 0a 2a 2f 0a 76  make it so..*/.v
5f40: 6f 69 64 20 73 71 6c 69 74 65 33 50 63 61 63 68  oid sqlite3Pcach
5f50: 65 4d 61 6b 65 44 69 72 74 79 28 50 67 48 64 72  eMakeDirty(PgHdr
5f60: 20 2a 70 29 7b 0a 20 20 50 43 61 63 68 65 20 2a   *p){.  PCache *
5f70: 70 43 61 63 68 65 3b 0a 20 20 70 2d 3e 66 6c 61  pCache;.  p->fla
5f80: 67 73 20 26 3d 20 7e 50 47 48 44 52 5f 44 4f 4e  gs &= ~PGHDR_DON
5f90: 54 5f 57 52 49 54 45 3b 0a 20 20 69 66 28 20 70  T_WRITE;.  if( p
5fa0: 2d 3e 66 6c 61 67 73 20 26 20 50 47 48 44 52 5f  ->flags & PGHDR_
5fb0: 44 49 52 54 59 20 29 20 72 65 74 75 72 6e 3b 0a  DIRTY ) return;.
5fc0: 20 20 61 73 73 65 72 74 28 20 28 70 2d 3e 66 6c    assert( (p->fl
5fd0: 61 67 73 20 26 20 50 47 48 44 52 5f 44 49 52 54  ags & PGHDR_DIRT
5fe0: 59 29 3d 3d 30 20 29 3b 0a 20 20 61 73 73 65 72  Y)==0 );.  asser
5ff0: 74 28 20 70 2d 3e 6e 52 65 66 3e 30 20 29 3b 0a  t( p->nRef>0 );.
6000: 20 20 70 43 61 63 68 65 20 3d 20 70 2d 3e 70 43    pCache = p->pC
6010: 61 63 68 65 3b 0a 20 20 70 63 61 63 68 65 45 6e  ache;.  pcacheEn
6020: 74 65 72 4d 75 74 65 78 28 29 3b 0a 20 20 70 63  terMutex();.  pc
6030: 61 63 68 65 52 65 6d 6f 76 65 46 72 6f 6d 4c 69  acheRemoveFromLi
6040: 73 74 28 26 70 43 61 63 68 65 2d 3e 70 43 6c 65  st(&pCache->pCle
6050: 61 6e 2c 20 70 29 3b 0a 20 20 70 63 61 63 68 65  an, p);.  pcache
6060: 41 64 64 54 6f 4c 69 73 74 28 26 70 43 61 63 68  AddToList(&pCach
6070: 65 2d 3e 70 44 69 72 74 79 2c 20 70 29 3b 0a 20  e->pDirty, p);. 
6080: 20 70 63 61 63 68 65 45 78 69 74 4d 75 74 65 78   pcacheExitMutex
6090: 28 29 3b 0a 20 20 70 2d 3e 66 6c 61 67 73 20 7c  ();.  p->flags |
60a0: 3d 20 50 47 48 44 52 5f 44 49 52 54 59 3b 0a 7d  = PGHDR_DIRTY;.}
60b0: 0a 0a 73 74 61 74 69 63 20 76 6f 69 64 20 70 63  ..static void pc
60c0: 61 63 68 65 4d 61 6b 65 43 6c 65 61 6e 28 50 67  acheMakeClean(Pg
60d0: 48 64 72 20 2a 70 29 7b 0a 20 20 50 43 61 63 68  Hdr *p){.  PCach
60e0: 65 20 2a 70 43 61 63 68 65 20 3d 20 70 2d 3e 70  e *pCache = p->p
60f0: 43 61 63 68 65 3b 0a 20 20 61 73 73 65 72 74 28  Cache;.  assert(
6100: 20 70 2d 3e 61 70 53 61 76 65 5b 30 5d 3d 3d 30   p->apSave[0]==0
6110: 20 26 26 20 70 2d 3e 61 70 53 61 76 65 5b 31 5d   && p->apSave[1]
6120: 3d 3d 30 20 29 3b 0a 20 20 61 73 73 65 72 74 28  ==0 );.  assert(
6130: 20 70 2d 3e 66 6c 61 67 73 20 26 20 50 47 48 44   p->flags & PGHD
6140: 52 5f 44 49 52 54 59 20 29 3b 0a 20 20 70 63 61  R_DIRTY );.  pca
6150: 63 68 65 52 65 6d 6f 76 65 46 72 6f 6d 4c 69 73  cheRemoveFromLis
6160: 74 28 26 70 43 61 63 68 65 2d 3e 70 44 69 72 74  t(&pCache->pDirt
6170: 79 2c 20 70 29 3b 0a 20 20 70 63 61 63 68 65 41  y, p);.  pcacheA
6180: 64 64 54 6f 4c 69 73 74 28 26 70 43 61 63 68 65  ddToList(&pCache
6190: 2d 3e 70 43 6c 65 61 6e 2c 20 70 29 3b 0a 20 20  ->pClean, p);.  
61a0: 70 2d 3e 66 6c 61 67 73 20 26 3d 20 7e 50 47 48  p->flags &= ~PGH
61b0: 44 52 5f 44 49 52 54 59 3b 0a 20 20 69 66 28 20  DR_DIRTY;.  if( 
61c0: 70 2d 3e 6e 52 65 66 3d 3d 30 20 29 7b 0a 20 20  p->nRef==0 ){.  
61d0: 20 20 70 63 61 63 68 65 41 64 64 54 6f 4c 72 75    pcacheAddToLru
61e0: 4c 69 73 74 28 70 29 3b 0a 20 20 20 20 70 43 61  List(p);.    pCa
61f0: 63 68 65 2d 3e 6e 50 69 6e 6e 65 64 2d 2d 3b 0a  che->nPinned--;.
6200: 20 20 7d 0a 20 20 65 78 70 65 6e 73 69 76 65 5f    }.  expensive_
6210: 61 73 73 65 72 74 28 20 70 43 61 63 68 65 2d 3e  assert( pCache->
6220: 6e 50 69 6e 6e 65 64 3d 3d 70 63 61 63 68 65 50  nPinned==pcacheP
6230: 69 6e 6e 65 64 43 6f 75 6e 74 28 70 43 61 63 68  innedCount(pCach
6240: 65 29 20 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 4d  e) );.}../*.** M
6250: 61 6b 65 20 73 75 72 65 20 74 68 65 20 70 61 67  ake sure the pag
6260: 65 20 69 73 20 6d 61 72 6b 65 64 20 61 73 20 63  e is marked as c
6270: 6c 65 61 6e 2e 20 20 49 66 20 69 74 20 69 73 6e  lean.  If it isn
6280: 27 74 20 63 6c 65 61 6e 20 61 6c 72 65 61 64 79  't clean already
6290: 2c 0a 2a 2a 20 6d 61 6b 65 20 69 74 20 73 6f 2e  ,.** make it so.
62a0: 0a 2a 2f 0a 76 6f 69 64 20 73 71 6c 69 74 65 33  .*/.void sqlite3
62b0: 50 63 61 63 68 65 4d 61 6b 65 43 6c 65 61 6e 28  PcacheMakeClean(
62c0: 50 67 48 64 72 20 2a 70 29 7b 0a 20 20 69 66 28  PgHdr *p){.  if(
62d0: 20 28 70 2d 3e 66 6c 61 67 73 20 26 20 50 47 48   (p->flags & PGH
62e0: 44 52 5f 44 49 52 54 59 29 20 29 7b 0a 20 20 20  DR_DIRTY) ){.   
62f0: 20 70 63 61 63 68 65 45 6e 74 65 72 4d 75 74 65   pcacheEnterMute
6300: 78 28 29 3b 0a 20 20 20 20 70 63 61 63 68 65 4d  x();.    pcacheM
6310: 61 6b 65 43 6c 65 61 6e 28 70 29 3b 0a 20 20 20  akeClean(p);.   
6320: 20 70 63 61 63 68 65 45 78 69 74 4d 75 74 65 78   pcacheExitMutex
6330: 28 29 3b 0a 20 20 7d 0a 7d 0a 0a 2f 2a 0a 2a 2a  ();.  }.}../*.**
6340: 20 4d 61 6b 65 20 65 76 65 72 79 20 70 61 67 65   Make every page
6350: 20 69 6e 20 74 68 65 20 63 61 63 68 65 20 63 6c   in the cache cl
6360: 65 61 6e 2e 0a 2a 2f 0a 76 6f 69 64 20 73 71 6c  ean..*/.void sql
6370: 69 74 65 33 50 63 61 63 68 65 43 6c 65 61 6e 41  ite3PcacheCleanA
6380: 6c 6c 28 50 43 61 63 68 65 20 2a 70 43 61 63 68  ll(PCache *pCach
6390: 65 29 7b 0a 20 20 50 67 48 64 72 20 2a 70 3b 0a  e){.  PgHdr *p;.
63a0: 20 20 70 63 61 63 68 65 45 6e 74 65 72 4d 75 74    pcacheEnterMut
63b0: 65 78 28 29 3b 0a 20 20 77 68 69 6c 65 28 20 28  ex();.  while( (
63c0: 70 20 3d 20 70 43 61 63 68 65 2d 3e 70 44 69 72  p = pCache->pDir
63d0: 74 79 29 21 3d 30 20 29 7b 0a 20 20 20 20 61 73  ty)!=0 ){.    as
63e0: 73 65 72 74 28 20 70 2d 3e 61 70 53 61 76 65 5b  sert( p->apSave[
63f0: 30 5d 3d 3d 30 20 26 26 20 70 2d 3e 61 70 53 61  0]==0 && p->apSa
6400: 76 65 5b 31 5d 3d 3d 30 20 29 3b 0a 20 20 20 20  ve[1]==0 );.    
6410: 70 63 61 63 68 65 52 65 6d 6f 76 65 46 72 6f 6d  pcacheRemoveFrom
6420: 4c 69 73 74 28 26 70 43 61 63 68 65 2d 3e 70 44  List(&pCache->pD
6430: 69 72 74 79 2c 20 70 29 3b 0a 20 20 20 20 70 2d  irty, p);.    p-
6440: 3e 66 6c 61 67 73 20 26 3d 20 7e 50 47 48 44 52  >flags &= ~PGHDR
6450: 5f 44 49 52 54 59 3b 0a 20 20 20 20 70 63 61 63  _DIRTY;.    pcac
6460: 68 65 41 64 64 54 6f 4c 69 73 74 28 26 70 43 61  heAddToList(&pCa
6470: 63 68 65 2d 3e 70 43 6c 65 61 6e 2c 20 70 29 3b  che->pClean, p);
6480: 0a 20 20 20 20 69 66 28 20 70 2d 3e 6e 52 65 66  .    if( p->nRef
6490: 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 70 63 61  ==0 ){.      pca
64a0: 63 68 65 41 64 64 54 6f 4c 72 75 4c 69 73 74 28  cheAddToLruList(
64b0: 70 29 3b 0a 20 20 20 20 20 20 70 43 61 63 68 65  p);.      pCache
64c0: 2d 3e 6e 50 69 6e 6e 65 64 2d 2d 3b 0a 20 20 20  ->nPinned--;.   
64d0: 20 7d 0a 20 20 7d 0a 20 20 73 71 6c 69 74 65 33   }.  }.  sqlite3
64e0: 50 63 61 63 68 65 41 73 73 65 72 74 46 6c 61 67  PcacheAssertFlag
64f0: 73 28 70 43 61 63 68 65 2c 20 30 2c 20 50 47 48  s(pCache, 0, PGH
6500: 44 52 5f 44 49 52 54 59 29 3b 0a 20 20 65 78 70  DR_DIRTY);.  exp
6510: 65 6e 73 69 76 65 5f 61 73 73 65 72 74 28 20 70  ensive_assert( p
6520: 43 61 63 68 65 2d 3e 6e 50 69 6e 6e 65 64 3d 3d  Cache->nPinned==
6530: 70 63 61 63 68 65 50 69 6e 6e 65 64 43 6f 75 6e  pcachePinnedCoun
6540: 74 28 70 43 61 63 68 65 29 20 29 3b 0a 20 20 70  t(pCache) );.  p
6550: 63 61 63 68 65 45 78 69 74 4d 75 74 65 78 28 29  cacheExitMutex()
6560: 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 43 68 61 6e 67  ;.}../*.** Chang
6570: 65 20 74 68 65 20 70 61 67 65 20 6e 75 6d 62 65  e the page numbe
6580: 72 20 6f 66 20 70 61 67 65 20 70 20 74 6f 20 6e  r of page p to n
6590: 65 77 50 67 6e 6f 2e 20 49 66 20 6e 65 77 50 67  ewPgno. If newPg
65a0: 6e 6f 20 69 73 20 30 2c 20 74 68 65 6e 20 74 68  no is 0, then th
65b0: 65 0a 2a 2a 20 70 61 67 65 20 6f 62 6a 65 63 74  e.** page object
65c0: 20 69 73 20 61 64 64 65 64 20 74 6f 20 74 68 65   is added to the
65d0: 20 63 6c 65 61 6e 2d 6c 69 73 74 20 61 6e 64 20   clean-list and 
65e0: 74 68 65 20 50 47 48 44 52 5f 52 45 55 53 45 5f  the PGHDR_REUSE_
65f0: 55 4e 4c 49 4b 45 4c 59 20 0a 2a 2a 20 66 6c 61  UNLIKELY .** fla
6600: 67 20 73 65 74 2e 0a 2a 2f 0a 76 6f 69 64 20 73  g set..*/.void s
6610: 71 6c 69 74 65 33 50 63 61 63 68 65 4d 6f 76 65  qlite3PcacheMove
6620: 28 50 67 48 64 72 20 2a 70 2c 20 50 67 6e 6f 20  (PgHdr *p, Pgno 
6630: 6e 65 77 50 67 6e 6f 29 7b 0a 20 20 61 73 73 65  newPgno){.  asse
6640: 72 74 28 20 70 2d 3e 6e 52 65 66 3e 30 20 29 3b  rt( p->nRef>0 );
6650: 0a 20 20 70 63 61 63 68 65 45 6e 74 65 72 4d 75  .  pcacheEnterMu
6660: 74 65 78 28 29 3b 0a 20 20 70 63 61 63 68 65 52  tex();.  pcacheR
6670: 65 6d 6f 76 65 46 72 6f 6d 48 61 73 68 28 70 29  emoveFromHash(p)
6680: 3b 0a 20 20 70 2d 3e 70 67 6e 6f 20 3d 20 6e 65  ;.  p->pgno = ne
6690: 77 50 67 6e 6f 3b 0a 20 20 69 66 28 20 6e 65 77  wPgno;.  if( new
66a0: 50 67 6e 6f 3d 3d 30 20 29 7b 0a 20 20 20 20 70  Pgno==0 ){.    p
66b0: 63 61 63 68 65 46 72 65 65 28 70 2d 3e 61 70 53  cacheFree(p->apS
66c0: 61 76 65 5b 30 5d 29 3b 0a 20 20 20 20 70 63 61  ave[0]);.    pca
66d0: 63 68 65 46 72 65 65 28 70 2d 3e 61 70 53 61 76  cheFree(p->apSav
66e0: 65 5b 31 5d 29 3b 0a 20 20 20 20 70 2d 3e 61 70  e[1]);.    p->ap
66f0: 53 61 76 65 5b 30 5d 20 3d 20 30 3b 0a 20 20 20  Save[0] = 0;.   
6700: 20 70 2d 3e 61 70 53 61 76 65 5b 31 5d 20 3d 20   p->apSave[1] = 
6710: 30 3b 0a 20 20 20 20 69 66 28 20 28 70 2d 3e 66  0;.    if( (p->f
6720: 6c 61 67 73 20 26 20 50 47 48 44 52 5f 44 49 52  lags & PGHDR_DIR
6730: 54 59 29 20 29 7b 0a 20 20 20 20 20 20 70 63 61  TY) ){.      pca
6740: 63 68 65 4d 61 6b 65 43 6c 65 61 6e 28 70 29 3b  cheMakeClean(p);
6750: 0a 20 20 20 20 7d 0a 20 20 20 20 70 2d 3e 66 6c  .    }.    p->fl
6760: 61 67 73 20 3d 20 50 47 48 44 52 5f 52 45 55 53  ags = PGHDR_REUS
6770: 45 5f 55 4e 4c 49 4b 45 4c 59 3b 0a 20 20 7d 0a  E_UNLIKELY;.  }.
6780: 20 20 70 63 61 63 68 65 41 64 64 54 6f 48 61 73    pcacheAddToHas
6790: 68 28 70 29 3b 0a 20 20 70 63 61 63 68 65 45 78  h(p);.  pcacheEx
67a0: 69 74 4d 75 74 65 78 28 29 3b 0a 7d 0a 0a 2f 2a  itMutex();.}../*
67b0: 0a 2a 2a 20 52 65 6d 6f 76 65 20 61 6c 6c 20 63  .** Remove all c
67c0: 6f 6e 74 65 6e 74 20 66 72 6f 6d 20 61 20 70 61  ontent from a pa
67d0: 67 65 20 63 61 63 68 65 0a 2a 2f 0a 73 74 61 74  ge cache.*/.stat
67e0: 69 63 20 76 6f 69 64 20 70 63 61 63 68 65 43 6c  ic void pcacheCl
67f0: 65 61 72 28 50 43 61 63 68 65 20 2a 70 43 61 63  ear(PCache *pCac
6800: 68 65 29 7b 0a 20 20 50 67 48 64 72 20 2a 70 2c  he){.  PgHdr *p,
6810: 20 2a 70 4e 65 78 74 3b 0a 20 20 61 73 73 65 72   *pNext;.  asser
6820: 74 28 20 73 71 6c 69 74 65 33 5f 6d 75 74 65 78  t( sqlite3_mutex
6830: 5f 68 65 6c 64 28 70 63 61 63 68 65 5f 67 2e 6d  _held(pcache_g.m
6840: 75 74 65 78 29 20 29 3b 0a 20 20 66 6f 72 28 70  utex) );.  for(p
6850: 3d 70 43 61 63 68 65 2d 3e 70 43 6c 65 61 6e 3b  =pCache->pClean;
6860: 20 70 3b 20 70 3d 70 4e 65 78 74 29 7b 0a 20 20   p; p=pNext){.  
6870: 20 20 70 4e 65 78 74 20 3d 20 70 2d 3e 70 4e 65    pNext = p->pNe
6880: 78 74 3b 0a 20 20 20 20 70 63 61 63 68 65 52 65  xt;.    pcacheRe
6890: 6d 6f 76 65 46 72 6f 6d 4c 72 75 4c 69 73 74 28  moveFromLruList(
68a0: 70 29 3b 0a 20 20 20 20 70 63 61 63 68 65 50 61  p);.    pcachePa
68b0: 67 65 46 72 65 65 28 70 29 3b 0a 20 20 7d 0a 20  geFree(p);.  }. 
68c0: 20 66 6f 72 28 70 3d 70 43 61 63 68 65 2d 3e 70   for(p=pCache->p
68d0: 44 69 72 74 79 3b 20 70 3b 20 70 3d 70 4e 65 78  Dirty; p; p=pNex
68e0: 74 29 7b 0a 20 20 20 20 70 4e 65 78 74 20 3d 20  t){.    pNext = 
68f0: 70 2d 3e 70 4e 65 78 74 3b 0a 20 20 20 20 70 63  p->pNext;.    pc
6900: 61 63 68 65 50 61 67 65 46 72 65 65 28 70 29 3b  achePageFree(p);
6910: 0a 20 20 7d 0a 20 20 70 43 61 63 68 65 2d 3e 70  .  }.  pCache->p
6920: 43 6c 65 61 6e 20 3d 20 30 3b 0a 20 20 70 43 61  Clean = 0;.  pCa
6930: 63 68 65 2d 3e 70 44 69 72 74 79 20 3d 20 30 3b  che->pDirty = 0;
6940: 0a 20 20 70 43 61 63 68 65 2d 3e 70 44 69 72 74  .  pCache->pDirt
6950: 79 54 61 69 6c 20 3d 20 30 3b 0a 20 20 70 43 61  yTail = 0;.  pCa
6960: 63 68 65 2d 3e 6e 50 61 67 65 20 3d 20 30 3b 0a  che->nPage = 0;.
6970: 20 20 70 43 61 63 68 65 2d 3e 6e 50 69 6e 6e 65    pCache->nPinne
6980: 64 20 3d 20 30 3b 0a 20 20 6d 65 6d 73 65 74 28  d = 0;.  memset(
6990: 70 43 61 63 68 65 2d 3e 61 70 48 61 73 68 2c 20  pCache->apHash, 
69a0: 30 2c 20 70 43 61 63 68 65 2d 3e 6e 48 61 73 68  0, pCache->nHash
69b0: 2a 73 69 7a 65 6f 66 28 70 43 61 63 68 65 2d 3e  *sizeof(pCache->
69c0: 61 70 48 61 73 68 5b 30 5d 29 29 3b 0a 7d 0a 0a  apHash[0]));.}..
69d0: 0a 2f 2a 0a 2a 2a 20 44 72 6f 70 20 65 76 65 72  ./*.** Drop ever
69e0: 79 20 63 61 63 68 65 20 65 6e 74 72 79 20 77 68  y cache entry wh
69f0: 6f 73 65 20 70 61 67 65 20 6e 75 6d 62 65 72 20  ose page number 
6a00: 69 73 20 67 72 65 61 74 65 72 20 74 68 61 6e 20  is greater than 
6a10: 22 70 67 6e 6f 22 2e 0a 2a 2f 0a 76 6f 69 64 20  "pgno"..*/.void 
6a20: 73 71 6c 69 74 65 33 50 63 61 63 68 65 54 72 75  sqlite3PcacheTru
6a30: 6e 63 61 74 65 28 50 43 61 63 68 65 20 2a 70 43  ncate(PCache *pC
6a40: 61 63 68 65 2c 20 50 67 6e 6f 20 70 67 6e 6f 29  ache, Pgno pgno)
6a50: 7b 0a 20 20 50 67 48 64 72 20 2a 70 2c 20 2a 70  {.  PgHdr *p, *p
6a60: 4e 65 78 74 3b 0a 20 20 50 67 48 64 72 20 2a 70  Next;.  PgHdr *p
6a70: 44 69 72 74 79 20 3d 20 70 43 61 63 68 65 2d 3e  Dirty = pCache->
6a80: 70 44 69 72 74 79 3b 0a 20 20 70 63 61 63 68 65  pDirty;.  pcache
6a90: 45 6e 74 65 72 4d 75 74 65 78 28 29 3b 0a 20 20  EnterMutex();.  
6aa0: 66 6f 72 28 70 3d 70 43 61 63 68 65 2d 3e 70 43  for(p=pCache->pC
6ab0: 6c 65 61 6e 3b 20 70 7c 7c 70 44 69 72 74 79 3b  lean; p||pDirty;
6ac0: 20 70 3d 70 4e 65 78 74 29 7b 0a 20 20 20 20 69   p=pNext){.    i
6ad0: 66 28 20 21 70 20 29 7b 0a 20 20 20 20 20 20 70  f( !p ){.      p
6ae0: 20 3d 20 70 44 69 72 74 79 3b 0a 20 20 20 20 20   = pDirty;.     
6af0: 20 70 44 69 72 74 79 20 3d 20 30 3b 0a 20 20 20   pDirty = 0;.   
6b00: 20 7d 0a 20 20 20 20 70 4e 65 78 74 20 3d 20 70   }.    pNext = p
6b10: 2d 3e 70 4e 65 78 74 3b 0a 20 20 20 20 69 66 28  ->pNext;.    if(
6b20: 20 70 2d 3e 70 67 6e 6f 3e 70 67 6e 6f 20 29 7b   p->pgno>pgno ){
6b30: 0a 20 20 20 20 20 20 69 66 28 20 70 2d 3e 6e 52  .      if( p->nR
6b40: 65 66 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 20  ef==0 ){.       
6b50: 20 70 63 61 63 68 65 52 65 6d 6f 76 65 46 72 6f   pcacheRemoveFro
6b60: 6d 48 61 73 68 28 70 29 3b 0a 20 20 20 20 20 20  mHash(p);.      
6b70: 20 20 69 66 28 20 70 2d 3e 66 6c 61 67 73 26 50    if( p->flags&P
6b80: 47 48 44 52 5f 44 49 52 54 59 20 29 7b 0a 20 20  GHDR_DIRTY ){.  
6b90: 20 20 20 20 20 20 20 20 70 63 61 63 68 65 52 65          pcacheRe
6ba0: 6d 6f 76 65 46 72 6f 6d 4c 69 73 74 28 26 70 43  moveFromList(&pC
6bb0: 61 63 68 65 2d 3e 70 44 69 72 74 79 2c 20 70 29  ache->pDirty, p)
6bc0: 3b 0a 20 20 20 20 20 20 20 20 20 20 70 43 61 63  ;.          pCac
6bd0: 68 65 2d 3e 6e 50 69 6e 6e 65 64 2d 2d 3b 0a 20  he->nPinned--;. 
6be0: 20 20 20 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20         }else{.  
6bf0: 20 20 20 20 20 20 20 20 70 63 61 63 68 65 52 65          pcacheRe
6c00: 6d 6f 76 65 46 72 6f 6d 4c 69 73 74 28 26 70 43  moveFromList(&pC
6c10: 61 63 68 65 2d 3e 70 43 6c 65 61 6e 2c 20 70 29  ache->pClean, p)
6c20: 3b 0a 20 20 20 20 20 20 20 20 20 20 70 63 61 63  ;.          pcac
6c30: 68 65 52 65 6d 6f 76 65 46 72 6f 6d 4c 72 75 4c  heRemoveFromLruL
6c40: 69 73 74 28 70 29 3b 0a 20 20 20 20 20 20 20 20  ist(p);.        
6c50: 7d 0a 20 20 20 20 20 20 20 20 70 63 61 63 68 65  }.        pcache
6c60: 50 61 67 65 46 72 65 65 28 70 29 3b 0a 20 20 20  PageFree(p);.   
6c70: 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20     }else{.      
6c80: 20 20 2f 2a 20 49 66 20 74 68 65 72 65 20 61 72    /* If there ar
6c90: 65 20 72 65 66 65 72 65 6e 63 65 73 20 74 6f 20  e references to 
6ca0: 74 68 65 20 70 61 67 65 2c 20 69 74 20 63 61 6e  the page, it can
6cb0: 6e 6f 74 20 62 65 20 66 72 65 65 64 2e 20 49 6e  not be freed. In
6cc0: 20 74 68 69 73 0a 20 20 20 20 20 20 20 20 2a 2a   this.        **
6cd0: 20 63 61 73 65 2c 20 7a 65 72 6f 20 74 68 65 20   case, zero the 
6ce0: 70 61 67 65 20 63 6f 6e 74 65 6e 74 20 69 6e 73  page content ins
6cf0: 74 65 61 64 2e 0a 20 20 20 20 20 20 20 20 2a 2f  tead..        */
6d00: 0a 20 20 20 20 20 20 20 20 6d 65 6d 73 65 74 28  .        memset(
6d10: 70 2d 3e 70 44 61 74 61 2c 20 30 2c 20 70 43 61  p->pData, 0, pCa
6d20: 63 68 65 2d 3e 73 7a 50 61 67 65 29 3b 0a 20 20  che->szPage);.  
6d30: 20 20 20 20 7d 0a 20 20 20 20 7d 0a 20 20 7d 0a      }.    }.  }.
6d40: 20 20 70 63 61 63 68 65 45 78 69 74 4d 75 74 65    pcacheExitMute
6d50: 78 28 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 49 66  x();.}../*.** If
6d60: 20 74 68 65 72 65 20 61 72 65 20 63 75 72 72 65   there are curre
6d70: 6e 74 6c 79 20 6d 6f 72 65 20 74 68 61 6e 20 70  ntly more than p
6d80: 63 61 63 68 65 2e 6e 4d 61 78 50 61 67 65 20 70  cache.nMaxPage p
6d90: 61 67 65 73 20 61 6c 6c 6f 63 61 74 65 64 2c 20  ages allocated, 
6da0: 74 72 79 0a 2a 2a 20 74 6f 20 72 65 63 79 63 6c  try.** to recycl
6db0: 65 20 70 61 67 65 73 20 74 6f 20 72 65 64 75 63  e pages to reduc
6dc0: 65 20 74 68 65 20 6e 75 6d 62 65 72 20 61 6c 6c  e the number all
6dd0: 6f 63 61 74 65 64 20 74 6f 20 70 63 61 63 68 65  ocated to pcache
6de0: 2e 6e 4d 61 78 50 61 67 65 2e 0a 2a 2f 0a 73 74  .nMaxPage..*/.st
6df0: 61 74 69 63 20 76 6f 69 64 20 70 63 61 63 68 65  atic void pcache
6e00: 45 6e 66 6f 72 63 65 4d 61 78 50 61 67 65 28 76  EnforceMaxPage(v
6e10: 6f 69 64 29 7b 0a 20 20 50 67 48 64 72 20 2a 70  oid){.  PgHdr *p
6e20: 3b 0a 20 20 61 73 73 65 72 74 28 20 73 71 6c 69  ;.  assert( sqli
6e30: 74 65 33 5f 6d 75 74 65 78 5f 68 65 6c 64 28 70  te3_mutex_held(p
6e40: 63 61 63 68 65 5f 67 2e 6d 75 74 65 78 29 20 29  cache_g.mutex) )
6e50: 3b 0a 20 20 77 68 69 6c 65 28 20 70 63 61 63 68  ;.  while( pcach
6e60: 65 5f 67 2e 6e 43 75 72 72 65 6e 74 50 61 67 65  e_g.nCurrentPage
6e70: 3e 70 63 61 63 68 65 5f 67 2e 6e 4d 61 78 50 61  >pcache_g.nMaxPa
6e80: 67 65 20 26 26 20 28 70 20 3d 20 70 63 61 63 68  ge && (p = pcach
6e90: 65 52 65 63 79 63 6c 65 50 61 67 65 28 29 29 20  eRecyclePage()) 
6ea0: 29 7b 0a 20 20 20 20 70 63 61 63 68 65 50 61 67  ){.    pcachePag
6eb0: 65 46 72 65 65 28 70 29 3b 0a 20 20 7d 0a 7d 0a  eFree(p);.  }.}.
6ec0: 0a 2f 2a 0a 2a 2a 20 43 6c 6f 73 65 20 61 20 63  ./*.** Close a c
6ed0: 61 63 68 65 2e 0a 2a 2f 0a 76 6f 69 64 20 73 71  ache..*/.void sq
6ee0: 6c 69 74 65 33 50 63 61 63 68 65 43 6c 6f 73 65  lite3PcacheClose
6ef0: 28 50 43 61 63 68 65 20 2a 70 43 61 63 68 65 29  (PCache *pCache)
6f00: 7b 0a 20 20 70 63 61 63 68 65 45 6e 74 65 72 4d  {.  pcacheEnterM
6f10: 75 74 65 78 28 29 3b 0a 0a 20 20 2f 2a 20 46 72  utex();..  /* Fr
6f20: 65 65 20 61 6c 6c 20 74 68 65 20 70 61 67 65 73  ee all the pages
6f30: 20 75 73 65 64 20 62 79 20 74 68 69 73 20 70 61   used by this pa
6f40: 67 65 72 20 61 6e 64 20 72 65 6d 6f 76 65 20 74  ger and remove t
6f50: 68 65 6d 20 66 72 6f 6d 20 74 68 65 20 4c 52 55  hem from the LRU
6f60: 20 6c 69 73 74 2e 20 2a 2f 0a 20 20 70 63 61 63   list. */.  pcac
6f70: 68 65 43 6c 65 61 72 28 70 43 61 63 68 65 29 3b  heClear(pCache);
6f80: 0a 20 20 69 66 28 20 70 43 61 63 68 65 2d 3e 62  .  if( pCache->b
6f90: 50 75 72 67 65 61 62 6c 65 20 29 7b 0a 20 20 20  Purgeable ){.   
6fa0: 20 70 63 61 63 68 65 5f 67 2e 6e 4d 61 78 50 61   pcache_g.nMaxPa
6fb0: 67 65 20 2d 3d 20 70 43 61 63 68 65 2d 3e 6e 4d  ge -= pCache->nM
6fc0: 61 78 3b 0a 20 20 20 20 70 63 61 63 68 65 5f 67  ax;.    pcache_g
6fd0: 2e 6e 4d 69 6e 50 61 67 65 20 2d 3d 20 70 43 61  .nMinPage -= pCa
6fe0: 63 68 65 2d 3e 6e 4d 69 6e 3b 0a 20 20 20 20 70  che->nMin;.    p
6ff0: 63 61 63 68 65 45 6e 66 6f 72 63 65 4d 61 78 50  cacheEnforceMaxP
7000: 61 67 65 28 29 3b 0a 20 20 7d 0a 20 20 73 71 6c  age();.  }.  sql
7010: 69 74 65 33 5f 66 72 65 65 28 70 43 61 63 68 65  ite3_free(pCache
7020: 2d 3e 61 70 48 61 73 68 29 3b 0a 20 20 70 63 61  ->apHash);.  pca
7030: 63 68 65 45 78 69 74 4d 75 74 65 78 28 29 3b 0a  cheExitMutex();.
7040: 7d 0a 0a 2f 2a 0a 2a 2a 20 50 72 65 73 65 72 76  }../*.** Preserv
7050: 65 20 74 68 65 20 63 6f 6e 74 65 6e 74 20 6f 66  e the content of
7060: 20 74 68 65 20 70 61 67 65 2e 20 20 49 74 20 69   the page.  It i
7070: 73 20 61 73 73 75 6d 65 64 20 74 68 61 74 20 74  s assumed that t
7080: 68 65 20 63 6f 6e 74 65 6e 74 0a 2a 2a 20 68 61  he content.** ha
7090: 73 20 6e 6f 74 20 62 65 65 6e 20 70 72 65 73 65  s not been prese
70a0: 72 76 65 64 20 61 6c 72 65 61 64 79 2e 0a 2a 2a  rved already..**
70b0: 0a 2a 2a 20 49 66 20 69 64 4a 6f 75 72 6e 61 6c  .** If idJournal
70c0: 3d 3d 30 20 74 68 65 6e 20 74 68 69 73 20 69 73  ==0 then this is
70d0: 20 66 6f 72 20 74 68 65 20 6f 76 65 72 61 6c 6c   for the overall
70e0: 20 74 72 61 6e 73 61 63 74 69 6f 6e 2e 0a 2a 2a   transaction..**
70f0: 20 49 66 20 69 64 4a 6f 75 72 6e 61 6c 3d 3d 31   If idJournal==1
7100: 20 74 68 65 6e 20 74 68 69 73 20 69 73 20 66 6f   then this is fo
7110: 72 20 74 68 65 20 73 74 61 74 65 6d 65 6e 74 20  r the statement 
7120: 6a 6f 75 72 6e 61 6c 2e 0a 2a 2a 0a 2a 2a 20 54  journal..**.** T
7130: 68 69 73 20 72 6f 75 74 69 6e 65 20 69 73 20 75  his routine is u
7140: 73 65 64 20 66 6f 72 20 69 6e 2d 6d 65 6d 6f 72  sed for in-memor
7150: 79 20 64 61 74 61 62 61 73 65 73 20 6f 6e 6c 79  y databases only
7160: 2e 0a 2a 2a 0a 2a 2a 20 52 65 74 75 72 6e 20 53  ..**.** Return S
7170: 51 4c 49 54 45 5f 4f 4b 20 6f 72 20 53 51 4c 49  QLITE_OK or SQLI
7180: 54 45 5f 4e 4f 4d 45 4d 20 69 66 20 61 20 6d 65  TE_NOMEM if a me
7190: 6d 6f 72 79 20 61 6c 6c 6f 63 61 74 69 6f 6e 20  mory allocation 
71a0: 66 61 69 6c 73 2e 0a 2a 2f 0a 69 6e 74 20 73 71  fails..*/.int sq
71b0: 6c 69 74 65 33 50 63 61 63 68 65 50 72 65 73 65  lite3PcachePrese
71c0: 72 76 65 28 50 67 48 64 72 20 2a 70 2c 20 69 6e  rve(PgHdr *p, in
71d0: 74 20 69 64 4a 6f 75 72 6e 61 6c 29 7b 0a 20 20  t idJournal){.  
71e0: 76 6f 69 64 20 2a 78 3b 0a 20 20 69 6e 74 20 73  void *x;.  int s
71f0: 7a 3b 0a 20 20 61 73 73 65 72 74 28 20 70 2d 3e  z;.  assert( p->
7200: 70 43 61 63 68 65 2d 3e 62 50 75 72 67 65 61 62  pCache->bPurgeab
7210: 6c 65 3d 3d 30 20 29 3b 0a 20 20 61 73 73 65 72  le==0 );.  asser
7220: 74 28 20 70 2d 3e 61 70 53 61 76 65 5b 69 64 4a  t( p->apSave[idJ
7230: 6f 75 72 6e 61 6c 5d 3d 3d 30 20 29 3b 0a 20 20  ournal]==0 );.  
7240: 73 7a 20 3d 20 70 2d 3e 70 43 61 63 68 65 2d 3e  sz = p->pCache->
7250: 73 7a 50 61 67 65 3b 0a 20 20 70 2d 3e 61 70 53  szPage;.  p->apS
7260: 61 76 65 5b 69 64 4a 6f 75 72 6e 61 6c 5d 20 3d  ave[idJournal] =
7270: 20 78 20 3d 20 73 71 6c 69 74 65 33 50 61 67 65   x = sqlite3Page
7280: 4d 61 6c 6c 6f 63 28 20 73 7a 20 29 3b 0a 20 20  Malloc( sz );.  
7290: 69 66 28 20 78 3d 3d 30 20 29 20 72 65 74 75 72  if( x==0 ) retur
72a0: 6e 20 53 51 4c 49 54 45 5f 4e 4f 4d 45 4d 3b 0a  n SQLITE_NOMEM;.
72b0: 20 20 6d 65 6d 63 70 79 28 78 2c 20 70 2d 3e 70    memcpy(x, p->p
72c0: 44 61 74 61 2c 20 73 7a 29 3b 0a 20 20 72 65 74  Data, sz);.  ret
72d0: 75 72 6e 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 7d  urn SQLITE_OK;.}
72e0: 0a 0a 2f 2a 0a 2a 2a 20 43 6f 6d 6d 69 74 20 61  ../*.** Commit a
72f0: 20 63 68 61 6e 67 65 20 70 72 65 76 69 6f 75 73   change previous
7300: 6c 79 20 70 72 65 73 65 72 76 65 64 2e 0a 2a 2f  ly preserved..*/
7310: 0a 76 6f 69 64 20 73 71 6c 69 74 65 33 50 63 61  .void sqlite3Pca
7320: 63 68 65 43 6f 6d 6d 69 74 28 50 43 61 63 68 65  cheCommit(PCache
7330: 20 2a 70 43 61 63 68 65 2c 20 69 6e 74 20 69 64   *pCache, int id
7340: 4a 6f 75 72 6e 61 6c 29 7b 0a 20 20 50 67 48 64  Journal){.  PgHd
7350: 72 20 2a 70 3b 0a 20 20 69 6e 74 20 6d 61 73 6b  r *p;.  int mask
7360: 20 3d 20 69 64 4a 6f 75 72 6e 61 6c 3d 3d 30 20   = idJournal==0 
7370: 3f 20 7e 50 47 48 44 52 5f 49 4e 5f 4a 4f 55 52  ? ~PGHDR_IN_JOUR
7380: 4e 41 4c 20 3a 20 30 78 66 66 66 66 66 66 3b 0a  NAL : 0xffffff;.
7390: 20 20 70 63 61 63 68 65 45 6e 74 65 72 4d 75 74    pcacheEnterMut
73a0: 65 78 28 29 3b 20 20 20 20 20 2f 2a 20 4d 75 74  ex();     /* Mut
73b0: 65 78 20 69 73 20 72 65 71 75 69 72 65 64 20 74  ex is required t
73c0: 6f 20 63 61 6c 6c 20 70 63 61 63 68 65 46 72 65  o call pcacheFre
73d0: 65 28 29 20 2a 2f 0a 20 20 66 6f 72 28 70 3d 70  e() */.  for(p=p
73e0: 43 61 63 68 65 2d 3e 70 44 69 72 74 79 3b 20 70  Cache->pDirty; p
73f0: 3b 20 70 3d 70 2d 3e 70 4e 65 78 74 29 7b 0a 20  ; p=p->pNext){. 
7400: 20 20 20 69 66 28 20 70 2d 3e 61 70 53 61 76 65     if( p->apSave
7410: 5b 69 64 4a 6f 75 72 6e 61 6c 5d 20 29 7b 0a 20  [idJournal] ){. 
7420: 20 20 20 20 20 70 63 61 63 68 65 46 72 65 65 28       pcacheFree(
7430: 70 2d 3e 61 70 53 61 76 65 5b 69 64 4a 6f 75 72  p->apSave[idJour
7440: 6e 61 6c 5d 29 3b 0a 20 20 20 20 20 20 70 2d 3e  nal]);.      p->
7450: 61 70 53 61 76 65 5b 69 64 4a 6f 75 72 6e 61 6c  apSave[idJournal
7460: 5d 20 3d 20 30 3b 0a 20 20 20 20 7d 0a 20 20 20  ] = 0;.    }.   
7470: 20 70 2d 3e 66 6c 61 67 73 20 26 3d 20 6d 61 73   p->flags &= mas
7480: 6b 3b 0a 20 20 7d 0a 20 20 70 63 61 63 68 65 45  k;.  }.  pcacheE
7490: 78 69 74 4d 75 74 65 78 28 29 3b 0a 7d 0a 0a 2f  xitMutex();.}../
74a0: 2a 0a 2a 2a 20 52 6f 6c 6c 62 61 63 6b 20 61 20  *.** Rollback a 
74b0: 63 68 61 6e 67 65 20 70 72 65 76 69 6f 75 73 6c  change previousl
74c0: 79 20 70 72 65 73 65 72 76 65 64 2e 0a 2a 2f 0a  y preserved..*/.
74d0: 76 6f 69 64 20 73 71 6c 69 74 65 33 50 63 61 63  void sqlite3Pcac
74e0: 68 65 52 6f 6c 6c 62 61 63 6b 28 0a 20 20 50 43  heRollback(.  PC
74f0: 61 63 68 65 20 2a 70 43 61 63 68 65 2c 20 20 20  ache *pCache,   
7500: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
7510: 2a 20 50 61 67 65 72 20 63 61 63 68 65 20 2a 2f  * Pager cache */
7520: 0a 20 20 69 6e 74 20 69 64 4a 6f 75 72 6e 61 6c  .  int idJournal
7530: 2c 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,               
7540: 20 20 20 20 2f 2a 20 57 68 69 63 68 20 63 6f 70      /* Which cop
7550: 79 20 74 6f 20 72 6f 6c 6c 62 61 63 6b 20 74 6f  y to rollback to
7560: 20 2a 2f 0a 20 20 76 6f 69 64 20 28 2a 78 52 65   */.  void (*xRe
7570: 69 6e 69 74 65 72 29 28 50 67 48 64 72 2a 29 20  initer)(PgHdr*) 
7580: 20 20 20 20 20 20 20 2f 2a 20 43 61 6c 6c 65 64         /* Called
7590: 20 6f 6e 20 65 61 63 68 20 72 6f 6c 6c 65 64 20   on each rolled 
75a0: 62 61 63 6b 20 70 61 67 65 20 2a 2f 0a 29 7b 0a  back page */.){.
75b0: 20 20 50 67 48 64 72 20 2a 70 3b 0a 20 20 69 6e    PgHdr *p;.  in
75c0: 74 20 73 7a 3b 0a 20 20 69 6e 74 20 6d 61 73 6b  t sz;.  int mask
75d0: 20 3d 20 69 64 4a 6f 75 72 6e 61 6c 3d 3d 30 20   = idJournal==0 
75e0: 3f 20 7e 50 47 48 44 52 5f 49 4e 5f 4a 4f 55 52  ? ~PGHDR_IN_JOUR
75f0: 4e 41 4c 20 3a 20 30 78 66 66 66 66 66 66 3b 0a  NAL : 0xffffff;.
7600: 20 20 70 63 61 63 68 65 45 6e 74 65 72 4d 75 74    pcacheEnterMut
7610: 65 78 28 29 3b 20 20 20 20 20 2f 2a 20 4d 75 74  ex();     /* Mut
7620: 65 78 20 69 73 20 72 65 71 75 69 72 65 64 20 74  ex is required t
7630: 6f 20 63 61 6c 6c 20 70 63 61 63 68 65 46 72 65  o call pcacheFre
7640: 65 28 29 20 2a 2f 0a 20 20 73 7a 20 3d 20 70 43  e() */.  sz = pC
7650: 61 63 68 65 2d 3e 73 7a 50 61 67 65 3b 0a 20 20  ache->szPage;.  
7660: 66 6f 72 28 70 3d 70 43 61 63 68 65 2d 3e 70 44  for(p=pCache->pD
7670: 69 72 74 79 3b 20 70 3b 20 70 3d 70 2d 3e 70 4e  irty; p; p=p->pN
7680: 65 78 74 29 7b 0a 20 20 20 20 69 66 28 20 70 2d  ext){.    if( p-
7690: 3e 61 70 53 61 76 65 5b 69 64 4a 6f 75 72 6e 61  >apSave[idJourna
76a0: 6c 5d 20 29 7b 0a 20 20 20 20 20 20 6d 65 6d 63  l] ){.      memc
76b0: 70 79 28 70 2d 3e 70 44 61 74 61 2c 20 70 2d 3e  py(p->pData, p->
76c0: 61 70 53 61 76 65 5b 69 64 4a 6f 75 72 6e 61 6c  apSave[idJournal
76d0: 5d 2c 20 73 7a 29 3b 0a 20 20 20 20 20 20 70 63  ], sz);.      pc
76e0: 61 63 68 65 46 72 65 65 28 70 2d 3e 61 70 53 61  acheFree(p->apSa
76f0: 76 65 5b 69 64 4a 6f 75 72 6e 61 6c 5d 29 3b 0a  ve[idJournal]);.
7700: 20 20 20 20 20 20 70 2d 3e 61 70 53 61 76 65 5b        p->apSave[
7710: 69 64 4a 6f 75 72 6e 61 6c 5d 20 3d 20 30 3b 0a  idJournal] = 0;.
7720: 20 20 20 20 20 20 69 66 28 20 78 52 65 69 6e 69        if( xReini
7730: 74 65 72 20 29 7b 0a 20 20 20 20 20 20 20 20 78  ter ){.        x
7740: 52 65 69 6e 69 74 65 72 28 70 29 3b 0a 20 20 20  Reiniter(p);.   
7750: 20 20 20 7d 0a 20 20 20 20 7d 0a 20 20 20 20 70     }.    }.    p
7760: 2d 3e 66 6c 61 67 73 20 26 3d 20 6d 61 73 6b 3b  ->flags &= mask;
7770: 0a 20 20 7d 0a 20 20 70 63 61 63 68 65 45 78 69  .  }.  pcacheExi
7780: 74 4d 75 74 65 78 28 29 3b 0a 7d 0a 0a 23 69 66  tMutex();.}..#if
7790: 6e 64 65 66 20 4e 44 45 42 55 47 0a 2f 2a 20 0a  ndef NDEBUG./* .
77a0: 2a 2a 20 41 73 73 65 72 74 20 66 6c 61 67 73 20  ** Assert flags 
77b0: 73 65 74 74 69 6e 67 73 20 6f 6e 20 61 6c 6c 20  settings on all 
77c0: 70 61 67 65 73 2e 20 20 44 65 62 75 67 67 69 6e  pages.  Debuggin
77d0: 67 20 6f 6e 6c 79 2e 0a 2a 2f 0a 76 6f 69 64 20  g only..*/.void 
77e0: 73 71 6c 69 74 65 33 50 63 61 63 68 65 41 73 73  sqlite3PcacheAss
77f0: 65 72 74 46 6c 61 67 73 28 50 43 61 63 68 65 20  ertFlags(PCache 
7800: 2a 70 43 61 63 68 65 2c 20 69 6e 74 20 74 72 75  *pCache, int tru
7810: 65 4d 61 73 6b 2c 20 69 6e 74 20 66 61 6c 73 65  eMask, int false
7820: 4d 61 73 6b 29 7b 0a 20 20 50 67 48 64 72 20 2a  Mask){.  PgHdr *
7830: 70 3b 0a 20 20 66 6f 72 28 70 3d 70 43 61 63 68  p;.  for(p=pCach
7840: 65 2d 3e 70 44 69 72 74 79 3b 20 70 3b 20 70 3d  e->pDirty; p; p=
7850: 70 2d 3e 70 4e 65 78 74 29 7b 0a 20 20 20 20 61  p->pNext){.    a
7860: 73 73 65 72 74 28 20 28 70 2d 3e 66 6c 61 67 73  ssert( (p->flags
7870: 26 74 72 75 65 4d 61 73 6b 29 3d 3d 74 72 75 65  &trueMask)==true
7880: 4d 61 73 6b 20 29 3b 0a 20 20 20 20 61 73 73 65  Mask );.    asse
7890: 72 74 28 20 28 70 2d 3e 66 6c 61 67 73 26 66 61  rt( (p->flags&fa
78a0: 6c 73 65 4d 61 73 6b 29 3d 3d 30 20 29 3b 0a 20  lseMask)==0 );. 
78b0: 20 7d 0a 20 20 66 6f 72 28 70 3d 70 43 61 63 68   }.  for(p=pCach
78c0: 65 2d 3e 70 43 6c 65 61 6e 3b 20 70 3b 20 70 3d  e->pClean; p; p=
78d0: 70 2d 3e 70 4e 65 78 74 29 7b 0a 20 20 20 20 61  p->pNext){.    a
78e0: 73 73 65 72 74 28 20 28 70 2d 3e 66 6c 61 67 73  ssert( (p->flags
78f0: 26 74 72 75 65 4d 61 73 6b 29 3d 3d 74 72 75 65  &trueMask)==true
7900: 4d 61 73 6b 20 29 3b 0a 20 20 20 20 61 73 73 65  Mask );.    asse
7910: 72 74 28 20 28 70 2d 3e 66 6c 61 67 73 26 66 61  rt( (p->flags&fa
7920: 6c 73 65 4d 61 73 6b 29 3d 3d 30 20 29 3b 0a 20  lseMask)==0 );. 
7930: 20 7d 0a 7d 0a 23 65 6e 64 69 66 0a 0a 2f 2a 20   }.}.#endif../* 
7940: 0a 2a 2a 20 44 69 73 63 61 72 64 20 74 68 65 20  .** Discard the 
7950: 63 6f 6e 74 65 6e 74 73 20 6f 66 20 74 68 65 20  contents of the 
7960: 63 61 63 68 65 2e 0a 2a 2f 0a 69 6e 74 20 73 71  cache..*/.int sq
7970: 6c 69 74 65 33 50 63 61 63 68 65 43 6c 65 61 72  lite3PcacheClear
7980: 28 50 43 61 63 68 65 20 2a 70 43 61 63 68 65 29  (PCache *pCache)
7990: 7b 0a 20 20 61 73 73 65 72 74 28 70 43 61 63 68  {.  assert(pCach
79a0: 65 2d 3e 6e 52 65 66 3d 3d 30 29 3b 0a 20 20 70  e->nRef==0);.  p
79b0: 63 61 63 68 65 45 6e 74 65 72 4d 75 74 65 78 28  cacheEnterMutex(
79c0: 29 3b 0a 20 20 70 63 61 63 68 65 43 6c 65 61 72  );.  pcacheClear
79d0: 28 70 43 61 63 68 65 29 3b 0a 20 20 70 63 61 63  (pCache);.  pcac
79e0: 68 65 45 78 69 74 4d 75 74 65 78 28 29 3b 0a 20  heExitMutex();. 
79f0: 20 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4f   return SQLITE_O
7a00: 4b 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 4d 65 72 67  K;.}../*.** Merg
7a10: 65 20 74 77 6f 20 6c 69 73 74 73 20 6f 66 20 70  e two lists of p
7a20: 61 67 65 73 20 63 6f 6e 6e 65 63 74 65 64 20 62  ages connected b
7a30: 79 20 70 44 69 72 74 79 20 61 6e 64 20 69 6e 20  y pDirty and in 
7a40: 70 67 6e 6f 20 6f 72 64 65 72 2e 0a 2a 2a 20 44  pgno order..** D
7a50: 6f 20 6e 6f 74 20 62 6f 74 68 20 66 69 78 69 6e  o not both fixin
7a60: 67 20 74 68 65 20 70 50 72 65 76 44 69 72 74 79  g the pPrevDirty
7a70: 20 70 6f 69 6e 74 65 72 73 2e 0a 2a 2f 0a 73 74   pointers..*/.st
7a80: 61 74 69 63 20 50 67 48 64 72 20 2a 70 63 61 63  atic PgHdr *pcac
7a90: 68 65 4d 65 72 67 65 44 69 72 74 79 4c 69 73 74  heMergeDirtyList
7aa0: 28 50 67 48 64 72 20 2a 70 41 2c 20 50 67 48 64  (PgHdr *pA, PgHd
7ab0: 72 20 2a 70 42 29 7b 0a 20 20 50 67 48 64 72 20  r *pB){.  PgHdr 
7ac0: 72 65 73 75 6c 74 2c 20 2a 70 54 61 69 6c 3b 0a  result, *pTail;.
7ad0: 20 20 70 54 61 69 6c 20 3d 20 26 72 65 73 75 6c    pTail = &resul
7ae0: 74 3b 0a 20 20 77 68 69 6c 65 28 20 70 41 20 26  t;.  while( pA &
7af0: 26 20 70 42 20 29 7b 0a 20 20 20 20 69 66 28 20  & pB ){.    if( 
7b00: 70 41 2d 3e 70 67 6e 6f 3c 70 42 2d 3e 70 67 6e  pA->pgno<pB->pgn
7b10: 6f 20 29 7b 0a 20 20 20 20 20 20 70 54 61 69 6c  o ){.      pTail
7b20: 2d 3e 70 44 69 72 74 79 20 3d 20 70 41 3b 0a 20  ->pDirty = pA;. 
7b30: 20 20 20 20 20 70 54 61 69 6c 20 3d 20 70 41 3b       pTail = pA;
7b40: 0a 20 20 20 20 20 20 70 41 20 3d 20 70 41 2d 3e  .      pA = pA->
7b50: 70 44 69 72 74 79 3b 0a 20 20 20 20 7d 65 6c 73  pDirty;.    }els
7b60: 65 7b 0a 20 20 20 20 20 20 70 54 61 69 6c 2d 3e  e{.      pTail->
7b70: 70 44 69 72 74 79 20 3d 20 70 42 3b 0a 20 20 20  pDirty = pB;.   
7b80: 20 20 20 70 54 61 69 6c 20 3d 20 70 42 3b 0a 20     pTail = pB;. 
7b90: 20 20 20 20 20 70 42 20 3d 20 70 42 2d 3e 70 44       pB = pB->pD
7ba0: 69 72 74 79 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a  irty;.    }.  }.
7bb0: 20 20 69 66 28 20 70 41 20 29 7b 0a 20 20 20 20    if( pA ){.    
7bc0: 70 54 61 69 6c 2d 3e 70 44 69 72 74 79 20 3d 20  pTail->pDirty = 
7bd0: 70 41 3b 0a 20 20 7d 65 6c 73 65 20 69 66 28 20  pA;.  }else if( 
7be0: 70 42 20 29 7b 0a 20 20 20 20 70 54 61 69 6c 2d  pB ){.    pTail-
7bf0: 3e 70 44 69 72 74 79 20 3d 20 70 42 3b 0a 20 20  >pDirty = pB;.  
7c00: 7d 65 6c 73 65 7b 0a 20 20 20 20 70 54 61 69 6c  }else{.    pTail
7c10: 2d 3e 70 44 69 72 74 79 20 3d 20 30 3b 0a 20 20  ->pDirty = 0;.  
7c20: 7d 0a 20 20 72 65 74 75 72 6e 20 72 65 73 75 6c  }.  return resul
7c30: 74 2e 70 44 69 72 74 79 3b 0a 7d 0a 0a 2f 2a 0a  t.pDirty;.}../*.
7c40: 2a 2a 20 53 6f 72 74 20 74 68 65 20 6c 69 73 74  ** Sort the list
7c50: 20 6f 66 20 70 61 67 65 73 20 69 6e 20 61 63 63   of pages in acc
7c60: 65 6e 64 69 6e 67 20 6f 72 64 65 72 20 62 79 20  ending order by 
7c70: 70 67 6e 6f 2e 20 20 50 61 67 65 73 20 61 72 65  pgno.  Pages are
7c80: 0a 2a 2a 20 63 6f 6e 6e 65 63 74 65 64 20 62 79  .** connected by
7c90: 20 70 44 69 72 74 79 20 70 6f 69 6e 74 65 72 73   pDirty pointers
7ca0: 2e 20 20 54 68 65 20 70 50 72 65 76 44 69 72 74  .  The pPrevDirt
7cb0: 79 20 70 6f 69 6e 74 65 72 73 20 61 72 65 0a 2a  y pointers are.*
7cc0: 2a 20 63 6f 72 72 75 70 74 65 64 20 62 79 20 74  * corrupted by t
7cd0: 68 69 73 20 73 6f 72 74 2e 0a 2a 2f 0a 23 64 65  his sort..*/.#de
7ce0: 66 69 6e 65 20 4e 5f 53 4f 52 54 5f 42 55 43 4b  fine N_SORT_BUCK
7cf0: 45 54 5f 41 4c 4c 4f 43 20 32 35 0a 23 64 65 66  ET_ALLOC 25.#def
7d00: 69 6e 65 20 4e 5f 53 4f 52 54 5f 42 55 43 4b 45  ine N_SORT_BUCKE
7d10: 54 20 20 20 20 20 20 20 32 35 0a 23 69 66 64 65  T       25.#ifde
7d20: 66 20 53 51 4c 49 54 45 5f 54 45 53 54 0a 20 20  f SQLITE_TEST.  
7d30: 69 6e 74 20 73 71 6c 69 74 65 33 5f 70 61 67 65  int sqlite3_page
7d40: 72 5f 6e 5f 73 6f 72 74 5f 62 75 63 6b 65 74 20  r_n_sort_bucket 
7d50: 3d 20 30 3b 0a 20 20 23 75 6e 64 65 66 20 4e 5f  = 0;.  #undef N_
7d60: 53 4f 52 54 5f 42 55 43 4b 45 54 0a 20 20 23 64  SORT_BUCKET.  #d
7d70: 65 66 69 6e 65 20 4e 5f 53 4f 52 54 5f 42 55 43  efine N_SORT_BUC
7d80: 4b 45 54 20 5c 0a 20 20 20 28 73 71 6c 69 74 65  KET \.   (sqlite
7d90: 33 5f 70 61 67 65 72 5f 6e 5f 73 6f 72 74 5f 62  3_pager_n_sort_b
7da0: 75 63 6b 65 74 3f 73 71 6c 69 74 65 33 5f 70 61  ucket?sqlite3_pa
7db0: 67 65 72 5f 6e 5f 73 6f 72 74 5f 62 75 63 6b 65  ger_n_sort_bucke
7dc0: 74 3a 4e 5f 53 4f 52 54 5f 42 55 43 4b 45 54 5f  t:N_SORT_BUCKET_
7dd0: 41 4c 4c 4f 43 29 0a 23 65 6e 64 69 66 0a 73 74  ALLOC).#endif.st
7de0: 61 74 69 63 20 50 67 48 64 72 20 2a 70 63 61 63  atic PgHdr *pcac
7df0: 68 65 53 6f 72 74 44 69 72 74 79 4c 69 73 74 28  heSortDirtyList(
7e00: 50 67 48 64 72 20 2a 70 49 6e 29 7b 0a 20 20 50  PgHdr *pIn){.  P
7e10: 67 48 64 72 20 2a 61 5b 4e 5f 53 4f 52 54 5f 42  gHdr *a[N_SORT_B
7e20: 55 43 4b 45 54 5f 41 4c 4c 4f 43 5d 2c 20 2a 70  UCKET_ALLOC], *p
7e30: 3b 0a 20 20 69 6e 74 20 69 3b 0a 20 20 6d 65 6d  ;.  int i;.  mem
7e40: 73 65 74 28 61 2c 20 30 2c 20 73 69 7a 65 6f 66  set(a, 0, sizeof
7e50: 28 61 29 29 3b 0a 20 20 77 68 69 6c 65 28 20 70  (a));.  while( p
7e60: 49 6e 20 29 7b 0a 20 20 20 20 70 20 3d 20 70 49  In ){.    p = pI
7e70: 6e 3b 0a 20 20 20 20 70 49 6e 20 3d 20 70 2d 3e  n;.    pIn = p->
7e80: 70 44 69 72 74 79 3b 0a 20 20 20 20 70 2d 3e 70  pDirty;.    p->p
7e90: 44 69 72 74 79 20 3d 20 30 3b 0a 20 20 20 20 66  Dirty = 0;.    f
7ea0: 6f 72 28 69 3d 30 3b 20 69 3c 4e 5f 53 4f 52 54  or(i=0; i<N_SORT
7eb0: 5f 42 55 43 4b 45 54 2d 31 3b 20 69 2b 2b 29 7b  _BUCKET-1; i++){
7ec0: 0a 20 20 20 20 20 20 69 66 28 20 61 5b 69 5d 3d  .      if( a[i]=
7ed0: 3d 30 20 29 7b 0a 20 20 20 20 20 20 20 20 61 5b  =0 ){.        a[
7ee0: 69 5d 20 3d 20 70 3b 0a 20 20 20 20 20 20 20 20  i] = p;.        
7ef0: 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 7d 65 6c  break;.      }el
7f00: 73 65 7b 0a 20 20 20 20 20 20 20 20 70 20 3d 20  se{.        p = 
7f10: 70 63 61 63 68 65 4d 65 72 67 65 44 69 72 74 79  pcacheMergeDirty
7f20: 4c 69 73 74 28 61 5b 69 5d 2c 20 70 29 3b 0a 20  List(a[i], p);. 
7f30: 20 20 20 20 20 20 20 61 5b 69 5d 20 3d 20 30 3b         a[i] = 0;
7f40: 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a 20  .      }.    }. 
7f50: 20 20 20 69 66 28 20 69 3d 3d 4e 5f 53 4f 52 54     if( i==N_SORT
7f60: 5f 42 55 43 4b 45 54 2d 31 20 29 7b 0a 20 20 20  _BUCKET-1 ){.   
7f70: 20 20 20 2f 2a 20 43 6f 76 65 72 61 67 65 3a 20     /* Coverage: 
7f80: 54 6f 20 67 65 74 20 68 65 72 65 2c 20 74 68 65  To get here, the
7f90: 72 65 20 6e 65 65 64 20 74 6f 20 62 65 20 32 5e  re need to be 2^
7fa0: 28 4e 5f 53 4f 52 54 5f 42 55 43 4b 45 54 29 20  (N_SORT_BUCKET) 
7fb0: 0a 20 20 20 20 20 20 2a 2a 20 65 6c 65 6d 65 6e  .      ** elemen
7fc0: 74 73 20 69 6e 20 74 68 65 20 69 6e 70 75 74 20  ts in the input 
7fd0: 6c 69 73 74 2e 20 54 68 69 73 20 69 73 20 70 6f  list. This is po
7fe0: 73 73 69 62 6c 65 2c 20 62 75 74 20 69 6d 70 72  ssible, but impr
7ff0: 61 63 74 69 63 61 6c 2e 0a 20 20 20 20 20 20 2a  actical..      *
8000: 2a 20 54 65 73 74 69 6e 67 20 74 68 69 73 20 6c  * Testing this l
8010: 69 6e 65 20 69 73 20 74 68 65 20 70 6f 69 6e 74  ine is the point
8020: 20 6f 66 20 67 6c 6f 62 61 6c 20 76 61 72 69 61   of global varia
8030: 62 6c 65 0a 20 20 20 20 20 20 2a 2a 20 73 71 6c  ble.      ** sql
8040: 69 74 65 33 5f 70 61 67 65 72 5f 6e 5f 73 6f 72  ite3_pager_n_sor
8050: 74 5f 62 75 63 6b 65 74 2e 0a 20 20 20 20 20 20  t_bucket..      
8060: 2a 2f 0a 20 20 20 20 20 20 61 5b 69 5d 20 3d 20  */.      a[i] = 
8070: 70 63 61 63 68 65 4d 65 72 67 65 44 69 72 74 79  pcacheMergeDirty
8080: 4c 69 73 74 28 61 5b 69 5d 2c 20 70 29 3b 0a 20  List(a[i], p);. 
8090: 20 20 20 7d 0a 20 20 7d 0a 20 20 70 20 3d 20 61     }.  }.  p = a
80a0: 5b 30 5d 3b 0a 20 20 66 6f 72 28 69 3d 31 3b 20  [0];.  for(i=1; 
80b0: 69 3c 4e 5f 53 4f 52 54 5f 42 55 43 4b 45 54 3b  i<N_SORT_BUCKET;
80c0: 20 69 2b 2b 29 7b 0a 20 20 20 20 70 20 3d 20 70   i++){.    p = p
80d0: 63 61 63 68 65 4d 65 72 67 65 44 69 72 74 79 4c  cacheMergeDirtyL
80e0: 69 73 74 28 70 2c 20 61 5b 69 5d 29 3b 0a 20 20  ist(p, a[i]);.  
80f0: 7d 0a 20 20 72 65 74 75 72 6e 20 70 3b 0a 7d 0a  }.  return p;.}.
8100: 0a 2f 2a 0a 2a 2a 20 52 65 74 75 72 6e 20 61 20  ./*.** Return a 
8110: 6c 69 73 74 20 6f 66 20 61 6c 6c 20 64 69 72 74  list of all dirt
8120: 79 20 70 61 67 65 73 20 69 6e 20 74 68 65 20 63  y pages in the c
8130: 61 63 68 65 2c 20 73 6f 72 74 65 64 20 62 79 20  ache, sorted by 
8140: 70 61 67 65 20 6e 75 6d 62 65 72 2e 0a 2a 2f 0a  page number..*/.
8150: 50 67 48 64 72 20 2a 73 71 6c 69 74 65 33 50 63  PgHdr *sqlite3Pc
8160: 61 63 68 65 44 69 72 74 79 4c 69 73 74 28 50 43  acheDirtyList(PC
8170: 61 63 68 65 20 2a 70 43 61 63 68 65 29 7b 0a 20  ache *pCache){. 
8180: 20 50 67 48 64 72 20 2a 70 3b 0a 20 20 66 6f 72   PgHdr *p;.  for
8190: 28 70 3d 70 43 61 63 68 65 2d 3e 70 44 69 72 74  (p=pCache->pDirt
81a0: 79 3b 20 70 3b 20 70 3d 70 2d 3e 70 4e 65 78 74  y; p; p=p->pNext
81b0: 29 7b 0a 20 20 20 20 70 2d 3e 70 44 69 72 74 79  ){.    p->pDirty
81c0: 20 3d 20 70 2d 3e 70 4e 65 78 74 3b 0a 20 20 7d   = p->pNext;.  }
81d0: 0a 20 20 72 65 74 75 72 6e 20 70 63 61 63 68 65  .  return pcache
81e0: 53 6f 72 74 44 69 72 74 79 4c 69 73 74 28 70 43  SortDirtyList(pC
81f0: 61 63 68 65 2d 3e 70 44 69 72 74 79 29 3b 0a 7d  ache->pDirty);.}
8200: 0a 0a 2f 2a 20 0a 2a 2a 20 52 65 74 75 72 6e 20  ../* .** Return 
8210: 74 68 65 20 74 6f 74 61 6c 20 6e 75 6d 62 65 72  the total number
8220: 20 6f 66 20 6f 75 74 73 74 61 6e 64 69 6e 67 20   of outstanding 
8230: 70 61 67 65 20 72 65 66 65 72 65 6e 63 65 73 2e  page references.
8240: 0a 2a 2f 0a 69 6e 74 20 73 71 6c 69 74 65 33 50  .*/.int sqlite3P
8250: 63 61 63 68 65 52 65 66 43 6f 75 6e 74 28 50 43  cacheRefCount(PC
8260: 61 63 68 65 20 2a 70 43 61 63 68 65 29 7b 0a 20  ache *pCache){. 
8270: 20 72 65 74 75 72 6e 20 70 43 61 63 68 65 2d 3e   return pCache->
8280: 6e 52 65 66 3b 0a 7d 0a 0a 2f 2a 20 0a 2a 2a 20  nRef;.}../* .** 
8290: 52 65 74 75 72 6e 20 74 68 65 20 74 6f 74 61 6c  Return the total
82a0: 20 6e 75 6d 62 65 72 20 6f 66 20 70 61 67 65 73   number of pages
82b0: 20 69 6e 20 74 68 65 20 63 61 63 68 65 2e 0a 2a   in the cache..*
82c0: 2f 0a 69 6e 74 20 73 71 6c 69 74 65 33 50 63 61  /.int sqlite3Pca
82d0: 63 68 65 50 61 67 65 63 6f 75 6e 74 28 50 43 61  chePagecount(PCa
82e0: 63 68 65 20 2a 70 43 61 63 68 65 29 7b 0a 20 20  che *pCache){.  
82f0: 61 73 73 65 72 74 28 20 70 43 61 63 68 65 2d 3e  assert( pCache->
8300: 6e 50 61 67 65 3e 3d 30 20 29 3b 0a 20 20 72 65  nPage>=0 );.  re
8310: 74 75 72 6e 20 70 43 61 63 68 65 2d 3e 6e 50 61  turn pCache->nPa
8320: 67 65 3b 0a 7d 0a 0a 23 69 66 64 65 66 20 53 51  ge;.}..#ifdef SQ
8330: 4c 49 54 45 5f 43 48 45 43 4b 5f 50 41 47 45 53  LITE_CHECK_PAGES
8340: 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20 66 75 6e 63  ./*.** This func
8350: 74 69 6f 6e 20 69 73 20 75 73 65 64 20 62 79 20  tion is used by 
8360: 74 68 65 20 70 61 67 65 72 2e 63 20 6d 6f 64 75  the pager.c modu
8370: 6c 65 20 74 6f 20 69 74 65 72 61 74 65 20 74 68  le to iterate th
8380: 72 6f 75 67 68 20 61 6c 6c 20 0a 2a 2a 20 70 61  rough all .** pa
8390: 67 65 73 20 69 6e 20 74 68 65 20 63 61 63 68 65  ges in the cache
83a0: 2e 20 41 74 20 70 72 65 73 65 6e 74 2c 20 74 68  . At present, th
83b0: 69 73 20 69 73 20 6f 6e 6c 79 20 72 65 71 75 69  is is only requi
83c0: 72 65 64 20 69 66 20 74 68 65 0a 2a 2a 20 53 51  red if the.** SQ
83d0: 4c 49 54 45 5f 43 48 45 43 4b 5f 50 41 47 45 53  LITE_CHECK_PAGES
83e0: 20 6d 61 63 72 6f 20 28 75 73 65 64 20 66 6f 72   macro (used for
83f0: 20 64 65 62 75 67 67 69 6e 67 29 20 69 73 20 73   debugging) is s
8400: 70 65 63 69 66 69 65 64 2e 0a 2a 2f 0a 76 6f 69  pecified..*/.voi
8410: 64 20 73 71 6c 69 74 65 33 50 63 61 63 68 65 49  d sqlite3PcacheI
8420: 74 65 72 61 74 65 28 50 43 61 63 68 65 20 2a 70  terate(PCache *p
8430: 43 61 63 68 65 2c 20 76 6f 69 64 20 28 2a 78 49  Cache, void (*xI
8440: 74 65 72 29 28 50 67 48 64 72 20 2a 29 29 7b 0a  ter)(PgHdr *)){.
8450: 20 20 50 67 48 64 72 20 2a 70 3b 0a 20 20 66 6f    PgHdr *p;.  fo
8460: 72 28 70 3d 70 43 61 63 68 65 2d 3e 70 43 6c 65  r(p=pCache->pCle
8470: 61 6e 3b 20 70 3b 20 70 3d 70 2d 3e 70 4e 65 78  an; p; p=p->pNex
8480: 74 29 7b 0a 20 20 20 20 78 49 74 65 72 28 70 29  t){.    xIter(p)
8490: 3b 0a 20 20 7d 0a 20 20 66 6f 72 28 70 3d 70 43  ;.  }.  for(p=pC
84a0: 61 63 68 65 2d 3e 70 44 69 72 74 79 3b 20 70 3b  ache->pDirty; p;
84b0: 20 70 3d 70 2d 3e 70 4e 65 78 74 29 7b 0a 20 20   p=p->pNext){.  
84c0: 20 20 78 49 74 65 72 28 70 29 3b 0a 20 20 7d 0a    xIter(p);.  }.
84d0: 7d 0a 23 65 6e 64 69 66 0a 0a 2f 2a 20 0a 2a 2a  }.#endif../* .**
84e0: 20 53 65 74 20 66 6c 61 67 73 20 6f 6e 20 61 6c   Set flags on al
84f0: 6c 20 70 61 67 65 73 20 69 6e 20 74 68 65 20 70  l pages in the p
8500: 61 67 65 20 63 61 63 68 65 20 0a 2a 2f 0a 76 6f  age cache .*/.vo
8510: 69 64 20 73 71 6c 69 74 65 33 50 63 61 63 68 65  id sqlite3Pcache
8520: 43 6c 65 61 72 46 6c 61 67 73 28 50 43 61 63 68  ClearFlags(PCach
8530: 65 20 2a 70 43 61 63 68 65 2c 20 69 6e 74 20 6d  e *pCache, int m
8540: 61 73 6b 29 7b 0a 20 20 50 67 48 64 72 20 2a 70  ask){.  PgHdr *p
8550: 3b 0a 0a 20 20 2f 2a 20 4f 62 74 61 69 6e 20 74  ;..  /* Obtain t
8560: 68 65 20 67 6c 6f 62 61 6c 20 6d 75 74 65 78 20  he global mutex 
8570: 62 65 66 6f 72 65 20 6d 6f 64 69 66 79 69 6e 67  before modifying
8580: 20 61 6e 79 20 50 67 48 64 72 2e 66 6c 61 67 73   any PgHdr.flags
8590: 20 76 61 72 69 61 62 6c 65 73 20 0a 20 20 2a 2a   variables .  **
85a0: 20 6f 72 20 74 72 61 76 65 72 73 69 6e 67 20 74   or traversing t
85b0: 68 65 20 4c 52 55 20 6c 69 73 74 2e 0a 20 20 2a  he LRU list..  *
85c0: 2f 20 0a 20 20 70 63 61 63 68 65 45 6e 74 65 72  / .  pcacheEnter
85d0: 4d 75 74 65 78 28 29 3b 0a 0a 20 20 6d 61 73 6b  Mutex();..  mask
85e0: 20 3d 20 7e 6d 61 73 6b 3b 0a 20 20 66 6f 72 28   = ~mask;.  for(
85f0: 70 3d 70 43 61 63 68 65 2d 3e 70 44 69 72 74 79  p=pCache->pDirty
8600: 3b 20 70 3b 20 70 3d 70 2d 3e 70 4e 65 78 74 29  ; p; p=p->pNext)
8610: 7b 0a 20 20 20 20 70 2d 3e 66 6c 61 67 73 20 26  {.    p->flags &
8620: 3d 20 6d 61 73 6b 3b 0a 20 20 7d 0a 20 20 66 6f  = mask;.  }.  fo
8630: 72 28 70 3d 70 43 61 63 68 65 2d 3e 70 43 6c 65  r(p=pCache->pCle
8640: 61 6e 3b 20 70 3b 20 70 3d 70 2d 3e 70 4e 65 78  an; p; p=p->pNex
8650: 74 29 7b 0a 20 20 20 20 70 2d 3e 66 6c 61 67 73  t){.    p->flags
8660: 20 26 3d 20 6d 61 73 6b 3b 0a 20 20 7d 0a 0a 20   &= mask;.  }.. 
8670: 20 69 66 28 20 30 3d 3d 28 6d 61 73 6b 26 50 47   if( 0==(mask&PG
8680: 48 44 52 5f 4e 45 45 44 5f 53 59 4e 43 29 20 29  HDR_NEED_SYNC) )
8690: 7b 0a 20 20 20 20 70 43 61 63 68 65 2d 3e 70 53  {.    pCache->pS
86a0: 79 6e 63 65 64 20 3d 20 70 43 61 63 68 65 2d 3e  ynced = pCache->
86b0: 70 44 69 72 74 79 54 61 69 6c 3b 0a 20 20 20 20  pDirtyTail;.    
86c0: 61 73 73 65 72 74 28 20 21 70 43 61 63 68 65 2d  assert( !pCache-
86d0: 3e 70 53 79 6e 63 65 64 20 7c 7c 20 28 70 43 61  >pSynced || (pCa
86e0: 63 68 65 2d 3e 70 53 79 6e 63 65 64 2d 3e 66 6c  che->pSynced->fl
86f0: 61 67 73 26 50 47 48 44 52 5f 4e 45 45 44 5f 53  ags&PGHDR_NEED_S
8700: 59 4e 43 29 3d 3d 30 20 29 3b 0a 20 20 7d 0a 0a  YNC)==0 );.  }..
8710: 20 20 70 63 61 63 68 65 45 78 69 74 4d 75 74 65    pcacheExitMute
8720: 78 28 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 53 65  x();.}../*.** Se
8730: 74 20 74 68 65 20 73 75 67 67 65 73 74 65 64 20  t the suggested 
8740: 63 61 63 68 65 2d 73 69 7a 65 20 76 61 6c 75 65  cache-size value
8750: 2e 0a 2a 2f 0a 69 6e 74 20 73 71 6c 69 74 65 33  ..*/.int sqlite3
8760: 50 63 61 63 68 65 47 65 74 43 61 63 68 65 73 69  PcacheGetCachesi
8770: 7a 65 28 50 43 61 63 68 65 20 2a 70 43 61 63 68  ze(PCache *pCach
8780: 65 29 7b 0a 20 20 72 65 74 75 72 6e 20 70 43 61  e){.  return pCa
8790: 63 68 65 2d 3e 6e 4d 61 78 3b 0a 7d 0a 0a 2f 2a  che->nMax;.}../*
87a0: 0a 2a 2a 20 53 65 74 20 74 68 65 20 73 75 67 67  .** Set the sugg
87b0: 65 73 74 65 64 20 63 61 63 68 65 2d 73 69 7a 65  ested cache-size
87c0: 20 76 61 6c 75 65 2e 0a 2a 2f 0a 76 6f 69 64 20   value..*/.void 
87d0: 73 71 6c 69 74 65 33 50 63 61 63 68 65 53 65 74  sqlite3PcacheSet
87e0: 43 61 63 68 65 73 69 7a 65 28 50 43 61 63 68 65  Cachesize(PCache
87f0: 20 2a 70 43 61 63 68 65 2c 20 69 6e 74 20 6d 78   *pCache, int mx
8800: 50 61 67 65 29 7b 0a 20 20 69 66 28 20 6d 78 50  Page){.  if( mxP
8810: 61 67 65 3c 31 30 20 29 7b 0a 20 20 20 20 6d 78  age<10 ){.    mx
8820: 50 61 67 65 20 3d 20 31 30 3b 0a 20 20 7d 0a 20  Page = 10;.  }. 
8830: 20 69 66 28 20 70 43 61 63 68 65 2d 3e 62 50 75   if( pCache->bPu
8840: 72 67 65 61 62 6c 65 20 29 7b 0a 20 20 20 20 70  rgeable ){.    p
8850: 63 61 63 68 65 45 6e 74 65 72 4d 75 74 65 78 28  cacheEnterMutex(
8860: 29 3b 0a 20 20 20 20 70 63 61 63 68 65 5f 67 2e  );.    pcache_g.
8870: 6e 4d 61 78 50 61 67 65 20 2d 3d 20 70 43 61 63  nMaxPage -= pCac
8880: 68 65 2d 3e 6e 4d 61 78 3b 0a 20 20 20 20 70 63  he->nMax;.    pc
8890: 61 63 68 65 5f 67 2e 6e 4d 61 78 50 61 67 65 20  ache_g.nMaxPage 
88a0: 2b 3d 20 6d 78 50 61 67 65 3b 0a 20 20 20 20 70  += mxPage;.    p
88b0: 63 61 63 68 65 45 6e 66 6f 72 63 65 4d 61 78 50  cacheEnforceMaxP
88c0: 61 67 65 28 29 3b 0a 20 20 20 20 70 63 61 63 68  age();.    pcach
88d0: 65 45 78 69 74 4d 75 74 65 78 28 29 3b 0a 20 20  eExitMutex();.  
88e0: 7d 0a 20 20 70 43 61 63 68 65 2d 3e 6e 4d 61 78  }.  pCache->nMax
88f0: 20 3d 20 6d 78 50 61 67 65 3b 0a 7d 0a 0a 23 69   = mxPage;.}..#i
8900: 66 64 65 66 20 53 51 4c 49 54 45 5f 45 4e 41 42  fdef SQLITE_ENAB
8910: 4c 45 5f 4d 45 4d 4f 52 59 5f 4d 41 4e 41 47 45  LE_MEMORY_MANAGE
8920: 4d 45 4e 54 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20  MENT./*.** This 
8930: 66 75 6e 63 74 69 6f 6e 20 69 73 20 63 61 6c 6c  function is call
8940: 65 64 20 74 6f 20 66 72 65 65 20 73 75 70 65 72  ed to free super
8950: 66 6c 75 6f 75 73 20 64 79 6e 61 6d 69 63 61 6c  fluous dynamical
8960: 6c 79 20 61 6c 6c 6f 63 61 74 65 64 20 6d 65 6d  ly allocated mem
8970: 6f 72 79 0a 2a 2a 20 68 65 6c 64 20 62 79 20 74  ory.** held by t
8980: 68 65 20 70 61 67 65 72 20 73 79 73 74 65 6d 2e  he pager system.
8990: 20 4d 65 6d 6f 72 79 20 69 6e 20 75 73 65 20 62   Memory in use b
89a0: 79 20 61 6e 79 20 53 51 4c 69 74 65 20 70 61 67  y any SQLite pag
89b0: 65 72 20 61 6c 6c 6f 63 61 74 65 64 0a 2a 2a 20  er allocated.** 
89c0: 62 79 20 74 68 65 20 63 75 72 72 65 6e 74 20 74  by the current t
89d0: 68 72 65 61 64 20 6d 61 79 20 62 65 20 73 71 6c  hread may be sql
89e0: 69 74 65 33 5f 66 72 65 65 28 29 65 64 2e 0a 2a  ite3_free()ed..*
89f0: 2a 0a 2a 2a 20 6e 52 65 71 20 69 73 20 74 68 65  *.** nReq is the
8a00: 20 6e 75 6d 62 65 72 20 6f 66 20 62 79 74 65 73   number of bytes
8a10: 20 6f 66 20 6d 65 6d 6f 72 79 20 72 65 71 75 69   of memory requi
8a20: 72 65 64 2e 20 4f 6e 63 65 20 74 68 69 73 20 6d  red. Once this m
8a30: 75 63 68 20 68 61 73 0a 2a 2a 20 62 65 65 6e 20  uch has.** been 
8a40: 72 65 6c 65 61 73 65 64 2c 20 74 68 65 20 66 75  released, the fu
8a50: 6e 63 74 69 6f 6e 20 72 65 74 75 72 6e 73 2e 20  nction returns. 
8a60: 54 68 65 20 72 65 74 75 72 6e 20 76 61 6c 75 65  The return value
8a70: 20 69 73 20 74 68 65 20 74 6f 74 61 6c 20 6e 75   is the total nu
8a80: 6d 62 65 72 20 0a 2a 2a 20 6f 66 20 62 79 74 65  mber .** of byte
8a90: 73 20 6f 66 20 6d 65 6d 6f 72 79 20 72 65 6c 65  s of memory rele
8aa0: 61 73 65 64 2e 0a 2a 2f 0a 69 6e 74 20 73 71 6c  ased..*/.int sql
8ab0: 69 74 65 33 50 63 61 63 68 65 52 65 6c 65 61 73  ite3PcacheReleas
8ac0: 65 4d 65 6d 6f 72 79 28 69 6e 74 20 6e 52 65 71  eMemory(int nReq
8ad0: 29 7b 0a 20 20 69 6e 74 20 6e 46 72 65 65 20 3d  ){.  int nFree =
8ae0: 20 30 3b 0a 20 20 69 66 28 20 70 63 61 63 68 65   0;.  if( pcache
8af0: 5f 67 2e 70 53 74 61 72 74 3d 3d 30 20 29 7b 0a  _g.pStart==0 ){.
8b00: 20 20 20 20 50 67 48 64 72 20 2a 70 3b 0a 20 20      PgHdr *p;.  
8b10: 20 20 70 63 61 63 68 65 45 6e 74 65 72 4d 75 74    pcacheEnterMut
8b20: 65 78 28 29 3b 0a 20 20 20 20 77 68 69 6c 65 28  ex();.    while(
8b30: 20 28 6e 52 65 71 3c 30 20 7c 7c 20 6e 46 72 65   (nReq<0 || nFre
8b40: 65 3c 6e 52 65 71 29 20 26 26 20 28 70 3d 70 63  e<nReq) && (p=pc
8b50: 61 63 68 65 52 65 63 79 63 6c 65 50 61 67 65 28  acheRecyclePage(
8b60: 29 29 20 29 7b 0a 20 20 20 20 20 20 6e 46 72 65  )) ){.      nFre
8b70: 65 20 2b 3d 20 70 63 61 63 68 65 50 61 67 65 53  e += pcachePageS
8b80: 69 7a 65 28 70 29 3b 0a 20 20 20 20 20 20 70 63  ize(p);.      pc
8b90: 61 63 68 65 50 61 67 65 46 72 65 65 28 70 29 3b  achePageFree(p);
8ba0: 0a 20 20 20 20 7d 0a 20 20 20 20 70 63 61 63 68  .    }.    pcach
8bb0: 65 45 78 69 74 4d 75 74 65 78 28 29 3b 0a 20 20  eExitMutex();.  
8bc0: 7d 0a 20 20 72 65 74 75 72 6e 20 6e 46 72 65 65  }.  return nFree
8bd0: 3b 0a 7d 0a 23 65 6e 64 69 66 20 2f 2a 20 53 51  ;.}.#endif /* SQ
8be0: 4c 49 54 45 5f 45 4e 41 42 4c 45 5f 4d 45 4d 4f  LITE_ENABLE_MEMO
8bf0: 52 59 5f 4d 41 4e 41 47 45 4d 45 4e 54 20 2a 2f  RY_MANAGEMENT */
8c00: 0a 0a 23 69 66 64 65 66 20 53 51 4c 49 54 45 5f  ..#ifdef SQLITE_
8c10: 54 45 53 54 0a 76 6f 69 64 20 73 71 6c 69 74 65  TEST.void sqlite
8c20: 33 50 63 61 63 68 65 53 74 61 74 73 28 0a 20 20  3PcacheStats(.  
8c30: 69 6e 74 20 2a 70 6e 43 75 72 72 65 6e 74 2c 0a  int *pnCurrent,.
8c40: 20 20 69 6e 74 20 2a 70 6e 4d 61 78 2c 0a 20 20    int *pnMax,.  
8c50: 69 6e 74 20 2a 70 6e 4d 69 6e 2c 0a 20 20 69 6e  int *pnMin,.  in
8c60: 74 20 2a 70 6e 52 65 63 79 63 6c 61 62 6c 65 0a  t *pnRecyclable.
8c70: 29 7b 0a 20 20 50 67 48 64 72 20 2a 70 3b 0a 20  ){.  PgHdr *p;. 
8c80: 20 69 6e 74 20 6e 52 65 63 79 63 6c 61 62 6c 65   int nRecyclable
8c90: 20 3d 20 30 3b 0a 20 20 66 6f 72 28 70 3d 70 63   = 0;.  for(p=pc
8ca0: 61 63 68 65 5f 67 2e 70 4c 72 75 48 65 61 64 3b  ache_g.pLruHead;
8cb0: 20 70 3b 20 70 3d 70 2d 3e 70 4e 65 78 74 4c 72   p; p=p->pNextLr
8cc0: 75 29 7b 0a 20 20 20 20 6e 52 65 63 79 63 6c 61  u){.    nRecycla
8cd0: 62 6c 65 2b 2b 3b 0a 20 20 7d 0a 0a 20 20 2a 70  ble++;.  }..  *p
8ce0: 6e 43 75 72 72 65 6e 74 20 3d 20 70 63 61 63 68  nCurrent = pcach
8cf0: 65 5f 67 2e 6e 43 75 72 72 65 6e 74 50 61 67 65  e_g.nCurrentPage
8d00: 3b 0a 20 20 2a 70 6e 4d 61 78 20 3d 20 70 63 61  ;.  *pnMax = pca
8d10: 63 68 65 5f 67 2e 6e 4d 61 78 50 61 67 65 3b 0a  che_g.nMaxPage;.
8d20: 20 20 2a 70 6e 4d 69 6e 20 3d 20 70 63 61 63 68    *pnMin = pcach
8d30: 65 5f 67 2e 6e 4d 69 6e 50 61 67 65 3b 0a 20 20  e_g.nMinPage;.  
8d40: 2a 70 6e 52 65 63 79 63 6c 61 62 6c 65 20 3d 20  *pnRecyclable = 
8d50: 6e 52 65 63 79 63 6c 61 62 6c 65 3b 0a 7d 0a 23  nRecyclable;.}.#
8d60: 65 6e 64 69 66 0a                                endif.