/ Hex Artifact Content
Login

Artifact 006714ad89db3c488526246e6ed6b130e457f01b:


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 31 35 20 32 30 30  che.c,v 1.15 200
01c0: 38 2f 30 38 2f 32 36 20 31 39 3a 30 38 3a 30 30  8/08/26 19:08:00
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 2f 0a 73   structure..*/.s
0240: 74 72 75 63 74 20 50 43 61 63 68 65 20 7b 0a 20  truct PCache {. 
0250: 20 69 6e 74 20 73 7a 50 61 67 65 3b 20 20 20 20   int szPage;    
0260: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0270: 20 20 20 20 20 2f 2a 20 53 69 7a 65 20 6f 66 20       /* Size of 
0280: 65 76 65 72 79 20 70 61 67 65 20 69 6e 20 74 68  every page in th
0290: 69 73 20 63 61 63 68 65 20 2a 2f 0a 20 20 69 6e  is cache */.  in
02a0: 74 20 73 7a 45 78 74 72 61 3b 20 20 20 20 20 20  t szExtra;      
02b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
02c0: 20 20 2f 2a 20 53 69 7a 65 20 6f 66 20 65 78 74    /* Size of ext
02d0: 72 61 20 73 70 61 63 65 20 66 6f 72 20 65 61 63  ra space for eac
02e0: 68 20 70 61 67 65 20 2a 2f 0a 20 20 69 6e 74 20  h page */.  int 
02f0: 6e 48 61 73 68 3b 20 20 20 20 20 20 20 20 20 20  nHash;          
0300: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0310: 2f 2a 20 4e 75 6d 62 65 72 20 6f 66 20 73 6c 6f  /* Number of slo
0320: 74 73 20 69 6e 20 61 70 48 61 73 68 5b 5d 20 2a  ts in apHash[] *
0330: 2f 0a 20 20 69 6e 74 20 6e 50 61 67 65 3b 20 20  /.  int nPage;  
0340: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0350: 20 20 20 20 20 20 20 20 2f 2a 20 54 6f 74 61 6c          /* Total
0360: 20 6e 75 6d 62 65 72 20 6f 66 20 70 61 67 65 73   number of pages
0370: 20 69 6e 20 61 70 48 61 73 68 20 2a 2f 0a 20 20   in apHash */.  
0380: 69 6e 74 20 6e 4d 61 78 3b 20 20 20 20 20 20 20  int nMax;       
0390: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
03a0: 20 20 20 20 2f 2a 20 43 6f 6e 66 69 67 75 72 65      /* Configure
03b0: 64 20 63 61 63 68 65 20 73 69 7a 65 20 2a 2f 0a  d cache size */.
03c0: 20 20 69 6e 74 20 6e 4d 69 6e 3b 20 20 20 20 20    int nMin;     
03d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
03e0: 20 20 20 20 20 20 2f 2a 20 43 6f 6e 66 69 67 75        /* Configu
03f0: 72 65 64 20 6d 69 6e 69 6d 75 6d 20 63 61 63 68  red minimum cach
0400: 65 20 73 69 7a 65 20 2a 2f 0a 20 20 50 67 48 64  e size */.  PgHd
0410: 72 20 2a 2a 61 70 48 61 73 68 3b 20 20 20 20 20  r **apHash;     
0420: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0430: 2f 2a 20 48 61 73 68 20 74 61 62 6c 65 20 66 6f  /* Hash table fo
0440: 72 20 66 61 73 74 20 6c 6f 6f 6b 75 70 20 62 79  r fast lookup by
0450: 20 70 67 6e 6f 20 2a 2f 0a 20 20 69 6e 74 20 62   pgno */.  int b
0460: 50 75 72 67 65 61 62 6c 65 3b 20 20 20 20 20 20  Purgeable;      
0470: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
0480: 2a 20 54 72 75 65 20 69 66 20 70 61 67 65 73 20  * True if pages 
0490: 61 72 65 20 6f 6e 20 62 61 63 6b 69 6e 67 20 73  are on backing s
04a0: 74 6f 72 65 20 2a 2f 0a 20 20 76 6f 69 64 20 28  tore */.  void (
04b0: 2a 78 44 65 73 74 72 6f 79 29 28 50 67 48 64 72  *xDestroy)(PgHdr
04c0: 2a 29 3b 20 20 20 20 20 20 20 20 20 20 20 2f 2a  *);           /*
04d0: 20 43 61 6c 6c 65 64 20 77 68 65 6e 20 72 65 66   Called when ref
04e0: 63 6e 74 20 67 6f 65 73 20 31 2d 3e 30 20 2a 2f  cnt goes 1->0 */
04f0: 0a 20 20 69 6e 74 20 28 2a 78 53 74 72 65 73 73  .  int (*xStress
0500: 29 28 76 6f 69 64 2a 2c 50 67 48 64 72 2a 29 3b  )(void*,PgHdr*);
0510: 20 20 20 20 20 20 20 2f 2a 20 43 61 6c 6c 20 74         /* Call t
0520: 6f 20 74 72 79 20 6d 61 6b 65 20 61 20 70 61 67  o try make a pag
0530: 65 20 63 6c 65 61 6e 20 2a 2f 0a 20 20 76 6f 69  e clean */.  voi
0540: 64 20 2a 70 53 74 72 65 73 73 3b 20 20 20 20 20  d *pStress;     
0550: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0560: 20 2f 2a 20 41 72 67 75 6d 65 6e 74 20 74 6f 20   /* Argument to 
0570: 78 53 74 72 65 73 73 20 2a 2f 0a 20 20 50 67 48  xStress */.  PgH
0580: 64 72 20 2a 70 43 6c 65 61 6e 3b 20 20 20 20 20  dr *pClean;     
0590: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
05a0: 20 2f 2a 20 4c 69 73 74 20 6f 66 20 63 6c 65 61   /* List of clea
05b0: 6e 20 70 61 67 65 73 20 69 6e 20 75 73 65 20 2a  n pages in use *
05c0: 2f 0a 20 20 50 67 48 64 72 20 2a 70 44 69 72 74  /.  PgHdr *pDirt
05d0: 79 2c 20 2a 70 44 69 72 74 79 54 61 69 6c 3b 20  y, *pDirtyTail; 
05e0: 20 20 20 20 20 20 20 20 2f 2a 20 4c 69 73 74 20          /* List 
05f0: 6f 66 20 64 69 72 74 79 20 70 61 67 65 73 20 69  of dirty pages i
0600: 6e 20 4c 52 55 20 6f 72 64 65 72 20 2a 2f 0a 20  n LRU order */. 
0610: 20 50 67 48 64 72 20 2a 70 53 79 6e 63 65 64 3b   PgHdr *pSynced;
0620: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0630: 20 20 20 20 20 2f 2a 20 4c 61 73 74 20 73 79 6e       /* Last syn
0640: 63 65 64 20 70 61 67 65 20 69 6e 20 64 69 72 74  ced page in dirt
0650: 79 20 70 61 67 65 20 6c 69 73 74 20 2a 2f 0a 20  y page list */. 
0660: 20 69 6e 74 20 6e 52 65 66 3b 20 20 20 20 20 20   int nRef;      
0670: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0680: 20 20 20 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f       /* Number o
0690: 66 20 70 69 6e 6e 65 64 20 70 61 67 65 73 20 2a  f pinned pages *
06a0: 2f 0a 20 20 69 6e 74 20 6e 50 69 6e 6e 65 64 3b  /.  int nPinned;
06b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
06c0: 20 20 20 20 20 20 20 20 2f 2a 20 4e 75 6d 62 65          /* Numbe
06d0: 72 20 6f 66 20 70 69 6e 6e 65 64 20 61 6e 64 2f  r of pinned and/
06e0: 6f 72 20 64 69 72 74 79 20 70 61 67 65 73 20 2a  or dirty pages *
06f0: 2f 0a 7d 3b 0a 0a 2f 2a 0a 2a 2a 20 46 72 65 65  /.};../*.** Free
0700: 20 73 6c 6f 74 73 20 69 6e 20 74 68 65 20 70 61   slots in the pa
0710: 67 65 20 62 6c 6f 63 6b 20 61 6c 6c 6f 63 61 74  ge block allocat
0720: 6f 72 0a 2a 2f 0a 74 79 70 65 64 65 66 20 73 74  or.*/.typedef st
0730: 72 75 63 74 20 50 67 46 72 65 65 73 6c 6f 74 20  ruct PgFreeslot 
0740: 50 67 46 72 65 65 73 6c 6f 74 3b 0a 73 74 72 75  PgFreeslot;.stru
0750: 63 74 20 50 67 46 72 65 65 73 6c 6f 74 20 7b 0a  ct PgFreeslot {.
0760: 20 20 50 67 46 72 65 65 73 6c 6f 74 20 2a 70 4e    PgFreeslot *pN
0770: 65 78 74 3b 20 20 2f 2a 20 4e 65 78 74 20 66 72  ext;  /* Next fr
0780: 65 65 20 73 6c 6f 74 20 2a 2f 0a 7d 3b 0a 0a 2f  ee slot */.};../
0790: 2a 0a 2a 2a 20 47 6c 6f 62 61 6c 20 64 61 74 61  *.** Global data
07a0: 20 66 6f 72 20 74 68 65 20 70 61 67 65 20 63 61   for the page ca
07b0: 63 68 65 2e 0a 2a 2a 0a 2a 2a 20 54 68 65 20 6d  che..**.** The m
07c0: 61 78 69 6d 75 6d 20 6e 75 6d 62 65 72 20 6f 66  aximum number of
07d0: 20 63 61 63 68 65 64 20 70 61 67 65 73 20 73 74   cached pages st
07e0: 6f 72 65 64 20 62 79 20 74 68 65 20 73 79 73 74  ored by the syst
07f0: 65 6d 20 69 73 20 64 65 74 65 72 6d 69 6e 65 64  em is determined
0800: 0a 2a 2a 20 62 79 20 74 68 65 20 70 63 61 63 68  .** by the pcach
0810: 65 2e 6d 78 50 61 67 65 20 61 6e 64 20 70 63 61  e.mxPage and pca
0820: 63 68 65 2e 6d 78 50 61 67 65 50 75 72 67 65 61  che.mxPagePurgea
0830: 62 6c 65 20 76 61 72 69 61 62 6c 65 73 2e 20 49  ble variables. I
0840: 66 0a 2a 2a 20 6d 78 50 61 67 65 20 69 73 20 6e  f.** mxPage is n
0850: 6f 6e 2d 7a 65 72 6f 2c 20 74 68 65 6e 20 74 68  on-zero, then th
0860: 65 20 73 79 73 74 65 6d 20 74 72 69 65 73 20 74  e system tries t
0870: 6f 20 6c 69 6d 69 74 20 74 68 65 20 6e 75 6d 62  o limit the numb
0880: 65 72 20 6f 66 0a 2a 2a 20 63 61 63 68 65 64 20  er of.** cached 
0890: 70 61 67 65 73 20 73 74 6f 72 65 64 20 74 6f 20  pages stored to 
08a0: 6d 78 50 61 67 65 2e 20 49 6e 20 74 68 69 73 20  mxPage. In this 
08b0: 63 61 73 65 20 6d 78 50 61 67 65 50 75 72 67 65  case mxPagePurge
08c0: 61 62 6c 65 20 69 73 20 6e 6f 74 20 0a 2a 2a 20  able is not .** 
08d0: 75 73 65 64 2e 0a 2a 2a 0a 2a 2a 20 49 66 20 6d  used..**.** If m
08e0: 78 50 61 67 65 20 69 73 20 7a 65 72 6f 2c 20 74  xPage is zero, t
08f0: 68 65 6e 20 74 68 65 20 73 79 73 74 65 6d 20 74  hen the system t
0900: 72 69 65 73 20 74 6f 20 6c 69 6d 69 74 20 74 68  ries to limit th
0910: 65 20 6e 75 6d 62 65 72 20 6f 66 0a 2a 2a 20 70  e number of.** p
0920: 61 67 65 73 20 68 65 6c 64 20 62 79 20 70 75 72  ages held by pur
0930: 67 61 62 6c 65 20 63 61 63 68 65 73 20 74 6f 20  gable caches to 
0940: 6d 78 50 61 67 65 50 75 72 67 65 61 62 6c 65 2e  mxPagePurgeable.
0950: 0a 2a 2a 0a 2a 2a 20 54 68 65 20 64 6f 75 62 6c  .**.** The doubl
0960: 79 2d 6c 69 6e 6b 65 64 20 6c 69 73 74 20 74 68  y-linked list th
0970: 61 74 20 72 75 6e 73 20 62 65 74 77 65 65 6e 20  at runs between 
0980: 70 63 61 63 68 65 2e 70 4c 72 75 48 65 61 64 20  pcache.pLruHead 
0990: 61 6e 64 20 0a 2a 2a 20 70 63 61 63 68 65 2e 70  and .** pcache.p
09a0: 4c 72 75 54 61 69 6c 20 63 6f 6e 74 61 69 6e 73  LruTail contains
09b0: 20 61 6c 6c 20 63 6c 65 61 6e 20 70 75 72 67 61   all clean purga
09c0: 62 6c 65 20 70 61 67 65 73 20 69 6e 20 74 68 65  ble pages in the
09d0: 20 73 79 73 74 65 6d 20 0a 2a 2a 20 77 69 74 68   system .** with
09e0: 20 61 20 7a 65 72 6f 20 72 65 66 65 72 65 6e 63   a zero referenc
09f0: 65 20 63 6f 75 6e 74 2e 20 70 63 61 63 68 65 2e  e count. pcache.
0a00: 70 4c 72 75 54 61 69 6c 20 69 73 20 74 68 65 20  pLruTail is the 
0a10: 6e 65 78 74 20 70 61 67 65 20 74 6f 0a 2a 2a 20  next page to.** 
0a20: 62 65 20 72 65 63 79 63 6c 65 64 2e 0a 2a 2f 0a  be recycled..*/.
0a30: 73 74 61 74 69 63 20 73 74 72 75 63 74 20 50 43  static struct PC
0a40: 61 63 68 65 47 6c 6f 62 61 6c 20 7b 0a 20 20 69  acheGlobal {.  i
0a50: 6e 74 20 69 73 49 6e 69 74 3b 20 20 20 20 20 20  nt isInit;      
0a60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0a70: 20 20 20 2f 2a 20 54 72 75 65 20 77 68 65 6e 20     /* True when 
0a80: 69 6e 69 74 69 61 6c 69 7a 65 64 20 2a 2f 0a 20  initialized */. 
0a90: 20 73 71 6c 69 74 65 33 5f 6d 75 74 65 78 20 2a   sqlite3_mutex *
0aa0: 6d 75 74 65 78 3b 20 20 20 20 20 20 20 20 20 20  mutex;          
0ab0: 20 20 20 20 20 2f 2a 20 73 74 61 74 69 63 20 6d       /* static m
0ac0: 75 74 65 78 20 4d 55 54 45 58 5f 53 54 41 54 49  utex MUTEX_STATI
0ad0: 43 5f 4c 52 55 20 2a 2f 0a 0a 20 20 69 6e 74 20  C_LRU */..  int 
0ae0: 6e 4d 61 78 50 61 67 65 3b 20 20 20 20 20 20 20  nMaxPage;       
0af0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0b00: 2f 2a 20 53 75 6d 20 6f 66 20 6e 4d 61 78 50 61  /* Sum of nMaxPa
0b10: 67 65 20 66 6f 72 20 70 75 72 67 65 61 62 6c 65  ge for purgeable
0b20: 20 63 61 63 68 65 73 20 2a 2f 0a 20 20 69 6e 74   caches */.  int
0b30: 20 6e 4d 69 6e 50 61 67 65 3b 20 20 20 20 20 20   nMinPage;      
0b40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0b50: 20 2f 2a 20 53 75 6d 20 6f 66 20 6e 4d 69 6e 50   /* Sum of nMinP
0b60: 61 67 65 20 66 6f 72 20 70 75 72 67 65 61 62 6c  age for purgeabl
0b70: 65 20 63 61 63 68 65 73 20 2a 2f 0a 20 20 69 6e  e caches */.  in
0b80: 74 20 6e 43 75 72 72 65 6e 74 50 61 67 65 3b 20  t nCurrentPage; 
0b90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0ba0: 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f 66 20 70    /* Number of p
0bb0: 75 72 67 65 61 62 6c 65 20 70 61 67 65 73 20 61  urgeable pages a
0bc0: 6c 6c 6f 63 61 74 65 64 20 2a 2f 0a 20 20 50 67  llocated */.  Pg
0bd0: 48 64 72 20 2a 70 4c 72 75 48 65 61 64 2c 20 2a  Hdr *pLruHead, *
0be0: 70 4c 72 75 54 61 69 6c 3b 20 20 20 20 20 20 20  pLruTail;       
0bf0: 20 20 2f 2a 20 4c 52 55 20 6c 69 73 74 20 6f 66    /* LRU list of
0c00: 20 75 6e 75 73 65 64 20 63 6c 65 61 6e 20 70 67   unused clean pg
0c10: 73 20 2a 2f 0a 0a 20 20 2f 2a 20 56 61 72 69 61  s */..  /* Varia
0c20: 62 6c 65 73 20 72 65 6c 61 74 65 64 20 74 6f 20  bles related to 
0c30: 53 51 4c 49 54 45 5f 43 4f 4e 46 49 47 5f 50 41  SQLITE_CONFIG_PA
0c40: 47 45 43 41 43 48 45 20 73 65 74 74 69 6e 67 73  GECACHE settings
0c50: 2e 20 2a 2f 0a 20 20 69 6e 74 20 73 7a 53 6c 6f  . */.  int szSlo
0c60: 74 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  t;              
0c70: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 53 69             /* Si
0c80: 7a 65 20 6f 66 20 65 61 63 68 20 66 72 65 65 20  ze of each free 
0c90: 73 6c 6f 74 20 2a 2f 0a 20 20 76 6f 69 64 20 2a  slot */.  void *
0ca0: 70 53 74 61 72 74 2c 20 2a 70 45 6e 64 3b 20 20  pStart, *pEnd;  
0cb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
0cc0: 20 42 6f 75 6e 64 73 20 6f 66 20 70 61 67 65 63   Bounds of pagec
0cd0: 61 63 68 65 20 6d 61 6c 6c 6f 63 20 72 61 6e 67  ache malloc rang
0ce0: 65 20 2a 2f 0a 20 20 50 67 46 72 65 65 73 6c 6f  e */.  PgFreeslo
0cf0: 74 20 2a 70 46 72 65 65 3b 20 20 20 20 20 20 20  t *pFree;       
0d00: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 46 72             /* Fr
0d10: 65 65 20 70 61 67 65 20 62 6c 6f 63 6b 73 20 2a  ee page blocks *
0d20: 2f 0a 7d 20 70 63 61 63 68 65 20 3d 20 7b 30 7d  /.} pcache = {0}
0d30: 3b 0a 0a 2f 2a 0a 2a 2a 20 41 6c 6c 20 67 6c 6f  ;../*.** All glo
0d40: 62 61 6c 20 76 61 72 69 61 62 6c 65 73 20 75 73  bal variables us
0d50: 65 64 20 62 79 20 74 68 69 73 20 6d 6f 64 75 6c  ed by this modul
0d60: 65 20 28 6d 6f 73 74 20 6f 66 20 77 68 69 63 68  e (most of which
0d70: 20 61 72 65 20 67 72 6f 75 70 65 64 20 0a 2a 2a   are grouped .**
0d80: 20 74 6f 67 65 74 68 65 72 20 69 6e 20 67 6c 6f   together in glo
0d90: 62 61 6c 20 73 74 72 75 63 74 75 72 65 20 22 70  bal structure "p
0da0: 63 61 63 68 65 22 20 61 62 6f 76 65 29 20 61 72  cache" above) ar
0db0: 65 20 70 72 6f 74 65 63 74 65 64 20 62 79 20 74  e protected by t
0dc0: 68 65 20 73 74 61 74 69 63 20 0a 2a 2a 20 53 51  he static .** SQ
0dd0: 4c 49 54 45 5f 4d 55 54 45 58 5f 53 54 41 54 49  LITE_MUTEX_STATI
0de0: 43 5f 4c 52 55 20 6d 75 74 65 78 2e 20 41 20 70  C_LRU mutex. A p
0df0: 6f 69 6e 74 65 72 20 74 6f 20 74 68 69 73 20 6d  ointer to this m
0e00: 75 74 65 78 20 69 73 20 73 74 6f 72 65 64 20 69  utex is stored i
0e10: 6e 0a 2a 2a 20 76 61 72 69 61 62 6c 65 20 22 70  n.** variable "p
0e20: 63 61 63 68 65 2e 6d 75 74 65 78 22 2e 0a 2a 2a  cache.mutex"..**
0e30: 0a 2a 2a 20 41 63 63 65 73 73 20 74 6f 20 74 68  .** Access to th
0e40: 65 20 63 6f 6e 74 65 6e 74 73 20 6f 66 20 74 68  e contents of th
0e50: 65 20 69 6e 64 69 76 69 64 75 61 6c 20 50 43 61  e individual PCa
0e60: 63 68 65 20 73 74 72 75 63 74 75 72 65 73 20 69  che structures i
0e70: 73 20 6e 6f 74 20 0a 2a 2a 20 70 72 6f 74 65 63  s not .** protec
0e80: 74 65 64 2e 20 49 74 20 69 73 20 74 68 65 20 6a  ted. It is the j
0e90: 6f 62 20 6f 66 20 74 68 65 20 63 61 6c 6c 65 72  ob of the caller
0ea0: 20 74 6f 20 65 6e 73 75 72 65 20 74 68 61 74 20   to ensure that 
0eb0: 74 68 65 73 65 20 73 74 72 75 63 74 75 72 65 73  these structures
0ec0: 0a 2a 2a 20 61 72 65 20 61 63 63 65 73 73 65 64  .** are accessed
0ed0: 20 69 6e 20 61 20 74 68 72 65 61 64 2d 73 61 66   in a thread-saf
0ee0: 65 20 6d 61 6e 6e 65 72 2e 0a 2a 2f 0a 0a 23 64  e manner..*/..#d
0ef0: 65 66 69 6e 65 20 70 63 61 63 68 65 45 6e 74 65  efine pcacheEnte
0f00: 72 47 6c 6f 62 61 6c 28 29 20 73 71 6c 69 74 65  rGlobal() sqlite
0f10: 33 5f 6d 75 74 65 78 5f 65 6e 74 65 72 28 70 63  3_mutex_enter(pc
0f20: 61 63 68 65 2e 6d 75 74 65 78 29 0a 23 64 65 66  ache.mutex).#def
0f30: 69 6e 65 20 70 63 61 63 68 65 45 78 69 74 47 6c  ine pcacheExitGl
0f40: 6f 62 61 6c 28 29 20 20 73 71 6c 69 74 65 33 5f  obal()  sqlite3_
0f50: 6d 75 74 65 78 5f 6c 65 61 76 65 28 70 63 61 63  mutex_leave(pcac
0f60: 68 65 2e 6d 75 74 65 78 29 0a 0a 2f 2a 2a 2a 2a  he.mutex)../****
0f70: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0f80: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20 4c  ************** L
0f90: 69 6e 6b 65 64 20 4c 69 73 74 20 4d 61 6e 61 67  inked List Manag
0fa0: 65 6d 65 6e 74 20 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ement **********
0fb0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2f 0a 0a 23 69 66  **********/..#if
0fc0: 6e 64 65 66 20 4e 44 45 42 55 47 0a 2f 2a 0a 2a  ndef NDEBUG./*.*
0fd0: 2a 20 54 68 69 73 20 72 6f 75 74 69 6e 65 20 76  * This routine v
0fe0: 65 72 69 66 69 65 73 20 74 68 61 74 20 74 68 65  erifies that the
0ff0: 20 6e 75 6d 62 65 72 20 6f 66 20 65 6e 74 72 69   number of entri
1000: 65 73 20 69 6e 20 74 68 65 20 68 61 73 68 20 74  es in the hash t
1010: 61 62 6c 65 0a 2a 2a 20 69 73 20 70 43 61 63 68  able.** is pCach
1020: 65 2d 3e 6e 50 61 67 65 2e 20 20 54 68 69 73 20  e->nPage.  This 
1030: 72 6f 75 74 69 6e 65 20 69 73 20 75 73 65 64 20  routine is used 
1040: 77 69 74 68 69 6e 20 61 73 73 65 72 74 28 29 20  within assert() 
1050: 73 74 61 74 65 6d 65 6e 74 73 0a 2a 2a 20 6f 6e  statements.** on
1060: 6c 79 20 61 6e 64 20 69 73 20 74 68 65 72 65 66  ly and is theref
1070: 6f 72 65 20 64 69 73 61 62 6c 65 64 20 64 75 72  ore disabled dur
1080: 69 6e 67 20 70 72 6f 64 75 63 74 69 6f 6e 20 62  ing production b
1090: 75 69 6c 64 73 2e 0a 2a 2f 0a 73 74 61 74 69 63  uilds..*/.static
10a0: 20 69 6e 74 20 70 63 61 63 68 65 43 68 65 63 6b   int pcacheCheck
10b0: 48 61 73 68 43 6f 75 6e 74 28 50 43 61 63 68 65  HashCount(PCache
10c0: 20 2a 70 43 61 63 68 65 29 7b 0a 23 69 66 20 30   *pCache){.#if 0
10d0: 0a 20 20 69 6e 74 20 69 3b 0a 20 20 69 6e 74 20  .  int i;.  int 
10e0: 6e 50 61 67 65 20 3d 20 30 3b 0a 20 20 66 6f 72  nPage = 0;.  for
10f0: 28 69 3d 30 3b 20 69 3c 70 43 61 63 68 65 2d 3e  (i=0; i<pCache->
1100: 6e 48 61 73 68 3b 20 69 2b 2b 29 7b 0a 20 20 20  nHash; i++){.   
1110: 20 50 67 48 64 72 20 2a 70 3b 0a 20 20 20 20 66   PgHdr *p;.    f
1120: 6f 72 28 70 3d 70 43 61 63 68 65 2d 3e 61 70 48  or(p=pCache->apH
1130: 61 73 68 5b 69 5d 3b 20 70 3b 20 70 3d 70 2d 3e  ash[i]; p; p=p->
1140: 70 4e 65 78 74 48 61 73 68 29 7b 0a 20 20 20 20  pNextHash){.    
1150: 20 20 6e 50 61 67 65 2b 2b 3b 0a 20 20 20 20 7d    nPage++;.    }
1160: 0a 20 20 7d 0a 20 20 61 73 73 65 72 74 28 20 6e  .  }.  assert( n
1170: 50 61 67 65 3d 3d 70 43 61 63 68 65 2d 3e 6e 50  Page==pCache->nP
1180: 61 67 65 20 29 3b 0a 23 65 6e 64 69 66 0a 20 20  age );.#endif.  
1190: 72 65 74 75 72 6e 20 31 3b 0a 7d 0a 0a 2f 2a 0a  return 1;.}../*.
11a0: 2a 2a 20 42 61 73 65 64 20 6f 6e 20 74 68 65 20  ** Based on the 
11b0: 63 75 72 72 65 6e 74 20 76 61 6c 75 65 20 6f 66  current value of
11c0: 20 50 43 61 63 68 65 2e 6e 52 65 66 20 61 6e 64   PCache.nRef and
11d0: 20 74 68 65 20 63 6f 6e 74 65 6e 74 73 20 6f 66   the contents of
11e0: 20 74 68 65 0a 2a 2a 20 50 43 61 63 68 65 2e 70   the.** PCache.p
11f0: 44 69 72 74 79 20 6c 69 73 74 2c 20 72 65 74 75  Dirty list, retu
1200: 72 6e 20 74 68 65 20 65 78 70 65 63 74 65 64 20  rn the expected 
1210: 76 61 6c 75 65 20 6f 66 20 74 68 65 20 50 43 61  value of the PCa
1220: 63 68 65 2e 6e 50 69 6e 6e 65 64 0a 2a 2a 20 63  che.nPinned.** c
1230: 6f 75 6e 74 65 72 2e 20 54 68 69 73 20 69 73 20  ounter. This is 
1240: 6f 6e 6c 79 20 75 73 65 64 20 69 6e 20 64 65 62  only used in deb
1250: 75 67 67 69 6e 67 20 62 75 69 6c 64 73 2c 20 61  ugging builds, a
1260: 73 20 66 6f 6c 6c 6f 77 73 3a 0a 2a 2a 0a 2a 2a  s follows:.**.**
1270: 20 20 20 61 73 73 65 72 74 28 20 70 43 61 63 68     assert( pCach
1280: 65 2d 3e 6e 50 69 6e 6e 65 64 3d 3d 70 63 61 63  e->nPinned==pcac
1290: 68 65 50 69 6e 6e 65 64 43 6f 75 6e 74 28 70 43  hePinnedCount(pC
12a0: 61 63 68 65 29 20 29 3b 0a 2a 2f 0a 73 74 61 74  ache) );.*/.stat
12b0: 69 63 20 69 6e 74 20 70 63 61 63 68 65 50 69 6e  ic int pcachePin
12c0: 6e 65 64 43 6f 75 6e 74 28 50 43 61 63 68 65 20  nedCount(PCache 
12d0: 2a 70 43 61 63 68 65 29 7b 0a 23 69 66 20 30 0a  *pCache){.#if 0.
12e0: 20 20 50 67 48 64 72 20 2a 70 3b 0a 20 20 69 6e    PgHdr *p;.  in
12f0: 74 20 6e 50 69 6e 6e 65 64 20 3d 20 70 43 61 63  t nPinned = pCac
1300: 68 65 2d 3e 6e 52 65 66 3b 0a 20 20 66 6f 72 28  he->nRef;.  for(
1310: 70 3d 70 43 61 63 68 65 2d 3e 70 44 69 72 74 79  p=pCache->pDirty
1320: 3b 20 70 3b 20 70 3d 70 2d 3e 70 4e 65 78 74 29  ; p; p=p->pNext)
1330: 7b 0a 20 20 20 20 69 66 28 20 70 2d 3e 6e 52 65  {.    if( p->nRe
1340: 66 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 6e 50  f==0 ){.      nP
1350: 69 6e 6e 65 64 2b 2b 3b 0a 20 20 20 20 7d 0a 20  inned++;.    }. 
1360: 20 7d 0a 20 20 72 65 74 75 72 6e 20 6e 50 69 6e   }.  return nPin
1370: 6e 65 64 3b 0a 23 65 6e 64 69 66 0a 20 20 72 65  ned;.#endif.  re
1380: 74 75 72 6e 20 70 43 61 63 68 65 2d 3e 6e 50 69  turn pCache->nPi
1390: 6e 6e 65 64 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 43  nned;.}../*.** C
13a0: 68 65 63 6b 20 74 68 61 74 20 74 68 65 20 70 43  heck that the pC
13b0: 61 63 68 65 2d 3e 70 53 79 6e 63 65 64 20 76 61  ache->pSynced va
13c0: 72 69 61 62 6c 65 20 69 73 20 73 65 74 20 63 6f  riable is set co
13d0: 72 72 65 63 74 6c 79 2e 20 49 66 20 69 74 0a 2a  rrectly. If it.*
13e0: 2a 20 69 73 20 6e 6f 74 2c 20 65 69 74 68 65 72  * is not, either
13f0: 20 66 61 69 6c 20 61 6e 20 61 73 73 65 72 74 20   fail an assert 
1400: 6f 72 20 72 65 74 75 72 6e 20 7a 65 72 6f 2e 20  or return zero. 
1410: 4f 74 68 65 72 77 69 73 65 2c 20 72 65 74 75 72  Otherwise, retur
1420: 6e 0a 2a 2a 20 6e 6f 6e 2d 7a 65 72 6f 2e 20 54  n.** non-zero. T
1430: 68 69 73 20 69 73 20 6f 6e 6c 79 20 75 73 65 64  his is only used
1440: 20 69 6e 20 64 65 62 75 67 67 69 6e 67 20 62 75   in debugging bu
1450: 69 6c 64 73 2c 20 61 73 20 66 6f 6c 6c 6f 77 73  ilds, as follows
1460: 3a 0a 2a 2a 0a 2a 2a 20 20 20 61 73 73 65 72 74  :.**.**   assert
1470: 28 20 70 63 61 63 68 65 43 68 65 63 6b 53 79 6e  ( pcacheCheckSyn
1480: 63 65 64 28 70 43 61 63 68 65 29 20 29 3b 0a 2a  ced(pCache) );.*
1490: 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 70 63 61  /.static int pca
14a0: 63 68 65 43 68 65 63 6b 53 79 6e 63 65 64 28 50  cheCheckSynced(P
14b0: 43 61 63 68 65 20 2a 70 43 61 63 68 65 29 7b 0a  Cache *pCache){.
14c0: 23 69 66 20 30 0a 20 20 50 67 48 64 72 20 2a 70  #if 0.  PgHdr *p
14d0: 20 3d 20 70 43 61 63 68 65 2d 3e 70 44 69 72 74   = pCache->pDirt
14e0: 79 54 61 69 6c 3b 0a 20 20 66 6f 72 28 70 3d 70  yTail;.  for(p=p
14f0: 43 61 63 68 65 2d 3e 70 44 69 72 74 79 54 61 69  Cache->pDirtyTai
1500: 6c 3b 20 70 21 3d 70 43 61 63 68 65 2d 3e 70 53  l; p!=pCache->pS
1510: 79 6e 63 65 64 3b 20 70 3d 70 2d 3e 70 50 72 65  ynced; p=p->pPre
1520: 76 29 7b 0a 20 20 20 20 61 73 73 65 72 74 28 20  v){.    assert( 
1530: 70 2d 3e 6e 52 65 66 20 7c 7c 20 28 70 2d 3e 66  p->nRef || (p->f
1540: 6c 61 67 73 26 50 47 48 44 52 5f 4e 45 45 44 5f  lags&PGHDR_NEED_
1550: 53 59 4e 43 29 20 29 3b 0a 20 20 7d 0a 20 20 72  SYNC) );.  }.  r
1560: 65 74 75 72 6e 20 28 70 3d 3d 30 20 7c 7c 20 70  eturn (p==0 || p
1570: 2d 3e 6e 52 65 66 20 7c 7c 20 28 70 2d 3e 66 6c  ->nRef || (p->fl
1580: 61 67 73 26 50 47 48 44 52 5f 4e 45 45 44 5f 53  ags&PGHDR_NEED_S
1590: 59 4e 43 29 3d 3d 30 29 3b 0a 23 65 6e 64 69 66  YNC)==0);.#endif
15a0: 0a 20 20 72 65 74 75 72 6e 20 31 3b 0a 7d 0a 0a  .  return 1;.}..
15b0: 23 65 6e 64 69 66 0a 0a 2f 2a 0a 2a 2a 20 52 65  #endif../*.** Re
15c0: 6d 6f 76 65 20 61 20 70 61 67 65 20 66 72 6f 6d  move a page from
15d0: 20 69 74 73 20 68 61 73 68 20 74 61 62 6c 65 20   its hash table 
15e0: 28 50 43 61 63 68 65 2e 61 70 48 61 73 68 5b 5d  (PCache.apHash[]
15f0: 29 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 76 6f 69  )..*/.static voi
1600: 64 20 70 63 61 63 68 65 52 65 6d 6f 76 65 46 72  d pcacheRemoveFr
1610: 6f 6d 48 61 73 68 28 50 67 48 64 72 20 2a 70 50  omHash(PgHdr *pP
1620: 61 67 65 29 7b 0a 20 20 69 66 28 20 70 50 61 67  age){.  if( pPag
1630: 65 2d 3e 70 50 72 65 76 48 61 73 68 20 29 7b 0a  e->pPrevHash ){.
1640: 20 20 20 20 70 50 61 67 65 2d 3e 70 50 72 65 76      pPage->pPrev
1650: 48 61 73 68 2d 3e 70 4e 65 78 74 48 61 73 68 20  Hash->pNextHash 
1660: 3d 20 70 50 61 67 65 2d 3e 70 4e 65 78 74 48 61  = pPage->pNextHa
1670: 73 68 3b 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20  sh;.  }else{.   
1680: 20 50 43 61 63 68 65 20 2a 70 43 61 63 68 65 20   PCache *pCache 
1690: 3d 20 70 50 61 67 65 2d 3e 70 43 61 63 68 65 3b  = pPage->pCache;
16a0: 0a 20 20 20 20 75 33 32 20 68 20 3d 20 70 50 61  .    u32 h = pPa
16b0: 67 65 2d 3e 70 67 6e 6f 20 25 20 70 43 61 63 68  ge->pgno % pCach
16c0: 65 2d 3e 6e 48 61 73 68 3b 0a 20 20 20 20 61 73  e->nHash;.    as
16d0: 73 65 72 74 28 20 70 43 61 63 68 65 2d 3e 61 70  sert( pCache->ap
16e0: 48 61 73 68 5b 68 5d 3d 3d 70 50 61 67 65 20 29  Hash[h]==pPage )
16f0: 3b 0a 20 20 20 20 70 43 61 63 68 65 2d 3e 61 70  ;.    pCache->ap
1700: 48 61 73 68 5b 68 5d 20 3d 20 70 50 61 67 65 2d  Hash[h] = pPage-
1710: 3e 70 4e 65 78 74 48 61 73 68 3b 0a 20 20 7d 0a  >pNextHash;.  }.
1720: 20 20 69 66 28 20 70 50 61 67 65 2d 3e 70 4e 65    if( pPage->pNe
1730: 78 74 48 61 73 68 20 29 7b 0a 20 20 20 20 70 50  xtHash ){.    pP
1740: 61 67 65 2d 3e 70 4e 65 78 74 48 61 73 68 2d 3e  age->pNextHash->
1750: 70 50 72 65 76 48 61 73 68 20 3d 20 70 50 61 67  pPrevHash = pPag
1760: 65 2d 3e 70 50 72 65 76 48 61 73 68 3b 0a 20 20  e->pPrevHash;.  
1770: 7d 0a 20 20 70 50 61 67 65 2d 3e 70 43 61 63 68  }.  pPage->pCach
1780: 65 2d 3e 6e 50 61 67 65 2d 2d 3b 0a 20 20 61 73  e->nPage--;.  as
1790: 73 65 72 74 28 20 70 63 61 63 68 65 43 68 65 63  sert( pcacheChec
17a0: 6b 48 61 73 68 43 6f 75 6e 74 28 70 50 61 67 65  kHashCount(pPage
17b0: 2d 3e 70 43 61 63 68 65 29 20 29 3b 0a 7d 0a 0a  ->pCache) );.}..
17c0: 2f 2a 0a 2a 2a 20 49 6e 73 65 72 74 20 61 20 70  /*.** Insert a p
17d0: 61 67 65 20 69 6e 74 6f 20 74 68 65 20 68 61 73  age into the has
17e0: 68 20 74 61 62 6c 65 0a 2a 2f 0a 73 74 61 74 69  h table.*/.stati
17f0: 63 20 76 6f 69 64 20 70 63 61 63 68 65 41 64 64  c void pcacheAdd
1800: 54 6f 48 61 73 68 28 50 67 48 64 72 20 2a 70 50  ToHash(PgHdr *pP
1810: 61 67 65 29 7b 0a 20 20 50 43 61 63 68 65 20 2a  age){.  PCache *
1820: 70 43 61 63 68 65 20 3d 20 70 50 61 67 65 2d 3e  pCache = pPage->
1830: 70 43 61 63 68 65 3b 0a 20 20 75 33 32 20 68 20  pCache;.  u32 h 
1840: 3d 20 70 50 61 67 65 2d 3e 70 67 6e 6f 20 25 20  = pPage->pgno % 
1850: 70 43 61 63 68 65 2d 3e 6e 48 61 73 68 3b 0a 20  pCache->nHash;. 
1860: 20 70 50 61 67 65 2d 3e 70 4e 65 78 74 48 61 73   pPage->pNextHas
1870: 68 20 3d 20 70 43 61 63 68 65 2d 3e 61 70 48 61  h = pCache->apHa
1880: 73 68 5b 68 5d 3b 0a 20 20 70 50 61 67 65 2d 3e  sh[h];.  pPage->
1890: 70 50 72 65 76 48 61 73 68 20 3d 20 30 3b 0a 20  pPrevHash = 0;. 
18a0: 20 69 66 28 20 70 43 61 63 68 65 2d 3e 61 70 48   if( pCache->apH
18b0: 61 73 68 5b 68 5d 20 29 7b 0a 20 20 20 20 70 43  ash[h] ){.    pC
18c0: 61 63 68 65 2d 3e 61 70 48 61 73 68 5b 68 5d 2d  ache->apHash[h]-
18d0: 3e 70 50 72 65 76 48 61 73 68 20 3d 20 70 50 61  >pPrevHash = pPa
18e0: 67 65 3b 0a 20 20 7d 0a 20 20 70 43 61 63 68 65  ge;.  }.  pCache
18f0: 2d 3e 61 70 48 61 73 68 5b 68 5d 20 3d 20 70 50  ->apHash[h] = pP
1900: 61 67 65 3b 0a 20 20 70 43 61 63 68 65 2d 3e 6e  age;.  pCache->n
1910: 50 61 67 65 2b 2b 3b 0a 20 20 61 73 73 65 72 74  Page++;.  assert
1920: 28 20 70 63 61 63 68 65 43 68 65 63 6b 48 61 73  ( pcacheCheckHas
1930: 68 43 6f 75 6e 74 28 70 43 61 63 68 65 29 20 29  hCount(pCache) )
1940: 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 41 74 74 65 6d  ;.}../*.** Attem
1950: 70 74 20 74 6f 20 69 6e 63 72 65 61 73 65 20 74  pt to increase t
1960: 68 65 20 73 69 7a 65 20 74 68 65 20 68 61 73 68  he size the hash
1970: 20 74 61 62 6c 65 20 74 6f 20 63 6f 6e 74 61 69   table to contai
1980: 6e 0a 2a 2a 20 61 74 20 6c 65 61 73 74 20 6e 48  n.** at least nH
1990: 61 73 68 20 62 75 63 6b 65 74 73 2e 0a 2a 2f 0a  ash buckets..*/.
19a0: 73 74 61 74 69 63 20 69 6e 74 20 70 63 61 63 68  static int pcach
19b0: 65 52 65 73 69 7a 65 48 61 73 68 28 50 43 61 63  eResizeHash(PCac
19c0: 68 65 20 2a 70 43 61 63 68 65 2c 20 69 6e 74 20  he *pCache, int 
19d0: 6e 48 61 73 68 29 7b 0a 23 69 66 64 65 66 20 53  nHash){.#ifdef S
19e0: 51 4c 49 54 45 5f 4d 41 4c 4c 4f 43 5f 53 4f 46  QLITE_MALLOC_SOF
19f0: 54 5f 4c 49 4d 49 54 0a 20 20 69 66 28 20 6e 48  T_LIMIT.  if( nH
1a00: 61 73 68 2a 73 69 7a 65 6f 66 28 50 67 48 64 72  ash*sizeof(PgHdr
1a10: 2a 29 3e 53 51 4c 49 54 45 5f 4d 41 4c 4c 4f 43  *)>SQLITE_MALLOC
1a20: 5f 53 4f 46 54 5f 4c 49 4d 49 54 20 29 7b 0a 20  _SOFT_LIMIT ){. 
1a30: 20 20 20 6e 48 61 73 68 20 3d 20 53 51 4c 49 54     nHash = SQLIT
1a40: 45 5f 4d 41 4c 4c 4f 43 5f 53 4f 46 54 5f 4c 49  E_MALLOC_SOFT_LI
1a50: 4d 49 54 2f 73 69 7a 65 6f 66 28 50 67 48 64 72  MIT/sizeof(PgHdr
1a60: 20 2a 29 3b 0a 20 20 7d 0a 23 65 6e 64 69 66 0a   *);.  }.#endif.
1a70: 20 20 69 66 28 20 6e 48 61 73 68 3e 70 43 61 63    if( nHash>pCac
1a80: 68 65 2d 3e 6e 48 61 73 68 20 29 7b 0a 20 20 20  he->nHash ){.   
1a90: 20 50 67 48 64 72 20 2a 70 3b 0a 20 20 20 20 50   PgHdr *p;.    P
1aa0: 67 48 64 72 20 2a 2a 70 4e 65 77 20 3d 20 28 50  gHdr **pNew = (P
1ab0: 67 48 64 72 20 2a 2a 29 73 71 6c 69 74 65 33 5f  gHdr **)sqlite3_
1ac0: 6d 61 6c 6c 6f 63 28 73 69 7a 65 6f 66 28 50 67  malloc(sizeof(Pg
1ad0: 48 64 72 2a 29 2a 6e 48 61 73 68 29 3b 0a 20 20  Hdr*)*nHash);.  
1ae0: 20 20 69 66 28 20 21 70 4e 65 77 20 29 7b 0a 20    if( !pNew ){. 
1af0: 20 20 20 20 20 72 65 74 75 72 6e 20 53 51 4c 49       return SQLI
1b00: 54 45 5f 4e 4f 4d 45 4d 3b 0a 20 20 20 20 7d 0a  TE_NOMEM;.    }.
1b10: 20 20 20 20 6d 65 6d 73 65 74 28 70 4e 65 77 2c      memset(pNew,
1b20: 20 30 2c 20 73 69 7a 65 6f 66 28 50 67 48 64 72   0, sizeof(PgHdr
1b30: 20 2a 29 2a 6e 48 61 73 68 29 3b 0a 20 20 20 20   *)*nHash);.    
1b40: 73 71 6c 69 74 65 33 5f 66 72 65 65 28 70 43 61  sqlite3_free(pCa
1b50: 63 68 65 2d 3e 61 70 48 61 73 68 29 3b 0a 20 20  che->apHash);.  
1b60: 20 20 70 43 61 63 68 65 2d 3e 61 70 48 61 73 68    pCache->apHash
1b70: 20 3d 20 70 4e 65 77 3b 0a 20 20 20 20 70 43 61   = pNew;.    pCa
1b80: 63 68 65 2d 3e 6e 48 61 73 68 20 3d 20 6e 48 61  che->nHash = nHa
1b90: 73 68 3b 0a 20 20 20 20 70 43 61 63 68 65 2d 3e  sh;.    pCache->
1ba0: 6e 50 61 67 65 20 3d 20 30 3b 0a 20 20 20 0a 20  nPage = 0;.   . 
1bb0: 20 20 20 66 6f 72 28 70 3d 70 43 61 63 68 65 2d     for(p=pCache-
1bc0: 3e 70 43 6c 65 61 6e 3b 20 70 3b 20 70 3d 70 2d  >pClean; p; p=p-
1bd0: 3e 70 4e 65 78 74 29 7b 0a 20 20 20 20 20 20 70  >pNext){.      p
1be0: 63 61 63 68 65 41 64 64 54 6f 48 61 73 68 28 70  cacheAddToHash(p
1bf0: 29 3b 0a 20 20 20 20 7d 0a 20 20 20 20 66 6f 72  );.    }.    for
1c00: 28 70 3d 70 43 61 63 68 65 2d 3e 70 44 69 72 74  (p=pCache->pDirt
1c10: 79 3b 20 70 3b 20 70 3d 70 2d 3e 70 4e 65 78 74  y; p; p=p->pNext
1c20: 29 7b 0a 20 20 20 20 20 20 70 63 61 63 68 65 41  ){.      pcacheA
1c30: 64 64 54 6f 48 61 73 68 28 70 29 3b 0a 20 20 20  ddToHash(p);.   
1c40: 20 7d 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20   }.  }.  return 
1c50: 53 51 4c 49 54 45 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a  SQLITE_OK;.}../*
1c60: 0a 2a 2a 20 52 65 6d 6f 76 65 20 61 20 70 61 67  .** Remove a pag
1c70: 65 20 66 72 6f 6d 20 61 20 6c 69 6e 6b 65 64 20  e from a linked 
1c80: 6c 69 73 74 20 74 68 61 74 20 69 73 20 68 65 61  list that is hea
1c90: 64 65 64 20 62 79 20 2a 70 70 48 65 61 64 2e 0a  ded by *ppHead..
1ca0: 2a 2a 20 2a 70 70 48 65 61 64 20 69 73 20 65 69  ** *ppHead is ei
1cb0: 74 68 65 72 20 50 43 61 63 68 65 2e 70 43 6c 65  ther PCache.pCle
1cc0: 61 6e 20 6f 72 20 50 43 61 63 68 65 2e 70 44 69  an or PCache.pDi
1cd0: 72 74 79 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 76  rty..*/.static v
1ce0: 6f 69 64 20 70 63 61 63 68 65 52 65 6d 6f 76 65  oid pcacheRemove
1cf0: 46 72 6f 6d 4c 69 73 74 28 50 67 48 64 72 20 2a  FromList(PgHdr *
1d00: 2a 70 70 48 65 61 64 2c 20 50 67 48 64 72 20 2a  *ppHead, PgHdr *
1d10: 70 50 61 67 65 29 7b 0a 20 20 69 6e 74 20 69 73  pPage){.  int is
1d20: 44 69 72 74 79 4c 69 73 74 20 3d 20 28 70 70 48  DirtyList = (ppH
1d30: 65 61 64 3d 3d 26 70 50 61 67 65 2d 3e 70 43 61  ead==&pPage->pCa
1d40: 63 68 65 2d 3e 70 44 69 72 74 79 29 3b 0a 20 20  che->pDirty);.  
1d50: 61 73 73 65 72 74 28 20 70 70 48 65 61 64 3d 3d  assert( ppHead==
1d60: 26 70 50 61 67 65 2d 3e 70 43 61 63 68 65 2d 3e  &pPage->pCache->
1d70: 70 43 6c 65 61 6e 20 7c 7c 20 70 70 48 65 61 64  pClean || ppHead
1d80: 3d 3d 26 70 50 61 67 65 2d 3e 70 43 61 63 68 65  ==&pPage->pCache
1d90: 2d 3e 70 44 69 72 74 79 20 29 3b 0a 0a 20 20 69  ->pDirty );..  i
1da0: 66 28 20 70 50 61 67 65 2d 3e 70 50 72 65 76 20  f( pPage->pPrev 
1db0: 29 7b 0a 20 20 20 20 70 50 61 67 65 2d 3e 70 50  ){.    pPage->pP
1dc0: 72 65 76 2d 3e 70 4e 65 78 74 20 3d 20 70 50 61  rev->pNext = pPa
1dd0: 67 65 2d 3e 70 4e 65 78 74 3b 0a 20 20 7d 65 6c  ge->pNext;.  }el
1de0: 73 65 7b 0a 20 20 20 20 61 73 73 65 72 74 28 20  se{.    assert( 
1df0: 2a 70 70 48 65 61 64 3d 3d 70 50 61 67 65 20 29  *ppHead==pPage )
1e00: 3b 0a 20 20 20 20 2a 70 70 48 65 61 64 20 3d 20  ;.    *ppHead = 
1e10: 70 50 61 67 65 2d 3e 70 4e 65 78 74 3b 0a 20 20  pPage->pNext;.  
1e20: 7d 0a 20 20 69 66 28 20 70 50 61 67 65 2d 3e 70  }.  if( pPage->p
1e30: 4e 65 78 74 20 29 7b 0a 20 20 20 20 70 50 61 67  Next ){.    pPag
1e40: 65 2d 3e 70 4e 65 78 74 2d 3e 70 50 72 65 76 20  e->pNext->pPrev 
1e50: 3d 20 70 50 61 67 65 2d 3e 70 50 72 65 76 3b 0a  = pPage->pPrev;.
1e60: 20 20 7d 0a 0a 20 20 69 66 28 20 69 73 44 69 72    }..  if( isDir
1e70: 74 79 4c 69 73 74 20 29 7b 0a 20 20 20 20 50 43  tyList ){.    PC
1e80: 61 63 68 65 20 2a 70 43 61 63 68 65 20 3d 20 70  ache *pCache = p
1e90: 50 61 67 65 2d 3e 70 43 61 63 68 65 3b 0a 20 20  Page->pCache;.  
1ea0: 20 20 61 73 73 65 72 74 28 20 70 50 61 67 65 2d    assert( pPage-
1eb0: 3e 70 4e 65 78 74 20 7c 7c 20 70 43 61 63 68 65  >pNext || pCache
1ec0: 2d 3e 70 44 69 72 74 79 54 61 69 6c 3d 3d 70 50  ->pDirtyTail==pP
1ed0: 61 67 65 20 29 3b 0a 20 20 20 20 69 66 28 20 21  age );.    if( !
1ee0: 70 50 61 67 65 2d 3e 70 4e 65 78 74 20 29 7b 0a  pPage->pNext ){.
1ef0: 20 20 20 20 20 20 70 43 61 63 68 65 2d 3e 70 44        pCache->pD
1f00: 69 72 74 79 54 61 69 6c 20 3d 20 70 50 61 67 65  irtyTail = pPage
1f10: 2d 3e 70 50 72 65 76 3b 0a 20 20 20 20 7d 0a 20  ->pPrev;.    }. 
1f20: 20 20 20 69 66 28 20 70 43 61 63 68 65 2d 3e 70     if( pCache->p
1f30: 53 79 6e 63 65 64 3d 3d 70 50 61 67 65 20 29 7b  Synced==pPage ){
1f40: 0a 20 20 20 20 20 20 50 67 48 64 72 20 2a 70 53  .      PgHdr *pS
1f50: 79 6e 63 65 64 20 3d 20 70 50 61 67 65 2d 3e 70  ynced = pPage->p
1f60: 50 72 65 76 3b 0a 20 20 20 20 20 20 77 68 69 6c  Prev;.      whil
1f70: 65 28 20 70 53 79 6e 63 65 64 20 26 26 20 28 70  e( pSynced && (p
1f80: 53 79 6e 63 65 64 2d 3e 66 6c 61 67 73 26 50 47  Synced->flags&PG
1f90: 48 44 52 5f 4e 45 45 44 5f 53 59 4e 43 29 20 29  HDR_NEED_SYNC) )
1fa0: 7b 0a 20 20 20 20 20 20 20 20 70 53 79 6e 63 65  {.        pSynce
1fb0: 64 20 3d 20 70 53 79 6e 63 65 64 2d 3e 70 50 72  d = pSynced->pPr
1fc0: 65 76 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20 20  ev;.      }.    
1fd0: 20 20 70 43 61 63 68 65 2d 3e 70 53 79 6e 63 65    pCache->pSynce
1fe0: 64 20 3d 20 70 53 79 6e 63 65 64 3b 0a 20 20 20  d = pSynced;.   
1ff0: 20 7d 0a 20 20 7d 0a 7d 0a 0a 2f 2a 0a 2a 2a 20   }.  }.}../*.** 
2000: 41 64 64 20 61 20 70 61 67 65 20 66 72 6f 6d 20  Add a page from 
2010: 61 20 6c 69 6e 6b 65 64 20 6c 69 73 74 20 74 68  a linked list th
2020: 61 74 20 69 73 20 68 65 61 64 65 64 20 62 79 20  at is headed by 
2030: 2a 70 70 48 65 61 64 2e 0a 2a 2a 20 2a 70 70 48  *ppHead..** *ppH
2040: 65 61 64 20 69 73 20 65 69 74 68 65 72 20 50 43  ead is either PC
2050: 61 63 68 65 2e 70 43 6c 65 61 6e 20 6f 72 20 50  ache.pClean or P
2060: 43 61 63 68 65 2e 70 44 69 72 74 79 2e 0a 2a 2f  Cache.pDirty..*/
2070: 0a 73 74 61 74 69 63 20 76 6f 69 64 20 70 63 61  .static void pca
2080: 63 68 65 41 64 64 54 6f 4c 69 73 74 28 50 67 48  cheAddToList(PgH
2090: 64 72 20 2a 2a 70 70 48 65 61 64 2c 20 50 67 48  dr **ppHead, PgH
20a0: 64 72 20 2a 70 50 61 67 65 29 7b 0a 20 20 69 6e  dr *pPage){.  in
20b0: 74 20 69 73 44 69 72 74 79 4c 69 73 74 20 3d 20  t isDirtyList = 
20c0: 28 70 70 48 65 61 64 3d 3d 26 70 50 61 67 65 2d  (ppHead==&pPage-
20d0: 3e 70 43 61 63 68 65 2d 3e 70 44 69 72 74 79 29  >pCache->pDirty)
20e0: 3b 0a 20 20 61 73 73 65 72 74 28 20 70 70 48 65  ;.  assert( ppHe
20f0: 61 64 3d 3d 26 70 50 61 67 65 2d 3e 70 43 61 63  ad==&pPage->pCac
2100: 68 65 2d 3e 70 43 6c 65 61 6e 20 7c 7c 20 70 70  he->pClean || pp
2110: 48 65 61 64 3d 3d 26 70 50 61 67 65 2d 3e 70 43  Head==&pPage->pC
2120: 61 63 68 65 2d 3e 70 44 69 72 74 79 20 29 3b 0a  ache->pDirty );.
2130: 0a 20 20 69 66 28 20 28 2a 70 70 48 65 61 64 29  .  if( (*ppHead)
2140: 20 29 7b 0a 20 20 20 20 28 2a 70 70 48 65 61 64   ){.    (*ppHead
2150: 29 2d 3e 70 50 72 65 76 20 3d 20 70 50 61 67 65  )->pPrev = pPage
2160: 3b 0a 20 20 7d 0a 20 20 70 50 61 67 65 2d 3e 70  ;.  }.  pPage->p
2170: 4e 65 78 74 20 3d 20 2a 70 70 48 65 61 64 3b 0a  Next = *ppHead;.
2180: 20 20 70 50 61 67 65 2d 3e 70 50 72 65 76 20 3d    pPage->pPrev =
2190: 20 30 3b 0a 20 20 2a 70 70 48 65 61 64 20 3d 20   0;.  *ppHead = 
21a0: 70 50 61 67 65 3b 0a 0a 20 20 69 66 28 20 69 73  pPage;..  if( is
21b0: 44 69 72 74 79 4c 69 73 74 20 29 7b 0a 20 20 20  DirtyList ){.   
21c0: 20 50 43 61 63 68 65 20 2a 70 43 61 63 68 65 20   PCache *pCache 
21d0: 3d 20 70 50 61 67 65 2d 3e 70 43 61 63 68 65 3b  = pPage->pCache;
21e0: 0a 20 20 20 20 69 66 28 20 21 70 43 61 63 68 65  .    if( !pCache
21f0: 2d 3e 70 44 69 72 74 79 54 61 69 6c 20 29 7b 0a  ->pDirtyTail ){.
2200: 20 20 20 20 20 20 61 73 73 65 72 74 28 20 70 50        assert( pP
2210: 61 67 65 2d 3e 70 4e 65 78 74 3d 3d 30 20 29 3b  age->pNext==0 );
2220: 0a 20 20 20 20 20 20 70 43 61 63 68 65 2d 3e 70  .      pCache->p
2230: 44 69 72 74 79 54 61 69 6c 20 3d 20 70 50 61 67  DirtyTail = pPag
2240: 65 3b 0a 20 20 20 20 7d 0a 20 20 20 20 69 66 28  e;.    }.    if(
2250: 20 21 70 43 61 63 68 65 2d 3e 70 53 79 6e 63 65   !pCache->pSynce
2260: 64 20 26 26 20 30 3d 3d 28 70 50 61 67 65 2d 3e  d && 0==(pPage->
2270: 66 6c 61 67 73 26 50 47 48 44 52 5f 4e 45 45 44  flags&PGHDR_NEED
2280: 5f 53 59 4e 43 29 20 29 7b 0a 20 20 20 20 20 20  _SYNC) ){.      
2290: 70 43 61 63 68 65 2d 3e 70 53 79 6e 63 65 64 20  pCache->pSynced 
22a0: 3d 20 70 50 61 67 65 3b 0a 20 20 20 20 7d 0a 20  = pPage;.    }. 
22b0: 20 7d 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 52 65 6d 6f   }.}../*.** Remo
22c0: 76 65 20 61 20 70 61 67 65 20 66 72 6f 6d 20 74  ve a page from t
22d0: 68 65 20 67 6c 6f 62 61 6c 20 4c 52 55 20 6c 69  he global LRU li
22e0: 73 74 0a 2a 2f 0a 73 74 61 74 69 63 20 76 6f 69  st.*/.static voi
22f0: 64 20 70 63 61 63 68 65 52 65 6d 6f 76 65 46 72  d pcacheRemoveFr
2300: 6f 6d 4c 72 75 4c 69 73 74 28 50 67 48 64 72 20  omLruList(PgHdr 
2310: 2a 70 50 61 67 65 29 7b 0a 20 20 61 73 73 65 72  *pPage){.  asser
2320: 74 28 20 73 71 6c 69 74 65 33 5f 6d 75 74 65 78  t( sqlite3_mutex
2330: 5f 68 65 6c 64 28 70 63 61 63 68 65 2e 6d 75 74  _held(pcache.mut
2340: 65 78 29 20 29 3b 0a 20 20 61 73 73 65 72 74 28  ex) );.  assert(
2350: 20 28 70 50 61 67 65 2d 3e 66 6c 61 67 73 26 50   (pPage->flags&P
2360: 47 48 44 52 5f 44 49 52 54 59 29 3d 3d 30 20 29  GHDR_DIRTY)==0 )
2370: 3b 0a 20 20 69 66 28 20 70 50 61 67 65 2d 3e 70  ;.  if( pPage->p
2380: 43 61 63 68 65 2d 3e 62 50 75 72 67 65 61 62 6c  Cache->bPurgeabl
2390: 65 3d 3d 30 20 29 20 72 65 74 75 72 6e 3b 0a 20  e==0 ) return;. 
23a0: 20 69 66 28 20 70 50 61 67 65 2d 3e 70 4e 65 78   if( pPage->pNex
23b0: 74 4c 72 75 20 29 7b 0a 20 20 20 20 61 73 73 65  tLru ){.    asse
23c0: 72 74 28 20 70 63 61 63 68 65 2e 70 4c 72 75 54  rt( pcache.pLruT
23d0: 61 69 6c 21 3d 70 50 61 67 65 20 29 3b 0a 20 20  ail!=pPage );.  
23e0: 20 20 70 50 61 67 65 2d 3e 70 4e 65 78 74 4c 72    pPage->pNextLr
23f0: 75 2d 3e 70 50 72 65 76 4c 72 75 20 3d 20 70 50  u->pPrevLru = pP
2400: 61 67 65 2d 3e 70 50 72 65 76 4c 72 75 3b 0a 20  age->pPrevLru;. 
2410: 20 7d 65 6c 73 65 7b 0a 20 20 20 20 61 73 73 65   }else{.    asse
2420: 72 74 28 20 70 63 61 63 68 65 2e 70 4c 72 75 54  rt( pcache.pLruT
2430: 61 69 6c 3d 3d 70 50 61 67 65 20 29 3b 0a 20 20  ail==pPage );.  
2440: 20 20 70 63 61 63 68 65 2e 70 4c 72 75 54 61 69    pcache.pLruTai
2450: 6c 20 3d 20 70 50 61 67 65 2d 3e 70 50 72 65 76  l = pPage->pPrev
2460: 4c 72 75 3b 0a 20 20 7d 0a 20 20 69 66 28 20 70  Lru;.  }.  if( p
2470: 50 61 67 65 2d 3e 70 50 72 65 76 4c 72 75 20 29  Page->pPrevLru )
2480: 7b 0a 20 20 20 20 61 73 73 65 72 74 28 20 70 63  {.    assert( pc
2490: 61 63 68 65 2e 70 4c 72 75 48 65 61 64 21 3d 70  ache.pLruHead!=p
24a0: 50 61 67 65 20 29 3b 0a 20 20 20 20 70 50 61 67  Page );.    pPag
24b0: 65 2d 3e 70 50 72 65 76 4c 72 75 2d 3e 70 4e 65  e->pPrevLru->pNe
24c0: 78 74 4c 72 75 20 3d 20 70 50 61 67 65 2d 3e 70  xtLru = pPage->p
24d0: 4e 65 78 74 4c 72 75 3b 0a 20 20 7d 65 6c 73 65  NextLru;.  }else
24e0: 7b 0a 20 20 20 20 61 73 73 65 72 74 28 20 70 63  {.    assert( pc
24f0: 61 63 68 65 2e 70 4c 72 75 48 65 61 64 3d 3d 70  ache.pLruHead==p
2500: 50 61 67 65 20 29 3b 0a 20 20 20 20 70 63 61 63  Page );.    pcac
2510: 68 65 2e 70 4c 72 75 48 65 61 64 20 3d 20 70 50  he.pLruHead = pP
2520: 61 67 65 2d 3e 70 4e 65 78 74 4c 72 75 3b 0a 20  age->pNextLru;. 
2530: 20 7d 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 41 64 64 20   }.}../*.** Add 
2540: 61 20 70 61 67 65 20 74 6f 20 74 68 65 20 67 6c  a page to the gl
2550: 6f 62 61 6c 20 4c 52 55 20 6c 69 73 74 2e 20 20  obal LRU list.  
2560: 54 68 65 20 70 61 67 65 20 69 73 20 6e 6f 72 6d  The page is norm
2570: 61 6c 6c 79 20 61 64 64 65 64 0a 2a 2a 20 74 6f  ally added.** to
2580: 20 74 68 65 20 66 72 6f 6e 74 20 6f 66 20 74 68   the front of th
2590: 65 20 6c 69 73 74 20 73 6f 20 74 68 61 74 20 69  e list so that i
25a0: 74 20 77 69 6c 6c 20 62 65 20 74 68 65 20 6c 61  t will be the la
25b0: 73 74 20 70 61 67 65 20 72 65 63 79 63 6c 65 64  st page recycled
25c0: 2e 0a 2a 2a 20 48 6f 77 65 76 65 72 2c 20 69 66  ..** However, if
25d0: 20 74 68 65 20 50 47 48 44 52 5f 52 45 55 53 45   the PGHDR_REUSE
25e0: 5f 55 4e 4c 49 4b 45 4c 59 20 62 69 74 20 69 73  _UNLIKELY bit is
25f0: 20 73 65 74 2c 20 74 68 65 20 70 61 67 65 20 69   set, the page i
2600: 73 20 61 64 64 65 64 0a 2a 2a 20 74 6f 20 74 68  s added.** to th
2610: 65 20 65 6e 64 20 6f 66 20 74 68 65 20 4c 52 55  e end of the LRU
2620: 20 6c 69 73 74 20 73 6f 20 74 68 61 74 20 69 74   list so that it
2630: 20 77 69 6c 6c 20 62 65 20 74 68 65 20 6e 65 78   will be the nex
2640: 74 20 74 6f 20 62 65 20 72 65 63 79 63 6c 65 64  t to be recycled
2650: 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 76 6f 69 64  ..*/.static void
2660: 20 70 63 61 63 68 65 41 64 64 54 6f 4c 72 75 4c   pcacheAddToLruL
2670: 69 73 74 28 50 67 48 64 72 20 2a 70 50 61 67 65  ist(PgHdr *pPage
2680: 29 7b 0a 20 20 61 73 73 65 72 74 28 20 73 71 6c  ){.  assert( sql
2690: 69 74 65 33 5f 6d 75 74 65 78 5f 68 65 6c 64 28  ite3_mutex_held(
26a0: 70 63 61 63 68 65 2e 6d 75 74 65 78 29 20 29 3b  pcache.mutex) );
26b0: 0a 20 20 61 73 73 65 72 74 28 20 28 70 50 61 67  .  assert( (pPag
26c0: 65 2d 3e 66 6c 61 67 73 26 50 47 48 44 52 5f 44  e->flags&PGHDR_D
26d0: 49 52 54 59 29 3d 3d 30 20 29 3b 0a 20 20 69 66  IRTY)==0 );.  if
26e0: 28 20 70 50 61 67 65 2d 3e 70 43 61 63 68 65 2d  ( pPage->pCache-
26f0: 3e 62 50 75 72 67 65 61 62 6c 65 3d 3d 30 20 29  >bPurgeable==0 )
2700: 20 72 65 74 75 72 6e 3b 0a 20 20 69 66 28 20 70   return;.  if( p
2710: 63 61 63 68 65 2e 70 4c 72 75 54 61 69 6c 20 26  cache.pLruTail &
2720: 26 20 28 70 50 61 67 65 2d 3e 66 6c 61 67 73 20  & (pPage->flags 
2730: 26 20 50 47 48 44 52 5f 52 45 55 53 45 5f 55 4e  & PGHDR_REUSE_UN
2740: 4c 49 4b 45 4c 59 29 21 3d 30 20 29 7b 0a 20 20  LIKELY)!=0 ){.  
2750: 20 20 2f 2a 20 49 66 20 72 65 75 73 65 20 69 73    /* If reuse is
2760: 20 75 6e 6c 69 6b 65 6c 79 2e 20 20 50 75 74 20   unlikely.  Put 
2770: 74 68 65 20 70 61 67 65 20 61 74 20 74 68 65 20  the page at the 
2780: 65 6e 64 20 6f 66 20 74 68 65 20 4c 52 55 20 6c  end of the LRU l
2790: 69 73 74 0a 20 20 20 20 2a 2a 20 77 68 65 72 65  ist.    ** where
27a0: 20 69 74 20 77 69 6c 6c 20 62 65 20 72 65 63 79   it will be recy
27b0: 63 6c 65 64 20 73 6f 6f 6e 65 72 20 72 61 74 68  cled sooner rath
27c0: 65 72 20 74 68 61 6e 20 6c 61 74 65 72 2e 20 0a  er than later. .
27d0: 20 20 20 20 2a 2f 0a 20 20 20 20 61 73 73 65 72      */.    asser
27e0: 74 28 20 70 63 61 63 68 65 2e 70 4c 72 75 48 65  t( pcache.pLruHe
27f0: 61 64 20 29 3b 0a 20 20 20 20 70 50 61 67 65 2d  ad );.    pPage-
2800: 3e 70 4e 65 78 74 4c 72 75 20 3d 20 30 3b 0a 20  >pNextLru = 0;. 
2810: 20 20 20 70 50 61 67 65 2d 3e 70 50 72 65 76 4c     pPage->pPrevL
2820: 72 75 20 3d 20 70 63 61 63 68 65 2e 70 4c 72 75  ru = pcache.pLru
2830: 54 61 69 6c 3b 0a 20 20 20 20 70 63 61 63 68 65  Tail;.    pcache
2840: 2e 70 4c 72 75 54 61 69 6c 2d 3e 70 4e 65 78 74  .pLruTail->pNext
2850: 4c 72 75 20 3d 20 70 50 61 67 65 3b 0a 20 20 20  Lru = pPage;.   
2860: 20 70 63 61 63 68 65 2e 70 4c 72 75 54 61 69 6c   pcache.pLruTail
2870: 20 3d 20 70 50 61 67 65 3b 0a 20 20 20 20 70 50   = pPage;.    pP
2880: 61 67 65 2d 3e 66 6c 61 67 73 20 26 3d 20 7e 50  age->flags &= ~P
2890: 47 48 44 52 5f 52 45 55 53 45 5f 55 4e 4c 49 4b  GHDR_REUSE_UNLIK
28a0: 45 4c 59 3b 0a 20 20 7d 65 6c 73 65 7b 0a 20 20  ELY;.  }else{.  
28b0: 20 20 2f 2a 20 49 66 20 72 65 75 73 65 20 69 73    /* If reuse is
28c0: 20 70 6f 73 73 69 62 6c 65 2e 20 74 68 65 20 70   possible. the p
28d0: 61 67 65 20 67 6f 65 73 20 61 74 20 74 68 65 20  age goes at the 
28e0: 62 65 67 69 6e 6e 69 6e 67 20 6f 66 20 74 68 65  beginning of the
28f0: 20 4c 52 55 0a 20 20 20 20 2a 2a 20 6c 69 73 74   LRU.    ** list
2900: 20 73 6f 20 74 68 61 74 20 69 74 20 77 69 6c 6c   so that it will
2910: 20 62 65 20 74 68 65 20 6c 61 73 74 20 74 6f 20   be the last to 
2920: 62 65 20 72 65 63 79 63 6c 65 64 2e 0a 20 20 20  be recycled..   
2930: 20 2a 2f 0a 20 20 20 20 69 66 28 20 70 63 61 63   */.    if( pcac
2940: 68 65 2e 70 4c 72 75 48 65 61 64 20 29 7b 0a 20  he.pLruHead ){. 
2950: 20 20 20 20 20 70 63 61 63 68 65 2e 70 4c 72 75       pcache.pLru
2960: 48 65 61 64 2d 3e 70 50 72 65 76 4c 72 75 20 3d  Head->pPrevLru =
2970: 20 70 50 61 67 65 3b 0a 20 20 20 20 7d 0a 20 20   pPage;.    }.  
2980: 20 20 70 50 61 67 65 2d 3e 70 4e 65 78 74 4c 72    pPage->pNextLr
2990: 75 20 3d 20 70 63 61 63 68 65 2e 70 4c 72 75 48  u = pcache.pLruH
29a0: 65 61 64 3b 0a 20 20 20 20 70 63 61 63 68 65 2e  ead;.    pcache.
29b0: 70 4c 72 75 48 65 61 64 20 3d 20 70 50 61 67 65  pLruHead = pPage
29c0: 3b 0a 20 20 20 20 70 50 61 67 65 2d 3e 70 50 72  ;.    pPage->pPr
29d0: 65 76 4c 72 75 20 3d 20 30 3b 0a 20 20 20 20 69  evLru = 0;.    i
29e0: 66 28 20 70 63 61 63 68 65 2e 70 4c 72 75 54 61  f( pcache.pLruTa
29f0: 69 6c 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 70  il==0 ){.      p
2a00: 63 61 63 68 65 2e 70 4c 72 75 54 61 69 6c 20 3d  cache.pLruTail =
2a10: 20 70 50 61 67 65 3b 0a 20 20 20 20 7d 0a 20 20   pPage;.    }.  
2a20: 7d 0a 7d 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  }.}../**********
2a30: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
2a40: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
2a50: 2a 2a 2a 2a 2a 20 4d 65 6d 6f 72 79 20 41 6c 6c  ***** Memory All
2a60: 6f 63 61 74 69 6f 6e 20 2a 2a 2a 2a 2a 2a 2a 2a  ocation ********
2a70: 2a 2a 2a 0a 2a 2a 0a 2a 2a 20 49 6e 69 74 69 61  ***.**.** Initia
2a80: 6c 69 7a 65 20 74 68 65 20 70 61 67 65 20 63 61  lize the page ca
2a90: 63 68 65 20 6d 65 6d 6f 72 79 20 70 6f 6f 6c 2e  che memory pool.
2aa0: 0a 2a 2a 0a 2a 2a 20 54 68 69 73 20 6d 75 73 74  .**.** This must
2ab0: 20 62 65 20 63 61 6c 6c 65 64 20 61 74 20 73 74   be called at st
2ac0: 61 72 74 2d 74 69 6d 65 20 77 68 65 6e 20 6e 6f  art-time when no
2ad0: 20 70 61 67 65 20 63 61 63 68 65 20 6c 69 6e 65   page cache line
2ae0: 73 20 61 72 65 0a 2a 2a 20 63 68 65 63 6b 65 64  s are.** checked
2af0: 20 6f 75 74 2e 20 54 68 69 73 20 66 75 6e 63 74   out. This funct
2b00: 69 6f 6e 20 69 73 20 6e 6f 74 20 74 68 72 65 61  ion is not threa
2b10: 64 73 61 66 65 2e 0a 2a 2f 0a 76 6f 69 64 20 73  dsafe..*/.void s
2b20: 71 6c 69 74 65 33 50 43 61 63 68 65 42 75 66 66  qlite3PCacheBuff
2b30: 65 72 53 65 74 75 70 28 76 6f 69 64 20 2a 70 42  erSetup(void *pB
2b40: 75 66 2c 20 69 6e 74 20 73 7a 2c 20 69 6e 74 20  uf, int sz, int 
2b50: 6e 29 7b 0a 20 20 50 67 46 72 65 65 73 6c 6f 74  n){.  PgFreeslot
2b60: 20 2a 70 3b 0a 20 20 73 7a 20 26 3d 20 7e 37 3b   *p;.  sz &= ~7;
2b70: 0a 20 20 70 63 61 63 68 65 2e 73 7a 53 6c 6f 74  .  pcache.szSlot
2b80: 20 3d 20 73 7a 3b 0a 20 20 70 63 61 63 68 65 2e   = sz;.  pcache.
2b90: 70 53 74 61 72 74 20 3d 20 70 42 75 66 3b 0a 20  pStart = pBuf;. 
2ba0: 20 70 63 61 63 68 65 2e 70 46 72 65 65 20 3d 20   pcache.pFree = 
2bb0: 30 3b 0a 20 20 77 68 69 6c 65 28 20 6e 2d 2d 20  0;.  while( n-- 
2bc0: 29 7b 0a 20 20 20 20 70 20 3d 20 28 50 67 46 72  ){.    p = (PgFr
2bd0: 65 65 73 6c 6f 74 2a 29 70 42 75 66 3b 0a 20 20  eeslot*)pBuf;.  
2be0: 20 20 70 2d 3e 70 4e 65 78 74 20 3d 20 70 63 61    p->pNext = pca
2bf0: 63 68 65 2e 70 46 72 65 65 3b 0a 20 20 20 20 70  che.pFree;.    p
2c00: 63 61 63 68 65 2e 70 46 72 65 65 20 3d 20 70 3b  cache.pFree = p;
2c10: 0a 20 20 20 20 70 42 75 66 20 3d 20 28 76 6f 69  .    pBuf = (voi
2c20: 64 2a 29 26 28 28 63 68 61 72 2a 29 70 42 75 66  d*)&((char*)pBuf
2c30: 29 5b 73 7a 5d 3b 0a 20 20 7d 0a 20 20 70 63 61  )[sz];.  }.  pca
2c40: 63 68 65 2e 70 45 6e 64 20 3d 20 70 42 75 66 3b  che.pEnd = pBuf;
2c50: 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 41 6c 6c 6f 63 61  .}../*.** Alloca
2c60: 74 65 20 61 20 70 61 67 65 20 63 61 63 68 65 20  te a page cache 
2c70: 6c 69 6e 65 2e 20 20 4c 6f 6f 6b 20 69 6e 20 74  line.  Look in t
2c80: 68 65 20 70 61 67 65 20 63 61 63 68 65 20 6d 65  he page cache me
2c90: 6d 6f 72 79 20 70 6f 6f 6c 20 66 69 72 73 74 0a  mory pool first.
2ca0: 2a 2a 20 61 6e 64 20 75 73 65 20 61 6e 20 65 6c  ** and use an el
2cb0: 65 6d 65 6e 74 20 66 72 6f 6d 20 69 74 20 66 69  ement from it fi
2cc0: 72 73 74 20 69 66 20 61 76 61 69 6c 61 62 6c 65  rst if available
2cd0: 2e 20 20 49 66 20 6e 6f 74 68 69 6e 67 20 69 73  .  If nothing is
2ce0: 20 61 76 61 69 6c 61 62 6c 65 0a 2a 2a 20 69 6e   available.** in
2cf0: 20 74 68 65 20 70 61 67 65 20 63 61 63 68 65 20   the page cache 
2d00: 6d 65 6d 6f 72 79 20 70 6f 6f 6c 2c 20 67 6f 20  memory pool, go 
2d10: 74 6f 20 74 68 65 20 67 65 6e 65 72 61 6c 20 70  to the general p
2d20: 75 72 70 6f 73 65 20 6d 65 6d 6f 72 79 20 61 6c  urpose memory al
2d30: 6c 6f 63 61 74 6f 72 2e 0a 2a 2f 0a 76 6f 69 64  locator..*/.void
2d40: 20 2a 70 63 61 63 68 65 4d 61 6c 6c 6f 63 28 69   *pcacheMalloc(i
2d50: 6e 74 20 73 7a 2c 20 50 43 61 63 68 65 20 2a 70  nt sz, PCache *p
2d60: 43 61 63 68 65 29 7b 0a 20 20 61 73 73 65 72 74  Cache){.  assert
2d70: 28 20 73 71 6c 69 74 65 33 5f 6d 75 74 65 78 5f  ( sqlite3_mutex_
2d80: 68 65 6c 64 28 70 63 61 63 68 65 2e 6d 75 74 65  held(pcache.mute
2d90: 78 29 20 29 3b 0a 20 20 69 66 28 20 73 7a 3c 3d  x) );.  if( sz<=
2da0: 70 63 61 63 68 65 2e 73 7a 53 6c 6f 74 20 26 26  pcache.szSlot &&
2db0: 20 70 63 61 63 68 65 2e 70 46 72 65 65 20 29 7b   pcache.pFree ){
2dc0: 0a 20 20 20 20 50 67 46 72 65 65 73 6c 6f 74 20  .    PgFreeslot 
2dd0: 2a 70 20 3d 20 70 63 61 63 68 65 2e 70 46 72 65  *p = pcache.pFre
2de0: 65 3b 0a 20 20 20 20 70 63 61 63 68 65 2e 70 46  e;.    pcache.pF
2df0: 72 65 65 20 3d 20 70 2d 3e 70 4e 65 78 74 3b 0a  ree = p->pNext;.
2e00: 20 20 20 20 73 71 6c 69 74 65 33 53 74 61 74 75      sqlite3Statu
2e10: 73 53 65 74 28 53 51 4c 49 54 45 5f 53 54 41 54  sSet(SQLITE_STAT
2e20: 55 53 5f 50 41 47 45 43 41 43 48 45 5f 53 49 5a  US_PAGECACHE_SIZ
2e30: 45 2c 20 73 7a 29 3b 0a 20 20 20 20 73 71 6c 69  E, sz);.    sqli
2e40: 74 65 33 53 74 61 74 75 73 41 64 64 28 53 51 4c  te3StatusAdd(SQL
2e50: 49 54 45 5f 53 54 41 54 55 53 5f 50 41 47 45 43  ITE_STATUS_PAGEC
2e60: 41 43 48 45 5f 55 53 45 44 2c 20 31 29 3b 0a 20  ACHE_USED, 1);. 
2e70: 20 20 20 72 65 74 75 72 6e 20 28 76 6f 69 64 2a     return (void*
2e80: 29 70 3b 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20  )p;.  }else{.   
2e90: 20 76 6f 69 64 20 2a 70 3b 0a 0a 20 20 20 20 2f   void *p;..    /
2ea0: 2a 20 41 6c 6c 6f 63 61 74 65 20 61 20 6e 65 77  * Allocate a new
2eb0: 20 62 75 66 66 65 72 20 75 73 69 6e 67 20 73 71   buffer using sq
2ec0: 6c 69 74 65 33 4d 61 6c 6c 6f 63 2e 20 42 65 66  lite3Malloc. Bef
2ed0: 6f 72 65 20 64 6f 69 6e 67 20 73 6f 2c 20 65 78  ore doing so, ex
2ee0: 69 74 20 74 68 65 0a 20 20 20 20 2a 2a 20 67 6c  it the.    ** gl
2ef0: 6f 62 61 6c 20 70 63 61 63 68 65 20 6d 75 74 65  obal pcache mute
2f00: 78 20 61 6e 64 20 75 6e 6c 6f 63 6b 20 74 68 65  x and unlock the
2f10: 20 70 61 67 65 72 2d 63 61 63 68 65 20 6f 62 6a   pager-cache obj
2f20: 65 63 74 20 70 43 61 63 68 65 2e 20 54 68 69 73  ect pCache. This
2f30: 20 69 73 20 0a 20 20 20 20 2a 2a 20 73 6f 20 74   is .    ** so t
2f40: 68 61 74 20 69 66 20 74 68 65 20 61 74 74 65 6d  hat if the attem
2f50: 70 74 20 74 6f 20 61 6c 6c 6f 63 61 74 65 20 61  pt to allocate a
2f60: 20 6e 65 77 20 62 75 66 66 65 72 20 63 61 75 73   new buffer caus
2f70: 65 73 20 74 68 65 20 74 68 65 20 0a 20 20 20 20  es the the .    
2f80: 2a 2a 20 63 6f 6e 66 69 67 75 72 65 64 20 73 6f  ** configured so
2f90: 66 74 2d 68 65 61 70 2d 6c 69 6d 69 74 20 74 6f  ft-heap-limit to
2fa0: 20 62 65 20 62 72 65 61 63 68 65 64 2c 20 69 74   be breached, it
2fb0: 20 77 69 6c 6c 20 62 65 20 70 6f 73 73 69 62 6c   will be possibl
2fc0: 65 20 74 6f 0a 20 20 20 20 2a 2a 20 72 65 63 6c  e to.    ** recl
2fd0: 61 69 6d 20 6d 65 6d 6f 72 79 20 66 72 6f 6d 20  aim memory from 
2fe0: 74 68 69 73 20 70 61 67 65 72 2d 63 61 63 68 65  this pager-cache
2ff0: 2e 20 42 65 63 61 75 73 65 20 73 71 6c 69 74 65  . Because sqlite
3000: 33 50 63 61 63 68 65 4c 6f 63 6b 28 29 20 0a 20  3PcacheLock() . 
3010: 20 20 20 2a 2a 20 6d 69 67 68 74 20 62 6c 6f 63     ** might bloc
3020: 6b 20 6f 6e 20 74 68 65 20 4d 45 4d 32 20 6d 75  k on the MEM2 mu
3030: 74 65 78 2c 20 69 74 20 68 61 73 20 74 6f 20 62  tex, it has to b
3040: 65 20 63 61 6c 6c 65 64 20 62 65 66 6f 72 65 20  e called before 
3050: 72 65 2d 65 6e 74 65 72 69 6e 67 0a 20 20 20 20  re-entering.    
3060: 2a 2a 20 74 68 65 20 67 6c 6f 62 61 6c 20 4c 52  ** the global LR
3070: 55 20 6d 75 74 65 78 2e 0a 20 20 20 20 2a 2f 0a  U mutex..    */.
3080: 20 20 20 20 70 63 61 63 68 65 45 78 69 74 47 6c      pcacheExitGl
3090: 6f 62 61 6c 28 29 3b 0a 20 20 20 20 70 20 3d 20  obal();.    p = 
30a0: 73 71 6c 69 74 65 33 4d 61 6c 6c 6f 63 28 73 7a  sqlite3Malloc(sz
30b0: 29 3b 0a 20 20 20 20 70 63 61 63 68 65 45 6e 74  );.    pcacheEnt
30c0: 65 72 47 6c 6f 62 61 6c 28 29 3b 0a 0a 20 20 20  erGlobal();..   
30d0: 20 69 66 28 20 70 20 29 7b 0a 20 20 20 20 20 20   if( p ){.      
30e0: 73 7a 20 3d 20 73 71 6c 69 74 65 33 4d 61 6c 6c  sz = sqlite3Mall
30f0: 6f 63 53 69 7a 65 28 70 29 3b 0a 20 20 20 20 20  ocSize(p);.     
3100: 20 73 71 6c 69 74 65 33 53 74 61 74 75 73 41 64   sqlite3StatusAd
3110: 64 28 53 51 4c 49 54 45 5f 53 54 41 54 55 53 5f  d(SQLITE_STATUS_
3120: 50 41 47 45 43 41 43 48 45 5f 4f 56 45 52 46 4c  PAGECACHE_OVERFL
3130: 4f 57 2c 20 73 7a 29 3b 0a 20 20 20 20 7d 0a 20  OW, sz);.    }. 
3140: 20 20 20 72 65 74 75 72 6e 20 70 3b 0a 20 20 7d     return p;.  }
3150: 0a 7d 0a 76 6f 69 64 20 2a 73 71 6c 69 74 65 33  .}.void *sqlite3
3160: 50 61 67 65 4d 61 6c 6c 6f 63 28 73 7a 29 7b 0a  PageMalloc(sz){.
3170: 20 20 76 6f 69 64 20 2a 70 3b 0a 20 20 70 63 61    void *p;.  pca
3180: 63 68 65 45 6e 74 65 72 47 6c 6f 62 61 6c 28 29  cheEnterGlobal()
3190: 3b 0a 20 20 70 20 3d 20 70 63 61 63 68 65 4d 61  ;.  p = pcacheMa
31a0: 6c 6c 6f 63 28 73 7a 2c 20 30 29 3b 0a 20 20 70  lloc(sz, 0);.  p
31b0: 63 61 63 68 65 45 78 69 74 47 6c 6f 62 61 6c 28  cacheExitGlobal(
31c0: 29 3b 0a 20 20 72 65 74 75 72 6e 20 70 3b 0a 7d  );.  return p;.}
31d0: 0a 0a 2f 2a 0a 2a 2a 20 52 65 6c 65 61 73 65 20  ../*.** Release 
31e0: 61 20 70 61 67 65 72 20 6d 65 6d 6f 72 79 20 61  a pager memory a
31f0: 6c 6c 6f 63 61 74 69 6f 6e 0a 2a 2f 0a 76 6f 69  llocation.*/.voi
3200: 64 20 70 63 61 63 68 65 46 72 65 65 28 76 6f 69  d pcacheFree(voi
3210: 64 20 2a 70 29 7b 0a 20 20 61 73 73 65 72 74 28  d *p){.  assert(
3220: 20 73 71 6c 69 74 65 33 5f 6d 75 74 65 78 5f 68   sqlite3_mutex_h
3230: 65 6c 64 28 70 63 61 63 68 65 2e 6d 75 74 65 78  eld(pcache.mutex
3240: 29 20 29 3b 0a 20 20 69 66 28 20 70 3d 3d 30 20  ) );.  if( p==0 
3250: 29 20 72 65 74 75 72 6e 3b 0a 20 20 69 66 28 20  ) return;.  if( 
3260: 70 3e 3d 70 63 61 63 68 65 2e 70 53 74 61 72 74  p>=pcache.pStart
3270: 20 26 26 20 70 3c 70 63 61 63 68 65 2e 70 45 6e   && p<pcache.pEn
3280: 64 20 29 7b 0a 20 20 20 20 50 67 46 72 65 65 73  d ){.    PgFrees
3290: 6c 6f 74 20 2a 70 53 6c 6f 74 3b 0a 20 20 20 20  lot *pSlot;.    
32a0: 73 71 6c 69 74 65 33 53 74 61 74 75 73 41 64 64  sqlite3StatusAdd
32b0: 28 53 51 4c 49 54 45 5f 53 54 41 54 55 53 5f 50  (SQLITE_STATUS_P
32c0: 41 47 45 43 41 43 48 45 5f 55 53 45 44 2c 20 2d  AGECACHE_USED, -
32d0: 31 29 3b 0a 20 20 20 20 70 53 6c 6f 74 20 3d 20  1);.    pSlot = 
32e0: 28 50 67 46 72 65 65 73 6c 6f 74 2a 29 70 3b 0a  (PgFreeslot*)p;.
32f0: 20 20 20 20 70 53 6c 6f 74 2d 3e 70 4e 65 78 74      pSlot->pNext
3300: 20 3d 20 70 63 61 63 68 65 2e 70 46 72 65 65 3b   = pcache.pFree;
3310: 0a 20 20 20 20 70 63 61 63 68 65 2e 70 46 72 65  .    pcache.pFre
3320: 65 20 3d 20 70 53 6c 6f 74 3b 0a 20 20 7d 65 6c  e = pSlot;.  }el
3330: 73 65 7b 0a 20 20 20 20 69 6e 74 20 69 53 69 7a  se{.    int iSiz
3340: 65 20 3d 20 73 71 6c 69 74 65 33 4d 61 6c 6c 6f  e = sqlite3Mallo
3350: 63 53 69 7a 65 28 70 29 3b 0a 20 20 20 20 73 71  cSize(p);.    sq
3360: 6c 69 74 65 33 53 74 61 74 75 73 41 64 64 28 53  lite3StatusAdd(S
3370: 51 4c 49 54 45 5f 53 54 41 54 55 53 5f 50 41 47  QLITE_STATUS_PAG
3380: 45 43 41 43 48 45 5f 4f 56 45 52 46 4c 4f 57 2c  ECACHE_OVERFLOW,
3390: 20 2d 69 53 69 7a 65 29 3b 0a 20 20 20 20 73 71   -iSize);.    sq
33a0: 6c 69 74 65 33 5f 66 72 65 65 28 70 29 3b 0a 20  lite3_free(p);. 
33b0: 20 7d 0a 7d 0a 76 6f 69 64 20 73 71 6c 69 74 65   }.}.void sqlite
33c0: 33 50 61 67 65 46 72 65 65 28 76 6f 69 64 20 2a  3PageFree(void *
33d0: 70 29 7b 0a 20 20 70 63 61 63 68 65 45 6e 74 65  p){.  pcacheEnte
33e0: 72 47 6c 6f 62 61 6c 28 29 3b 0a 20 20 70 63 61  rGlobal();.  pca
33f0: 63 68 65 46 72 65 65 28 70 29 3b 0a 20 20 70 63  cheFree(p);.  pc
3400: 61 63 68 65 45 78 69 74 47 6c 6f 62 61 6c 28 29  acheExitGlobal()
3410: 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 41 6c 6c 6f 63  ;.}../*.** Alloc
3420: 61 74 65 20 61 20 6e 65 77 20 70 61 67 65 2e 0a  ate a new page..
3430: 2a 2f 0a 73 74 61 74 69 63 20 50 67 48 64 72 20  */.static PgHdr 
3440: 2a 70 63 61 63 68 65 50 61 67 65 41 6c 6c 6f 63  *pcachePageAlloc
3450: 28 50 43 61 63 68 65 20 2a 70 43 61 63 68 65 29  (PCache *pCache)
3460: 7b 0a 20 20 50 67 48 64 72 20 2a 70 3b 0a 20 20  {.  PgHdr *p;.  
3470: 69 6e 74 20 73 7a 20 3d 20 73 69 7a 65 6f 66 28  int sz = sizeof(
3480: 2a 70 29 20 2b 20 70 43 61 63 68 65 2d 3e 73 7a  *p) + pCache->sz
3490: 50 61 67 65 20 2b 20 70 43 61 63 68 65 2d 3e 73  Page + pCache->s
34a0: 7a 45 78 74 72 61 3b 0a 20 20 61 73 73 65 72 74  zExtra;.  assert
34b0: 28 20 73 71 6c 69 74 65 33 5f 6d 75 74 65 78 5f  ( sqlite3_mutex_
34c0: 68 65 6c 64 28 70 63 61 63 68 65 2e 6d 75 74 65  held(pcache.mute
34d0: 78 29 20 29 3b 0a 20 20 70 20 3d 20 70 63 61 63  x) );.  p = pcac
34e0: 68 65 4d 61 6c 6c 6f 63 28 73 7a 2c 20 70 43 61  heMalloc(sz, pCa
34f0: 63 68 65 29 3b 0a 20 20 69 66 28 20 70 3d 3d 30  che);.  if( p==0
3500: 20 29 20 72 65 74 75 72 6e 20 30 3b 0a 20 20 6d   ) return 0;.  m
3510: 65 6d 73 65 74 28 70 2c 20 30 2c 20 73 69 7a 65  emset(p, 0, size
3520: 6f 66 28 50 67 48 64 72 29 29 3b 0a 20 20 70 2d  of(PgHdr));.  p-
3530: 3e 70 44 61 74 61 20 3d 20 28 76 6f 69 64 2a 29  >pData = (void*)
3540: 26 70 5b 31 5d 3b 0a 20 20 70 2d 3e 70 45 78 74  &p[1];.  p->pExt
3550: 72 61 20 3d 20 28 76 6f 69 64 2a 29 26 28 28 63  ra = (void*)&((c
3560: 68 61 72 2a 29 70 2d 3e 70 44 61 74 61 29 5b 70  har*)p->pData)[p
3570: 43 61 63 68 65 2d 3e 73 7a 50 61 67 65 5d 3b 0a  Cache->szPage];.
3580: 20 20 69 66 28 20 70 43 61 63 68 65 2d 3e 62 50    if( pCache->bP
3590: 75 72 67 65 61 62 6c 65 20 29 7b 0a 20 20 20 20  urgeable ){.    
35a0: 70 63 61 63 68 65 2e 6e 43 75 72 72 65 6e 74 50  pcache.nCurrentP
35b0: 61 67 65 2b 2b 3b 0a 20 20 7d 0a 20 20 72 65 74  age++;.  }.  ret
35c0: 75 72 6e 20 70 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20  urn p;.}../*.** 
35d0: 44 65 61 6c 6c 6f 63 61 74 65 20 61 20 70 61 67  Deallocate a pag
35e0: 65 0a 2a 2f 0a 73 74 61 74 69 63 20 76 6f 69 64  e.*/.static void
35f0: 20 70 63 61 63 68 65 50 61 67 65 46 72 65 65 28   pcachePageFree(
3600: 50 67 48 64 72 20 2a 70 29 7b 0a 20 20 61 73 73  PgHdr *p){.  ass
3610: 65 72 74 28 20 73 71 6c 69 74 65 33 5f 6d 75 74  ert( sqlite3_mut
3620: 65 78 5f 68 65 6c 64 28 70 63 61 63 68 65 2e 6d  ex_held(pcache.m
3630: 75 74 65 78 29 20 29 3b 0a 20 20 69 66 28 20 70  utex) );.  if( p
3640: 2d 3e 70 43 61 63 68 65 2d 3e 62 50 75 72 67 65  ->pCache->bPurge
3650: 61 62 6c 65 20 29 7b 0a 20 20 20 20 70 63 61 63  able ){.    pcac
3660: 68 65 2e 6e 43 75 72 72 65 6e 74 50 61 67 65 2d  he.nCurrentPage-
3670: 2d 3b 0a 20 20 7d 0a 20 20 70 63 61 63 68 65 46  -;.  }.  pcacheF
3680: 72 65 65 28 70 2d 3e 61 70 53 61 76 65 5b 30 5d  ree(p->apSave[0]
3690: 29 3b 0a 20 20 70 63 61 63 68 65 46 72 65 65 28  );.  pcacheFree(
36a0: 70 2d 3e 61 70 53 61 76 65 5b 31 5d 29 3b 0a 20  p->apSave[1]);. 
36b0: 20 70 63 61 63 68 65 46 72 65 65 28 70 29 3b 0a   pcacheFree(p);.
36c0: 7d 0a 0a 23 69 66 64 65 66 20 53 51 4c 49 54 45  }..#ifdef SQLITE
36d0: 5f 45 4e 41 42 4c 45 5f 4d 45 4d 4f 52 59 5f 4d  _ENABLE_MEMORY_M
36e0: 41 4e 41 47 45 4d 45 4e 54 0a 2f 2a 0a 2a 2a 20  ANAGEMENT./*.** 
36f0: 52 65 74 75 72 6e 20 74 68 65 20 6e 75 6d 62 65  Return the numbe
3700: 72 20 6f 66 20 62 79 74 65 73 20 74 68 61 74 20  r of bytes that 
3710: 77 69 6c 6c 20 62 65 20 72 65 74 75 72 6e 65 64  will be returned
3720: 20 74 6f 20 74 68 65 20 68 65 61 70 20 77 68 65   to the heap whe
3730: 6e 0a 2a 2a 20 74 68 65 20 61 72 67 75 6d 65 6e  n.** the argumen
3740: 74 20 69 73 20 70 61 73 73 65 64 20 74 6f 20 70  t is passed to p
3750: 63 61 63 68 65 50 61 67 65 46 72 65 65 28 29 2e  cachePageFree().
3760: 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 70  .*/.static int p
3770: 63 61 63 68 65 50 61 67 65 53 69 7a 65 28 50 67  cachePageSize(Pg
3780: 48 64 72 20 2a 70 29 7b 0a 20 20 61 73 73 65 72  Hdr *p){.  asser
3790: 74 28 20 73 71 6c 69 74 65 33 5f 6d 75 74 65 78  t( sqlite3_mutex
37a0: 5f 68 65 6c 64 28 70 63 61 63 68 65 2e 6d 75 74  _held(pcache.mut
37b0: 65 78 29 20 29 3b 0a 20 20 61 73 73 65 72 74 28  ex) );.  assert(
37c0: 20 21 70 63 61 63 68 65 2e 70 53 74 61 72 74 20   !pcache.pStart 
37d0: 29 3b 0a 20 20 61 73 73 65 72 74 28 20 70 2d 3e  );.  assert( p->
37e0: 61 70 53 61 76 65 5b 30 5d 3d 3d 30 20 29 3b 0a  apSave[0]==0 );.
37f0: 20 20 61 73 73 65 72 74 28 20 70 2d 3e 61 70 53    assert( p->apS
3800: 61 76 65 5b 31 5d 3d 3d 30 20 29 3b 0a 20 20 61  ave[1]==0 );.  a
3810: 73 73 65 72 74 28 20 70 20 26 26 20 70 2d 3e 70  ssert( p && p->p
3820: 43 61 63 68 65 20 29 3b 0a 20 20 72 65 74 75 72  Cache );.  retur
3830: 6e 20 73 71 6c 69 74 65 33 4d 61 6c 6c 6f 63 53  n sqlite3MallocS
3840: 69 7a 65 28 70 29 3b 0a 7d 0a 23 65 6e 64 69 66  ize(p);.}.#endif
3850: 0a 0a 2f 2a 0a 2a 2a 20 41 74 74 65 6d 70 74 20  ../*.** Attempt 
3860: 74 6f 20 27 72 65 63 79 63 6c 65 27 20 61 20 70  to 'recycle' a p
3870: 61 67 65 20 66 72 6f 6d 20 74 68 65 20 67 6c 6f  age from the glo
3880: 62 61 6c 20 4c 52 55 20 6c 69 73 74 2e 20 4f 6e  bal LRU list. On
3890: 6c 79 20 63 6c 65 61 6e 2c 0a 2a 2a 20 75 6e 72  ly clean,.** unr
38a0: 65 66 65 72 65 6e 63 65 64 20 70 61 67 65 73 20  eferenced pages 
38b0: 66 72 6f 6d 20 70 75 72 67 65 61 62 6c 65 20 63  from purgeable c
38c0: 61 63 68 65 73 20 61 72 65 20 65 6c 69 67 69 62  aches are eligib
38d0: 6c 65 20 66 6f 72 20 72 65 63 79 63 6c 69 6e 67  le for recycling
38e0: 2e 0a 2a 2a 0a 2a 2a 20 54 68 69 73 20 66 75 6e  ..**.** This fun
38f0: 63 74 69 6f 6e 20 72 65 6d 6f 76 65 73 20 70 61  ction removes pa
3900: 67 65 20 70 63 61 63 68 65 2e 70 4c 72 75 54 61  ge pcache.pLruTa
3910: 69 6c 20 66 72 6f 6d 20 74 68 65 20 67 6c 6f 62  il from the glob
3920: 61 6c 20 4c 52 55 20 6c 69 73 74 2c 0a 2a 2a 20  al LRU list,.** 
3930: 61 6e 64 20 66 72 6f 6d 20 74 68 65 20 68 61 73  and from the has
3940: 68 2d 74 61 62 6c 65 20 61 6e 64 20 50 43 61 63  h-table and PCac
3950: 68 65 2e 70 43 6c 65 61 6e 20 6c 69 73 74 20 6f  he.pClean list o
3960: 66 20 74 68 65 20 6f 77 6e 65 72 20 70 63 61 63  f the owner pcac
3970: 68 65 2e 0a 2a 2a 20 54 68 65 72 65 20 73 68 6f  he..** There sho
3980: 75 6c 64 20 62 65 20 6e 6f 20 6f 74 68 65 72 20  uld be no other 
3990: 72 65 66 65 72 65 6e 63 65 73 20 74 6f 20 74 68  references to th
39a0: 65 20 70 61 67 65 2e 0a 2a 2a 0a 2a 2a 20 41 20  e page..**.** A 
39b0: 70 6f 69 6e 74 65 72 20 74 6f 20 74 68 65 20 72  pointer to the r
39c0: 65 63 79 63 6c 65 64 20 70 61 67 65 20 69 73 20  ecycled page is 
39d0: 72 65 74 75 72 6e 65 64 2c 20 6f 72 20 4e 55 4c  returned, or NUL
39e0: 4c 20 69 66 20 6e 6f 20 70 61 67 65 20 69 73 0a  L if no page is.
39f0: 2a 2a 20 65 6c 69 67 69 62 6c 65 20 66 6f 72 20  ** eligible for 
3a00: 72 65 63 79 63 6c 69 6e 67 2e 0a 2a 2f 0a 73 74  recycling..*/.st
3a10: 61 74 69 63 20 50 67 48 64 72 20 2a 70 63 61 63  atic PgHdr *pcac
3a20: 68 65 52 65 63 79 63 6c 65 50 61 67 65 28 29 7b  heRecyclePage(){
3a30: 0a 20 20 50 67 48 64 72 20 2a 70 20 3d 20 30 3b  .  PgHdr *p = 0;
3a40: 0a 20 20 61 73 73 65 72 74 28 20 73 71 6c 69 74  .  assert( sqlit
3a50: 65 33 5f 6d 75 74 65 78 5f 68 65 6c 64 28 70 63  e3_mutex_held(pc
3a60: 61 63 68 65 2e 6d 75 74 65 78 29 20 29 3b 0a 0a  ache.mutex) );..
3a70: 20 20 69 66 28 20 28 70 3d 70 63 61 63 68 65 2e    if( (p=pcache.
3a80: 70 4c 72 75 54 61 69 6c 29 20 29 7b 0a 20 20 20  pLruTail) ){.   
3a90: 20 61 73 73 65 72 74 28 20 28 70 2d 3e 66 6c 61   assert( (p->fla
3aa0: 67 73 26 50 47 48 44 52 5f 44 49 52 54 59 29 3d  gs&PGHDR_DIRTY)=
3ab0: 3d 30 20 29 3b 0a 20 20 20 20 70 63 61 63 68 65  =0 );.    pcache
3ac0: 52 65 6d 6f 76 65 46 72 6f 6d 4c 72 75 4c 69 73  RemoveFromLruLis
3ad0: 74 28 70 29 3b 0a 20 20 20 20 70 63 61 63 68 65  t(p);.    pcache
3ae0: 52 65 6d 6f 76 65 46 72 6f 6d 48 61 73 68 28 70  RemoveFromHash(p
3af0: 29 3b 0a 20 20 20 20 70 63 61 63 68 65 52 65 6d  );.    pcacheRem
3b00: 6f 76 65 46 72 6f 6d 4c 69 73 74 28 26 70 2d 3e  oveFromList(&p->
3b10: 70 43 61 63 68 65 2d 3e 70 43 6c 65 61 6e 2c 20  pCache->pClean, 
3b20: 70 29 3b 0a 0a 20 20 20 20 2f 2a 20 49 66 20 74  p);..    /* If t
3b30: 68 65 20 61 6c 77 61 79 73 2d 72 6f 6c 6c 62 61  he always-rollba
3b40: 63 6b 20 66 6c 61 67 20 69 73 20 73 65 74 20 6f  ck flag is set o
3b50: 6e 20 74 68 65 20 70 61 67 65 20 62 65 69 6e 67  n the page being
3b60: 20 72 65 63 79 63 6c 65 64 2c 20 73 65 74 20 0a   recycled, set .
3b70: 20 20 20 20 2a 2a 20 74 68 65 20 61 6c 77 61 79      ** the alway
3b80: 73 2d 72 6f 6c 6c 62 61 63 6b 20 66 6c 61 67 20  s-rollback flag 
3b90: 6f 6e 20 74 68 65 20 63 6f 72 72 65 73 70 6f 6e  on the correspon
3ba0: 64 69 6e 67 20 70 61 67 65 72 2e 20 54 4f 44 4f  ding pager. TODO
3bb0: 3a 20 54 68 69 73 20 69 73 0a 20 20 20 20 2a 2a  : This is.    **
3bc0: 20 61 20 74 68 72 65 61 64 2d 73 61 66 65 74 79   a thread-safety
3bd0: 20 70 72 6f 62 6c 65 6d 2e 0a 20 20 20 20 2a 2f   problem..    */
3be0: 0a 20 20 20 20 69 66 28 20 70 2d 3e 66 6c 61 67  .    if( p->flag
3bf0: 73 26 50 47 48 44 52 5f 41 4c 57 41 59 53 5f 52  s&PGHDR_ALWAYS_R
3c00: 4f 4c 4c 42 41 43 4b 20 29 7b 0a 20 20 20 20 20  OLLBACK ){.     
3c10: 20 61 73 73 65 72 74 28 70 2d 3e 70 50 61 67 65   assert(p->pPage
3c20: 72 29 3b 0a 20 20 20 20 20 20 73 71 6c 69 74 65  r);.      sqlite
3c30: 33 50 61 67 65 72 41 6c 77 61 79 73 52 6f 6c 6c  3PagerAlwaysRoll
3c40: 62 61 63 6b 28 70 2d 3e 70 50 61 67 65 72 29 3b  back(p->pPager);
3c50: 0a 20 20 20 20 7d 0a 20 20 7d 0a 0a 20 20 72 65  .    }.  }..  re
3c60: 74 75 72 6e 20 70 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a  turn p;.}../*.**
3c70: 20 4f 62 74 61 69 6e 20 73 70 61 63 65 20 66 6f   Obtain space fo
3c80: 72 20 61 20 70 61 67 65 2e 20 54 72 79 20 74 6f  r a page. Try to
3c90: 20 72 65 63 79 63 6c 65 20 61 6e 20 6f 6c 64 20   recycle an old 
3ca0: 70 61 67 65 20 69 66 20 74 68 65 20 6c 69 6d 69  page if the limi
3cb0: 74 20 6f 6e 20 74 68 65 20 0a 2a 2a 20 6e 75 6d  t on the .** num
3cc0: 62 65 72 20 6f 66 20 70 61 67 65 73 20 68 61 73  ber of pages has
3cd0: 20 62 65 65 6e 20 72 65 61 63 68 65 64 2e 20 49   been reached. I
3ce0: 66 20 74 68 65 20 6c 69 6d 69 74 20 68 61 73 20  f the limit has 
3cf0: 6e 6f 74 20 62 65 65 6e 20 72 65 61 63 68 65 64  not been reached
3d00: 20 6f 72 0a 2a 2a 20 74 68 65 72 65 20 61 72 65   or.** there are
3d10: 20 6e 6f 20 70 61 67 65 73 20 65 6c 69 67 69 62   no pages eligib
3d20: 6c 65 20 66 6f 72 20 72 65 63 79 63 6c 69 6e 67  le for recycling
3d30: 2c 20 61 6c 6c 6f 63 61 74 65 20 61 20 6e 65 77  , allocate a new
3d40: 20 70 61 67 65 2e 0a 2a 2a 0a 2a 2a 20 52 65 74   page..**.** Ret
3d50: 75 72 6e 20 61 20 70 6f 69 6e 74 65 72 20 74 6f  urn a pointer to
3d60: 20 74 68 65 20 6e 65 77 20 70 61 67 65 2c 20 6f   the new page, o
3d70: 72 20 4e 55 4c 4c 20 69 66 20 61 6e 20 4f 4f 4d  r NULL if an OOM
3d80: 20 63 6f 6e 64 69 74 69 6f 6e 20 6f 63 63 75 72   condition occur
3d90: 73 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 50 67 48  s..*/.static PgH
3da0: 64 72 20 2a 70 63 61 63 68 65 52 65 63 79 63 6c  dr *pcacheRecycl
3db0: 65 4f 72 41 6c 6c 6f 63 28 50 43 61 63 68 65 20  eOrAlloc(PCache 
3dc0: 2a 70 43 61 63 68 65 29 7b 0a 20 20 50 67 48 64  *pCache){.  PgHd
3dd0: 72 20 2a 70 20 3d 20 30 3b 0a 0a 20 20 69 6e 74  r *p = 0;..  int
3de0: 20 73 7a 50 61 67 65 20 3d 20 70 43 61 63 68 65   szPage = pCache
3df0: 2d 3e 73 7a 50 61 67 65 3b 0a 20 20 69 6e 74 20  ->szPage;.  int 
3e00: 73 7a 45 78 74 72 61 20 3d 20 70 43 61 63 68 65  szExtra = pCache
3e10: 2d 3e 73 7a 45 78 74 72 61 3b 0a 0a 20 20 61 73  ->szExtra;..  as
3e20: 73 65 72 74 28 20 70 63 61 63 68 65 2e 69 73 49  sert( pcache.isI
3e30: 6e 69 74 20 29 3b 0a 20 20 61 73 73 65 72 74 28  nit );.  assert(
3e40: 20 73 71 6c 69 74 65 33 5f 6d 75 74 65 78 5f 6e   sqlite3_mutex_n
3e50: 6f 74 68 65 6c 64 28 70 63 61 63 68 65 2e 6d 75  otheld(pcache.mu
3e60: 74 65 78 29 20 29 3b 0a 0a 20 20 70 63 61 63 68  tex) );..  pcach
3e70: 65 45 6e 74 65 72 47 6c 6f 62 61 6c 28 29 3b 0a  eEnterGlobal();.
3e80: 0a 20 20 2f 2a 20 49 66 20 77 65 20 68 61 76 65  .  /* If we have
3e90: 20 72 65 61 63 68 65 64 20 74 68 65 20 6c 69 6d   reached the lim
3ea0: 69 74 20 66 6f 72 20 70 69 6e 6e 65 64 2f 64 69  it for pinned/di
3eb0: 72 74 79 20 70 61 67 65 73 2c 20 61 6e 64 20 74  rty pages, and t
3ec0: 68 65 72 65 20 69 73 20 61 74 0a 20 20 2a 2a 20  here is at.  ** 
3ed0: 6c 65 61 73 74 20 6f 6e 65 20 64 69 72 74 79 20  least one dirty 
3ee0: 70 61 67 65 2c 20 69 6e 76 6f 6b 65 20 74 68 65  page, invoke the
3ef0: 20 78 53 74 72 65 73 73 20 63 61 6c 6c 62 61 63   xStress callbac
3f00: 6b 20 74 6f 20 63 61 75 73 65 20 61 20 70 61 67  k to cause a pag
3f10: 65 20 74 6f 0a 20 20 2a 2a 20 62 65 63 6f 6d 65  e to.  ** become
3f20: 20 63 6c 65 61 6e 2e 0a 20 20 2a 2f 0a 20 20 61   clean..  */.  a
3f30: 73 73 65 72 74 28 20 70 43 61 63 68 65 2d 3e 6e  ssert( pCache->n
3f40: 50 69 6e 6e 65 64 3d 3d 70 63 61 63 68 65 50 69  Pinned==pcachePi
3f50: 6e 6e 65 64 43 6f 75 6e 74 28 70 43 61 63 68 65  nnedCount(pCache
3f60: 29 20 29 3b 0a 20 20 61 73 73 65 72 74 28 20 70  ) );.  assert( p
3f70: 63 61 63 68 65 43 68 65 63 6b 53 79 6e 63 65 64  cacheCheckSynced
3f80: 28 70 43 61 63 68 65 29 20 29 3b 0a 20 20 69 66  (pCache) );.  if
3f90: 28 20 70 43 61 63 68 65 2d 3e 78 53 74 72 65 73  ( pCache->xStres
3fa0: 73 0a 20 20 20 26 26 20 70 43 61 63 68 65 2d 3e  s.   && pCache->
3fb0: 70 44 69 72 74 79 0a 20 20 20 26 26 20 70 43 61  pDirty.   && pCa
3fc0: 63 68 65 2d 3e 6e 50 69 6e 6e 65 64 3e 3d 28 70  che->nPinned>=(p
3fd0: 63 61 63 68 65 2e 6e 4d 61 78 50 61 67 65 2b 70  cache.nMaxPage+p
3fe0: 43 61 63 68 65 2d 3e 6e 4d 69 6e 2d 70 63 61 63  Cache->nMin-pcac
3ff0: 68 65 2e 6e 4d 69 6e 50 61 67 65 29 0a 20 20 29  he.nMinPage).  )
4000: 7b 0a 20 20 20 20 50 67 48 64 72 20 2a 70 50 67  {.    PgHdr *pPg
4010: 3b 0a 20 20 20 20 61 73 73 65 72 74 28 70 43 61  ;.    assert(pCa
4020: 63 68 65 2d 3e 70 44 69 72 74 79 54 61 69 6c 29  che->pDirtyTail)
4030: 3b 0a 0a 20 20 20 20 66 6f 72 28 70 50 67 3d 70  ;..    for(pPg=p
4040: 43 61 63 68 65 2d 3e 70 53 79 6e 63 65 64 3b 20  Cache->pSynced; 
4050: 0a 20 20 20 20 20 20 20 20 70 50 67 20 26 26 20  .        pPg && 
4060: 28 70 50 67 2d 3e 6e 52 65 66 20 7c 7c 20 28 70  (pPg->nRef || (p
4070: 50 67 2d 3e 66 6c 61 67 73 26 50 47 48 44 52 5f  Pg->flags&PGHDR_
4080: 4e 45 45 44 5f 53 59 4e 43 29 29 3b 20 0a 20 20  NEED_SYNC)); .  
4090: 20 20 20 20 20 20 70 50 67 3d 70 50 67 2d 3e 70        pPg=pPg->p
40a0: 50 72 65 76 0a 20 20 20 20 29 3b 0a 20 20 20 20  Prev.    );.    
40b0: 69 66 28 20 21 70 50 67 20 29 7b 0a 20 20 20 20  if( !pPg ){.    
40c0: 20 20 66 6f 72 28 70 50 67 3d 70 43 61 63 68 65    for(pPg=pCache
40d0: 2d 3e 70 44 69 72 74 79 54 61 69 6c 3b 20 70 50  ->pDirtyTail; pP
40e0: 67 20 26 26 20 70 50 67 2d 3e 6e 52 65 66 3b 20  g && pPg->nRef; 
40f0: 70 50 67 3d 70 50 67 2d 3e 70 50 72 65 76 29 3b  pPg=pPg->pPrev);
4100: 0a 20 20 20 20 7d 0a 20 20 20 20 69 66 28 20 70  .    }.    if( p
4110: 50 67 20 29 7b 0a 20 20 20 20 20 20 70 63 61 63  Pg ){.      pcac
4120: 68 65 45 78 69 74 47 6c 6f 62 61 6c 28 29 3b 0a  heExitGlobal();.
4130: 20 20 20 20 20 20 70 43 61 63 68 65 2d 3e 78 53        pCache->xS
4140: 74 72 65 73 73 28 70 43 61 63 68 65 2d 3e 70 53  tress(pCache->pS
4150: 74 72 65 73 73 2c 20 70 50 67 29 3b 0a 20 20 20  tress, pPg);.   
4160: 20 20 20 70 63 61 63 68 65 45 6e 74 65 72 47 6c     pcacheEnterGl
4170: 6f 62 61 6c 28 29 3b 0a 20 20 20 20 7d 0a 20 20  obal();.    }.  
4180: 7d 0a 0a 20 20 2f 2a 20 49 66 20 74 68 65 20 67  }..  /* If the g
4190: 6c 6f 62 61 6c 20 70 61 67 65 20 6c 69 6d 69 74  lobal page limit
41a0: 20 68 61 73 20 62 65 65 6e 20 72 65 61 63 68 65   has been reache
41b0: 64 2c 20 74 72 79 20 74 6f 20 72 65 63 79 63 6c  d, try to recycl
41c0: 65 20 61 20 70 61 67 65 2e 20 2a 2f 0a 20 20 69  e a page. */.  i
41d0: 66 28 20 70 63 61 63 68 65 2e 6e 43 75 72 72 65  f( pcache.nCurre
41e0: 6e 74 50 61 67 65 3e 3d 70 63 61 63 68 65 2e 6e  ntPage>=pcache.n
41f0: 4d 61 78 50 61 67 65 20 29 7b 0a 20 20 20 20 70  MaxPage ){.    p
4200: 20 3d 20 70 63 61 63 68 65 52 65 63 79 63 6c 65   = pcacheRecycle
4210: 50 61 67 65 28 29 3b 0a 20 20 7d 0a 0a 20 20 2f  Page();.  }..  /
4220: 2a 20 49 66 20 61 20 70 61 67 65 20 68 61 73 20  * If a page has 
4230: 62 65 65 6e 20 72 65 63 79 63 6c 65 64 20 62 75  been recycled bu
4240: 74 20 69 74 20 69 73 20 74 68 65 20 77 72 6f 6e  t it is the wron
4250: 67 20 73 69 7a 65 2c 20 66 72 65 65 20 69 74 2e  g size, free it.
4260: 20 2a 2f 0a 20 20 69 66 28 20 70 20 26 26 20 28   */.  if( p && (
4270: 70 2d 3e 70 43 61 63 68 65 2d 3e 73 7a 50 61 67  p->pCache->szPag
4280: 65 21 3d 73 7a 50 61 67 65 20 7c 7c 20 70 2d 3e  e!=szPage || p->
4290: 70 43 61 63 68 65 2d 3e 73 7a 45 78 74 72 61 21  pCache->szExtra!
42a0: 3d 73 7a 45 78 74 72 61 29 20 29 7b 0a 20 20 20  =szExtra) ){.   
42b0: 20 70 63 61 63 68 65 50 61 67 65 46 72 65 65 28   pcachePageFree(
42c0: 70 29 3b 0a 20 20 20 20 70 20 3d 20 30 3b 0a 20  p);.    p = 0;. 
42d0: 20 7d 0a 0a 20 20 69 66 28 20 21 70 20 29 7b 0a   }..  if( !p ){.
42e0: 20 20 20 20 70 20 3d 20 70 63 61 63 68 65 50 61      p = pcachePa
42f0: 67 65 41 6c 6c 6f 63 28 70 43 61 63 68 65 29 3b  geAlloc(pCache);
4300: 0a 20 20 7d 0a 0a 20 20 70 63 61 63 68 65 45 78  .  }..  pcacheEx
4310: 69 74 47 6c 6f 62 61 6c 28 29 3b 0a 20 20 72 65  itGlobal();.  re
4320: 74 75 72 6e 20 70 3b 0a 7d 0a 0a 2f 2a 2a 2a 2a  turn p;.}../****
4330: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
4340: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
4350: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20  *************** 
4360: 47 65 6e 65 72 61 6c 20 49 6e 74 65 72 66 61 63  General Interfac
4370: 65 73 20 2a 2a 2a 2a 2a 2a 0a 2a 2a 0a 2a 2a 20  es ******.**.** 
4380: 49 6e 69 74 69 61 6c 69 7a 65 20 61 6e 64 20 73  Initialize and s
4390: 68 75 74 64 6f 77 6e 20 74 68 65 20 70 61 67 65  hutdown the page
43a0: 20 63 61 63 68 65 20 73 75 62 73 79 73 74 65 6d   cache subsystem
43b0: 2e 20 4e 65 69 74 68 65 72 20 6f 66 20 74 68 65  . Neither of the
43c0: 73 65 20 0a 2a 2a 20 66 75 6e 63 74 69 6f 6e 73  se .** functions
43d0: 20 61 72 65 20 74 68 72 65 61 64 73 61 66 65 2e   are threadsafe.
43e0: 0a 2a 2f 0a 69 6e 74 20 73 71 6c 69 74 65 33 50  .*/.int sqlite3P
43f0: 63 61 63 68 65 49 6e 69 74 69 61 6c 69 7a 65 28  cacheInitialize(
4400: 76 6f 69 64 29 7b 0a 20 20 61 73 73 65 72 74 28  void){.  assert(
4410: 20 70 63 61 63 68 65 2e 69 73 49 6e 69 74 3d 3d   pcache.isInit==
4420: 30 20 29 3b 0a 20 20 6d 65 6d 73 65 74 28 26 70  0 );.  memset(&p
4430: 63 61 63 68 65 2c 20 30 2c 20 73 69 7a 65 6f 66  cache, 0, sizeof
4440: 28 70 63 61 63 68 65 29 29 3b 0a 20 20 69 66 28  (pcache));.  if(
4450: 20 73 71 6c 69 74 65 33 43 6f 6e 66 69 67 2e 62   sqlite3Config.b
4460: 43 6f 72 65 4d 75 74 65 78 20 29 7b 0a 20 20 20  CoreMutex ){.   
4470: 20 70 63 61 63 68 65 2e 6d 75 74 65 78 20 3d 20   pcache.mutex = 
4480: 73 71 6c 69 74 65 33 5f 6d 75 74 65 78 5f 61 6c  sqlite3_mutex_al
4490: 6c 6f 63 28 53 51 4c 49 54 45 5f 4d 55 54 45 58  loc(SQLITE_MUTEX
44a0: 5f 53 54 41 54 49 43 5f 4c 52 55 29 3b 0a 20 20  _STATIC_LRU);.  
44b0: 20 20 69 66 28 20 70 63 61 63 68 65 2e 6d 75 74    if( pcache.mut
44c0: 65 78 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 72  ex==0 ){.      r
44d0: 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4e 4f 4d  eturn SQLITE_NOM
44e0: 45 4d 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20  EM;.    }.  }.  
44f0: 70 63 61 63 68 65 2e 69 73 49 6e 69 74 20 3d 20  pcache.isInit = 
4500: 31 3b 0a 20 20 72 65 74 75 72 6e 20 53 51 4c 49  1;.  return SQLI
4510: 54 45 5f 4f 4b 3b 0a 7d 0a 76 6f 69 64 20 73 71  TE_OK;.}.void sq
4520: 6c 69 74 65 33 50 63 61 63 68 65 53 68 75 74 64  lite3PcacheShutd
4530: 6f 77 6e 28 76 6f 69 64 29 7b 0a 20 20 6d 65 6d  own(void){.  mem
4540: 73 65 74 28 26 70 63 61 63 68 65 2c 20 30 2c 20  set(&pcache, 0, 
4550: 73 69 7a 65 6f 66 28 70 63 61 63 68 65 29 29 3b  sizeof(pcache));
4560: 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 52 65 74 75 72 6e  .}../*.** Return
4570: 20 74 68 65 20 73 69 7a 65 20 69 6e 20 62 79 74   the size in byt
4580: 65 73 20 6f 66 20 61 20 50 43 61 63 68 65 20 6f  es of a PCache o
4590: 62 6a 65 63 74 2e 0a 2a 2f 0a 69 6e 74 20 73 71  bject..*/.int sq
45a0: 6c 69 74 65 33 50 63 61 63 68 65 53 69 7a 65 28  lite3PcacheSize(
45b0: 76 6f 69 64 29 7b 20 72 65 74 75 72 6e 20 73 69  void){ return si
45c0: 7a 65 6f 66 28 50 43 61 63 68 65 29 3b 20 7d 0a  zeof(PCache); }.
45d0: 0a 2f 2a 0a 2a 2a 20 43 72 65 61 74 65 20 61 20  ./*.** Create a 
45e0: 6e 65 77 20 50 43 61 63 68 65 20 6f 62 6a 65 63  new PCache objec
45f0: 74 2e 20 20 53 74 6f 72 61 67 65 20 73 70 61 63  t.  Storage spac
4600: 65 20 74 6f 20 68 6f 6c 64 20 74 68 65 20 6f 62  e to hold the ob
4610: 6a 65 63 74 0a 2a 2a 20 68 61 73 20 61 6c 72 65  ject.** has alre
4620: 61 64 79 20 62 65 65 6e 20 61 6c 6c 6f 63 61 74  ady been allocat
4630: 65 64 20 61 6e 64 20 69 73 20 70 61 73 73 65 64  ed and is passed
4640: 20 69 6e 20 61 73 20 74 68 65 20 70 20 70 6f 69   in as the p poi
4650: 6e 74 65 72 2e 0a 2a 2f 0a 76 6f 69 64 20 73 71  nter..*/.void sq
4660: 6c 69 74 65 33 50 63 61 63 68 65 4f 70 65 6e 28  lite3PcacheOpen(
4670: 0a 20 20 69 6e 74 20 73 7a 50 61 67 65 2c 20 20  .  int szPage,  
4680: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4690: 2f 2a 20 53 69 7a 65 20 6f 66 20 65 76 65 72 79  /* Size of every
46a0: 20 70 61 67 65 20 2a 2f 0a 20 20 69 6e 74 20 73   page */.  int s
46b0: 7a 45 78 74 72 61 2c 20 20 20 20 20 20 20 20 20  zExtra,         
46c0: 20 20 20 20 20 20 20 20 2f 2a 20 45 78 74 72 61          /* Extra
46d0: 20 73 70 61 63 65 20 61 73 73 6f 63 69 61 74 65   space associate
46e0: 64 20 77 69 74 68 20 65 61 63 68 20 70 61 67 65  d with each page
46f0: 20 2a 2f 0a 20 20 69 6e 74 20 62 50 75 72 67 65   */.  int bPurge
4700: 61 62 6c 65 2c 20 20 20 20 20 20 20 20 20 20 20  able,           
4710: 20 20 20 2f 2a 20 54 72 75 65 20 69 66 20 70 61     /* True if pa
4720: 67 65 73 20 61 72 65 20 6f 6e 20 62 61 63 6b 69  ges are on backi
4730: 6e 67 20 73 74 6f 72 65 20 2a 2f 0a 20 20 76 6f  ng store */.  vo
4740: 69 64 20 28 2a 78 44 65 73 74 72 6f 79 29 28 50  id (*xDestroy)(P
4750: 67 48 64 72 2a 29 2c 20 20 20 20 2f 2a 20 43 61  gHdr*),    /* Ca
4760: 6c 6c 65 64 20 74 6f 20 64 65 73 74 72 6f 79 20  lled to destroy 
4770: 61 20 70 61 67 65 20 2a 2f 0a 20 20 69 6e 74 20  a page */.  int 
4780: 28 2a 78 53 74 72 65 73 73 29 28 76 6f 69 64 2a  (*xStress)(void*
4790: 2c 50 67 48 64 72 2a 29 2c 2f 2a 20 43 61 6c 6c  ,PgHdr*),/* Call
47a0: 20 74 6f 20 74 72 79 20 74 6f 20 6d 61 6b 65 20   to try to make 
47b0: 70 61 67 65 73 20 63 6c 65 61 6e 20 2a 2f 0a 20  pages clean */. 
47c0: 20 76 6f 69 64 20 2a 70 53 74 72 65 73 73 2c 20   void *pStress, 
47d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
47e0: 20 41 72 67 75 6d 65 6e 74 20 74 6f 20 78 53 74   Argument to xSt
47f0: 72 65 73 73 20 2a 2f 0a 20 20 50 43 61 63 68 65  ress */.  PCache
4800: 20 2a 70 20 20 20 20 20 20 20 20 20 20 20 20 20   *p             
4810: 20 20 20 20 20 20 20 2f 2a 20 50 72 65 61 6c 6c         /* Preall
4820: 6f 63 61 74 65 64 20 73 70 61 63 65 20 66 6f 72  ocated space for
4830: 20 74 68 65 20 50 43 61 63 68 65 20 2a 2f 0a 29   the PCache */.)
4840: 7b 0a 20 20 61 73 73 65 72 74 28 20 70 63 61 63  {.  assert( pcac
4850: 68 65 2e 69 73 49 6e 69 74 20 29 3b 0a 20 20 6d  he.isInit );.  m
4860: 65 6d 73 65 74 28 70 2c 20 30 2c 20 73 69 7a 65  emset(p, 0, size
4870: 6f 66 28 50 43 61 63 68 65 29 29 3b 0a 20 20 70  of(PCache));.  p
4880: 2d 3e 73 7a 50 61 67 65 20 3d 20 73 7a 50 61 67  ->szPage = szPag
4890: 65 3b 0a 20 20 70 2d 3e 73 7a 45 78 74 72 61 20  e;.  p->szExtra 
48a0: 3d 20 73 7a 45 78 74 72 61 3b 0a 20 20 70 2d 3e  = szExtra;.  p->
48b0: 62 50 75 72 67 65 61 62 6c 65 20 3d 20 62 50 75  bPurgeable = bPu
48c0: 72 67 65 61 62 6c 65 3b 0a 20 20 70 2d 3e 78 44  rgeable;.  p->xD
48d0: 65 73 74 72 6f 79 20 3d 20 78 44 65 73 74 72 6f  estroy = xDestro
48e0: 79 3b 0a 20 20 70 2d 3e 78 53 74 72 65 73 73 20  y;.  p->xStress 
48f0: 3d 20 78 53 74 72 65 73 73 3b 0a 20 20 70 2d 3e  = xStress;.  p->
4900: 70 53 74 72 65 73 73 20 3d 20 70 53 74 72 65 73  pStress = pStres
4910: 73 3b 0a 20 20 70 2d 3e 6e 4d 61 78 20 3d 20 31  s;.  p->nMax = 1
4920: 30 30 3b 0a 20 20 70 2d 3e 6e 4d 69 6e 20 3d 20  00;.  p->nMin = 
4930: 32 30 3b 0a 0a 20 20 70 63 61 63 68 65 45 6e 74  20;..  pcacheEnt
4940: 65 72 47 6c 6f 62 61 6c 28 29 3b 0a 20 20 69 66  erGlobal();.  if
4950: 28 20 62 50 75 72 67 65 61 62 6c 65 20 29 7b 0a  ( bPurgeable ){.
4960: 20 20 20 20 70 63 61 63 68 65 2e 6e 4d 61 78 50      pcache.nMaxP
4970: 61 67 65 20 2b 3d 20 70 2d 3e 6e 4d 61 78 3b 0a  age += p->nMax;.
4980: 20 20 20 20 70 63 61 63 68 65 2e 6e 4d 69 6e 50      pcache.nMinP
4990: 61 67 65 20 2b 3d 20 70 2d 3e 6e 4d 69 6e 3b 0a  age += p->nMin;.
49a0: 20 20 7d 0a 0a 20 20 70 63 61 63 68 65 45 78 69    }..  pcacheExi
49b0: 74 47 6c 6f 62 61 6c 28 29 3b 0a 7d 0a 0a 2f 2a  tGlobal();.}../*
49c0: 0a 2a 2a 20 43 68 61 6e 67 65 20 74 68 65 20 70  .** Change the p
49d0: 61 67 65 20 73 69 7a 65 20 66 6f 72 20 50 43 61  age size for PCa
49e0: 63 68 65 20 6f 62 6a 65 63 74 2e 20 20 54 68 69  che object.  Thi
49f0: 73 20 63 61 6e 20 6f 6e 6c 79 20 68 61 70 70 65  s can only happe
4a00: 6e 0a 2a 2a 20 77 68 65 6e 20 74 68 65 20 63 61  n.** when the ca
4a10: 63 68 65 20 69 73 20 65 6d 70 74 79 2e 0a 2a 2f  che is empty..*/
4a20: 0a 76 6f 69 64 20 73 71 6c 69 74 65 33 50 63 61  .void sqlite3Pca
4a30: 63 68 65 53 65 74 50 61 67 65 53 69 7a 65 28 50  cheSetPageSize(P
4a40: 43 61 63 68 65 20 2a 70 43 61 63 68 65 2c 20 69  Cache *pCache, i
4a50: 6e 74 20 73 7a 50 61 67 65 29 7b 0a 20 20 61 73  nt szPage){.  as
4a60: 73 65 72 74 28 70 43 61 63 68 65 2d 3e 6e 50 61  sert(pCache->nPa
4a70: 67 65 3d 3d 30 29 3b 0a 20 20 70 43 61 63 68 65  ge==0);.  pCache
4a80: 2d 3e 73 7a 50 61 67 65 20 3d 20 73 7a 50 61 67  ->szPage = szPag
4a90: 65 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54 72 79 20  e;.}../*.** Try 
4aa0: 74 6f 20 6f 62 74 61 69 6e 20 61 20 70 61 67 65  to obtain a page
4ab0: 20 66 72 6f 6d 20 74 68 65 20 63 61 63 68 65 2e   from the cache.
4ac0: 0a 2a 2f 0a 69 6e 74 20 73 71 6c 69 74 65 33 50  .*/.int sqlite3P
4ad0: 63 61 63 68 65 46 65 74 63 68 28 0a 20 20 50 43  cacheFetch(.  PC
4ae0: 61 63 68 65 20 2a 70 43 61 63 68 65 2c 20 20 20  ache *pCache,   
4af0: 20 20 20 20 2f 2a 20 4f 62 74 61 69 6e 20 74 68      /* Obtain th
4b00: 65 20 70 61 67 65 20 66 72 6f 6d 20 74 68 69 73  e page from this
4b10: 20 63 61 63 68 65 20 2a 2f 0a 20 20 50 67 6e 6f   cache */.  Pgno
4b20: 20 70 67 6e 6f 2c 20 20 20 20 20 20 20 20 20 20   pgno,          
4b30: 20 20 2f 2a 20 50 61 67 65 20 6e 75 6d 62 65 72    /* Page number
4b40: 20 74 6f 20 6f 62 74 61 69 6e 20 2a 2f 0a 20 20   to obtain */.  
4b50: 69 6e 74 20 63 72 65 61 74 65 46 6c 61 67 2c 20  int createFlag, 
4b60: 20 20 20 20 20 20 2f 2a 20 49 66 20 74 72 75 65        /* If true
4b70: 2c 20 63 72 65 61 74 65 20 70 61 67 65 20 69 66  , create page if
4b80: 20 69 74 20 64 6f 65 73 20 6e 6f 74 20 65 78 69   it does not exi
4b90: 73 74 20 61 6c 72 65 61 64 79 20 2a 2f 0a 20 20  st already */.  
4ba0: 50 67 48 64 72 20 2a 2a 70 70 50 61 67 65 20 20  PgHdr **ppPage  
4bb0: 20 20 20 20 20 20 2f 2a 20 57 72 69 74 65 20 74        /* Write t
4bc0: 68 65 20 70 61 67 65 20 68 65 72 65 20 2a 2f 0a  he page here */.
4bd0: 29 7b 0a 20 20 50 67 48 64 72 20 2a 70 50 61 67  ){.  PgHdr *pPag
4be0: 65 3b 0a 20 20 61 73 73 65 72 74 28 20 70 63 61  e;.  assert( pca
4bf0: 63 68 65 2e 69 73 49 6e 69 74 20 29 3b 0a 20 20  che.isInit );.  
4c00: 61 73 73 65 72 74 28 20 70 43 61 63 68 65 21 3d  assert( pCache!=
4c10: 30 20 29 3b 0a 20 20 61 73 73 65 72 74 28 20 70  0 );.  assert( p
4c20: 67 6e 6f 3e 30 20 29 3b 0a 20 20 61 73 73 65 72  gno>0 );.  asser
4c30: 74 28 20 70 43 61 63 68 65 2d 3e 6e 50 69 6e 6e  t( pCache->nPinn
4c40: 65 64 3d 3d 70 63 61 63 68 65 50 69 6e 6e 65 64  ed==pcachePinned
4c50: 43 6f 75 6e 74 28 70 43 61 63 68 65 29 20 29 3b  Count(pCache) );
4c60: 0a 0a 20 20 2f 2a 20 53 65 61 72 63 68 20 74 68  ..  /* Search th
4c70: 65 20 68 61 73 68 20 74 61 62 6c 65 20 66 6f 72  e hash table for
4c80: 20 74 68 65 20 72 65 71 75 65 73 74 65 64 20 70   the requested p
4c90: 61 67 65 2e 20 45 78 69 74 20 65 61 72 6c 79 20  age. Exit early 
4ca0: 69 66 20 69 74 20 69 73 20 66 6f 75 6e 64 2e 20  if it is found. 
4cb0: 2a 2f 0a 20 20 69 66 28 20 70 43 61 63 68 65 2d  */.  if( pCache-
4cc0: 3e 61 70 48 61 73 68 20 29 7b 0a 20 20 20 20 75  >apHash ){.    u
4cd0: 33 32 20 68 20 3d 20 70 67 6e 6f 20 25 20 70 43  32 h = pgno % pC
4ce0: 61 63 68 65 2d 3e 6e 48 61 73 68 3b 0a 20 20 20  ache->nHash;.   
4cf0: 20 66 6f 72 28 70 50 61 67 65 3d 70 43 61 63 68   for(pPage=pCach
4d00: 65 2d 3e 61 70 48 61 73 68 5b 68 5d 3b 20 70 50  e->apHash[h]; pP
4d10: 61 67 65 3b 20 70 50 61 67 65 3d 70 50 61 67 65  age; pPage=pPage
4d20: 2d 3e 70 4e 65 78 74 48 61 73 68 29 7b 0a 20 20  ->pNextHash){.  
4d30: 20 20 20 20 69 66 28 20 70 50 61 67 65 2d 3e 70      if( pPage->p
4d40: 67 6e 6f 3d 3d 70 67 6e 6f 20 29 7b 0a 20 20 20  gno==pgno ){.   
4d50: 20 20 20 20 20 69 66 28 20 70 50 61 67 65 2d 3e       if( pPage->
4d60: 6e 52 65 66 3d 3d 30 20 29 7b 0a 20 20 20 20 20  nRef==0 ){.     
4d70: 20 20 20 20 20 69 66 28 20 30 3d 3d 28 70 50 61       if( 0==(pPa
4d80: 67 65 2d 3e 66 6c 61 67 73 26 50 47 48 44 52 5f  ge->flags&PGHDR_
4d90: 44 49 52 54 59 29 20 29 7b 0a 20 20 20 20 20 20  DIRTY) ){.      
4da0: 20 20 20 20 20 20 70 63 61 63 68 65 45 6e 74 65        pcacheEnte
4db0: 72 47 6c 6f 62 61 6c 28 29 3b 0a 20 20 20 20 20  rGlobal();.     
4dc0: 20 20 20 20 20 20 20 70 63 61 63 68 65 52 65 6d         pcacheRem
4dd0: 6f 76 65 46 72 6f 6d 4c 72 75 4c 69 73 74 28 70  oveFromLruList(p
4de0: 50 61 67 65 29 3b 0a 20 20 20 20 20 20 20 20 20  Page);.         
4df0: 20 20 20 70 63 61 63 68 65 45 78 69 74 47 6c 6f     pcacheExitGlo
4e00: 62 61 6c 28 29 3b 0a 20 20 20 20 20 20 20 20 20  bal();.         
4e10: 20 20 20 70 43 61 63 68 65 2d 3e 6e 50 69 6e 6e     pCache->nPinn
4e20: 65 64 2b 2b 3b 0a 20 20 20 20 20 20 20 20 20 20  ed++;.          
4e30: 7d 0a 20 20 20 20 20 20 20 20 20 20 70 43 61 63  }.          pCac
4e40: 68 65 2d 3e 6e 52 65 66 2b 2b 3b 0a 20 20 20 20  he->nRef++;.    
4e50: 20 20 20 20 7d 0a 20 20 20 20 20 20 20 20 70 50      }.        pP
4e60: 61 67 65 2d 3e 6e 52 65 66 2b 2b 3b 0a 20 20 20  age->nRef++;.   
4e70: 20 20 20 20 20 2a 70 70 50 61 67 65 20 3d 20 70       *ppPage = p
4e80: 50 61 67 65 3b 0a 20 20 20 20 20 20 20 20 72 65  Page;.        re
4e90: 74 75 72 6e 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a  turn SQLITE_OK;.
4ea0: 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a 20 20        }.    }.  
4eb0: 7d 0a 0a 20 20 69 66 28 20 63 72 65 61 74 65 46  }..  if( createF
4ec0: 6c 61 67 20 29 7b 0a 20 20 20 20 69 66 28 20 70  lag ){.    if( p
4ed0: 43 61 63 68 65 2d 3e 6e 48 61 73 68 3c 3d 70 43  Cache->nHash<=pC
4ee0: 61 63 68 65 2d 3e 6e 50 61 67 65 20 29 7b 0a 20  ache->nPage ){. 
4ef0: 20 20 20 20 20 69 6e 74 20 72 63 20 3d 20 70 63       int rc = pc
4f00: 61 63 68 65 52 65 73 69 7a 65 48 61 73 68 28 70  acheResizeHash(p
4f10: 43 61 63 68 65 2c 20 70 43 61 63 68 65 2d 3e 6e  Cache, pCache->n
4f20: 48 61 73 68 3c 32 35 36 3f 32 35 36 3a 70 43 61  Hash<256?256:pCa
4f30: 63 68 65 2d 3e 6e 48 61 73 68 2a 32 29 3b 0a 20  che->nHash*2);. 
4f40: 20 20 20 20 20 69 66 28 20 72 63 21 3d 53 51 4c       if( rc!=SQL
4f50: 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20  ITE_OK ){.      
4f60: 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 20 20 20    return rc;.   
4f70: 20 20 20 7d 0a 20 20 20 20 7d 0a 0a 20 20 20 20     }.    }..    
4f80: 70 50 61 67 65 20 3d 20 70 63 61 63 68 65 52 65  pPage = pcacheRe
4f90: 63 79 63 6c 65 4f 72 41 6c 6c 6f 63 28 70 43 61  cycleOrAlloc(pCa
4fa0: 63 68 65 29 3b 0a 20 20 20 20 2a 70 70 50 61 67  che);.    *ppPag
4fb0: 65 20 3d 20 70 50 61 67 65 3b 0a 20 20 20 20 69  e = pPage;.    i
4fc0: 66 28 20 70 50 61 67 65 3d 3d 30 20 29 7b 0a 20  f( pPage==0 ){. 
4fd0: 20 20 20 20 20 72 65 74 75 72 6e 20 53 51 4c 49       return SQLI
4fe0: 54 45 5f 4e 4f 4d 45 4d 3b 0a 20 20 20 20 7d 0a  TE_NOMEM;.    }.
4ff0: 0a 20 20 20 20 70 50 61 67 65 2d 3e 70 50 61 67  .    pPage->pPag
5000: 65 72 20 3d 20 30 3b 0a 20 20 20 20 70 50 61 67  er = 0;.    pPag
5010: 65 2d 3e 66 6c 61 67 73 20 3d 20 30 3b 0a 20 20  e->flags = 0;.  
5020: 20 20 70 50 61 67 65 2d 3e 70 44 69 72 74 79 20    pPage->pDirty 
5030: 3d 20 30 3b 0a 20 20 20 20 70 50 61 67 65 2d 3e  = 0;.    pPage->
5040: 70 67 6e 6f 20 3d 20 70 67 6e 6f 3b 0a 20 20 20  pgno = pgno;.   
5050: 20 70 50 61 67 65 2d 3e 70 43 61 63 68 65 20 3d   pPage->pCache =
5060: 20 70 43 61 63 68 65 3b 0a 20 20 20 20 70 50 61   pCache;.    pPa
5070: 67 65 2d 3e 6e 52 65 66 20 3d 20 31 3b 0a 20 20  ge->nRef = 1;.  
5080: 20 20 70 43 61 63 68 65 2d 3e 6e 52 65 66 2b 2b    pCache->nRef++
5090: 3b 0a 20 20 20 20 70 43 61 63 68 65 2d 3e 6e 50  ;.    pCache->nP
50a0: 69 6e 6e 65 64 2b 2b 3b 0a 20 20 20 20 70 63 61  inned++;.    pca
50b0: 63 68 65 41 64 64 54 6f 4c 69 73 74 28 26 70 43  cheAddToList(&pC
50c0: 61 63 68 65 2d 3e 70 43 6c 65 61 6e 2c 20 70 50  ache->pClean, pP
50d0: 61 67 65 29 3b 0a 20 20 20 20 70 63 61 63 68 65  age);.    pcache
50e0: 41 64 64 54 6f 48 61 73 68 28 70 50 61 67 65 29  AddToHash(pPage)
50f0: 3b 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 2a  ;.  }else{.    *
5100: 70 70 50 61 67 65 20 3d 20 30 3b 0a 20 20 7d 0a  ppPage = 0;.  }.
5110: 0a 20 20 61 73 73 65 72 74 28 20 70 43 61 63 68  .  assert( pCach
5120: 65 2d 3e 6e 50 69 6e 6e 65 64 3d 3d 70 63 61 63  e->nPinned==pcac
5130: 68 65 50 69 6e 6e 65 64 43 6f 75 6e 74 28 70 43  hePinnedCount(pC
5140: 61 63 68 65 29 20 29 3b 0a 20 20 72 65 74 75 72  ache) );.  retur
5150: 6e 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 7d 0a 0a  n SQLITE_OK;.}..
5160: 2f 2a 0a 2a 2a 20 44 65 72 65 66 65 72 65 6e 63  /*.** Dereferenc
5170: 65 20 61 20 70 61 67 65 2e 20 20 57 68 65 6e 20  e a page.  When 
5180: 74 68 65 20 72 65 66 65 72 65 6e 63 65 20 63 6f  the reference co
5190: 75 6e 74 20 72 65 61 63 68 65 73 20 7a 65 72 6f  unt reaches zero
51a0: 2c 0a 2a 2a 20 6d 6f 76 65 20 74 68 65 20 70 61  ,.** move the pa
51b0: 67 65 20 74 6f 20 74 68 65 20 4c 52 55 20 6c 69  ge to the LRU li
51c0: 73 74 20 69 66 20 69 74 20 69 73 20 63 6c 65 61  st if it is clea
51d0: 6e 2e 0a 2a 2f 0a 76 6f 69 64 20 73 71 6c 69 74  n..*/.void sqlit
51e0: 65 33 50 63 61 63 68 65 52 65 6c 65 61 73 65 28  e3PcacheRelease(
51f0: 50 67 48 64 72 20 2a 70 29 7b 0a 20 20 61 73 73  PgHdr *p){.  ass
5200: 65 72 74 28 20 70 2d 3e 6e 52 65 66 3e 30 20 29  ert( p->nRef>0 )
5210: 3b 0a 20 20 70 2d 3e 6e 52 65 66 2d 2d 3b 0a 20  ;.  p->nRef--;. 
5220: 20 69 66 28 20 70 2d 3e 6e 52 65 66 3d 3d 30 20   if( p->nRef==0 
5230: 29 7b 0a 20 20 20 20 50 43 61 63 68 65 20 2a 70  ){.    PCache *p
5240: 43 61 63 68 65 20 3d 20 70 2d 3e 70 43 61 63 68  Cache = p->pCach
5250: 65 3b 0a 20 20 20 20 69 66 28 20 70 2d 3e 70 43  e;.    if( p->pC
5260: 61 63 68 65 2d 3e 78 44 65 73 74 72 6f 79 20 29  ache->xDestroy )
5270: 7b 0a 20 20 20 20 20 20 70 2d 3e 70 43 61 63 68  {.      p->pCach
5280: 65 2d 3e 78 44 65 73 74 72 6f 79 28 70 29 3b 0a  e->xDestroy(p);.
5290: 20 20 20 20 7d 0a 20 20 20 20 70 43 61 63 68 65      }.    pCache
52a0: 2d 3e 6e 52 65 66 2d 2d 3b 0a 20 20 20 20 69 66  ->nRef--;.    if
52b0: 28 20 28 70 2d 3e 66 6c 61 67 73 26 50 47 48 44  ( (p->flags&PGHD
52c0: 52 5f 44 49 52 54 59 29 3d 3d 30 20 29 7b 0a 20  R_DIRTY)==0 ){. 
52d0: 20 20 20 20 20 70 43 61 63 68 65 2d 3e 6e 50 69       pCache->nPi
52e0: 6e 6e 65 64 2d 2d 3b 0a 20 20 20 20 20 20 70 63  nned--;.      pc
52f0: 61 63 68 65 45 6e 74 65 72 47 6c 6f 62 61 6c 28  acheEnterGlobal(
5300: 29 3b 0a 20 20 20 20 20 20 70 63 61 63 68 65 41  );.      pcacheA
5310: 64 64 54 6f 4c 72 75 4c 69 73 74 28 70 29 3b 0a  ddToLruList(p);.
5320: 20 20 20 20 20 20 70 63 61 63 68 65 45 78 69 74        pcacheExit
5330: 47 6c 6f 62 61 6c 28 29 3b 0a 20 20 20 20 7d 65  Global();.    }e
5340: 6c 73 65 7b 0a 20 20 20 20 20 20 2f 2a 20 4d 6f  lse{.      /* Mo
5350: 76 65 20 74 68 65 20 70 61 67 65 20 74 6f 20 74  ve the page to t
5360: 68 65 20 68 65 61 64 20 6f 66 20 74 68 65 20 63  he head of the c
5370: 61 63 68 65 73 20 64 69 72 74 79 20 6c 69 73 74  aches dirty list
5380: 2e 20 2a 2f 0a 20 20 20 20 20 20 70 63 61 63 68  . */.      pcach
5390: 65 52 65 6d 6f 76 65 46 72 6f 6d 4c 69 73 74 28  eRemoveFromList(
53a0: 26 70 43 61 63 68 65 2d 3e 70 44 69 72 74 79 2c  &pCache->pDirty,
53b0: 20 70 29 3b 0a 20 20 20 20 20 20 70 63 61 63 68   p);.      pcach
53c0: 65 41 64 64 54 6f 4c 69 73 74 28 26 70 43 61 63  eAddToList(&pCac
53d0: 68 65 2d 3e 70 44 69 72 74 79 2c 20 70 29 3b 0a  he->pDirty, p);.
53e0: 20 20 20 20 7d 0a 20 20 7d 0a 7d 0a 0a 76 6f 69      }.  }.}..voi
53f0: 64 20 73 71 6c 69 74 65 33 50 63 61 63 68 65 52  d sqlite3PcacheR
5400: 65 66 28 50 67 48 64 72 20 2a 70 29 7b 0a 20 20  ef(PgHdr *p){.  
5410: 61 73 73 65 72 74 28 70 2d 3e 6e 52 65 66 3e 30  assert(p->nRef>0
5420: 29 3b 0a 20 20 70 2d 3e 6e 52 65 66 2b 2b 3b 0a  );.  p->nRef++;.
5430: 7d 0a 0a 2f 2a 0a 2a 2a 20 44 72 6f 70 20 61 20  }../*.** Drop a 
5440: 70 61 67 65 20 66 72 6f 6d 20 74 68 65 20 63 61  page from the ca
5450: 63 68 65 2e 20 20 54 68 69 73 20 73 68 6f 75 6c  che.  This shoul
5460: 64 20 62 65 20 74 68 65 20 6f 6e 6c 79 20 72 65  d be the only re
5470: 66 65 72 65 6e 63 65 20 74 6f 0a 2a 2a 20 74 68  ference to.** th
5480: 65 20 70 61 67 65 2e 0a 2a 2f 0a 76 6f 69 64 20  e page..*/.void 
5490: 73 71 6c 69 74 65 33 50 63 61 63 68 65 44 72 6f  sqlite3PcacheDro
54a0: 70 28 50 67 48 64 72 20 2a 70 29 7b 0a 20 20 50  p(PgHdr *p){.  P
54b0: 43 61 63 68 65 20 2a 70 43 61 63 68 65 3b 0a 20  Cache *pCache;. 
54c0: 20 61 73 73 65 72 74 28 20 70 2d 3e 6e 52 65 66   assert( p->nRef
54d0: 3d 3d 31 20 29 3b 0a 20 20 70 43 61 63 68 65 20  ==1 );.  pCache 
54e0: 3d 20 70 2d 3e 70 43 61 63 68 65 3b 0a 20 20 70  = p->pCache;.  p
54f0: 43 61 63 68 65 2d 3e 6e 52 65 66 2d 2d 3b 0a 20  Cache->nRef--;. 
5500: 20 70 43 61 63 68 65 2d 3e 6e 50 69 6e 6e 65 64   pCache->nPinned
5510: 2d 2d 3b 0a 20 20 69 66 28 20 70 2d 3e 66 6c 61  --;.  if( p->fla
5520: 67 73 20 26 20 50 47 48 44 52 5f 44 49 52 54 59  gs & PGHDR_DIRTY
5530: 20 29 7b 0a 20 20 20 20 70 63 61 63 68 65 52 65   ){.    pcacheRe
5540: 6d 6f 76 65 46 72 6f 6d 4c 69 73 74 28 26 70 43  moveFromList(&pC
5550: 61 63 68 65 2d 3e 70 44 69 72 74 79 2c 20 70 29  ache->pDirty, p)
5560: 3b 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 70  ;.  }else{.    p
5570: 63 61 63 68 65 52 65 6d 6f 76 65 46 72 6f 6d 4c  cacheRemoveFromL
5580: 69 73 74 28 26 70 43 61 63 68 65 2d 3e 70 43 6c  ist(&pCache->pCl
5590: 65 61 6e 2c 20 70 29 3b 0a 20 20 7d 0a 20 20 70  ean, p);.  }.  p
55a0: 63 61 63 68 65 52 65 6d 6f 76 65 46 72 6f 6d 48  cacheRemoveFromH
55b0: 61 73 68 28 70 29 3b 0a 20 20 70 63 61 63 68 65  ash(p);.  pcache
55c0: 45 6e 74 65 72 47 6c 6f 62 61 6c 28 29 3b 0a 20  EnterGlobal();. 
55d0: 20 70 63 61 63 68 65 50 61 67 65 46 72 65 65 28   pcachePageFree(
55e0: 70 29 3b 0a 20 20 70 63 61 63 68 65 45 78 69 74  p);.  pcacheExit
55f0: 47 6c 6f 62 61 6c 28 29 3b 0a 7d 0a 0a 2f 2a 0a  Global();.}../*.
5600: 2a 2a 20 4d 61 6b 65 20 73 75 72 65 20 74 68 65  ** Make sure the
5610: 20 70 61 67 65 20 69 73 20 6d 61 72 6b 65 64 20   page is marked 
5620: 61 73 20 64 69 72 74 79 2e 20 20 49 66 20 69 74  as dirty.  If it
5630: 20 69 73 6e 27 74 20 64 69 72 74 79 20 61 6c 72   isn't dirty alr
5640: 65 61 64 79 2c 0a 2a 2a 20 6d 61 6b 65 20 69 74  eady,.** make it
5650: 20 73 6f 2e 0a 2a 2f 0a 76 6f 69 64 20 73 71 6c   so..*/.void sql
5660: 69 74 65 33 50 63 61 63 68 65 4d 61 6b 65 44 69  ite3PcacheMakeDi
5670: 72 74 79 28 50 67 48 64 72 20 2a 70 29 7b 0a 20  rty(PgHdr *p){. 
5680: 20 50 43 61 63 68 65 20 2a 70 43 61 63 68 65 3b   PCache *pCache;
5690: 0a 20 20 70 2d 3e 66 6c 61 67 73 20 26 3d 20 7e  .  p->flags &= ~
56a0: 50 47 48 44 52 5f 44 4f 4e 54 5f 57 52 49 54 45  PGHDR_DONT_WRITE
56b0: 3b 0a 20 20 69 66 28 20 70 2d 3e 66 6c 61 67 73  ;.  if( p->flags
56c0: 20 26 20 50 47 48 44 52 5f 44 49 52 54 59 20 29   & PGHDR_DIRTY )
56d0: 20 72 65 74 75 72 6e 3b 0a 20 20 61 73 73 65 72   return;.  asser
56e0: 74 28 20 28 70 2d 3e 66 6c 61 67 73 20 26 20 50  t( (p->flags & P
56f0: 47 48 44 52 5f 44 49 52 54 59 29 3d 3d 30 20 29  GHDR_DIRTY)==0 )
5700: 3b 0a 20 20 61 73 73 65 72 74 28 20 70 2d 3e 6e  ;.  assert( p->n
5710: 52 65 66 3e 30 20 29 3b 0a 20 20 70 43 61 63 68  Ref>0 );.  pCach
5720: 65 20 3d 20 70 2d 3e 70 43 61 63 68 65 3b 0a 20  e = p->pCache;. 
5730: 20 70 63 61 63 68 65 52 65 6d 6f 76 65 46 72 6f   pcacheRemoveFro
5740: 6d 4c 69 73 74 28 26 70 43 61 63 68 65 2d 3e 70  mList(&pCache->p
5750: 43 6c 65 61 6e 2c 20 70 29 3b 0a 20 20 70 63 61  Clean, p);.  pca
5760: 63 68 65 41 64 64 54 6f 4c 69 73 74 28 26 70 43  cheAddToList(&pC
5770: 61 63 68 65 2d 3e 70 44 69 72 74 79 2c 20 70 29  ache->pDirty, p)
5780: 3b 0a 20 20 70 2d 3e 66 6c 61 67 73 20 7c 3d 20  ;.  p->flags |= 
5790: 50 47 48 44 52 5f 44 49 52 54 59 3b 0a 7d 0a 0a  PGHDR_DIRTY;.}..
57a0: 2f 2a 0a 2a 2a 20 4d 61 6b 65 20 73 75 72 65 20  /*.** Make sure 
57b0: 74 68 65 20 70 61 67 65 20 69 73 20 6d 61 72 6b  the page is mark
57c0: 65 64 20 61 73 20 63 6c 65 61 6e 2e 20 20 49 66  ed as clean.  If
57d0: 20 69 74 20 69 73 6e 27 74 20 63 6c 65 61 6e 20   it isn't clean 
57e0: 61 6c 72 65 61 64 79 2c 0a 2a 2a 20 6d 61 6b 65  already,.** make
57f0: 20 69 74 20 73 6f 2e 0a 2a 2f 0a 76 6f 69 64 20   it so..*/.void 
5800: 73 71 6c 69 74 65 33 50 63 61 63 68 65 4d 61 6b  sqlite3PcacheMak
5810: 65 43 6c 65 61 6e 28 50 67 48 64 72 20 2a 70 29  eClean(PgHdr *p)
5820: 7b 0a 20 20 50 43 61 63 68 65 20 2a 70 43 61 63  {.  PCache *pCac
5830: 68 65 3b 0a 20 20 69 66 28 20 28 70 2d 3e 66 6c  he;.  if( (p->fl
5840: 61 67 73 20 26 20 50 47 48 44 52 5f 44 49 52 54  ags & PGHDR_DIRT
5850: 59 29 3d 3d 30 20 29 20 72 65 74 75 72 6e 3b 0a  Y)==0 ) return;.
5860: 20 20 61 73 73 65 72 74 28 20 70 2d 3e 61 70 53    assert( p->apS
5870: 61 76 65 5b 30 5d 3d 3d 30 20 26 26 20 70 2d 3e  ave[0]==0 && p->
5880: 61 70 53 61 76 65 5b 31 5d 3d 3d 30 20 29 3b 0a  apSave[1]==0 );.
5890: 20 20 61 73 73 65 72 74 28 20 70 2d 3e 66 6c 61    assert( p->fla
58a0: 67 73 20 26 20 50 47 48 44 52 5f 44 49 52 54 59  gs & PGHDR_DIRTY
58b0: 20 29 3b 0a 20 20 70 43 61 63 68 65 20 3d 20 70   );.  pCache = p
58c0: 2d 3e 70 43 61 63 68 65 3b 0a 20 20 70 63 61 63  ->pCache;.  pcac
58d0: 68 65 52 65 6d 6f 76 65 46 72 6f 6d 4c 69 73 74  heRemoveFromList
58e0: 28 26 70 43 61 63 68 65 2d 3e 70 44 69 72 74 79  (&pCache->pDirty
58f0: 2c 20 70 29 3b 0a 20 20 70 63 61 63 68 65 45 6e  , p);.  pcacheEn
5900: 74 65 72 47 6c 6f 62 61 6c 28 29 3b 0a 20 20 70  terGlobal();.  p
5910: 63 61 63 68 65 41 64 64 54 6f 4c 69 73 74 28 26  cacheAddToList(&
5920: 70 43 61 63 68 65 2d 3e 70 43 6c 65 61 6e 2c 20  pCache->pClean, 
5930: 70 29 3b 0a 20 20 70 2d 3e 66 6c 61 67 73 20 26  p);.  p->flags &
5940: 3d 20 7e 50 47 48 44 52 5f 44 49 52 54 59 3b 0a  = ~PGHDR_DIRTY;.
5950: 20 20 69 66 28 20 70 2d 3e 6e 52 65 66 3d 3d 30    if( p->nRef==0
5960: 20 29 7b 0a 20 20 20 20 70 63 61 63 68 65 41 64   ){.    pcacheAd
5970: 64 54 6f 4c 72 75 4c 69 73 74 28 70 29 3b 0a 20  dToLruList(p);. 
5980: 20 20 20 70 43 61 63 68 65 2d 3e 6e 50 69 6e 6e     pCache->nPinn
5990: 65 64 2d 2d 3b 0a 20 20 7d 0a 20 20 61 73 73 65  ed--;.  }.  asse
59a0: 72 74 28 20 70 43 61 63 68 65 2d 3e 6e 50 69 6e  rt( pCache->nPin
59b0: 6e 65 64 3d 3d 70 63 61 63 68 65 50 69 6e 6e 65  ned==pcachePinne
59c0: 64 43 6f 75 6e 74 28 70 43 61 63 68 65 29 20 29  dCount(pCache) )
59d0: 3b 0a 20 20 70 63 61 63 68 65 45 78 69 74 47 6c  ;.  pcacheExitGl
59e0: 6f 62 61 6c 28 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a  obal();.}../*.**
59f0: 20 4d 61 6b 65 20 65 76 65 72 79 20 70 61 67 65   Make every page
5a00: 20 69 6e 20 74 68 65 20 63 61 63 68 65 20 63 6c   in the cache cl
5a10: 65 61 6e 2e 0a 2a 2f 0a 76 6f 69 64 20 73 71 6c  ean..*/.void sql
5a20: 69 74 65 33 50 63 61 63 68 65 43 6c 65 61 6e 41  ite3PcacheCleanA
5a30: 6c 6c 28 50 43 61 63 68 65 20 2a 70 43 61 63 68  ll(PCache *pCach
5a40: 65 29 7b 0a 20 20 50 67 48 64 72 20 2a 70 3b 0a  e){.  PgHdr *p;.
5a50: 20 20 70 63 61 63 68 65 45 6e 74 65 72 47 6c 6f    pcacheEnterGlo
5a60: 62 61 6c 28 29 3b 0a 20 20 77 68 69 6c 65 28 20  bal();.  while( 
5a70: 28 70 20 3d 20 70 43 61 63 68 65 2d 3e 70 44 69  (p = pCache->pDi
5a80: 72 74 79 29 21 3d 30 20 29 7b 0a 20 20 20 20 61  rty)!=0 ){.    a
5a90: 73 73 65 72 74 28 20 70 2d 3e 61 70 53 61 76 65  ssert( p->apSave
5aa0: 5b 30 5d 3d 3d 30 20 26 26 20 70 2d 3e 61 70 53  [0]==0 && p->apS
5ab0: 61 76 65 5b 31 5d 3d 3d 30 20 29 3b 0a 20 20 20  ave[1]==0 );.   
5ac0: 20 70 63 61 63 68 65 52 65 6d 6f 76 65 46 72 6f   pcacheRemoveFro
5ad0: 6d 4c 69 73 74 28 26 70 43 61 63 68 65 2d 3e 70  mList(&pCache->p
5ae0: 44 69 72 74 79 2c 20 70 29 3b 0a 20 20 20 20 70  Dirty, p);.    p
5af0: 2d 3e 66 6c 61 67 73 20 26 3d 20 7e 50 47 48 44  ->flags &= ~PGHD
5b00: 52 5f 44 49 52 54 59 3b 0a 20 20 20 20 70 63 61  R_DIRTY;.    pca
5b10: 63 68 65 41 64 64 54 6f 4c 69 73 74 28 26 70 43  cheAddToList(&pC
5b20: 61 63 68 65 2d 3e 70 43 6c 65 61 6e 2c 20 70 29  ache->pClean, p)
5b30: 3b 0a 20 20 20 20 69 66 28 20 70 2d 3e 6e 52 65  ;.    if( p->nRe
5b40: 66 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 70 63  f==0 ){.      pc
5b50: 61 63 68 65 41 64 64 54 6f 4c 72 75 4c 69 73 74  acheAddToLruList
5b60: 28 70 29 3b 0a 20 20 20 20 20 20 70 43 61 63 68  (p);.      pCach
5b70: 65 2d 3e 6e 50 69 6e 6e 65 64 2d 2d 3b 0a 20 20  e->nPinned--;.  
5b80: 20 20 7d 0a 20 20 7d 0a 20 20 73 71 6c 69 74 65    }.  }.  sqlite
5b90: 33 50 63 61 63 68 65 41 73 73 65 72 74 46 6c 61  3PcacheAssertFla
5ba0: 67 73 28 70 43 61 63 68 65 2c 20 30 2c 20 50 47  gs(pCache, 0, PG
5bb0: 48 44 52 5f 44 49 52 54 59 29 3b 0a 20 20 61 73  HDR_DIRTY);.  as
5bc0: 73 65 72 74 28 20 70 43 61 63 68 65 2d 3e 6e 50  sert( pCache->nP
5bd0: 69 6e 6e 65 64 3d 3d 70 63 61 63 68 65 50 69 6e  inned==pcachePin
5be0: 6e 65 64 43 6f 75 6e 74 28 70 43 61 63 68 65 29  nedCount(pCache)
5bf0: 20 29 3b 0a 20 20 70 63 61 63 68 65 45 78 69 74   );.  pcacheExit
5c00: 47 6c 6f 62 61 6c 28 29 3b 0a 7d 0a 0a 2f 2a 0a  Global();.}../*.
5c10: 2a 2a 20 43 68 61 6e 67 65 20 74 68 65 20 70 61  ** Change the pa
5c20: 67 65 20 6e 75 6d 62 65 72 20 6f 66 20 70 61 67  ge number of pag
5c30: 65 20 70 20 74 6f 20 6e 65 77 50 67 6e 6f 2e 20  e p to newPgno. 
5c40: 49 66 20 6e 65 77 50 67 6e 6f 20 69 73 20 30 2c  If newPgno is 0,
5c50: 20 74 68 65 6e 20 74 68 65 0a 2a 2a 20 70 61 67   then the.** pag
5c60: 65 20 6f 62 6a 65 63 74 20 69 73 20 61 64 64 65  e object is adde
5c70: 64 20 74 6f 20 74 68 65 20 63 6c 65 61 6e 2d 6c  d to the clean-l
5c80: 69 73 74 20 61 6e 64 20 74 68 65 20 50 47 48 44  ist and the PGHD
5c90: 52 5f 52 45 55 53 45 5f 55 4e 4c 49 4b 45 4c 59  R_REUSE_UNLIKELY
5ca0: 20 0a 2a 2a 20 66 6c 61 67 20 73 65 74 2e 0a 2a   .** flag set..*
5cb0: 2f 0a 76 6f 69 64 20 73 71 6c 69 74 65 33 50 63  /.void sqlite3Pc
5cc0: 61 63 68 65 4d 6f 76 65 28 50 67 48 64 72 20 2a  acheMove(PgHdr *
5cd0: 70 2c 20 50 67 6e 6f 20 6e 65 77 50 67 6e 6f 29  p, Pgno newPgno)
5ce0: 7b 0a 20 20 61 73 73 65 72 74 28 20 70 2d 3e 6e  {.  assert( p->n
5cf0: 52 65 66 3e 30 20 29 3b 0a 20 20 70 63 61 63 68  Ref>0 );.  pcach
5d00: 65 52 65 6d 6f 76 65 46 72 6f 6d 48 61 73 68 28  eRemoveFromHash(
5d10: 70 29 3b 0a 20 20 70 2d 3e 70 67 6e 6f 20 3d 20  p);.  p->pgno = 
5d20: 6e 65 77 50 67 6e 6f 3b 0a 20 20 69 66 28 20 6e  newPgno;.  if( n
5d30: 65 77 50 67 6e 6f 3d 3d 30 20 29 7b 0a 20 20 20  ewPgno==0 ){.   
5d40: 20 70 2d 3e 66 6c 61 67 73 20 7c 3d 20 50 47 48   p->flags |= PGH
5d50: 44 52 5f 52 45 55 53 45 5f 55 4e 4c 49 4b 45 4c  DR_REUSE_UNLIKEL
5d60: 59 3b 0a 20 20 20 20 70 63 61 63 68 65 45 6e 74  Y;.    pcacheEnt
5d70: 65 72 47 6c 6f 62 61 6c 28 29 3b 0a 20 20 20 20  erGlobal();.    
5d80: 70 63 61 63 68 65 46 72 65 65 28 70 2d 3e 61 70  pcacheFree(p->ap
5d90: 53 61 76 65 5b 30 5d 29 3b 0a 20 20 20 20 70 63  Save[0]);.    pc
5da0: 61 63 68 65 46 72 65 65 28 70 2d 3e 61 70 53 61  acheFree(p->apSa
5db0: 76 65 5b 31 5d 29 3b 0a 20 20 20 20 70 63 61 63  ve[1]);.    pcac
5dc0: 68 65 45 78 69 74 47 6c 6f 62 61 6c 28 29 3b 0a  heExitGlobal();.
5dd0: 20 20 20 20 70 2d 3e 61 70 53 61 76 65 5b 30 5d      p->apSave[0]
5de0: 20 3d 20 30 3b 0a 20 20 20 20 70 2d 3e 61 70 53   = 0;.    p->apS
5df0: 61 76 65 5b 31 5d 20 3d 20 30 3b 0a 20 20 20 20  ave[1] = 0;.    
5e00: 73 71 6c 69 74 65 33 50 63 61 63 68 65 4d 61 6b  sqlite3PcacheMak
5e10: 65 43 6c 65 61 6e 28 70 29 3b 0a 20 20 7d 0a 20  eClean(p);.  }. 
5e20: 20 70 63 61 63 68 65 41 64 64 54 6f 48 61 73 68   pcacheAddToHash
5e30: 28 70 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 52 65  (p);.}../*.** Re
5e40: 6d 6f 76 65 20 61 6c 6c 20 63 6f 6e 74 65 6e 74  move all content
5e50: 20 66 72 6f 6d 20 61 20 70 61 67 65 20 63 61 63   from a page cac
5e60: 68 65 0a 2a 2f 0a 76 6f 69 64 20 70 63 61 63 68  he.*/.void pcach
5e70: 65 43 6c 65 61 72 28 50 43 61 63 68 65 20 2a 70  eClear(PCache *p
5e80: 43 61 63 68 65 29 7b 0a 20 20 50 67 48 64 72 20  Cache){.  PgHdr 
5e90: 2a 70 2c 20 2a 70 4e 65 78 74 3b 0a 20 20 61 73  *p, *pNext;.  as
5ea0: 73 65 72 74 28 20 73 71 6c 69 74 65 33 5f 6d 75  sert( sqlite3_mu
5eb0: 74 65 78 5f 68 65 6c 64 28 70 63 61 63 68 65 2e  tex_held(pcache.
5ec0: 6d 75 74 65 78 29 20 29 3b 0a 20 20 66 6f 72 28  mutex) );.  for(
5ed0: 70 3d 70 43 61 63 68 65 2d 3e 70 43 6c 65 61 6e  p=pCache->pClean
5ee0: 3b 20 70 3b 20 70 3d 70 4e 65 78 74 29 7b 0a 20  ; p; p=pNext){. 
5ef0: 20 20 20 70 4e 65 78 74 20 3d 20 70 2d 3e 70 4e     pNext = p->pN
5f00: 65 78 74 3b 0a 20 20 20 20 70 63 61 63 68 65 52  ext;.    pcacheR
5f10: 65 6d 6f 76 65 46 72 6f 6d 4c 72 75 4c 69 73 74  emoveFromLruList
5f20: 28 70 29 3b 0a 20 20 20 20 70 63 61 63 68 65 50  (p);.    pcacheP
5f30: 61 67 65 46 72 65 65 28 70 29 3b 0a 20 20 7d 0a  ageFree(p);.  }.
5f40: 20 20 66 6f 72 28 70 3d 70 43 61 63 68 65 2d 3e    for(p=pCache->
5f50: 70 44 69 72 74 79 3b 20 70 3b 20 70 3d 70 4e 65  pDirty; p; p=pNe
5f60: 78 74 29 7b 0a 20 20 20 20 70 4e 65 78 74 20 3d  xt){.    pNext =
5f70: 20 70 2d 3e 70 4e 65 78 74 3b 0a 20 20 20 20 70   p->pNext;.    p
5f80: 63 61 63 68 65 50 61 67 65 46 72 65 65 28 70 29  cachePageFree(p)
5f90: 3b 0a 20 20 7d 0a 20 20 70 43 61 63 68 65 2d 3e  ;.  }.  pCache->
5fa0: 70 43 6c 65 61 6e 20 3d 20 30 3b 0a 20 20 70 43  pClean = 0;.  pC
5fb0: 61 63 68 65 2d 3e 70 44 69 72 74 79 20 3d 20 30  ache->pDirty = 0
5fc0: 3b 0a 20 20 70 43 61 63 68 65 2d 3e 70 44 69 72  ;.  pCache->pDir
5fd0: 74 79 54 61 69 6c 20 3d 20 30 3b 0a 20 20 70 43  tyTail = 0;.  pC
5fe0: 61 63 68 65 2d 3e 6e 50 61 67 65 20 3d 20 30 3b  ache->nPage = 0;
5ff0: 0a 20 20 70 43 61 63 68 65 2d 3e 6e 50 69 6e 6e  .  pCache->nPinn
6000: 65 64 20 3d 20 30 3b 0a 20 20 6d 65 6d 73 65 74  ed = 0;.  memset
6010: 28 70 43 61 63 68 65 2d 3e 61 70 48 61 73 68 2c  (pCache->apHash,
6020: 20 30 2c 20 70 43 61 63 68 65 2d 3e 6e 48 61 73   0, pCache->nHas
6030: 68 2a 73 69 7a 65 6f 66 28 70 43 61 63 68 65 2d  h*sizeof(pCache-
6040: 3e 61 70 48 61 73 68 5b 30 5d 29 29 3b 0a 7d 0a  >apHash[0]));.}.
6050: 0a 0a 2f 2a 0a 2a 2a 20 44 72 6f 70 20 65 76 65  ../*.** Drop eve
6060: 72 79 20 63 61 63 68 65 20 65 6e 74 72 79 20 77  ry cache entry w
6070: 68 6f 73 65 20 70 61 67 65 20 6e 75 6d 62 65 72  hose page number
6080: 20 69 73 20 67 72 65 61 74 65 72 20 74 68 61 6e   is greater than
6090: 20 22 70 67 6e 6f 22 2e 0a 2a 2f 0a 76 6f 69 64   "pgno"..*/.void
60a0: 20 73 71 6c 69 74 65 33 50 63 61 63 68 65 54 72   sqlite3PcacheTr
60b0: 75 6e 63 61 74 65 28 50 43 61 63 68 65 20 2a 70  uncate(PCache *p
60c0: 43 61 63 68 65 2c 20 50 67 6e 6f 20 70 67 6e 6f  Cache, Pgno pgno
60d0: 29 7b 0a 20 20 50 67 48 64 72 20 2a 70 2c 20 2a  ){.  PgHdr *p, *
60e0: 70 4e 65 78 74 3b 0a 20 20 50 67 48 64 72 20 2a  pNext;.  PgHdr *
60f0: 70 44 69 72 74 79 20 3d 20 70 43 61 63 68 65 2d  pDirty = pCache-
6100: 3e 70 44 69 72 74 79 3b 0a 20 20 70 63 61 63 68  >pDirty;.  pcach
6110: 65 45 6e 74 65 72 47 6c 6f 62 61 6c 28 29 3b 0a  eEnterGlobal();.
6120: 20 20 66 6f 72 28 70 3d 70 43 61 63 68 65 2d 3e    for(p=pCache->
6130: 70 43 6c 65 61 6e 3b 20 70 7c 7c 70 44 69 72 74  pClean; p||pDirt
6140: 79 3b 20 70 3d 70 4e 65 78 74 29 7b 0a 20 20 20  y; p=pNext){.   
6150: 20 69 66 28 20 21 70 20 29 7b 0a 20 20 20 20 20   if( !p ){.     
6160: 20 70 20 3d 20 70 44 69 72 74 79 3b 0a 20 20 20   p = pDirty;.   
6170: 20 20 20 70 44 69 72 74 79 20 3d 20 30 3b 0a 20     pDirty = 0;. 
6180: 20 20 20 7d 0a 20 20 20 20 70 4e 65 78 74 20 3d     }.    pNext =
6190: 20 70 2d 3e 70 4e 65 78 74 3b 0a 20 20 20 20 69   p->pNext;.    i
61a0: 66 28 20 70 2d 3e 70 67 6e 6f 3e 70 67 6e 6f 20  f( p->pgno>pgno 
61b0: 29 7b 0a 20 20 20 20 20 20 69 66 28 20 70 2d 3e  ){.      if( p->
61c0: 6e 52 65 66 3d 3d 30 20 29 7b 0a 20 20 20 20 20  nRef==0 ){.     
61d0: 20 20 20 70 63 61 63 68 65 52 65 6d 6f 76 65 46     pcacheRemoveF
61e0: 72 6f 6d 48 61 73 68 28 70 29 3b 0a 20 20 20 20  romHash(p);.    
61f0: 20 20 20 20 69 66 28 20 70 2d 3e 66 6c 61 67 73      if( p->flags
6200: 26 50 47 48 44 52 5f 44 49 52 54 59 20 29 7b 0a  &PGHDR_DIRTY ){.
6210: 20 20 20 20 20 20 20 20 20 20 70 63 61 63 68 65            pcache
6220: 52 65 6d 6f 76 65 46 72 6f 6d 4c 69 73 74 28 26  RemoveFromList(&
6230: 70 43 61 63 68 65 2d 3e 70 44 69 72 74 79 2c 20  pCache->pDirty, 
6240: 70 29 3b 0a 20 20 20 20 20 20 20 20 20 20 70 43  p);.          pC
6250: 61 63 68 65 2d 3e 6e 50 69 6e 6e 65 64 2d 2d 3b  ache->nPinned--;
6260: 0a 20 20 20 20 20 20 20 20 7d 65 6c 73 65 7b 0a  .        }else{.
6270: 20 20 20 20 20 20 20 20 20 20 70 63 61 63 68 65            pcache
6280: 52 65 6d 6f 76 65 46 72 6f 6d 4c 69 73 74 28 26  RemoveFromList(&
6290: 70 43 61 63 68 65 2d 3e 70 43 6c 65 61 6e 2c 20  pCache->pClean, 
62a0: 70 29 3b 0a 20 20 20 20 20 20 20 20 20 20 70 63  p);.          pc
62b0: 61 63 68 65 52 65 6d 6f 76 65 46 72 6f 6d 4c 72  acheRemoveFromLr
62c0: 75 4c 69 73 74 28 70 29 3b 0a 20 20 20 20 20 20  uList(p);.      
62d0: 20 20 7d 0a 20 20 20 20 20 20 20 20 70 63 61 63    }.        pcac
62e0: 68 65 50 61 67 65 46 72 65 65 28 70 29 3b 0a 20  hePageFree(p);. 
62f0: 20 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20       }else{.    
6300: 20 20 20 20 2f 2a 20 49 66 20 74 68 65 72 65 20      /* If there 
6310: 61 72 65 20 72 65 66 65 72 65 6e 63 65 73 20 74  are references t
6320: 6f 20 74 68 65 20 70 61 67 65 2c 20 69 74 20 63  o the page, it c
6330: 61 6e 6e 6f 74 20 62 65 20 66 72 65 65 64 2e 20  annot be freed. 
6340: 49 6e 20 74 68 69 73 0a 20 20 20 20 20 20 20 20  In this.        
6350: 2a 2a 20 63 61 73 65 2c 20 7a 65 72 6f 20 74 68  ** case, zero th
6360: 65 20 70 61 67 65 20 63 6f 6e 74 65 6e 74 20 69  e page content i
6370: 6e 73 74 65 61 64 2e 0a 20 20 20 20 20 20 20 20  nstead..        
6380: 2a 2f 0a 20 20 20 20 20 20 20 20 6d 65 6d 73 65  */.        memse
6390: 74 28 70 2d 3e 70 44 61 74 61 2c 20 30 2c 20 70  t(p->pData, 0, p
63a0: 43 61 63 68 65 2d 3e 73 7a 50 61 67 65 29 3b 0a  Cache->szPage);.
63b0: 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a 20 20        }.    }.  
63c0: 7d 0a 20 20 70 63 61 63 68 65 45 78 69 74 47 6c  }.  pcacheExitGl
63d0: 6f 62 61 6c 28 29 3b 0a 7d 0a 0a 0a 2f 2a 0a 2a  obal();.}.../*.*
63e0: 2a 20 43 6c 6f 73 65 20 61 20 63 61 63 68 65 2e  * Close a cache.
63f0: 0a 2a 2f 0a 76 6f 69 64 20 73 71 6c 69 74 65 33  .*/.void sqlite3
6400: 50 63 61 63 68 65 43 6c 6f 73 65 28 50 43 61 63  PcacheClose(PCac
6410: 68 65 20 2a 70 43 61 63 68 65 29 7b 0a 20 20 70  he *pCache){.  p
6420: 63 61 63 68 65 45 6e 74 65 72 47 6c 6f 62 61 6c  cacheEnterGlobal
6430: 28 29 3b 0a 0a 20 20 2f 2a 20 46 72 65 65 20 61  ();..  /* Free a
6440: 6c 6c 20 74 68 65 20 70 61 67 65 73 20 75 73 65  ll the pages use
6450: 64 20 62 79 20 74 68 69 73 20 70 61 67 65 72 20  d by this pager 
6460: 61 6e 64 20 72 65 6d 6f 76 65 20 74 68 65 6d 20  and remove them 
6470: 66 72 6f 6d 20 74 68 65 20 4c 52 55 20 6c 69 73  from the LRU lis
6480: 74 2e 20 2a 2f 0a 20 20 70 63 61 63 68 65 43 6c  t. */.  pcacheCl
6490: 65 61 72 28 70 43 61 63 68 65 29 3b 0a 20 20 69  ear(pCache);.  i
64a0: 66 28 20 70 43 61 63 68 65 2d 3e 62 50 75 72 67  f( pCache->bPurg
64b0: 65 61 62 6c 65 20 29 7b 0a 20 20 20 20 70 63 61  eable ){.    pca
64c0: 63 68 65 2e 6e 4d 61 78 50 61 67 65 20 2d 3d 20  che.nMaxPage -= 
64d0: 70 43 61 63 68 65 2d 3e 6e 4d 61 78 3b 0a 20 20  pCache->nMax;.  
64e0: 20 20 70 63 61 63 68 65 2e 6e 4d 69 6e 50 61 67    pcache.nMinPag
64f0: 65 20 2d 3d 20 70 43 61 63 68 65 2d 3e 6e 4d 69  e -= pCache->nMi
6500: 6e 3b 0a 20 20 7d 0a 20 20 73 71 6c 69 74 65 33  n;.  }.  sqlite3
6510: 5f 66 72 65 65 28 70 43 61 63 68 65 2d 3e 61 70  _free(pCache->ap
6520: 48 61 73 68 29 3b 0a 0a 20 20 70 63 61 63 68 65  Hash);..  pcache
6530: 45 78 69 74 47 6c 6f 62 61 6c 28 29 3b 0a 7d 0a  ExitGlobal();.}.
6540: 0a 2f 2a 0a 2a 2a 20 50 72 65 73 65 72 76 65 20  ./*.** Preserve 
6550: 74 68 65 20 63 6f 6e 74 65 6e 74 20 6f 66 20 74  the content of t
6560: 68 65 20 70 61 67 65 2c 20 69 66 20 69 74 20 68  he page, if it h
6570: 61 73 20 6e 6f 74 20 62 65 65 6e 20 70 72 65 73  as not been pres
6580: 65 72 76 65 64 0a 2a 2a 20 61 6c 72 65 61 64 79  erved.** already
6590: 2e 20 20 49 66 20 69 64 4a 6f 75 72 6e 61 6c 3d  .  If idJournal=
65a0: 3d 30 20 74 68 65 6e 20 74 68 69 73 20 69 73 20  =0 then this is 
65b0: 66 6f 72 20 74 68 65 20 6f 76 65 72 61 6c 6c 20  for the overall 
65c0: 74 72 61 6e 73 61 63 74 69 6f 6e 2e 0a 2a 2a 20  transaction..** 
65d0: 49 66 20 69 64 4a 6f 75 72 6e 61 6c 3d 3d 31 20  If idJournal==1 
65e0: 74 68 65 6e 20 74 68 69 73 20 69 73 20 66 6f 72  then this is for
65f0: 20 74 68 65 20 73 74 61 74 65 6d 65 6e 74 20 6a   the statement j
6600: 6f 75 72 6e 61 6c 2e 0a 2a 2a 0a 2a 2a 20 54 68  ournal..**.** Th
6610: 69 73 20 72 6f 75 74 69 6e 65 20 69 73 20 75 73  is routine is us
6620: 65 64 20 66 6f 72 20 69 6e 2d 6d 65 6d 6f 72 79  ed for in-memory
6630: 20 64 61 74 61 62 61 73 65 73 20 6f 6e 6c 79 2e   databases only.
6640: 0a 2a 2a 0a 2a 2a 20 52 65 74 75 72 6e 20 53 51  .**.** Return SQ
6650: 4c 49 54 45 5f 4f 4b 20 6f 72 20 53 51 4c 49 54  LITE_OK or SQLIT
6660: 45 5f 4e 4f 4d 45 4d 20 69 66 20 61 20 6d 65 6d  E_NOMEM if a mem
6670: 6f 72 79 20 61 6c 6c 6f 63 61 74 69 6f 6e 20 66  ory allocation f
6680: 61 69 6c 73 2e 0a 2a 2f 0a 69 6e 74 20 73 71 6c  ails..*/.int sql
6690: 69 74 65 33 50 63 61 63 68 65 50 72 65 73 65 72  ite3PcachePreser
66a0: 76 65 28 50 67 48 64 72 20 2a 70 2c 20 69 6e 74  ve(PgHdr *p, int
66b0: 20 69 64 4a 6f 75 72 6e 61 6c 29 7b 0a 20 20 76   idJournal){.  v
66c0: 6f 69 64 20 2a 78 3b 0a 20 20 69 6e 74 20 73 7a  oid *x;.  int sz
66d0: 3b 0a 20 20 61 73 73 65 72 74 28 20 70 2d 3e 70  ;.  assert( p->p
66e0: 43 61 63 68 65 2d 3e 62 50 75 72 67 65 61 62 6c  Cache->bPurgeabl
66f0: 65 3d 3d 30 20 29 3b 0a 20 20 69 66 28 20 21 70  e==0 );.  if( !p
6700: 2d 3e 61 70 53 61 76 65 5b 69 64 4a 6f 75 72 6e  ->apSave[idJourn
6710: 61 6c 5d 20 29 7b 0a 20 20 20 20 73 7a 20 3d 20  al] ){.    sz = 
6720: 70 2d 3e 70 43 61 63 68 65 2d 3e 73 7a 50 61 67  p->pCache->szPag
6730: 65 3b 0a 20 20 20 20 70 2d 3e 61 70 53 61 76 65  e;.    p->apSave
6740: 5b 69 64 4a 6f 75 72 6e 61 6c 5d 20 3d 20 78 20  [idJournal] = x 
6750: 3d 20 73 71 6c 69 74 65 33 50 61 67 65 4d 61 6c  = sqlite3PageMal
6760: 6c 6f 63 28 20 73 7a 20 29 3b 0a 20 20 20 20 69  loc( sz );.    i
6770: 66 28 20 78 3d 3d 30 20 29 20 72 65 74 75 72 6e  f( x==0 ) return
6780: 20 53 51 4c 49 54 45 5f 4e 4f 4d 45 4d 3b 0a 20   SQLITE_NOMEM;. 
6790: 20 20 20 6d 65 6d 63 70 79 28 78 2c 20 70 2d 3e     memcpy(x, p->
67a0: 70 44 61 74 61 2c 20 73 7a 29 3b 0a 20 20 7d 0a  pData, sz);.  }.
67b0: 20 20 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f    return SQLITE_
67c0: 4f 4b 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 43 6f 6d  OK;.}../*.** Com
67d0: 6d 69 74 20 61 20 63 68 61 6e 67 65 20 70 72 65  mit a change pre
67e0: 76 69 6f 75 73 6c 79 20 70 72 65 73 65 72 76 65  viously preserve
67f0: 64 2e 0a 2a 2f 0a 76 6f 69 64 20 73 71 6c 69 74  d..*/.void sqlit
6800: 65 33 50 63 61 63 68 65 43 6f 6d 6d 69 74 28 50  e3PcacheCommit(P
6810: 43 61 63 68 65 20 2a 70 43 61 63 68 65 2c 20 69  Cache *pCache, i
6820: 6e 74 20 69 64 4a 6f 75 72 6e 61 6c 29 7b 0a 20  nt idJournal){. 
6830: 20 50 67 48 64 72 20 2a 70 3b 0a 20 20 70 63 61   PgHdr *p;.  pca
6840: 63 68 65 45 6e 74 65 72 47 6c 6f 62 61 6c 28 29  cheEnterGlobal()
6850: 3b 20 20 20 20 20 2f 2a 20 4d 75 74 65 78 20 69  ;     /* Mutex i
6860: 73 20 72 65 71 75 69 72 65 64 20 74 6f 20 63 61  s required to ca
6870: 6c 6c 20 70 63 61 63 68 65 46 72 65 65 28 29 20  ll pcacheFree() 
6880: 2a 2f 0a 20 20 66 6f 72 28 70 3d 70 43 61 63 68  */.  for(p=pCach
6890: 65 2d 3e 70 44 69 72 74 79 3b 20 70 3b 20 70 3d  e->pDirty; p; p=
68a0: 70 2d 3e 70 4e 65 78 74 29 7b 0a 20 20 20 20 69  p->pNext){.    i
68b0: 66 28 20 70 2d 3e 61 70 53 61 76 65 5b 69 64 4a  f( p->apSave[idJ
68c0: 6f 75 72 6e 61 6c 5d 20 29 7b 0a 20 20 20 20 20  ournal] ){.     
68d0: 20 70 63 61 63 68 65 46 72 65 65 28 70 2d 3e 61   pcacheFree(p->a
68e0: 70 53 61 76 65 5b 69 64 4a 6f 75 72 6e 61 6c 5d  pSave[idJournal]
68f0: 29 3b 0a 20 20 20 20 20 20 70 2d 3e 61 70 53 61  );.      p->apSa
6900: 76 65 5b 69 64 4a 6f 75 72 6e 61 6c 5d 20 3d 20  ve[idJournal] = 
6910: 30 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20 70  0;.    }.  }.  p
6920: 63 61 63 68 65 45 78 69 74 47 6c 6f 62 61 6c 28  cacheExitGlobal(
6930: 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 52 6f 6c 6c  );.}../*.** Roll
6940: 62 61 63 6b 20 61 20 63 68 61 6e 67 65 20 70 72  back a change pr
6950: 65 76 69 6f 75 73 6c 79 20 70 72 65 73 65 72 76  eviously preserv
6960: 65 64 2e 0a 2a 2f 0a 76 6f 69 64 20 73 71 6c 69  ed..*/.void sqli
6970: 74 65 33 50 63 61 63 68 65 52 6f 6c 6c 62 61 63  te3PcacheRollbac
6980: 6b 28 50 43 61 63 68 65 20 2a 70 43 61 63 68 65  k(PCache *pCache
6990: 2c 20 69 6e 74 20 69 64 4a 6f 75 72 6e 61 6c 29  , int idJournal)
69a0: 7b 0a 20 20 50 67 48 64 72 20 2a 70 3b 0a 20 20  {.  PgHdr *p;.  
69b0: 69 6e 74 20 73 7a 3b 0a 20 20 70 63 61 63 68 65  int sz;.  pcache
69c0: 45 6e 74 65 72 47 6c 6f 62 61 6c 28 29 3b 20 20  EnterGlobal();  
69d0: 20 20 20 2f 2a 20 4d 75 74 65 78 20 69 73 20 72     /* Mutex is r
69e0: 65 71 75 69 72 65 64 20 74 6f 20 63 61 6c 6c 20  equired to call 
69f0: 70 63 61 63 68 65 46 72 65 65 28 29 20 2a 2f 0a  pcacheFree() */.
6a00: 20 20 73 7a 20 3d 20 70 43 61 63 68 65 2d 3e 73    sz = pCache->s
6a10: 7a 50 61 67 65 3b 0a 20 20 66 6f 72 28 70 3d 70  zPage;.  for(p=p
6a20: 43 61 63 68 65 2d 3e 70 44 69 72 74 79 3b 20 70  Cache->pDirty; p
6a30: 3b 20 70 3d 70 2d 3e 70 4e 65 78 74 29 7b 0a 20  ; p=p->pNext){. 
6a40: 20 20 20 69 66 28 20 70 2d 3e 61 70 53 61 76 65     if( p->apSave
6a50: 5b 69 64 4a 6f 75 72 6e 61 6c 5d 20 29 7b 0a 20  [idJournal] ){. 
6a60: 20 20 20 20 20 6d 65 6d 63 70 79 28 70 2d 3e 70       memcpy(p->p
6a70: 44 61 74 61 2c 20 70 2d 3e 61 70 53 61 76 65 5b  Data, p->apSave[
6a80: 69 64 4a 6f 75 72 6e 61 6c 5d 2c 20 73 7a 29 3b  idJournal], sz);
6a90: 0a 20 20 20 20 20 20 70 63 61 63 68 65 46 72 65  .      pcacheFre
6aa0: 65 28 70 2d 3e 61 70 53 61 76 65 5b 69 64 4a 6f  e(p->apSave[idJo
6ab0: 75 72 6e 61 6c 5d 29 3b 0a 20 20 20 20 20 20 70  urnal]);.      p
6ac0: 2d 3e 61 70 53 61 76 65 5b 69 64 4a 6f 75 72 6e  ->apSave[idJourn
6ad0: 61 6c 5d 20 3d 20 30 3b 0a 20 20 20 20 7d 0a 20  al] = 0;.    }. 
6ae0: 20 7d 0a 20 20 70 63 61 63 68 65 45 78 69 74 47   }.  pcacheExitG
6af0: 6c 6f 62 61 6c 28 29 3b 0a 7d 0a 0a 2f 2a 20 0a  lobal();.}../* .
6b00: 2a 2a 20 41 73 73 65 72 74 20 66 6c 61 67 73 20  ** Assert flags 
6b10: 73 65 74 74 69 6e 67 73 20 6f 6e 20 61 6c 6c 20  settings on all 
6b20: 70 61 67 65 73 2e 20 20 44 65 62 75 67 67 69 6e  pages.  Debuggin
6b30: 67 20 6f 6e 6c 79 2e 0a 2a 2f 0a 76 6f 69 64 20  g only..*/.void 
6b40: 73 71 6c 69 74 65 33 50 63 61 63 68 65 41 73 73  sqlite3PcacheAss
6b50: 65 72 74 46 6c 61 67 73 28 50 43 61 63 68 65 20  ertFlags(PCache 
6b60: 2a 70 43 61 63 68 65 2c 20 69 6e 74 20 74 72 75  *pCache, int tru
6b70: 65 4d 61 73 6b 2c 20 69 6e 74 20 66 61 6c 73 65  eMask, int false
6b80: 4d 61 73 6b 29 7b 0a 20 20 50 67 48 64 72 20 2a  Mask){.  PgHdr *
6b90: 70 3b 0a 20 20 66 6f 72 28 70 3d 70 43 61 63 68  p;.  for(p=pCach
6ba0: 65 2d 3e 70 44 69 72 74 79 3b 20 70 3b 20 70 3d  e->pDirty; p; p=
6bb0: 70 2d 3e 70 4e 65 78 74 29 7b 0a 20 20 20 20 61  p->pNext){.    a
6bc0: 73 73 65 72 74 28 20 28 70 2d 3e 66 6c 61 67 73  ssert( (p->flags
6bd0: 26 74 72 75 65 4d 61 73 6b 29 3d 3d 74 72 75 65  &trueMask)==true
6be0: 4d 61 73 6b 20 29 3b 0a 20 20 20 20 61 73 73 65  Mask );.    asse
6bf0: 72 74 28 20 28 70 2d 3e 66 6c 61 67 73 26 66 61  rt( (p->flags&fa
6c00: 6c 73 65 4d 61 73 6b 29 3d 3d 30 20 29 3b 0a 20  lseMask)==0 );. 
6c10: 20 7d 0a 20 20 66 6f 72 28 70 3d 70 43 61 63 68   }.  for(p=pCach
6c20: 65 2d 3e 70 43 6c 65 61 6e 3b 20 70 3b 20 70 3d  e->pClean; p; p=
6c30: 70 2d 3e 70 4e 65 78 74 29 7b 0a 20 20 20 20 61  p->pNext){.    a
6c40: 73 73 65 72 74 28 20 28 70 2d 3e 66 6c 61 67 73  ssert( (p->flags
6c50: 26 74 72 75 65 4d 61 73 6b 29 3d 3d 74 72 75 65  &trueMask)==true
6c60: 4d 61 73 6b 20 29 3b 0a 20 20 20 20 61 73 73 65  Mask );.    asse
6c70: 72 74 28 20 28 70 2d 3e 66 6c 61 67 73 26 66 61  rt( (p->flags&fa
6c80: 6c 73 65 4d 61 73 6b 29 3d 3d 30 20 29 3b 0a 20  lseMask)==0 );. 
6c90: 20 7d 0a 7d 0a 0a 2f 2a 20 0a 2a 2a 20 44 69 73   }.}../* .** Dis
6ca0: 63 61 72 64 20 74 68 65 20 63 6f 6e 74 65 6e 74  card the content
6cb0: 73 20 6f 66 20 74 68 65 20 63 61 63 68 65 2e 0a  s of the cache..
6cc0: 2a 2f 0a 69 6e 74 20 73 71 6c 69 74 65 33 50 63  */.int sqlite3Pc
6cd0: 61 63 68 65 43 6c 65 61 72 28 50 43 61 63 68 65  acheClear(PCache
6ce0: 20 2a 70 43 61 63 68 65 29 7b 0a 20 20 61 73 73   *pCache){.  ass
6cf0: 65 72 74 28 70 43 61 63 68 65 2d 3e 6e 52 65 66  ert(pCache->nRef
6d00: 3d 3d 30 29 3b 0a 20 20 70 63 61 63 68 65 45 6e  ==0);.  pcacheEn
6d10: 74 65 72 47 6c 6f 62 61 6c 28 29 3b 0a 20 20 70  terGlobal();.  p
6d20: 63 61 63 68 65 43 6c 65 61 72 28 70 43 61 63 68  cacheClear(pCach
6d30: 65 29 3b 0a 20 20 70 63 61 63 68 65 45 78 69 74  e);.  pcacheExit
6d40: 47 6c 6f 62 61 6c 28 29 3b 0a 20 20 72 65 74 75  Global();.  retu
6d50: 72 6e 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 7d 0a  rn SQLITE_OK;.}.
6d60: 0a 2f 2a 0a 2a 2a 20 4d 65 72 67 65 20 74 77 6f  ./*.** Merge two
6d70: 20 6c 69 73 74 73 20 6f 66 20 70 61 67 65 73 20   lists of pages 
6d80: 63 6f 6e 6e 65 63 74 65 64 20 62 79 20 70 44 69  connected by pDi
6d90: 72 74 79 20 61 6e 64 20 69 6e 20 70 67 6e 6f 20  rty and in pgno 
6da0: 6f 72 64 65 72 2e 0a 2a 2a 20 44 6f 20 6e 6f 74  order..** Do not
6db0: 20 62 6f 74 68 20 66 69 78 69 6e 67 20 74 68 65   both fixing the
6dc0: 20 70 50 72 65 76 44 69 72 74 79 20 70 6f 69 6e   pPrevDirty poin
6dd0: 74 65 72 73 2e 0a 2a 2f 0a 73 74 61 74 69 63 20  ters..*/.static 
6de0: 50 67 48 64 72 20 2a 70 63 61 63 68 65 4d 65 72  PgHdr *pcacheMer
6df0: 67 65 44 69 72 74 79 4c 69 73 74 28 50 67 48 64  geDirtyList(PgHd
6e00: 72 20 2a 70 41 2c 20 50 67 48 64 72 20 2a 70 42  r *pA, PgHdr *pB
6e10: 29 7b 0a 20 20 50 67 48 64 72 20 72 65 73 75 6c  ){.  PgHdr resul
6e20: 74 2c 20 2a 70 54 61 69 6c 3b 0a 20 20 70 54 61  t, *pTail;.  pTa
6e30: 69 6c 20 3d 20 26 72 65 73 75 6c 74 3b 0a 20 20  il = &result;.  
6e40: 77 68 69 6c 65 28 20 70 41 20 26 26 20 70 42 20  while( pA && pB 
6e50: 29 7b 0a 20 20 20 20 69 66 28 20 70 41 2d 3e 70  ){.    if( pA->p
6e60: 67 6e 6f 3c 70 42 2d 3e 70 67 6e 6f 20 29 7b 0a  gno<pB->pgno ){.
6e70: 20 20 20 20 20 20 70 54 61 69 6c 2d 3e 70 44 69        pTail->pDi
6e80: 72 74 79 20 3d 20 70 41 3b 0a 20 20 20 20 20 20  rty = pA;.      
6e90: 70 54 61 69 6c 20 3d 20 70 41 3b 0a 20 20 20 20  pTail = pA;.    
6ea0: 20 20 70 41 20 3d 20 70 41 2d 3e 70 44 69 72 74    pA = pA->pDirt
6eb0: 79 3b 0a 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20  y;.    }else{.  
6ec0: 20 20 20 20 70 54 61 69 6c 2d 3e 70 44 69 72 74      pTail->pDirt
6ed0: 79 20 3d 20 70 42 3b 0a 20 20 20 20 20 20 70 54  y = pB;.      pT
6ee0: 61 69 6c 20 3d 20 70 42 3b 0a 20 20 20 20 20 20  ail = pB;.      
6ef0: 70 42 20 3d 20 70 42 2d 3e 70 44 69 72 74 79 3b  pB = pB->pDirty;
6f00: 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20 69 66 28  .    }.  }.  if(
6f10: 20 70 41 20 29 7b 0a 20 20 20 20 70 54 61 69 6c   pA ){.    pTail
6f20: 2d 3e 70 44 69 72 74 79 20 3d 20 70 41 3b 0a 20  ->pDirty = pA;. 
6f30: 20 7d 65 6c 73 65 20 69 66 28 20 70 42 20 29 7b   }else if( pB ){
6f40: 0a 20 20 20 20 70 54 61 69 6c 2d 3e 70 44 69 72  .    pTail->pDir
6f50: 74 79 20 3d 20 70 42 3b 0a 20 20 7d 65 6c 73 65  ty = pB;.  }else
6f60: 7b 0a 20 20 20 20 70 54 61 69 6c 2d 3e 70 44 69  {.    pTail->pDi
6f70: 72 74 79 20 3d 20 30 3b 0a 20 20 7d 0a 20 20 72  rty = 0;.  }.  r
6f80: 65 74 75 72 6e 20 72 65 73 75 6c 74 2e 70 44 69  eturn result.pDi
6f90: 72 74 79 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 53 6f  rty;.}../*.** So
6fa0: 72 74 20 74 68 65 20 6c 69 73 74 20 6f 66 20 70  rt the list of p
6fb0: 61 67 65 73 20 69 6e 20 61 63 63 65 6e 64 69 6e  ages in accendin
6fc0: 67 20 6f 72 64 65 72 20 62 79 20 70 67 6e 6f 2e  g order by pgno.
6fd0: 20 20 50 61 67 65 73 20 61 72 65 0a 2a 2a 20 63    Pages are.** c
6fe0: 6f 6e 6e 65 63 74 65 64 20 62 79 20 70 44 69 72  onnected by pDir
6ff0: 74 79 20 70 6f 69 6e 74 65 72 73 2e 20 20 54 68  ty pointers.  Th
7000: 65 20 70 50 72 65 76 44 69 72 74 79 20 70 6f 69  e pPrevDirty poi
7010: 6e 74 65 72 73 20 61 72 65 0a 2a 2a 20 63 6f 72  nters are.** cor
7020: 72 75 70 74 65 64 20 62 79 20 74 68 69 73 20 73  rupted by this s
7030: 6f 72 74 2e 0a 2a 2f 0a 23 64 65 66 69 6e 65 20  ort..*/.#define 
7040: 4e 5f 53 4f 52 54 5f 42 55 43 4b 45 54 5f 41 4c  N_SORT_BUCKET_AL
7050: 4c 4f 43 20 32 35 0a 23 64 65 66 69 6e 65 20 4e  LOC 25.#define N
7060: 5f 53 4f 52 54 5f 42 55 43 4b 45 54 20 20 20 20  _SORT_BUCKET    
7070: 20 20 20 32 35 0a 23 69 66 64 65 66 20 53 51 4c     25.#ifdef SQL
7080: 49 54 45 5f 54 45 53 54 0a 20 20 69 6e 74 20 73  ITE_TEST.  int s
7090: 71 6c 69 74 65 33 5f 70 61 67 65 72 5f 6e 5f 73  qlite3_pager_n_s
70a0: 6f 72 74 5f 62 75 63 6b 65 74 20 3d 20 30 3b 0a  ort_bucket = 0;.
70b0: 20 20 23 75 6e 64 65 66 20 4e 5f 53 4f 52 54 5f    #undef N_SORT_
70c0: 42 55 43 4b 45 54 0a 20 20 23 64 65 66 69 6e 65  BUCKET.  #define
70d0: 20 4e 5f 53 4f 52 54 5f 42 55 43 4b 45 54 20 5c   N_SORT_BUCKET \
70e0: 0a 20 20 20 28 73 71 6c 69 74 65 33 5f 70 61 67  .   (sqlite3_pag
70f0: 65 72 5f 6e 5f 73 6f 72 74 5f 62 75 63 6b 65 74  er_n_sort_bucket
7100: 3f 73 71 6c 69 74 65 33 5f 70 61 67 65 72 5f 6e  ?sqlite3_pager_n
7110: 5f 73 6f 72 74 5f 62 75 63 6b 65 74 3a 4e 5f 53  _sort_bucket:N_S
7120: 4f 52 54 5f 42 55 43 4b 45 54 5f 41 4c 4c 4f 43  ORT_BUCKET_ALLOC
7130: 29 0a 23 65 6e 64 69 66 0a 73 74 61 74 69 63 20  ).#endif.static 
7140: 50 67 48 64 72 20 2a 70 63 61 63 68 65 53 6f 72  PgHdr *pcacheSor
7150: 74 44 69 72 74 79 4c 69 73 74 28 50 67 48 64 72  tDirtyList(PgHdr
7160: 20 2a 70 49 6e 29 7b 0a 20 20 50 67 48 64 72 20   *pIn){.  PgHdr 
7170: 2a 61 5b 4e 5f 53 4f 52 54 5f 42 55 43 4b 45 54  *a[N_SORT_BUCKET
7180: 5f 41 4c 4c 4f 43 5d 2c 20 2a 70 3b 0a 20 20 69  _ALLOC], *p;.  i
7190: 6e 74 20 69 3b 0a 20 20 6d 65 6d 73 65 74 28 61  nt i;.  memset(a
71a0: 2c 20 30 2c 20 73 69 7a 65 6f 66 28 61 29 29 3b  , 0, sizeof(a));
71b0: 0a 20 20 77 68 69 6c 65 28 20 70 49 6e 20 29 7b  .  while( pIn ){
71c0: 0a 20 20 20 20 70 20 3d 20 70 49 6e 3b 0a 20 20  .    p = pIn;.  
71d0: 20 20 70 49 6e 20 3d 20 70 2d 3e 70 44 69 72 74    pIn = p->pDirt
71e0: 79 3b 0a 20 20 20 20 70 2d 3e 70 44 69 72 74 79  y;.    p->pDirty
71f0: 20 3d 20 30 3b 0a 20 20 20 20 66 6f 72 28 69 3d   = 0;.    for(i=
7200: 30 3b 20 69 3c 4e 5f 53 4f 52 54 5f 42 55 43 4b  0; i<N_SORT_BUCK
7210: 45 54 2d 31 3b 20 69 2b 2b 29 7b 0a 20 20 20 20  ET-1; i++){.    
7220: 20 20 69 66 28 20 61 5b 69 5d 3d 3d 30 20 29 7b    if( a[i]==0 ){
7230: 0a 20 20 20 20 20 20 20 20 61 5b 69 5d 20 3d 20  .        a[i] = 
7240: 70 3b 0a 20 20 20 20 20 20 20 20 62 72 65 61 6b  p;.        break
7250: 3b 0a 20 20 20 20 20 20 7d 65 6c 73 65 7b 0a 20  ;.      }else{. 
7260: 20 20 20 20 20 20 20 70 20 3d 20 70 63 61 63 68         p = pcach
7270: 65 4d 65 72 67 65 44 69 72 74 79 4c 69 73 74 28  eMergeDirtyList(
7280: 61 5b 69 5d 2c 20 70 29 3b 0a 20 20 20 20 20 20  a[i], p);.      
7290: 20 20 61 5b 69 5d 20 3d 20 30 3b 0a 20 20 20 20    a[i] = 0;.    
72a0: 20 20 7d 0a 20 20 20 20 7d 0a 20 20 20 20 69 66    }.    }.    if
72b0: 28 20 69 3d 3d 4e 5f 53 4f 52 54 5f 42 55 43 4b  ( i==N_SORT_BUCK
72c0: 45 54 2d 31 20 29 7b 0a 20 20 20 20 20 20 2f 2a  ET-1 ){.      /*
72d0: 20 43 6f 76 65 72 61 67 65 3a 20 54 6f 20 67 65   Coverage: To ge
72e0: 74 20 68 65 72 65 2c 20 74 68 65 72 65 20 6e 65  t here, there ne
72f0: 65 64 20 74 6f 20 62 65 20 32 5e 28 4e 5f 53 4f  ed to be 2^(N_SO
7300: 52 54 5f 42 55 43 4b 45 54 29 20 0a 20 20 20 20  RT_BUCKET) .    
7310: 20 20 2a 2a 20 65 6c 65 6d 65 6e 74 73 20 69 6e    ** elements in
7320: 20 74 68 65 20 69 6e 70 75 74 20 6c 69 73 74 2e   the input list.
7330: 20 54 68 69 73 20 69 73 20 70 6f 73 73 69 62 6c   This is possibl
7340: 65 2c 20 62 75 74 20 69 6d 70 72 61 63 74 69 63  e, but impractic
7350: 61 6c 2e 0a 20 20 20 20 20 20 2a 2a 20 54 65 73  al..      ** Tes
7360: 74 69 6e 67 20 74 68 69 73 20 6c 69 6e 65 20 69  ting this line i
7370: 73 20 74 68 65 20 70 6f 69 6e 74 20 6f 66 20 67  s the point of g
7380: 6c 6f 62 61 6c 20 76 61 72 69 61 62 6c 65 0a 20  lobal variable. 
7390: 20 20 20 20 20 2a 2a 20 73 71 6c 69 74 65 33 5f       ** sqlite3_
73a0: 70 61 67 65 72 5f 6e 5f 73 6f 72 74 5f 62 75 63  pager_n_sort_buc
73b0: 6b 65 74 2e 0a 20 20 20 20 20 20 2a 2f 0a 20 20  ket..      */.  
73c0: 20 20 20 20 61 5b 69 5d 20 3d 20 70 63 61 63 68      a[i] = pcach
73d0: 65 4d 65 72 67 65 44 69 72 74 79 4c 69 73 74 28  eMergeDirtyList(
73e0: 61 5b 69 5d 2c 20 70 29 3b 0a 20 20 20 20 7d 0a  a[i], p);.    }.
73f0: 20 20 7d 0a 20 20 70 20 3d 20 61 5b 30 5d 3b 0a    }.  p = a[0];.
7400: 20 20 66 6f 72 28 69 3d 31 3b 20 69 3c 4e 5f 53    for(i=1; i<N_S
7410: 4f 52 54 5f 42 55 43 4b 45 54 3b 20 69 2b 2b 29  ORT_BUCKET; i++)
7420: 7b 0a 20 20 20 20 70 20 3d 20 70 63 61 63 68 65  {.    p = pcache
7430: 4d 65 72 67 65 44 69 72 74 79 4c 69 73 74 28 70  MergeDirtyList(p
7440: 2c 20 61 5b 69 5d 29 3b 0a 20 20 7d 0a 20 20 72  , a[i]);.  }.  r
7450: 65 74 75 72 6e 20 70 3b 0a 7d 0a 0a 2f 2a 0a 2a  eturn p;.}../*.*
7460: 2a 20 52 65 74 75 72 6e 20 61 20 6c 69 73 74 20  * Return a list 
7470: 6f 66 20 61 6c 6c 20 64 69 72 74 79 20 70 61 67  of all dirty pag
7480: 65 73 20 69 6e 20 74 68 65 20 63 61 63 68 65 2c  es in the cache,
7490: 20 73 6f 72 74 65 64 20 62 79 20 70 61 67 65 20   sorted by page 
74a0: 6e 75 6d 62 65 72 2e 0a 2a 2f 0a 50 67 48 64 72  number..*/.PgHdr
74b0: 20 2a 73 71 6c 69 74 65 33 50 63 61 63 68 65 44   *sqlite3PcacheD
74c0: 69 72 74 79 4c 69 73 74 28 50 43 61 63 68 65 20  irtyList(PCache 
74d0: 2a 70 43 61 63 68 65 29 7b 0a 20 20 50 67 48 64  *pCache){.  PgHd
74e0: 72 20 2a 70 3b 0a 20 20 66 6f 72 28 70 3d 70 43  r *p;.  for(p=pC
74f0: 61 63 68 65 2d 3e 70 44 69 72 74 79 3b 20 70 3b  ache->pDirty; p;
7500: 20 70 3d 70 2d 3e 70 4e 65 78 74 29 7b 0a 20 20   p=p->pNext){.  
7510: 20 20 70 2d 3e 70 44 69 72 74 79 20 3d 20 70 2d    p->pDirty = p-
7520: 3e 70 4e 65 78 74 3b 0a 20 20 7d 0a 20 20 72 65  >pNext;.  }.  re
7530: 74 75 72 6e 20 70 63 61 63 68 65 53 6f 72 74 44  turn pcacheSortD
7540: 69 72 74 79 4c 69 73 74 28 70 43 61 63 68 65 2d  irtyList(pCache-
7550: 3e 70 44 69 72 74 79 29 3b 0a 7d 0a 0a 2f 2a 20  >pDirty);.}../* 
7560: 0a 2a 2a 20 52 65 74 75 72 6e 20 74 68 65 20 74  .** Return the t
7570: 6f 74 61 6c 20 6e 75 6d 62 65 72 20 6f 66 20 6f  otal number of o
7580: 75 74 73 74 61 6e 64 69 6e 67 20 70 61 67 65 20  utstanding page 
7590: 72 65 66 65 72 65 6e 63 65 73 2e 0a 2a 2f 0a 69  references..*/.i
75a0: 6e 74 20 73 71 6c 69 74 65 33 50 63 61 63 68 65  nt sqlite3Pcache
75b0: 52 65 66 43 6f 75 6e 74 28 50 43 61 63 68 65 20  RefCount(PCache 
75c0: 2a 70 43 61 63 68 65 29 7b 0a 20 20 72 65 74 75  *pCache){.  retu
75d0: 72 6e 20 70 43 61 63 68 65 2d 3e 6e 52 65 66 3b  rn pCache->nRef;
75e0: 0a 7d 0a 0a 2f 2a 20 0a 2a 2a 20 52 65 74 75 72  .}../* .** Retur
75f0: 6e 20 74 68 65 20 74 6f 74 61 6c 20 6e 75 6d 62  n the total numb
7600: 65 72 20 6f 66 20 70 61 67 65 73 20 69 6e 20 74  er of pages in t
7610: 68 65 20 63 61 63 68 65 2e 0a 2a 2f 0a 69 6e 74  he cache..*/.int
7620: 20 73 71 6c 69 74 65 33 50 63 61 63 68 65 50 61   sqlite3PcachePa
7630: 67 65 63 6f 75 6e 74 28 50 43 61 63 68 65 20 2a  gecount(PCache *
7640: 70 43 61 63 68 65 29 7b 0a 20 20 61 73 73 65 72  pCache){.  asser
7650: 74 28 20 70 43 61 63 68 65 2d 3e 6e 50 61 67 65  t( pCache->nPage
7660: 3e 3d 30 20 29 3b 0a 20 20 72 65 74 75 72 6e 20  >=0 );.  return 
7670: 70 43 61 63 68 65 2d 3e 6e 50 61 67 65 3b 0a 7d  pCache->nPage;.}
7680: 0a 0a 23 69 66 64 65 66 20 53 51 4c 49 54 45 5f  ..#ifdef SQLITE_
7690: 43 48 45 43 4b 5f 50 41 47 45 53 0a 2f 2a 0a 2a  CHECK_PAGES./*.*
76a0: 2a 20 54 68 69 73 20 66 75 6e 63 74 69 6f 6e 20  * This function 
76b0: 69 73 20 75 73 65 64 20 62 79 20 74 68 65 20 70  is used by the p
76c0: 61 67 65 72 2e 63 20 6d 6f 64 75 6c 65 20 74 6f  ager.c module to
76d0: 20 69 74 65 72 61 74 65 20 74 68 72 6f 75 67 68   iterate through
76e0: 20 61 6c 6c 20 0a 2a 2a 20 70 61 67 65 73 20 69   all .** pages i
76f0: 6e 20 74 68 65 20 63 61 63 68 65 2e 20 41 74 20  n the cache. At 
7700: 70 72 65 73 65 6e 74 2c 20 74 68 69 73 20 69 73  present, this is
7710: 20 6f 6e 6c 79 20 72 65 71 75 69 72 65 64 20 69   only required i
7720: 66 20 74 68 65 0a 2a 2a 20 53 51 4c 49 54 45 5f  f the.** SQLITE_
7730: 43 48 45 43 4b 5f 50 41 47 45 53 20 6d 61 63 72  CHECK_PAGES macr
7740: 6f 20 28 75 73 65 64 20 66 6f 72 20 64 65 62 75  o (used for debu
7750: 67 67 69 6e 67 29 20 69 73 20 73 70 65 63 69 66  gging) is specif
7760: 69 65 64 2e 0a 2a 2f 0a 76 6f 69 64 20 73 71 6c  ied..*/.void sql
7770: 69 74 65 33 50 63 61 63 68 65 49 74 65 72 61 74  ite3PcacheIterat
7780: 65 28 50 43 61 63 68 65 20 2a 70 43 61 63 68 65  e(PCache *pCache
7790: 2c 20 76 6f 69 64 20 28 2a 78 49 74 65 72 29 28  , void (*xIter)(
77a0: 50 67 48 64 72 20 2a 29 29 7b 0a 20 20 50 67 48  PgHdr *)){.  PgH
77b0: 64 72 20 2a 70 3b 0a 20 20 66 6f 72 28 70 3d 70  dr *p;.  for(p=p
77c0: 43 61 63 68 65 2d 3e 70 43 6c 65 61 6e 3b 20 70  Cache->pClean; p
77d0: 3b 20 70 3d 70 2d 3e 70 4e 65 78 74 29 7b 0a 20  ; p=p->pNext){. 
77e0: 20 20 20 78 49 74 65 72 28 70 29 3b 0a 20 20 7d     xIter(p);.  }
77f0: 0a 20 20 66 6f 72 28 70 3d 70 43 61 63 68 65 2d  .  for(p=pCache-
7800: 3e 70 44 69 72 74 79 3b 20 70 3b 20 70 3d 70 2d  >pDirty; p; p=p-
7810: 3e 70 4e 65 78 74 29 7b 0a 20 20 20 20 78 49 74  >pNext){.    xIt
7820: 65 72 28 70 29 3b 0a 20 20 7d 0a 7d 0a 23 65 6e  er(p);.  }.}.#en
7830: 64 69 66 0a 0a 2f 2a 20 0a 2a 2a 20 53 65 74 20  dif../* .** Set 
7840: 66 6c 61 67 73 20 6f 6e 20 61 6c 6c 20 70 61 67  flags on all pag
7850: 65 73 20 69 6e 20 74 68 65 20 70 61 67 65 20 63  es in the page c
7860: 61 63 68 65 20 0a 2a 2f 0a 76 6f 69 64 20 73 71  ache .*/.void sq
7870: 6c 69 74 65 33 50 63 61 63 68 65 53 65 74 46 6c  lite3PcacheSetFl
7880: 61 67 73 28 50 43 61 63 68 65 20 2a 70 43 61 63  ags(PCache *pCac
7890: 68 65 2c 20 69 6e 74 20 61 6e 64 4d 61 73 6b 2c  he, int andMask,
78a0: 20 69 6e 74 20 6f 72 4d 61 73 6b 29 7b 0a 20 20   int orMask){.  
78b0: 50 67 48 64 72 20 2a 70 3b 0a 0a 20 20 61 73 73  PgHdr *p;..  ass
78c0: 65 72 74 28 20 28 6f 72 4d 61 73 6b 26 50 47 48  ert( (orMask&PGH
78d0: 44 52 5f 4e 45 45 44 5f 53 59 4e 43 29 3d 3d 30  DR_NEED_SYNC)==0
78e0: 20 29 3b 0a 0a 20 20 2f 2a 20 4f 62 74 61 69 6e   );..  /* Obtain
78f0: 20 74 68 65 20 67 6c 6f 62 61 6c 20 6d 75 74 65   the global mute
7900: 78 20 62 65 66 6f 72 65 20 6d 6f 64 69 66 79 69  x before modifyi
7910: 6e 67 20 61 6e 79 20 50 67 48 64 72 2e 66 6c 61  ng any PgHdr.fla
7920: 67 73 20 76 61 72 69 61 62 6c 65 73 20 0a 20 20  gs variables .  
7930: 2a 2a 20 6f 72 20 74 72 61 76 65 72 73 69 6e 67  ** or traversing
7940: 20 74 68 65 20 4c 52 55 20 6c 69 73 74 2e 0a 20   the LRU list.. 
7950: 20 2a 2f 20 0a 20 20 70 63 61 63 68 65 45 6e 74   */ .  pcacheEnt
7960: 65 72 47 6c 6f 62 61 6c 28 29 3b 0a 0a 20 20 66  erGlobal();..  f
7970: 6f 72 28 70 3d 70 43 61 63 68 65 2d 3e 70 44 69  or(p=pCache->pDi
7980: 72 74 79 3b 20 70 3b 20 70 3d 70 2d 3e 70 4e 65  rty; p; p=p->pNe
7990: 78 74 29 7b 0a 20 20 20 20 70 2d 3e 66 6c 61 67  xt){.    p->flag
79a0: 73 20 3d 20 28 70 2d 3e 66 6c 61 67 73 26 61 6e  s = (p->flags&an
79b0: 64 4d 61 73 6b 29 7c 6f 72 4d 61 73 6b 3b 0a 20  dMask)|orMask;. 
79c0: 20 7d 0a 20 20 66 6f 72 28 70 3d 70 43 61 63 68   }.  for(p=pCach
79d0: 65 2d 3e 70 43 6c 65 61 6e 3b 20 70 3b 20 70 3d  e->pClean; p; p=
79e0: 70 2d 3e 70 4e 65 78 74 29 7b 0a 20 20 20 20 70  p->pNext){.    p
79f0: 2d 3e 66 6c 61 67 73 20 3d 20 28 70 2d 3e 66 6c  ->flags = (p->fl
7a00: 61 67 73 26 61 6e 64 4d 61 73 6b 29 7c 6f 72 4d  ags&andMask)|orM
7a10: 61 73 6b 3b 0a 20 20 7d 0a 0a 20 20 69 66 28 20  ask;.  }..  if( 
7a20: 30 3d 3d 28 61 6e 64 4d 61 73 6b 26 50 47 48 44  0==(andMask&PGHD
7a30: 52 5f 4e 45 45 44 5f 53 59 4e 43 29 20 29 7b 0a  R_NEED_SYNC) ){.
7a40: 20 20 20 20 50 67 48 64 72 20 2a 70 53 79 6e 63      PgHdr *pSync
7a50: 65 64 20 3d 20 70 43 61 63 68 65 2d 3e 70 44 69  ed = pCache->pDi
7a60: 72 74 79 54 61 69 6c 3b 0a 20 20 20 20 77 68 69  rtyTail;.    whi
7a70: 6c 65 28 20 70 53 79 6e 63 65 64 20 26 26 20 28  le( pSynced && (
7a80: 70 53 79 6e 63 65 64 2d 3e 66 6c 61 67 73 26 50  pSynced->flags&P
7a90: 47 48 44 52 5f 4e 45 45 44 5f 53 59 4e 43 29 20  GHDR_NEED_SYNC) 
7aa0: 29 7b 0a 20 20 20 20 20 20 70 53 79 6e 63 65 64  ){.      pSynced
7ab0: 20 3d 20 70 53 79 6e 63 65 64 2d 3e 70 50 72 65   = pSynced->pPre
7ac0: 76 3b 0a 20 20 20 20 7d 0a 20 20 20 20 70 43 61  v;.    }.    pCa
7ad0: 63 68 65 2d 3e 70 53 79 6e 63 65 64 20 3d 20 70  che->pSynced = p
7ae0: 53 79 6e 63 65 64 3b 0a 20 20 7d 0a 0a 20 20 70  Synced;.  }..  p
7af0: 63 61 63 68 65 45 78 69 74 47 6c 6f 62 61 6c 28  cacheExitGlobal(
7b00: 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 53 65 74 20  );.}../*.** Set 
7b10: 74 68 65 20 73 75 67 67 65 73 74 65 64 20 63 61  the suggested ca
7b20: 63 68 65 2d 73 69 7a 65 20 76 61 6c 75 65 2e 0a  che-size value..
7b30: 2a 2f 0a 69 6e 74 20 73 71 6c 69 74 65 33 50 63  */.int sqlite3Pc
7b40: 61 63 68 65 47 65 74 43 61 63 68 65 73 69 7a 65  acheGetCachesize
7b50: 28 50 43 61 63 68 65 20 2a 70 43 61 63 68 65 29  (PCache *pCache)
7b60: 7b 0a 20 20 72 65 74 75 72 6e 20 70 43 61 63 68  {.  return pCach
7b70: 65 2d 3e 6e 4d 61 78 3b 0a 7d 0a 0a 2f 2a 0a 2a  e->nMax;.}../*.*
7b80: 2a 20 53 65 74 20 74 68 65 20 73 75 67 67 65 73  * Set the sugges
7b90: 74 65 64 20 63 61 63 68 65 2d 73 69 7a 65 20 76  ted cache-size v
7ba0: 61 6c 75 65 2e 0a 2a 2f 0a 76 6f 69 64 20 73 71  alue..*/.void sq
7bb0: 6c 69 74 65 33 50 63 61 63 68 65 53 65 74 43 61  lite3PcacheSetCa
7bc0: 63 68 65 73 69 7a 65 28 50 43 61 63 68 65 20 2a  chesize(PCache *
7bd0: 70 43 61 63 68 65 2c 20 69 6e 74 20 6d 78 50 61  pCache, int mxPa
7be0: 67 65 29 7b 0a 20 20 69 66 28 20 6d 78 50 61 67  ge){.  if( mxPag
7bf0: 65 3c 31 30 20 29 7b 0a 20 20 20 20 6d 78 50 61  e<10 ){.    mxPa
7c00: 67 65 20 3d 20 31 30 3b 0a 20 20 7d 0a 20 20 69  ge = 10;.  }.  i
7c10: 66 28 20 70 43 61 63 68 65 2d 3e 62 50 75 72 67  f( pCache->bPurg
7c20: 65 61 62 6c 65 20 29 7b 0a 20 20 20 20 70 63 61  eable ){.    pca
7c30: 63 68 65 45 6e 74 65 72 47 6c 6f 62 61 6c 28 29  cheEnterGlobal()
7c40: 3b 0a 20 20 20 20 70 63 61 63 68 65 2e 6e 4d 61  ;.    pcache.nMa
7c50: 78 50 61 67 65 20 2d 3d 20 70 43 61 63 68 65 2d  xPage -= pCache-
7c60: 3e 6e 4d 61 78 3b 0a 20 20 20 20 70 63 61 63 68  >nMax;.    pcach
7c70: 65 2e 6e 4d 61 78 50 61 67 65 20 2b 3d 20 6d 78  e.nMaxPage += mx
7c80: 50 61 67 65 3b 0a 20 20 20 20 70 63 61 63 68 65  Page;.    pcache
7c90: 45 78 69 74 47 6c 6f 62 61 6c 28 29 3b 0a 20 20  ExitGlobal();.  
7ca0: 7d 0a 20 20 70 43 61 63 68 65 2d 3e 6e 4d 61 78  }.  pCache->nMax
7cb0: 20 3d 20 6d 78 50 61 67 65 3b 0a 7d 0a 0a 23 69   = mxPage;.}..#i
7cc0: 66 64 65 66 20 53 51 4c 49 54 45 5f 45 4e 41 42  fdef SQLITE_ENAB
7cd0: 4c 45 5f 4d 45 4d 4f 52 59 5f 4d 41 4e 41 47 45  LE_MEMORY_MANAGE
7ce0: 4d 45 4e 54 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20  MENT./*.** This 
7cf0: 66 75 6e 63 74 69 6f 6e 20 69 73 20 63 61 6c 6c  function is call
7d00: 65 64 20 74 6f 20 66 72 65 65 20 73 75 70 65 72  ed to free super
7d10: 66 6c 75 6f 75 73 20 64 79 6e 61 6d 69 63 61 6c  fluous dynamical
7d20: 6c 79 20 61 6c 6c 6f 63 61 74 65 64 20 6d 65 6d  ly allocated mem
7d30: 6f 72 79 0a 2a 2a 20 68 65 6c 64 20 62 79 20 74  ory.** held by t
7d40: 68 65 20 70 61 67 65 72 20 73 79 73 74 65 6d 2e  he pager system.
7d50: 20 4d 65 6d 6f 72 79 20 69 6e 20 75 73 65 20 62   Memory in use b
7d60: 79 20 61 6e 79 20 53 51 4c 69 74 65 20 70 61 67  y any SQLite pag
7d70: 65 72 20 61 6c 6c 6f 63 61 74 65 64 0a 2a 2a 20  er allocated.** 
7d80: 62 79 20 74 68 65 20 63 75 72 72 65 6e 74 20 74  by the current t
7d90: 68 72 65 61 64 20 6d 61 79 20 62 65 20 73 71 6c  hread may be sql
7da0: 69 74 65 33 5f 66 72 65 65 28 29 65 64 2e 0a 2a  ite3_free()ed..*
7db0: 2a 0a 2a 2a 20 6e 52 65 71 20 69 73 20 74 68 65  *.** nReq is the
7dc0: 20 6e 75 6d 62 65 72 20 6f 66 20 62 79 74 65 73   number of bytes
7dd0: 20 6f 66 20 6d 65 6d 6f 72 79 20 72 65 71 75 69   of memory requi
7de0: 72 65 64 2e 20 4f 6e 63 65 20 74 68 69 73 20 6d  red. Once this m
7df0: 75 63 68 20 68 61 73 0a 2a 2a 20 62 65 65 6e 20  uch has.** been 
7e00: 72 65 6c 65 61 73 65 64 2c 20 74 68 65 20 66 75  released, the fu
7e10: 6e 63 74 69 6f 6e 20 72 65 74 75 72 6e 73 2e 20  nction returns. 
7e20: 54 68 65 20 72 65 74 75 72 6e 20 76 61 6c 75 65  The return value
7e30: 20 69 73 20 74 68 65 20 74 6f 74 61 6c 20 6e 75   is the total nu
7e40: 6d 62 65 72 20 0a 2a 2a 20 6f 66 20 62 79 74 65  mber .** of byte
7e50: 73 20 6f 66 20 6d 65 6d 6f 72 79 20 72 65 6c 65  s of memory rele
7e60: 61 73 65 64 2e 0a 2a 2f 0a 69 6e 74 20 73 71 6c  ased..*/.int sql
7e70: 69 74 65 33 50 63 61 63 68 65 52 65 6c 65 61 73  ite3PcacheReleas
7e80: 65 4d 65 6d 6f 72 79 28 69 6e 74 20 6e 52 65 71  eMemory(int nReq
7e90: 29 7b 0a 20 20 69 6e 74 20 6e 46 72 65 65 20 3d  ){.  int nFree =
7ea0: 20 30 3b 0a 20 20 69 66 28 20 70 63 61 63 68 65   0;.  if( pcache
7eb0: 2e 70 53 74 61 72 74 3d 3d 30 20 29 7b 0a 20 20  .pStart==0 ){.  
7ec0: 20 20 50 67 48 64 72 20 2a 70 3b 0a 20 20 20 20    PgHdr *p;.    
7ed0: 70 63 61 63 68 65 45 6e 74 65 72 47 6c 6f 62 61  pcacheEnterGloba
7ee0: 6c 28 29 3b 0a 20 20 20 20 77 68 69 6c 65 28 20  l();.    while( 
7ef0: 28 6e 52 65 71 3c 30 20 7c 7c 20 6e 46 72 65 65  (nReq<0 || nFree
7f00: 3c 6e 52 65 71 29 20 26 26 20 28 70 3d 70 63 61  <nReq) && (p=pca
7f10: 63 68 65 52 65 63 79 63 6c 65 50 61 67 65 28 29  cheRecyclePage()
7f20: 29 20 29 7b 0a 20 20 20 20 20 20 6e 46 72 65 65  ) ){.      nFree
7f30: 20 2b 3d 20 70 63 61 63 68 65 50 61 67 65 53 69   += pcachePageSi
7f40: 7a 65 28 70 29 3b 0a 20 20 20 20 20 20 70 63 61  ze(p);.      pca
7f50: 63 68 65 50 61 67 65 46 72 65 65 28 70 29 3b 0a  chePageFree(p);.
7f60: 20 20 20 20 7d 0a 20 20 20 20 70 63 61 63 68 65      }.    pcache
7f70: 45 78 69 74 47 6c 6f 62 61 6c 28 29 3b 0a 20 20  ExitGlobal();.  
7f80: 7d 0a 20 20 72 65 74 75 72 6e 20 6e 46 72 65 65  }.  return nFree
7f90: 3b 0a 7d 0a 23 65 6e 64 69 66 20 2f 2a 20 53 51  ;.}.#endif /* SQ
7fa0: 4c 49 54 45 5f 45 4e 41 42 4c 45 5f 4d 45 4d 4f  LITE_ENABLE_MEMO
7fb0: 52 59 5f 4d 41 4e 41 47 45 4d 45 4e 54 20 2a 2f  RY_MANAGEMENT */
7fc0: 0a                                               .