/ Hex Artifact Content
Login

Artifact 76adfc1ed9ffebaf92746dde4b370ccc48143ca8b05b563816eadd2aadf1c525:


0000: 2f 2a 0a 2a 2a 20 32 30 31 32 2d 30 31 2d 32 33  /*.** 2012-01-23
0010: 0a 2a 2a 0a 2a 2a 20 54 68 65 20 61 75 74 68 6f  .**.** The autho
0020: 72 20 64 69 73 63 6c 61 69 6d 73 20 63 6f 70 79  r disclaims copy
0030: 72 69 67 68 74 20 74 6f 20 74 68 69 73 20 73 6f  right to this so
0040: 75 72 63 65 20 63 6f 64 65 2e 20 20 49 6e 20 70  urce code.  In p
0050: 6c 61 63 65 20 6f 66 0a 2a 2a 20 61 20 6c 65 67  lace of.** a leg
0060: 61 6c 20 6e 6f 74 69 63 65 2c 20 68 65 72 65 20  al notice, here 
0070: 69 73 20 61 20 62 6c 65 73 73 69 6e 67 3a 0a 2a  is a blessing:.*
0080: 2a 0a 2a 2a 20 20 20 20 4d 61 79 20 79 6f 75 20  *.**    May you 
0090: 64 6f 20 67 6f 6f 64 20 61 6e 64 20 6e 6f 74 20  do good and not 
00a0: 65 76 69 6c 2e 0a 2a 2a 20 20 20 20 4d 61 79 20  evil..**    May 
00b0: 79 6f 75 20 66 69 6e 64 20 66 6f 72 67 69 76 65  you find forgive
00c0: 6e 65 73 73 20 66 6f 72 20 79 6f 75 72 73 65 6c  ness for yoursel
00d0: 66 20 61 6e 64 20 66 6f 72 67 69 76 65 20 6f 74  f and forgive ot
00e0: 68 65 72 73 2e 0a 2a 2a 20 20 20 20 4d 61 79 20  hers..**    May 
00f0: 79 6f 75 20 73 68 61 72 65 20 66 72 65 65 6c 79  you share freely
0100: 2c 20 6e 65 76 65 72 20 74 61 6b 69 6e 67 20 6d  , never taking m
0110: 6f 72 65 20 74 68 61 6e 20 79 6f 75 20 67 69 76  ore than you giv
0120: 65 2e 0a 2a 2a 0a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  e..**.**********
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 0a  ***************.
0170: 2a 2a 0a 2a 2a 20 55 74 69 6c 69 74 69 65 73 20  **.** Utilities 
0180: 75 73 65 64 20 74 6f 20 68 65 6c 70 20 6d 75 6c  used to help mul
0190: 74 69 70 6c 65 20 4c 53 4d 20 63 6c 69 65 6e 74  tiple LSM client
01a0: 73 20 74 6f 20 63 6f 65 78 69 73 74 20 77 69 74  s to coexist wit
01b0: 68 69 6e 20 74 68 65 0a 2a 2a 20 73 61 6d 65 20  hin the.** same 
01c0: 70 72 6f 63 65 73 73 20 73 70 61 63 65 2e 0a 2a  process space..*
01d0: 2f 0a 23 69 6e 63 6c 75 64 65 20 22 6c 73 6d 49  /.#include "lsmI
01e0: 6e 74 2e 68 22 0a 0a 2f 2a 0a 2a 2a 20 47 6c 6f  nt.h"../*.** Glo
01f0: 62 61 6c 20 64 61 74 61 2e 20 41 6c 6c 20 67 6c  bal data. All gl
0200: 6f 62 61 6c 20 76 61 72 69 61 62 6c 65 73 20 75  obal variables u
0210: 73 65 64 20 62 79 20 63 6f 64 65 20 69 6e 20 74  sed by code in t
0220: 68 69 73 20 66 69 6c 65 20 61 72 65 20 67 72 6f  his file are gro
0230: 75 70 65 64 0a 2a 2a 20 69 6e 74 6f 20 74 68 65  uped.** into the
0240: 20 66 6f 6c 6c 6f 77 69 6e 67 20 73 74 72 75 63   following struc
0250: 74 75 72 65 20 69 6e 73 74 61 6e 63 65 2e 0a 2a  ture instance..*
0260: 2a 0a 2a 2a 20 70 44 61 74 61 62 61 73 65 3a 0a  *.** pDatabase:.
0270: 2a 2a 20 20 20 4c 69 6e 6b 65 64 20 6c 69 73 74  **   Linked list
0280: 20 6f 66 20 61 6c 6c 20 44 61 74 61 62 61 73 65   of all Database
0290: 20 6f 62 6a 65 63 74 73 20 61 6c 6c 6f 63 61 74   objects allocat
02a0: 65 64 20 77 69 74 68 69 6e 20 74 68 69 73 20 70  ed within this p
02b0: 72 6f 63 65 73 73 2e 0a 2a 2a 20 20 20 54 68 69  rocess..**   Thi
02c0: 73 20 6c 69 73 74 20 6d 61 79 20 6e 6f 74 20 62  s list may not b
02d0: 65 20 74 72 61 76 65 72 73 65 64 20 77 69 74 68  e traversed with
02e0: 6f 75 74 20 68 6f 6c 64 69 6e 67 20 74 68 65 20  out holding the 
02f0: 67 6c 6f 62 61 6c 20 6d 75 74 65 78 20 28 73 65  global mutex (se
0300: 65 0a 2a 2a 20 20 20 66 75 6e 63 74 69 6f 6e 73  e.**   functions
0310: 20 65 6e 74 65 72 47 6c 6f 62 61 6c 4d 75 74 65   enterGlobalMute
0320: 78 28 29 20 61 6e 64 20 6c 65 61 76 65 47 6c 6f  x() and leaveGlo
0330: 62 61 6c 4d 75 74 65 78 28 29 29 2e 0a 2a 2f 0a  balMutex())..*/.
0340: 73 74 61 74 69 63 20 73 74 72 75 63 74 20 53 68  static struct Sh
0350: 61 72 65 64 44 61 74 61 20 7b 0a 20 20 44 61 74  aredData {.  Dat
0360: 61 62 61 73 65 20 2a 70 44 61 74 61 62 61 73 65  abase *pDatabase
0370: 3b 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20  ;            /* 
0380: 4c 69 6e 6b 65 64 20 6c 69 73 74 20 6f 66 20 61  Linked list of a
0390: 6c 6c 20 44 61 74 61 62 61 73 65 20 6f 62 6a 65  ll Database obje
03a0: 63 74 73 20 2a 2f 0a 7d 20 67 53 68 61 72 65 64  cts */.} gShared
03b0: 3b 0a 0a 2f 2a 0a 2a 2a 20 44 61 74 61 62 61 73  ;../*.** Databas
03c0: 65 20 73 74 72 75 63 74 75 72 65 2e 20 54 68 65  e structure. The
03d0: 72 65 20 69 73 20 6f 6e 65 20 73 75 63 68 20 73  re is one such s
03e0: 74 72 75 63 74 75 72 65 20 66 6f 72 20 65 61 63  tructure for eac
03f0: 68 20 64 69 73 74 69 6e 63 74 20 0a 2a 2a 20 64  h distinct .** d
0400: 61 74 61 62 61 73 65 20 61 63 63 65 73 73 65 64  atabase accessed
0410: 20 62 79 20 74 68 69 73 20 70 72 6f 63 65 73 73   by this process
0420: 2e 20 54 68 65 79 20 61 72 65 20 73 74 6f 72 65  . They are store
0430: 64 20 69 6e 20 74 68 65 20 73 69 6e 67 6c 79 20  d in the singly 
0440: 6c 69 6e 6b 65 64 20 0a 2a 2a 20 6c 69 73 74 20  linked .** list 
0450: 73 74 61 72 74 69 6e 67 20 61 74 20 67 6c 6f 62  starting at glob
0460: 61 6c 20 76 61 72 69 61 62 6c 65 20 67 53 68 61  al variable gSha
0470: 72 65 64 2e 70 44 61 74 61 62 61 73 65 2e 20 44  red.pDatabase. D
0480: 61 74 61 62 61 73 65 20 6f 62 6a 65 63 74 73 20  atabase objects 
0490: 61 72 65 20 0a 2a 2a 20 72 65 66 65 72 65 6e 63  are .** referenc
04a0: 65 20 63 6f 75 6e 74 65 64 2e 20 4f 6e 63 65 20  e counted. Once 
04b0: 74 68 65 20 6e 75 6d 62 65 72 20 6f 66 20 63 6f  the number of co
04c0: 6e 6e 65 63 74 69 6f 6e 73 20 74 6f 20 74 68 65  nnections to the
04d0: 20 61 73 73 6f 63 69 61 74 65 64 0a 2a 2a 20 64   associated.** d
04e0: 61 74 61 62 61 73 65 20 64 72 6f 70 73 20 74 6f  atabase drops to
04f0: 20 7a 65 72 6f 2c 20 74 68 65 79 20 61 72 65 20   zero, they are 
0500: 72 65 6d 6f 76 65 64 20 66 72 6f 6d 20 74 68 65  removed from the
0510: 20 6c 69 6e 6b 65 64 20 6c 69 73 74 20 61 6e 64   linked list and
0520: 20 64 65 6c 65 74 65 64 2e 0a 2a 2a 0a 2a 2a 20   deleted..**.** 
0530: 70 46 69 6c 65 3a 0a 2a 2a 20 20 20 49 6e 20 6d  pFile:.**   In m
0540: 75 6c 74 69 2d 70 72 6f 63 65 73 73 20 6d 6f 64  ulti-process mod
0550: 65 2c 20 74 68 69 73 20 66 69 6c 65 20 64 65 73  e, this file des
0560: 63 72 69 70 74 6f 72 20 69 73 20 75 73 65 64 20  criptor is used 
0570: 74 6f 20 6f 62 74 61 69 6e 20 6c 6f 63 6b 73 20  to obtain locks 
0580: 0a 2a 2a 20 20 20 61 6e 64 20 74 6f 20 61 63 63  .**   and to acc
0590: 65 73 73 20 73 68 61 72 65 64 2d 6d 65 6d 6f 72  ess shared-memor
05a0: 79 2e 20 49 6e 20 73 69 6e 67 6c 65 20 70 72 6f  y. In single pro
05b0: 63 65 73 73 20 6d 6f 64 65 2c 20 69 74 73 20 6f  cess mode, its o
05c0: 6e 6c 79 20 6a 6f 62 20 69 73 0a 2a 2a 20 20 20  nly job is.**   
05d0: 74 6f 20 68 6f 6c 64 20 74 68 65 20 65 78 63 6c  to hold the excl
05e0: 75 73 69 76 65 20 6c 6f 63 6b 20 6f 6e 20 74 68  usive lock on th
05f0: 65 20 66 69 6c 65 2e 0a 2a 2a 20 20 20 0a 2a 2f  e file..**   .*/
0600: 0a 73 74 72 75 63 74 20 44 61 74 61 62 61 73 65  .struct Database
0610: 20 7b 0a 20 20 2f 2a 20 50 72 6f 74 65 63 74 65   {.  /* Protecte
0620: 64 20 62 79 20 74 68 65 20 67 6c 6f 62 61 6c 20  d by the global 
0630: 6d 75 74 65 78 20 28 65 6e 74 65 72 47 6c 6f 62  mutex (enterGlob
0640: 61 6c 4d 75 74 65 78 2f 6c 65 61 76 65 47 6c 6f  alMutex/leaveGlo
0650: 62 61 6c 4d 75 74 65 78 29 3a 20 2a 2f 0a 20 20  balMutex): */.  
0660: 63 68 61 72 20 2a 7a 4e 61 6d 65 3b 20 20 20 20  char *zName;    
0670: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0680: 2f 2a 20 43 61 6e 6f 6e 69 63 61 6c 20 70 61 74  /* Canonical pat
0690: 68 20 74 6f 20 64 61 74 61 62 61 73 65 20 66 69  h to database fi
06a0: 6c 65 20 2a 2f 0a 20 20 69 6e 74 20 6e 4e 61 6d  le */.  int nNam
06b0: 65 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  e;              
06c0: 20 20 20 20 20 20 20 20 2f 2a 20 73 74 72 6c 65          /* strle
06d0: 6e 28 7a 4e 61 6d 65 29 20 2a 2f 0a 20 20 69 6e  n(zName) */.  in
06e0: 74 20 6e 44 62 52 65 66 3b 20 20 20 20 20 20 20  t nDbRef;       
06f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
0700: 20 4e 75 6d 62 65 72 20 6f 66 20 61 73 73 6f 63   Number of assoc
0710: 69 61 74 65 64 20 6c 73 6d 5f 64 62 20 68 61 6e  iated lsm_db han
0720: 64 6c 65 73 20 2a 2f 0a 20 20 44 61 74 61 62 61  dles */.  Databa
0730: 73 65 20 2a 70 44 62 4e 65 78 74 3b 20 20 20 20  se *pDbNext;    
0740: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4e 65 78            /* Nex
0750: 74 20 44 61 74 61 62 61 73 65 20 73 74 72 75 63  t Database struc
0760: 74 75 72 65 20 69 6e 20 67 6c 6f 62 61 6c 20 6c  ture in global l
0770: 69 73 74 20 2a 2f 0a 0a 20 20 2f 2a 20 50 72 6f  ist */..  /* Pro
0780: 74 65 63 74 65 64 20 62 79 20 74 68 65 20 6c 6f  tected by the lo
0790: 63 61 6c 20 6d 75 74 65 78 20 28 70 43 6c 69 65  cal mutex (pClie
07a0: 6e 74 4d 75 74 65 78 29 20 2a 2f 0a 20 20 69 6e  ntMutex) */.  in
07b0: 74 20 62 52 65 61 64 6f 6e 6c 79 3b 20 20 20 20  t bReadonly;    
07c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
07d0: 20 54 72 75 65 20 69 66 20 44 61 74 61 62 61 73   True if Databas
07e0: 65 2e 70 46 69 6c 65 20 69 73 20 72 65 61 64 2d  e.pFile is read-
07f0: 6f 6e 6c 79 20 2a 2f 0a 20 20 69 6e 74 20 62 4d  only */.  int bM
0800: 75 6c 74 69 50 72 6f 63 3b 20 20 20 20 20 20 20  ultiProc;       
0810: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 54 72 75            /* Tru
0820: 65 20 69 66 20 72 75 6e 6e 69 6e 67 20 69 6e 20  e if running in 
0830: 6d 75 6c 74 69 2d 70 72 6f 63 65 73 73 20 6d 6f  multi-process mo
0840: 64 65 20 2a 2f 0a 20 20 6c 73 6d 5f 66 69 6c 65  de */.  lsm_file
0850: 20 2a 70 46 69 6c 65 3b 20 20 20 20 20 20 20 20   *pFile;        
0860: 20 20 20 20 20 20 20 20 2f 2a 20 55 73 65 64 20          /* Used 
0870: 66 6f 72 20 6c 6f 63 6b 73 2f 73 68 6d 20 69 6e  for locks/shm in
0880: 20 6d 75 6c 74 69 2d 70 72 6f 63 20 6d 6f 64 65   multi-proc mode
0890: 20 2a 2f 0a 20 20 4c 73 6d 46 69 6c 65 20 2a 70   */.  LsmFile *p
08a0: 4c 73 6d 46 69 6c 65 3b 20 20 20 20 20 20 20 20  LsmFile;        
08b0: 20 20 20 20 20 20 2f 2a 20 4c 69 73 74 20 6f 66        /* List of
08c0: 20 64 65 66 65 72 72 65 64 20 63 6c 6f 73 65 73   deferred closes
08d0: 20 2a 2f 0a 20 20 6c 73 6d 5f 6d 75 74 65 78 20   */.  lsm_mutex 
08e0: 2a 70 43 6c 69 65 6e 74 4d 75 74 65 78 3b 20 20  *pClientMutex;  
08f0: 20 20 20 20 20 20 2f 2a 20 50 72 6f 74 65 63 74        /* Protect
0900: 73 20 74 68 65 20 61 70 53 68 6d 43 68 75 6e 6b  s the apShmChunk
0910: 5b 5d 20 61 6e 64 20 70 43 6f 6e 6e 20 2a 2f 0a  [] and pConn */.
0920: 20 20 69 6e 74 20 6e 53 68 6d 43 68 75 6e 6b 3b    int nShmChunk;
0930: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0940: 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f 66 20 65    /* Number of e
0950: 6e 74 72 69 65 73 20 69 6e 20 61 70 53 68 6d 43  ntries in apShmC
0960: 68 75 6e 6b 5b 5d 20 61 72 72 61 79 20 2a 2f 0a  hunk[] array */.
0970: 20 20 76 6f 69 64 20 2a 2a 61 70 53 68 6d 43 68    void **apShmCh
0980: 75 6e 6b 3b 20 20 20 20 20 20 20 20 20 20 20 20  unk;            
0990: 20 20 2f 2a 20 41 72 72 61 79 20 6f 66 20 22 73    /* Array of "s
09a0: 68 61 72 65 64 22 20 6d 65 6d 6f 72 79 20 72 65  hared" memory re
09b0: 67 69 6f 6e 73 20 2a 2f 0a 20 20 6c 73 6d 5f 64  gions */.  lsm_d
09c0: 62 20 2a 70 43 6f 6e 6e 3b 20 20 20 20 20 20 20  b *pConn;       
09d0: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4c 69             /* Li
09e0: 73 74 20 6f 66 20 63 6f 6e 6e 65 63 74 69 6f 6e  st of connection
09f0: 73 20 74 6f 20 74 68 69 73 20 64 62 2e 20 2a 2f  s to this db. */
0a00: 0a 7d 3b 0a 0a 2f 2a 0a 2a 2a 20 46 75 6e 63 74  .};../*.** Funct
0a10: 69 6f 6e 73 20 74 6f 20 65 6e 74 65 72 20 61 6e  ions to enter an
0a20: 64 20 6c 65 61 76 65 20 74 68 65 20 67 6c 6f 62  d leave the glob
0a30: 61 6c 20 6d 75 74 65 78 2e 20 54 68 69 73 20 6d  al mutex. This m
0a40: 75 74 65 78 20 69 73 20 75 73 65 64 0a 2a 2a 20  utex is used.** 
0a50: 74 6f 20 70 72 6f 74 65 63 74 20 74 68 65 20 67  to protect the g
0a60: 6c 6f 62 61 6c 20 6c 69 6e 6b 65 64 2d 6c 69 73  lobal linked-lis
0a70: 74 20 68 65 61 64 65 64 20 61 74 20 67 53 68 61  t headed at gSha
0a80: 72 65 64 2e 70 44 61 74 61 62 61 73 65 2e 0a 2a  red.pDatabase..*
0a90: 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 65 6e 74  /.static int ent
0aa0: 65 72 47 6c 6f 62 61 6c 4d 75 74 65 78 28 6c 73  erGlobalMutex(ls
0ab0: 6d 5f 65 6e 76 20 2a 70 45 6e 76 29 7b 0a 20 20  m_env *pEnv){.  
0ac0: 6c 73 6d 5f 6d 75 74 65 78 20 2a 70 3b 0a 20 20  lsm_mutex *p;.  
0ad0: 69 6e 74 20 72 63 20 3d 20 6c 73 6d 4d 75 74 65  int rc = lsmMute
0ae0: 78 53 74 61 74 69 63 28 70 45 6e 76 2c 20 4c 53  xStatic(pEnv, LS
0af0: 4d 5f 4d 55 54 45 58 5f 47 4c 4f 42 41 4c 2c 20  M_MUTEX_GLOBAL, 
0b00: 26 70 29 3b 0a 20 20 69 66 28 20 72 63 3d 3d 4c  &p);.  if( rc==L
0b10: 53 4d 5f 4f 4b 20 29 20 6c 73 6d 4d 75 74 65 78  SM_OK ) lsmMutex
0b20: 45 6e 74 65 72 28 70 45 6e 76 2c 20 70 29 3b 0a  Enter(pEnv, p);.
0b30: 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 73    return rc;.}.s
0b40: 74 61 74 69 63 20 76 6f 69 64 20 6c 65 61 76 65  tatic void leave
0b50: 47 6c 6f 62 61 6c 4d 75 74 65 78 28 6c 73 6d 5f  GlobalMutex(lsm_
0b60: 65 6e 76 20 2a 70 45 6e 76 29 7b 0a 20 20 6c 73  env *pEnv){.  ls
0b70: 6d 5f 6d 75 74 65 78 20 2a 70 3b 0a 20 20 6c 73  m_mutex *p;.  ls
0b80: 6d 4d 75 74 65 78 53 74 61 74 69 63 28 70 45 6e  mMutexStatic(pEn
0b90: 76 2c 20 4c 53 4d 5f 4d 55 54 45 58 5f 47 4c 4f  v, LSM_MUTEX_GLO
0ba0: 42 41 4c 2c 20 26 70 29 3b 0a 20 20 6c 73 6d 4d  BAL, &p);.  lsmM
0bb0: 75 74 65 78 4c 65 61 76 65 28 70 45 6e 76 2c 20  utexLeave(pEnv, 
0bc0: 70 29 3b 0a 7d 0a 0a 23 69 66 64 65 66 20 4c 53  p);.}..#ifdef LS
0bd0: 4d 5f 44 45 42 55 47 0a 73 74 61 74 69 63 20 69  M_DEBUG.static i
0be0: 6e 74 20 68 6f 6c 64 69 6e 67 47 6c 6f 62 61 6c  nt holdingGlobal
0bf0: 4d 75 74 65 78 28 6c 73 6d 5f 65 6e 76 20 2a 70  Mutex(lsm_env *p
0c00: 45 6e 76 29 7b 0a 20 20 6c 73 6d 5f 6d 75 74 65  Env){.  lsm_mute
0c10: 78 20 2a 70 3b 0a 20 20 6c 73 6d 4d 75 74 65 78  x *p;.  lsmMutex
0c20: 53 74 61 74 69 63 28 70 45 6e 76 2c 20 4c 53 4d  Static(pEnv, LSM
0c30: 5f 4d 55 54 45 58 5f 47 4c 4f 42 41 4c 2c 20 26  _MUTEX_GLOBAL, &
0c40: 70 29 3b 0a 20 20 72 65 74 75 72 6e 20 6c 73 6d  p);.  return lsm
0c50: 4d 75 74 65 78 48 65 6c 64 28 70 45 6e 76 2c 20  MutexHeld(pEnv, 
0c60: 70 29 3b 0a 7d 0a 23 65 6e 64 69 66 0a 0a 23 69  p);.}.#endif..#i
0c70: 66 20 30 0a 73 74 61 74 69 63 20 76 6f 69 64 20  f 0.static void 
0c80: 61 73 73 65 72 74 4e 6f 74 49 6e 46 72 65 65 6c  assertNotInFreel
0c90: 69 73 74 28 46 72 65 65 6c 69 73 74 20 2a 70 2c  ist(Freelist *p,
0ca0: 20 69 6e 74 20 69 42 6c 6b 29 7b 0a 20 20 69 6e   int iBlk){.  in
0cb0: 74 20 69 3b 20 0a 20 20 66 6f 72 28 69 3d 30 3b  t i; .  for(i=0;
0cc0: 20 69 3c 70 2d 3e 6e 45 6e 74 72 79 3b 20 69 2b   i<p->nEntry; i+
0cd0: 2b 29 7b 0a 20 20 20 20 61 73 73 65 72 74 28 20  +){.    assert( 
0ce0: 70 2d 3e 61 45 6e 74 72 79 5b 69 5d 2e 69 42 6c  p->aEntry[i].iBl
0cf0: 6b 21 3d 69 42 6c 6b 20 29 3b 0a 20 20 7d 0a 7d  k!=iBlk );.  }.}
0d00: 0a 23 65 6c 73 65 0a 23 20 64 65 66 69 6e 65 20  .#else.# define 
0d10: 61 73 73 65 72 74 4e 6f 74 49 6e 46 72 65 65 6c  assertNotInFreel
0d20: 69 73 74 28 78 2c 79 29 0a 23 65 6e 64 69 66 0a  ist(x,y).#endif.
0d30: 0a 2f 2a 0a 2a 2a 20 41 70 70 65 6e 64 20 61 6e  ./*.** Append an
0d40: 20 65 6e 74 72 79 20 74 6f 20 74 68 65 20 66 72   entry to the fr
0d50: 65 65 2d 6c 69 73 74 2e 20 49 66 20 28 69 49 64  ee-list. If (iId
0d60: 3d 3d 2d 31 29 2c 20 74 68 69 73 20 69 73 20 61  ==-1), this is a
0d70: 20 64 65 6c 65 74 65 2e 0a 2a 2f 0a 69 6e 74 20   delete..*/.int 
0d80: 66 72 65 65 6c 69 73 74 41 70 70 65 6e 64 28 6c  freelistAppend(l
0d90: 73 6d 5f 64 62 20 2a 64 62 2c 20 75 33 32 20 69  sm_db *db, u32 i
0da0: 42 6c 6b 2c 20 69 36 34 20 69 49 64 29 7b 0a 20  Blk, i64 iId){. 
0db0: 20 6c 73 6d 5f 65 6e 76 20 2a 70 45 6e 76 20 3d   lsm_env *pEnv =
0dc0: 20 64 62 2d 3e 70 45 6e 76 3b 0a 20 20 46 72 65   db->pEnv;.  Fre
0dd0: 65 6c 69 73 74 20 2a 70 3b 0a 20 20 69 6e 74 20  elist *p;.  int 
0de0: 69 3b 20 0a 0a 20 20 61 73 73 65 72 74 28 20 69  i; ..  assert( i
0df0: 49 64 3d 3d 2d 31 20 7c 7c 20 69 49 64 3e 3d 30  Id==-1 || iId>=0
0e00: 20 29 3b 0a 20 20 70 20 3d 20 64 62 2d 3e 62 55   );.  p = db->bU
0e10: 73 65 46 72 65 65 6c 69 73 74 20 3f 20 64 62 2d  seFreelist ? db-
0e20: 3e 70 46 72 65 65 6c 69 73 74 20 3a 20 26 64 62  >pFreelist : &db
0e30: 2d 3e 70 57 6f 72 6b 65 72 2d 3e 66 72 65 65 6c  ->pWorker->freel
0e40: 69 73 74 3b 0a 0a 20 20 2f 2a 20 45 78 74 65 6e  ist;..  /* Exten
0e50: 64 20 74 68 65 20 73 70 61 63 65 20 61 6c 6c 6f  d the space allo
0e60: 63 61 74 65 64 20 66 6f 72 20 74 68 65 20 66 72  cated for the fr
0e70: 65 65 6c 69 73 74 2c 20 69 66 20 72 65 71 75 69  eelist, if requi
0e80: 72 65 64 20 2a 2f 0a 20 20 61 73 73 65 72 74 28  red */.  assert(
0e90: 20 70 2d 3e 6e 41 6c 6c 6f 63 3e 3d 70 2d 3e 6e   p->nAlloc>=p->n
0ea0: 45 6e 74 72 79 20 29 3b 0a 20 20 69 66 28 20 70  Entry );.  if( p
0eb0: 2d 3e 6e 41 6c 6c 6f 63 3d 3d 70 2d 3e 6e 45 6e  ->nAlloc==p->nEn
0ec0: 74 72 79 20 29 7b 0a 20 20 20 20 69 6e 74 20 6e  try ){.    int n
0ed0: 4e 65 77 3b 20 0a 20 20 20 20 69 6e 74 20 6e 42  New; .    int nB
0ee0: 79 74 65 3b 20 0a 20 20 20 20 46 72 65 65 6c 69  yte; .    Freeli
0ef0: 73 74 45 6e 74 72 79 20 2a 61 4e 65 77 3b 0a 0a  stEntry *aNew;..
0f00: 20 20 20 20 6e 4e 65 77 20 3d 20 28 70 2d 3e 6e      nNew = (p->n
0f10: 41 6c 6c 6f 63 3d 3d 30 20 3f 20 34 20 3a 20 70  Alloc==0 ? 4 : p
0f20: 2d 3e 6e 41 6c 6c 6f 63 2a 32 29 3b 0a 20 20 20  ->nAlloc*2);.   
0f30: 20 6e 42 79 74 65 20 3d 20 73 69 7a 65 6f 66 28   nByte = sizeof(
0f40: 46 72 65 65 6c 69 73 74 45 6e 74 72 79 29 20 2a  FreelistEntry) *
0f50: 20 6e 4e 65 77 3b 0a 20 20 20 20 61 4e 65 77 20   nNew;.    aNew 
0f60: 3d 20 28 46 72 65 65 6c 69 73 74 45 6e 74 72 79  = (FreelistEntry
0f70: 20 2a 29 6c 73 6d 52 65 61 6c 6c 6f 63 28 70 45   *)lsmRealloc(pE
0f80: 6e 76 2c 20 70 2d 3e 61 45 6e 74 72 79 2c 20 6e  nv, p->aEntry, n
0f90: 42 79 74 65 29 3b 0a 20 20 20 20 69 66 28 20 21  Byte);.    if( !
0fa0: 61 4e 65 77 20 29 20 72 65 74 75 72 6e 20 4c 53  aNew ) return LS
0fb0: 4d 5f 4e 4f 4d 45 4d 5f 42 4b 50 54 3b 0a 20 20  M_NOMEM_BKPT;.  
0fc0: 20 20 70 2d 3e 6e 41 6c 6c 6f 63 20 3d 20 6e 4e    p->nAlloc = nN
0fd0: 65 77 3b 0a 20 20 20 20 70 2d 3e 61 45 6e 74 72  ew;.    p->aEntr
0fe0: 79 20 3d 20 61 4e 65 77 3b 0a 20 20 7d 0a 0a 20  y = aNew;.  }.. 
0ff0: 20 66 6f 72 28 69 3d 30 3b 20 69 3c 70 2d 3e 6e   for(i=0; i<p->n
1000: 45 6e 74 72 79 3b 20 69 2b 2b 29 7b 0a 20 20 20  Entry; i++){.   
1010: 20 61 73 73 65 72 74 28 20 69 3d 3d 30 20 7c 7c   assert( i==0 ||
1020: 20 70 2d 3e 61 45 6e 74 72 79 5b 69 5d 2e 69 42   p->aEntry[i].iB
1030: 6c 6b 20 3e 20 70 2d 3e 61 45 6e 74 72 79 5b 69  lk > p->aEntry[i
1040: 2d 31 5d 2e 69 42 6c 6b 20 29 3b 0a 20 20 20 20  -1].iBlk );.    
1050: 69 66 28 20 70 2d 3e 61 45 6e 74 72 79 5b 69 5d  if( p->aEntry[i]
1060: 2e 69 42 6c 6b 3e 3d 69 42 6c 6b 20 29 20 62 72  .iBlk>=iBlk ) br
1070: 65 61 6b 3b 0a 20 20 7d 0a 0a 20 20 69 66 28 20  eak;.  }..  if( 
1080: 69 3c 70 2d 3e 6e 45 6e 74 72 79 20 26 26 20 70  i<p->nEntry && p
1090: 2d 3e 61 45 6e 74 72 79 5b 69 5d 2e 69 42 6c 6b  ->aEntry[i].iBlk
10a0: 3d 3d 69 42 6c 6b 20 29 7b 0a 20 20 20 20 2f 2a  ==iBlk ){.    /*
10b0: 20 43 6c 6f 62 62 65 72 20 61 6e 20 65 78 69 73   Clobber an exis
10c0: 74 69 6e 67 20 65 6e 74 72 79 20 2a 2f 0a 20 20  ting entry */.  
10d0: 20 20 70 2d 3e 61 45 6e 74 72 79 5b 69 5d 2e 69    p->aEntry[i].i
10e0: 49 64 20 3d 20 69 49 64 3b 0a 20 20 7d 65 6c 73  Id = iId;.  }els
10f0: 65 7b 0a 20 20 20 20 2f 2a 20 49 6e 73 65 72 74  e{.    /* Insert
1100: 20 61 20 6e 65 77 20 65 6e 74 72 79 20 69 6e 74   a new entry int
1110: 6f 20 74 68 65 20 6c 69 73 74 20 2a 2f 0a 20 20  o the list */.  
1120: 20 20 69 6e 74 20 6e 42 79 74 65 20 3d 20 73 69    int nByte = si
1130: 7a 65 6f 66 28 46 72 65 65 6c 69 73 74 45 6e 74  zeof(FreelistEnt
1140: 72 79 29 2a 28 70 2d 3e 6e 45 6e 74 72 79 2d 69  ry)*(p->nEntry-i
1150: 29 3b 0a 20 20 20 20 6d 65 6d 6d 6f 76 65 28 26  );.    memmove(&
1160: 70 2d 3e 61 45 6e 74 72 79 5b 69 2b 31 5d 2c 20  p->aEntry[i+1], 
1170: 26 70 2d 3e 61 45 6e 74 72 79 5b 69 5d 2c 20 6e  &p->aEntry[i], n
1180: 42 79 74 65 29 3b 0a 20 20 20 20 70 2d 3e 61 45  Byte);.    p->aE
1190: 6e 74 72 79 5b 69 5d 2e 69 42 6c 6b 20 3d 20 69  ntry[i].iBlk = i
11a0: 42 6c 6b 3b 0a 20 20 20 20 70 2d 3e 61 45 6e 74  Blk;.    p->aEnt
11b0: 72 79 5b 69 5d 2e 69 49 64 20 3d 20 69 49 64 3b  ry[i].iId = iId;
11c0: 0a 20 20 20 20 70 2d 3e 6e 45 6e 74 72 79 2b 2b  .    p->nEntry++
11d0: 3b 0a 20 20 7d 0a 0a 20 20 72 65 74 75 72 6e 20  ;.  }..  return 
11e0: 4c 53 4d 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a  LSM_OK;.}../*.**
11f0: 20 54 68 69 73 20 66 75 6e 63 74 69 6f 6e 20 66   This function f
1200: 72 65 65 73 20 61 6c 6c 20 72 65 73 6f 75 72 63  rees all resourc
1210: 65 73 20 68 65 6c 64 20 62 79 20 74 68 65 20 44  es held by the D
1220: 61 74 61 62 61 73 65 20 73 74 72 75 63 74 75 72  atabase structur
1230: 65 20 70 61 73 73 65 64 0a 2a 2a 20 61 73 20 74  e passed.** as t
1240: 68 65 20 6f 6e 6c 79 20 61 72 67 75 6d 65 6e 74  he only argument
1250: 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 76 6f 69 64  ..*/.static void
1260: 20 66 72 65 65 44 61 74 61 62 61 73 65 28 6c 73   freeDatabase(ls
1270: 6d 5f 65 6e 76 20 2a 70 45 6e 76 2c 20 44 61 74  m_env *pEnv, Dat
1280: 61 62 61 73 65 20 2a 70 29 7b 0a 20 20 61 73 73  abase *p){.  ass
1290: 65 72 74 28 20 68 6f 6c 64 69 6e 67 47 6c 6f 62  ert( holdingGlob
12a0: 61 6c 4d 75 74 65 78 28 70 45 6e 76 29 20 29 3b  alMutex(pEnv) );
12b0: 0a 20 20 69 66 28 20 70 20 29 7b 0a 20 20 20 20  .  if( p ){.    
12c0: 2f 2a 20 46 72 65 65 20 74 68 65 20 6d 75 74 65  /* Free the mute
12d0: 78 65 73 20 2a 2f 0a 20 20 20 20 6c 73 6d 4d 75  xes */.    lsmMu
12e0: 74 65 78 44 65 6c 28 70 45 6e 76 2c 20 70 2d 3e  texDel(pEnv, p->
12f0: 70 43 6c 69 65 6e 74 4d 75 74 65 78 29 3b 0a 0a  pClientMutex);..
1300: 20 20 20 20 69 66 28 20 70 2d 3e 70 46 69 6c 65      if( p->pFile
1310: 20 29 7b 0a 20 20 20 20 20 20 6c 73 6d 45 6e 76   ){.      lsmEnv
1320: 43 6c 6f 73 65 28 70 45 6e 76 2c 20 70 2d 3e 70  Close(pEnv, p->p
1330: 46 69 6c 65 29 3b 0a 20 20 20 20 7d 0a 0a 20 20  File);.    }..  
1340: 20 20 2f 2a 20 46 72 65 65 20 74 68 65 20 61 72    /* Free the ar
1350: 72 61 79 20 6f 66 20 73 68 6d 20 70 6f 69 6e 74  ray of shm point
1360: 65 72 73 20 2a 2f 0a 20 20 20 20 6c 73 6d 46 72  ers */.    lsmFr
1370: 65 65 28 70 45 6e 76 2c 20 70 2d 3e 61 70 53 68  ee(pEnv, p->apSh
1380: 6d 43 68 75 6e 6b 29 3b 0a 0a 20 20 20 20 2f 2a  mChunk);..    /*
1390: 20 46 72 65 65 20 74 68 65 20 6d 65 6d 6f 72 79   Free the memory
13a0: 20 61 6c 6c 6f 63 61 74 65 64 20 66 6f 72 20 74   allocated for t
13b0: 68 65 20 44 61 74 61 62 61 73 65 20 73 74 72 75  he Database stru
13c0: 63 74 20 69 74 73 65 6c 66 20 2a 2f 0a 20 20 20  ct itself */.   
13d0: 20 6c 73 6d 46 72 65 65 28 70 45 6e 76 2c 20 70   lsmFree(pEnv, p
13e0: 29 3b 0a 20 20 7d 0a 7d 0a 0a 74 79 70 65 64 65  );.  }.}..typede
13f0: 66 20 73 74 72 75 63 74 20 44 62 54 72 75 6e 63  f struct DbTrunc
1400: 61 74 65 43 74 78 20 44 62 54 72 75 6e 63 61 74  ateCtx DbTruncat
1410: 65 43 74 78 3b 0a 73 74 72 75 63 74 20 44 62 54  eCtx;.struct DbT
1420: 72 75 6e 63 61 74 65 43 74 78 20 7b 0a 20 20 69  runcateCtx {.  i
1430: 6e 74 20 6e 42 6c 6f 63 6b 3b 0a 20 20 69 36 34  nt nBlock;.  i64
1440: 20 69 49 6e 55 73 65 3b 0a 7d 3b 0a 0a 73 74 61   iInUse;.};..sta
1450: 74 69 63 20 69 6e 74 20 64 62 54 72 75 6e 63 61  tic int dbTrunca
1460: 74 65 43 62 28 76 6f 69 64 20 2a 70 43 74 78 2c  teCb(void *pCtx,
1470: 20 69 6e 74 20 69 42 6c 6b 2c 20 69 36 34 20 69   int iBlk, i64 i
1480: 53 6e 61 70 73 68 6f 74 29 7b 0a 20 20 44 62 54  Snapshot){.  DbT
1490: 72 75 6e 63 61 74 65 43 74 78 20 2a 70 20 3d 20  runcateCtx *p = 
14a0: 28 44 62 54 72 75 6e 63 61 74 65 43 74 78 20 2a  (DbTruncateCtx *
14b0: 29 70 43 74 78 3b 0a 20 20 69 66 28 20 69 42 6c  )pCtx;.  if( iBl
14c0: 6b 21 3d 70 2d 3e 6e 42 6c 6f 63 6b 20 7c 7c 20  k!=p->nBlock || 
14d0: 28 70 2d 3e 69 49 6e 55 73 65 3e 3d 30 20 26 26  (p->iInUse>=0 &&
14e0: 20 69 53 6e 61 70 73 68 6f 74 3e 3d 70 2d 3e 69   iSnapshot>=p->i
14f0: 49 6e 55 73 65 29 20 29 20 72 65 74 75 72 6e 20  InUse) ) return 
1500: 31 3b 0a 20 20 70 2d 3e 6e 42 6c 6f 63 6b 2d 2d  1;.  p->nBlock--
1510: 3b 0a 20 20 72 65 74 75 72 6e 20 30 3b 0a 7d 0a  ;.  return 0;.}.
1520: 0a 73 74 61 74 69 63 20 69 6e 74 20 64 62 54 72  .static int dbTr
1530: 75 6e 63 61 74 65 28 6c 73 6d 5f 64 62 20 2a 70  uncate(lsm_db *p
1540: 44 62 2c 20 69 36 34 20 69 49 6e 55 73 65 29 7b  Db, i64 iInUse){
1550: 0a 20 20 69 6e 74 20 72 63 20 3d 20 4c 53 4d 5f  .  int rc = LSM_
1560: 4f 4b 3b 0a 23 69 66 20 30 0a 20 20 69 6e 74 20  OK;.#if 0.  int 
1570: 69 3b 0a 20 20 44 62 54 72 75 6e 63 61 74 65 43  i;.  DbTruncateC
1580: 74 78 20 63 74 78 3b 0a 0a 20 20 61 73 73 65 72  tx ctx;..  asser
1590: 74 28 20 70 44 62 2d 3e 70 57 6f 72 6b 65 72 20  t( pDb->pWorker 
15a0: 29 3b 0a 20 20 63 74 78 2e 6e 42 6c 6f 63 6b 20  );.  ctx.nBlock 
15b0: 3d 20 70 44 62 2d 3e 70 57 6f 72 6b 65 72 2d 3e  = pDb->pWorker->
15c0: 6e 42 6c 6f 63 6b 3b 0a 20 20 63 74 78 2e 69 49  nBlock;.  ctx.iI
15d0: 6e 55 73 65 20 3d 20 69 49 6e 55 73 65 3b 0a 0a  nUse = iInUse;..
15e0: 20 20 72 63 20 3d 20 6c 73 6d 57 61 6c 6b 46 72    rc = lsmWalkFr
15f0: 65 65 6c 69 73 74 28 70 44 62 2c 20 31 2c 20 64  eelist(pDb, 1, d
1600: 62 54 72 75 6e 63 61 74 65 43 62 2c 20 28 76 6f  bTruncateCb, (vo
1610: 69 64 20 2a 29 26 63 74 78 29 3b 0a 20 20 66 6f  id *)&ctx);.  fo
1620: 72 28 69 3d 63 74 78 2e 6e 42 6c 6f 63 6b 2b 31  r(i=ctx.nBlock+1
1630: 3b 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 26 26 20  ; rc==LSM_OK && 
1640: 69 3c 3d 70 44 62 2d 3e 70 57 6f 72 6b 65 72 2d  i<=pDb->pWorker-
1650: 3e 6e 42 6c 6f 63 6b 3b 20 69 2b 2b 29 7b 0a 20  >nBlock; i++){. 
1660: 20 20 20 72 63 20 3d 20 66 72 65 65 6c 69 73 74     rc = freelist
1670: 41 70 70 65 6e 64 28 70 44 62 2c 20 69 2c 20 2d  Append(pDb, i, -
1680: 31 29 3b 0a 20 20 7d 0a 0a 20 20 69 66 28 20 72  1);.  }..  if( r
1690: 63 3d 3d 4c 53 4d 5f 4f 4b 20 29 7b 0a 23 69 66  c==LSM_OK ){.#if
16a0: 64 65 66 20 4c 53 4d 5f 4c 4f 47 5f 46 52 45 45  def LSM_LOG_FREE
16b0: 4c 49 53 54 0a 20 20 20 20 69 66 28 20 63 74 78  LIST.    if( ctx
16c0: 2e 6e 42 6c 6f 63 6b 21 3d 70 44 62 2d 3e 70 57  .nBlock!=pDb->pW
16d0: 6f 72 6b 65 72 2d 3e 6e 42 6c 6f 63 6b 20 29 7b  orker->nBlock ){
16e0: 0a 20 20 20 20 20 20 6c 73 6d 4c 6f 67 4d 65 73  .      lsmLogMes
16f0: 73 61 67 65 28 70 44 62 2c 20 30 2c 20 0a 20 20  sage(pDb, 0, .  
1700: 20 20 20 20 20 20 20 20 22 64 62 54 72 75 6e 63          "dbTrunc
1710: 61 74 65 28 29 3a 20 74 72 75 6e 63 61 74 65 64  ate(): truncated
1720: 20 64 62 20 74 6f 20 25 64 20 62 6c 6f 63 6b 73   db to %d blocks
1730: 22 2c 63 74 78 2e 6e 42 6c 6f 63 6b 0a 20 20 20  ",ctx.nBlock.   
1740: 20 20 20 29 3b 0a 20 20 20 20 7d 0a 23 65 6e 64     );.    }.#end
1750: 69 66 0a 20 20 20 20 70 44 62 2d 3e 70 57 6f 72  if.    pDb->pWor
1760: 6b 65 72 2d 3e 6e 42 6c 6f 63 6b 20 3d 20 63 74  ker->nBlock = ct
1770: 78 2e 6e 42 6c 6f 63 6b 3b 0a 20 20 7d 0a 23 65  x.nBlock;.  }.#e
1780: 6e 64 69 66 0a 20 20 72 65 74 75 72 6e 20 72 63  ndif.  return rc
1790: 3b 0a 7d 0a 0a 0a 2f 2a 0a 2a 2a 20 54 68 69 73  ;.}.../*.** This
17a0: 20 66 75 6e 63 74 69 6f 6e 20 69 73 20 63 61 6c   function is cal
17b0: 6c 65 64 20 64 75 72 69 6e 67 20 64 61 74 61 62  led during datab
17c0: 61 73 65 20 73 68 75 74 64 6f 77 6e 20 28 77 68  ase shutdown (wh
17d0: 65 6e 20 74 68 65 20 6e 75 6d 62 65 72 20 6f 66  en the number of
17e0: 0a 2a 2a 20 63 6f 6e 6e 65 63 74 69 6f 6e 73 20  .** connections 
17f0: 64 72 6f 70 73 20 66 72 6f 6d 20 6f 6e 65 20 74  drops from one t
1800: 6f 20 7a 65 72 6f 29 2e 20 49 74 20 74 72 75 6e  o zero). It trun
1810: 63 61 74 65 73 20 74 68 65 20 64 61 74 61 62 61  cates the databa
1820: 73 65 20 66 69 6c 65 0a 2a 2a 20 74 6f 20 61 73  se file.** to as
1830: 20 73 6d 61 6c 6c 20 61 20 73 69 7a 65 20 61 73   small a size as
1840: 20 70 6f 73 73 69 62 6c 65 20 77 69 74 68 6f 75   possible withou
1850: 74 20 74 72 75 6e 63 61 74 69 6e 67 20 61 77 61  t truncating awa
1860: 79 20 61 6e 79 20 62 6c 6f 63 6b 73 20 74 68 61  y any blocks tha
1870: 74 0a 2a 2a 20 63 6f 6e 74 61 69 6e 20 64 61 74  t.** contain dat
1880: 61 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74  a..*/.static int
1890: 20 64 62 54 72 75 6e 63 61 74 65 46 69 6c 65 28   dbTruncateFile(
18a0: 6c 73 6d 5f 64 62 20 2a 70 44 62 29 7b 0a 20 20  lsm_db *pDb){.  
18b0: 69 6e 74 20 72 63 3b 0a 0a 20 20 61 73 73 65 72  int rc;..  asser
18c0: 74 28 20 70 44 62 2d 3e 70 57 6f 72 6b 65 72 3d  t( pDb->pWorker=
18d0: 3d 30 20 29 3b 0a 20 20 61 73 73 65 72 74 28 20  =0 );.  assert( 
18e0: 6c 73 6d 53 68 6d 41 73 73 65 72 74 4c 6f 63 6b  lsmShmAssertLock
18f0: 28 70 44 62 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 44  (pDb, LSM_LOCK_D
1900: 4d 53 31 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 45 58  MS1, LSM_LOCK_EX
1910: 43 4c 29 20 29 3b 0a 20 20 72 63 20 3d 20 6c 73  CL) );.  rc = ls
1920: 6d 43 68 65 63 6b 70 6f 69 6e 74 4c 6f 61 64 57  mCheckpointLoadW
1930: 6f 72 6b 65 72 28 70 44 62 29 3b 0a 0a 20 20 69  orker(pDb);..  i
1940: 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 29 7b  f( rc==LSM_OK ){
1950: 0a 20 20 20 20 44 62 54 72 75 6e 63 61 74 65 43  .    DbTruncateC
1960: 74 78 20 63 74 78 3b 0a 0a 20 20 20 20 2f 2a 20  tx ctx;..    /* 
1970: 57 61 6c 6b 20 74 68 65 20 64 61 74 61 62 61 73  Walk the databas
1980: 65 20 66 72 65 65 2d 62 6c 6f 63 6b 2d 6c 69 73  e free-block-lis
1990: 74 20 69 6e 20 72 65 76 65 72 73 65 20 6f 72 64  t in reverse ord
19a0: 65 72 2e 20 53 65 74 20 63 74 78 2e 6e 42 6c 6f  er. Set ctx.nBlo
19b0: 63 6b 0a 20 20 20 20 2a 2a 20 74 6f 20 74 68 65  ck.    ** to the
19c0: 20 62 6c 6f 63 6b 20 6e 75 6d 62 65 72 20 6f 66   block number of
19d0: 20 74 68 65 20 6c 61 73 74 20 62 6c 6f 63 6b 20   the last block 
19e0: 69 6e 20 74 68 65 20 64 61 74 61 62 61 73 65 20  in the database 
19f0: 74 68 61 74 20 61 63 74 75 61 6c 6c 79 0a 20 20  that actually.  
1a00: 20 20 2a 2a 20 63 6f 6e 74 61 69 6e 73 20 64 61    ** contains da
1a10: 74 61 2e 20 2a 2f 0a 20 20 20 20 63 74 78 2e 6e  ta. */.    ctx.n
1a20: 42 6c 6f 63 6b 20 3d 20 70 44 62 2d 3e 70 57 6f  Block = pDb->pWo
1a30: 72 6b 65 72 2d 3e 6e 42 6c 6f 63 6b 3b 0a 20 20  rker->nBlock;.  
1a40: 20 20 63 74 78 2e 69 49 6e 55 73 65 20 3d 20 2d    ctx.iInUse = -
1a50: 31 3b 0a 20 20 20 20 72 63 20 3d 20 6c 73 6d 57  1;.    rc = lsmW
1a60: 61 6c 6b 46 72 65 65 6c 69 73 74 28 70 44 62 2c  alkFreelist(pDb,
1a70: 20 31 2c 20 64 62 54 72 75 6e 63 61 74 65 43 62   1, dbTruncateCb
1a80: 2c 20 28 76 6f 69 64 20 2a 29 26 63 74 78 29 3b  , (void *)&ctx);
1a90: 0a 0a 20 20 20 20 2f 2a 20 49 66 20 74 68 65 20  ..    /* If the 
1aa0: 6c 61 73 74 20 62 6c 6f 63 6b 20 74 68 61 74 20  last block that 
1ab0: 63 6f 6e 74 61 69 6e 73 20 64 61 74 61 20 69 73  contains data is
1ac0: 20 6e 6f 74 20 61 6c 72 65 61 64 79 20 74 68 65   not already the
1ad0: 20 6c 61 73 74 20 62 6c 6f 63 6b 20 69 6e 0a 20   last block in. 
1ae0: 20 20 20 2a 2a 20 74 68 65 20 64 61 74 61 62 61     ** the databa
1af0: 73 65 20 66 69 6c 65 2c 20 74 72 75 6e 63 61 74  se file, truncat
1b00: 65 20 74 68 65 20 64 61 74 61 62 61 73 65 20 66  e the database f
1b10: 69 6c 65 20 73 6f 20 74 68 61 74 20 69 74 20 69  ile so that it i
1b20: 73 2e 20 2a 2f 0a 20 20 20 20 69 66 28 20 72 63  s. */.    if( rc
1b30: 3d 3d 4c 53 4d 5f 4f 4b 20 29 7b 0a 20 20 20 20  ==LSM_OK ){.    
1b40: 20 20 72 63 20 3d 20 6c 73 6d 46 73 54 72 75 6e    rc = lsmFsTrun
1b50: 63 61 74 65 44 62 28 0a 20 20 20 20 20 20 20 20  cateDb(.        
1b60: 20 20 70 44 62 2d 3e 70 46 53 2c 20 28 69 36 34    pDb->pFS, (i64
1b70: 29 63 74 78 2e 6e 42 6c 6f 63 6b 2a 6c 73 6d 46  )ctx.nBlock*lsmF
1b80: 73 42 6c 6f 63 6b 53 69 7a 65 28 70 44 62 2d 3e  sBlockSize(pDb->
1b90: 70 46 53 29 0a 20 20 20 20 20 20 29 3b 0a 20 20  pFS).      );.  
1ba0: 20 20 7d 0a 20 20 7d 0a 0a 20 20 6c 73 6d 46 72    }.  }..  lsmFr
1bb0: 65 65 53 6e 61 70 73 68 6f 74 28 70 44 62 2d 3e  eeSnapshot(pDb->
1bc0: 70 45 6e 76 2c 20 70 44 62 2d 3e 70 57 6f 72 6b  pEnv, pDb->pWork
1bd0: 65 72 29 3b 0a 20 20 70 44 62 2d 3e 70 57 6f 72  er);.  pDb->pWor
1be0: 6b 65 72 20 3d 20 30 3b 0a 20 20 72 65 74 75 72  ker = 0;.  retur
1bf0: 6e 20 72 63 3b 0a 7d 0a 0a 73 74 61 74 69 63 20  n rc;.}..static 
1c00: 76 6f 69 64 20 64 6f 44 62 44 69 73 63 6f 6e 6e  void doDbDisconn
1c10: 65 63 74 28 6c 73 6d 5f 64 62 20 2a 70 44 62 29  ect(lsm_db *pDb)
1c20: 7b 0a 20 20 69 6e 74 20 72 63 3b 0a 0a 20 20 69  {.  int rc;..  i
1c30: 66 28 20 70 44 62 2d 3e 62 52 65 61 64 6f 6e 6c  f( pDb->bReadonl
1c40: 79 20 29 7b 0a 20 20 20 20 6c 73 6d 53 68 6d 4c  y ){.    lsmShmL
1c50: 6f 63 6b 28 70 44 62 2c 20 4c 53 4d 5f 4c 4f 43  ock(pDb, LSM_LOC
1c60: 4b 5f 44 4d 53 33 2c 20 4c 53 4d 5f 4c 4f 43 4b  K_DMS3, LSM_LOCK
1c70: 5f 55 4e 4c 4f 43 4b 2c 20 30 29 3b 0a 20 20 7d  _UNLOCK, 0);.  }
1c80: 65 6c 73 65 7b 0a 20 20 20 20 2f 2a 20 42 6c 6f  else{.    /* Blo
1c90: 63 6b 20 66 6f 72 20 61 6e 20 65 78 63 6c 75 73  ck for an exclus
1ca0: 69 76 65 20 6c 6f 63 6b 20 6f 6e 20 44 4d 53 31  ive lock on DMS1
1cb0: 2e 20 54 68 69 73 20 6c 6f 63 6b 20 73 65 72 69  . This lock seri
1cc0: 61 6c 69 7a 65 73 20 61 6c 6c 20 63 61 6c 6c 73  alizes all calls
1cd0: 0a 20 20 20 20 2a 2a 20 74 6f 20 64 6f 44 62 43  .    ** to doDbC
1ce0: 6f 6e 6e 65 63 74 28 29 20 61 6e 64 20 64 6f 44  onnect() and doD
1cf0: 62 44 69 73 63 6f 6e 6e 65 63 74 28 29 20 61 63  bDisconnect() ac
1d00: 72 6f 73 73 20 61 6c 6c 20 70 72 6f 63 65 73 73  ross all process
1d10: 65 73 2e 20 20 2a 2f 0a 20 20 20 20 72 63 20 3d  es.  */.    rc =
1d20: 20 6c 73 6d 53 68 6d 4c 6f 63 6b 28 70 44 62 2c   lsmShmLock(pDb,
1d30: 20 4c 53 4d 5f 4c 4f 43 4b 5f 44 4d 53 31 2c 20   LSM_LOCK_DMS1, 
1d40: 4c 53 4d 5f 4c 4f 43 4b 5f 45 58 43 4c 2c 20 31  LSM_LOCK_EXCL, 1
1d50: 29 3b 0a 20 20 20 20 69 66 28 20 72 63 3d 3d 4c  );.    if( rc==L
1d60: 53 4d 5f 4f 4b 20 29 7b 0a 0a 20 20 20 20 20 20  SM_OK ){..      
1d70: 6c 73 6d 53 68 6d 4c 6f 63 6b 28 70 44 62 2c 20  lsmShmLock(pDb, 
1d80: 4c 53 4d 5f 4c 4f 43 4b 5f 44 4d 53 32 2c 20 4c  LSM_LOCK_DMS2, L
1d90: 53 4d 5f 4c 4f 43 4b 5f 55 4e 4c 4f 43 4b 2c 20  SM_LOCK_UNLOCK, 
1da0: 30 29 3b 0a 0a 20 20 20 20 20 20 2f 2a 20 54 72  0);..      /* Tr
1db0: 79 20 61 6e 20 65 78 63 6c 75 73 69 76 65 20 6c  y an exclusive l
1dc0: 6f 63 6b 20 6f 6e 20 44 4d 53 32 2e 20 49 66 20  ock on DMS2. If 
1dd0: 73 75 63 63 65 73 73 66 75 6c 2c 20 74 68 69 73  successful, this
1de0: 20 69 73 20 74 68 65 20 6c 61 73 74 0a 20 20 20   is the last.   
1df0: 20 20 20 2a 2a 20 63 6f 6e 6e 65 63 74 69 6f 6e     ** connection
1e00: 20 74 6f 20 74 68 65 20 64 61 74 61 62 61 73 65   to the database
1e10: 2e 20 49 6e 20 74 68 69 73 20 63 61 73 65 20 66  . In this case f
1e20: 6c 75 73 68 20 74 68 65 20 63 6f 6e 74 65 6e 74  lush the content
1e30: 73 20 6f 66 20 74 68 65 0a 20 20 20 20 20 20 2a  s of the.      *
1e40: 2a 20 69 6e 2d 6d 65 6d 6f 72 79 20 74 72 65 65  * in-memory tree
1e50: 20 74 6f 20 64 69 73 6b 20 61 6e 64 20 77 72 69   to disk and wri
1e60: 74 65 20 61 20 63 68 65 63 6b 70 6f 69 6e 74 2e  te a checkpoint.
1e70: 20 20 2a 2f 0a 20 20 20 20 20 20 72 63 20 3d 20    */.      rc = 
1e80: 6c 73 6d 53 68 6d 54 65 73 74 4c 6f 63 6b 28 70  lsmShmTestLock(p
1e90: 44 62 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 44 4d 53  Db, LSM_LOCK_DMS
1ea0: 32 2c 20 31 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 45  2, 1, LSM_LOCK_E
1eb0: 58 43 4c 29 3b 0a 20 20 20 20 20 20 69 66 28 20  XCL);.      if( 
1ec0: 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 29 7b 0a 20 20  rc==LSM_OK ){.  
1ed0: 20 20 20 20 20 20 72 63 20 3d 20 6c 73 6d 53 68        rc = lsmSh
1ee0: 6d 54 65 73 74 4c 6f 63 6b 28 70 44 62 2c 20 4c  mTestLock(pDb, L
1ef0: 53 4d 5f 4c 4f 43 4b 5f 43 48 45 43 4b 50 4f 49  SM_LOCK_CHECKPOI
1f00: 4e 54 45 52 2c 20 31 2c 20 4c 53 4d 5f 4c 4f 43  NTER, 1, LSM_LOC
1f10: 4b 5f 45 58 43 4c 29 3b 0a 20 20 20 20 20 20 7d  K_EXCL);.      }
1f20: 0a 20 20 20 20 20 20 69 66 28 20 72 63 3d 3d 4c  .      if( rc==L
1f30: 53 4d 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 20  SM_OK ){.       
1f40: 20 69 6e 74 20 62 52 65 61 64 6f 6e 6c 79 20 3d   int bReadonly =
1f50: 20 30 3b 20 20 20 20 20 20 20 20 2f 2a 20 54 72   0;        /* Tr
1f60: 75 65 20 69 66 20 74 68 65 72 65 20 65 78 69 73  ue if there exis
1f70: 74 20 72 65 61 64 2d 6f 6e 6c 79 20 63 6f 6e 6e  t read-only conn
1f80: 73 2e 20 2a 2f 0a 0a 20 20 20 20 20 20 20 20 2f  s. */..        /
1f90: 2a 20 46 6c 75 73 68 20 74 68 65 20 69 6e 2d 6d  * Flush the in-m
1fa0: 65 6d 6f 72 79 20 74 72 65 65 2c 20 69 66 20 72  emory tree, if r
1fb0: 65 71 75 69 72 65 64 2e 20 49 66 20 74 68 65 72  equired. If ther
1fc0: 65 20 69 73 20 64 61 74 61 20 74 6f 20 66 6c 75  e is data to flu
1fd0: 73 68 2c 0a 20 20 20 20 20 20 20 20 2a 2a 20 74  sh,.        ** t
1fe0: 68 69 73 20 77 69 6c 6c 20 63 72 65 61 74 65 20  his will create 
1ff0: 61 20 6e 65 77 20 63 6c 69 65 6e 74 20 73 6e 61  a new client sna
2000: 70 73 68 6f 74 20 69 6e 20 44 61 74 61 62 61 73  pshot in Databas
2010: 65 2e 70 43 6c 69 65 6e 74 2e 20 54 68 65 0a 20  e.pClient. The. 
2020: 20 20 20 20 20 20 20 2a 2a 20 63 68 65 63 6b 70         ** checkp
2030: 6f 69 6e 74 20 28 73 65 72 69 61 6c 69 7a 61 74  oint (serializat
2040: 69 6f 6e 29 20 6f 66 20 74 68 69 73 20 73 6e 61  ion) of this sna
2050: 70 73 68 6f 74 20 6d 61 79 20 62 65 20 77 72 69  pshot may be wri
2060: 74 74 65 6e 20 74 6f 20 64 69 73 6b 0a 20 20 20  tten to disk.   
2070: 20 20 20 20 20 2a 2a 20 62 79 20 74 68 65 20 66       ** by the f
2080: 6f 6c 6c 6f 77 69 6e 67 20 62 6c 6f 63 6b 2e 20  ollowing block. 
2090: 20 0a 20 20 20 20 20 20 20 20 2a 2a 0a 20 20 20   .        **.   
20a0: 20 20 20 20 20 2a 2a 20 54 68 65 72 65 20 69 73       ** There is
20b0: 20 6e 6f 20 6e 65 65 64 20 74 6f 20 74 61 6b 65   no need to take
20c0: 20 61 20 57 52 49 54 45 52 20 6c 6f 63 6b 20 68   a WRITER lock h
20d0: 65 72 65 2e 20 54 68 61 74 20 74 68 65 72 65 20  ere. That there 
20e0: 61 72 65 20 6e 6f 20 0a 20 20 20 20 20 20 20 20  are no .        
20f0: 2a 2a 20 6f 74 68 65 72 20 6c 6f 63 6b 73 20 6f  ** other locks o
2100: 6e 20 44 4d 53 32 20 67 75 61 72 61 6e 74 65 65  n DMS2 guarantee
2110: 73 20 74 68 61 74 20 74 68 65 72 65 20 61 72 65  s that there are
2120: 20 6e 6f 20 6f 74 68 65 72 20 72 65 61 64 2d 77   no other read-w
2130: 72 69 74 65 0a 20 20 20 20 20 20 20 20 2a 2a 20  rite.        ** 
2140: 63 6f 6e 6e 65 63 74 69 6f 6e 73 20 61 74 20 74  connections at t
2150: 68 69 73 20 74 69 6d 65 20 28 61 6e 64 20 74 68  his time (and th
2160: 65 20 6c 6f 63 6b 20 6f 6e 20 44 4d 53 31 20 67  e lock on DMS1 g
2170: 75 61 72 61 6e 74 65 65 73 20 74 68 61 74 0a 20  uarantees that. 
2180: 20 20 20 20 20 20 20 2a 2a 20 6e 6f 20 6e 65 77         ** no new
2190: 20 6f 6e 65 73 20 6d 61 79 20 61 70 70 65 61 72   ones may appear
21a0: 29 2e 0a 20 20 20 20 20 20 20 20 2a 2f 0a 20 20  )..        */.  
21b0: 20 20 20 20 20 20 72 63 20 3d 20 6c 73 6d 54 72        rc = lsmTr
21c0: 65 65 4c 6f 61 64 48 65 61 64 65 72 28 70 44 62  eeLoadHeader(pDb
21d0: 2c 20 30 29 3b 0a 20 20 20 20 20 20 20 20 69 66  , 0);.        if
21e0: 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 26 26 20  ( rc==LSM_OK && 
21f0: 28 6c 73 6d 54 72 65 65 48 61 73 4f 6c 64 28 70  (lsmTreeHasOld(p
2200: 44 62 29 20 7c 7c 20 6c 73 6d 54 72 65 65 53 69  Db) || lsmTreeSi
2210: 7a 65 28 70 44 62 29 3e 30 29 20 29 7b 0a 20 20  ze(pDb)>0) ){.  
2220: 20 20 20 20 20 20 20 20 72 63 20 3d 20 6c 73 6d          rc = lsm
2230: 46 6c 75 73 68 54 72 65 65 54 6f 44 69 73 6b 28  FlushTreeToDisk(
2240: 70 44 62 29 3b 0a 20 20 20 20 20 20 20 20 7d 0a  pDb);.        }.
2250: 0a 20 20 20 20 20 20 20 20 2f 2a 20 4e 6f 77 20  .        /* Now 
2260: 63 68 65 63 6b 20 69 66 20 74 68 65 72 65 20 61  check if there a
2270: 72 65 20 61 6e 79 20 72 65 61 64 2d 6f 6e 6c 79  re any read-only
2280: 20 63 6f 6e 6e 65 63 74 69 6f 6e 73 2e 20 49 66   connections. If
2290: 20 74 68 65 72 65 20 61 72 65 2c 0a 20 20 20 20   there are,.    
22a0: 20 20 20 20 2a 2a 20 74 68 65 6e 20 64 6f 20 6e      ** then do n
22b0: 6f 74 20 74 72 75 6e 63 61 74 65 20 74 68 65 20  ot truncate the 
22c0: 64 62 20 66 69 6c 65 20 6f 72 20 75 6e 6c 69 6e  db file or unlin
22d0: 6b 20 74 68 65 20 73 68 61 72 65 64 2d 6d 65 6d  k the shared-mem
22e0: 6f 72 79 20 0a 20 20 20 20 20 20 20 20 2a 2a 20  ory .        ** 
22f0: 72 65 67 69 6f 6e 2e 20 20 2a 2f 0a 20 20 20 20  region.  */.    
2300: 20 20 20 20 69 66 28 20 72 63 3d 3d 4c 53 4d 5f      if( rc==LSM_
2310: 4f 4b 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20  OK ){.          
2320: 72 63 20 3d 20 6c 73 6d 53 68 6d 54 65 73 74 4c  rc = lsmShmTestL
2330: 6f 63 6b 28 70 44 62 2c 20 4c 53 4d 5f 4c 4f 43  ock(pDb, LSM_LOC
2340: 4b 5f 44 4d 53 33 2c 20 31 2c 20 4c 53 4d 5f 4c  K_DMS3, 1, LSM_L
2350: 4f 43 4b 5f 45 58 43 4c 29 3b 0a 20 20 20 20 20  OCK_EXCL);.     
2360: 20 20 20 20 20 69 66 28 20 72 63 3d 3d 4c 53 4d       if( rc==LSM
2370: 5f 42 55 53 59 20 29 7b 0a 20 20 20 20 20 20 20  _BUSY ){.       
2380: 20 20 20 20 20 62 52 65 61 64 6f 6e 6c 79 20 3d       bReadonly =
2390: 20 31 3b 0a 20 20 20 20 20 20 20 20 20 20 20 20   1;.            
23a0: 72 63 20 3d 20 4c 53 4d 5f 4f 4b 3b 0a 20 20 20  rc = LSM_OK;.   
23b0: 20 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 20         }.       
23c0: 20 7d 0a 0a 20 20 20 20 20 20 20 20 2f 2a 20 57   }..        /* W
23d0: 72 69 74 65 20 61 20 63 68 65 63 6b 70 6f 69 6e  rite a checkpoin
23e0: 74 20 74 6f 20 64 69 73 6b 2e 20 2a 2f 0a 20 20  t to disk. */.  
23f0: 20 20 20 20 20 20 69 66 28 20 72 63 3d 3d 4c 53        if( rc==LS
2400: 4d 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 20 20  M_OK ){.        
2410: 20 20 72 63 20 3d 20 6c 73 6d 43 68 65 63 6b 70    rc = lsmCheckp
2420: 6f 69 6e 74 57 72 69 74 65 28 70 44 62 2c 20 30  ointWrite(pDb, 0
2430: 29 3b 0a 20 20 20 20 20 20 20 20 7d 0a 0a 20 20  );.        }..  
2440: 20 20 20 20 20 20 2f 2a 20 49 66 20 74 68 65 20        /* If the 
2450: 63 68 65 63 6b 70 6f 69 6e 74 20 77 61 73 20 77  checkpoint was w
2460: 72 69 74 74 65 6e 20 73 75 63 63 65 73 73 66 75  ritten successfu
2470: 6c 6c 79 2c 20 64 65 6c 65 74 65 20 74 68 65 20  lly, delete the 
2480: 6c 6f 67 20 66 69 6c 65 0a 20 20 20 20 20 20 20  log file.       
2490: 20 2a 2a 20 61 6e 64 2c 20 69 66 20 70 6f 73 73   ** and, if poss
24a0: 69 62 6c 65 2c 20 74 72 75 6e 63 61 74 65 20 74  ible, truncate t
24b0: 68 65 20 64 61 74 61 62 61 73 65 20 66 69 6c 65  he database file
24c0: 2e 20 20 2a 2f 0a 20 20 20 20 20 20 20 20 69 66  .  */.        if
24d0: 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 29 7b 0a  ( rc==LSM_OK ){.
24e0: 20 20 20 20 20 20 20 20 20 20 69 6e 74 20 62 52            int bR
24f0: 6f 74 72 61 6e 73 20 3d 20 30 3b 0a 20 20 20 20  otrans = 0;.    
2500: 20 20 20 20 20 20 44 61 74 61 62 61 73 65 20 2a        Database *
2510: 70 20 3d 20 70 44 62 2d 3e 70 44 61 74 61 62 61  p = pDb->pDataba
2520: 73 65 3b 0a 0a 20 20 20 20 20 20 20 20 20 20 2f  se;..          /
2530: 2a 20 54 68 65 20 6c 6f 67 20 66 69 6c 65 20 6d  * The log file m
2540: 61 79 20 6f 6e 6c 79 20 62 65 20 64 65 6c 65 74  ay only be delet
2550: 65 64 20 69 66 20 74 68 65 72 65 20 61 72 65 20  ed if there are 
2560: 6e 6f 20 63 6c 69 65 6e 74 73 20 0a 20 20 20 20  no clients .    
2570: 20 20 20 20 20 20 2a 2a 20 72 65 61 64 2d 6f 6e        ** read-on
2580: 6c 79 20 63 6c 69 65 6e 74 73 20 72 75 6e 6e 69  ly clients runni
2590: 6e 67 20 72 6f 74 72 61 6e 73 20 74 72 61 6e 73  ng rotrans trans
25a0: 61 63 74 69 6f 6e 73 2e 20 20 2a 2f 0a 20 20 20  actions.  */.   
25b0: 20 20 20 20 20 20 20 72 63 20 3d 20 6c 73 6d 44         rc = lsmD
25c0: 65 74 65 63 74 52 6f 54 72 61 6e 73 28 70 44 62  etectRoTrans(pDb
25d0: 2c 20 26 62 52 6f 74 72 61 6e 73 29 3b 0a 20 20  , &bRotrans);.  
25e0: 20 20 20 20 20 20 20 20 69 66 28 20 72 63 3d 3d          if( rc==
25f0: 4c 53 4d 5f 4f 4b 20 26 26 20 62 52 6f 74 72 61  LSM_OK && bRotra
2600: 6e 73 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 20  ns==0 ){.       
2610: 20 20 20 20 20 6c 73 6d 46 73 43 6c 6f 73 65 41       lsmFsCloseA
2620: 6e 64 44 65 6c 65 74 65 4c 6f 67 28 70 44 62 2d  ndDeleteLog(pDb-
2630: 3e 70 46 53 29 3b 0a 20 20 20 20 20 20 20 20 20  >pFS);.         
2640: 20 7d 0a 0a 20 20 20 20 20 20 20 20 20 20 2f 2a   }..          /*
2650: 20 54 68 65 20 64 61 74 61 62 61 73 65 20 6d 61   The database ma
2660: 79 20 6f 6e 6c 79 20 62 65 20 74 72 75 6e 63 61  y only be trunca
2670: 74 65 64 20 69 66 20 74 68 65 72 65 20 65 78 69  ted if there exi
2680: 73 74 20 6e 6f 20 72 65 61 64 2d 6f 6e 6c 79 0a  st no read-only.
2690: 20 20 20 20 20 20 20 20 20 20 2a 2a 20 63 6c 69            ** cli
26a0: 65 6e 74 73 20 2d 20 65 69 74 68 65 72 20 63 6f  ents - either co
26b0: 6e 6e 65 63 74 65 64 20 6f 72 20 72 75 6e 6e 69  nnected or runni
26c0: 6e 67 20 72 6f 74 72 61 6e 73 20 74 72 61 6e 73  ng rotrans trans
26d0: 61 63 74 69 6f 6e 73 2e 20 2a 2f 0a 20 20 20 20  actions. */.    
26e0: 20 20 20 20 20 20 69 66 28 20 62 52 65 61 64 6f        if( bReado
26f0: 6e 6c 79 3d 3d 30 20 26 26 20 62 52 6f 74 72 61  nly==0 && bRotra
2700: 6e 73 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 20  ns==0 ){.       
2710: 20 20 20 20 20 6c 73 6d 46 73 55 6e 6d 61 70 28       lsmFsUnmap(
2720: 70 44 62 2d 3e 70 46 53 29 3b 0a 20 20 20 20 20  pDb->pFS);.     
2730: 20 20 20 20 20 20 20 64 62 54 72 75 6e 63 61 74         dbTruncat
2740: 65 46 69 6c 65 28 70 44 62 29 3b 0a 20 20 20 20  eFile(pDb);.    
2750: 20 20 20 20 20 20 20 20 69 66 28 20 70 2d 3e 70          if( p->p
2760: 46 69 6c 65 20 26 26 20 70 2d 3e 62 4d 75 6c 74  File && p->bMult
2770: 69 50 72 6f 63 20 29 7b 0a 20 20 20 20 20 20 20  iProc ){.       
2780: 20 20 20 20 20 20 20 6c 73 6d 45 6e 76 53 68 6d         lsmEnvShm
2790: 55 6e 6d 61 70 28 70 44 62 2d 3e 70 45 6e 76 2c  Unmap(pDb->pEnv,
27a0: 20 70 2d 3e 70 46 69 6c 65 2c 20 31 29 3b 0a 20   p->pFile, 1);. 
27b0: 20 20 20 20 20 20 20 20 20 20 20 7d 0a 20 20 20             }.   
27c0: 20 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 20         }.       
27d0: 20 7d 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 7d   }.      }.    }
27e0: 0a 0a 20 20 20 20 69 66 28 20 70 44 62 2d 3e 69  ..    if( pDb->i
27f0: 52 77 63 6c 69 65 6e 74 3e 3d 30 20 29 7b 0a 20  Rwclient>=0 ){. 
2800: 20 20 20 20 20 6c 73 6d 53 68 6d 4c 6f 63 6b 28       lsmShmLock(
2810: 70 44 62 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 52 57  pDb, LSM_LOCK_RW
2820: 43 4c 49 45 4e 54 28 70 44 62 2d 3e 69 52 77 63  CLIENT(pDb->iRwc
2830: 6c 69 65 6e 74 29 2c 20 4c 53 4d 5f 4c 4f 43 4b  lient), LSM_LOCK
2840: 5f 55 4e 4c 4f 43 4b 2c 20 30 29 3b 0a 20 20 20  _UNLOCK, 0);.   
2850: 20 20 20 70 44 62 2d 3e 69 52 77 63 6c 69 65 6e     pDb->iRwclien
2860: 74 20 3d 20 2d 31 3b 0a 20 20 20 20 7d 0a 0a 20  t = -1;.    }.. 
2870: 20 20 20 6c 73 6d 53 68 6d 4c 6f 63 6b 28 70 44     lsmShmLock(pD
2880: 62 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 44 4d 53 31  b, LSM_LOCK_DMS1
2890: 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 55 4e 4c 4f 43  , LSM_LOCK_UNLOC
28a0: 4b 2c 20 30 29 3b 0a 20 20 7d 0a 20 20 70 44 62  K, 0);.  }.  pDb
28b0: 2d 3e 70 53 68 6d 68 64 72 20 3d 20 30 3b 0a 7d  ->pShmhdr = 0;.}
28c0: 0a 0a 73 74 61 74 69 63 20 69 6e 74 20 64 6f 44  ..static int doD
28d0: 62 43 6f 6e 6e 65 63 74 28 6c 73 6d 5f 64 62 20  bConnect(lsm_db 
28e0: 2a 70 44 62 29 7b 0a 20 20 63 6f 6e 73 74 20 69  *pDb){.  const i
28f0: 6e 74 20 6e 55 73 4d 61 78 20 3d 20 31 30 30 30  nt nUsMax = 1000
2900: 30 30 3b 20 20 20 20 20 20 2f 2a 20 4d 61 78 20  00;      /* Max 
2910: 76 61 6c 75 65 20 66 6f 72 20 6e 55 73 20 2a 2f  value for nUs */
2920: 0a 20 20 69 6e 74 20 6e 55 73 20 3d 20 31 30 30  .  int nUs = 100
2930: 30 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  0;              
2940: 20 20 20 2f 2a 20 75 73 20 74 6f 20 77 61 69 74     /* us to wait
2950: 20 62 65 74 77 65 65 6e 20 44 4d 53 31 20 61 74   between DMS1 at
2960: 74 65 6d 70 74 73 20 2a 2f 0a 20 20 69 6e 74 20  tempts */.  int 
2970: 72 63 3b 0a 0a 20 20 2f 2a 20 4f 62 74 61 69 6e  rc;..  /* Obtain
2980: 20 61 20 70 6f 69 6e 74 65 72 20 74 6f 20 74 68   a pointer to th
2990: 65 20 73 68 61 72 65 64 2d 6d 65 6d 6f 72 79 20  e shared-memory 
29a0: 68 65 61 64 65 72 20 2a 2f 0a 20 20 61 73 73 65  header */.  asse
29b0: 72 74 28 20 70 44 62 2d 3e 70 53 68 6d 68 64 72  rt( pDb->pShmhdr
29c0: 3d 3d 30 20 29 3b 0a 20 20 61 73 73 65 72 74 28  ==0 );.  assert(
29d0: 20 70 44 62 2d 3e 62 52 65 61 64 6f 6e 6c 79 3d   pDb->bReadonly=
29e0: 3d 30 20 29 3b 0a 0a 20 20 2f 2a 20 42 6c 6f 63  =0 );..  /* Bloc
29f0: 6b 20 66 6f 72 20 61 6e 20 65 78 63 6c 75 73 69  k for an exclusi
2a00: 76 65 20 6c 6f 63 6b 20 6f 6e 20 44 4d 53 31 2e  ve lock on DMS1.
2a10: 20 54 68 69 73 20 6c 6f 63 6b 20 73 65 72 69 61   This lock seria
2a20: 6c 69 7a 65 73 20 61 6c 6c 20 63 61 6c 6c 73 0a  lizes all calls.
2a30: 20 20 2a 2a 20 74 6f 20 64 6f 44 62 43 6f 6e 6e    ** to doDbConn
2a40: 65 63 74 28 29 20 61 6e 64 20 64 6f 44 62 44 69  ect() and doDbDi
2a50: 73 63 6f 6e 6e 65 63 74 28 29 20 61 63 72 6f 73  sconnect() acros
2a60: 73 20 61 6c 6c 20 70 72 6f 63 65 73 73 65 73 2e  s all processes.
2a70: 20 20 2a 2f 0a 20 20 77 68 69 6c 65 28 20 31 20    */.  while( 1 
2a80: 29 7b 0a 20 20 20 20 72 63 20 3d 20 6c 73 6d 53  ){.    rc = lsmS
2a90: 68 6d 4c 6f 63 6b 28 70 44 62 2c 20 4c 53 4d 5f  hmLock(pDb, LSM_
2aa0: 4c 4f 43 4b 5f 44 4d 53 31 2c 20 4c 53 4d 5f 4c  LOCK_DMS1, LSM_L
2ab0: 4f 43 4b 5f 45 58 43 4c 2c 20 31 29 3b 0a 20 20  OCK_EXCL, 1);.  
2ac0: 20 20 69 66 28 20 72 63 21 3d 4c 53 4d 5f 42 55    if( rc!=LSM_BU
2ad0: 53 59 20 29 20 62 72 65 61 6b 3b 0a 20 20 20 20  SY ) break;.    
2ae0: 6c 73 6d 45 6e 76 53 6c 65 65 70 28 70 44 62 2d  lsmEnvSleep(pDb-
2af0: 3e 70 45 6e 76 2c 20 6e 55 73 29 3b 0a 20 20 20  >pEnv, nUs);.   
2b00: 20 6e 55 73 20 3d 20 6e 55 73 20 2a 20 32 3b 0a   nUs = nUs * 2;.
2b10: 20 20 20 20 69 66 28 20 6e 55 73 3e 6e 55 73 4d      if( nUs>nUsM
2b20: 61 78 20 29 20 6e 55 73 20 3d 20 6e 55 73 4d 61  ax ) nUs = nUsMa
2b30: 78 3b 0a 20 20 7d 0a 20 20 69 66 28 20 72 63 3d  x;.  }.  if( rc=
2b40: 3d 4c 53 4d 5f 4f 4b 20 29 7b 0a 20 20 20 20 72  =LSM_OK ){.    r
2b50: 63 20 3d 20 6c 73 6d 53 68 6d 43 61 63 68 65 43  c = lsmShmCacheC
2b60: 68 75 6e 6b 73 28 70 44 62 2c 20 31 29 3b 0a 20  hunks(pDb, 1);. 
2b70: 20 7d 0a 20 20 69 66 28 20 72 63 21 3d 4c 53 4d   }.  if( rc!=LSM
2b80: 5f 4f 4b 20 29 20 72 65 74 75 72 6e 20 72 63 3b  _OK ) return rc;
2b90: 0a 20 20 70 44 62 2d 3e 70 53 68 6d 68 64 72 20  .  pDb->pShmhdr 
2ba0: 3d 20 28 53 68 6d 48 65 61 64 65 72 20 2a 29 70  = (ShmHeader *)p
2bb0: 44 62 2d 3e 61 70 53 68 6d 5b 30 5d 3b 0a 0a 20  Db->apShm[0];.. 
2bc0: 20 2f 2a 20 54 72 79 20 61 6e 20 65 78 63 6c 75   /* Try an exclu
2bd0: 73 69 76 65 20 6c 6f 63 6b 20 6f 6e 20 44 4d 53  sive lock on DMS
2be0: 32 2f 44 4d 53 33 2e 20 49 66 20 73 75 63 63 65  2/DMS3. If succe
2bf0: 73 73 66 75 6c 2c 20 74 68 69 73 20 69 73 20 74  ssful, this is t
2c00: 68 65 20 66 69 72 73 74 20 0a 20 20 2a 2a 20 61  he first .  ** a
2c10: 6e 64 20 6f 6e 6c 79 20 63 6f 6e 6e 65 63 74 69  nd only connecti
2c20: 6f 6e 20 74 6f 20 74 68 65 20 64 61 74 61 62 61  on to the databa
2c30: 73 65 2e 20 49 6e 20 74 68 69 73 20 63 61 73 65  se. In this case
2c40: 20 69 6e 69 74 69 61 6c 69 7a 65 20 74 68 65 20   initialize the 
2c50: 0a 20 20 2a 2a 20 73 68 61 72 65 64 2d 6d 65 6d  .  ** shared-mem
2c60: 6f 72 79 20 61 6e 64 20 72 75 6e 20 6c 6f 67 20  ory and run log 
2c70: 66 69 6c 65 20 72 65 63 6f 76 65 72 79 2e 20 20  file recovery.  
2c80: 2a 2f 0a 20 20 61 73 73 65 72 74 28 20 4c 53 4d  */.  assert( LSM
2c90: 5f 4c 4f 43 4b 5f 44 4d 53 33 3d 3d 31 2b 4c 53  _LOCK_DMS3==1+LS
2ca0: 4d 5f 4c 4f 43 4b 5f 44 4d 53 32 20 29 3b 0a 20  M_LOCK_DMS2 );. 
2cb0: 20 72 63 20 3d 20 6c 73 6d 53 68 6d 54 65 73 74   rc = lsmShmTest
2cc0: 4c 6f 63 6b 28 70 44 62 2c 20 4c 53 4d 5f 4c 4f  Lock(pDb, LSM_LO
2cd0: 43 4b 5f 44 4d 53 32 2c 20 32 2c 20 4c 53 4d 5f  CK_DMS2, 2, LSM_
2ce0: 4c 4f 43 4b 5f 45 58 43 4c 29 3b 0a 20 20 69 66  LOCK_EXCL);.  if
2cf0: 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 29 7b 0a  ( rc==LSM_OK ){.
2d00: 20 20 20 20 6d 65 6d 73 65 74 28 70 44 62 2d 3e      memset(pDb->
2d10: 70 53 68 6d 68 64 72 2c 20 30 2c 20 73 69 7a 65  pShmhdr, 0, size
2d20: 6f 66 28 53 68 6d 48 65 61 64 65 72 29 29 3b 0a  of(ShmHeader));.
2d30: 20 20 20 20 72 63 20 3d 20 6c 73 6d 43 68 65 63      rc = lsmChec
2d40: 6b 70 6f 69 6e 74 52 65 63 6f 76 65 72 28 70 44  kpointRecover(pD
2d50: 62 29 3b 0a 20 20 20 20 69 66 28 20 72 63 3d 3d  b);.    if( rc==
2d60: 4c 53 4d 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20  LSM_OK ){.      
2d70: 72 63 20 3d 20 6c 73 6d 4c 6f 67 52 65 63 6f 76  rc = lsmLogRecov
2d80: 65 72 28 70 44 62 29 3b 0a 20 20 20 20 7d 0a 20  er(pDb);.    }. 
2d90: 20 20 20 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f     if( rc==LSM_O
2da0: 4b 20 29 7b 0a 20 20 20 20 20 20 53 68 6d 48 65  K ){.      ShmHe
2db0: 61 64 65 72 20 2a 70 53 68 6d 20 3d 20 70 44 62  ader *pShm = pDb
2dc0: 2d 3e 70 53 68 6d 68 64 72 3b 0a 20 20 20 20 20  ->pShmhdr;.     
2dd0: 20 70 53 68 6d 2d 3e 61 52 65 61 64 65 72 5b 30   pShm->aReader[0
2de0: 5d 2e 69 4c 73 6d 49 64 20 3d 20 6c 73 6d 43 68  ].iLsmId = lsmCh
2df0: 65 63 6b 70 6f 69 6e 74 49 64 28 70 53 68 6d 2d  eckpointId(pShm-
2e00: 3e 61 53 6e 61 70 31 2c 20 30 29 3b 0a 20 20 20  >aSnap1, 0);.   
2e10: 20 20 20 70 53 68 6d 2d 3e 61 52 65 61 64 65 72     pShm->aReader
2e20: 5b 30 5d 2e 69 54 72 65 65 49 64 20 3d 20 70 44  [0].iTreeId = pD
2e30: 62 2d 3e 74 72 65 65 68 64 72 2e 69 55 73 65 64  b->treehdr.iUsed
2e40: 53 68 6d 69 64 3b 0a 20 20 20 20 7d 0a 20 20 7d  Shmid;.    }.  }
2e50: 65 6c 73 65 20 69 66 28 20 72 63 3d 3d 4c 53 4d  else if( rc==LSM
2e60: 5f 42 55 53 59 20 29 7b 0a 20 20 20 20 72 63 20  _BUSY ){.    rc 
2e70: 3d 20 4c 53 4d 5f 4f 4b 3b 0a 20 20 7d 0a 0a 20  = LSM_OK;.  }.. 
2e80: 20 2f 2a 20 54 61 6b 65 20 61 20 73 68 61 72 65   /* Take a share
2e90: 64 20 6c 6f 63 6b 20 6f 6e 20 44 4d 53 32 2e 20  d lock on DMS2. 
2ea0: 49 6e 20 6d 75 6c 74 69 2d 70 72 6f 63 65 73 73  In multi-process
2eb0: 20 6d 6f 64 65 20 74 68 69 73 20 6c 6f 63 6b 20   mode this lock 
2ec0: 22 63 61 6e 6e 6f 74 22 20 0a 20 20 2a 2a 20 66  "cannot" .  ** f
2ed0: 61 69 6c 2c 20 61 73 20 63 6f 6e 6e 65 63 74 69  ail, as connecti
2ee0: 6f 6e 73 20 6d 61 79 20 6f 6e 6c 79 20 68 6f 6c  ons may only hol
2ef0: 64 20 61 6e 20 65 78 63 6c 75 73 69 76 65 20 6c  d an exclusive l
2f00: 6f 63 6b 20 6f 6e 20 44 4d 53 32 20 69 66 20 74  ock on DMS2 if t
2f10: 68 65 79 20 0a 20 20 2a 2a 20 66 69 72 73 74 20  hey .  ** first 
2f20: 68 6f 6c 64 20 61 6e 20 65 78 63 6c 75 73 69 76  hold an exclusiv
2f30: 65 20 6c 6f 63 6b 20 6f 6e 20 44 4d 53 31 2e 20  e lock on DMS1. 
2f40: 41 6e 64 20 74 68 69 73 20 63 6f 6e 6e 65 63 74  And this connect
2f50: 69 6f 6e 20 69 73 20 63 75 72 72 65 6e 74 6c 79  ion is currently
2f60: 20 0a 20 20 2a 2a 20 68 6f 6c 64 69 6e 67 20 74   .  ** holding t
2f70: 68 65 20 65 78 63 6c 75 73 69 76 65 20 6c 6f 63  he exclusive loc
2f80: 6b 20 6f 6e 20 44 53 4d 31 2e 20 0a 20 20 2a 2a  k on DSM1. .  **
2f90: 0a 20 20 2a 2a 20 48 6f 77 65 76 65 72 2c 20 69  .  ** However, i
2fa0: 66 20 73 6f 6d 65 20 6f 74 68 65 72 20 63 6f 6e  f some other con
2fb0: 6e 65 63 74 69 6f 6e 20 68 61 73 20 74 68 65 20  nection has the 
2fc0: 64 61 74 61 62 61 73 65 20 6f 70 65 6e 20 69 6e  database open in
2fd0: 20 73 69 6e 67 6c 65 2d 70 72 6f 63 65 73 73 0a   single-process.
2fe0: 20 20 2a 2a 20 6d 6f 64 65 2c 20 74 68 69 73 20    ** mode, this 
2ff0: 6f 70 65 72 61 74 69 6f 6e 20 77 69 6c 6c 20 66  operation will f
3000: 61 69 6c 2e 20 49 6e 20 74 68 69 73 20 63 61 73  ail. In this cas
3010: 65 2c 20 72 65 74 75 72 6e 20 74 68 65 20 65 72  e, return the er
3020: 72 6f 72 20 74 6f 20 74 68 65 0a 20 20 2a 2a 20  ror to the.  ** 
3030: 63 61 6c 6c 65 72 20 2d 20 74 68 65 20 61 74 74  caller - the att
3040: 65 6d 70 74 20 74 6f 20 63 6f 6e 6e 65 63 74 20  empt to connect 
3050: 74 6f 20 74 68 65 20 64 62 20 68 61 73 20 66 61  to the db has fa
3060: 69 6c 65 64 2e 0a 20 20 2a 2f 0a 20 20 69 66 28  iled..  */.  if(
3070: 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 29 7b 0a 20   rc==LSM_OK ){. 
3080: 20 20 20 72 63 20 3d 20 6c 73 6d 53 68 6d 4c 6f     rc = lsmShmLo
3090: 63 6b 28 70 44 62 2c 20 4c 53 4d 5f 4c 4f 43 4b  ck(pDb, LSM_LOCK
30a0: 5f 44 4d 53 32 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f  _DMS2, LSM_LOCK_
30b0: 53 48 41 52 45 44 2c 20 30 29 3b 0a 20 20 7d 0a  SHARED, 0);.  }.
30c0: 0a 20 20 2f 2a 20 49 66 20 61 6e 79 74 68 69 6e  .  /* If anythin
30d0: 67 20 77 65 6e 74 20 77 72 6f 6e 67 2c 20 75 6e  g went wrong, un
30e0: 6c 6f 63 6b 20 44 4d 53 32 2e 20 4f 74 68 65 72  lock DMS2. Other
30f0: 77 69 73 65 2c 20 74 72 79 20 74 6f 20 74 61 6b  wise, try to tak
3100: 65 20 61 6e 20 65 78 63 6c 75 73 69 76 65 0a 20  e an exclusive. 
3110: 20 2a 2a 20 6c 6f 63 6b 20 6f 6e 20 6f 6e 65 20   ** lock on one 
3120: 6f 66 20 74 68 65 20 4c 53 4d 5f 4c 4f 43 4b 5f  of the LSM_LOCK_
3130: 52 57 43 4c 49 45 4e 54 28 29 20 6c 6f 63 6b 73  RWCLIENT() locks
3140: 2e 20 55 6e 6c 6f 63 6b 20 44 4d 53 31 20 69 6e  . Unlock DMS1 in
3150: 20 61 6e 79 20 63 61 73 65 2e 20 2a 2f 0a 20 20   any case. */.  
3160: 69 66 28 20 72 63 21 3d 4c 53 4d 5f 4f 4b 20 29  if( rc!=LSM_OK )
3170: 7b 0a 20 20 20 20 70 44 62 2d 3e 70 53 68 6d 68  {.    pDb->pShmh
3180: 64 72 20 3d 20 30 3b 0a 20 20 7d 65 6c 73 65 7b  dr = 0;.  }else{
3190: 0a 20 20 20 20 69 6e 74 20 69 3b 0a 20 20 20 20  .    int i;.    
31a0: 66 6f 72 28 69 3d 30 3b 20 69 3c 4c 53 4d 5f 4c  for(i=0; i<LSM_L
31b0: 4f 43 4b 5f 4e 52 57 43 4c 49 45 4e 54 3b 20 69  OCK_NRWCLIENT; i
31c0: 2b 2b 29 7b 0a 20 20 20 20 20 20 69 6e 74 20 72  ++){.      int r
31d0: 63 32 20 3d 20 6c 73 6d 53 68 6d 4c 6f 63 6b 28  c2 = lsmShmLock(
31e0: 70 44 62 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 52 57  pDb, LSM_LOCK_RW
31f0: 43 4c 49 45 4e 54 28 69 29 2c 20 4c 53 4d 5f 4c  CLIENT(i), LSM_L
3200: 4f 43 4b 5f 45 58 43 4c 2c 20 30 29 3b 0a 20 20  OCK_EXCL, 0);.  
3210: 20 20 20 20 69 66 28 20 72 63 32 3d 3d 4c 53 4d      if( rc2==LSM
3220: 5f 4f 4b 20 29 20 70 44 62 2d 3e 69 52 77 63 6c  _OK ) pDb->iRwcl
3230: 69 65 6e 74 20 3d 20 69 3b 0a 20 20 20 20 20 20  ient = i;.      
3240: 69 66 28 20 72 63 32 21 3d 4c 53 4d 5f 42 55 53  if( rc2!=LSM_BUS
3250: 59 20 29 7b 0a 20 20 20 20 20 20 20 20 72 63 20  Y ){.        rc 
3260: 3d 20 72 63 32 3b 0a 20 20 20 20 20 20 20 20 62  = rc2;.        b
3270: 72 65 61 6b 3b 0a 20 20 20 20 20 20 7d 0a 20 20  reak;.      }.  
3280: 20 20 7d 0a 20 20 7d 0a 20 20 6c 73 6d 53 68 6d    }.  }.  lsmShm
3290: 4c 6f 63 6b 28 70 44 62 2c 20 4c 53 4d 5f 4c 4f  Lock(pDb, LSM_LO
32a0: 43 4b 5f 44 4d 53 31 2c 20 4c 53 4d 5f 4c 4f 43  CK_DMS1, LSM_LOC
32b0: 4b 5f 55 4e 4c 4f 43 4b 2c 20 30 29 3b 0a 0a 20  K_UNLOCK, 0);.. 
32c0: 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 73   return rc;.}..s
32d0: 74 61 74 69 63 20 69 6e 74 20 64 62 4f 70 65 6e  tatic int dbOpen
32e0: 53 68 61 72 65 64 46 64 28 6c 73 6d 5f 65 6e 76  SharedFd(lsm_env
32f0: 20 2a 70 45 6e 76 2c 20 44 61 74 61 62 61 73 65   *pEnv, Database
3300: 20 2a 70 2c 20 69 6e 74 20 62 52 6f 4f 6b 29 7b   *p, int bRoOk){
3310: 0a 20 20 69 6e 74 20 72 63 3b 0a 0a 20 20 72 63  .  int rc;..  rc
3320: 20 3d 20 6c 73 6d 45 6e 76 4f 70 65 6e 28 70 45   = lsmEnvOpen(pE
3330: 6e 76 2c 20 70 2d 3e 7a 4e 61 6d 65 2c 20 30 2c  nv, p->zName, 0,
3340: 20 26 70 2d 3e 70 46 69 6c 65 29 3b 0a 20 20 69   &p->pFile);.  i
3350: 66 28 20 72 63 3d 3d 4c 53 4d 5f 49 4f 45 52 52  f( rc==LSM_IOERR
3360: 20 26 26 20 62 52 6f 4f 6b 20 29 7b 0a 20 20 20   && bRoOk ){.   
3370: 20 72 63 20 3d 20 6c 73 6d 45 6e 76 4f 70 65 6e   rc = lsmEnvOpen
3380: 28 70 45 6e 76 2c 20 70 2d 3e 7a 4e 61 6d 65 2c  (pEnv, p->zName,
3390: 20 4c 53 4d 5f 4f 50 45 4e 5f 52 45 41 44 4f 4e   LSM_OPEN_READON
33a0: 4c 59 2c 20 26 70 2d 3e 70 46 69 6c 65 29 3b 0a  LY, &p->pFile);.
33b0: 20 20 20 20 70 2d 3e 62 52 65 61 64 6f 6e 6c 79      p->bReadonly
33c0: 20 3d 20 31 3b 0a 20 20 7d 0a 0a 20 20 72 65 74   = 1;.  }..  ret
33d0: 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a  urn rc;.}../*.**
33e0: 20 52 65 74 75 72 6e 20 61 20 72 65 66 65 72 65   Return a refere
33f0: 6e 63 65 20 74 6f 20 74 68 65 20 73 68 61 72 65  nce to the share
3400: 64 20 44 61 74 61 62 61 73 65 20 68 61 6e 64 6c  d Database handl
3410: 65 20 66 6f 72 20 74 68 65 20 64 61 74 61 62 61  e for the databa
3420: 73 65 20 0a 2a 2a 20 69 64 65 6e 74 69 66 69 65  se .** identifie
3430: 64 20 62 79 20 63 61 6e 6f 6e 69 63 61 6c 20 70  d by canonical p
3440: 61 74 68 20 7a 4e 61 6d 65 2e 20 49 66 20 74 68  ath zName. If th
3450: 69 73 20 69 73 20 74 68 65 20 66 69 72 73 74 20  is is the first 
3460: 63 6f 6e 6e 65 63 74 69 6f 6e 20 74 6f 0a 2a 2a  connection to.**
3470: 20 74 68 65 20 6e 61 6d 65 64 20 64 61 74 61 62   the named datab
3480: 61 73 65 2c 20 61 20 6e 65 77 20 44 61 74 61 62  ase, a new Datab
3490: 61 73 65 20 6f 62 6a 65 63 74 20 69 73 20 61 6c  ase object is al
34a0: 6c 6f 63 61 74 65 64 2e 20 4f 74 68 65 72 77 69  located. Otherwi
34b0: 73 65 2c 20 61 0a 2a 2a 20 70 6f 69 6e 74 65 72  se, a.** pointer
34c0: 20 74 6f 20 61 6e 20 65 78 69 73 74 69 6e 67 20   to an existing 
34d0: 6f 62 6a 65 63 74 20 69 73 20 72 65 74 75 72 6e  object is return
34e0: 65 64 2e 0a 2a 2a 0a 2a 2a 20 49 66 20 73 75 63  ed..**.** If suc
34f0: 63 65 73 73 66 75 6c 2c 20 2a 70 70 44 61 74 61  cessful, *ppData
3500: 62 61 73 65 20 69 73 20 73 65 74 20 74 6f 20 70  base is set to p
3510: 6f 69 6e 74 20 74 6f 20 74 68 65 20 73 68 61 72  oint to the shar
3520: 65 64 20 44 61 74 61 62 61 73 65 20 0a 2a 2a 20  ed Database .** 
3530: 73 74 72 75 63 74 75 72 65 20 61 6e 64 20 4c 53  structure and LS
3540: 4d 5f 4f 4b 20 72 65 74 75 72 6e 65 64 2e 20 4f  M_OK returned. O
3550: 74 68 65 72 77 69 73 65 2c 20 2a 70 70 44 61 74  therwise, *ppDat
3560: 61 62 61 73 65 20 69 73 20 73 65 74 20 74 6f 20  abase is set to 
3570: 4e 55 4c 4c 0a 2a 2a 20 61 6e 64 20 61 6e 64 20  NULL.** and and 
3580: 4c 53 4d 20 65 72 72 6f 72 20 63 6f 64 65 20 72  LSM error code r
3590: 65 74 75 72 6e 65 64 2e 0a 2a 2a 0a 2a 2a 20 45  eturned..**.** E
35a0: 61 63 68 20 73 75 63 63 65 73 73 66 75 6c 20 63  ach successful c
35b0: 61 6c 6c 20 74 6f 20 74 68 69 73 20 66 75 6e 63  all to this func
35c0: 74 69 6f 6e 20 73 68 6f 75 6c 64 20 62 65 20 28  tion should be (
35d0: 65 76 65 6e 74 75 61 6c 6c 79 29 20 6d 61 74 63  eventually) matc
35e0: 68 65 64 0a 2a 2a 20 62 79 20 61 20 63 61 6c 6c  hed.** by a call
35f0: 20 74 6f 20 6c 73 6d 44 62 44 61 74 61 62 61 73   to lsmDbDatabas
3600: 65 52 65 6c 65 61 73 65 28 29 2e 0a 2a 2f 0a 69  eRelease()..*/.i
3610: 6e 74 20 6c 73 6d 44 62 44 61 74 61 62 61 73 65  nt lsmDbDatabase
3620: 43 6f 6e 6e 65 63 74 28 0a 20 20 6c 73 6d 5f 64  Connect(.  lsm_d
3630: 62 20 2a 70 44 62 2c 20 20 20 20 20 20 20 20 20  b *pDb,         
3640: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 44 61             /* Da
3650: 74 61 62 61 73 65 20 68 61 6e 64 6c 65 20 2a 2f  tabase handle */
3660: 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a  .  const char *z
3670: 4e 61 6d 65 20 20 20 20 20 20 20 20 20 20 20 20  Name            
3680: 20 20 20 2f 2a 20 46 75 6c 6c 2d 70 61 74 68 20     /* Full-path 
3690: 74 6f 20 64 62 20 66 69 6c 65 20 2a 2f 0a 29 7b  to db file */.){
36a0: 0a 20 20 6c 73 6d 5f 65 6e 76 20 2a 70 45 6e 76  .  lsm_env *pEnv
36b0: 20 3d 20 70 44 62 2d 3e 70 45 6e 76 3b 0a 20 20   = pDb->pEnv;.  
36c0: 69 6e 74 20 72 63 3b 20 20 20 20 20 20 20 20 20  int rc;         
36d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
36e0: 2f 2a 20 52 65 74 75 72 6e 20 63 6f 64 65 20 2a  /* Return code *
36f0: 2f 0a 20 20 44 61 74 61 62 61 73 65 20 2a 70 20  /.  Database *p 
3700: 3d 20 30 3b 20 20 20 20 20 20 20 20 20 20 20 20  = 0;            
3710: 20 20 20 20 2f 2a 20 50 6f 69 6e 74 65 72 20 72      /* Pointer r
3720: 65 74 75 72 6e 65 64 20 76 69 61 20 2a 70 70 44  eturned via *ppD
3730: 61 74 61 62 61 73 65 20 2a 2f 0a 20 20 69 6e 74  atabase */.  int
3740: 20 6e 4e 61 6d 65 20 3d 20 6c 73 6d 53 74 72 6c   nName = lsmStrl
3750: 65 6e 28 7a 4e 61 6d 65 29 3b 0a 0a 20 20 61 73  en(zName);..  as
3760: 73 65 72 74 28 20 70 44 62 2d 3e 70 44 61 74 61  sert( pDb->pData
3770: 62 61 73 65 3d 3d 30 20 29 3b 0a 20 20 72 63 20  base==0 );.  rc 
3780: 3d 20 65 6e 74 65 72 47 6c 6f 62 61 6c 4d 75 74  = enterGlobalMut
3790: 65 78 28 70 45 6e 76 29 3b 0a 20 20 69 66 28 20  ex(pEnv);.  if( 
37a0: 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 29 7b 0a 0a 20  rc==LSM_OK ){.. 
37b0: 20 20 20 2f 2a 20 53 65 61 72 63 68 20 74 68 65     /* Search the
37c0: 20 67 6c 6f 62 61 6c 20 6c 69 73 74 20 66 6f 72   global list for
37d0: 20 61 6e 20 65 78 69 73 74 69 6e 67 20 6f 62 6a   an existing obj
37e0: 65 63 74 2e 20 54 4f 44 4f 3a 20 4e 65 65 64 20  ect. TODO: Need 
37f0: 73 6f 6d 65 74 68 69 6e 67 0a 20 20 20 20 2a 2a  something.    **
3800: 20 62 65 74 74 65 72 20 74 68 61 6e 20 74 68 65   better than the
3810: 20 6d 65 6d 63 6d 70 28 29 20 62 65 6c 6f 77 20   memcmp() below 
3820: 74 6f 20 66 69 67 75 72 65 20 6f 75 74 20 69 66  to figure out if
3830: 20 61 20 67 69 76 65 6e 20 44 61 74 61 62 61 73   a given Databas
3840: 65 0a 20 20 20 20 2a 2a 20 6f 62 6a 65 63 74 20  e.    ** object 
3850: 72 65 70 72 65 73 65 6e 74 73 20 74 68 65 20 72  represents the r
3860: 65 71 75 65 73 74 65 64 20 66 69 6c 65 2e 20 20  equested file.  
3870: 2a 2f 0a 20 20 20 20 66 6f 72 28 70 3d 67 53 68  */.    for(p=gSh
3880: 61 72 65 64 2e 70 44 61 74 61 62 61 73 65 3b 20  ared.pDatabase; 
3890: 70 3b 20 70 3d 70 2d 3e 70 44 62 4e 65 78 74 29  p; p=p->pDbNext)
38a0: 7b 0a 20 20 20 20 20 20 69 66 28 20 6e 4e 61 6d  {.      if( nNam
38b0: 65 3d 3d 70 2d 3e 6e 4e 61 6d 65 20 26 26 20 30  e==p->nName && 0
38c0: 3d 3d 6d 65 6d 63 6d 70 28 7a 4e 61 6d 65 2c 20  ==memcmp(zName, 
38d0: 70 2d 3e 7a 4e 61 6d 65 2c 20 6e 4e 61 6d 65 29  p->zName, nName)
38e0: 20 29 20 62 72 65 61 6b 3b 0a 20 20 20 20 7d 0a   ) break;.    }.
38f0: 0a 20 20 20 20 2f 2a 20 49 66 20 6e 6f 20 73 75  .    /* If no su
3900: 69 74 61 62 6c 65 20 44 61 74 61 62 61 73 65 20  itable Database 
3910: 6f 62 6a 65 63 74 20 77 61 73 20 66 6f 75 6e 64  object was found
3920: 2c 20 61 6c 6c 6f 63 61 74 65 20 61 20 6e 65 77  , allocate a new
3930: 20 6f 6e 65 2e 20 2a 2f 0a 20 20 20 20 69 66 28   one. */.    if(
3940: 20 70 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 70   p==0 ){.      p
3950: 20 3d 20 28 44 61 74 61 62 61 73 65 20 2a 29 6c   = (Database *)l
3960: 73 6d 4d 61 6c 6c 6f 63 5a 65 72 6f 52 63 28 70  smMallocZeroRc(p
3970: 45 6e 76 2c 20 73 69 7a 65 6f 66 28 44 61 74 61  Env, sizeof(Data
3980: 62 61 73 65 29 2b 6e 4e 61 6d 65 2b 31 2c 20 26  base)+nName+1, &
3990: 72 63 29 3b 0a 0a 20 20 20 20 20 20 2f 2a 20 49  rc);..      /* I
39a0: 66 20 74 68 65 20 61 6c 6c 6f 63 61 74 69 6f 6e  f the allocation
39b0: 20 77 61 73 20 73 75 63 63 65 73 73 66 75 6c 2c   was successful,
39c0: 20 66 69 6c 6c 20 69 6e 20 6f 74 68 65 72 20 66   fill in other f
39d0: 69 65 6c 64 73 20 61 6e 64 0a 20 20 20 20 20 20  ields and.      
39e0: 2a 2a 20 61 6c 6c 6f 63 61 74 65 20 74 68 65 20  ** allocate the 
39f0: 63 6c 69 65 6e 74 20 6d 75 74 65 78 2e 20 2a 2f  client mutex. */
3a00: 20 0a 20 20 20 20 20 20 69 66 28 20 72 63 3d 3d   .      if( rc==
3a10: 4c 53 4d 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20  LSM_OK ){.      
3a20: 20 20 70 2d 3e 62 4d 75 6c 74 69 50 72 6f 63 20    p->bMultiProc 
3a30: 3d 20 70 44 62 2d 3e 62 4d 75 6c 74 69 50 72 6f  = pDb->bMultiPro
3a40: 63 3b 0a 20 20 20 20 20 20 20 20 70 2d 3e 7a 4e  c;.        p->zN
3a50: 61 6d 65 20 3d 20 28 63 68 61 72 20 2a 29 26 70  ame = (char *)&p
3a60: 5b 31 5d 3b 0a 20 20 20 20 20 20 20 20 70 2d 3e  [1];.        p->
3a70: 6e 4e 61 6d 65 20 3d 20 6e 4e 61 6d 65 3b 0a 20  nName = nName;. 
3a80: 20 20 20 20 20 20 20 6d 65 6d 63 70 79 28 28 76         memcpy((v
3a90: 6f 69 64 20 2a 29 70 2d 3e 7a 4e 61 6d 65 2c 20  oid *)p->zName, 
3aa0: 7a 4e 61 6d 65 2c 20 6e 4e 61 6d 65 2b 31 29 3b  zName, nName+1);
3ab0: 0a 20 20 20 20 20 20 20 20 72 63 20 3d 20 6c 73  .        rc = ls
3ac0: 6d 4d 75 74 65 78 4e 65 77 28 70 45 6e 76 2c 20  mMutexNew(pEnv, 
3ad0: 26 70 2d 3e 70 43 6c 69 65 6e 74 4d 75 74 65 78  &p->pClientMutex
3ae0: 29 3b 0a 20 20 20 20 20 20 7d 0a 0a 20 20 20 20  );.      }..    
3af0: 20 20 2f 2a 20 49 66 20 6e 6f 74 68 69 6e 67 20    /* If nothing 
3b00: 68 61 73 20 67 6f 6e 65 20 77 72 6f 6e 67 20 73  has gone wrong s
3b10: 6f 20 66 61 72 2c 20 6f 70 65 6e 20 74 68 65 20  o far, open the 
3b20: 73 68 61 72 65 64 20 66 64 2e 20 41 6e 64 20 69  shared fd. And i
3b30: 66 20 74 68 61 74 0a 20 20 20 20 20 20 2a 2a 20  f that.      ** 
3b40: 73 75 63 63 65 65 64 73 20 61 6e 64 20 74 68 69  succeeds and thi
3b50: 73 20 63 6f 6e 6e 65 63 74 69 6f 6e 20 72 65 71  s connection req
3b60: 75 65 73 74 65 64 20 73 69 6e 67 6c 65 2d 70 72  uested single-pr
3b70: 6f 63 65 73 73 20 6d 6f 64 65 2c 20 0a 20 20 20  ocess mode, .   
3b80: 20 20 20 2a 2a 20 61 74 74 65 6d 70 74 20 74 6f     ** attempt to
3b90: 20 74 61 6b 65 20 74 68 65 20 65 78 63 6c 75 73   take the exclus
3ba0: 69 76 65 20 6c 6f 63 6b 20 6f 6e 20 44 4d 53 32  ive lock on DMS2
3bb0: 2e 20 20 2a 2f 0a 20 20 20 20 20 20 69 66 28 20  .  */.      if( 
3bc0: 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 29 7b 0a 20 20  rc==LSM_OK ){.  
3bd0: 20 20 20 20 20 20 69 6e 74 20 62 52 65 61 64 6f        int bReado
3be0: 6e 6c 79 20 3d 20 28 70 44 62 2d 3e 62 52 65 61  nly = (pDb->bRea
3bf0: 64 6f 6e 6c 79 20 26 26 20 70 44 62 2d 3e 62 4d  donly && pDb->bM
3c00: 75 6c 74 69 50 72 6f 63 29 3b 0a 20 20 20 20 20  ultiProc);.     
3c10: 20 20 20 72 63 20 3d 20 64 62 4f 70 65 6e 53 68     rc = dbOpenSh
3c20: 61 72 65 64 46 64 28 70 44 62 2d 3e 70 45 6e 76  aredFd(pDb->pEnv
3c30: 2c 20 70 2c 20 62 52 65 61 64 6f 6e 6c 79 29 3b  , p, bReadonly);
3c40: 0a 20 20 20 20 20 20 7d 0a 0a 20 20 20 20 20 20  .      }..      
3c50: 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 26  if( rc==LSM_OK &
3c60: 26 20 70 2d 3e 62 4d 75 6c 74 69 50 72 6f 63 3d  & p->bMultiProc=
3c70: 3d 30 20 29 7b 0a 20 20 20 20 20 20 20 20 2f 2a  =0 ){.        /*
3c80: 20 48 6f 6c 64 20 61 6e 20 65 78 63 6c 75 73 69   Hold an exclusi
3c90: 76 65 20 6c 6f 63 6b 20 44 4d 53 31 20 77 68 69  ve lock DMS1 whi
3ca0: 6c 65 20 67 72 61 62 62 69 6e 67 20 44 4d 53 32  le grabbing DMS2
3cb0: 2e 20 54 68 69 73 20 65 6e 73 75 72 65 73 0a 20  . This ensures. 
3cc0: 20 20 20 20 20 20 20 2a 2a 20 74 68 61 74 20 61         ** that a
3cd0: 6e 79 20 6f 6e 67 6f 69 6e 67 20 63 61 6c 6c 20  ny ongoing call 
3ce0: 74 6f 20 64 6f 44 62 44 69 73 63 6f 6e 6e 65 63  to doDbDisconnec
3cf0: 74 28 29 20 28 65 76 65 6e 20 6f 6e 65 20 69 6e  t() (even one in
3d00: 20 61 6e 6f 74 68 65 72 0a 20 20 20 20 20 20 20   another.       
3d10: 20 2a 2a 20 70 72 6f 63 65 73 73 29 20 69 73 20   ** process) is 
3d20: 66 69 6e 69 73 68 65 64 20 62 65 66 6f 72 65 20  finished before 
3d30: 70 72 6f 63 65 65 64 69 6e 67 2e 20 20 2a 2f 0a  proceeding.  */.
3d40: 20 20 20 20 20 20 20 20 61 73 73 65 72 74 28 20          assert( 
3d50: 70 2d 3e 62 52 65 61 64 6f 6e 6c 79 3d 3d 30 20  p->bReadonly==0 
3d60: 29 3b 0a 20 20 20 20 20 20 20 20 72 63 20 3d 20  );.        rc = 
3d70: 6c 73 6d 45 6e 76 4c 6f 63 6b 28 70 44 62 2d 3e  lsmEnvLock(pDb->
3d80: 70 45 6e 76 2c 20 70 2d 3e 70 46 69 6c 65 2c 20  pEnv, p->pFile, 
3d90: 4c 53 4d 5f 4c 4f 43 4b 5f 44 4d 53 31 2c 20 4c  LSM_LOCK_DMS1, L
3da0: 53 4d 5f 4c 4f 43 4b 5f 45 58 43 4c 29 3b 0a 20  SM_LOCK_EXCL);. 
3db0: 20 20 20 20 20 20 20 69 66 28 20 72 63 3d 3d 4c         if( rc==L
3dc0: 53 4d 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 20  SM_OK ){.       
3dd0: 20 20 20 72 63 20 3d 20 6c 73 6d 45 6e 76 4c 6f     rc = lsmEnvLo
3de0: 63 6b 28 70 44 62 2d 3e 70 45 6e 76 2c 20 70 2d  ck(pDb->pEnv, p-
3df0: 3e 70 46 69 6c 65 2c 20 4c 53 4d 5f 4c 4f 43 4b  >pFile, LSM_LOCK
3e00: 5f 44 4d 53 32 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f  _DMS2, LSM_LOCK_
3e10: 45 58 43 4c 29 3b 0a 20 20 20 20 20 20 20 20 20  EXCL);.         
3e20: 20 6c 73 6d 45 6e 76 4c 6f 63 6b 28 70 44 62 2d   lsmEnvLock(pDb-
3e30: 3e 70 45 6e 76 2c 20 70 2d 3e 70 46 69 6c 65 2c  >pEnv, p->pFile,
3e40: 20 4c 53 4d 5f 4c 4f 43 4b 5f 44 4d 53 31 2c 20   LSM_LOCK_DMS1, 
3e50: 4c 53 4d 5f 4c 4f 43 4b 5f 55 4e 4c 4f 43 4b 29  LSM_LOCK_UNLOCK)
3e60: 3b 0a 20 20 20 20 20 20 20 20 7d 0a 20 20 20 20  ;.        }.    
3e70: 20 20 7d 0a 0a 20 20 20 20 20 20 69 66 28 20 72    }..      if( r
3e80: 63 3d 3d 4c 53 4d 5f 4f 4b 20 29 7b 0a 20 20 20  c==LSM_OK ){.   
3e90: 20 20 20 20 20 70 2d 3e 70 44 62 4e 65 78 74 20       p->pDbNext 
3ea0: 3d 20 67 53 68 61 72 65 64 2e 70 44 61 74 61 62  = gShared.pDatab
3eb0: 61 73 65 3b 0a 20 20 20 20 20 20 20 20 67 53 68  ase;.        gSh
3ec0: 61 72 65 64 2e 70 44 61 74 61 62 61 73 65 20 3d  ared.pDatabase =
3ed0: 20 70 3b 0a 20 20 20 20 20 20 7d 65 6c 73 65 7b   p;.      }else{
3ee0: 0a 20 20 20 20 20 20 20 20 66 72 65 65 44 61 74  .        freeDat
3ef0: 61 62 61 73 65 28 70 45 6e 76 2c 20 70 29 3b 0a  abase(pEnv, p);.
3f00: 20 20 20 20 20 20 20 20 70 20 3d 20 30 3b 0a 20          p = 0;. 
3f10: 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a 0a 20 20       }.    }..  
3f20: 20 20 69 66 28 20 70 20 29 7b 0a 20 20 20 20 20    if( p ){.     
3f30: 20 70 2d 3e 6e 44 62 52 65 66 2b 2b 3b 0a 20 20   p->nDbRef++;.  
3f40: 20 20 7d 0a 20 20 20 20 6c 65 61 76 65 47 6c 6f    }.    leaveGlo
3f50: 62 61 6c 4d 75 74 65 78 28 70 45 6e 76 29 3b 0a  balMutex(pEnv);.
3f60: 0a 20 20 20 20 69 66 28 20 70 20 29 7b 0a 20 20  .    if( p ){.  
3f70: 20 20 20 20 6c 73 6d 4d 75 74 65 78 45 6e 74 65      lsmMutexEnte
3f80: 72 28 70 44 62 2d 3e 70 45 6e 76 2c 20 70 2d 3e  r(pDb->pEnv, p->
3f90: 70 43 6c 69 65 6e 74 4d 75 74 65 78 29 3b 0a 20  pClientMutex);. 
3fa0: 20 20 20 20 20 70 44 62 2d 3e 70 4e 65 78 74 20       pDb->pNext 
3fb0: 3d 20 70 2d 3e 70 43 6f 6e 6e 3b 0a 20 20 20 20  = p->pConn;.    
3fc0: 20 20 70 2d 3e 70 43 6f 6e 6e 20 3d 20 70 44 62    p->pConn = pDb
3fd0: 3b 0a 20 20 20 20 20 20 6c 73 6d 4d 75 74 65 78  ;.      lsmMutex
3fe0: 4c 65 61 76 65 28 70 44 62 2d 3e 70 45 6e 76 2c  Leave(pDb->pEnv,
3ff0: 20 70 2d 3e 70 43 6c 69 65 6e 74 4d 75 74 65 78   p->pClientMutex
4000: 29 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 0a 20 20  );.    }.  }..  
4010: 70 44 62 2d 3e 70 44 61 74 61 62 61 73 65 20 3d  pDb->pDatabase =
4020: 20 70 3b 0a 20 20 69 66 28 20 72 63 3d 3d 4c 53   p;.  if( rc==LS
4030: 4d 5f 4f 4b 20 29 7b 0a 20 20 20 20 61 73 73 65  M_OK ){.    asse
4040: 72 74 28 20 70 20 29 3b 0a 20 20 20 20 72 63 20  rt( p );.    rc 
4050: 3d 20 6c 73 6d 46 73 4f 70 65 6e 28 70 44 62 2c  = lsmFsOpen(pDb,
4060: 20 7a 4e 61 6d 65 2c 20 70 2d 3e 62 52 65 61 64   zName, p->bRead
4070: 6f 6e 6c 79 29 3b 0a 20 20 7d 0a 0a 20 20 2f 2a  only);.  }..  /*
4080: 20 49 66 20 74 68 65 20 64 62 20 68 61 6e 64 6c   If the db handl
4090: 65 20 69 73 20 72 65 61 64 2d 77 72 69 74 65 2c  e is read-write,
40a0: 20 74 68 65 6e 20 63 6f 6e 6e 65 63 74 20 74 6f   then connect to
40b0: 20 74 68 65 20 73 79 73 74 65 6d 20 6e 6f 77 2e   the system now.
40c0: 20 52 75 6e 0a 20 20 2a 2a 20 72 65 63 6f 76 65   Run.  ** recove
40d0: 72 79 20 61 73 20 6e 65 63 65 73 73 61 72 79 2e  ry as necessary.
40e0: 20 4f 72 2c 20 69 66 20 74 68 69 73 20 69 73 20   Or, if this is 
40f0: 61 20 72 65 61 64 2d 6f 6e 6c 79 20 64 61 74 61  a read-only data
4100: 62 61 73 65 20 68 61 6e 64 6c 65 2c 0a 20 20 2a  base handle,.  *
4110: 2a 20 64 65 66 65 72 20 61 74 74 65 6d 70 74 69  * defer attempti
4120: 6e 67 20 74 6f 20 63 6f 6e 6e 65 63 74 20 74 6f  ng to connect to
4130: 20 74 68 65 20 73 79 73 74 65 6d 20 75 6e 74 69   the system unti
4140: 6c 20 61 20 72 65 61 64 2d 74 72 61 6e 73 61 63  l a read-transac
4150: 74 69 6f 6e 0a 20 20 2a 2a 20 69 73 20 6f 70 65  tion.  ** is ope
4160: 6e 65 64 2e 20 20 2a 2f 0a 20 20 69 66 28 20 72  ned.  */.  if( r
4170: 63 3d 3d 4c 53 4d 5f 4f 4b 20 29 7b 0a 20 20 20  c==LSM_OK ){.   
4180: 20 72 63 20 3d 20 6c 73 6d 46 73 43 6f 6e 66 69   rc = lsmFsConfi
4190: 67 75 72 65 28 70 44 62 29 3b 0a 20 20 7d 0a 20  gure(pDb);.  }. 
41a0: 20 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20   if( rc==LSM_OK 
41b0: 26 26 20 70 44 62 2d 3e 62 52 65 61 64 6f 6e 6c  && pDb->bReadonl
41c0: 79 3d 3d 30 20 29 7b 0a 20 20 20 20 72 63 20 3d  y==0 ){.    rc =
41d0: 20 64 6f 44 62 43 6f 6e 6e 65 63 74 28 70 44 62   doDbConnect(pDb
41e0: 29 3b 0a 20 20 7d 0a 0a 20 20 72 65 74 75 72 6e  );.  }..  return
41f0: 20 72 63 3b 0a 7d 0a 0a 73 74 61 74 69 63 20 76   rc;.}..static v
4200: 6f 69 64 20 64 62 44 65 66 65 72 43 6c 6f 73 65  oid dbDeferClose
4210: 28 6c 73 6d 5f 64 62 20 2a 70 44 62 29 7b 0a 20  (lsm_db *pDb){. 
4220: 20 69 66 28 20 70 44 62 2d 3e 70 46 53 20 29 7b   if( pDb->pFS ){
4230: 0a 20 20 20 20 4c 73 6d 46 69 6c 65 20 2a 70 4c  .    LsmFile *pL
4240: 73 6d 46 69 6c 65 3b 0a 20 20 20 20 44 61 74 61  smFile;.    Data
4250: 62 61 73 65 20 2a 70 20 3d 20 70 44 62 2d 3e 70  base *p = pDb->p
4260: 44 61 74 61 62 61 73 65 3b 0a 20 20 20 20 70 4c  Database;.    pL
4270: 73 6d 46 69 6c 65 20 3d 20 6c 73 6d 46 73 44 65  smFile = lsmFsDe
4280: 66 65 72 43 6c 6f 73 65 28 70 44 62 2d 3e 70 46  ferClose(pDb->pF
4290: 53 29 3b 0a 20 20 20 20 70 4c 73 6d 46 69 6c 65  S);.    pLsmFile
42a0: 2d 3e 70 4e 65 78 74 20 3d 20 70 2d 3e 70 4c 73  ->pNext = p->pLs
42b0: 6d 46 69 6c 65 3b 0a 20 20 20 20 70 2d 3e 70 4c  mFile;.    p->pL
42c0: 73 6d 46 69 6c 65 20 3d 20 70 4c 73 6d 46 69 6c  smFile = pLsmFil
42d0: 65 3b 0a 20 20 7d 0a 7d 0a 0a 4c 73 6d 46 69 6c  e;.  }.}..LsmFil
42e0: 65 20 2a 6c 73 6d 44 62 52 65 63 79 63 6c 65 46  e *lsmDbRecycleF
42f0: 64 28 6c 73 6d 5f 64 62 20 2a 64 62 29 7b 0a 20  d(lsm_db *db){. 
4300: 20 4c 73 6d 46 69 6c 65 20 2a 70 52 65 74 3b 0a   LsmFile *pRet;.
4310: 20 20 44 61 74 61 62 61 73 65 20 2a 70 20 3d 20    Database *p = 
4320: 64 62 2d 3e 70 44 61 74 61 62 61 73 65 3b 0a 20  db->pDatabase;. 
4330: 20 6c 73 6d 4d 75 74 65 78 45 6e 74 65 72 28 64   lsmMutexEnter(d
4340: 62 2d 3e 70 45 6e 76 2c 20 70 2d 3e 70 43 6c 69  b->pEnv, p->pCli
4350: 65 6e 74 4d 75 74 65 78 29 3b 0a 20 20 69 66 28  entMutex);.  if(
4360: 20 28 70 52 65 74 20 3d 20 70 2d 3e 70 4c 73 6d   (pRet = p->pLsm
4370: 46 69 6c 65 29 21 3d 30 20 29 7b 0a 20 20 20 20  File)!=0 ){.    
4380: 70 2d 3e 70 4c 73 6d 46 69 6c 65 20 3d 20 70 52  p->pLsmFile = pR
4390: 65 74 2d 3e 70 4e 65 78 74 3b 0a 20 20 7d 0a 20  et->pNext;.  }. 
43a0: 20 6c 73 6d 4d 75 74 65 78 4c 65 61 76 65 28 64   lsmMutexLeave(d
43b0: 62 2d 3e 70 45 6e 76 2c 20 70 2d 3e 70 43 6c 69  b->pEnv, p->pCli
43c0: 65 6e 74 4d 75 74 65 78 29 3b 0a 20 20 72 65 74  entMutex);.  ret
43d0: 75 72 6e 20 70 52 65 74 3b 0a 7d 0a 0a 2f 2a 0a  urn pRet;.}../*.
43e0: 2a 2a 20 52 65 6c 65 61 73 65 20 61 20 72 65 66  ** Release a ref
43f0: 65 72 65 6e 63 65 20 74 6f 20 61 20 44 61 74 61  erence to a Data
4400: 62 61 73 65 20 6f 62 6a 65 63 74 20 6f 62 74 61  base object obta
4410: 69 6e 65 64 20 66 72 6f 6d 20 0a 2a 2a 20 6c 73  ined from .** ls
4420: 6d 44 62 44 61 74 61 62 61 73 65 43 6f 6e 6e 65  mDbDatabaseConne
4430: 63 74 28 29 2e 20 54 68 65 72 65 20 73 68 6f 75  ct(). There shou
4440: 6c 64 20 62 65 20 65 78 61 63 74 6c 79 20 6f 6e  ld be exactly on
4450: 65 20 63 61 6c 6c 20 74 6f 20 74 68 69 73 20 66  e call to this f
4460: 75 6e 63 74 69 6f 6e 20 0a 2a 2a 20 66 6f 72 20  unction .** for 
4470: 65 61 63 68 20 73 75 63 63 65 73 73 66 75 6c 20  each successful 
4480: 63 61 6c 6c 20 74 6f 20 46 69 6e 64 28 29 2e 0a  call to Find()..
4490: 2a 2f 0a 76 6f 69 64 20 6c 73 6d 44 62 44 61 74  */.void lsmDbDat
44a0: 61 62 61 73 65 52 65 6c 65 61 73 65 28 6c 73 6d  abaseRelease(lsm
44b0: 5f 64 62 20 2a 70 44 62 29 7b 0a 20 20 44 61 74  _db *pDb){.  Dat
44c0: 61 62 61 73 65 20 2a 70 20 3d 20 70 44 62 2d 3e  abase *p = pDb->
44d0: 70 44 61 74 61 62 61 73 65 3b 0a 20 20 69 66 28  pDatabase;.  if(
44e0: 20 70 20 29 7b 0a 20 20 20 20 6c 73 6d 5f 64 62   p ){.    lsm_db
44f0: 20 2a 2a 70 70 44 62 3b 0a 0a 20 20 20 20 69 66   **ppDb;..    if
4500: 28 20 70 44 62 2d 3e 70 53 68 6d 68 64 72 20 29  ( pDb->pShmhdr )
4510: 7b 0a 20 20 20 20 20 20 64 6f 44 62 44 69 73 63  {.      doDbDisc
4520: 6f 6e 6e 65 63 74 28 70 44 62 29 3b 0a 20 20 20  onnect(pDb);.   
4530: 20 7d 0a 0a 20 20 20 20 6c 73 6d 46 73 55 6e 6d   }..    lsmFsUnm
4540: 61 70 28 70 44 62 2d 3e 70 46 53 29 3b 0a 20 20  ap(pDb->pFS);.  
4550: 20 20 6c 73 6d 4d 75 74 65 78 45 6e 74 65 72 28    lsmMutexEnter(
4560: 70 44 62 2d 3e 70 45 6e 76 2c 20 70 2d 3e 70 43  pDb->pEnv, p->pC
4570: 6c 69 65 6e 74 4d 75 74 65 78 29 3b 0a 20 20 20  lientMutex);.   
4580: 20 66 6f 72 28 70 70 44 62 3d 26 70 2d 3e 70 43   for(ppDb=&p->pC
4590: 6f 6e 6e 3b 20 2a 70 70 44 62 21 3d 70 44 62 3b  onn; *ppDb!=pDb;
45a0: 20 70 70 44 62 3d 26 28 28 2a 70 70 44 62 29 2d   ppDb=&((*ppDb)-
45b0: 3e 70 4e 65 78 74 29 29 3b 0a 20 20 20 20 2a 70  >pNext));.    *p
45c0: 70 44 62 20 3d 20 70 44 62 2d 3e 70 4e 65 78 74  pDb = pDb->pNext
45d0: 3b 0a 20 20 20 20 64 62 44 65 66 65 72 43 6c 6f  ;.    dbDeferClo
45e0: 73 65 28 70 44 62 29 3b 0a 20 20 20 20 6c 73 6d  se(pDb);.    lsm
45f0: 4d 75 74 65 78 4c 65 61 76 65 28 70 44 62 2d 3e  MutexLeave(pDb->
4600: 70 45 6e 76 2c 20 70 2d 3e 70 43 6c 69 65 6e 74  pEnv, p->pClient
4610: 4d 75 74 65 78 29 3b 0a 0a 20 20 20 20 65 6e 74  Mutex);..    ent
4620: 65 72 47 6c 6f 62 61 6c 4d 75 74 65 78 28 70 44  erGlobalMutex(pD
4630: 62 2d 3e 70 45 6e 76 29 3b 0a 20 20 20 20 70 2d  b->pEnv);.    p-
4640: 3e 6e 44 62 52 65 66 2d 2d 3b 0a 20 20 20 20 69  >nDbRef--;.    i
4650: 66 28 20 70 2d 3e 6e 44 62 52 65 66 3d 3d 30 20  f( p->nDbRef==0 
4660: 29 7b 0a 20 20 20 20 20 20 4c 73 6d 46 69 6c 65  ){.      LsmFile
4670: 20 2a 70 49 74 65 72 3b 0a 20 20 20 20 20 20 4c   *pIter;.      L
4680: 73 6d 46 69 6c 65 20 2a 70 4e 65 78 74 3b 0a 20  smFile *pNext;. 
4690: 20 20 20 20 20 44 61 74 61 62 61 73 65 20 2a 2a       Database **
46a0: 70 70 3b 0a 0a 20 20 20 20 20 20 2f 2a 20 52 65  pp;..      /* Re
46b0: 6d 6f 76 65 20 74 68 65 20 44 61 74 61 62 61 73  move the Databas
46c0: 65 20 73 74 72 75 63 74 75 72 65 20 66 72 6f 6d  e structure from
46d0: 20 74 68 65 20 6c 69 6e 6b 65 64 20 6c 69 73 74   the linked list
46e0: 2e 20 2a 2f 0a 20 20 20 20 20 20 66 6f 72 28 70  . */.      for(p
46f0: 70 3d 26 67 53 68 61 72 65 64 2e 70 44 61 74 61  p=&gShared.pData
4700: 62 61 73 65 3b 20 2a 70 70 21 3d 70 3b 20 70 70  base; *pp!=p; pp
4710: 3d 26 28 28 2a 70 70 29 2d 3e 70 44 62 4e 65 78  =&((*pp)->pDbNex
4720: 74 29 29 3b 0a 20 20 20 20 20 20 2a 70 70 20 3d  t));.      *pp =
4730: 20 70 2d 3e 70 44 62 4e 65 78 74 3b 0a 0a 20 20   p->pDbNext;..  
4740: 20 20 20 20 2f 2a 20 49 66 20 74 68 65 79 20 77      /* If they w
4750: 65 72 65 20 61 6c 6c 6f 63 61 74 65 64 20 66 72  ere allocated fr
4760: 6f 6d 20 74 68 65 20 68 65 61 70 2c 20 66 72 65  om the heap, fre
4770: 65 20 74 68 65 20 73 68 61 72 65 64 20 6d 65 6d  e the shared mem
4780: 6f 72 79 20 63 68 75 6e 6b 73 20 2a 2f 0a 20 20  ory chunks */.  
4790: 20 20 20 20 69 66 28 20 70 2d 3e 62 4d 75 6c 74      if( p->bMult
47a0: 69 50 72 6f 63 3d 3d 30 20 29 7b 0a 20 20 20 20  iProc==0 ){.    
47b0: 20 20 20 20 69 6e 74 20 69 3b 0a 20 20 20 20 20      int i;.     
47c0: 20 20 20 66 6f 72 28 69 3d 30 3b 20 69 3c 70 2d     for(i=0; i<p-
47d0: 3e 6e 53 68 6d 43 68 75 6e 6b 3b 20 69 2b 2b 29  >nShmChunk; i++)
47e0: 7b 0a 20 20 20 20 20 20 20 20 20 20 6c 73 6d 46  {.          lsmF
47f0: 72 65 65 28 70 44 62 2d 3e 70 45 6e 76 2c 20 70  ree(pDb->pEnv, p
4800: 2d 3e 61 70 53 68 6d 43 68 75 6e 6b 5b 69 5d 29  ->apShmChunk[i])
4810: 3b 0a 20 20 20 20 20 20 20 20 7d 0a 20 20 20 20  ;.        }.    
4820: 20 20 7d 0a 0a 20 20 20 20 20 20 2f 2a 20 43 6c    }..      /* Cl
4830: 6f 73 65 20 61 6e 79 20 6f 75 74 73 74 61 6e 64  ose any outstand
4840: 69 6e 67 20 66 69 6c 65 20 64 65 73 63 72 69 70  ing file descrip
4850: 74 6f 72 73 20 2a 2f 0a 20 20 20 20 20 20 66 6f  tors */.      fo
4860: 72 28 70 49 74 65 72 3d 70 2d 3e 70 4c 73 6d 46  r(pIter=p->pLsmF
4870: 69 6c 65 3b 20 70 49 74 65 72 3b 20 70 49 74 65  ile; pIter; pIte
4880: 72 3d 70 4e 65 78 74 29 7b 0a 20 20 20 20 20 20  r=pNext){.      
4890: 20 20 70 4e 65 78 74 20 3d 20 70 49 74 65 72 2d    pNext = pIter-
48a0: 3e 70 4e 65 78 74 3b 0a 20 20 20 20 20 20 20 20  >pNext;.        
48b0: 6c 73 6d 45 6e 76 43 6c 6f 73 65 28 70 44 62 2d  lsmEnvClose(pDb-
48c0: 3e 70 45 6e 76 2c 20 70 49 74 65 72 2d 3e 70 46  >pEnv, pIter->pF
48d0: 69 6c 65 29 3b 0a 20 20 20 20 20 20 20 20 6c 73  ile);.        ls
48e0: 6d 46 72 65 65 28 70 44 62 2d 3e 70 45 6e 76 2c  mFree(pDb->pEnv,
48f0: 20 70 49 74 65 72 29 3b 0a 20 20 20 20 20 20 7d   pIter);.      }
4900: 0a 20 20 20 20 20 20 66 72 65 65 44 61 74 61 62  .      freeDatab
4910: 61 73 65 28 70 44 62 2d 3e 70 45 6e 76 2c 20 70  ase(pDb->pEnv, p
4920: 29 3b 0a 20 20 20 20 7d 0a 20 20 20 20 6c 65 61  );.    }.    lea
4930: 76 65 47 6c 6f 62 61 6c 4d 75 74 65 78 28 70 44  veGlobalMutex(pD
4940: 62 2d 3e 70 45 6e 76 29 3b 0a 20 20 7d 0a 7d 0a  b->pEnv);.  }.}.
4950: 0a 4c 65 76 65 6c 20 2a 6c 73 6d 44 62 53 6e 61  .Level *lsmDbSna
4960: 70 73 68 6f 74 4c 65 76 65 6c 28 53 6e 61 70 73  pshotLevel(Snaps
4970: 68 6f 74 20 2a 70 53 6e 61 70 73 68 6f 74 29 7b  hot *pSnapshot){
4980: 0a 20 20 72 65 74 75 72 6e 20 70 53 6e 61 70 73  .  return pSnaps
4990: 68 6f 74 2d 3e 70 4c 65 76 65 6c 3b 0a 7d 0a 0a  hot->pLevel;.}..
49a0: 76 6f 69 64 20 6c 73 6d 44 62 53 6e 61 70 73 68  void lsmDbSnapsh
49b0: 6f 74 53 65 74 4c 65 76 65 6c 28 53 6e 61 70 73  otSetLevel(Snaps
49c0: 68 6f 74 20 2a 70 53 6e 61 70 2c 20 4c 65 76 65  hot *pSnap, Leve
49d0: 6c 20 2a 70 4c 65 76 65 6c 29 7b 0a 20 20 70 53  l *pLevel){.  pS
49e0: 6e 61 70 2d 3e 70 4c 65 76 65 6c 20 3d 20 70 4c  nap->pLevel = pL
49f0: 65 76 65 6c 3b 0a 7d 0a 0a 2f 2a 20 54 4f 44 4f  evel;.}../* TODO
4a00: 3a 20 53 68 75 66 66 6c 65 20 74 68 69 6e 67 73  : Shuffle things
4a10: 20 61 72 6f 75 6e 64 20 74 6f 20 67 65 74 20 72   around to get r
4a20: 69 64 20 6f 66 20 74 68 69 73 20 2a 2f 0a 73 74  id of this */.st
4a30: 61 74 69 63 20 69 6e 74 20 66 69 72 73 74 53 6e  atic int firstSn
4a40: 61 70 73 68 6f 74 49 6e 55 73 65 28 6c 73 6d 5f  apshotInUse(lsm_
4a50: 64 62 20 2a 2c 20 69 36 34 20 2a 29 3b 0a 0a 2f  db *, i64 *);../
4a60: 2a 20 0a 2a 2a 20 43 6f 6e 74 65 78 74 20 6f 62  * .** Context ob
4a70: 6a 65 63 74 20 75 73 65 64 20 62 79 20 74 68 65  ject used by the
4a80: 20 6c 73 6d 57 61 6c 6b 46 72 65 65 6c 69 73 74   lsmWalkFreelist
4a90: 28 29 20 75 74 69 6c 69 74 79 2e 20 0a 2a 2f 0a  () utility. .*/.
4aa0: 74 79 70 65 64 65 66 20 73 74 72 75 63 74 20 57  typedef struct W
4ab0: 61 6c 6b 46 72 65 65 6c 69 73 74 43 74 78 20 57  alkFreelistCtx W
4ac0: 61 6c 6b 46 72 65 65 6c 69 73 74 43 74 78 3b 0a  alkFreelistCtx;.
4ad0: 73 74 72 75 63 74 20 57 61 6c 6b 46 72 65 65 6c  struct WalkFreel
4ae0: 69 73 74 43 74 78 20 7b 0a 20 20 6c 73 6d 5f 64  istCtx {.  lsm_d
4af0: 62 20 2a 70 44 62 3b 0a 20 20 69 6e 74 20 62 52  b *pDb;.  int bR
4b00: 65 76 65 72 73 65 3b 0a 20 20 46 72 65 65 6c 69  everse;.  Freeli
4b10: 73 74 20 2a 70 46 72 65 65 6c 69 73 74 3b 0a 20  st *pFreelist;. 
4b20: 20 69 6e 74 20 69 46 72 65 65 3b 0a 20 20 69 6e   int iFree;.  in
4b30: 74 20 28 2a 78 55 73 72 29 28 76 6f 69 64 20 2a  t (*xUsr)(void *
4b40: 2c 20 69 6e 74 2c 20 69 36 34 29 3b 20 20 2f 2a  , int, i64);  /*
4b50: 20 55 73 65 72 20 63 61 6c 6c 62 61 63 6b 20 66   User callback f
4b60: 75 6e 63 74 69 6f 6e 20 2a 2f 0a 20 20 76 6f 69  unction */.  voi
4b70: 64 20 2a 70 55 73 72 63 74 78 3b 20 20 20 20 20  d *pUsrctx;     
4b80: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
4b90: 55 73 65 72 20 63 61 6c 6c 62 61 63 6b 20 63 6f  User callback co
4ba0: 6e 74 65 78 74 20 2a 2f 0a 20 20 69 6e 74 20 62  ntext */.  int b
4bb0: 44 6f 6e 65 3b 20 20 20 20 20 20 20 20 20 20 20  Done;           
4bc0: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 53 65             /* Se
4bd0: 74 20 74 6f 20 74 72 75 65 20 61 66 74 65 72 20  t to true after 
4be0: 78 55 73 72 28 29 20 72 65 74 75 72 6e 73 20 74  xUsr() returns t
4bf0: 72 75 65 20 2a 2f 0a 7d 3b 0a 0a 2f 2a 20 0a 2a  rue */.};../* .*
4c00: 2a 20 43 61 6c 6c 62 61 63 6b 20 75 73 65 64 20  * Callback used 
4c10: 62 79 20 6c 73 6d 57 61 6c 6b 46 72 65 65 6c 69  by lsmWalkFreeli
4c20: 73 74 28 29 2e 0a 2a 2f 0a 73 74 61 74 69 63 20  st()..*/.static 
4c30: 69 6e 74 20 77 61 6c 6b 46 72 65 65 6c 69 73 74  int walkFreelist
4c40: 43 62 28 76 6f 69 64 20 2a 70 43 74 78 2c 20 69  Cb(void *pCtx, i
4c50: 6e 74 20 69 42 6c 6b 2c 20 69 36 34 20 69 53 6e  nt iBlk, i64 iSn
4c60: 61 70 73 68 6f 74 29 7b 0a 20 20 57 61 6c 6b 46  apshot){.  WalkF
4c70: 72 65 65 6c 69 73 74 43 74 78 20 2a 70 20 3d 20  reelistCtx *p = 
4c80: 28 57 61 6c 6b 46 72 65 65 6c 69 73 74 43 74 78  (WalkFreelistCtx
4c90: 20 2a 29 70 43 74 78 3b 0a 20 20 63 6f 6e 73 74   *)pCtx;.  const
4ca0: 20 69 6e 74 20 69 44 69 72 20 3d 20 28 70 2d 3e   int iDir = (p->
4cb0: 62 52 65 76 65 72 73 65 20 3f 20 2d 31 20 3a 20  bReverse ? -1 : 
4cc0: 31 29 3b 0a 20 20 46 72 65 65 6c 69 73 74 20 2a  1);.  Freelist *
4cd0: 70 46 72 65 65 20 3d 20 70 2d 3e 70 46 72 65 65  pFree = p->pFree
4ce0: 6c 69 73 74 3b 0a 0a 20 20 61 73 73 65 72 74 28  list;..  assert(
4cf0: 20 70 2d 3e 62 44 6f 6e 65 3d 3d 30 20 29 3b 0a   p->bDone==0 );.
4d00: 20 20 61 73 73 65 72 74 28 20 69 42 6c 6b 3e 3d    assert( iBlk>=
4d10: 30 20 29 3b 0a 20 20 69 66 28 20 70 46 72 65 65  0 );.  if( pFree
4d20: 20 29 7b 0a 20 20 20 20 77 68 69 6c 65 28 20 28   ){.    while( (
4d30: 70 2d 3e 69 46 72 65 65 20 3c 20 70 46 72 65 65  p->iFree < pFree
4d40: 2d 3e 6e 45 6e 74 72 79 29 20 26 26 20 70 2d 3e  ->nEntry) && p->
4d50: 69 46 72 65 65 3e 3d 30 20 29 7b 0a 20 20 20 20  iFree>=0 ){.    
4d60: 20 20 46 72 65 65 6c 69 73 74 45 6e 74 72 79 20    FreelistEntry 
4d70: 2a 70 45 6e 74 72 79 20 3d 20 26 70 46 72 65 65  *pEntry = &pFree
4d80: 2d 3e 61 45 6e 74 72 79 5b 70 2d 3e 69 46 72 65  ->aEntry[p->iFre
4d90: 65 5d 3b 0a 20 20 20 20 20 20 69 66 28 20 28 70  e];.      if( (p
4da0: 2d 3e 62 52 65 76 65 72 73 65 3d 3d 30 20 26 26  ->bReverse==0 &&
4db0: 20 70 45 6e 74 72 79 2d 3e 69 42 6c 6b 3e 28 75   pEntry->iBlk>(u
4dc0: 33 32 29 69 42 6c 6b 29 0a 20 20 20 20 20 20 20  32)iBlk).       
4dd0: 7c 7c 20 28 70 2d 3e 62 52 65 76 65 72 73 65 21  || (p->bReverse!
4de0: 3d 30 20 26 26 20 70 45 6e 74 72 79 2d 3e 69 42  =0 && pEntry->iB
4df0: 6c 6b 3c 28 75 33 32 29 69 42 6c 6b 29 0a 20 20  lk<(u32)iBlk).  
4e00: 20 20 20 20 29 7b 0a 20 20 20 20 20 20 20 20 62      ){.        b
4e10: 72 65 61 6b 3b 0a 20 20 20 20 20 20 7d 65 6c 73  reak;.      }els
4e20: 65 7b 0a 20 20 20 20 20 20 20 20 70 2d 3e 69 46  e{.        p->iF
4e30: 72 65 65 20 2b 3d 20 69 44 69 72 3b 0a 20 20 20  ree += iDir;.   
4e40: 20 20 20 20 20 69 66 28 20 70 45 6e 74 72 79 2d       if( pEntry-
4e50: 3e 69 49 64 3e 3d 30 20 0a 20 20 20 20 20 20 20  >iId>=0 .       
4e60: 20 20 20 20 20 26 26 20 70 2d 3e 78 55 73 72 28       && p->xUsr(
4e70: 70 2d 3e 70 55 73 72 63 74 78 2c 20 70 45 6e 74  p->pUsrctx, pEnt
4e80: 72 79 2d 3e 69 42 6c 6b 2c 20 70 45 6e 74 72 79  ry->iBlk, pEntry
4e90: 2d 3e 69 49 64 29 20 0a 20 20 20 20 20 20 20 20  ->iId) .        
4ea0: 20 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20 70    ){.          p
4eb0: 2d 3e 62 44 6f 6e 65 20 3d 20 31 3b 0a 20 20 20  ->bDone = 1;.   
4ec0: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 31 3b         return 1;
4ed0: 0a 20 20 20 20 20 20 20 20 7d 0a 20 20 20 20 20  .        }.     
4ee0: 20 20 20 69 66 28 20 70 45 6e 74 72 79 2d 3e 69     if( pEntry->i
4ef0: 42 6c 6b 3d 3d 28 75 33 32 29 69 42 6c 6b 20 29  Blk==(u32)iBlk )
4f00: 20 72 65 74 75 72 6e 20 30 3b 0a 20 20 20 20 20   return 0;.     
4f10: 20 7d 0a 20 20 20 20 7d 0a 20 20 7d 0a 0a 20 20   }.    }.  }..  
4f20: 69 66 28 20 70 2d 3e 78 55 73 72 28 70 2d 3e 70  if( p->xUsr(p->p
4f30: 55 73 72 63 74 78 2c 20 69 42 6c 6b 2c 20 69 53  Usrctx, iBlk, iS
4f40: 6e 61 70 73 68 6f 74 29 20 29 7b 0a 20 20 20 20  napshot) ){.    
4f50: 70 2d 3e 62 44 6f 6e 65 20 3d 20 31 3b 0a 20 20  p->bDone = 1;.  
4f60: 20 20 72 65 74 75 72 6e 20 31 3b 0a 20 20 7d 0a    return 1;.  }.
4f70: 20 20 72 65 74 75 72 6e 20 30 3b 0a 7d 0a 0a 2f    return 0;.}../
4f80: 2a 0a 2a 2a 20 54 68 65 20 64 61 74 61 62 61 73  *.** The databas
4f90: 65 20 68 61 6e 64 6c 65 20 70 61 73 73 65 64 20  e handle passed 
4fa0: 61 73 20 74 68 65 20 66 69 72 73 74 20 61 72 67  as the first arg
4fb0: 75 6d 65 6e 74 20 6d 75 73 74 20 62 65 20 74 68  ument must be th
4fc0: 65 20 77 6f 72 6b 65 72 0a 2a 2a 20 63 6f 6e 6e  e worker.** conn
4fd0: 65 63 74 69 6f 6e 2e 20 54 68 69 73 20 66 75 6e  ection. This fun
4fe0: 63 74 69 6f 6e 20 69 74 65 72 61 74 65 73 20 74  ction iterates t
4ff0: 68 72 6f 75 67 68 20 74 68 65 20 63 6f 6e 74 65  hrough the conte
5000: 6e 74 73 20 6f 66 20 74 68 65 20 63 75 72 72 65  nts of the curre
5010: 6e 74 0a 2a 2a 20 66 72 65 65 20 62 6c 6f 63 6b  nt.** free block
5020: 20 6c 69 73 74 2c 20 69 6e 76 6f 6b 69 6e 67 20   list, invoking 
5030: 74 68 65 20 73 75 70 70 6c 69 65 64 20 63 61 6c  the supplied cal
5040: 6c 62 61 63 6b 20 6f 6e 63 65 20 66 6f 72 20 65  lback once for e
5050: 61 63 68 20 6c 69 73 74 0a 2a 2a 20 65 6c 65 6d  ach list.** elem
5060: 65 6e 74 2e 0a 2a 2a 0a 2a 2a 20 54 68 65 20 64  ent..**.** The d
5070: 69 66 66 65 72 65 6e 63 65 20 62 65 74 77 65 65  ifference betwee
5080: 6e 20 74 68 69 73 20 66 75 6e 63 74 69 6f 6e 20  n this function 
5090: 61 6e 64 20 6c 73 6d 53 6f 72 74 65 64 57 61 6c  and lsmSortedWal
50a0: 6b 46 72 65 65 6c 69 73 74 28 29 20 69 73 0a 2a  kFreelist() is.*
50b0: 2a 20 74 68 61 74 20 6c 73 6d 53 6f 72 74 65 64  * that lsmSorted
50c0: 57 61 6c 6b 46 72 65 65 6c 69 73 74 28 29 20 6f  WalkFreelist() o
50d0: 6e 6c 79 20 63 6f 6e 73 69 64 65 72 73 20 74 68  nly considers th
50e0: 6f 73 65 20 66 72 65 65 2d 6c 69 73 74 20 65 6c  ose free-list el
50f0: 65 6d 65 6e 74 73 0a 2a 2a 20 73 74 6f 72 65 64  ements.** stored
5100: 20 77 69 74 68 69 6e 20 74 68 65 20 4c 53 4d 2e   within the LSM.
5110: 20 54 68 69 73 20 66 75 6e 63 74 69 6f 6e 20 61   This function a
5120: 6c 73 6f 20 6d 65 72 67 65 73 20 69 6e 20 61 6e  lso merges in an
5130: 79 20 69 6e 2d 6d 65 6d 6f 72 79 20 0a 2a 2a 20  y in-memory .** 
5140: 65 6c 65 6d 65 6e 74 73 2e 0a 2a 2f 0a 69 6e 74  elements..*/.int
5150: 20 6c 73 6d 57 61 6c 6b 46 72 65 65 6c 69 73 74   lsmWalkFreelist
5160: 28 0a 20 20 6c 73 6d 5f 64 62 20 2a 70 44 62 2c  (.  lsm_db *pDb,
5170: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5180: 20 20 20 20 2f 2a 20 44 61 74 61 62 61 73 65 20      /* Database 
5190: 68 61 6e 64 6c 65 20 28 6d 75 73 74 20 62 65 20  handle (must be 
51a0: 77 6f 72 6b 65 72 29 20 2a 2f 0a 20 20 69 6e 74  worker) */.  int
51b0: 20 62 52 65 76 65 72 73 65 2c 20 20 20 20 20 20   bReverse,      
51c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
51d0: 54 72 75 65 20 74 6f 20 69 74 65 72 61 74 65 20  True to iterate 
51e0: 66 72 6f 6d 20 6c 61 72 67 65 73 74 20 74 6f 20  from largest to 
51f0: 73 6d 61 6c 6c 65 73 74 20 2a 2f 0a 20 20 69 6e  smallest */.  in
5200: 74 20 28 2a 78 29 28 76 6f 69 64 20 2a 2c 20 69  t (*x)(void *, i
5210: 6e 74 2c 20 69 36 34 29 2c 20 20 20 20 20 2f 2a  nt, i64),     /*
5220: 20 43 61 6c 6c 62 61 63 6b 20 66 75 6e 63 74 69   Callback functi
5230: 6f 6e 20 2a 2f 0a 20 20 76 6f 69 64 20 2a 70 43  on */.  void *pC
5240: 74 78 20 20 20 20 20 20 20 20 20 20 20 20 20 20  tx              
5250: 20 20 20 20 20 20 20 20 2f 2a 20 46 69 72 73 74          /* First
5260: 20 61 72 67 75 6d 65 6e 74 20 74 6f 20 70 61 73   argument to pas
5270: 73 20 74 6f 20 63 61 6c 6c 62 61 63 6b 20 2a 2f  s to callback */
5280: 0a 29 7b 0a 20 20 63 6f 6e 73 74 20 69 6e 74 20  .){.  const int 
5290: 69 44 69 72 20 3d 20 28 62 52 65 76 65 72 73 65  iDir = (bReverse
52a0: 20 3f 20 2d 31 20 3a 20 31 29 3b 0a 20 20 69 6e   ? -1 : 1);.  in
52b0: 74 20 72 63 3b 0a 20 20 69 6e 74 20 69 43 74 78  t rc;.  int iCtx
52c0: 3b 0a 0a 20 20 57 61 6c 6b 46 72 65 65 6c 69 73  ;..  WalkFreelis
52d0: 74 43 74 78 20 63 74 78 5b 32 5d 3b 0a 0a 20 20  tCtx ctx[2];..  
52e0: 63 74 78 5b 30 5d 2e 70 44 62 20 3d 20 70 44 62  ctx[0].pDb = pDb
52f0: 3b 0a 20 20 63 74 78 5b 30 5d 2e 62 52 65 76 65  ;.  ctx[0].bReve
5300: 72 73 65 20 3d 20 62 52 65 76 65 72 73 65 3b 0a  rse = bReverse;.
5310: 20 20 63 74 78 5b 30 5d 2e 70 46 72 65 65 6c 69    ctx[0].pFreeli
5320: 73 74 20 3d 20 26 70 44 62 2d 3e 70 57 6f 72 6b  st = &pDb->pWork
5330: 65 72 2d 3e 66 72 65 65 6c 69 73 74 3b 0a 20 20  er->freelist;.  
5340: 69 66 28 20 63 74 78 5b 30 5d 2e 70 46 72 65 65  if( ctx[0].pFree
5350: 6c 69 73 74 20 26 26 20 62 52 65 76 65 72 73 65  list && bReverse
5360: 20 29 7b 0a 20 20 20 20 63 74 78 5b 30 5d 2e 69   ){.    ctx[0].i
5370: 46 72 65 65 20 3d 20 63 74 78 5b 30 5d 2e 70 46  Free = ctx[0].pF
5380: 72 65 65 6c 69 73 74 2d 3e 6e 45 6e 74 72 79 2d  reelist->nEntry-
5390: 31 3b 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20  1;.  }else{.    
53a0: 63 74 78 5b 30 5d 2e 69 46 72 65 65 20 3d 20 30  ctx[0].iFree = 0
53b0: 3b 0a 20 20 7d 0a 20 20 63 74 78 5b 30 5d 2e 78  ;.  }.  ctx[0].x
53c0: 55 73 72 20 3d 20 77 61 6c 6b 46 72 65 65 6c 69  Usr = walkFreeli
53d0: 73 74 43 62 3b 0a 20 20 63 74 78 5b 30 5d 2e 70  stCb;.  ctx[0].p
53e0: 55 73 72 63 74 78 20 3d 20 28 76 6f 69 64 20 2a  Usrctx = (void *
53f0: 29 26 63 74 78 5b 31 5d 3b 0a 20 20 63 74 78 5b  )&ctx[1];.  ctx[
5400: 30 5d 2e 62 44 6f 6e 65 20 3d 20 30 3b 0a 0a 20  0].bDone = 0;.. 
5410: 20 63 74 78 5b 31 5d 2e 70 44 62 20 3d 20 70 44   ctx[1].pDb = pD
5420: 62 3b 0a 20 20 63 74 78 5b 31 5d 2e 62 52 65 76  b;.  ctx[1].bRev
5430: 65 72 73 65 20 3d 20 62 52 65 76 65 72 73 65 3b  erse = bReverse;
5440: 0a 20 20 63 74 78 5b 31 5d 2e 70 46 72 65 65 6c  .  ctx[1].pFreel
5450: 69 73 74 20 3d 20 70 44 62 2d 3e 70 46 72 65 65  ist = pDb->pFree
5460: 6c 69 73 74 3b 0a 20 20 69 66 28 20 63 74 78 5b  list;.  if( ctx[
5470: 31 5d 2e 70 46 72 65 65 6c 69 73 74 20 26 26 20  1].pFreelist && 
5480: 62 52 65 76 65 72 73 65 20 29 7b 0a 20 20 20 20  bReverse ){.    
5490: 63 74 78 5b 31 5d 2e 69 46 72 65 65 20 3d 20 63  ctx[1].iFree = c
54a0: 74 78 5b 31 5d 2e 70 46 72 65 65 6c 69 73 74 2d  tx[1].pFreelist-
54b0: 3e 6e 45 6e 74 72 79 2d 31 3b 0a 20 20 7d 65 6c  >nEntry-1;.  }el
54c0: 73 65 7b 0a 20 20 20 20 63 74 78 5b 31 5d 2e 69  se{.    ctx[1].i
54d0: 46 72 65 65 20 3d 20 30 3b 0a 20 20 7d 0a 20 20  Free = 0;.  }.  
54e0: 63 74 78 5b 31 5d 2e 78 55 73 72 20 3d 20 78 3b  ctx[1].xUsr = x;
54f0: 0a 20 20 63 74 78 5b 31 5d 2e 70 55 73 72 63 74  .  ctx[1].pUsrct
5500: 78 20 3d 20 70 43 74 78 3b 0a 20 20 63 74 78 5b  x = pCtx;.  ctx[
5510: 31 5d 2e 62 44 6f 6e 65 20 3d 20 30 3b 0a 0a 20  1].bDone = 0;.. 
5520: 20 72 63 20 3d 20 6c 73 6d 53 6f 72 74 65 64 57   rc = lsmSortedW
5530: 61 6c 6b 46 72 65 65 6c 69 73 74 28 70 44 62 2c  alkFreelist(pDb,
5540: 20 62 52 65 76 65 72 73 65 2c 20 77 61 6c 6b 46   bReverse, walkF
5550: 72 65 65 6c 69 73 74 43 62 2c 20 28 76 6f 69 64  reelistCb, (void
5560: 20 2a 29 26 63 74 78 5b 30 5d 29 3b 0a 0a 20 20   *)&ctx[0]);..  
5570: 69 66 28 20 63 74 78 5b 30 5d 2e 62 44 6f 6e 65  if( ctx[0].bDone
5580: 3d 3d 30 20 29 7b 0a 20 20 20 20 66 6f 72 28 69  ==0 ){.    for(i
5590: 43 74 78 3d 30 3b 20 69 43 74 78 3c 32 3b 20 69  Ctx=0; iCtx<2; i
55a0: 43 74 78 2b 2b 29 7b 0a 20 20 20 20 20 20 69 6e  Ctx++){.      in
55b0: 74 20 69 3b 0a 20 20 20 20 20 20 57 61 6c 6b 46  t i;.      WalkF
55c0: 72 65 65 6c 69 73 74 43 74 78 20 2a 70 20 3d 20  reelistCtx *p = 
55d0: 26 63 74 78 5b 69 43 74 78 5d 3b 0a 20 20 20 20  &ctx[iCtx];.    
55e0: 20 20 66 6f 72 28 69 3d 70 2d 3e 69 46 72 65 65    for(i=p->iFree
55f0: 3b 20 0a 20 20 20 20 20 20 20 20 20 20 70 2d 3e  ; .          p->
5600: 70 46 72 65 65 6c 69 73 74 20 26 26 20 72 63 3d  pFreelist && rc=
5610: 3d 4c 53 4d 5f 4f 4b 20 26 26 20 69 3c 70 2d 3e  =LSM_OK && i<p->
5620: 70 46 72 65 65 6c 69 73 74 2d 3e 6e 45 6e 74 72  pFreelist->nEntr
5630: 79 20 26 26 20 69 3e 3d 30 3b 0a 20 20 20 20 20  y && i>=0;.     
5640: 20 20 20 20 20 69 20 2b 3d 20 69 44 69 72 0a 20       i += iDir. 
5650: 20 20 20 20 20 20 20 20 29 7b 0a 20 20 20 20 20          ){.     
5660: 20 20 20 46 72 65 65 6c 69 73 74 45 6e 74 72 79     FreelistEntry
5670: 20 2a 70 45 6e 74 72 79 20 3d 20 26 70 2d 3e 70   *pEntry = &p->p
5680: 46 72 65 65 6c 69 73 74 2d 3e 61 45 6e 74 72 79  Freelist->aEntry
5690: 5b 69 5d 3b 0a 20 20 20 20 20 20 20 20 69 66 28  [i];.        if(
56a0: 20 70 45 6e 74 72 79 2d 3e 69 49 64 3e 3d 30 20   pEntry->iId>=0 
56b0: 26 26 20 70 2d 3e 78 55 73 72 28 70 2d 3e 70 55  && p->xUsr(p->pU
56c0: 73 72 63 74 78 2c 20 70 45 6e 74 72 79 2d 3e 69  srctx, pEntry->i
56d0: 42 6c 6b 2c 20 70 45 6e 74 72 79 2d 3e 69 49 64  Blk, pEntry->iId
56e0: 29 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20 72  ) ){.          r
56f0: 65 74 75 72 6e 20 4c 53 4d 5f 4f 4b 3b 0a 20 20  eturn LSM_OK;.  
5700: 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 7d 0a        }.      }.
5710: 20 20 20 20 7d 0a 20 20 7d 0a 0a 20 20 72 65 74      }.  }..  ret
5720: 75 72 6e 20 72 63 3b 0a 7d 0a 0a 0a 74 79 70 65  urn rc;.}...type
5730: 64 65 66 20 73 74 72 75 63 74 20 46 69 6e 64 46  def struct FindF
5740: 72 65 65 62 6c 6f 63 6b 43 74 78 20 46 69 6e 64  reeblockCtx Find
5750: 46 72 65 65 62 6c 6f 63 6b 43 74 78 3b 0a 73 74  FreeblockCtx;.st
5760: 72 75 63 74 20 46 69 6e 64 46 72 65 65 62 6c 6f  ruct FindFreeblo
5770: 63 6b 43 74 78 20 7b 0a 20 20 69 36 34 20 69 49  ckCtx {.  i64 iI
5780: 6e 55 73 65 3b 0a 20 20 69 6e 74 20 69 52 65 74  nUse;.  int iRet
5790: 3b 0a 20 20 69 6e 74 20 62 4e 6f 74 4f 6e 65 3b  ;.  int bNotOne;
57a0: 0a 7d 3b 0a 0a 73 74 61 74 69 63 20 69 6e 74 20  .};..static int 
57b0: 66 69 6e 64 46 72 65 65 62 6c 6f 63 6b 43 62 28  findFreeblockCb(
57c0: 76 6f 69 64 20 2a 70 43 74 78 2c 20 69 6e 74 20  void *pCtx, int 
57d0: 69 42 6c 6b 2c 20 69 36 34 20 69 53 6e 61 70 73  iBlk, i64 iSnaps
57e0: 68 6f 74 29 7b 0a 20 20 46 69 6e 64 46 72 65 65  hot){.  FindFree
57f0: 62 6c 6f 63 6b 43 74 78 20 2a 70 20 3d 20 28 46  blockCtx *p = (F
5800: 69 6e 64 46 72 65 65 62 6c 6f 63 6b 43 74 78 20  indFreeblockCtx 
5810: 2a 29 70 43 74 78 3b 0a 20 20 69 66 28 20 69 53  *)pCtx;.  if( iS
5820: 6e 61 70 73 68 6f 74 3c 70 2d 3e 69 49 6e 55 73  napshot<p->iInUs
5830: 65 20 26 26 20 28 69 42 6c 6b 21 3d 31 20 7c 7c  e && (iBlk!=1 ||
5840: 20 70 2d 3e 62 4e 6f 74 4f 6e 65 3d 3d 30 29 20   p->bNotOne==0) 
5850: 29 7b 0a 20 20 20 20 70 2d 3e 69 52 65 74 20 3d  ){.    p->iRet =
5860: 20 69 42 6c 6b 3b 0a 20 20 20 20 72 65 74 75 72   iBlk;.    retur
5870: 6e 20 31 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72  n 1;.  }.  retur
5880: 6e 20 30 3b 0a 7d 0a 0a 73 74 61 74 69 63 20 69  n 0;.}..static i
5890: 6e 74 20 66 69 6e 64 46 72 65 65 62 6c 6f 63 6b  nt findFreeblock
58a0: 28 6c 73 6d 5f 64 62 20 2a 70 44 62 2c 20 69 36  (lsm_db *pDb, i6
58b0: 34 20 69 49 6e 55 73 65 2c 20 69 6e 74 20 62 4e  4 iInUse, int bN
58c0: 6f 74 4f 6e 65 2c 20 69 6e 74 20 2a 70 69 52 65  otOne, int *piRe
58d0: 74 29 7b 0a 20 20 69 6e 74 20 72 63 3b 20 20 20  t){.  int rc;   
58e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
58f0: 20 20 20 20 20 20 2f 2a 20 52 65 74 75 72 6e 20        /* Return 
5900: 63 6f 64 65 20 2a 2f 0a 20 20 46 69 6e 64 46 72  code */.  FindFr
5910: 65 65 62 6c 6f 63 6b 43 74 78 20 63 74 78 3b 20  eeblockCtx ctx; 
5920: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 43 6f 6e            /* Con
5930: 74 65 78 74 20 6f 62 6a 65 63 74 20 2a 2f 0a 0a  text object */..
5940: 20 20 63 74 78 2e 69 49 6e 55 73 65 20 3d 20 69    ctx.iInUse = i
5950: 49 6e 55 73 65 3b 0a 20 20 63 74 78 2e 69 52 65  InUse;.  ctx.iRe
5960: 74 20 3d 20 30 3b 0a 20 20 63 74 78 2e 62 4e 6f  t = 0;.  ctx.bNo
5970: 74 4f 6e 65 20 3d 20 62 4e 6f 74 4f 6e 65 3b 0a  tOne = bNotOne;.
5980: 20 20 72 63 20 3d 20 6c 73 6d 57 61 6c 6b 46 72    rc = lsmWalkFr
5990: 65 65 6c 69 73 74 28 70 44 62 2c 20 30 2c 20 66  eelist(pDb, 0, f
59a0: 69 6e 64 46 72 65 65 62 6c 6f 63 6b 43 62 2c 20  indFreeblockCb, 
59b0: 28 76 6f 69 64 20 2a 29 26 63 74 78 29 3b 0a 20  (void *)&ctx);. 
59c0: 20 2a 70 69 52 65 74 20 3d 20 63 74 78 2e 69 52   *piRet = ctx.iR
59d0: 65 74 3b 0a 0a 20 20 72 65 74 75 72 6e 20 72 63  et;..  return rc
59e0: 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 41 6c 6c 6f 63  ;.}../*.** Alloc
59f0: 61 74 65 20 61 20 6e 65 77 20 64 61 74 61 62 61  ate a new databa
5a00: 73 65 20 66 69 6c 65 20 62 6c 6f 63 6b 20 74 6f  se file block to
5a10: 20 77 72 69 74 65 20 64 61 74 61 20 74 6f 2c 20   write data to, 
5a20: 65 69 74 68 65 72 20 62 79 20 65 78 74 65 6e 64  either by extend
5a30: 69 6e 67 0a 2a 2a 20 74 68 65 20 64 61 74 61 62  ing.** the datab
5a40: 61 73 65 20 66 69 6c 65 20 6f 72 20 62 79 20 72  ase file or by r
5a50: 65 63 79 63 6c 69 6e 67 20 61 20 66 72 65 65 2d  ecycling a free-
5a60: 6c 69 73 74 20 65 6e 74 72 79 2e 20 54 68 65 20  list entry. The 
5a70: 77 6f 72 6b 65 72 20 73 6e 61 70 73 68 6f 74 20  worker snapshot 
5a80: 0a 2a 2a 20 6d 75 73 74 20 62 65 20 68 65 6c 64  .** must be held
5a90: 20 69 6e 20 6f 72 64 65 72 20 74 6f 20 63 61 6c   in order to cal
5aa0: 6c 20 74 68 69 73 20 66 75 6e 63 74 69 6f 6e 2e  l this function.
5ab0: 0a 2a 2a 0a 2a 2a 20 49 66 20 73 75 63 63 65 73  .**.** If succes
5ac0: 73 66 75 6c 2c 20 2a 70 69 42 6c 6b 20 69 73 20  sful, *piBlk is 
5ad0: 73 65 74 20 74 6f 20 74 68 65 20 62 6c 6f 63 6b  set to the block
5ae0: 20 6e 75 6d 62 65 72 20 61 6c 6c 6f 63 61 74 65   number allocate
5af0: 64 20 61 6e 64 20 4c 53 4d 5f 4f 4b 20 69 73 0a  d and LSM_OK is.
5b00: 2a 2a 20 72 65 74 75 72 6e 65 64 2e 20 4f 74 68  ** returned. Oth
5b10: 65 72 77 69 73 65 2c 20 2a 70 69 42 6c 6b 20 69  erwise, *piBlk i
5b20: 73 20 7a 65 72 6f 65 64 20 61 6e 64 20 61 6e 20  s zeroed and an 
5b30: 6c 73 6d 20 65 72 72 6f 72 20 63 6f 64 65 20 72  lsm error code r
5b40: 65 74 75 72 6e 65 64 2e 0a 2a 2f 0a 69 6e 74 20  eturned..*/.int 
5b50: 6c 73 6d 42 6c 6f 63 6b 41 6c 6c 6f 63 61 74 65  lsmBlockAllocate
5b60: 28 6c 73 6d 5f 64 62 20 2a 70 44 62 2c 20 69 6e  (lsm_db *pDb, in
5b70: 74 20 69 42 65 66 6f 72 65 2c 20 69 6e 74 20 2a  t iBefore, int *
5b80: 70 69 42 6c 6b 29 7b 0a 20 20 53 6e 61 70 73 68  piBlk){.  Snapsh
5b90: 6f 74 20 2a 70 20 3d 20 70 44 62 2d 3e 70 57 6f  ot *p = pDb->pWo
5ba0: 72 6b 65 72 3b 0a 20 20 69 6e 74 20 69 52 65 74  rker;.  int iRet
5bb0: 20 3d 20 30 3b 20 20 20 20 20 20 20 20 20 20 20   = 0;           
5bc0: 20 20 20 20 20 20 20 20 2f 2a 20 42 6c 6f 63 6b          /* Block
5bd0: 20 6e 75 6d 62 65 72 20 6f 66 20 61 6c 6c 6f 63   number of alloc
5be0: 61 74 65 64 20 62 6c 6f 63 6b 20 2a 2f 0a 20 20  ated block */.  
5bf0: 69 6e 74 20 72 63 20 3d 20 4c 53 4d 5f 4f 4b 3b  int rc = LSM_OK;
5c00: 0a 20 20 69 36 34 20 69 49 6e 55 73 65 20 3d 20  .  i64 iInUse = 
5c10: 30 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  0;              
5c20: 20 20 20 2f 2a 20 53 6e 61 70 73 68 6f 74 20 69     /* Snapshot i
5c30: 64 20 73 74 69 6c 6c 20 69 6e 20 75 73 65 20 2a  d still in use *
5c40: 2f 0a 20 20 69 36 34 20 69 53 79 6e 63 65 64 20  /.  i64 iSynced 
5c50: 3d 20 30 3b 20 20 20 20 20 20 20 20 20 20 20 20  = 0;            
5c60: 20 20 20 20 2f 2a 20 53 6e 61 70 73 68 6f 74 20      /* Snapshot 
5c70: 69 64 20 73 79 6e 63 65 64 20 74 6f 20 64 69 73  id synced to dis
5c80: 6b 20 2a 2f 0a 0a 20 20 61 73 73 65 72 74 28 20  k */..  assert( 
5c90: 70 20 29 3b 0a 0a 23 69 66 64 65 66 20 4c 53 4d  p );..#ifdef LSM
5ca0: 5f 4c 4f 47 5f 46 52 45 45 4c 49 53 54 0a 20 20  _LOG_FREELIST.  
5cb0: 7b 0a 20 20 20 20 73 74 61 74 69 63 20 69 6e 74  {.    static int
5cc0: 20 6e 43 61 6c 6c 20 3d 20 30 3b 0a 20 20 20 20   nCall = 0;.    
5cd0: 63 68 61 72 20 2a 7a 46 72 65 65 20 3d 20 30 3b  char *zFree = 0;
5ce0: 0a 20 20 20 20 6e 43 61 6c 6c 2b 2b 3b 0a 20 20  .    nCall++;.  
5cf0: 20 20 72 63 20 3d 20 6c 73 6d 49 6e 66 6f 46 72    rc = lsmInfoFr
5d00: 65 65 6c 69 73 74 28 70 44 62 2c 20 26 7a 46 72  eelist(pDb, &zFr
5d10: 65 65 29 3b 0a 20 20 20 20 69 66 28 20 72 63 21  ee);.    if( rc!
5d20: 3d 4c 53 4d 5f 4f 4b 20 29 20 72 65 74 75 72 6e  =LSM_OK ) return
5d30: 20 72 63 3b 0a 20 20 20 20 6c 73 6d 4c 6f 67 4d   rc;.    lsmLogM
5d40: 65 73 73 61 67 65 28 70 44 62 2c 20 30 2c 20 22  essage(pDb, 0, "
5d50: 6c 73 6d 42 6c 6f 63 6b 41 6c 6c 6f 63 61 74 65  lsmBlockAllocate
5d60: 28 29 3a 20 25 64 20 66 72 65 65 6c 69 73 74 3a  (): %d freelist:
5d70: 20 25 73 22 2c 20 6e 43 61 6c 6c 2c 20 7a 46 72   %s", nCall, zFr
5d80: 65 65 29 3b 0a 20 20 20 20 6c 73 6d 46 72 65 65  ee);.    lsmFree
5d90: 28 70 44 62 2d 3e 70 45 6e 76 2c 20 7a 46 72 65  (pDb->pEnv, zFre
5da0: 65 29 3b 0a 20 20 7d 0a 23 65 6e 64 69 66 0a 0a  e);.  }.#endif..
5db0: 20 20 2f 2a 20 53 65 74 20 69 49 6e 55 73 65 20    /* Set iInUse 
5dc0: 74 6f 20 74 68 65 20 73 6d 61 6c 6c 65 73 74 20  to the smallest 
5dd0: 73 6e 61 70 73 68 6f 74 20 69 64 20 74 68 61 74  snapshot id that
5de0: 20 69 73 20 65 69 74 68 65 72 3a 0a 20 20 2a 2a   is either:.  **
5df0: 0a 20 20 2a 2a 20 20 20 2a 20 43 75 72 72 65 6e  .  **   * Curren
5e00: 74 6c 79 20 69 6e 20 75 73 65 20 62 79 20 61 20  tly in use by a 
5e10: 64 61 74 61 62 61 73 65 20 63 6c 69 65 6e 74 2c  database client,
5e20: 0a 20 20 2a 2a 20 20 20 2a 20 4d 61 79 20 62 65  .  **   * May be
5e30: 20 75 73 65 64 20 62 79 20 61 20 64 61 74 61 62   used by a datab
5e40: 61 73 65 20 63 6c 69 65 6e 74 20 69 6e 20 74 68  ase client in th
5e50: 65 20 66 75 74 75 72 65 2c 20 6f 72 0a 20 20 2a  e future, or.  *
5e60: 2a 20 20 20 2a 20 49 73 20 74 68 65 20 6d 6f 73  *   * Is the mos
5e70: 74 20 72 65 63 65 6e 74 6c 79 20 63 68 65 63 6b  t recently check
5e80: 70 6f 69 6e 74 65 64 20 73 6e 61 70 73 68 6f 74  pointed snapshot
5e90: 20 28 69 2e 65 2e 20 74 68 65 20 6f 6e 65 20 74   (i.e. the one t
5ea0: 68 61 74 20 77 69 6c 6c 0a 20 20 2a 2a 20 20 20  hat will.  **   
5eb0: 20 20 62 65 20 75 73 65 64 20 66 6f 6c 6c 6f 77    be used follow
5ec0: 69 6e 67 20 72 65 63 6f 76 65 72 79 20 69 66 20  ing recovery if 
5ed0: 61 20 66 61 69 6c 75 72 65 20 6f 63 63 75 72 73  a failure occurs
5ee0: 20 61 74 20 74 68 69 73 20 70 6f 69 6e 74 29 2e   at this point).
5ef0: 0a 20 20 2a 2f 0a 20 20 72 63 20 3d 20 6c 73 6d  .  */.  rc = lsm
5f00: 43 68 65 63 6b 70 6f 69 6e 74 53 79 6e 63 65 64  CheckpointSynced
5f10: 28 70 44 62 2c 20 26 69 53 79 6e 63 65 64 2c 20  (pDb, &iSynced, 
5f20: 30 2c 20 30 29 3b 0a 20 20 69 66 28 20 72 63 3d  0, 0);.  if( rc=
5f30: 3d 4c 53 4d 5f 4f 4b 20 26 26 20 69 53 79 6e 63  =LSM_OK && iSync
5f40: 65 64 3d 3d 30 20 29 20 69 53 79 6e 63 65 64 20  ed==0 ) iSynced 
5f50: 3d 20 70 2d 3e 69 49 64 3b 0a 20 20 69 49 6e 55  = p->iId;.  iInU
5f60: 73 65 20 3d 20 69 53 79 6e 63 65 64 3b 0a 20 20  se = iSynced;.  
5f70: 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 26  if( rc==LSM_OK &
5f80: 26 20 70 44 62 2d 3e 69 52 65 61 64 65 72 3e 3d  & pDb->iReader>=
5f90: 30 20 29 7b 0a 20 20 20 20 61 73 73 65 72 74 28  0 ){.    assert(
5fa0: 20 70 44 62 2d 3e 70 43 6c 69 65 6e 74 20 29 3b   pDb->pClient );
5fb0: 0a 20 20 20 20 69 49 6e 55 73 65 20 3d 20 4c 53  .    iInUse = LS
5fc0: 4d 5f 4d 49 4e 28 69 49 6e 55 73 65 2c 20 70 44  M_MIN(iInUse, pD
5fd0: 62 2d 3e 70 43 6c 69 65 6e 74 2d 3e 69 49 64 29  b->pClient->iId)
5fe0: 3b 0a 20 20 7d 0a 20 20 69 66 28 20 72 63 3d 3d  ;.  }.  if( rc==
5ff0: 4c 53 4d 5f 4f 4b 20 29 20 72 63 20 3d 20 66 69  LSM_OK ) rc = fi
6000: 72 73 74 53 6e 61 70 73 68 6f 74 49 6e 55 73 65  rstSnapshotInUse
6010: 28 70 44 62 2c 20 26 69 49 6e 55 73 65 29 3b 0a  (pDb, &iInUse);.
6020: 0a 23 69 66 64 65 66 20 4c 53 4d 5f 4c 4f 47 5f  .#ifdef LSM_LOG_
6030: 46 52 45 45 4c 49 53 54 0a 20 20 7b 0a 20 20 20  FREELIST.  {.   
6040: 20 6c 73 6d 4c 6f 67 4d 65 73 73 61 67 65 28 70   lsmLogMessage(p
6050: 44 62 2c 20 30 2c 20 22 6c 73 6d 42 6c 6f 63 6b  Db, 0, "lsmBlock
6060: 41 6c 6c 6f 63 61 74 65 28 29 3a 20 22 0a 20 20  Allocate(): ".  
6070: 20 20 20 20 20 20 22 73 6e 61 70 73 68 6f 74 2d        "snapshot-
6080: 69 6e 2d 75 73 65 3a 20 25 6c 6c 64 20 28 69 53  in-use: %lld (iS
6090: 79 6e 63 65 64 3d 25 6c 6c 64 29 20 28 63 6c 69  ynced=%lld) (cli
60a0: 65 6e 74 2d 69 64 3d 25 6c 6c 64 29 22 2c 20 0a  ent-id=%lld)", .
60b0: 20 20 20 20 20 20 20 20 69 49 6e 55 73 65 2c 20          iInUse, 
60c0: 69 53 79 6e 63 65 64 2c 20 28 70 44 62 2d 3e 69  iSynced, (pDb->i
60d0: 52 65 61 64 65 72 3e 3d 30 20 3f 20 70 44 62 2d  Reader>=0 ? pDb-
60e0: 3e 70 43 6c 69 65 6e 74 2d 3e 69 49 64 20 3a 20  >pClient->iId : 
60f0: 30 29 0a 20 20 20 20 29 3b 0a 20 20 7d 0a 23 65  0).    );.  }.#e
6100: 6e 64 69 66 0a 0a 0a 20 20 2f 2a 20 55 6e 6c 65  ndif...  /* Unle
6110: 73 73 20 74 68 65 72 65 20 65 78 69 73 74 73 20  ss there exists 
6120: 61 20 72 65 61 64 2d 6f 6e 6c 79 20 74 72 61 6e  a read-only tran
6130: 73 61 63 74 69 6f 6e 20 28 77 68 69 63 68 20 70  saction (which p
6140: 72 65 76 65 6e 74 73 20 75 73 20 66 72 6f 6d 0a  revents us from.
6150: 20 20 2a 2a 20 72 65 63 79 63 6c 69 6e 67 20 61    ** recycling a
6160: 6e 79 20 62 6c 6f 63 6b 73 20 72 65 67 61 72 64  ny blocks regard
6170: 6c 65 73 73 2c 20 71 75 65 72 79 20 74 68 65 20  less, query the 
6180: 66 72 65 65 20 62 6c 6f 63 6b 20 6c 69 73 74 20  free block list 
6190: 66 6f 72 20 61 20 0a 20 20 2a 2a 20 73 75 69 74  for a .  ** suit
61a0: 61 62 6c 65 20 62 6c 6f 63 6b 20 74 6f 20 72 65  able block to re
61b0: 75 73 65 2e 20 0a 20 20 2a 2a 0a 20 20 2a 2a 20  use. .  **.  ** 
61c0: 49 74 20 6d 69 67 68 74 20 73 65 65 6d 20 6d 6f  It might seem mo
61d0: 72 65 20 6e 61 74 75 72 61 6c 20 74 6f 20 63 68  re natural to ch
61e0: 65 63 6b 20 66 6f 72 20 61 20 72 65 61 64 2d 6f  eck for a read-o
61f0: 6e 6c 79 20 74 72 61 6e 73 61 63 74 69 6f 6e 20  nly transaction 
6200: 61 74 0a 20 20 2a 2a 20 74 68 65 20 73 74 61 72  at.  ** the star
6210: 74 20 6f 66 20 74 68 69 73 20 66 75 6e 63 74 69  t of this functi
6220: 6f 6e 2e 20 48 6f 77 65 76 65 72 2c 20 69 74 20  on. However, it 
6230: 69 73 20 62 65 74 74 65 72 20 64 6f 20 77 61 69  is better do wai
6240: 74 20 75 6e 74 69 6c 20 61 66 74 65 72 0a 20 20  t until after.  
6250: 2a 2a 20 74 68 65 20 63 61 6c 6c 20 74 6f 20 6c  ** the call to l
6260: 73 6d 43 68 65 63 6b 70 6f 69 6e 74 53 79 6e 63  smCheckpointSync
6270: 65 64 28 29 20 74 6f 20 64 6f 20 73 6f 2e 0a 20  ed() to do so.. 
6280: 20 2a 2f 0a 20 20 69 66 28 20 72 63 3d 3d 4c 53   */.  if( rc==LS
6290: 4d 5f 4f 4b 20 29 7b 0a 20 20 20 20 69 6e 74 20  M_OK ){.    int 
62a0: 62 52 6f 74 72 61 6e 73 3b 0a 20 20 20 20 72 63  bRotrans;.    rc
62b0: 20 3d 20 6c 73 6d 44 65 74 65 63 74 52 6f 54 72   = lsmDetectRoTr
62c0: 61 6e 73 28 70 44 62 2c 20 26 62 52 6f 74 72 61  ans(pDb, &bRotra
62d0: 6e 73 29 3b 0a 0a 20 20 20 20 69 66 28 20 72 63  ns);..    if( rc
62e0: 3d 3d 4c 53 4d 5f 4f 4b 20 26 26 20 62 52 6f 74  ==LSM_OK && bRot
62f0: 72 61 6e 73 3d 3d 30 20 29 7b 0a 20 20 20 20 20  rans==0 ){.     
6300: 20 72 63 20 3d 20 66 69 6e 64 46 72 65 65 62 6c   rc = findFreebl
6310: 6f 63 6b 28 70 44 62 2c 20 69 49 6e 55 73 65 2c  ock(pDb, iInUse,
6320: 20 28 69 42 65 66 6f 72 65 3e 30 29 2c 20 26 69   (iBefore>0), &i
6330: 52 65 74 29 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a  Ret);.    }.  }.
6340: 0a 20 20 69 66 28 20 69 42 65 66 6f 72 65 3e 30  .  if( iBefore>0
6350: 20 26 26 20 28 69 52 65 74 3c 3d 30 20 7c 7c 20   && (iRet<=0 || 
6360: 69 52 65 74 3e 3d 69 42 65 66 6f 72 65 29 20 29  iRet>=iBefore) )
6370: 7b 0a 20 20 20 20 69 52 65 74 20 3d 20 30 3b 0a  {.    iRet = 0;.
6380: 0a 20 20 7d 65 6c 73 65 20 69 66 28 20 72 63 3d  .  }else if( rc=
6390: 3d 4c 53 4d 5f 4f 4b 20 29 7b 0a 20 20 20 20 2f  =LSM_OK ){.    /
63a0: 2a 20 49 66 20 61 20 62 6c 6f 63 6b 20 77 61 73  * If a block was
63b0: 20 66 6f 75 6e 64 20 69 6e 20 74 68 65 20 66 72   found in the fr
63c0: 65 65 20 62 6c 6f 63 6b 20 6c 69 73 74 2c 20 75  ee block list, u
63d0: 73 65 20 69 74 20 61 6e 64 20 72 65 6d 6f 76 65  se it and remove
63e0: 20 69 74 20 66 72 6f 6d 20 0a 20 20 20 20 2a 2a   it from .    **
63f0: 20 74 68 65 20 6c 69 73 74 2e 20 4f 74 68 65 72   the list. Other
6400: 77 69 73 65 2c 20 69 66 20 6e 6f 20 73 75 69 74  wise, if no suit
6410: 61 62 6c 65 20 62 6c 6f 63 6b 20 77 61 73 20 66  able block was f
6420: 6f 75 6e 64 2c 20 61 6c 6c 6f 63 61 74 65 20 6f  ound, allocate o
6430: 6e 65 20 66 72 6f 6d 0a 20 20 20 20 2a 2a 20 74  ne from.    ** t
6440: 68 65 20 65 6e 64 20 6f 66 20 74 68 65 20 66 69  he end of the fi
6450: 6c 65 2e 20 20 2a 2f 0a 20 20 20 20 69 66 28 20  le.  */.    if( 
6460: 69 52 65 74 3e 30 20 29 7b 0a 23 69 66 64 65 66  iRet>0 ){.#ifdef
6470: 20 4c 53 4d 5f 4c 4f 47 5f 46 52 45 45 4c 49 53   LSM_LOG_FREELIS
6480: 54 0a 20 20 20 20 20 20 6c 73 6d 4c 6f 67 4d 65  T.      lsmLogMe
6490: 73 73 61 67 65 28 70 44 62 2c 20 30 2c 20 0a 20  ssage(pDb, 0, . 
64a0: 20 20 20 20 20 20 20 20 20 22 72 65 75 73 69 6e           "reusin
64b0: 67 20 62 6c 6f 63 6b 20 25 64 20 28 73 6e 61 70  g block %d (snap
64c0: 73 68 6f 74 2d 69 6e 2d 75 73 65 3d 25 6c 6c 64  shot-in-use=%lld
64d0: 29 22 2c 20 69 52 65 74 2c 20 69 49 6e 55 73 65  )", iRet, iInUse
64e0: 29 3b 0a 23 65 6e 64 69 66 0a 20 20 20 20 20 20  );.#endif.      
64f0: 72 63 20 3d 20 66 72 65 65 6c 69 73 74 41 70 70  rc = freelistApp
6500: 65 6e 64 28 70 44 62 2c 20 69 52 65 74 2c 20 2d  end(pDb, iRet, -
6510: 31 29 3b 0a 20 20 20 20 20 20 69 66 28 20 72 63  1);.      if( rc
6520: 3d 3d 4c 53 4d 5f 4f 4b 20 29 7b 0a 20 20 20 20  ==LSM_OK ){.    
6530: 20 20 20 20 72 63 20 3d 20 64 62 54 72 75 6e 63      rc = dbTrunc
6540: 61 74 65 28 70 44 62 2c 20 69 49 6e 55 73 65 29  ate(pDb, iInUse)
6550: 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 65  ;.      }.    }e
6560: 6c 73 65 7b 0a 20 20 20 20 20 20 69 52 65 74 20  lse{.      iRet 
6570: 3d 20 2b 2b 28 70 2d 3e 6e 42 6c 6f 63 6b 29 3b  = ++(p->nBlock);
6580: 0a 23 69 66 64 65 66 20 4c 53 4d 5f 4c 4f 47 5f  .#ifdef LSM_LOG_
6590: 46 52 45 45 4c 49 53 54 0a 20 20 20 20 20 20 6c  FREELIST.      l
65a0: 73 6d 4c 6f 67 4d 65 73 73 61 67 65 28 70 44 62  smLogMessage(pDb
65b0: 2c 20 30 2c 20 22 65 78 74 65 6e 64 69 6e 67 20  , 0, "extending 
65c0: 66 69 6c 65 20 74 6f 20 25 64 20 62 6c 6f 63 6b  file to %d block
65d0: 73 22 2c 20 69 52 65 74 29 3b 0a 23 65 6e 64 69  s", iRet);.#endi
65e0: 66 0a 20 20 20 20 7d 0a 20 20 7d 0a 0a 20 20 61  f.    }.  }..  a
65f0: 73 73 65 72 74 28 20 69 42 65 66 6f 72 65 3e 30  ssert( iBefore>0
6600: 20 7c 7c 20 69 52 65 74 3e 30 20 7c 7c 20 72 63   || iRet>0 || rc
6610: 21 3d 4c 53 4d 5f 4f 4b 20 29 3b 0a 20 20 2a 70  !=LSM_OK );.  *p
6620: 69 42 6c 6b 20 3d 20 69 52 65 74 3b 0a 20 20 72  iBlk = iRet;.  r
6630: 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 0a  eturn rc;.}../*.
6640: 2a 2a 20 46 72 65 65 20 61 20 64 61 74 61 62 61  ** Free a databa
6650: 73 65 20 62 6c 6f 63 6b 2e 20 54 68 65 20 77 6f  se block. The wo
6660: 72 6b 65 72 20 73 6e 61 70 73 68 6f 74 20 6d 75  rker snapshot mu
6670: 73 74 20 62 65 20 68 65 6c 64 20 69 6e 20 6f 72  st be held in or
6680: 64 65 72 20 74 6f 20 63 61 6c 6c 20 0a 2a 2a 20  der to call .** 
6690: 74 68 69 73 20 66 75 6e 63 74 69 6f 6e 2e 0a 2a  this function..*
66a0: 2a 0a 2a 2a 20 49 66 20 73 75 63 63 65 73 73 66  *.** If successf
66b0: 75 6c 2c 20 4c 53 4d 5f 4f 4b 20 69 73 20 72 65  ul, LSM_OK is re
66c0: 74 75 72 6e 65 64 2e 20 4f 74 68 65 72 77 69 73  turned. Otherwis
66d0: 65 2c 20 61 6e 20 6c 73 6d 20 65 72 72 6f 72 20  e, an lsm error 
66e0: 63 6f 64 65 20 28 65 2e 67 2e 20 0a 2a 2a 20 4c  code (e.g. .** L
66f0: 53 4d 5f 4e 4f 4d 45 4d 29 2e 0a 2a 2f 0a 69 6e  SM_NOMEM)..*/.in
6700: 74 20 6c 73 6d 42 6c 6f 63 6b 46 72 65 65 28 6c  t lsmBlockFree(l
6710: 73 6d 5f 64 62 20 2a 70 44 62 2c 20 69 6e 74 20  sm_db *pDb, int 
6720: 69 42 6c 6b 29 7b 0a 20 20 53 6e 61 70 73 68 6f  iBlk){.  Snapsho
6730: 74 20 2a 70 20 3d 20 70 44 62 2d 3e 70 57 6f 72  t *p = pDb->pWor
6740: 6b 65 72 3b 0a 20 20 61 73 73 65 72 74 28 20 6c  ker;.  assert( l
6750: 73 6d 53 68 6d 41 73 73 65 72 74 57 6f 72 6b 65  smShmAssertWorke
6760: 72 28 70 44 62 29 20 29 3b 0a 0a 23 69 66 64 65  r(pDb) );..#ifde
6770: 66 20 4c 53 4d 5f 4c 4f 47 5f 46 52 45 45 4c 49  f LSM_LOG_FREELI
6780: 53 54 0a 20 20 6c 73 6d 4c 6f 67 4d 65 73 73 61  ST.  lsmLogMessa
6790: 67 65 28 70 44 62 2c 20 4c 53 4d 5f 4f 4b 2c 20  ge(pDb, LSM_OK, 
67a0: 22 6c 73 6d 42 6c 6f 63 6b 46 72 65 65 28 29 3a  "lsmBlockFree():
67b0: 20 46 72 65 65 20 62 6c 6f 63 6b 20 25 64 22 2c   Free block %d",
67c0: 20 69 42 6c 6b 29 3b 0a 23 65 6e 64 69 66 0a 0a   iBlk);.#endif..
67d0: 20 20 72 65 74 75 72 6e 20 66 72 65 65 6c 69 73    return freelis
67e0: 74 41 70 70 65 6e 64 28 70 44 62 2c 20 69 42 6c  tAppend(pDb, iBl
67f0: 6b 2c 20 70 2d 3e 69 49 64 29 3b 0a 7d 0a 0a 2f  k, p->iId);.}../
6800: 2a 0a 2a 2a 20 52 65 66 72 65 65 20 61 20 64 61  *.** Refree a da
6810: 74 61 62 61 73 65 20 62 6c 6f 63 6b 2e 20 54 68  tabase block. Th
6820: 65 20 77 6f 72 6b 65 72 20 73 6e 61 70 73 68 6f  e worker snapsho
6830: 74 20 6d 75 73 74 20 62 65 20 68 65 6c 64 20 69  t must be held i
6840: 6e 20 6f 72 64 65 72 20 74 6f 20 63 61 6c 6c 20  n order to call 
6850: 0a 2a 2a 20 74 68 69 73 20 66 75 6e 63 74 69 6f  .** this functio
6860: 6e 2e 0a 2a 2a 0a 2a 2a 20 52 65 66 72 65 65 69  n..**.** Refreei
6870: 6e 67 20 69 73 20 72 65 71 75 69 72 65 64 20 77  ng is required w
6880: 68 65 6e 20 61 20 62 6c 6f 63 6b 20 69 73 20 61  hen a block is a
6890: 6c 6c 6f 63 61 74 65 64 20 75 73 69 6e 67 20 6c  llocated using l
68a0: 73 6d 42 6c 6f 63 6b 41 6c 6c 6f 63 61 74 65 28  smBlockAllocate(
68b0: 29 0a 2a 2a 20 62 75 74 20 74 68 65 6e 20 6e 6f  ).** but then no
68c0: 74 20 75 73 65 64 2e 20 54 68 69 73 20 66 75 6e  t used. This fun
68d0: 63 74 69 6f 6e 20 69 73 20 75 73 65 64 20 74 6f  ction is used to
68e0: 20 70 75 73 68 20 74 68 65 20 62 6c 6f 63 6b 20   push the block 
68f0: 62 61 63 6b 20 6f 6e 74 6f 0a 2a 2a 20 74 68 65  back onto.** the
6900: 20 66 72 65 65 6c 69 73 74 2e 20 52 65 66 72 65   freelist. Refre
6910: 65 69 6e 67 20 61 20 62 6c 6f 63 6b 20 69 73 20  eing a block is 
6920: 64 69 66 66 65 72 65 6e 74 20 66 72 6f 6d 20 66  different from f
6930: 72 65 65 69 6e 67 20 69 73 2c 20 61 73 20 61 20  reeing is, as a 
6940: 72 65 66 72 65 65 64 0a 2a 2a 20 62 6c 6f 63 6b  refreed.** block
6950: 20 6d 61 79 20 62 65 20 72 65 75 73 65 64 20 69   may be reused i
6960: 6d 6d 65 64 69 61 74 65 6c 79 2e 20 57 68 65 72  mmediately. Wher
6970: 65 61 73 20 61 20 66 72 65 65 64 20 62 6c 6f 63  eas a freed bloc
6980: 6b 20 63 61 6e 20 6e 6f 74 20 62 65 20 72 65 75  k can not be reu
6990: 73 65 64 20 0a 2a 2a 20 75 6e 74 69 6c 20 28 61  sed .** until (a
69a0: 74 20 6c 65 61 73 74 29 20 61 66 74 65 72 20 74  t least) after t
69b0: 68 65 20 6e 65 78 74 20 63 68 65 63 6b 70 6f 69  he next checkpoi
69c0: 6e 74 2e 0a 2a 2f 0a 69 6e 74 20 6c 73 6d 42 6c  nt..*/.int lsmBl
69d0: 6f 63 6b 52 65 66 72 65 65 28 6c 73 6d 5f 64 62  ockRefree(lsm_db
69e0: 20 2a 70 44 62 2c 20 69 6e 74 20 69 42 6c 6b 29   *pDb, int iBlk)
69f0: 7b 0a 20 20 69 6e 74 20 72 63 20 3d 20 4c 53 4d  {.  int rc = LSM
6a00: 5f 4f 4b 3b 20 20 20 20 20 20 20 20 20 20 20 20  _OK;            
6a10: 20 20 20 20 2f 2a 20 52 65 74 75 72 6e 20 63 6f      /* Return co
6a20: 64 65 20 2a 2f 0a 0a 23 69 66 64 65 66 20 4c 53  de */..#ifdef LS
6a30: 4d 5f 4c 4f 47 5f 46 52 45 45 4c 49 53 54 0a 20  M_LOG_FREELIST. 
6a40: 20 6c 73 6d 4c 6f 67 4d 65 73 73 61 67 65 28 70   lsmLogMessage(p
6a50: 44 62 2c 20 4c 53 4d 5f 4f 4b 2c 20 22 6c 73 6d  Db, LSM_OK, "lsm
6a60: 42 6c 6f 63 6b 52 65 66 72 65 65 28 29 3a 20 52  BlockRefree(): R
6a70: 65 66 72 65 65 20 62 6c 6f 63 6b 20 25 64 22 2c  efree block %d",
6a80: 20 69 42 6c 6b 29 3b 0a 23 65 6e 64 69 66 0a 0a   iBlk);.#endif..
6a90: 20 20 72 63 20 3d 20 66 72 65 65 6c 69 73 74 41    rc = freelistA
6aa0: 70 70 65 6e 64 28 70 44 62 2c 20 69 42 6c 6b 2c  ppend(pDb, iBlk,
6ab0: 20 30 29 3b 0a 20 20 72 65 74 75 72 6e 20 72 63   0);.  return rc
6ac0: 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 49 66 20 72 65  ;.}../*.** If re
6ad0: 71 75 69 72 65 64 2c 20 63 6f 70 79 20 61 20 64  quired, copy a d
6ae0: 61 74 61 62 61 73 65 20 63 68 65 63 6b 70 6f 69  atabase checkpoi
6af0: 6e 74 20 66 72 6f 6d 20 73 68 61 72 65 64 20 6d  nt from shared m
6b00: 65 6d 6f 72 79 20 69 6e 74 6f 20 74 68 65 0a 2a  emory into the.*
6b10: 2a 20 64 61 74 61 62 61 73 65 20 69 74 73 65 6c  * database itsel
6b20: 66 2e 0a 2a 2a 0a 2a 2a 20 54 68 65 20 57 4f 52  f..**.** The WOR
6b30: 4b 45 52 20 6c 6f 63 6b 20 6d 75 73 74 20 6e 6f  KER lock must no
6b40: 74 20 62 65 20 68 65 6c 64 20 77 68 65 6e 20 74  t be held when t
6b50: 68 69 73 20 69 73 20 63 61 6c 6c 65 64 2e 20 54  his is called. T
6b60: 68 69 73 20 69 73 20 62 65 63 61 75 73 65 0a 2a  his is because.*
6b70: 2a 20 74 68 69 73 20 66 75 6e 63 74 69 6f 6e 20  * this function 
6b80: 6d 61 79 20 69 6e 64 69 72 65 63 74 6c 79 20 63  may indirectly c
6b90: 61 6c 6c 20 66 73 79 6e 63 28 29 2e 20 41 6e 64  all fsync(). And
6ba0: 20 74 68 65 20 57 4f 52 4b 45 52 20 6c 6f 63 6b   the WORKER lock
6bb0: 20 73 68 6f 75 6c 64 0a 2a 2a 20 6e 6f 74 20 62   should.** not b
6bc0: 65 20 68 65 6c 64 20 74 68 61 74 20 6c 6f 6e 67  e held that long
6bd0: 20 28 69 6e 20 63 61 73 65 20 69 74 20 69 73 20   (in case it is 
6be0: 72 65 71 75 69 72 65 64 20 62 79 20 61 20 63 6c  required by a cl
6bf0: 69 65 6e 74 20 66 6c 75 73 68 69 6e 67 20 61 6e  ient flushing an
6c00: 0a 2a 2a 20 69 6e 2d 6d 65 6d 6f 72 79 20 74 72  .** in-memory tr
6c10: 65 65 20 74 6f 20 64 69 73 6b 29 2e 0a 2a 2f 0a  ee to disk)..*/.
6c20: 69 6e 74 20 6c 73 6d 43 68 65 63 6b 70 6f 69 6e  int lsmCheckpoin
6c30: 74 57 72 69 74 65 28 6c 73 6d 5f 64 62 20 2a 70  tWrite(lsm_db *p
6c40: 44 62 2c 20 75 33 32 20 2a 70 6e 57 72 69 74 65  Db, u32 *pnWrite
6c50: 29 7b 0a 20 20 69 6e 74 20 72 63 3b 20 20 20 20  ){.  int rc;    
6c60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6c70: 20 20 20 20 20 2f 2a 20 52 65 74 75 72 6e 20 43       /* Return C
6c80: 6f 64 65 20 2a 2f 0a 20 20 75 33 32 20 6e 57 72  ode */.  u32 nWr
6c90: 69 74 65 20 3d 20 30 3b 0a 0a 20 20 61 73 73 65  ite = 0;..  asse
6ca0: 72 74 28 20 70 44 62 2d 3e 70 57 6f 72 6b 65 72  rt( pDb->pWorker
6cb0: 3d 3d 30 20 29 3b 0a 20 20 61 73 73 65 72 74 28  ==0 );.  assert(
6cc0: 20 31 20 7c 7c 20 70 44 62 2d 3e 70 43 6c 69 65   1 || pDb->pClie
6cd0: 6e 74 3d 3d 30 20 29 3b 0a 20 20 61 73 73 65 72  nt==0 );.  asser
6ce0: 74 28 20 6c 73 6d 53 68 6d 41 73 73 65 72 74 4c  t( lsmShmAssertL
6cf0: 6f 63 6b 28 70 44 62 2c 20 4c 53 4d 5f 4c 4f 43  ock(pDb, LSM_LOC
6d00: 4b 5f 57 4f 52 4b 45 52 2c 20 4c 53 4d 5f 4c 4f  K_WORKER, LSM_LO
6d10: 43 4b 5f 55 4e 4c 4f 43 4b 29 20 29 3b 0a 0a 20  CK_UNLOCK) );.. 
6d20: 20 72 63 20 3d 20 6c 73 6d 53 68 6d 4c 6f 63 6b   rc = lsmShmLock
6d30: 28 70 44 62 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 43  (pDb, LSM_LOCK_C
6d40: 48 45 43 4b 50 4f 49 4e 54 45 52 2c 20 4c 53 4d  HECKPOINTER, LSM
6d50: 5f 4c 4f 43 4b 5f 45 58 43 4c 2c 20 30 29 3b 0a  _LOCK_EXCL, 0);.
6d60: 20 20 69 66 28 20 72 63 21 3d 4c 53 4d 5f 4f 4b    if( rc!=LSM_OK
6d70: 20 29 20 72 65 74 75 72 6e 20 72 63 3b 0a 0a 20   ) return rc;.. 
6d80: 20 72 63 20 3d 20 6c 73 6d 43 68 65 63 6b 70 6f   rc = lsmCheckpo
6d90: 69 6e 74 4c 6f 61 64 28 70 44 62 2c 20 30 29 3b  intLoad(pDb, 0);
6da0: 0a 20 20 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f  .  if( rc==LSM_O
6db0: 4b 20 29 7b 0a 20 20 20 20 69 6e 74 20 6e 42 6c  K ){.    int nBl
6dc0: 6f 63 6b 20 3d 20 6c 73 6d 43 68 65 63 6b 70 6f  ock = lsmCheckpo
6dd0: 69 6e 74 4e 42 6c 6f 63 6b 28 70 44 62 2d 3e 61  intNBlock(pDb->a
6de0: 53 6e 61 70 73 68 6f 74 29 3b 0a 20 20 20 20 53  Snapshot);.    S
6df0: 68 6d 48 65 61 64 65 72 20 2a 70 53 68 6d 20 3d  hmHeader *pShm =
6e00: 20 70 44 62 2d 3e 70 53 68 6d 68 64 72 3b 0a 20   pDb->pShmhdr;. 
6e10: 20 20 20 69 6e 74 20 62 44 6f 6e 65 20 3d 20 30     int bDone = 0
6e20: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ;               
6e30: 20 2f 2a 20 54 72 75 65 20 69 66 20 63 68 65 63   /* True if chec
6e40: 6b 70 6f 69 6e 74 20 69 73 20 61 6c 72 65 61 64  kpoint is alread
6e50: 79 20 73 74 6f 72 65 64 20 2a 2f 0a 0a 20 20 20  y stored */..   
6e60: 20 2f 2a 20 43 68 65 63 6b 20 69 66 20 74 68 69   /* Check if thi
6e70: 73 20 63 68 65 63 6b 70 6f 69 6e 74 20 68 61 73  s checkpoint has
6e80: 20 61 6c 72 65 61 64 79 20 62 65 65 6e 20 77 72   already been wr
6e90: 69 74 74 65 6e 20 74 6f 20 74 68 65 20 64 61 74  itten to the dat
6ea0: 61 62 61 73 65 0a 20 20 20 20 2a 2a 20 66 69 6c  abase.    ** fil
6eb0: 65 2e 20 49 66 20 73 6f 2c 20 73 65 74 20 76 61  e. If so, set va
6ec0: 72 69 61 62 6c 65 20 62 44 6f 6e 65 20 74 6f 20  riable bDone to 
6ed0: 74 72 75 65 2e 20 20 2a 2f 0a 20 20 20 20 69 66  true.  */.    if
6ee0: 28 20 70 53 68 6d 2d 3e 69 4d 65 74 61 50 61 67  ( pShm->iMetaPag
6ef0: 65 20 29 7b 0a 20 20 20 20 20 20 4d 65 74 61 50  e ){.      MetaP
6f00: 61 67 65 20 2a 70 50 67 3b 20 20 20 20 20 20 20  age *pPg;       
6f10: 20 20 20 20 20 20 20 2f 2a 20 4d 65 74 61 20 70         /* Meta p
6f20: 61 67 65 20 2a 2f 0a 20 20 20 20 20 20 75 38 20  age */.      u8 
6f30: 2a 61 44 61 74 61 3b 20 20 20 20 20 20 20 20 20  *aData;         
6f40: 20 20 20 20 20 20 20 20 20 2f 2a 20 4d 65 74 61           /* Meta
6f50: 2d 70 61 67 65 20 64 61 74 61 20 62 75 66 66 65  -page data buffe
6f60: 72 20 2a 2f 0a 20 20 20 20 20 20 69 6e 74 20 6e  r */.      int n
6f70: 44 61 74 61 3b 20 20 20 20 20 20 20 20 20 20 20  Data;           
6f80: 20 20 20 20 20 20 20 2f 2a 20 53 69 7a 65 20 6f         /* Size o
6f90: 66 20 61 44 61 74 61 5b 5d 20 69 6e 20 62 79 74  f aData[] in byt
6fa0: 65 73 20 2a 2f 0a 20 20 20 20 20 20 69 36 34 20  es */.      i64 
6fb0: 69 43 6b 70 74 3b 20 20 20 20 20 20 20 20 20 20  iCkpt;          
6fc0: 20 20 20 20 20 20 20 20 2f 2a 20 49 64 20 6f 66          /* Id of
6fd0: 20 63 68 65 63 6b 70 6f 69 6e 74 20 6a 75 73 74   checkpoint just
6fe0: 20 6c 6f 61 64 65 64 20 2a 2f 0a 20 20 20 20 20   loaded */.     
6ff0: 20 69 36 34 20 69 44 69 73 6b 20 3d 20 30 3b 20   i64 iDisk = 0; 
7000: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
7010: 49 64 20 6f 66 20 63 68 65 63 6b 70 6f 69 6e 74  Id of checkpoint
7020: 20 61 6c 72 65 61 64 79 20 73 74 6f 72 65 64 20   already stored 
7030: 69 6e 20 64 62 20 2a 2f 0a 20 20 20 20 20 20 69  in db */.      i
7040: 43 6b 70 74 20 3d 20 6c 73 6d 43 68 65 63 6b 70  Ckpt = lsmCheckp
7050: 6f 69 6e 74 49 64 28 70 44 62 2d 3e 61 53 6e 61  ointId(pDb->aSna
7060: 70 73 68 6f 74 2c 20 30 29 3b 0a 20 20 20 20 20  pshot, 0);.     
7070: 20 72 63 20 3d 20 6c 73 6d 46 73 4d 65 74 61 50   rc = lsmFsMetaP
7080: 61 67 65 47 65 74 28 70 44 62 2d 3e 70 46 53 2c  ageGet(pDb->pFS,
7090: 20 30 2c 20 70 53 68 6d 2d 3e 69 4d 65 74 61 50   0, pShm->iMetaP
70a0: 61 67 65 2c 20 26 70 50 67 29 3b 0a 20 20 20 20  age, &pPg);.    
70b0: 20 20 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b    if( rc==LSM_OK
70c0: 20 29 7b 0a 20 20 20 20 20 20 20 20 61 44 61 74   ){.        aDat
70d0: 61 20 3d 20 6c 73 6d 46 73 4d 65 74 61 50 61 67  a = lsmFsMetaPag
70e0: 65 44 61 74 61 28 70 50 67 2c 20 26 6e 44 61 74  eData(pPg, &nDat
70f0: 61 29 3b 0a 20 20 20 20 20 20 20 20 69 44 69 73  a);.        iDis
7100: 6b 20 3d 20 6c 73 6d 43 68 65 63 6b 70 6f 69 6e  k = lsmCheckpoin
7110: 74 49 64 28 28 75 33 32 20 2a 29 61 44 61 74 61  tId((u32 *)aData
7120: 2c 20 31 29 3b 0a 20 20 20 20 20 20 20 20 6e 57  , 1);.        nW
7130: 72 69 74 65 20 3d 20 6c 73 6d 43 68 65 63 6b 70  rite = lsmCheckp
7140: 6f 69 6e 74 4e 57 72 69 74 65 28 28 75 33 32 20  ointNWrite((u32 
7150: 2a 29 61 44 61 74 61 2c 20 31 29 3b 0a 20 20 20  *)aData, 1);.   
7160: 20 20 20 20 20 6c 73 6d 46 73 4d 65 74 61 50 61       lsmFsMetaPa
7170: 67 65 52 65 6c 65 61 73 65 28 70 50 67 29 3b 0a  geRelease(pPg);.
7180: 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 62 44        }.      bD
7190: 6f 6e 65 20 3d 20 28 69 44 69 73 6b 3e 3d 69 43  one = (iDisk>=iC
71a0: 6b 70 74 29 3b 0a 20 20 20 20 7d 0a 0a 20 20 20  kpt);.    }..   
71b0: 20 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20   if( rc==LSM_OK 
71c0: 26 26 20 62 44 6f 6e 65 3d 3d 30 20 29 7b 0a 20  && bDone==0 ){. 
71d0: 20 20 20 20 20 69 6e 74 20 69 4d 65 74 61 20 3d       int iMeta =
71e0: 20 28 70 53 68 6d 2d 3e 69 4d 65 74 61 50 61 67   (pShm->iMetaPag
71f0: 65 20 25 20 32 29 20 2b 20 31 3b 0a 20 20 20 20  e % 2) + 1;.    
7200: 20 20 69 66 28 20 70 44 62 2d 3e 65 53 61 66 65    if( pDb->eSafe
7210: 74 79 21 3d 4c 53 4d 5f 53 41 46 45 54 59 5f 4f  ty!=LSM_SAFETY_O
7220: 46 46 20 29 7b 0a 20 20 20 20 20 20 20 20 72 63  FF ){.        rc
7230: 20 3d 20 6c 73 6d 46 73 53 79 6e 63 44 62 28 70   = lsmFsSyncDb(p
7240: 44 62 2d 3e 70 46 53 2c 20 6e 42 6c 6f 63 6b 29  Db->pFS, nBlock)
7250: 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20  ;.      }.      
7260: 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 29  if( rc==LSM_OK )
7270: 20 72 63 20 3d 20 6c 73 6d 43 68 65 63 6b 70 6f   rc = lsmCheckpo
7280: 69 6e 74 53 74 6f 72 65 28 70 44 62 2c 20 69 4d  intStore(pDb, iM
7290: 65 74 61 29 3b 0a 20 20 20 20 20 20 69 66 28 20  eta);.      if( 
72a0: 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 26 26 20 70 44  rc==LSM_OK && pD
72b0: 62 2d 3e 65 53 61 66 65 74 79 21 3d 4c 53 4d 5f  b->eSafety!=LSM_
72c0: 53 41 46 45 54 59 5f 4f 46 46 29 7b 0a 20 20 20  SAFETY_OFF){.   
72d0: 20 20 20 20 20 72 63 20 3d 20 6c 73 6d 46 73 53       rc = lsmFsS
72e0: 79 6e 63 44 62 28 70 44 62 2d 3e 70 46 53 2c 20  yncDb(pDb->pFS, 
72f0: 30 29 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20 20  0);.      }.    
7300: 20 20 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b    if( rc==LSM_OK
7310: 20 29 7b 0a 20 20 20 20 20 20 20 20 70 53 68 6d   ){.        pShm
7320: 2d 3e 69 4d 65 74 61 50 61 67 65 20 3d 20 69 4d  ->iMetaPage = iM
7330: 65 74 61 3b 0a 20 20 20 20 20 20 20 20 6e 57 72  eta;.        nWr
7340: 69 74 65 20 3d 20 6c 73 6d 43 68 65 63 6b 70 6f  ite = lsmCheckpo
7350: 69 6e 74 4e 57 72 69 74 65 28 70 44 62 2d 3e 61  intNWrite(pDb->a
7360: 53 6e 61 70 73 68 6f 74 2c 20 30 29 20 2d 20 6e  Snapshot, 0) - n
7370: 57 72 69 74 65 3b 0a 20 20 20 20 20 20 7d 0a 23  Write;.      }.#
7380: 69 66 64 65 66 20 4c 53 4d 5f 4c 4f 47 5f 57 4f  ifdef LSM_LOG_WO
7390: 52 4b 0a 20 20 20 20 20 20 6c 73 6d 4c 6f 67 4d  RK.      lsmLogM
73a0: 65 73 73 61 67 65 28 70 44 62 2c 20 30 2c 20 22  essage(pDb, 0, "
73b0: 66 69 6e 69 73 68 20 63 68 65 63 6b 70 6f 69 6e  finish checkpoin
73c0: 74 20 25 64 22 2c 20 0a 20 20 20 20 20 20 20 20  t %d", .        
73d0: 20 20 28 69 6e 74 29 6c 73 6d 43 68 65 63 6b 70    (int)lsmCheckp
73e0: 6f 69 6e 74 49 64 28 70 44 62 2d 3e 61 53 6e 61  ointId(pDb->aSna
73f0: 70 73 68 6f 74 2c 20 30 29 0a 20 20 20 20 20 20  pshot, 0).      
7400: 29 3b 0a 23 65 6e 64 69 66 0a 20 20 20 20 7d 0a  );.#endif.    }.
7410: 20 20 7d 0a 0a 20 20 6c 73 6d 53 68 6d 4c 6f 63    }..  lsmShmLoc
7420: 6b 28 70 44 62 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f  k(pDb, LSM_LOCK_
7430: 43 48 45 43 4b 50 4f 49 4e 54 45 52 2c 20 4c 53  CHECKPOINTER, LS
7440: 4d 5f 4c 4f 43 4b 5f 55 4e 4c 4f 43 4b 2c 20 30  M_LOCK_UNLOCK, 0
7450: 29 3b 0a 20 20 69 66 28 20 70 6e 57 72 69 74 65  );.  if( pnWrite
7460: 20 26 26 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 29   && rc==LSM_OK )
7470: 20 2a 70 6e 57 72 69 74 65 20 3d 20 6e 57 72 69   *pnWrite = nWri
7480: 74 65 3b 0a 20 20 72 65 74 75 72 6e 20 72 63 3b  te;.  return rc;
7490: 0a 7d 0a 0a 69 6e 74 20 6c 73 6d 42 65 67 69 6e  .}..int lsmBegin
74a0: 57 6f 72 6b 28 6c 73 6d 5f 64 62 20 2a 70 44 62  Work(lsm_db *pDb
74b0: 29 7b 0a 20 20 69 6e 74 20 72 63 3b 0a 0a 20 20  ){.  int rc;..  
74c0: 2f 2a 20 41 74 74 65 6d 70 74 20 74 6f 20 74 61  /* Attempt to ta
74d0: 6b 65 20 74 68 65 20 57 4f 52 4b 45 52 20 6c 6f  ke the WORKER lo
74e0: 63 6b 20 2a 2f 0a 20 20 72 63 20 3d 20 6c 73 6d  ck */.  rc = lsm
74f0: 53 68 6d 4c 6f 63 6b 28 70 44 62 2c 20 4c 53 4d  ShmLock(pDb, LSM
7500: 5f 4c 4f 43 4b 5f 57 4f 52 4b 45 52 2c 20 4c 53  _LOCK_WORKER, LS
7510: 4d 5f 4c 4f 43 4b 5f 45 58 43 4c 2c 20 30 29 3b  M_LOCK_EXCL, 0);
7520: 0a 0a 20 20 2f 2a 20 44 65 73 65 72 69 61 6c 69  ..  /* Deseriali
7530: 7a 65 20 74 68 65 20 63 75 72 72 65 6e 74 20 77  ze the current w
7540: 6f 72 6b 65 72 20 73 6e 61 70 73 68 6f 74 20 2a  orker snapshot *
7550: 2f 0a 20 20 69 66 28 20 72 63 3d 3d 4c 53 4d 5f  /.  if( rc==LSM_
7560: 4f 4b 20 29 7b 0a 20 20 20 20 72 63 20 3d 20 6c  OK ){.    rc = l
7570: 73 6d 43 68 65 63 6b 70 6f 69 6e 74 4c 6f 61 64  smCheckpointLoad
7580: 57 6f 72 6b 65 72 28 70 44 62 29 3b 0a 20 20 7d  Worker(pDb);.  }
7590: 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a  .  return rc;.}.
75a0: 0a 76 6f 69 64 20 6c 73 6d 46 72 65 65 53 6e 61  .void lsmFreeSna
75b0: 70 73 68 6f 74 28 6c 73 6d 5f 65 6e 76 20 2a 70  pshot(lsm_env *p
75c0: 45 6e 76 2c 20 53 6e 61 70 73 68 6f 74 20 2a 70  Env, Snapshot *p
75d0: 29 7b 0a 20 20 69 66 28 20 70 20 29 7b 0a 20 20  ){.  if( p ){.  
75e0: 20 20 6c 73 6d 53 6f 72 74 65 64 46 72 65 65 4c    lsmSortedFreeL
75f0: 65 76 65 6c 28 70 45 6e 76 2c 20 70 2d 3e 70 4c  evel(pEnv, p->pL
7600: 65 76 65 6c 29 3b 0a 20 20 20 20 6c 73 6d 46 72  evel);.    lsmFr
7610: 65 65 28 70 45 6e 76 2c 20 70 2d 3e 66 72 65 65  ee(pEnv, p->free
7620: 6c 69 73 74 2e 61 45 6e 74 72 79 29 3b 0a 20 20  list.aEntry);.  
7630: 20 20 6c 73 6d 46 72 65 65 28 70 45 6e 76 2c 20    lsmFree(pEnv, 
7640: 70 2d 3e 72 65 64 69 72 65 63 74 2e 61 29 3b 0a  p->redirect.a);.
7650: 20 20 20 20 6c 73 6d 46 72 65 65 28 70 45 6e 76      lsmFree(pEnv
7660: 2c 20 70 29 3b 0a 20 20 7d 0a 7d 0a 0a 2f 2a 0a  , p);.  }.}../*.
7670: 2a 2a 20 41 74 74 65 6d 70 74 20 74 6f 20 70 6f  ** Attempt to po
7680: 70 75 6c 61 74 65 20 6f 6e 65 20 6f 66 20 74 68  pulate one of th
7690: 65 20 72 65 61 64 2d 6c 6f 63 6b 20 73 6c 6f 74  e read-lock slot
76a0: 73 20 74 6f 20 63 6f 6e 74 61 69 6e 20 6c 6f 63  s to contain loc
76b0: 6b 20 76 61 6c 75 65 73 0a 2a 2a 20 69 4c 73 6d  k values.** iLsm
76c0: 2f 69 53 68 6d 2e 20 4f 72 2c 20 69 66 20 73 75  /iShm. Or, if su
76d0: 63 68 20 61 20 73 6c 6f 74 20 65 78 69 73 74 73  ch a slot exists
76e0: 20 61 6c 72 65 61 64 79 2c 20 74 68 69 73 20 66   already, this f
76f0: 75 6e 63 74 69 6f 6e 20 69 73 20 61 20 6e 6f 2d  unction is a no-
7700: 6f 70 2e 0a 2a 2a 0a 2a 2a 20 49 74 20 69 73 20  op..**.** It is 
7710: 6e 6f 74 20 61 6e 20 65 72 72 6f 72 20 69 66 20  not an error if 
7720: 6e 6f 20 73 6c 6f 74 20 63 61 6e 20 62 65 20 70  no slot can be p
7730: 6f 70 75 6c 61 74 65 64 20 62 65 63 61 75 73 65  opulated because
7740: 20 74 68 65 20 77 72 69 74 65 2d 6c 6f 63 6b 0a   the write-lock.
7750: 2a 2a 20 63 61 6e 6e 6f 74 20 62 65 20 6f 62 74  ** cannot be obt
7760: 61 69 6e 65 64 2e 20 49 66 20 61 6e 79 20 6f 74  ained. If any ot
7770: 68 65 72 20 65 72 72 6f 72 20 6f 63 63 75 72 73  her error occurs
7780: 2c 20 72 65 74 75 72 6e 20 61 6e 20 4c 53 4d 20  , return an LSM 
7790: 65 72 72 6f 72 20 63 6f 64 65 2e 0a 2a 2a 20 4f  error code..** O
77a0: 74 68 65 72 77 69 73 65 2c 20 4c 53 4d 5f 4f 4b  therwise, LSM_OK
77b0: 2e 0a 2a 2a 0a 2a 2a 20 54 68 69 73 20 66 75 6e  ..**.** This fun
77c0: 63 74 69 6f 6e 20 69 73 20 63 61 6c 6c 65 64 20  ction is called 
77d0: 61 74 20 76 61 72 69 6f 75 73 20 70 6f 69 6e 74  at various point
77e0: 73 20 74 6f 20 74 72 79 20 74 6f 20 65 6e 73 75  s to try to ensu
77f0: 72 65 20 74 68 61 74 20 74 68 65 72 65 0a 2a 2a  re that there.**
7800: 20 61 6c 77 61 79 73 20 65 78 69 73 74 73 20 61   always exists a
7810: 74 20 6c 65 61 73 74 20 6f 6e 65 20 72 65 61 64  t least one read
7820: 2d 6c 6f 63 6b 20 73 6c 6f 74 20 74 68 61 74 20  -lock slot that 
7830: 63 61 6e 20 62 65 20 75 73 65 64 20 62 79 20 61  can be used by a
7840: 20 72 65 61 64 2d 6f 6e 6c 79 0a 2a 2a 20 63 6c   read-only.** cl
7850: 69 65 6e 74 2e 20 41 6e 64 20 73 6f 20 74 68 61  ient. And so tha
7860: 74 2c 20 69 6e 20 74 68 65 20 75 73 75 61 6c 20  t, in the usual 
7870: 63 61 73 65 2c 20 74 68 65 72 65 20 69 73 20 61  case, there is a
7880: 6e 20 22 65 78 61 63 74 20 6d 61 74 63 68 22 20  n "exact match" 
7890: 61 76 61 69 6c 61 62 6c 65 0a 2a 2a 20 77 68 65  available.** whe
78a0: 6e 65 76 65 72 20 61 20 72 65 61 64 20 74 72 61  never a read tra
78b0: 6e 73 61 63 74 69 6f 6e 20 69 73 20 6f 70 65 6e  nsaction is open
78c0: 65 64 20 62 79 20 61 6e 79 20 63 6c 69 65 6e 74  ed by any client
78d0: 2e 20 41 74 20 70 72 65 73 65 6e 74 20 74 68 69  . At present thi
78e0: 73 0a 2a 2a 20 66 75 6e 63 74 69 6f 6e 20 69 73  s.** function is
78f0: 20 63 61 6c 6c 65 64 20 77 68 65 6e 3a 0a 2a 2a   called when:.**
7900: 0a 2a 2a 20 20 20 20 2a 20 41 20 77 72 69 74 65  .**    * A write
7910: 20 74 72 61 6e 73 61 63 74 69 6f 6e 20 74 68 61   transaction tha
7920: 74 20 63 61 6c 6c 65 64 20 6c 73 6d 54 72 65 65  t called lsmTree
7930: 44 69 73 63 61 72 64 4f 6c 64 28 29 20 69 73 20  DiscardOld() is 
7940: 63 6f 6d 6d 69 74 74 65 64 2c 20 61 6e 64 0a 2a  committed, and.*
7950: 2a 20 20 20 20 2a 20 57 68 65 6e 65 76 65 72 20  *    * Whenever 
7960: 74 68 65 20 77 6f 72 6b 69 6e 67 20 73 6e 61 70  the working snap
7970: 73 68 6f 74 20 69 73 20 75 70 64 61 74 65 64 20  shot is updated 
7980: 28 69 2e 65 2e 20 6c 73 6d 46 69 6e 69 73 68 57  (i.e. lsmFinishW
7990: 6f 72 6b 28 29 29 2e 0a 2a 2f 0a 73 74 61 74 69  ork())..*/.stati
79a0: 63 20 69 6e 74 20 64 62 53 65 74 52 65 61 64 4c  c int dbSetReadL
79b0: 6f 63 6b 28 6c 73 6d 5f 64 62 20 2a 64 62 2c 20  ock(lsm_db *db, 
79c0: 69 36 34 20 69 4c 73 6d 2c 20 75 33 32 20 69 53  i64 iLsm, u32 iS
79d0: 68 6d 29 7b 0a 20 20 69 6e 74 20 72 63 20 3d 20  hm){.  int rc = 
79e0: 4c 53 4d 5f 4f 4b 3b 0a 20 20 53 68 6d 48 65 61  LSM_OK;.  ShmHea
79f0: 64 65 72 20 2a 70 53 68 6d 20 3d 20 64 62 2d 3e  der *pShm = db->
7a00: 70 53 68 6d 68 64 72 3b 0a 20 20 69 6e 74 20 69  pShmhdr;.  int i
7a10: 3b 0a 0a 20 20 2f 2a 20 43 68 65 63 6b 20 69 66  ;..  /* Check if
7a20: 20 74 68 65 72 65 20 69 73 20 61 6c 72 65 61 64   there is alread
7a30: 79 20 61 20 73 6c 6f 74 20 63 6f 6e 74 61 69 6e  y a slot contain
7a40: 69 6e 67 20 74 68 65 20 72 65 71 75 69 72 65 64  ing the required
7a50: 20 76 61 6c 75 65 73 2e 20 2a 2f 0a 20 20 66 6f   values. */.  fo
7a60: 72 28 69 3d 30 3b 20 69 3c 4c 53 4d 5f 4c 4f 43  r(i=0; i<LSM_LOC
7a70: 4b 5f 4e 52 45 41 44 45 52 3b 20 69 2b 2b 29 7b  K_NREADER; i++){
7a80: 0a 20 20 20 20 53 68 6d 52 65 61 64 65 72 20 2a  .    ShmReader *
7a90: 70 20 3d 20 26 70 53 68 6d 2d 3e 61 52 65 61 64  p = &pShm->aRead
7aa0: 65 72 5b 69 5d 3b 0a 20 20 20 20 69 66 28 20 70  er[i];.    if( p
7ab0: 2d 3e 69 4c 73 6d 49 64 3d 3d 69 4c 73 6d 20 26  ->iLsmId==iLsm &
7ac0: 26 20 70 2d 3e 69 54 72 65 65 49 64 3d 3d 69 53  & p->iTreeId==iS
7ad0: 68 6d 20 29 20 72 65 74 75 72 6e 20 4c 53 4d 5f  hm ) return LSM_
7ae0: 4f 4b 3b 0a 20 20 7d 0a 0a 20 20 2f 2a 20 49 74  OK;.  }..  /* It
7af0: 65 72 61 74 65 20 74 68 72 6f 75 67 68 20 61 6c  erate through al
7b00: 6c 20 72 65 61 64 2d 6c 6f 63 6b 20 73 6c 6f 74  l read-lock slot
7b10: 73 2c 20 61 74 74 65 6d 70 74 69 6e 67 20 74 6f  s, attempting to
7b20: 20 74 61 6b 65 20 61 20 77 72 69 74 65 2d 6c 6f   take a write-lo
7b30: 63 6b 0a 20 20 2a 2a 20 6f 6e 20 65 61 63 68 20  ck.  ** on each 
7b40: 6f 66 20 74 68 65 6d 2e 20 49 66 20 61 20 77 72  of them. If a wr
7b50: 69 74 65 2d 6c 6f 63 6b 20 73 75 63 63 65 65 64  ite-lock succeed
7b60: 73 2c 20 70 6f 70 75 6c 61 74 65 20 74 68 65 20  s, populate the 
7b70: 6c 6f 63 6b 65 64 20 73 6c 6f 74 0a 20 20 2a 2a  locked slot.  **
7b80: 20 77 69 74 68 20 74 68 65 20 72 65 71 75 69 72   with the requir
7b90: 65 64 20 76 61 6c 75 65 73 20 61 6e 64 20 62 72  ed values and br
7ba0: 65 61 6b 20 6f 75 74 20 6f 66 20 74 68 65 20 6c  eak out of the l
7bb0: 6f 6f 70 2e 20 20 2a 2f 0a 20 20 66 6f 72 28 69  oop.  */.  for(i
7bc0: 3d 30 3b 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 26  =0; rc==LSM_OK &
7bd0: 26 20 69 3c 4c 53 4d 5f 4c 4f 43 4b 5f 4e 52 45  & i<LSM_LOCK_NRE
7be0: 41 44 45 52 3b 20 69 2b 2b 29 7b 0a 20 20 20 20  ADER; i++){.    
7bf0: 72 63 20 3d 20 6c 73 6d 53 68 6d 4c 6f 63 6b 28  rc = lsmShmLock(
7c00: 64 62 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 52 45 41  db, LSM_LOCK_REA
7c10: 44 45 52 28 69 29 2c 20 4c 53 4d 5f 4c 4f 43 4b  DER(i), LSM_LOCK
7c20: 5f 45 58 43 4c 2c 20 30 29 3b 0a 20 20 20 20 69  _EXCL, 0);.    i
7c30: 66 28 20 72 63 3d 3d 4c 53 4d 5f 42 55 53 59 20  f( rc==LSM_BUSY 
7c40: 29 7b 0a 20 20 20 20 20 20 72 63 20 3d 20 4c 53  ){.      rc = LS
7c50: 4d 5f 4f 4b 3b 0a 20 20 20 20 7d 65 6c 73 65 7b  M_OK;.    }else{
7c60: 0a 20 20 20 20 20 20 53 68 6d 52 65 61 64 65 72  .      ShmReader
7c70: 20 2a 70 20 3d 20 26 70 53 68 6d 2d 3e 61 52 65   *p = &pShm->aRe
7c80: 61 64 65 72 5b 69 5d 3b 0a 20 20 20 20 20 20 70  ader[i];.      p
7c90: 2d 3e 69 4c 73 6d 49 64 20 3d 20 69 4c 73 6d 3b  ->iLsmId = iLsm;
7ca0: 0a 20 20 20 20 20 20 70 2d 3e 69 54 72 65 65 49  .      p->iTreeI
7cb0: 64 20 3d 20 69 53 68 6d 3b 0a 20 20 20 20 20 20  d = iShm;.      
7cc0: 6c 73 6d 53 68 6d 4c 6f 63 6b 28 64 62 2c 20 4c  lsmShmLock(db, L
7cd0: 53 4d 5f 4c 4f 43 4b 5f 52 45 41 44 45 52 28 69  SM_LOCK_READER(i
7ce0: 29 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 55 4e 4c 4f  ), LSM_LOCK_UNLO
7cf0: 43 4b 2c 20 30 29 3b 0a 20 20 20 20 20 20 62 72  CK, 0);.      br
7d00: 65 61 6b 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 0a  eak;.    }.  }..
7d10: 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a    return rc;.}..
7d20: 2f 2a 0a 2a 2a 20 52 65 6c 65 61 73 65 20 74 68  /*.** Release th
7d30: 65 20 72 65 61 64 2d 6c 6f 63 6b 20 63 75 72 72  e read-lock curr
7d40: 65 6e 74 6c 79 20 68 65 6c 64 20 62 79 20 63 6f  ently held by co
7d50: 6e 6e 65 63 74 69 6f 6e 20 64 62 2e 0a 2a 2f 0a  nnection db..*/.
7d60: 69 6e 74 20 64 62 52 65 6c 65 61 73 65 52 65 61  int dbReleaseRea
7d70: 64 6c 6f 63 6b 28 6c 73 6d 5f 64 62 20 2a 64 62  dlock(lsm_db *db
7d80: 29 7b 0a 20 20 69 6e 74 20 72 63 20 3d 20 4c 53  ){.  int rc = LS
7d90: 4d 5f 4f 4b 3b 0a 20 20 69 66 28 20 64 62 2d 3e  M_OK;.  if( db->
7da0: 69 52 65 61 64 65 72 3e 3d 30 20 29 7b 0a 20 20  iReader>=0 ){.  
7db0: 20 20 72 63 20 3d 20 6c 73 6d 53 68 6d 4c 6f 63    rc = lsmShmLoc
7dc0: 6b 28 64 62 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 52  k(db, LSM_LOCK_R
7dd0: 45 41 44 45 52 28 64 62 2d 3e 69 52 65 61 64 65  EADER(db->iReade
7de0: 72 29 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 55 4e 4c  r), LSM_LOCK_UNL
7df0: 4f 43 4b 2c 20 30 29 3b 0a 20 20 20 20 64 62 2d  OCK, 0);.    db-
7e00: 3e 69 52 65 61 64 65 72 20 3d 20 2d 31 3b 0a 20  >iReader = -1;. 
7e10: 20 7d 0a 20 20 64 62 2d 3e 62 52 6f 54 72 61 6e   }.  db->bRoTran
7e20: 73 20 3d 20 30 3b 0a 20 20 72 65 74 75 72 6e 20  s = 0;.  return 
7e30: 72 63 3b 0a 7d 0a 0a 0a 2f 2a 0a 2a 2a 20 41 72  rc;.}.../*.** Ar
7e40: 67 75 6d 65 6e 74 20 62 46 6c 75 73 68 20 69 73  gument bFlush is
7e50: 20 74 72 75 65 20 69 66 20 74 68 65 20 63 6f 6e   true if the con
7e60: 74 65 6e 74 73 20 6f 66 20 74 68 65 20 69 6e 2d  tents of the in-
7e70: 6d 65 6d 6f 72 79 20 74 72 65 65 20 68 61 73 20  memory tree has 
7e80: 6a 75 73 74 0a 2a 2a 20 62 65 65 6e 20 66 6c 75  just.** been flu
7e90: 73 68 65 64 20 74 6f 20 64 69 73 6b 2e 20 54 68  shed to disk. Th
7ea0: 65 20 73 69 67 6e 69 66 69 63 61 6e 63 65 20 6f  e significance o
7eb0: 66 20 74 68 69 73 20 69 73 20 74 68 61 74 20 6f  f this is that o
7ec0: 6e 63 65 20 74 68 65 20 73 6e 61 70 73 68 6f 74  nce the snapshot
7ed0: 0a 2a 2a 20 63 72 65 61 74 65 64 20 74 6f 20 68  .** created to h
7ee0: 6f 6c 64 20 74 68 65 20 75 70 64 61 74 65 64 20  old the updated 
7ef0: 73 74 61 74 65 20 6f 66 20 74 68 65 20 64 61 74  state of the dat
7f00: 61 62 61 73 65 20 69 73 20 73 79 6e 63 65 64 20  abase is synced 
7f10: 74 6f 20 64 69 73 6b 2c 20 6c 6f 67 0a 2a 2a 20  to disk, log.** 
7f20: 66 69 6c 65 20 73 70 61 63 65 20 63 61 6e 20 62  file space can b
7f30: 65 20 72 65 63 79 63 6c 65 64 2e 0a 2a 2f 0a 76  e recycled..*/.v
7f40: 6f 69 64 20 6c 73 6d 46 69 6e 69 73 68 57 6f 72  oid lsmFinishWor
7f50: 6b 28 6c 73 6d 5f 64 62 20 2a 70 44 62 2c 20 69  k(lsm_db *pDb, i
7f60: 6e 74 20 62 46 6c 75 73 68 2c 20 69 6e 74 20 2a  nt bFlush, int *
7f70: 70 52 63 29 7b 0a 20 20 69 6e 74 20 72 63 20 3d  pRc){.  int rc =
7f80: 20 2a 70 52 63 3b 0a 20 20 61 73 73 65 72 74 28   *pRc;.  assert(
7f90: 20 72 63 21 3d 30 20 7c 7c 20 70 44 62 2d 3e 70   rc!=0 || pDb->p
7fa0: 57 6f 72 6b 65 72 20 29 3b 0a 20 20 69 66 28 20  Worker );.  if( 
7fb0: 70 44 62 2d 3e 70 57 6f 72 6b 65 72 20 29 7b 0a  pDb->pWorker ){.
7fc0: 20 20 20 20 2f 2a 20 49 66 20 6e 6f 20 65 72 72      /* If no err
7fd0: 6f 72 20 68 61 73 20 6f 63 63 75 72 72 65 64 2c  or has occurred,
7fe0: 20 73 65 72 69 61 6c 69 7a 65 20 74 68 65 20 77   serialize the w
7ff0: 6f 72 6b 65 72 20 73 6e 61 70 73 68 6f 74 20 61  orker snapshot a
8000: 6e 64 20 77 72 69 74 65 0a 20 20 20 20 2a 2a 20  nd write.    ** 
8010: 69 74 20 74 6f 20 73 68 61 72 65 64 20 6d 65 6d  it to shared mem
8020: 6f 72 79 2e 20 20 2a 2f 0a 20 20 20 20 69 66 28  ory.  */.    if(
8030: 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 29 7b 0a 20   rc==LSM_OK ){. 
8040: 20 20 20 20 20 72 63 20 3d 20 6c 73 6d 53 61 76       rc = lsmSav
8050: 65 57 6f 72 6b 65 72 28 70 44 62 2c 20 62 46 6c  eWorker(pDb, bFl
8060: 75 73 68 29 3b 0a 20 20 20 20 7d 0a 0a 20 20 20  ush);.    }..   
8070: 20 2f 2a 20 41 73 73 75 6d 69 6e 67 20 6e 6f 20   /* Assuming no 
8080: 65 72 72 6f 72 20 68 61 73 20 6f 63 63 75 72 72  error has occurr
8090: 65 64 2c 20 75 70 64 61 74 65 20 61 20 72 65 61  ed, update a rea
80a0: 64 20 6c 6f 63 6b 20 73 6c 6f 74 20 77 69 74 68  d lock slot with
80b0: 20 74 68 65 0a 20 20 20 20 2a 2a 20 6e 65 77 20   the.    ** new 
80c0: 73 6e 61 70 73 68 6f 74 20 69 64 20 28 73 65 65  snapshot id (see
80d0: 20 63 6f 6d 6d 65 6e 74 73 20 61 62 6f 76 65 20   comments above 
80e0: 66 75 6e 63 74 69 6f 6e 20 64 62 53 65 74 52 65  function dbSetRe
80f0: 61 64 4c 6f 63 6b 28 29 29 2e 20 20 2a 2f 0a 20  adLock()).  */. 
8100: 20 20 20 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f     if( rc==LSM_O
8110: 4b 20 29 7b 0a 20 20 20 20 20 20 69 66 28 20 70  K ){.      if( p
8120: 44 62 2d 3e 69 52 65 61 64 65 72 3c 30 20 29 7b  Db->iReader<0 ){
8130: 0a 20 20 20 20 20 20 20 20 72 63 20 3d 20 6c 73  .        rc = ls
8140: 6d 54 72 65 65 4c 6f 61 64 48 65 61 64 65 72 28  mTreeLoadHeader(
8150: 70 44 62 2c 20 30 29 3b 0a 20 20 20 20 20 20 7d  pDb, 0);.      }
8160: 0a 20 20 20 20 20 20 69 66 28 20 72 63 3d 3d 4c  .      if( rc==L
8170: 53 4d 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 20  SM_OK ){.       
8180: 20 72 63 20 3d 20 64 62 53 65 74 52 65 61 64 4c   rc = dbSetReadL
8190: 6f 63 6b 28 70 44 62 2c 20 70 44 62 2d 3e 70 57  ock(pDb, pDb->pW
81a0: 6f 72 6b 65 72 2d 3e 69 49 64 2c 20 70 44 62 2d  orker->iId, pDb-
81b0: 3e 74 72 65 65 68 64 72 2e 69 55 73 65 64 53 68  >treehdr.iUsedSh
81c0: 6d 69 64 29 3b 0a 20 20 20 20 20 20 7d 0a 20 20  mid);.      }.  
81d0: 20 20 7d 0a 0a 20 20 20 20 2f 2a 20 46 72 65 65    }..    /* Free
81e0: 20 74 68 65 20 73 6e 61 70 73 68 6f 74 20 6f 62   the snapshot ob
81f0: 6a 65 63 74 2e 20 2a 2f 0a 20 20 20 20 6c 73 6d  ject. */.    lsm
8200: 46 72 65 65 53 6e 61 70 73 68 6f 74 28 70 44 62  FreeSnapshot(pDb
8210: 2d 3e 70 45 6e 76 2c 20 70 44 62 2d 3e 70 57 6f  ->pEnv, pDb->pWo
8220: 72 6b 65 72 29 3b 0a 20 20 20 20 70 44 62 2d 3e  rker);.    pDb->
8230: 70 57 6f 72 6b 65 72 20 3d 20 30 3b 0a 20 20 7d  pWorker = 0;.  }
8240: 0a 0a 20 20 6c 73 6d 53 68 6d 4c 6f 63 6b 28 70  ..  lsmShmLock(p
8250: 44 62 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 57 4f 52  Db, LSM_LOCK_WOR
8260: 4b 45 52 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 55 4e  KER, LSM_LOCK_UN
8270: 4c 4f 43 4b 2c 20 30 29 3b 0a 20 20 2a 70 52 63  LOCK, 0);.  *pRc
8280: 20 3d 20 72 63 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20   = rc;.}../*.** 
8290: 43 61 6c 6c 65 64 20 77 68 65 6e 20 72 65 63 6f  Called when reco
82a0: 76 65 72 79 20 69 73 20 66 69 6e 69 73 68 65 64  very is finished
82b0: 2e 0a 2a 2f 0a 69 6e 74 20 6c 73 6d 46 69 6e 69  ..*/.int lsmFini
82c0: 73 68 52 65 63 6f 76 65 72 79 28 6c 73 6d 5f 64  shRecovery(lsm_d
82d0: 62 20 2a 70 44 62 29 7b 0a 20 20 6c 73 6d 54 72  b *pDb){.  lsmTr
82e0: 65 65 45 6e 64 54 72 61 6e 73 61 63 74 69 6f 6e  eeEndTransaction
82f0: 28 70 44 62 2c 20 31 29 3b 0a 20 20 72 65 74 75  (pDb, 1);.  retu
8300: 72 6e 20 4c 53 4d 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a  rn LSM_OK;.}../*
8310: 0a 2a 2a 20 43 68 65 63 6b 20 69 66 20 74 68 65  .** Check if the
8320: 20 63 75 72 72 65 6e 74 6c 79 20 63 6f 6e 66 69   currently confi
8330: 67 75 72 65 64 20 63 6f 6d 70 72 65 73 73 69 6f  gured compressio
8340: 6e 20 66 75 6e 63 74 69 6f 6e 73 0a 2a 2a 20 28  n functions.** (
8350: 4c 53 4d 5f 43 4f 4e 46 49 47 5f 53 45 54 5f 43  LSM_CONFIG_SET_C
8360: 4f 4d 50 52 45 53 53 49 4f 4e 29 20 61 72 65 20  OMPRESSION) are 
8370: 63 6f 6d 70 61 74 69 62 6c 65 20 77 69 74 68 20  compatible with 
8380: 61 20 64 61 74 61 62 61 73 65 20 74 68 61 74 20  a database that 
8390: 68 61 73 20 69 74 73 0a 2a 2a 20 63 6f 6d 70 72  has its.** compr
83a0: 65 73 73 69 6f 6e 20 69 64 20 73 65 74 20 74 6f  ession id set to
83b0: 20 69 52 65 71 2e 20 43 6f 6d 70 72 65 73 73 69   iReq. Compressi
83c0: 6f 6e 20 72 6f 75 74 69 6e 65 73 20 61 72 65 20  on routines are 
83d0: 63 6f 6d 70 61 74 69 62 6c 65 20 69 66 20 69 52  compatible if iR
83e0: 65 71 0a 2a 2a 20 69 73 20 7a 65 72 6f 20 28 69  eq.** is zero (i
83f0: 6e 64 69 63 61 74 69 6e 67 20 74 68 65 20 64 61  ndicating the da
8400: 74 61 62 61 73 65 20 69 73 20 65 6d 70 74 79 29  tabase is empty)
8410: 2c 20 6f 72 20 69 66 20 69 74 20 69 73 20 65 71  , or if it is eq
8420: 75 61 6c 20 74 6f 20 74 68 65 20 0a 2a 2a 20 63  ual to the .** c
8430: 6f 6d 70 72 65 73 73 69 6f 6e 20 69 64 20 6f 66  ompression id of
8440: 20 74 68 65 20 63 6f 6e 66 69 67 75 72 65 64 20   the configured 
8450: 63 6f 6d 70 72 65 73 73 69 6f 6e 20 72 6f 75 74  compression rout
8460: 69 6e 65 73 2e 0a 2a 2a 0a 2a 2a 20 49 66 20 74  ines..**.** If t
8470: 68 65 20 63 68 65 63 6b 20 73 68 6f 77 73 20 74  he check shows t
8480: 68 61 74 20 74 68 65 20 63 75 72 72 65 6e 74 20  hat the current 
8490: 63 6f 6d 70 72 65 73 73 69 6f 6e 20 61 72 65 20  compression are 
84a0: 69 6e 63 6f 6d 70 61 74 69 62 6c 65 20 61 6e 64  incompatible and
84b0: 20 74 68 65 72 65 0a 2a 2a 20 69 73 20 61 20 63   there.** is a c
84c0: 6f 6d 70 72 65 73 73 69 6f 6e 20 66 61 63 74 6f  ompression facto
84d0: 72 79 20 72 65 67 69 73 74 65 72 65 64 2c 20 67  ry registered, g
84e0: 69 76 65 20 69 74 20 61 20 63 68 61 6e 63 65 20  ive it a chance 
84f0: 74 6f 20 69 6e 73 74 61 6c 6c 20 6e 65 77 0a 2a  to install new.*
8500: 2a 20 63 6f 6d 70 72 65 73 73 69 6f 6e 20 72 6f  * compression ro
8510: 75 74 69 6e 65 73 2e 0a 2a 2a 0a 2a 2a 20 49 66  utines..**.** If
8520: 2c 20 61 66 74 65 72 20 61 6e 79 20 72 65 67 69  , after any regi
8530: 73 74 65 72 65 64 20 66 61 63 74 6f 72 79 20 69  stered factory i
8540: 73 20 69 6e 76 6f 6b 65 64 2c 20 74 68 65 20 63  s invoked, the c
8550: 6f 6d 70 72 65 73 73 69 6f 6e 20 66 75 6e 63 74  ompression funct
8560: 69 6f 6e 73 0a 2a 2a 20 61 72 65 20 73 74 69 6c  ions.** are stil
8570: 6c 20 69 6e 63 6f 6d 70 61 74 69 62 6c 65 2c 20  l incompatible, 
8580: 72 65 74 75 72 6e 20 4c 53 4d 5f 4d 49 53 4d 41  return LSM_MISMA
8590: 54 43 48 2e 20 4f 74 68 65 72 77 69 73 65 2c 20  TCH. Otherwise, 
85a0: 4c 53 4d 5f 4f 4b 2e 0a 2a 2f 0a 69 6e 74 20 6c  LSM_OK..*/.int l
85b0: 73 6d 43 68 65 63 6b 43 6f 6d 70 72 65 73 73 69  smCheckCompressi
85c0: 6f 6e 49 64 28 6c 73 6d 5f 64 62 20 2a 70 44 62  onId(lsm_db *pDb
85d0: 2c 20 75 33 32 20 69 52 65 71 29 7b 0a 20 20 69  , u32 iReq){.  i
85e0: 66 28 20 69 52 65 71 21 3d 4c 53 4d 5f 43 4f 4d  f( iReq!=LSM_COM
85f0: 50 52 45 53 53 49 4f 4e 5f 45 4d 50 54 59 20 26  PRESSION_EMPTY &
8600: 26 20 70 44 62 2d 3e 63 6f 6d 70 72 65 73 73 2e  & pDb->compress.
8610: 69 49 64 21 3d 69 52 65 71 20 29 7b 0a 20 20 20  iId!=iReq ){.   
8620: 20 69 66 28 20 70 44 62 2d 3e 66 61 63 74 6f 72   if( pDb->factor
8630: 79 2e 78 46 61 63 74 6f 72 79 20 29 7b 0a 20 20  y.xFactory ){.  
8640: 20 20 20 20 70 44 62 2d 3e 62 49 6e 46 61 63 74      pDb->bInFact
8650: 6f 72 79 20 3d 20 31 3b 0a 20 20 20 20 20 20 70  ory = 1;.      p
8660: 44 62 2d 3e 66 61 63 74 6f 72 79 2e 78 46 61 63  Db->factory.xFac
8670: 74 6f 72 79 28 70 44 62 2d 3e 66 61 63 74 6f 72  tory(pDb->factor
8680: 79 2e 70 43 74 78 2c 20 70 44 62 2c 20 69 52 65  y.pCtx, pDb, iRe
8690: 71 29 3b 0a 20 20 20 20 20 20 70 44 62 2d 3e 62  q);.      pDb->b
86a0: 49 6e 46 61 63 74 6f 72 79 20 3d 20 30 3b 0a 20  InFactory = 0;. 
86b0: 20 20 20 7d 0a 20 20 20 20 69 66 28 20 70 44 62     }.    if( pDb
86c0: 2d 3e 63 6f 6d 70 72 65 73 73 2e 69 49 64 21 3d  ->compress.iId!=
86d0: 69 52 65 71 20 29 7b 0a 20 20 20 20 20 20 2f 2a  iReq ){.      /*
86e0: 20 49 6e 63 6f 6d 70 61 74 69 62 6c 65 20 2a 2f   Incompatible */
86f0: 0a 20 20 20 20 20 20 72 65 74 75 72 6e 20 4c 53  .      return LS
8700: 4d 5f 4d 49 53 4d 41 54 43 48 3b 0a 20 20 20 20  M_MISMATCH;.    
8710: 7d 0a 20 20 7d 0a 20 20 2f 2a 20 43 6f 6d 70 61  }.  }.  /* Compa
8720: 74 69 62 6c 65 20 2a 2f 0a 20 20 72 65 74 75 72  tible */.  retur
8730: 6e 20 4c 53 4d 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a 0a  n LSM_OK;.}../*.
8740: 2a 2a 20 42 65 67 69 6e 20 61 20 72 65 61 64 20  ** Begin a read 
8750: 74 72 61 6e 73 61 63 74 69 6f 6e 2e 20 54 68 69  transaction. Thi
8760: 73 20 66 75 6e 63 74 69 6f 6e 20 69 73 20 61 20  s function is a 
8770: 6e 6f 2d 6f 70 20 69 66 20 74 68 65 20 63 6f 6e  no-op if the con
8780: 6e 65 63 74 69 6f 6e 0a 2a 2a 20 70 61 73 73 65  nection.** passe
8790: 64 20 61 73 20 74 68 65 20 6f 6e 6c 79 20 61 72  d as the only ar
87a0: 67 75 6d 65 6e 74 20 61 6c 72 65 61 64 79 20 68  gument already h
87b0: 61 73 20 61 6e 20 6f 70 65 6e 20 72 65 61 64 20  as an open read 
87c0: 74 72 61 6e 73 61 63 74 69 6f 6e 2e 0a 2a 2f 0a  transaction..*/.
87d0: 69 6e 74 20 6c 73 6d 42 65 67 69 6e 52 65 61 64  int lsmBeginRead
87e0: 54 72 61 6e 73 28 6c 73 6d 5f 64 62 20 2a 70 44  Trans(lsm_db *pD
87f0: 62 29 7b 0a 20 20 63 6f 6e 73 74 20 69 6e 74 20  b){.  const int 
8800: 4d 41 58 5f 52 45 41 44 4c 4f 43 4b 5f 41 54 54  MAX_READLOCK_ATT
8810: 45 4d 50 54 53 20 3d 20 31 30 3b 0a 20 20 63 6f  EMPTS = 10;.  co
8820: 6e 73 74 20 69 6e 74 20 6e 4d 61 78 41 74 74 65  nst int nMaxAtte
8830: 6d 70 74 20 3d 20 28 70 44 62 2d 3e 62 52 6f 54  mpt = (pDb->bRoT
8840: 72 61 6e 73 20 3f 20 31 20 3a 20 4d 41 58 5f 52  rans ? 1 : MAX_R
8850: 45 41 44 4c 4f 43 4b 5f 41 54 54 45 4d 50 54 53  EADLOCK_ATTEMPTS
8860: 29 3b 0a 0a 20 20 69 6e 74 20 72 63 20 3d 20 4c  );..  int rc = L
8870: 53 4d 5f 4f 4b 3b 20 20 20 20 20 20 20 20 20 20  SM_OK;          
8880: 20 20 20 20 20 20 2f 2a 20 52 65 74 75 72 6e 20        /* Return 
8890: 63 6f 64 65 20 2a 2f 0a 20 20 69 6e 74 20 69 41  code */.  int iA
88a0: 74 74 65 6d 70 74 20 3d 20 30 3b 0a 0a 20 20 61  ttempt = 0;..  a
88b0: 73 73 65 72 74 28 20 70 44 62 2d 3e 70 57 6f 72  ssert( pDb->pWor
88c0: 6b 65 72 3d 3d 30 20 29 3b 0a 0a 20 20 77 68 69  ker==0 );..  whi
88d0: 6c 65 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 26  le( rc==LSM_OK &
88e0: 26 20 70 44 62 2d 3e 69 52 65 61 64 65 72 3c 30  & pDb->iReader<0
88f0: 20 26 26 20 28 69 41 74 74 65 6d 70 74 2b 2b 29   && (iAttempt++)
8900: 3c 6e 4d 61 78 41 74 74 65 6d 70 74 20 29 7b 0a  <nMaxAttempt ){.
8910: 20 20 20 20 69 6e 74 20 69 54 72 65 65 68 64 72      int iTreehdr
8920: 20 3d 20 30 3b 0a 20 20 20 20 69 6e 74 20 69 53   = 0;.    int iS
8930: 6e 61 70 20 3d 20 30 3b 0a 20 20 20 20 61 73 73  nap = 0;.    ass
8940: 65 72 74 28 20 70 44 62 2d 3e 70 43 73 72 3d 3d  ert( pDb->pCsr==
8950: 30 20 26 26 20 70 44 62 2d 3e 6e 54 72 61 6e 73  0 && pDb->nTrans
8960: 4f 70 65 6e 3d 3d 30 20 29 3b 0a 0a 20 20 20 20  Open==0 );..    
8970: 2f 2a 20 4c 6f 61 64 20 74 68 65 20 69 6e 2d 6d  /* Load the in-m
8980: 65 6d 6f 72 79 20 74 72 65 65 20 68 65 61 64 65  emory tree heade
8990: 72 2e 20 2a 2f 0a 20 20 20 20 72 63 20 3d 20 6c  r. */.    rc = l
89a0: 73 6d 54 72 65 65 4c 6f 61 64 48 65 61 64 65 72  smTreeLoadHeader
89b0: 28 70 44 62 2c 20 26 69 54 72 65 65 68 64 72 29  (pDb, &iTreehdr)
89c0: 3b 0a 0a 20 20 20 20 2f 2a 20 4c 6f 61 64 20 74  ;..    /* Load t
89d0: 68 65 20 64 61 74 61 62 61 73 65 20 73 6e 61 70  he database snap
89e0: 73 68 6f 74 20 2a 2f 0a 20 20 20 20 69 66 28 20  shot */.    if( 
89f0: 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 29 7b 0a 20 20  rc==LSM_OK ){.  
8a00: 20 20 20 20 69 66 28 20 6c 73 6d 43 68 65 63 6b      if( lsmCheck
8a10: 70 6f 69 6e 74 43 6c 69 65 6e 74 43 61 63 68 65  pointClientCache
8a20: 4f 6b 28 70 44 62 29 3d 3d 30 20 29 7b 0a 20 20  Ok(pDb)==0 ){.  
8a30: 20 20 20 20 20 20 6c 73 6d 46 72 65 65 53 6e 61        lsmFreeSna
8a40: 70 73 68 6f 74 28 70 44 62 2d 3e 70 45 6e 76 2c  pshot(pDb->pEnv,
8a50: 20 70 44 62 2d 3e 70 43 6c 69 65 6e 74 29 3b 0a   pDb->pClient);.
8a60: 20 20 20 20 20 20 20 20 70 44 62 2d 3e 70 43 6c          pDb->pCl
8a70: 69 65 6e 74 20 3d 20 30 3b 0a 20 20 20 20 20 20  ient = 0;.      
8a80: 20 20 6c 73 6d 4d 43 75 72 73 6f 72 46 72 65 65    lsmMCursorFree
8a90: 43 61 63 68 65 28 70 44 62 29 3b 0a 20 20 20 20  Cache(pDb);.    
8aa0: 20 20 20 20 6c 73 6d 46 73 50 75 72 67 65 43 61      lsmFsPurgeCa
8ab0: 63 68 65 28 70 44 62 2d 3e 70 46 53 29 3b 0a 20  che(pDb->pFS);. 
8ac0: 20 20 20 20 20 20 20 72 63 20 3d 20 6c 73 6d 43         rc = lsmC
8ad0: 68 65 63 6b 70 6f 69 6e 74 4c 6f 61 64 28 70 44  heckpointLoad(pD
8ae0: 62 2c 20 26 69 53 6e 61 70 29 3b 0a 20 20 20 20  b, &iSnap);.    
8af0: 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 20    }else{.       
8b00: 20 69 53 6e 61 70 20 3d 20 31 3b 0a 20 20 20 20   iSnap = 1;.    
8b10: 20 20 7d 0a 20 20 20 20 7d 0a 0a 20 20 20 20 2f    }.    }..    /
8b20: 2a 20 54 61 6b 65 20 61 20 72 65 61 64 2d 6c 6f  * Take a read-lo
8b30: 63 6b 20 6f 6e 20 74 68 65 20 74 72 65 65 20 61  ck on the tree a
8b40: 6e 64 20 73 6e 61 70 73 68 6f 74 20 6a 75 73 74  nd snapshot just
8b50: 20 6c 6f 61 64 65 64 2e 20 54 68 65 6e 20 63 68   loaded. Then ch
8b60: 65 63 6b 0a 20 20 20 20 2a 2a 20 74 68 61 74 20  eck.    ** that 
8b70: 74 68 65 20 73 68 61 72 65 64 2d 6d 65 6d 6f 72  the shared-memor
8b80: 79 20 73 74 69 6c 6c 20 63 6f 6e 74 61 69 6e 73  y still contains
8b90: 20 74 68 65 20 73 61 6d 65 20 76 61 6c 75 65 73   the same values
8ba0: 2e 20 49 66 20 73 6f 2c 20 70 72 6f 63 65 65 64  . If so, proceed
8bb0: 2e 0a 20 20 20 20 2a 2a 20 4f 74 68 65 72 77 69  ..    ** Otherwi
8bc0: 73 65 2c 20 72 65 6c 69 6e 71 75 69 73 68 20 74  se, relinquish t
8bd0: 68 65 20 72 65 61 64 2d 6c 6f 63 6b 20 61 6e 64  he read-lock and
8be0: 20 72 65 74 72 79 20 74 68 65 20 77 68 6f 6c 65   retry the whole
8bf0: 20 70 72 6f 63 65 64 75 72 65 0a 20 20 20 20 2a   procedure.    *
8c00: 2a 20 28 73 74 61 72 74 69 6e 67 20 77 69 74 68  * (starting with
8c10: 20 6c 6f 61 64 69 6e 67 20 74 68 65 20 69 6e 2d   loading the in-
8c20: 6d 65 6d 6f 72 79 20 74 72 65 65 20 68 65 61 64  memory tree head
8c30: 65 72 29 2e 20 20 2a 2f 0a 20 20 20 20 69 66 28  er).  */.    if(
8c40: 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 29 7b 0a 20   rc==LSM_OK ){. 
8c50: 20 20 20 20 20 75 33 32 20 69 53 68 6d 4d 61 78       u32 iShmMax
8c60: 20 3d 20 70 44 62 2d 3e 74 72 65 65 68 64 72 2e   = pDb->treehdr.
8c70: 69 55 73 65 64 53 68 6d 69 64 3b 0a 20 20 20 20  iUsedShmid;.    
8c80: 20 20 75 33 32 20 69 53 68 6d 4d 69 6e 20 3d 20    u32 iShmMin = 
8c90: 70 44 62 2d 3e 74 72 65 65 68 64 72 2e 69 4e 65  pDb->treehdr.iNe
8ca0: 78 74 53 68 6d 69 64 2b 31 2d 4c 53 4d 5f 4d 41  xtShmid+1-LSM_MA
8cb0: 58 5f 53 48 4d 43 48 55 4e 4b 53 3b 0a 20 20 20  X_SHMCHUNKS;.   
8cc0: 20 20 20 72 63 20 3d 20 6c 73 6d 52 65 61 64 6c     rc = lsmReadl
8cd0: 6f 63 6b 28 0a 20 20 20 20 20 20 20 20 20 20 70  ock(.          p
8ce0: 44 62 2c 20 6c 73 6d 43 68 65 63 6b 70 6f 69 6e  Db, lsmCheckpoin
8cf0: 74 49 64 28 70 44 62 2d 3e 61 53 6e 61 70 73 68  tId(pDb->aSnapsh
8d00: 6f 74 2c 20 30 29 2c 20 69 53 68 6d 4d 69 6e 2c  ot, 0), iShmMin,
8d10: 20 69 53 68 6d 4d 61 78 0a 20 20 20 20 20 20 29   iShmMax.      )
8d20: 3b 0a 20 20 20 20 20 20 69 66 28 20 72 63 3d 3d  ;.      if( rc==
8d30: 4c 53 4d 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20  LSM_OK ){.      
8d40: 20 20 69 66 28 20 6c 73 6d 54 72 65 65 4c 6f 61    if( lsmTreeLoa
8d50: 64 48 65 61 64 65 72 4f 6b 28 70 44 62 2c 20 69  dHeaderOk(pDb, i
8d60: 54 72 65 65 68 64 72 29 0a 20 20 20 20 20 20 20  Treehdr).       
8d70: 20 20 26 26 20 6c 73 6d 43 68 65 63 6b 70 6f 69    && lsmCheckpoi
8d80: 6e 74 4c 6f 61 64 4f 6b 28 70 44 62 2c 20 69 53  ntLoadOk(pDb, iS
8d90: 6e 61 70 29 0a 20 20 20 20 20 20 20 20 29 7b 0a  nap).        ){.
8da0: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 52 65 61            /* Rea
8db0: 64 20 6c 6f 63 6b 20 68 61 73 20 62 65 65 6e 20  d lock has been 
8dc0: 73 75 63 63 65 73 73 66 75 6c 6c 79 20 6f 62 74  successfully obt
8dd0: 61 69 6e 65 64 2e 20 44 65 73 65 72 69 61 6c 69  ained. Deseriali
8de0: 7a 65 20 74 68 65 20 0a 20 20 20 20 20 20 20 20  ze the .        
8df0: 20 20 2a 2a 20 63 68 65 63 6b 70 6f 69 6e 74 20    ** checkpoint 
8e00: 6a 75 73 74 20 6c 6f 61 64 65 64 2e 20 54 4f 44  just loaded. TOD
8e10: 4f 3a 20 54 68 69 73 20 77 69 6c 6c 20 62 65 20  O: This will be 
8e20: 72 65 6d 6f 76 65 64 20 61 66 74 65 72 20 0a 20  removed after . 
8e30: 20 20 20 20 20 20 20 20 20 2a 2a 20 6c 73 6d 5f           ** lsm_
8e40: 73 6f 72 74 65 64 2e 63 20 69 73 20 63 68 61 6e  sorted.c is chan
8e50: 67 65 64 20 74 6f 20 77 6f 72 6b 20 64 69 72 65  ged to work dire
8e60: 63 74 6c 79 20 66 72 6f 6d 20 74 68 65 20 73 65  ctly from the se
8e70: 72 69 61 6c 69 7a 65 64 0a 20 20 20 20 20 20 20  rialized.       
8e80: 20 20 20 2a 2a 20 76 65 72 73 69 6f 6e 20 6f 66     ** version of
8e90: 20 74 68 65 20 73 6e 61 70 73 68 6f 74 2e 20 20   the snapshot.  
8ea0: 2a 2f 0a 20 20 20 20 20 20 20 20 20 20 69 66 28  */.          if(
8eb0: 20 70 44 62 2d 3e 70 43 6c 69 65 6e 74 3d 3d 30   pDb->pClient==0
8ec0: 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20 20 20   ){.            
8ed0: 72 63 20 3d 20 6c 73 6d 43 68 65 63 6b 70 6f 69  rc = lsmCheckpoi
8ee0: 6e 74 44 65 73 65 72 69 61 6c 69 7a 65 28 70 44  ntDeserialize(pD
8ef0: 62 2c 20 30 2c 20 70 44 62 2d 3e 61 53 6e 61 70  b, 0, pDb->aSnap
8f00: 73 68 6f 74 2c 26 70 44 62 2d 3e 70 43 6c 69 65  shot,&pDb->pClie
8f10: 6e 74 29 3b 0a 20 20 20 20 20 20 20 20 20 20 7d  nt);.          }
8f20: 0a 20 20 20 20 20 20 20 20 20 20 61 73 73 65 72  .          asser
8f30: 74 28 20 28 72 63 3d 3d 4c 53 4d 5f 4f 4b 29 3d  t( (rc==LSM_OK)=
8f40: 3d 28 70 44 62 2d 3e 70 43 6c 69 65 6e 74 21 3d  =(pDb->pClient!=
8f50: 30 29 20 29 3b 0a 20 20 20 20 20 20 20 20 20 20  0) );.          
8f60: 61 73 73 65 72 74 28 20 70 44 62 2d 3e 69 52 65  assert( pDb->iRe
8f70: 61 64 65 72 3e 3d 30 20 29 3b 0a 0a 20 20 20 20  ader>=0 );..    
8f80: 20 20 20 20 20 20 2f 2a 20 43 68 65 63 6b 20 74        /* Check t
8f90: 68 61 74 20 74 68 65 20 63 6c 69 65 6e 74 20 68  hat the client h
8fa0: 61 73 20 74 68 65 20 72 69 67 68 74 20 63 6f 6d  as the right com
8fb0: 70 72 65 73 73 69 6f 6e 20 68 6f 6f 6b 73 20 6c  pression hooks l
8fc0: 6f 61 64 65 64 2e 0a 20 20 20 20 20 20 20 20 20  oaded..         
8fd0: 20 2a 2a 20 49 66 20 6e 6f 74 2c 20 73 65 74 20   ** If not, set 
8fe0: 72 63 20 74 6f 20 4c 53 4d 5f 4d 49 53 4d 41 54  rc to LSM_MISMAT
8ff0: 43 48 2e 20 20 2a 2f 0a 20 20 20 20 20 20 20 20  CH.  */.        
9000: 20 20 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b    if( rc==LSM_OK
9010: 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20 20 20   ){.            
9020: 72 63 20 3d 20 6c 73 6d 43 68 65 63 6b 43 6f 6d  rc = lsmCheckCom
9030: 70 72 65 73 73 69 6f 6e 49 64 28 70 44 62 2c 20  pressionId(pDb, 
9040: 70 44 62 2d 3e 70 43 6c 69 65 6e 74 2d 3e 69 43  pDb->pClient->iC
9050: 6d 70 49 64 29 3b 0a 20 20 20 20 20 20 20 20 20  mpId);.         
9060: 20 7d 0a 20 20 20 20 20 20 20 20 7d 65 6c 73 65   }.        }else
9070: 7b 0a 20 20 20 20 20 20 20 20 20 20 72 63 20 3d  {.          rc =
9080: 20 64 62 52 65 6c 65 61 73 65 52 65 61 64 6c 6f   dbReleaseReadlo
9090: 63 6b 28 70 44 62 29 3b 0a 20 20 20 20 20 20 20  ck(pDb);.       
90a0: 20 7d 0a 20 20 20 20 20 20 7d 0a 0a 20 20 20 20   }.      }..    
90b0: 20 20 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 42 55    if( rc==LSM_BU
90c0: 53 59 20 29 7b 0a 20 20 20 20 20 20 20 20 72 63  SY ){.        rc
90d0: 20 3d 20 4c 53 4d 5f 4f 4b 3b 0a 20 20 20 20 20   = LSM_OK;.     
90e0: 20 7d 0a 20 20 20 20 7d 0a 23 69 66 20 30 0a 69   }.    }.#if 0.i
90f0: 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 26 26  f( rc==LSM_OK &&
9100: 20 70 44 62 2d 3e 70 43 6c 69 65 6e 74 20 29 7b   pDb->pClient ){
9110: 0a 20 20 66 70 72 69 6e 74 66 28 73 74 64 65 72  .  fprintf(stder
9120: 72 2c 20 0a 20 20 20 20 20 20 22 72 65 61 64 69  r, .      "readi
9130: 6e 67 20 25 70 3a 20 73 6e 61 70 73 68 6f 74 3a  ng %p: snapshot:
9140: 25 64 20 75 73 65 64 2d 73 68 6d 69 64 3a 25 64  %d used-shmid:%d
9150: 20 74 72 61 6e 73 2d 69 64 3a 25 64 20 69 4f 6c   trans-id:%d iOl
9160: 64 53 68 6d 69 64 3d 25 64 5c 6e 22 2c 0a 20 20  dShmid=%d\n",.  
9170: 20 20 20 20 28 76 6f 69 64 20 2a 29 70 44 62 2c      (void *)pDb,
9180: 0a 20 20 20 20 20 20 28 69 6e 74 29 70 44 62 2d  .      (int)pDb-
9190: 3e 70 43 6c 69 65 6e 74 2d 3e 69 49 64 2c 20 28  >pClient->iId, (
91a0: 69 6e 74 29 70 44 62 2d 3e 74 72 65 65 68 64 72  int)pDb->treehdr
91b0: 2e 69 55 73 65 64 53 68 6d 69 64 2c 20 0a 20 20  .iUsedShmid, .  
91c0: 20 20 20 20 28 69 6e 74 29 70 44 62 2d 3e 74 72      (int)pDb->tr
91d0: 65 65 68 64 72 2e 72 6f 6f 74 2e 69 54 72 61 6e  eehdr.root.iTran
91e0: 73 49 64 2c 0a 20 20 20 20 20 20 28 69 6e 74 29  sId,.      (int)
91f0: 70 44 62 2d 3e 74 72 65 65 68 64 72 2e 69 4f 6c  pDb->treehdr.iOl
9200: 64 53 68 6d 69 64 0a 20 20 29 3b 0a 7d 0a 23 65  dShmid.  );.}.#e
9210: 6e 64 69 66 0a 20 20 7d 0a 0a 20 20 69 66 28 20  ndif.  }..  if( 
9220: 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 29 7b 0a 20 20  rc==LSM_OK ){.  
9230: 20 20 72 63 20 3d 20 6c 73 6d 53 68 6d 43 61 63    rc = lsmShmCac
9240: 68 65 43 68 75 6e 6b 73 28 70 44 62 2c 20 70 44  heChunks(pDb, pD
9250: 62 2d 3e 74 72 65 65 68 64 72 2e 6e 43 68 75 6e  b->treehdr.nChun
9260: 6b 29 3b 0a 20 20 7d 0a 20 20 69 66 28 20 72 63  k);.  }.  if( rc
9270: 21 3d 4c 53 4d 5f 4f 4b 20 29 7b 0a 20 20 20 20  !=LSM_OK ){.    
9280: 64 62 52 65 6c 65 61 73 65 52 65 61 64 6c 6f 63  dbReleaseReadloc
9290: 6b 28 70 44 62 29 3b 0a 20 20 7d 0a 20 20 69 66  k(pDb);.  }.  if
92a0: 28 20 70 44 62 2d 3e 70 43 6c 69 65 6e 74 3d 3d  ( pDb->pClient==
92b0: 30 20 26 26 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20  0 && rc==LSM_OK 
92c0: 29 20 72 63 20 3d 20 4c 53 4d 5f 42 55 53 59 3b  ) rc = LSM_BUSY;
92d0: 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a  .  return rc;.}.
92e0: 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20 66 75 6e 63  ./*.** This func
92f0: 74 69 6f 6e 20 69 73 20 75 73 65 64 20 62 79 20  tion is used by 
9300: 61 20 72 65 61 64 2d 77 72 69 74 65 20 63 6f 6e  a read-write con
9310: 6e 65 63 74 69 6f 6e 20 74 6f 20 64 65 74 65 72  nection to deter
9320: 6d 69 6e 65 20 69 66 20 74 68 65 72 65 0a 2a 2a  mine if there.**
9330: 20 61 72 65 20 63 75 72 72 65 6e 74 6c 79 20 6f   are currently o
9340: 6e 65 20 6f 72 20 6d 6f 72 65 20 72 65 61 64 2d  ne or more read-
9350: 6f 6e 6c 79 20 74 72 61 6e 73 61 63 74 69 6f 6e  only transaction
9360: 73 20 6f 70 65 6e 20 6f 6e 20 74 68 65 20 64 61  s open on the da
9370: 74 61 62 61 73 65 0a 2a 2a 20 28 69 6e 20 74 68  tabase.** (in th
9380: 69 73 20 63 6f 6e 74 65 78 74 20 61 20 72 65 61  is context a rea
9390: 64 2d 6f 6e 6c 79 20 74 72 61 6e 73 61 63 74 69  d-only transacti
93a0: 6f 6e 20 69 73 20 6f 6e 65 20 6f 70 65 6e 65 64  on is one opened
93b0: 20 62 79 20 61 20 72 65 61 64 2d 6f 6e 6c 79 0a   by a read-only.
93c0: 2a 2a 20 63 6f 6e 6e 65 63 74 69 6f 6e 20 6f 6e  ** connection on
93d0: 20 61 20 6e 6f 6e 2d 6c 69 76 65 20 64 61 74 61   a non-live data
93e0: 62 61 73 65 29 2e 0a 2a 2a 0a 2a 2a 20 49 66 20  base)..**.** If 
93f0: 6e 6f 20 65 72 72 6f 72 20 6f 63 63 75 72 73 2c  no error occurs,
9400: 20 4c 53 4d 5f 4f 4b 20 69 73 20 72 65 74 75 72   LSM_OK is retur
9410: 6e 65 64 20 61 6e 64 20 2a 70 62 45 78 69 73 74  ned and *pbExist
9420: 73 20 69 73 20 73 65 74 20 74 6f 20 74 72 75 65  s is set to true
9430: 20 69 66 0a 2a 2a 20 73 6f 6d 65 20 6f 74 68 65   if.** some othe
9440: 72 20 63 6f 6e 6e 65 63 74 69 6f 6e 20 68 61 73  r connection has
9450: 20 61 20 72 65 61 64 2d 6f 6e 6c 79 20 74 72 61   a read-only tra
9460: 6e 73 61 63 74 69 6f 6e 20 6f 70 65 6e 2c 20 6f  nsaction open, o
9470: 72 20 66 61 6c 73 65 20 0a 2a 2a 20 6f 74 68 65  r false .** othe
9480: 72 77 69 73 65 2e 20 49 66 20 61 6e 20 65 72 72  rwise. If an err
9490: 6f 72 20 6f 63 63 75 72 73 20 61 6e 20 4c 53 4d  or occurs an LSM
94a0: 20 65 72 72 6f 72 20 63 6f 64 65 20 69 73 20 72   error code is r
94b0: 65 74 75 72 6e 65 64 20 61 6e 64 20 74 68 65 20  eturned and the 
94c0: 66 69 6e 61 6c 0a 2a 2a 20 76 61 6c 75 65 20 6f  final.** value o
94d0: 66 20 2a 70 62 45 78 69 73 74 20 69 73 20 75 6e  f *pbExist is un
94e0: 64 65 66 69 6e 65 64 2e 0a 2a 2f 0a 69 6e 74 20  defined..*/.int 
94f0: 6c 73 6d 44 65 74 65 63 74 52 6f 54 72 61 6e 73  lsmDetectRoTrans
9500: 28 6c 73 6d 5f 64 62 20 2a 64 62 2c 20 69 6e 74  (lsm_db *db, int
9510: 20 2a 70 62 45 78 69 73 74 29 7b 0a 20 20 69 6e   *pbExist){.  in
9520: 74 20 72 63 3b 0a 0a 20 20 2f 2a 20 4f 6e 6c 79  t rc;..  /* Only
9530: 20 61 20 72 65 61 64 2d 77 72 69 74 65 20 63 6f   a read-write co
9540: 6e 6e 65 63 74 69 6f 6e 20 6d 61 79 20 75 73 65  nnection may use
9550: 20 74 68 69 73 20 66 75 6e 63 74 69 6f 6e 2e 20   this function. 
9560: 2a 2f 0a 20 20 61 73 73 65 72 74 28 20 64 62 2d  */.  assert( db-
9570: 3e 62 52 65 61 64 6f 6e 6c 79 3d 3d 30 20 29 3b  >bReadonly==0 );
9580: 0a 0a 20 20 72 63 20 3d 20 6c 73 6d 53 68 6d 54  ..  rc = lsmShmT
9590: 65 73 74 4c 6f 63 6b 28 64 62 2c 20 4c 53 4d 5f  estLock(db, LSM_
95a0: 4c 4f 43 4b 5f 52 4f 54 52 41 4e 53 2c 20 31 2c  LOCK_ROTRANS, 1,
95b0: 20 4c 53 4d 5f 4c 4f 43 4b 5f 45 58 43 4c 29 3b   LSM_LOCK_EXCL);
95c0: 0a 20 20 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 42  .  if( rc==LSM_B
95d0: 55 53 59 20 29 7b 0a 20 20 20 20 2a 70 62 45 78  USY ){.    *pbEx
95e0: 69 73 74 20 3d 20 31 3b 0a 20 20 20 20 72 63 20  ist = 1;.    rc 
95f0: 3d 20 4c 53 4d 5f 4f 4b 3b 0a 20 20 7d 65 6c 73  = LSM_OK;.  }els
9600: 65 7b 0a 20 20 20 20 2a 70 62 45 78 69 73 74 20  e{.    *pbExist 
9610: 3d 20 30 3b 0a 20 20 7d 0a 0a 20 20 72 65 74 75  = 0;.  }..  retu
9620: 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20  rn rc;.}../*.** 
9630: 64 62 20 69 73 20 61 20 72 65 61 64 2d 6f 6e 6c  db is a read-onl
9640: 79 20 64 61 74 61 62 61 73 65 20 68 61 6e 64 6c  y database handl
9650: 65 20 69 6e 20 74 68 65 20 64 69 73 63 6f 6e 6e  e in the disconn
9660: 65 63 74 65 64 20 73 74 61 74 65 2e 20 54 68 69  ected state. Thi
9670: 73 20 66 75 6e 63 74 69 6f 6e 0a 2a 2a 20 61 74  s function.** at
9680: 74 65 6d 70 74 73 20 74 6f 20 6f 70 65 6e 20 61  tempts to open a
9690: 20 72 65 61 64 2d 74 72 61 6e 73 61 63 74 69 6f   read-transactio
96a0: 6e 20 6f 6e 20 74 68 65 20 64 61 74 61 62 61 73  n on the databas
96b0: 65 2e 20 54 68 69 73 20 6d 61 79 20 69 6e 76 6f  e. This may invo
96c0: 6c 76 65 0a 2a 2a 20 63 6f 6e 6e 65 63 74 69 6e  lve.** connectin
96d0: 67 20 74 6f 20 74 68 65 20 64 61 74 61 62 61 73  g to the databas
96e0: 65 20 73 79 73 74 65 6d 20 28 6f 70 65 6e 69 6e  e system (openin
96f0: 67 20 73 68 61 72 65 64 20 6d 65 6d 6f 72 79 20  g shared memory 
9700: 65 74 63 2e 29 2e 0a 2a 2f 0a 69 6e 74 20 6c 73  etc.)..*/.int ls
9710: 6d 42 65 67 69 6e 52 6f 54 72 61 6e 73 28 6c 73  mBeginRoTrans(ls
9720: 6d 5f 64 62 20 2a 64 62 29 7b 0a 20 20 69 6e 74  m_db *db){.  int
9730: 20 72 63 20 3d 20 4c 53 4d 5f 4f 4b 3b 0a 0a 20   rc = LSM_OK;.. 
9740: 20 61 73 73 65 72 74 28 20 64 62 2d 3e 62 52 65   assert( db->bRe
9750: 61 64 6f 6e 6c 79 20 26 26 20 64 62 2d 3e 70 53  adonly && db->pS
9760: 68 6d 68 64 72 3d 3d 30 20 29 3b 0a 20 20 61 73  hmhdr==0 );.  as
9770: 73 65 72 74 28 20 64 62 2d 3e 69 52 65 61 64 65  sert( db->iReade
9780: 72 3c 30 20 29 3b 0a 0a 20 20 69 66 28 20 64 62  r<0 );..  if( db
9790: 2d 3e 62 52 6f 54 72 61 6e 73 3d 3d 30 20 29 7b  ->bRoTrans==0 ){
97a0: 0a 0a 20 20 20 20 2f 2a 20 41 74 74 65 6d 70 74  ..    /* Attempt
97b0: 20 61 20 73 68 61 72 65 64 2d 6c 6f 63 6b 20 6f   a shared-lock o
97c0: 6e 20 44 4d 53 31 2e 20 2a 2f 0a 20 20 20 20 72  n DMS1. */.    r
97d0: 63 20 3d 20 6c 73 6d 53 68 6d 4c 6f 63 6b 28 64  c = lsmShmLock(d
97e0: 62 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 44 4d 53 31  b, LSM_LOCK_DMS1
97f0: 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 53 48 41 52 45  , LSM_LOCK_SHARE
9800: 44 2c 20 30 29 3b 0a 20 20 20 20 69 66 28 20 72  D, 0);.    if( r
9810: 63 21 3d 4c 53 4d 5f 4f 4b 20 29 20 72 65 74 75  c!=LSM_OK ) retu
9820: 72 6e 20 72 63 3b 0a 0a 20 20 20 20 72 63 20 3d  rn rc;..    rc =
9830: 20 6c 73 6d 53 68 6d 54 65 73 74 4c 6f 63 6b 28   lsmShmTestLock(
9840: 0a 20 20 20 20 20 20 20 20 64 62 2c 20 4c 53 4d  .        db, LSM
9850: 5f 4c 4f 43 4b 5f 52 57 43 4c 49 45 4e 54 28 30  _LOCK_RWCLIENT(0
9860: 29 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 4e 52 45 41  ), LSM_LOCK_NREA
9870: 44 45 52 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 53 48  DER, LSM_LOCK_SH
9880: 41 52 45 44 0a 20 20 20 20 29 3b 0a 20 20 20 20  ARED.    );.    
9890: 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 29  if( rc==LSM_OK )
98a0: 7b 0a 20 20 20 20 20 20 2f 2a 20 53 79 73 74 65  {.      /* Syste
98b0: 6d 20 69 73 20 6e 6f 74 20 6c 69 76 65 2e 20 54  m is not live. T
98c0: 61 6b 65 20 61 20 53 48 41 52 45 44 20 6c 6f 63  ake a SHARED loc
98d0: 6b 20 6f 6e 20 74 68 65 20 52 4f 54 52 41 4e 53  k on the ROTRANS
98e0: 20 62 79 74 65 20 61 6e 64 0a 20 20 20 20 20 20   byte and.      
98f0: 2a 2a 20 72 65 6c 65 61 73 65 20 44 4d 53 31 2e  ** release DMS1.
9900: 20 4c 6f 63 6b 69 6e 67 20 52 4f 54 52 41 4e 53   Locking ROTRANS
9910: 20 74 65 6c 6c 73 20 61 6c 6c 20 72 65 61 64 2d   tells all read-
9920: 77 72 69 74 65 20 63 6c 69 65 6e 74 73 20 74 68  write clients th
9930: 61 74 20 74 68 65 79 0a 20 20 20 20 20 20 2a 2a  at they.      **
9940: 20 6d 61 79 20 6e 6f 74 20 72 65 63 79 63 6c 65   may not recycle
9950: 20 61 6e 79 20 64 69 73 6b 20 73 70 61 63 65 20   any disk space 
9960: 66 72 6f 6d 20 77 69 74 68 69 6e 20 74 68 65 20  from within the 
9970: 64 61 74 61 62 61 73 65 20 6f 72 20 6c 6f 67 20  database or log 
9980: 66 69 6c 65 73 2c 0a 20 20 20 20 20 20 2a 2a 20  files,.      ** 
9990: 61 73 20 61 20 72 65 61 64 2d 6f 6e 6c 79 20 63  as a read-only c
99a0: 6c 69 65 6e 74 20 6d 61 79 20 62 65 20 75 73 69  lient may be usi
99b0: 6e 67 20 69 74 2e 20 20 2a 2f 0a 20 20 20 20 20  ng it.  */.     
99c0: 20 72 63 20 3d 20 6c 73 6d 53 68 6d 4c 6f 63 6b   rc = lsmShmLock
99d0: 28 64 62 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 52 4f  (db, LSM_LOCK_RO
99e0: 54 52 41 4e 53 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f  TRANS, LSM_LOCK_
99f0: 53 48 41 52 45 44 2c 20 30 29 3b 0a 20 20 20 20  SHARED, 0);.    
9a00: 20 20 6c 73 6d 53 68 6d 4c 6f 63 6b 28 64 62 2c    lsmShmLock(db,
9a10: 20 4c 53 4d 5f 4c 4f 43 4b 5f 44 4d 53 31 2c 20   LSM_LOCK_DMS1, 
9a20: 4c 53 4d 5f 4c 4f 43 4b 5f 55 4e 4c 4f 43 4b 2c  LSM_LOCK_UNLOCK,
9a30: 20 30 29 3b 0a 0a 20 20 20 20 20 20 69 66 28 20   0);..      if( 
9a40: 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 29 7b 0a 20 20  rc==LSM_OK ){.  
9a50: 20 20 20 20 20 20 64 62 2d 3e 62 52 6f 54 72 61        db->bRoTra
9a60: 6e 73 20 3d 20 31 3b 0a 20 20 20 20 20 20 20 20  ns = 1;.        
9a70: 72 63 20 3d 20 6c 73 6d 53 68 6d 43 61 63 68 65  rc = lsmShmCache
9a80: 43 68 75 6e 6b 73 28 64 62 2c 20 31 29 3b 0a 20  Chunks(db, 1);. 
9a90: 20 20 20 20 20 20 20 69 66 28 20 72 63 3d 3d 4c         if( rc==L
9aa0: 53 4d 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 20  SM_OK ){.       
9ab0: 20 20 20 64 62 2d 3e 70 53 68 6d 68 64 72 20 3d     db->pShmhdr =
9ac0: 20 28 53 68 6d 48 65 61 64 65 72 20 2a 29 64 62   (ShmHeader *)db
9ad0: 2d 3e 61 70 53 68 6d 5b 30 5d 3b 0a 20 20 20 20  ->apShm[0];.    
9ae0: 20 20 20 20 20 20 6d 65 6d 73 65 74 28 64 62 2d        memset(db-
9af0: 3e 70 53 68 6d 68 64 72 2c 20 30 2c 20 73 69 7a  >pShmhdr, 0, siz
9b00: 65 6f 66 28 53 68 6d 48 65 61 64 65 72 29 29 3b  eof(ShmHeader));
9b10: 0a 20 20 20 20 20 20 20 20 20 20 72 63 20 3d 20  .          rc = 
9b20: 6c 73 6d 43 68 65 63 6b 70 6f 69 6e 74 52 65 63  lsmCheckpointRec
9b30: 6f 76 65 72 28 64 62 29 3b 0a 20 20 20 20 20 20  over(db);.      
9b40: 20 20 20 20 69 66 28 20 72 63 3d 3d 4c 53 4d 5f      if( rc==LSM_
9b50: 4f 4b 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20  OK ){.          
9b60: 20 20 72 63 20 3d 20 6c 73 6d 4c 6f 67 52 65 63    rc = lsmLogRec
9b70: 6f 76 65 72 28 64 62 29 3b 0a 20 20 20 20 20 20  over(db);.      
9b80: 20 20 20 20 7d 0a 20 20 20 20 20 20 20 20 7d 0a      }.        }.
9b90: 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 65 6c 73        }.    }els
9ba0: 65 20 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 42 55  e if( rc==LSM_BU
9bb0: 53 59 20 29 7b 0a 20 20 20 20 20 20 2f 2a 20 53  SY ){.      /* S
9bc0: 79 73 74 65 6d 20 69 73 20 6c 69 76 65 21 20 2a  ystem is live! *
9bd0: 2f 0a 20 20 20 20 20 20 72 63 20 3d 20 6c 73 6d  /.      rc = lsm
9be0: 53 68 6d 4c 6f 63 6b 28 64 62 2c 20 4c 53 4d 5f  ShmLock(db, LSM_
9bf0: 4c 4f 43 4b 5f 44 4d 53 33 2c 20 4c 53 4d 5f 4c  LOCK_DMS3, LSM_L
9c00: 4f 43 4b 5f 53 48 41 52 45 44 2c 20 30 29 3b 0a  OCK_SHARED, 0);.
9c10: 20 20 20 20 20 20 6c 73 6d 53 68 6d 4c 6f 63 6b        lsmShmLock
9c20: 28 64 62 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 44 4d  (db, LSM_LOCK_DM
9c30: 53 31 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 55 4e 4c  S1, LSM_LOCK_UNL
9c40: 4f 43 4b 2c 20 30 29 3b 0a 20 20 20 20 20 20 69  OCK, 0);.      i
9c50: 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 29 7b  f( rc==LSM_OK ){
9c60: 0a 20 20 20 20 20 20 20 20 72 63 20 3d 20 6c 73  .        rc = ls
9c70: 6d 53 68 6d 43 61 63 68 65 43 68 75 6e 6b 73 28  mShmCacheChunks(
9c80: 64 62 2c 20 31 29 3b 0a 20 20 20 20 20 20 20 20  db, 1);.        
9c90: 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 29  if( rc==LSM_OK )
9ca0: 7b 0a 20 20 20 20 20 20 20 20 20 20 64 62 2d 3e  {.          db->
9cb0: 70 53 68 6d 68 64 72 20 3d 20 28 53 68 6d 48 65  pShmhdr = (ShmHe
9cc0: 61 64 65 72 20 2a 29 64 62 2d 3e 61 70 53 68 6d  ader *)db->apShm
9cd0: 5b 30 5d 3b 0a 20 20 20 20 20 20 20 20 7d 0a 20  [0];.        }. 
9ce0: 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a 0a 20 20       }.    }..  
9cf0: 20 20 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b    if( rc==LSM_OK
9d00: 20 29 7b 0a 20 20 20 20 20 20 72 63 20 3d 20 6c   ){.      rc = l
9d10: 73 6d 42 65 67 69 6e 52 65 61 64 54 72 61 6e 73  smBeginReadTrans
9d20: 28 64 62 29 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a  (db);.    }.  }.
9d30: 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a  .  return rc;.}.
9d40: 0a 2f 2a 0a 2a 2a 20 43 6c 6f 73 65 20 74 68 65  ./*.** Close the
9d50: 20 63 75 72 72 65 6e 74 6c 79 20 6f 70 65 6e 20   currently open 
9d60: 72 65 61 64 20 74 72 61 6e 73 61 63 74 69 6f 6e  read transaction
9d70: 2e 0a 2a 2f 0a 76 6f 69 64 20 6c 73 6d 46 69 6e  ..*/.void lsmFin
9d80: 69 73 68 52 65 61 64 54 72 61 6e 73 28 6c 73 6d  ishReadTrans(lsm
9d90: 5f 64 62 20 2a 70 44 62 29 7b 0a 0a 20 20 2f 2a  _db *pDb){..  /*
9da0: 20 57 6f 72 6b 65 72 20 63 6f 6e 6e 65 63 74 69   Worker connecti
9db0: 6f 6e 73 20 73 68 6f 75 6c 64 20 6e 6f 74 20 62  ons should not b
9dc0: 65 20 63 6c 6f 73 69 6e 67 20 72 65 61 64 20 74  e closing read t
9dd0: 72 61 6e 73 61 63 74 69 6f 6e 73 2e 20 41 6e 64  ransactions. And
9de0: 0a 20 20 2a 2a 20 72 65 61 64 20 74 72 61 6e 73  .  ** read trans
9df0: 61 63 74 69 6f 6e 73 20 73 68 6f 75 6c 64 20 6f  actions should o
9e00: 6e 6c 79 20 62 65 20 63 6c 6f 73 65 64 20 61 66  nly be closed af
9e10: 74 65 72 20 61 6c 6c 20 63 75 72 73 6f 72 73 20  ter all cursors 
9e20: 61 6e 64 20 77 72 69 74 65 0a 20 20 2a 2a 20 74  and write.  ** t
9e30: 72 61 6e 73 61 63 74 69 6f 6e 73 20 68 61 76 65  ransactions have
9e40: 20 62 65 65 6e 20 63 6c 6f 73 65 64 2e 20 46 69   been closed. Fi
9e50: 6e 61 6c 6c 79 20 70 43 6c 69 65 6e 74 20 73 68  nally pClient sh
9e60: 6f 75 6c 64 20 62 65 20 6e 6f 6e 2d 4e 55 4c 4c  ould be non-NULL
9e70: 0a 20 20 2a 2a 20 6f 6e 6c 79 20 69 66 66 20 70  .  ** only iff p
9e80: 44 62 2d 3e 69 52 65 61 64 65 72 3e 3d 30 2e 20  Db->iReader>=0. 
9e90: 20 2a 2f 0a 20 20 61 73 73 65 72 74 28 20 70 44   */.  assert( pD
9ea0: 62 2d 3e 70 57 6f 72 6b 65 72 3d 3d 30 20 29 3b  b->pWorker==0 );
9eb0: 0a 20 20 61 73 73 65 72 74 28 20 70 44 62 2d 3e  .  assert( pDb->
9ec0: 70 43 73 72 3d 3d 30 20 26 26 20 70 44 62 2d 3e  pCsr==0 && pDb->
9ed0: 6e 54 72 61 6e 73 4f 70 65 6e 3d 3d 30 20 29 3b  nTransOpen==0 );
9ee0: 0a 0a 20 20 69 66 28 20 70 44 62 2d 3e 62 52 6f  ..  if( pDb->bRo
9ef0: 54 72 61 6e 73 20 29 7b 0a 20 20 20 20 69 6e 74  Trans ){.    int
9f00: 20 69 3b 0a 20 20 20 20 66 6f 72 28 69 3d 30 3b   i;.    for(i=0;
9f10: 20 69 3c 70 44 62 2d 3e 6e 53 68 6d 3b 20 69 2b   i<pDb->nShm; i+
9f20: 2b 29 7b 0a 20 20 20 20 20 20 6c 73 6d 46 72 65  +){.      lsmFre
9f30: 65 28 70 44 62 2d 3e 70 45 6e 76 2c 20 70 44 62  e(pDb->pEnv, pDb
9f40: 2d 3e 61 70 53 68 6d 5b 69 5d 29 3b 0a 20 20 20  ->apShm[i]);.   
9f50: 20 7d 0a 20 20 20 20 6c 73 6d 46 72 65 65 28 70   }.    lsmFree(p
9f60: 44 62 2d 3e 70 45 6e 76 2c 20 70 44 62 2d 3e 61  Db->pEnv, pDb->a
9f70: 70 53 68 6d 29 3b 0a 20 20 20 20 70 44 62 2d 3e  pShm);.    pDb->
9f80: 61 70 53 68 6d 20 3d 20 30 3b 0a 20 20 20 20 70  apShm = 0;.    p
9f90: 44 62 2d 3e 6e 53 68 6d 20 3d 20 30 3b 0a 20 20  Db->nShm = 0;.  
9fa0: 20 20 70 44 62 2d 3e 70 53 68 6d 68 64 72 20 3d    pDb->pShmhdr =
9fb0: 20 30 3b 0a 0a 20 20 20 20 6c 73 6d 53 68 6d 4c   0;..    lsmShmL
9fc0: 6f 63 6b 28 70 44 62 2c 20 4c 53 4d 5f 4c 4f 43  ock(pDb, LSM_LOC
9fd0: 4b 5f 52 4f 54 52 41 4e 53 2c 20 4c 53 4d 5f 4c  K_ROTRANS, LSM_L
9fe0: 4f 43 4b 5f 55 4e 4c 4f 43 4b 2c 20 30 29 3b 0a  OCK_UNLOCK, 0);.
9ff0: 20 20 7d 0a 20 20 64 62 52 65 6c 65 61 73 65 52    }.  dbReleaseR
a000: 65 61 64 6c 6f 63 6b 28 70 44 62 29 3b 0a 7d 0a  eadlock(pDb);.}.
a010: 0a 2f 2a 0a 2a 2a 20 4f 70 65 6e 20 61 20 77 72  ./*.** Open a wr
a020: 69 74 65 20 74 72 61 6e 73 61 63 74 69 6f 6e 2e  ite transaction.
a030: 0a 2a 2f 0a 69 6e 74 20 6c 73 6d 42 65 67 69 6e  .*/.int lsmBegin
a040: 57 72 69 74 65 54 72 61 6e 73 28 6c 73 6d 5f 64  WriteTrans(lsm_d
a050: 62 20 2a 70 44 62 29 7b 0a 20 20 69 6e 74 20 72  b *pDb){.  int r
a060: 63 20 3d 20 4c 53 4d 5f 4f 4b 3b 20 20 20 20 20  c = LSM_OK;     
a070: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 52 65             /* Re
a080: 74 75 72 6e 20 63 6f 64 65 20 2a 2f 0a 20 20 53  turn code */.  S
a090: 68 6d 48 65 61 64 65 72 20 2a 70 53 68 6d 20 3d  hmHeader *pShm =
a0a0: 20 70 44 62 2d 3e 70 53 68 6d 68 64 72 3b 20 2f   pDb->pShmhdr; /
a0b0: 2a 20 53 68 61 72 65 64 20 6d 65 6d 6f 72 79 20  * Shared memory 
a0c0: 68 65 61 64 65 72 20 2a 2f 0a 0a 20 20 61 73 73  header */..  ass
a0d0: 65 72 74 28 20 70 44 62 2d 3e 6e 54 72 61 6e 73  ert( pDb->nTrans
a0e0: 4f 70 65 6e 3d 3d 30 20 29 3b 0a 20 20 61 73 73  Open==0 );.  ass
a0f0: 65 72 74 28 20 70 44 62 2d 3e 62 44 69 73 63 61  ert( pDb->bDisca
a100: 72 64 4f 6c 64 3d 3d 30 20 29 3b 0a 20 20 61 73  rdOld==0 );.  as
a110: 73 65 72 74 28 20 70 44 62 2d 3e 62 52 65 61 64  sert( pDb->bRead
a120: 6f 6e 6c 79 3d 3d 30 20 29 3b 0a 0a 20 20 2f 2a  only==0 );..  /*
a130: 20 49 66 20 74 68 65 72 65 20 69 73 20 6e 6f 20   If there is no 
a140: 72 65 61 64 2d 74 72 61 6e 73 61 63 74 69 6f 6e  read-transaction
a150: 20 6f 70 65 6e 2c 20 6f 70 65 6e 20 6f 6e 65 20   open, open one 
a160: 6e 6f 77 2e 20 2a 2f 0a 20 20 69 66 28 20 70 44  now. */.  if( pD
a170: 62 2d 3e 69 52 65 61 64 65 72 3c 30 20 29 7b 0a  b->iReader<0 ){.
a180: 20 20 20 20 72 63 20 3d 20 6c 73 6d 42 65 67 69      rc = lsmBegi
a190: 6e 52 65 61 64 54 72 61 6e 73 28 70 44 62 29 3b  nReadTrans(pDb);
a1a0: 0a 20 20 7d 0a 0a 20 20 2f 2a 20 41 74 74 65 6d  .  }..  /* Attem
a1b0: 70 74 20 74 6f 20 74 61 6b 65 20 74 68 65 20 57  pt to take the W
a1c0: 52 49 54 45 52 20 6c 6f 63 6b 20 2a 2f 0a 20 20  RITER lock */.  
a1d0: 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 29  if( rc==LSM_OK )
a1e0: 7b 0a 20 20 20 20 72 63 20 3d 20 6c 73 6d 53 68  {.    rc = lsmSh
a1f0: 6d 4c 6f 63 6b 28 70 44 62 2c 20 4c 53 4d 5f 4c  mLock(pDb, LSM_L
a200: 4f 43 4b 5f 57 52 49 54 45 52 2c 20 4c 53 4d 5f  OCK_WRITER, LSM_
a210: 4c 4f 43 4b 5f 45 58 43 4c 2c 20 30 29 3b 0a 20  LOCK_EXCL, 0);. 
a220: 20 7d 0a 0a 20 20 2f 2a 20 49 66 20 74 68 65 20   }..  /* If the 
a230: 70 72 65 76 69 6f 75 73 20 77 72 69 74 65 72 20  previous writer 
a240: 66 61 69 6c 65 64 20 6d 69 64 2d 74 72 61 6e 73  failed mid-trans
a250: 61 63 74 69 6f 6e 2c 20 72 75 6e 20 65 6d 65 72  action, run emer
a260: 67 65 6e 63 79 20 72 6f 6c 6c 62 61 63 6b 2e 20  gency rollback. 
a270: 2a 2f 0a 20 20 69 66 28 20 72 63 3d 3d 4c 53 4d  */.  if( rc==LSM
a280: 5f 4f 4b 20 26 26 20 70 53 68 6d 2d 3e 62 57 72  _OK && pShm->bWr
a290: 69 74 65 72 20 29 7b 0a 20 20 20 20 72 63 20 3d  iter ){.    rc =
a2a0: 20 6c 73 6d 54 72 65 65 52 65 70 61 69 72 28 70   lsmTreeRepair(p
a2b0: 44 62 29 3b 0a 20 20 20 20 69 66 28 20 72 63 3d  Db);.    if( rc=
a2c0: 3d 4c 53 4d 5f 4f 4b 20 29 20 70 53 68 6d 2d 3e  =LSM_OK ) pShm->
a2d0: 62 57 72 69 74 65 72 20 3d 20 30 3b 0a 20 20 7d  bWriter = 0;.  }
a2e0: 0a 0a 20 20 2f 2a 20 43 68 65 63 6b 20 74 68 61  ..  /* Check tha
a2f0: 74 20 74 68 69 73 20 63 6f 6e 6e 65 63 74 69 6f  t this connectio
a300: 6e 20 69 73 20 63 75 72 72 65 6e 74 6c 79 20 72  n is currently r
a310: 65 61 64 69 6e 67 20 66 72 6f 6d 20 74 68 65 20  eading from the 
a320: 6d 6f 73 74 20 72 65 63 65 6e 74 0a 20 20 2a 2a  most recent.  **
a330: 20 76 65 72 73 69 6f 6e 20 6f 66 20 74 68 65 20   version of the 
a340: 64 61 74 61 62 61 73 65 2e 20 49 66 20 6e 6f 74  database. If not
a350: 2c 20 72 65 74 75 72 6e 20 4c 53 4d 5f 42 55 53  , return LSM_BUS
a360: 59 2e 20 20 2a 2f 0a 20 20 69 66 28 20 72 63 3d  Y.  */.  if( rc=
a370: 3d 4c 53 4d 5f 4f 4b 20 26 26 20 6d 65 6d 63 6d  =LSM_OK && memcm
a380: 70 28 26 70 53 68 6d 2d 3e 68 64 72 31 2c 20 26  p(&pShm->hdr1, &
a390: 70 44 62 2d 3e 74 72 65 65 68 64 72 2c 20 73 69  pDb->treehdr, si
a3a0: 7a 65 6f 66 28 54 72 65 65 48 65 61 64 65 72 29  zeof(TreeHeader)
a3b0: 29 20 29 7b 0a 20 20 20 20 72 63 20 3d 20 4c 53  ) ){.    rc = LS
a3c0: 4d 5f 42 55 53 59 3b 0a 20 20 7d 0a 0a 20 20 69  M_BUSY;.  }..  i
a3d0: 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 29 7b  f( rc==LSM_OK ){
a3e0: 0a 20 20 20 20 72 63 20 3d 20 6c 73 6d 4c 6f 67  .    rc = lsmLog
a3f0: 42 65 67 69 6e 28 70 44 62 29 3b 0a 20 20 7d 0a  Begin(pDb);.  }.
a400: 0a 20 20 2f 2a 20 49 66 20 65 76 65 72 79 74 68  .  /* If everyth
a410: 69 6e 67 20 77 61 73 20 73 75 63 63 65 73 73 66  ing was successf
a420: 75 6c 2c 20 73 65 74 20 74 68 65 20 22 74 72 61  ul, set the "tra
a430: 6e 73 61 63 74 69 6f 6e 2d 69 6e 2d 70 72 6f 67  nsaction-in-prog
a440: 72 65 73 73 22 20 66 6c 61 67 0a 20 20 2a 2a 20  ress" flag.  ** 
a450: 61 6e 64 20 72 65 74 75 72 6e 20 4c 53 4d 5f 4f  and return LSM_O
a460: 4b 2e 20 4f 74 68 65 72 77 69 73 65 2c 20 69 66  K. Otherwise, if
a470: 20 73 6f 6d 65 20 65 72 72 6f 72 20 6f 63 63 75   some error occu
a480: 72 72 65 64 2c 20 72 65 6c 69 6e 71 75 69 73 68  rred, relinquish
a490: 20 74 68 65 20 0a 20 20 2a 2a 20 57 52 49 54 45   the .  ** WRITE
a4a0: 52 20 6c 6f 63 6b 20 61 6e 64 20 72 65 74 75 72  R lock and retur
a4b0: 6e 20 61 6e 20 65 72 72 6f 72 20 63 6f 64 65 2e  n an error code.
a4c0: 20 20 2a 2f 0a 20 20 69 66 28 20 72 63 3d 3d 4c    */.  if( rc==L
a4d0: 53 4d 5f 4f 4b 20 29 7b 0a 20 20 20 20 54 72 65  SM_OK ){.    Tre
a4e0: 65 48 65 61 64 65 72 20 2a 70 20 3d 20 26 70 44  eHeader *p = &pD
a4f0: 62 2d 3e 74 72 65 65 68 64 72 3b 0a 20 20 20 20  b->treehdr;.    
a500: 70 53 68 6d 2d 3e 62 57 72 69 74 65 72 20 3d 20  pShm->bWriter = 
a510: 31 3b 0a 20 20 20 20 70 2d 3e 72 6f 6f 74 2e 69  1;.    p->root.i
a520: 54 72 61 6e 73 49 64 2b 2b 3b 0a 20 20 20 20 69  TransId++;.    i
a530: 66 28 20 6c 73 6d 54 72 65 65 48 61 73 4f 6c 64  f( lsmTreeHasOld
a540: 28 70 44 62 29 20 26 26 20 70 2d 3e 69 4f 6c 64  (pDb) && p->iOld
a550: 4c 6f 67 3d 3d 70 44 62 2d 3e 70 43 6c 69 65 6e  Log==pDb->pClien
a560: 74 2d 3e 69 4c 6f 67 4f 66 66 20 29 7b 0a 20 20  t->iLogOff ){.  
a570: 20 20 20 20 6c 73 6d 54 72 65 65 44 69 73 63 61      lsmTreeDisca
a580: 72 64 4f 6c 64 28 70 44 62 29 3b 0a 20 20 20 20  rdOld(pDb);.    
a590: 20 20 70 44 62 2d 3e 62 44 69 73 63 61 72 64 4f    pDb->bDiscardO
a5a0: 6c 64 20 3d 20 31 3b 0a 20 20 20 20 7d 0a 20 20  ld = 1;.    }.  
a5b0: 7d 65 6c 73 65 7b 0a 20 20 20 20 6c 73 6d 53 68  }else{.    lsmSh
a5c0: 6d 4c 6f 63 6b 28 70 44 62 2c 20 4c 53 4d 5f 4c  mLock(pDb, LSM_L
a5d0: 4f 43 4b 5f 57 52 49 54 45 52 2c 20 4c 53 4d 5f  OCK_WRITER, LSM_
a5e0: 4c 4f 43 4b 5f 55 4e 4c 4f 43 4b 2c 20 30 29 3b  LOCK_UNLOCK, 0);
a5f0: 0a 20 20 20 20 69 66 28 20 70 44 62 2d 3e 70 43  .    if( pDb->pC
a600: 73 72 3d 3d 30 20 29 20 6c 73 6d 46 69 6e 69 73  sr==0 ) lsmFinis
a610: 68 52 65 61 64 54 72 61 6e 73 28 70 44 62 29 3b  hReadTrans(pDb);
a620: 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20 72 63  .  }.  return rc
a630: 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 45 6e 64 20 74  ;.}../*.** End t
a640: 68 65 20 63 75 72 72 65 6e 74 20 77 72 69 74 65  he current write
a650: 20 74 72 61 6e 73 61 63 74 69 6f 6e 2e 20 54 68   transaction. Th
a660: 65 20 63 6f 6e 6e 65 63 74 69 6f 6e 20 69 73 20  e connection is 
a670: 6c 65 66 74 20 77 69 74 68 20 61 6e 20 6f 70 65  left with an ope
a680: 6e 0a 2a 2a 20 72 65 61 64 20 74 72 61 6e 73 61  n.** read transa
a690: 63 74 69 6f 6e 2e 20 49 74 20 69 73 20 61 6e 20  ction. It is an 
a6a0: 65 72 72 6f 72 20 74 6f 20 63 61 6c 6c 20 74 68  error to call th
a6b0: 69 73 20 69 66 20 74 68 65 72 65 20 69 73 20 6e  is if there is n
a6c0: 6f 20 6f 70 65 6e 20 77 72 69 74 65 20 0a 2a 2a  o open write .**
a6d0: 20 74 72 61 6e 73 61 63 74 69 6f 6e 2e 0a 2a 2a   transaction..**
a6e0: 0a 2a 2a 20 49 66 20 74 68 65 20 74 72 61 6e 73  .** If the trans
a6f0: 61 63 74 69 6f 6e 20 77 61 73 20 63 6f 6d 6d 69  action was commi
a700: 74 74 65 64 2c 20 74 68 65 6e 20 61 20 63 6f 6d  tted, then a com
a710: 6d 69 74 20 72 65 63 6f 72 64 20 68 61 73 20 61  mit record has a
a720: 6c 72 65 61 64 79 20 62 65 65 6e 0a 2a 2a 20 77  lready been.** w
a730: 72 69 74 74 65 6e 20 69 6e 74 6f 20 74 68 65 20  ritten into the 
a740: 6c 6f 67 20 66 69 6c 65 20 77 68 65 6e 20 74 68  log file when th
a750: 69 73 20 66 75 6e 63 74 69 6f 6e 20 69 73 20 63  is function is c
a760: 61 6c 6c 65 64 2e 20 4f 72 2c 20 69 66 20 74 68  alled. Or, if th
a770: 65 0a 2a 2a 20 74 72 61 6e 73 61 63 74 69 6f 6e  e.** transaction
a780: 20 77 61 73 20 72 6f 6c 6c 65 64 20 62 61 63 6b   was rolled back
a790: 2c 20 62 6f 74 68 20 74 68 65 20 6c 6f 67 20 66  , both the log f
a7a0: 69 6c 65 20 61 6e 64 20 69 6e 2d 6d 65 6d 6f 72  ile and in-memor
a7b0: 79 20 74 72 65 65 20 0a 2a 2a 20 73 74 72 75 63  y tree .** struc
a7c0: 74 75 72 65 20 68 61 76 65 20 61 6c 72 65 61 64  ture have alread
a7d0: 79 20 62 65 65 6e 20 72 65 73 74 6f 72 65 64 2e  y been restored.
a7e0: 20 49 6e 20 65 69 74 68 65 72 20 63 61 73 65 2c   In either case,
a7f0: 20 74 68 69 73 20 66 75 6e 63 74 69 6f 6e 20 0a   this function .
a800: 2a 2a 20 6d 65 72 65 6c 79 20 72 65 6c 65 61 73  ** merely releas
a810: 65 73 20 6c 6f 63 6b 73 20 61 6e 64 20 6f 74 68  es locks and oth
a820: 65 72 20 72 65 73 6f 75 72 63 65 73 20 68 65 6c  er resources hel
a830: 64 20 62 79 20 74 68 65 20 77 72 69 74 65 2d 74  d by the write-t
a840: 72 61 6e 73 61 63 74 69 6f 6e 2e 0a 2a 2a 0a 2a  ransaction..**.*
a850: 2a 20 4c 53 4d 5f 4f 4b 20 69 73 20 72 65 74 75  * LSM_OK is retu
a860: 72 6e 65 64 20 69 66 20 73 75 63 63 65 73 73 66  rned if successf
a870: 75 6c 2c 20 6f 72 20 61 6e 20 4c 53 4d 20 65 72  ul, or an LSM er
a880: 72 6f 72 20 63 6f 64 65 20 6f 74 68 65 72 77 69  ror code otherwi
a890: 73 65 2e 0a 2a 2f 0a 69 6e 74 20 6c 73 6d 46 69  se..*/.int lsmFi
a8a0: 6e 69 73 68 57 72 69 74 65 54 72 61 6e 73 28 6c  nishWriteTrans(l
a8b0: 73 6d 5f 64 62 20 2a 70 44 62 2c 20 69 6e 74 20  sm_db *pDb, int 
a8c0: 62 43 6f 6d 6d 69 74 29 7b 0a 20 20 69 6e 74 20  bCommit){.  int 
a8d0: 72 63 20 3d 20 4c 53 4d 5f 4f 4b 3b 0a 20 20 69  rc = LSM_OK;.  i
a8e0: 6e 74 20 62 46 6c 75 73 68 20 3d 20 30 3b 0a 0a  nt bFlush = 0;..
a8f0: 20 20 6c 73 6d 4c 6f 67 45 6e 64 28 70 44 62 2c    lsmLogEnd(pDb,
a900: 20 62 43 6f 6d 6d 69 74 29 3b 0a 20 20 69 66 28   bCommit);.  if(
a910: 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 26 26 20 62   rc==LSM_OK && b
a920: 43 6f 6d 6d 69 74 20 26 26 20 6c 73 6d 54 72 65  Commit && lsmTre
a930: 65 53 69 7a 65 28 70 44 62 29 3e 70 44 62 2d 3e  eSize(pDb)>pDb->
a940: 6e 54 72 65 65 4c 69 6d 69 74 20 29 7b 0a 20 20  nTreeLimit ){.  
a950: 20 20 62 46 6c 75 73 68 20 3d 20 31 3b 0a 20 20    bFlush = 1;.  
a960: 20 20 6c 73 6d 54 72 65 65 4d 61 6b 65 4f 6c 64    lsmTreeMakeOld
a970: 28 70 44 62 29 3b 0a 20 20 7d 0a 20 20 6c 73 6d  (pDb);.  }.  lsm
a980: 54 72 65 65 45 6e 64 54 72 61 6e 73 61 63 74 69  TreeEndTransacti
a990: 6f 6e 28 70 44 62 2c 20 62 43 6f 6d 6d 69 74 29  on(pDb, bCommit)
a9a0: 3b 0a 0a 20 20 69 66 28 20 72 63 3d 3d 4c 53 4d  ;..  if( rc==LSM
a9b0: 5f 4f 4b 20 29 7b 0a 20 20 20 20 69 66 28 20 62  _OK ){.    if( b
a9c0: 46 6c 75 73 68 20 26 26 20 70 44 62 2d 3e 62 41  Flush && pDb->bA
a9d0: 75 74 6f 77 6f 72 6b 20 29 7b 0a 20 20 20 20 20  utowork ){.     
a9e0: 20 72 63 20 3d 20 6c 73 6d 53 6f 72 74 65 64 41   rc = lsmSortedA
a9f0: 75 74 6f 57 6f 72 6b 28 70 44 62 2c 20 31 29 3b  utoWork(pDb, 1);
aa00: 0a 20 20 20 20 7d 65 6c 73 65 20 69 66 28 20 62  .    }else if( b
aa10: 43 6f 6d 6d 69 74 20 26 26 20 70 44 62 2d 3e 62  Commit && pDb->b
aa20: 44 69 73 63 61 72 64 4f 6c 64 20 29 7b 0a 20 20  DiscardOld ){.  
aa30: 20 20 20 20 72 63 20 3d 20 64 62 53 65 74 52 65      rc = dbSetRe
aa40: 61 64 4c 6f 63 6b 28 70 44 62 2c 20 70 44 62 2d  adLock(pDb, pDb-
aa50: 3e 70 43 6c 69 65 6e 74 2d 3e 69 49 64 2c 20 70  >pClient->iId, p
aa60: 44 62 2d 3e 74 72 65 65 68 64 72 2e 69 55 73 65  Db->treehdr.iUse
aa70: 64 53 68 6d 69 64 29 3b 0a 20 20 20 20 7d 0a 20  dShmid);.    }. 
aa80: 20 7d 0a 20 20 70 44 62 2d 3e 62 44 69 73 63 61   }.  pDb->bDisca
aa90: 72 64 4f 6c 64 20 3d 20 30 3b 0a 20 20 6c 73 6d  rdOld = 0;.  lsm
aaa0: 53 68 6d 4c 6f 63 6b 28 70 44 62 2c 20 4c 53 4d  ShmLock(pDb, LSM
aab0: 5f 4c 4f 43 4b 5f 57 52 49 54 45 52 2c 20 4c 53  _LOCK_WRITER, LS
aac0: 4d 5f 4c 4f 43 4b 5f 55 4e 4c 4f 43 4b 2c 20 30  M_LOCK_UNLOCK, 0
aad0: 29 3b 0a 0a 20 20 69 66 28 20 62 46 6c 75 73 68  );..  if( bFlush
aae0: 20 26 26 20 70 44 62 2d 3e 62 41 75 74 6f 77 6f   && pDb->bAutowo
aaf0: 72 6b 3d 3d 30 20 26 26 20 70 44 62 2d 3e 78 57  rk==0 && pDb->xW
ab00: 6f 72 6b 20 29 7b 0a 20 20 20 20 70 44 62 2d 3e  ork ){.    pDb->
ab10: 78 57 6f 72 6b 28 70 44 62 2c 20 70 44 62 2d 3e  xWork(pDb, pDb->
ab20: 70 57 6f 72 6b 43 74 78 29 3b 0a 20 20 7d 0a 20  pWorkCtx);.  }. 
ab30: 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 0a   return rc;.}...
ab40: 2f 2a 0a 2a 2a 20 52 65 74 75 72 6e 20 6e 6f 6e  /*.** Return non
ab50: 2d 7a 65 72 6f 20 69 66 20 74 68 65 20 63 61 6c  -zero if the cal
ab60: 6c 65 72 20 69 73 20 68 6f 6c 64 69 6e 67 20 74  ler is holding t
ab70: 68 65 20 63 6c 69 65 6e 74 20 6d 75 74 65 78 2e  he client mutex.
ab80: 0a 2a 2f 0a 23 69 66 64 65 66 20 4c 53 4d 5f 44  .*/.#ifdef LSM_D
ab90: 45 42 55 47 0a 69 6e 74 20 6c 73 6d 48 6f 6c 64  EBUG.int lsmHold
aba0: 69 6e 67 43 6c 69 65 6e 74 4d 75 74 65 78 28 6c  ingClientMutex(l
abb0: 73 6d 5f 64 62 20 2a 70 44 62 29 7b 0a 20 20 72  sm_db *pDb){.  r
abc0: 65 74 75 72 6e 20 6c 73 6d 4d 75 74 65 78 48 65  eturn lsmMutexHe
abd0: 6c 64 28 70 44 62 2d 3e 70 45 6e 76 2c 20 70 44  ld(pDb->pEnv, pD
abe0: 62 2d 3e 70 44 61 74 61 62 61 73 65 2d 3e 70 43  b->pDatabase->pC
abf0: 6c 69 65 6e 74 4d 75 74 65 78 29 3b 0a 7d 0a 23  lientMutex);.}.#
ac00: 65 6e 64 69 66 0a 0a 73 74 61 74 69 63 20 69 6e  endif..static in
ac10: 74 20 73 6c 6f 74 49 73 55 73 61 62 6c 65 28 53  t slotIsUsable(S
ac20: 68 6d 52 65 61 64 65 72 20 2a 70 2c 20 69 36 34  hmReader *p, i64
ac30: 20 69 4c 73 6d 2c 20 75 33 32 20 69 53 68 6d 4d   iLsm, u32 iShmM
ac40: 69 6e 2c 20 75 33 32 20 69 53 68 6d 4d 61 78 29  in, u32 iShmMax)
ac50: 7b 0a 20 20 72 65 74 75 72 6e 28 20 0a 20 20 20  {.  return( .   
ac60: 20 20 20 70 2d 3e 69 4c 73 6d 49 64 20 26 26 20     p->iLsmId && 
ac70: 70 2d 3e 69 4c 73 6d 49 64 3c 3d 69 4c 73 6d 20  p->iLsmId<=iLsm 
ac80: 0a 20 20 20 20 20 20 26 26 20 73 68 6d 5f 73 65  .      && shm_se
ac90: 71 75 65 6e 63 65 5f 67 65 28 69 53 68 6d 4d 61  quence_ge(iShmMa
aca0: 78 2c 20 70 2d 3e 69 54 72 65 65 49 64 29 0a 20  x, p->iTreeId). 
acb0: 20 20 20 20 20 26 26 20 73 68 6d 5f 73 65 71 75       && shm_sequ
acc0: 65 6e 63 65 5f 67 65 28 70 2d 3e 69 54 72 65 65  ence_ge(p->iTree
acd0: 49 64 2c 20 69 53 68 6d 4d 69 6e 29 0a 20 20 29  Id, iShmMin).  )
ace0: 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 4f 62 74 61 69  ;.}../*.** Obtai
acf0: 6e 20 61 20 72 65 61 64 2d 6c 6f 63 6b 20 6f 6e  n a read-lock on
ad00: 20 64 61 74 61 62 61 73 65 20 76 65 72 73 69 6f   database versio
ad10: 6e 20 69 64 65 6e 74 69 66 69 65 64 20 62 79 20  n identified by 
ad20: 74 68 65 20 63 6f 6d 62 69 6e 61 74 69 6f 6e 0a  the combination.
ad30: 2a 2a 20 6f 66 20 73 6e 61 70 73 68 6f 74 20 69  ** of snapshot i
ad40: 4c 73 6d 20 61 6e 64 20 74 72 65 65 20 69 54 72  Lsm and tree iTr
ad50: 65 65 2e 20 52 65 74 75 72 6e 20 4c 53 4d 5f 4f  ee. Return LSM_O
ad60: 4b 20 69 66 20 73 75 63 63 65 73 73 66 75 6c 2c  K if successful,
ad70: 20 6f 72 0a 2a 2a 20 61 6e 20 4c 53 4d 20 65 72   or.** an LSM er
ad80: 72 6f 72 20 63 6f 64 65 20 6f 74 68 65 72 77 69  ror code otherwi
ad90: 73 65 2e 0a 2a 2f 0a 69 6e 74 20 6c 73 6d 52 65  se..*/.int lsmRe
ada0: 61 64 6c 6f 63 6b 28 6c 73 6d 5f 64 62 20 2a 64  adlock(lsm_db *d
adb0: 62 2c 20 69 36 34 20 69 4c 73 6d 2c 20 75 33 32  b, i64 iLsm, u32
adc0: 20 69 53 68 6d 4d 69 6e 2c 20 75 33 32 20 69 53   iShmMin, u32 iS
add0: 68 6d 4d 61 78 29 7b 0a 20 20 69 6e 74 20 72 63  hmMax){.  int rc
ade0: 20 3d 20 4c 53 4d 5f 4f 4b 3b 0a 20 20 53 68 6d   = LSM_OK;.  Shm
adf0: 48 65 61 64 65 72 20 2a 70 53 68 6d 20 3d 20 64  Header *pShm = d
ae00: 62 2d 3e 70 53 68 6d 68 64 72 3b 0a 20 20 69 6e  b->pShmhdr;.  in
ae10: 74 20 69 3b 0a 0a 20 20 61 73 73 65 72 74 28 20  t i;..  assert( 
ae20: 64 62 2d 3e 69 52 65 61 64 65 72 3c 30 20 29 3b  db->iReader<0 );
ae30: 0a 20 20 61 73 73 65 72 74 28 20 73 68 6d 5f 73  .  assert( shm_s
ae40: 65 71 75 65 6e 63 65 5f 67 65 28 69 53 68 6d 4d  equence_ge(iShmM
ae50: 61 78 2c 20 69 53 68 6d 4d 69 6e 29 20 29 3b 0a  ax, iShmMin) );.
ae60: 0a 20 20 2f 2a 20 54 68 69 73 20 69 73 20 61 20  .  /* This is a 
ae70: 6e 6f 2d 6f 70 20 69 66 20 74 68 65 20 72 65 61  no-op if the rea
ae80: 64 2d 6f 6e 6c 79 20 74 72 61 6e 73 61 63 74 69  d-only transacti
ae90: 6f 6e 20 66 6c 61 67 20 69 73 20 73 65 74 2e 20  on flag is set. 
aea0: 2a 2f 0a 20 20 69 66 28 20 64 62 2d 3e 62 52 6f  */.  if( db->bRo
aeb0: 54 72 61 6e 73 20 29 7b 0a 20 20 20 20 64 62 2d  Trans ){.    db-
aec0: 3e 69 52 65 61 64 65 72 20 3d 20 30 3b 0a 20 20  >iReader = 0;.  
aed0: 20 20 72 65 74 75 72 6e 20 4c 53 4d 5f 4f 4b 3b    return LSM_OK;
aee0: 0a 20 20 7d 0a 0a 20 20 2f 2a 20 53 65 61 72 63  .  }..  /* Searc
aef0: 68 20 66 6f 72 20 61 6e 20 65 78 61 63 74 20 6d  h for an exact m
af00: 61 74 63 68 2e 20 2a 2f 0a 20 20 66 6f 72 28 69  atch. */.  for(i
af10: 3d 30 3b 20 64 62 2d 3e 69 52 65 61 64 65 72 3c  =0; db->iReader<
af20: 30 20 26 26 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20  0 && rc==LSM_OK 
af30: 26 26 20 69 3c 4c 53 4d 5f 4c 4f 43 4b 5f 4e 52  && i<LSM_LOCK_NR
af40: 45 41 44 45 52 3b 20 69 2b 2b 29 7b 0a 20 20 20  EADER; i++){.   
af50: 20 53 68 6d 52 65 61 64 65 72 20 2a 70 20 3d 20   ShmReader *p = 
af60: 26 70 53 68 6d 2d 3e 61 52 65 61 64 65 72 5b 69  &pShm->aReader[i
af70: 5d 3b 0a 20 20 20 20 69 66 28 20 70 2d 3e 69 4c  ];.    if( p->iL
af80: 73 6d 49 64 3d 3d 69 4c 73 6d 20 26 26 20 70 2d  smId==iLsm && p-
af90: 3e 69 54 72 65 65 49 64 3d 3d 69 53 68 6d 4d 61  >iTreeId==iShmMa
afa0: 78 20 29 7b 0a 20 20 20 20 20 20 72 63 20 3d 20  x ){.      rc = 
afb0: 6c 73 6d 53 68 6d 4c 6f 63 6b 28 64 62 2c 20 4c  lsmShmLock(db, L
afc0: 53 4d 5f 4c 4f 43 4b 5f 52 45 41 44 45 52 28 69  SM_LOCK_READER(i
afd0: 29 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 53 48 41 52  ), LSM_LOCK_SHAR
afe0: 45 44 2c 20 30 29 3b 0a 20 20 20 20 20 20 69 66  ED, 0);.      if
aff0: 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 26 26 20  ( rc==LSM_OK && 
b000: 70 2d 3e 69 4c 73 6d 49 64 3d 3d 69 4c 73 6d 20  p->iLsmId==iLsm 
b010: 26 26 20 70 2d 3e 69 54 72 65 65 49 64 3d 3d 69  && p->iTreeId==i
b020: 53 68 6d 4d 61 78 20 29 7b 0a 20 20 20 20 20 20  ShmMax ){.      
b030: 20 20 64 62 2d 3e 69 52 65 61 64 65 72 20 3d 20    db->iReader = 
b040: 69 3b 0a 20 20 20 20 20 20 7d 65 6c 73 65 20 69  i;.      }else i
b050: 66 28 20 72 63 3d 3d 4c 53 4d 5f 42 55 53 59 20  f( rc==LSM_BUSY 
b060: 29 7b 0a 20 20 20 20 20 20 20 20 72 63 20 3d 20  ){.        rc = 
b070: 4c 53 4d 5f 4f 4b 3b 0a 20 20 20 20 20 20 7d 0a  LSM_OK;.      }.
b080: 20 20 20 20 7d 0a 20 20 7d 0a 0a 20 20 2f 2a 20      }.  }..  /* 
b090: 54 72 79 20 74 6f 20 6f 62 74 61 69 6e 20 61 20  Try to obtain a 
b0a0: 77 72 69 74 65 2d 6c 6f 63 6b 20 6f 6e 20 65 61  write-lock on ea
b0b0: 63 68 20 73 6c 6f 74 2c 20 69 6e 20 6f 72 64 65  ch slot, in orde
b0c0: 72 2e 20 49 66 20 73 75 63 63 65 73 73 66 75 6c  r. If successful
b0d0: 2c 20 73 65 74 0a 20 20 2a 2a 20 74 68 65 20 73  , set.  ** the s
b0e0: 6c 6f 74 20 76 61 6c 75 65 73 20 74 6f 20 69 4c  lot values to iL
b0f0: 73 6d 2f 69 54 72 65 65 2e 20 20 2a 2f 0a 20 20  sm/iTree.  */.  
b100: 66 6f 72 28 69 3d 30 3b 20 64 62 2d 3e 69 52 65  for(i=0; db->iRe
b110: 61 64 65 72 3c 30 20 26 26 20 72 63 3d 3d 4c 53  ader<0 && rc==LS
b120: 4d 5f 4f 4b 20 26 26 20 69 3c 4c 53 4d 5f 4c 4f  M_OK && i<LSM_LO
b130: 43 4b 5f 4e 52 45 41 44 45 52 3b 20 69 2b 2b 29  CK_NREADER; i++)
b140: 7b 0a 20 20 20 20 72 63 20 3d 20 6c 73 6d 53 68  {.    rc = lsmSh
b150: 6d 4c 6f 63 6b 28 64 62 2c 20 4c 53 4d 5f 4c 4f  mLock(db, LSM_LO
b160: 43 4b 5f 52 45 41 44 45 52 28 69 29 2c 20 4c 53  CK_READER(i), LS
b170: 4d 5f 4c 4f 43 4b 5f 45 58 43 4c 2c 20 30 29 3b  M_LOCK_EXCL, 0);
b180: 0a 20 20 20 20 69 66 28 20 72 63 3d 3d 4c 53 4d  .    if( rc==LSM
b190: 5f 42 55 53 59 20 29 7b 0a 20 20 20 20 20 20 72  _BUSY ){.      r
b1a0: 63 20 3d 20 4c 53 4d 5f 4f 4b 3b 0a 20 20 20 20  c = LSM_OK;.    
b1b0: 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 53 68 6d  }else{.      Shm
b1c0: 52 65 61 64 65 72 20 2a 70 20 3d 20 26 70 53 68  Reader *p = &pSh
b1d0: 6d 2d 3e 61 52 65 61 64 65 72 5b 69 5d 3b 0a 20  m->aReader[i];. 
b1e0: 20 20 20 20 20 70 2d 3e 69 4c 73 6d 49 64 20 3d       p->iLsmId =
b1f0: 20 69 4c 73 6d 3b 0a 20 20 20 20 20 20 70 2d 3e   iLsm;.      p->
b200: 69 54 72 65 65 49 64 20 3d 20 69 53 68 6d 4d 61  iTreeId = iShmMa
b210: 78 3b 0a 20 20 20 20 20 20 72 63 20 3d 20 6c 73  x;.      rc = ls
b220: 6d 53 68 6d 4c 6f 63 6b 28 64 62 2c 20 4c 53 4d  mShmLock(db, LSM
b230: 5f 4c 4f 43 4b 5f 52 45 41 44 45 52 28 69 29 2c  _LOCK_READER(i),
b240: 20 4c 53 4d 5f 4c 4f 43 4b 5f 53 48 41 52 45 44   LSM_LOCK_SHARED
b250: 2c 20 30 29 3b 0a 20 20 20 20 20 20 61 73 73 65  , 0);.      asse
b260: 72 74 28 20 72 63 21 3d 4c 53 4d 5f 42 55 53 59  rt( rc!=LSM_BUSY
b270: 20 29 3b 0a 20 20 20 20 20 20 69 66 28 20 72 63   );.      if( rc
b280: 3d 3d 4c 53 4d 5f 4f 4b 20 29 20 64 62 2d 3e 69  ==LSM_OK ) db->i
b290: 52 65 61 64 65 72 20 3d 20 69 3b 0a 20 20 20 20  Reader = i;.    
b2a0: 7d 0a 20 20 7d 0a 0a 20 20 2f 2a 20 53 65 61 72  }.  }..  /* Sear
b2b0: 63 68 20 66 6f 72 20 61 6e 79 20 75 73 61 62 6c  ch for any usabl
b2c0: 65 20 73 6c 6f 74 20 2a 2f 0a 20 20 66 6f 72 28  e slot */.  for(
b2d0: 69 3d 30 3b 20 64 62 2d 3e 69 52 65 61 64 65 72  i=0; db->iReader
b2e0: 3c 30 20 26 26 20 72 63 3d 3d 4c 53 4d 5f 4f 4b  <0 && rc==LSM_OK
b2f0: 20 26 26 20 69 3c 4c 53 4d 5f 4c 4f 43 4b 5f 4e   && i<LSM_LOCK_N
b300: 52 45 41 44 45 52 3b 20 69 2b 2b 29 7b 0a 20 20  READER; i++){.  
b310: 20 20 53 68 6d 52 65 61 64 65 72 20 2a 70 20 3d    ShmReader *p =
b320: 20 26 70 53 68 6d 2d 3e 61 52 65 61 64 65 72 5b   &pShm->aReader[
b330: 69 5d 3b 0a 20 20 20 20 69 66 28 20 73 6c 6f 74  i];.    if( slot
b340: 49 73 55 73 61 62 6c 65 28 70 2c 20 69 4c 73 6d  IsUsable(p, iLsm
b350: 2c 20 69 53 68 6d 4d 69 6e 2c 20 69 53 68 6d 4d  , iShmMin, iShmM
b360: 61 78 29 20 29 7b 0a 20 20 20 20 20 20 72 63 20  ax) ){.      rc 
b370: 3d 20 6c 73 6d 53 68 6d 4c 6f 63 6b 28 64 62 2c  = lsmShmLock(db,
b380: 20 4c 53 4d 5f 4c 4f 43 4b 5f 52 45 41 44 45 52   LSM_LOCK_READER
b390: 28 69 29 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 53 48  (i), LSM_LOCK_SH
b3a0: 41 52 45 44 2c 20 30 29 3b 0a 20 20 20 20 20 20  ARED, 0);.      
b3b0: 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 26  if( rc==LSM_OK &
b3c0: 26 20 73 6c 6f 74 49 73 55 73 61 62 6c 65 28 70  & slotIsUsable(p
b3d0: 2c 20 69 4c 73 6d 2c 20 69 53 68 6d 4d 69 6e 2c  , iLsm, iShmMin,
b3e0: 20 69 53 68 6d 4d 61 78 29 20 29 7b 0a 20 20 20   iShmMax) ){.   
b3f0: 20 20 20 20 20 64 62 2d 3e 69 52 65 61 64 65 72       db->iReader
b400: 20 3d 20 69 3b 0a 20 20 20 20 20 20 7d 65 6c 73   = i;.      }els
b410: 65 20 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 42 55  e if( rc==LSM_BU
b420: 53 59 20 29 7b 0a 20 20 20 20 20 20 20 20 72 63  SY ){.        rc
b430: 20 3d 20 4c 53 4d 5f 4f 4b 3b 0a 20 20 20 20 20   = LSM_OK;.     
b440: 20 7d 0a 20 20 20 20 7d 0a 20 20 7d 0a 0a 20 20   }.    }.  }..  
b450: 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 26  if( rc==LSM_OK &
b460: 26 20 64 62 2d 3e 69 52 65 61 64 65 72 3c 30 20  & db->iReader<0 
b470: 29 7b 0a 20 20 20 20 72 63 20 3d 20 4c 53 4d 5f  ){.    rc = LSM_
b480: 42 55 53 59 3b 0a 20 20 7d 0a 20 20 72 65 74 75  BUSY;.  }.  retu
b490: 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20  rn rc;.}../*.** 
b4a0: 54 68 69 73 20 69 73 20 75 73 65 64 20 74 6f 20  This is used to 
b4b0: 63 68 65 63 6b 20 69 66 20 74 68 65 72 65 20 65  check if there e
b4c0: 78 69 73 74 73 20 61 20 72 65 61 64 2d 6c 6f 63  xists a read-loc
b4d0: 6b 20 6c 6f 63 6b 69 6e 67 20 61 20 70 61 72 74  k locking a part
b4e0: 69 63 75 6c 61 72 0a 2a 2a 20 76 65 72 73 69 6f  icular.** versio
b4f0: 6e 20 6f 66 20 65 69 74 68 65 72 20 74 68 65 20  n of either the 
b500: 69 6e 2d 6d 65 6d 6f 72 79 20 74 72 65 65 20 6f  in-memory tree o
b510: 72 20 64 61 74 61 62 61 73 65 20 66 69 6c 65 2e  r database file.
b520: 20 0a 2a 2a 0a 2a 2a 20 49 66 20 69 4c 73 6d 49   .**.** If iLsmI
b530: 64 20 69 73 20 6e 6f 6e 2d 7a 65 72 6f 2c 20 74  d is non-zero, t
b540: 68 65 6e 20 69 74 20 69 73 20 61 20 73 6e 61 70  hen it is a snap
b550: 73 68 6f 74 20 69 64 2e 20 49 66 20 74 68 65 72  shot id. If ther
b560: 65 20 65 78 69 73 74 73 20 61 20 0a 2a 2a 20 72  e exists a .** r
b570: 65 61 64 2d 6c 6f 63 6b 20 75 73 69 6e 67 20 74  ead-lock using t
b580: 68 69 73 20 73 6e 61 70 73 68 6f 74 20 6f 72 20  his snapshot or 
b590: 6e 65 77 65 72 2c 20 73 65 74 20 2a 70 62 49 6e  newer, set *pbIn
b5a0: 55 73 65 20 74 6f 20 74 72 75 65 2e 20 4f 72 2c  Use to true. Or,
b5b0: 0a 2a 2a 20 69 66 20 74 68 65 72 65 20 69 73 20  .** if there is 
b5c0: 6e 6f 20 73 75 63 68 20 72 65 61 64 2d 6c 6f 63  no such read-loc
b5d0: 6b 2c 20 73 65 74 20 69 74 20 74 6f 20 66 61 6c  k, set it to fal
b5e0: 73 65 2e 0a 2a 2a 0a 2a 2a 20 4f 72 2c 20 69 66  se..**.** Or, if
b5f0: 20 69 4c 73 6d 49 64 20 69 73 20 7a 65 72 6f 2c   iLsmId is zero,
b600: 20 74 68 65 6e 20 69 53 68 6d 69 64 20 69 73 20   then iShmid is 
b610: 61 20 73 68 61 72 65 64 2d 6d 65 6d 6f 72 79 20  a shared-memory 
b620: 73 65 71 75 65 6e 63 65 20 69 64 2e 0a 2a 2a 20  sequence id..** 
b630: 53 65 61 72 63 68 20 66 6f 72 20 61 20 72 65 61  Search for a rea
b640: 64 2d 6c 6f 63 6b 20 75 73 69 6e 67 20 74 68 69  d-lock using thi
b650: 73 20 73 65 71 75 65 6e 63 65 20 69 64 20 6f 72  s sequence id or
b660: 20 6e 65 77 65 72 2e 20 65 74 63 2e 0a 2a 2f 0a   newer. etc..*/.
b670: 73 74 61 74 69 63 20 69 6e 74 20 69 73 49 6e 55  static int isInU
b680: 73 65 28 6c 73 6d 5f 64 62 20 2a 64 62 2c 20 69  se(lsm_db *db, i
b690: 36 34 20 69 4c 73 6d 49 64 2c 20 75 33 32 20 69  64 iLsmId, u32 i
b6a0: 53 68 6d 69 64 2c 20 69 6e 74 20 2a 70 62 49 6e  Shmid, int *pbIn
b6b0: 55 73 65 29 7b 0a 20 20 53 68 6d 48 65 61 64 65  Use){.  ShmHeade
b6c0: 72 20 2a 70 53 68 6d 20 3d 20 64 62 2d 3e 70 53  r *pShm = db->pS
b6d0: 68 6d 68 64 72 3b 0a 20 20 69 6e 74 20 69 3b 0a  hmhdr;.  int i;.
b6e0: 20 20 69 6e 74 20 72 63 20 3d 20 4c 53 4d 5f 4f    int rc = LSM_O
b6f0: 4b 3b 0a 0a 20 20 66 6f 72 28 69 3d 30 3b 20 72  K;..  for(i=0; r
b700: 63 3d 3d 4c 53 4d 5f 4f 4b 20 26 26 20 69 3c 4c  c==LSM_OK && i<L
b710: 53 4d 5f 4c 4f 43 4b 5f 4e 52 45 41 44 45 52 3b  SM_LOCK_NREADER;
b720: 20 69 2b 2b 29 7b 0a 20 20 20 20 53 68 6d 52 65   i++){.    ShmRe
b730: 61 64 65 72 20 2a 70 20 3d 20 26 70 53 68 6d 2d  ader *p = &pShm-
b740: 3e 61 52 65 61 64 65 72 5b 69 5d 3b 0a 20 20 20  >aReader[i];.   
b750: 20 69 66 28 20 70 2d 3e 69 4c 73 6d 49 64 20 29   if( p->iLsmId )
b760: 7b 0a 20 20 20 20 20 20 69 66 28 20 28 69 4c 73  {.      if( (iLs
b770: 6d 49 64 21 3d 30 20 26 26 20 70 2d 3e 69 4c 73  mId!=0 && p->iLs
b780: 6d 49 64 21 3d 30 20 26 26 20 69 4c 73 6d 49 64  mId!=0 && iLsmId
b790: 3e 3d 70 2d 3e 69 4c 73 6d 49 64 29 20 0a 20 20  >=p->iLsmId) .  
b7a0: 20 20 20 20 20 7c 7c 20 28 69 4c 73 6d 49 64 3d       || (iLsmId=
b7b0: 3d 30 20 26 26 20 73 68 6d 5f 73 65 71 75 65 6e  =0 && shm_sequen
b7c0: 63 65 5f 67 65 28 70 2d 3e 69 54 72 65 65 49 64  ce_ge(p->iTreeId
b7d0: 2c 20 69 53 68 6d 69 64 29 29 0a 20 20 20 20 20  , iShmid)).     
b7e0: 20 29 7b 0a 20 20 20 20 20 20 20 20 72 63 20 3d   ){.        rc =
b7f0: 20 6c 73 6d 53 68 6d 4c 6f 63 6b 28 64 62 2c 20   lsmShmLock(db, 
b800: 4c 53 4d 5f 4c 4f 43 4b 5f 52 45 41 44 45 52 28  LSM_LOCK_READER(
b810: 69 29 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 45 58 43  i), LSM_LOCK_EXC
b820: 4c 2c 20 30 29 3b 0a 20 20 20 20 20 20 20 20 69  L, 0);.        i
b830: 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 29 7b  f( rc==LSM_OK ){
b840: 0a 20 20 20 20 20 20 20 20 20 20 70 2d 3e 69 4c  .          p->iL
b850: 73 6d 49 64 20 3d 20 30 3b 0a 20 20 20 20 20 20  smId = 0;.      
b860: 20 20 20 20 6c 73 6d 53 68 6d 4c 6f 63 6b 28 64      lsmShmLock(d
b870: 62 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 52 45 41 44  b, LSM_LOCK_READ
b880: 45 52 28 69 29 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f  ER(i), LSM_LOCK_
b890: 55 4e 4c 4f 43 4b 2c 20 30 29 3b 0a 20 20 20 20  UNLOCK, 0);.    
b8a0: 20 20 20 20 7d 0a 20 20 20 20 20 20 7d 0a 20 20      }.      }.  
b8b0: 20 20 7d 0a 20 20 7d 0a 0a 20 20 69 66 28 20 72    }.  }..  if( r
b8c0: 63 3d 3d 4c 53 4d 5f 42 55 53 59 20 29 7b 0a 20  c==LSM_BUSY ){. 
b8d0: 20 20 20 2a 70 62 49 6e 55 73 65 20 3d 20 31 3b     *pbInUse = 1;
b8e0: 0a 20 20 20 20 72 65 74 75 72 6e 20 4c 53 4d 5f  .    return LSM_
b8f0: 4f 4b 3b 0a 20 20 7d 0a 20 20 2a 70 62 49 6e 55  OK;.  }.  *pbInU
b900: 73 65 20 3d 20 30 3b 0a 20 20 72 65 74 75 72 6e  se = 0;.  return
b910: 20 72 63 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54 68   rc;.}../*.** Th
b920: 69 73 20 66 75 6e 63 74 69 6f 6e 20 69 73 20 63  is function is c
b930: 61 6c 6c 65 64 20 62 79 20 77 6f 72 6b 65 72 20  alled by worker 
b940: 63 6f 6e 6e 65 63 74 69 6f 6e 73 20 74 6f 20 64  connections to d
b950: 65 74 65 72 6d 69 6e 65 20 74 68 65 20 73 6d 61  etermine the sma
b960: 6c 6c 65 73 74 0a 2a 2a 20 73 6e 61 70 73 68 6f  llest.** snapsho
b970: 74 20 69 64 20 74 68 61 74 20 69 73 20 63 75 72  t id that is cur
b980: 72 65 6e 74 6c 79 20 69 6e 20 75 73 65 20 62 79  rently in use by
b990: 20 61 20 64 61 74 61 62 61 73 65 20 63 6c 69 65   a database clie
b9a0: 6e 74 2e 20 54 68 65 20 77 6f 72 6b 65 72 0a 2a  nt. The worker.*
b9b0: 2a 20 63 6f 6e 6e 65 63 74 69 6f 6e 20 75 73 65  * connection use
b9c0: 73 20 74 68 69 73 20 72 65 73 75 6c 74 20 74 6f  s this result to
b9d0: 20 64 65 74 65 72 6d 69 6e 65 20 77 68 65 74 68   determine wheth
b9e0: 65 72 20 6f 72 20 6e 6f 74 20 69 74 20 69 73 20  er or not it is 
b9f0: 73 61 66 65 20 74 6f 0a 2a 2a 20 72 65 63 79 63  safe to.** recyc
ba00: 6c 65 20 61 20 64 61 74 61 62 61 73 65 20 62 6c  le a database bl
ba10: 6f 63 6b 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69  ock..*/.static i
ba20: 6e 74 20 66 69 72 73 74 53 6e 61 70 73 68 6f 74  nt firstSnapshot
ba30: 49 6e 55 73 65 28 0a 20 20 6c 73 6d 5f 64 62 20  InUse(.  lsm_db 
ba40: 2a 64 62 2c 20 20 20 20 20 20 20 20 20 20 20 20  *db,            
ba50: 20 20 20 20 20 20 20 20 20 2f 2a 20 44 61 74 61           /* Data
ba60: 62 61 73 65 20 68 61 6e 64 6c 65 20 2a 2f 0a 20  base handle */. 
ba70: 20 69 36 34 20 2a 70 69 49 6e 55 73 65 20 20 20   i64 *piInUse   
ba80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
ba90: 20 2f 2a 20 49 4e 2f 4f 55 54 3a 20 53 6d 61 6c   /* IN/OUT: Smal
baa0: 6c 65 73 74 20 73 6e 61 70 73 68 6f 74 20 69 64  lest snapshot id
bab0: 20 69 6e 20 75 73 65 20 2a 2f 0a 29 7b 0a 20 20   in use */.){.  
bac0: 53 68 6d 48 65 61 64 65 72 20 2a 70 53 68 6d 20  ShmHeader *pShm 
bad0: 3d 20 64 62 2d 3e 70 53 68 6d 68 64 72 3b 0a 20  = db->pShmhdr;. 
bae0: 20 69 36 34 20 69 49 6e 55 73 65 20 3d 20 2a 70   i64 iInUse = *p
baf0: 69 49 6e 55 73 65 3b 0a 20 20 69 6e 74 20 69 3b  iInUse;.  int i;
bb00: 0a 0a 20 20 61 73 73 65 72 74 28 20 69 49 6e 55  ..  assert( iInU
bb10: 73 65 3e 30 20 29 3b 0a 20 20 66 6f 72 28 69 3d  se>0 );.  for(i=
bb20: 30 3b 20 69 3c 4c 53 4d 5f 4c 4f 43 4b 5f 4e 52  0; i<LSM_LOCK_NR
bb30: 45 41 44 45 52 3b 20 69 2b 2b 29 7b 0a 20 20 20  EADER; i++){.   
bb40: 20 53 68 6d 52 65 61 64 65 72 20 2a 70 20 3d 20   ShmReader *p = 
bb50: 26 70 53 68 6d 2d 3e 61 52 65 61 64 65 72 5b 69  &pShm->aReader[i
bb60: 5d 3b 0a 20 20 20 20 69 66 28 20 70 2d 3e 69 4c  ];.    if( p->iL
bb70: 73 6d 49 64 20 29 7b 0a 20 20 20 20 20 20 69 36  smId ){.      i6
bb80: 34 20 69 54 68 69 73 20 3d 20 70 2d 3e 69 4c 73  4 iThis = p->iLs
bb90: 6d 49 64 3b 0a 20 20 20 20 20 20 69 66 28 20 69  mId;.      if( i
bba0: 54 68 69 73 21 3d 30 20 26 26 20 69 49 6e 55 73  This!=0 && iInUs
bbb0: 65 3e 69 54 68 69 73 20 29 7b 0a 20 20 20 20 20  e>iThis ){.     
bbc0: 20 20 20 69 6e 74 20 72 63 20 3d 20 6c 73 6d 53     int rc = lsmS
bbd0: 68 6d 4c 6f 63 6b 28 64 62 2c 20 4c 53 4d 5f 4c  hmLock(db, LSM_L
bbe0: 4f 43 4b 5f 52 45 41 44 45 52 28 69 29 2c 20 4c  OCK_READER(i), L
bbf0: 53 4d 5f 4c 4f 43 4b 5f 45 58 43 4c 2c 20 30 29  SM_LOCK_EXCL, 0)
bc00: 3b 0a 20 20 20 20 20 20 20 20 69 66 28 20 72 63  ;.        if( rc
bc10: 3d 3d 4c 53 4d 5f 4f 4b 20 29 7b 0a 20 20 20 20  ==LSM_OK ){.    
bc20: 20 20 20 20 20 20 70 2d 3e 69 4c 73 6d 49 64 20        p->iLsmId 
bc30: 3d 20 30 3b 0a 20 20 20 20 20 20 20 20 20 20 6c  = 0;.          l
bc40: 73 6d 53 68 6d 4c 6f 63 6b 28 64 62 2c 20 4c 53  smShmLock(db, LS
bc50: 4d 5f 4c 4f 43 4b 5f 52 45 41 44 45 52 28 69 29  M_LOCK_READER(i)
bc60: 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 55 4e 4c 4f 43  , LSM_LOCK_UNLOC
bc70: 4b 2c 20 30 29 3b 0a 20 20 20 20 20 20 20 20 7d  K, 0);.        }
bc80: 65 6c 73 65 20 69 66 28 20 72 63 3d 3d 4c 53 4d  else if( rc==LSM
bc90: 5f 42 55 53 59 20 29 7b 0a 20 20 20 20 20 20 20  _BUSY ){.       
bca0: 20 20 20 69 49 6e 55 73 65 20 3d 20 69 54 68 69     iInUse = iThi
bcb0: 73 3b 0a 20 20 20 20 20 20 20 20 7d 65 6c 73 65  s;.        }else
bcc0: 7b 0a 20 20 20 20 20 20 20 20 20 20 2f 2a 20 53  {.          /* S
bcd0: 6f 6d 65 20 65 72 72 6f 72 20 6f 74 68 65 72 20  ome error other 
bce0: 74 68 61 6e 20 4c 53 4d 5f 42 55 53 59 2e 20 52  than LSM_BUSY. R
bcf0: 65 74 75 72 6e 20 74 68 65 20 65 72 72 6f 72 20  eturn the error 
bd00: 63 6f 64 65 20 74 6f 0a 20 20 20 20 20 20 20 20  code to.        
bd10: 20 20 2a 2a 20 74 68 65 20 63 61 6c 6c 65 72 20    ** the caller 
bd20: 69 6e 20 74 68 69 73 20 63 61 73 65 2e 20 20 2a  in this case.  *
bd30: 2f 0a 20 20 20 20 20 20 20 20 20 20 72 65 74 75  /.          retu
bd40: 72 6e 20 72 63 3b 0a 20 20 20 20 20 20 20 20 7d  rn rc;.        }
bd50: 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a 20  .      }.    }. 
bd60: 20 7d 0a 0a 20 20 2a 70 69 49 6e 55 73 65 20 3d   }..  *piInUse =
bd70: 20 69 49 6e 55 73 65 3b 0a 20 20 72 65 74 75 72   iInUse;.  retur
bd80: 6e 20 4c 53 4d 5f 4f 4b 3b 0a 7d 0a 0a 69 6e 74  n LSM_OK;.}..int
bd90: 20 6c 73 6d 54 72 65 65 49 6e 55 73 65 28 6c 73   lsmTreeInUse(ls
bda0: 6d 5f 64 62 20 2a 64 62 2c 20 75 33 32 20 69 53  m_db *db, u32 iS
bdb0: 68 6d 69 64 2c 20 69 6e 74 20 2a 70 62 49 6e 55  hmid, int *pbInU
bdc0: 73 65 29 7b 0a 20 20 69 66 28 20 64 62 2d 3e 74  se){.  if( db->t
bdd0: 72 65 65 68 64 72 2e 69 55 73 65 64 53 68 6d 69  reehdr.iUsedShmi
bde0: 64 3d 3d 69 53 68 6d 69 64 20 29 7b 0a 20 20 20  d==iShmid ){.   
bdf0: 20 2a 70 62 49 6e 55 73 65 20 3d 20 31 3b 0a 20   *pbInUse = 1;. 
be00: 20 20 20 72 65 74 75 72 6e 20 4c 53 4d 5f 4f 4b     return LSM_OK
be10: 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20 69  ;.  }.  return i
be20: 73 49 6e 55 73 65 28 64 62 2c 20 30 2c 20 69 53  sInUse(db, 0, iS
be30: 68 6d 69 64 2c 20 70 62 49 6e 55 73 65 29 3b 0a  hmid, pbInUse);.
be40: 7d 0a 0a 69 6e 74 20 6c 73 6d 4c 73 6d 49 6e 55  }..int lsmLsmInU
be50: 73 65 28 6c 73 6d 5f 64 62 20 2a 64 62 2c 20 69  se(lsm_db *db, i
be60: 36 34 20 69 4c 73 6d 49 64 2c 20 69 6e 74 20 2a  64 iLsmId, int *
be70: 70 62 49 6e 55 73 65 29 7b 0a 20 20 69 66 28 20  pbInUse){.  if( 
be80: 64 62 2d 3e 70 43 6c 69 65 6e 74 20 26 26 20 64  db->pClient && d
be90: 62 2d 3e 70 43 6c 69 65 6e 74 2d 3e 69 49 64 3c  b->pClient->iId<
bea0: 3d 69 4c 73 6d 49 64 20 29 7b 0a 20 20 20 20 2a  =iLsmId ){.    *
beb0: 70 62 49 6e 55 73 65 20 3d 20 31 3b 0a 20 20 20  pbInUse = 1;.   
bec0: 20 72 65 74 75 72 6e 20 4c 53 4d 5f 4f 4b 3b 0a   return LSM_OK;.
bed0: 20 20 7d 0a 20 20 72 65 74 75 72 6e 20 69 73 49    }.  return isI
bee0: 6e 55 73 65 28 64 62 2c 20 69 4c 73 6d 49 64 2c  nUse(db, iLsmId,
bef0: 20 30 2c 20 70 62 49 6e 55 73 65 29 3b 0a 7d 0a   0, pbInUse);.}.
bf00: 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20 66 75 6e 63  ./*.** This func
bf10: 74 69 6f 6e 20 6d 61 79 20 6f 6e 6c 79 20 62 65  tion may only be
bf20: 20 63 61 6c 6c 65 64 20 61 66 74 65 72 20 61 20   called after a 
bf30: 73 75 63 63 65 73 73 66 75 6c 20 63 61 6c 6c 20  successful call 
bf40: 74 6f 0a 2a 2a 20 6c 73 6d 44 62 44 61 74 61 62  to.** lsmDbDatab
bf50: 61 73 65 43 6f 6e 6e 65 63 74 28 29 2e 20 49 74  aseConnect(). It
bf60: 20 72 65 74 75 72 6e 73 20 74 72 75 65 20 69 66   returns true if
bf70: 20 74 68 65 20 63 6f 6e 6e 65 63 74 69 6f 6e 20   the connection 
bf80: 69 73 20 69 6e 0a 2a 2a 20 6d 75 6c 74 69 2d 70  is in.** multi-p
bf90: 72 6f 63 65 73 73 20 6d 6f 64 65 2c 20 6f 72 20  rocess mode, or 
bfa0: 66 61 6c 73 65 20 6f 74 68 65 72 77 69 73 65 2e  false otherwise.
bfb0: 0a 2a 2f 0a 69 6e 74 20 6c 73 6d 44 62 4d 75 6c  .*/.int lsmDbMul
bfc0: 74 69 50 72 6f 63 28 6c 73 6d 5f 64 62 20 2a 70  tiProc(lsm_db *p
bfd0: 44 62 29 7b 0a 20 20 72 65 74 75 72 6e 20 70 44  Db){.  return pD
bfe0: 62 2d 3e 70 44 61 74 61 62 61 73 65 20 26 26 20  b->pDatabase && 
bff0: 70 44 62 2d 3e 70 44 61 74 61 62 61 73 65 2d 3e  pDb->pDatabase->
c000: 62 4d 75 6c 74 69 50 72 6f 63 3b 0a 7d 0a 0a 0a  bMultiProc;.}...
c010: 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  /***************
c020: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
c030: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
c040: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
c050: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 0a 2a 2a 2a 2a 2a  **********.*****
c060: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
c070: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
c080: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
c090: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
c0a0: 2a 2a 2a 2a 2a 0a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  *****.**********
c0b0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
c0c0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
c0d0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
c0e0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
c0f0: 0a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  .***************
c100: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
c110: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
c120: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
c130: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 0a 2a 2a 2a 2a  ***********.****
c140: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
c150: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
c160: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
c170: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
c180: 2a 2a 2a 2a 2a 2a 0a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ******.*********
c190: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
c1a0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
c1b0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
c1c0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
c1d0: 2f 0a 0a 2f 2a 0a 2a 2a 20 45 6e 73 75 72 65 20  /../*.** Ensure 
c1e0: 74 68 61 74 20 64 61 74 61 62 61 73 65 20 63 6f  that database co
c1f0: 6e 6e 65 63 74 69 6f 6e 20 64 62 20 68 61 73 20  nnection db has 
c200: 63 61 63 68 65 64 20 70 6f 69 6e 74 65 72 73 20  cached pointers 
c210: 74 6f 20 61 74 20 6c 65 61 73 74 20 74 68 65 20  to at least the 
c220: 0a 2a 2a 20 66 69 72 73 74 20 6e 43 68 75 6e 6b  .** first nChunk
c230: 20 63 68 75 6e 6b 73 20 6f 66 20 73 68 61 72 65   chunks of share
c240: 64 20 6d 65 6d 6f 72 79 2e 0a 2a 2f 0a 69 6e 74  d memory..*/.int
c250: 20 6c 73 6d 53 68 6d 43 61 63 68 65 43 68 75 6e   lsmShmCacheChun
c260: 6b 73 28 6c 73 6d 5f 64 62 20 2a 64 62 2c 20 69  ks(lsm_db *db, i
c270: 6e 74 20 6e 43 68 75 6e 6b 29 7b 0a 20 20 69 6e  nt nChunk){.  in
c280: 74 20 72 63 20 3d 20 4c 53 4d 5f 4f 4b 3b 0a 20  t rc = LSM_OK;. 
c290: 20 69 66 28 20 6e 43 68 75 6e 6b 3e 64 62 2d 3e   if( nChunk>db->
c2a0: 6e 53 68 6d 20 29 7b 0a 20 20 20 20 73 74 61 74  nShm ){.    stat
c2b0: 69 63 20 63 6f 6e 73 74 20 69 6e 74 20 4e 49 4e  ic const int NIN
c2c0: 43 52 20 3d 20 31 36 3b 0a 20 20 20 20 44 61 74  CR = 16;.    Dat
c2d0: 61 62 61 73 65 20 2a 70 20 3d 20 64 62 2d 3e 70  abase *p = db->p
c2e0: 44 61 74 61 62 61 73 65 3b 0a 20 20 20 20 6c 73  Database;.    ls
c2f0: 6d 5f 65 6e 76 20 2a 70 45 6e 76 20 3d 20 64 62  m_env *pEnv = db
c300: 2d 3e 70 45 6e 76 3b 0a 20 20 20 20 69 6e 74 20  ->pEnv;.    int 
c310: 6e 41 6c 6c 6f 63 3b 0a 20 20 20 20 69 6e 74 20  nAlloc;.    int 
c320: 69 3b 0a 0a 20 20 20 20 2f 2a 20 45 6e 73 75 72  i;..    /* Ensur
c330: 65 20 74 68 61 74 20 74 68 65 20 64 62 2d 3e 61  e that the db->a
c340: 70 53 68 6d 5b 5d 20 61 72 72 61 79 20 69 73 20  pShm[] array is 
c350: 6c 61 72 67 65 20 65 6e 6f 75 67 68 2e 20 49 66  large enough. If
c360: 20 61 6e 20 61 74 74 65 6d 70 74 20 74 6f 0a 20   an attempt to. 
c370: 20 20 20 2a 2a 20 61 6c 6c 6f 63 61 74 65 20 6d     ** allocate m
c380: 65 6d 6f 72 79 20 66 61 69 6c 73 2c 20 72 65 74  emory fails, ret
c390: 75 72 6e 20 4c 53 4d 5f 4e 4f 4d 45 4d 20 69 6d  urn LSM_NOMEM im
c3a0: 6d 65 64 69 61 74 65 6c 79 2e 20 54 68 65 20 61  mediately. The a
c3b0: 70 53 68 6d 5b 5d 20 61 72 72 61 79 0a 20 20 20  pShm[] array.   
c3c0: 20 2a 2a 20 69 73 20 61 6c 77 61 79 73 20 65 78   ** is always ex
c3d0: 74 65 6e 64 65 64 20 69 6e 20 6d 75 6c 74 69 70  tended in multip
c3e0: 6c 65 73 20 6f 66 20 31 36 20 65 6e 74 72 69 65  les of 16 entrie
c3f0: 73 20 2d 20 73 6f 20 74 68 65 20 61 63 74 75 61  s - so the actua
c400: 6c 20 61 6c 6c 6f 63 61 74 65 64 0a 20 20 20 20  l allocated.    
c410: 2a 2a 20 73 69 7a 65 20 63 61 6e 20 62 65 20 69  ** size can be i
c420: 6e 66 65 72 72 65 64 20 66 72 6f 6d 20 6e 53 68  nferred from nSh
c430: 6d 2e 20 20 2a 2f 20 0a 20 20 20 20 6e 41 6c 6c  m.  */ .    nAll
c440: 6f 63 20 3d 20 28 28 64 62 2d 3e 6e 53 68 6d 20  oc = ((db->nShm 
c450: 2b 20 4e 49 4e 43 52 20 2d 20 31 29 20 2f 20 4e  + NINCR - 1) / N
c460: 49 4e 43 52 29 20 2a 20 4e 49 4e 43 52 3b 0a 20  INCR) * NINCR;. 
c470: 20 20 20 77 68 69 6c 65 28 20 6e 43 68 75 6e 6b     while( nChunk
c480: 3e 3d 6e 41 6c 6c 6f 63 20 29 7b 0a 20 20 20 20  >=nAlloc ){.    
c490: 20 20 76 6f 69 64 20 2a 2a 61 70 53 68 6d 3b 0a    void **apShm;.
c4a0: 20 20 20 20 20 20 6e 41 6c 6c 6f 63 20 2b 3d 20        nAlloc += 
c4b0: 4e 49 4e 43 52 3b 0a 20 20 20 20 20 20 61 70 53  NINCR;.      apS
c4c0: 68 6d 20 3d 20 6c 73 6d 52 65 61 6c 6c 6f 63 28  hm = lsmRealloc(
c4d0: 70 45 6e 76 2c 20 64 62 2d 3e 61 70 53 68 6d 2c  pEnv, db->apShm,
c4e0: 20 73 69 7a 65 6f 66 28 76 6f 69 64 2a 29 2a 6e   sizeof(void*)*n
c4f0: 41 6c 6c 6f 63 29 3b 0a 20 20 20 20 20 20 69 66  Alloc);.      if
c500: 28 20 21 61 70 53 68 6d 20 29 20 72 65 74 75 72  ( !apShm ) retur
c510: 6e 20 4c 53 4d 5f 4e 4f 4d 45 4d 5f 42 4b 50 54  n LSM_NOMEM_BKPT
c520: 3b 0a 20 20 20 20 20 20 64 62 2d 3e 61 70 53 68  ;.      db->apSh
c530: 6d 20 3d 20 61 70 53 68 6d 3b 0a 20 20 20 20 7d  m = apShm;.    }
c540: 0a 0a 20 20 20 20 69 66 28 20 64 62 2d 3e 62 52  ..    if( db->bR
c550: 6f 54 72 61 6e 73 20 29 7b 0a 20 20 20 20 20 20  oTrans ){.      
c560: 66 6f 72 28 69 3d 64 62 2d 3e 6e 53 68 6d 3b 20  for(i=db->nShm; 
c570: 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 26 26 20 69 3c  rc==LSM_OK && i<
c580: 6e 43 68 75 6e 6b 3b 20 69 2b 2b 29 7b 0a 20 20  nChunk; i++){.  
c590: 20 20 20 20 20 20 64 62 2d 3e 61 70 53 68 6d 5b        db->apShm[
c5a0: 69 5d 20 3d 20 6c 73 6d 4d 61 6c 6c 6f 63 5a 65  i] = lsmMallocZe
c5b0: 72 6f 52 63 28 70 45 6e 76 2c 20 4c 53 4d 5f 53  roRc(pEnv, LSM_S
c5c0: 48 4d 5f 43 48 55 4e 4b 5f 53 49 5a 45 2c 20 26  HM_CHUNK_SIZE, &
c5d0: 72 63 29 3b 0a 20 20 20 20 20 20 20 20 64 62 2d  rc);.        db-
c5e0: 3e 6e 53 68 6d 2b 2b 3b 0a 20 20 20 20 20 20 7d  >nShm++;.      }
c5f0: 0a 0a 20 20 20 20 7d 65 6c 73 65 7b 0a 0a 20 20  ..    }else{..  
c600: 20 20 20 20 2f 2a 20 45 6e 74 65 72 20 74 68 65      /* Enter the
c610: 20 63 6c 69 65 6e 74 20 6d 75 74 65 78 20 2a 2f   client mutex */
c620: 0a 20 20 20 20 20 20 6c 73 6d 4d 75 74 65 78 45  .      lsmMutexE
c630: 6e 74 65 72 28 70 45 6e 76 2c 20 70 2d 3e 70 43  nter(pEnv, p->pC
c640: 6c 69 65 6e 74 4d 75 74 65 78 29 3b 0a 0a 20 20  lientMutex);..  
c650: 20 20 20 20 2f 2a 20 45 78 74 65 6e 64 20 74 68      /* Extend th
c660: 65 20 44 61 74 61 62 61 73 65 20 6f 62 6a 65 63  e Database objec
c670: 74 73 20 61 70 53 68 6d 43 68 75 6e 6b 5b 5d 20  ts apShmChunk[] 
c680: 61 72 72 61 79 20 69 66 20 6e 65 63 65 73 73 61  array if necessa
c690: 72 79 2e 20 55 73 69 6e 67 20 74 68 65 0a 20 20  ry. Using the.  
c6a0: 20 20 20 20 20 2a 2a 20 73 61 6d 65 20 70 61 74       ** same pat
c6b0: 74 65 72 6e 20 61 73 20 66 6f 72 20 74 68 65 20  tern as for the 
c6c0: 6c 73 6d 5f 64 62 2e 61 70 53 68 6d 5b 5d 20 61  lsm_db.apShm[] a
c6d0: 72 72 61 79 20 61 62 6f 76 65 2e 20 20 2a 2f 0a  rray above.  */.
c6e0: 20 20 20 20 20 20 6e 41 6c 6c 6f 63 20 3d 20 28        nAlloc = (
c6f0: 28 70 2d 3e 6e 53 68 6d 43 68 75 6e 6b 20 2b 20  (p->nShmChunk + 
c700: 4e 49 4e 43 52 20 2d 20 31 29 20 2f 20 4e 49 4e  NINCR - 1) / NIN
c710: 43 52 29 20 2a 20 4e 49 4e 43 52 3b 0a 20 20 20  CR) * NINCR;.   
c720: 20 20 20 77 68 69 6c 65 28 20 6e 43 68 75 6e 6b     while( nChunk
c730: 3e 3d 6e 41 6c 6c 6f 63 20 29 7b 0a 20 20 20 20  >=nAlloc ){.    
c740: 20 20 20 20 76 6f 69 64 20 2a 2a 61 70 53 68 6d      void **apShm
c750: 3b 0a 20 20 20 20 20 20 20 20 6e 41 6c 6c 6f 63  ;.        nAlloc
c760: 20 2b 3d 20 20 4e 49 4e 43 52 3b 0a 20 20 20 20   +=  NINCR;.    
c770: 20 20 20 20 61 70 53 68 6d 20 3d 20 6c 73 6d 52      apShm = lsmR
c780: 65 61 6c 6c 6f 63 28 70 45 6e 76 2c 20 70 2d 3e  ealloc(pEnv, p->
c790: 61 70 53 68 6d 43 68 75 6e 6b 2c 20 73 69 7a 65  apShmChunk, size
c7a0: 6f 66 28 76 6f 69 64 2a 29 2a 6e 41 6c 6c 6f 63  of(void*)*nAlloc
c7b0: 29 3b 0a 20 20 20 20 20 20 20 20 69 66 28 20 21  );.        if( !
c7c0: 61 70 53 68 6d 20 29 7b 0a 20 20 20 20 20 20 20  apShm ){.       
c7d0: 20 20 20 72 63 20 3d 20 4c 53 4d 5f 4e 4f 4d 45     rc = LSM_NOME
c7e0: 4d 5f 42 4b 50 54 3b 0a 20 20 20 20 20 20 20 20  M_BKPT;.        
c7f0: 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 20    break;.       
c800: 20 7d 0a 20 20 20 20 20 20 20 20 70 2d 3e 61 70   }.        p->ap
c810: 53 68 6d 43 68 75 6e 6b 20 3d 20 61 70 53 68 6d  ShmChunk = apShm
c820: 3b 0a 20 20 20 20 20 20 7d 0a 0a 20 20 20 20 20  ;.      }..     
c830: 20 66 6f 72 28 69 3d 64 62 2d 3e 6e 53 68 6d 3b   for(i=db->nShm;
c840: 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 26 26 20 69   rc==LSM_OK && i
c850: 3c 6e 43 68 75 6e 6b 3b 20 69 2b 2b 29 7b 0a 20  <nChunk; i++){. 
c860: 20 20 20 20 20 20 20 69 66 28 20 69 3e 3d 70 2d         if( i>=p-
c870: 3e 6e 53 68 6d 43 68 75 6e 6b 20 29 7b 0a 20 20  >nShmChunk ){.  
c880: 20 20 20 20 20 20 20 20 76 6f 69 64 20 2a 70 43          void *pC
c890: 68 75 6e 6b 20 3d 20 30 3b 0a 20 20 20 20 20 20  hunk = 0;.      
c8a0: 20 20 20 20 69 66 28 20 70 2d 3e 62 4d 75 6c 74      if( p->bMult
c8b0: 69 50 72 6f 63 3d 3d 30 20 29 7b 0a 20 20 20 20  iProc==0 ){.    
c8c0: 20 20 20 20 20 20 20 20 2f 2a 20 53 69 6e 67 6c          /* Singl
c8d0: 65 20 70 72 6f 63 65 73 73 20 6d 6f 64 65 20 2a  e process mode *
c8e0: 2f 0a 20 20 20 20 20 20 20 20 20 20 20 20 70 43  /.            pC
c8f0: 68 75 6e 6b 20 3d 20 6c 73 6d 4d 61 6c 6c 6f 63  hunk = lsmMalloc
c900: 5a 65 72 6f 52 63 28 70 45 6e 76 2c 20 4c 53 4d  ZeroRc(pEnv, LSM
c910: 5f 53 48 4d 5f 43 48 55 4e 4b 5f 53 49 5a 45 2c  _SHM_CHUNK_SIZE,
c920: 20 26 72 63 29 3b 0a 20 20 20 20 20 20 20 20 20   &rc);.         
c930: 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 20 20   }else{.        
c940: 20 20 20 20 2f 2a 20 4d 75 6c 74 69 2d 70 72 6f      /* Multi-pro
c950: 63 65 73 73 20 6d 6f 64 65 20 2a 2f 0a 20 20 20  cess mode */.   
c960: 20 20 20 20 20 20 20 20 20 72 63 20 3d 20 6c 73           rc = ls
c970: 6d 45 6e 76 53 68 6d 4d 61 70 28 70 45 6e 76 2c  mEnvShmMap(pEnv,
c980: 20 70 2d 3e 70 46 69 6c 65 2c 20 69 2c 20 4c 53   p->pFile, i, LS
c990: 4d 5f 53 48 4d 5f 43 48 55 4e 4b 5f 53 49 5a 45  M_SHM_CHUNK_SIZE
c9a0: 2c 20 26 70 43 68 75 6e 6b 29 3b 0a 20 20 20 20  , &pChunk);.    
c9b0: 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 20 20        }.        
c9c0: 20 20 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b    if( rc==LSM_OK
c9d0: 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20 20 20   ){.            
c9e0: 70 2d 3e 61 70 53 68 6d 43 68 75 6e 6b 5b 69 5d  p->apShmChunk[i]
c9f0: 20 3d 20 70 43 68 75 6e 6b 3b 0a 20 20 20 20 20   = pChunk;.     
ca00: 20 20 20 20 20 20 20 70 2d 3e 6e 53 68 6d 43 68         p->nShmCh
ca10: 75 6e 6b 2b 2b 3b 0a 20 20 20 20 20 20 20 20 20  unk++;.         
ca20: 20 7d 0a 20 20 20 20 20 20 20 20 7d 0a 20 20 20   }.        }.   
ca30: 20 20 20 20 20 69 66 28 20 72 63 3d 3d 4c 53 4d       if( rc==LSM
ca40: 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 20 20 20  _OK ){.         
ca50: 20 64 62 2d 3e 61 70 53 68 6d 5b 69 5d 20 3d 20   db->apShm[i] = 
ca60: 70 2d 3e 61 70 53 68 6d 43 68 75 6e 6b 5b 69 5d  p->apShmChunk[i]
ca70: 3b 0a 20 20 20 20 20 20 20 20 20 20 64 62 2d 3e  ;.          db->
ca80: 6e 53 68 6d 2b 2b 3b 0a 20 20 20 20 20 20 20 20  nShm++;.        
ca90: 7d 0a 20 20 20 20 20 20 7d 0a 0a 20 20 20 20 20  }.      }..     
caa0: 20 2f 2a 20 52 65 6c 65 61 73 65 20 74 68 65 20   /* Release the 
cab0: 63 6c 69 65 6e 74 20 6d 75 74 65 78 20 2a 2f 0a  client mutex */.
cac0: 20 20 20 20 20 20 6c 73 6d 4d 75 74 65 78 4c 65        lsmMutexLe
cad0: 61 76 65 28 70 45 6e 76 2c 20 70 2d 3e 70 43 6c  ave(pEnv, p->pCl
cae0: 69 65 6e 74 4d 75 74 65 78 29 3b 0a 20 20 20 20  ientMutex);.    
caf0: 7d 0a 20 20 7d 0a 0a 20 20 72 65 74 75 72 6e 20  }.  }..  return 
cb00: 72 63 3b 0a 7d 0a 0a 73 74 61 74 69 63 20 69 6e  rc;.}..static in
cb10: 74 20 6c 6f 63 6b 53 68 61 72 65 64 46 69 6c 65  t lockSharedFile
cb20: 28 6c 73 6d 5f 65 6e 76 20 2a 70 45 6e 76 2c 20  (lsm_env *pEnv, 
cb30: 44 61 74 61 62 61 73 65 20 2a 70 2c 20 69 6e 74  Database *p, int
cb40: 20 69 4c 6f 63 6b 2c 20 69 6e 74 20 65 4f 70 29   iLock, int eOp)
cb50: 7b 0a 20 20 69 6e 74 20 72 63 20 3d 20 4c 53 4d  {.  int rc = LSM
cb60: 5f 4f 4b 3b 0a 20 20 69 66 28 20 70 2d 3e 62 4d  _OK;.  if( p->bM
cb70: 75 6c 74 69 50 72 6f 63 20 29 7b 0a 20 20 20 20  ultiProc ){.    
cb80: 72 63 20 3d 20 6c 73 6d 45 6e 76 4c 6f 63 6b 28  rc = lsmEnvLock(
cb90: 70 45 6e 76 2c 20 70 2d 3e 70 46 69 6c 65 2c 20  pEnv, p->pFile, 
cba0: 69 4c 6f 63 6b 2c 20 65 4f 70 29 3b 0a 20 20 7d  iLock, eOp);.  }
cbb0: 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a  .  return rc;.}.
cbc0: 0a 2f 2a 0a 2a 2a 20 54 65 73 74 20 69 66 20 69  ./*.** Test if i
cbd0: 74 20 77 6f 75 6c 64 20 62 65 20 70 6f 73 73 69  t would be possi
cbe0: 62 6c 65 20 66 6f 72 20 63 6f 6e 6e 65 63 74 69  ble for connecti
cbf0: 6f 6e 20 64 62 20 74 6f 20 6f 62 74 61 69 6e 20  on db to obtain 
cc00: 61 20 6c 6f 63 6b 20 6f 66 20 74 79 70 65 0a 2a  a lock of type.*
cc10: 2a 20 65 54 79 70 65 20 6f 6e 20 74 68 65 20 6e  * eType on the n
cc20: 4c 6f 63 6b 20 6c 6f 63 6b 73 20 73 74 61 72 74  Lock locks start
cc30: 69 6e 67 20 61 74 20 69 4c 6f 63 6b 2e 20 49 66  ing at iLock. If
cc40: 20 73 6f 2c 20 72 65 74 75 72 6e 20 4c 53 4d 5f   so, return LSM_
cc50: 4f 4b 2e 20 49 66 20 69 74 0a 2a 2a 20 77 6f 75  OK. If it.** wou
cc60: 6c 64 20 6e 6f 74 20 62 65 20 70 6f 73 73 69 62  ld not be possib
cc70: 6c 65 20 74 6f 20 6f 62 74 61 69 6e 20 74 68 65  le to obtain the
cc80: 20 6c 6f 63 6b 20 64 75 65 20 74 6f 20 61 20 6c   lock due to a l
cc90: 6f 63 6b 20 68 65 6c 64 20 62 79 20 61 6e 6f 74  ock held by anot
cca0: 68 65 72 0a 2a 2a 20 63 6f 6e 6e 65 63 74 69 6f  her.** connectio
ccb0: 6e 2c 20 72 65 74 75 72 6e 20 4c 53 4d 5f 42 55  n, return LSM_BU
ccc0: 53 59 2e 20 49 66 20 61 6e 20 49 4f 20 6f 72 20  SY. If an IO or 
ccd0: 6f 74 68 65 72 20 65 72 72 6f 72 20 6f 63 63 75  other error occu
cce0: 72 73 20 28 69 2e 65 2e 20 69 6e 20 74 68 65 20  rs (i.e. in the 
ccf0: 0a 2a 2a 20 6c 73 6d 5f 65 6e 76 2e 78 54 65 73  .** lsm_env.xTes
cd00: 74 4c 6f 63 6b 20 66 75 6e 63 74 69 6f 6e 29 2c  tLock function),
cd10: 20 72 65 74 75 72 6e 20 73 6f 6d 65 20 6f 74 68   return some oth
cd20: 65 72 20 4c 53 4d 20 65 72 72 6f 72 20 63 6f 64  er LSM error cod
cd30: 65 2e 0a 2a 2a 0a 2a 2a 20 4e 6f 74 65 20 74 68  e..**.** Note th
cd40: 61 74 20 74 68 69 73 20 66 75 6e 63 74 69 6f 6e  at this function
cd50: 20 6e 65 76 65 72 20 61 63 74 75 61 6c 6c 79 20   never actually 
cd60: 6c 6f 63 6b 73 20 74 68 65 20 64 61 74 61 62 61  locks the databa
cd70: 73 65 20 2d 20 69 74 20 6d 65 72 65 6c 79 0a 2a  se - it merely.*
cd80: 2a 20 71 75 65 72 69 65 73 20 74 68 65 20 73 79  * queries the sy
cd90: 73 74 65 6d 20 74 6f 20 73 65 65 20 69 66 20 74  stem to see if t
cda0: 68 65 72 65 20 65 78 69 73 74 73 20 61 20 6c 6f  here exists a lo
cdb0: 63 6b 20 74 68 61 74 20 77 6f 75 6c 64 20 70 72  ck that would pr
cdc0: 65 76 65 6e 74 0a 2a 2a 20 69 74 20 66 72 6f 6d  event.** it from
cdd0: 20 64 6f 69 6e 67 20 73 6f 2e 0a 2a 2f 0a 69 6e   doing so..*/.in
cde0: 74 20 6c 73 6d 53 68 6d 54 65 73 74 4c 6f 63 6b  t lsmShmTestLock
cdf0: 28 0a 20 20 6c 73 6d 5f 64 62 20 2a 64 62 2c 0a  (.  lsm_db *db,.
ce00: 20 20 69 6e 74 20 69 4c 6f 63 6b 2c 0a 20 20 69    int iLock,.  i
ce10: 6e 74 20 6e 4c 6f 63 6b 2c 0a 20 20 69 6e 74 20  nt nLock,.  int 
ce20: 65 4f 70 0a 29 7b 0a 20 20 69 6e 74 20 72 63 20  eOp.){.  int rc 
ce30: 3d 20 4c 53 4d 5f 4f 4b 3b 0a 20 20 6c 73 6d 5f  = LSM_OK;.  lsm_
ce40: 64 62 20 2a 70 49 74 65 72 3b 0a 20 20 44 61 74  db *pIter;.  Dat
ce50: 61 62 61 73 65 20 2a 70 20 3d 20 64 62 2d 3e 70  abase *p = db->p
ce60: 44 61 74 61 62 61 73 65 3b 0a 20 20 69 6e 74 20  Database;.  int 
ce70: 69 3b 0a 20 20 75 36 34 20 6d 61 73 6b 20 3d 20  i;.  u64 mask = 
ce80: 30 3b 0a 0a 20 20 66 6f 72 28 69 3d 69 4c 6f 63  0;..  for(i=iLoc
ce90: 6b 3b 20 69 3c 28 69 4c 6f 63 6b 2b 6e 4c 6f 63  k; i<(iLock+nLoc
cea0: 6b 29 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 6d 61  k); i++){.    ma
ceb0: 73 6b 20 7c 3d 20 28 28 75 36 34 29 31 20 3c 3c  sk |= ((u64)1 <<
cec0: 20 28 69 4c 6f 63 6b 2d 31 29 29 3b 0a 20 20 20   (iLock-1));.   
ced0: 20 69 66 28 20 65 4f 70 3d 3d 4c 53 4d 5f 4c 4f   if( eOp==LSM_LO
cee0: 43 4b 5f 45 58 43 4c 20 29 20 6d 61 73 6b 20 7c  CK_EXCL ) mask |
cef0: 3d 20 28 28 75 36 34 29 31 20 3c 3c 20 28 69 4c  = ((u64)1 << (iL
cf00: 6f 63 6b 2b 33 32 2d 31 29 29 3b 0a 20 20 7d 0a  ock+32-1));.  }.
cf10: 0a 20 20 6c 73 6d 4d 75 74 65 78 45 6e 74 65 72  .  lsmMutexEnter
cf20: 28 64 62 2d 3e 70 45 6e 76 2c 20 70 2d 3e 70 43  (db->pEnv, p->pC
cf30: 6c 69 65 6e 74 4d 75 74 65 78 29 3b 0a 20 20 66  lientMutex);.  f
cf40: 6f 72 28 70 49 74 65 72 3d 70 2d 3e 70 43 6f 6e  or(pIter=p->pCon
cf50: 6e 3b 20 70 49 74 65 72 3b 20 70 49 74 65 72 3d  n; pIter; pIter=
cf60: 70 49 74 65 72 2d 3e 70 4e 65 78 74 29 7b 0a 20  pIter->pNext){. 
cf70: 20 20 20 69 66 28 20 70 49 74 65 72 21 3d 64 62     if( pIter!=db
cf80: 20 26 26 20 28 70 49 74 65 72 2d 3e 6d 4c 6f 63   && (pIter->mLoc
cf90: 6b 20 26 20 6d 61 73 6b 29 20 29 7b 0a 20 20 20  k & mask) ){.   
cfa0: 20 20 20 61 73 73 65 72 74 28 20 70 49 74 65 72     assert( pIter
cfb0: 21 3d 64 62 20 29 3b 0a 20 20 20 20 20 20 62 72  !=db );.      br
cfc0: 65 61 6b 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 0a  eak;.    }.  }..
cfd0: 20 20 69 66 28 20 70 49 74 65 72 20 29 7b 0a 20    if( pIter ){. 
cfe0: 20 20 20 72 63 20 3d 20 4c 53 4d 5f 42 55 53 59     rc = LSM_BUSY
cff0: 3b 0a 20 20 7d 65 6c 73 65 20 69 66 28 20 70 2d  ;.  }else if( p-
d000: 3e 62 4d 75 6c 74 69 50 72 6f 63 20 29 7b 0a 20  >bMultiProc ){. 
d010: 20 20 20 72 63 20 3d 20 6c 73 6d 45 6e 76 54 65     rc = lsmEnvTe
d020: 73 74 4c 6f 63 6b 28 64 62 2d 3e 70 45 6e 76 2c  stLock(db->pEnv,
d030: 20 70 2d 3e 70 46 69 6c 65 2c 20 69 4c 6f 63 6b   p->pFile, iLock
d040: 2c 20 6e 4c 6f 63 6b 2c 20 65 4f 70 29 3b 0a 20  , nLock, eOp);. 
d050: 20 7d 0a 0a 20 20 6c 73 6d 4d 75 74 65 78 4c 65   }..  lsmMutexLe
d060: 61 76 65 28 64 62 2d 3e 70 45 6e 76 2c 20 70 2d  ave(db->pEnv, p-
d070: 3e 70 43 6c 69 65 6e 74 4d 75 74 65 78 29 3b 0a  >pClientMutex);.
d080: 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a    return rc;.}..
d090: 2f 2a 0a 2a 2a 20 41 74 74 65 6d 70 74 20 74 6f  /*.** Attempt to
d0a0: 20 6f 62 74 61 69 6e 20 74 68 65 20 6c 6f 63 6b   obtain the lock
d0b0: 20 69 64 65 6e 74 69 66 69 65 64 20 62 79 20 74   identified by t
d0c0: 68 65 20 69 4c 6f 63 6b 20 61 6e 64 20 62 45 78  he iLock and bEx
d0d0: 63 6c 20 70 61 72 61 6d 65 74 65 72 73 2e 0a 2a  cl parameters..*
d0e0: 2a 20 49 66 20 73 75 63 63 65 73 73 66 75 6c 2c  * If successful,
d0f0: 20 72 65 74 75 72 6e 20 4c 53 4d 5f 4f 4b 2e 20   return LSM_OK. 
d100: 49 66 20 74 68 65 20 6c 6f 63 6b 20 63 61 6e 6e  If the lock cann
d110: 6f 74 20 62 65 20 6f 62 74 61 69 6e 65 64 20 62  ot be obtained b
d120: 65 63 61 75 73 65 20 0a 2a 2a 20 74 68 65 72 65  ecause .** there
d130: 20 65 78 69 73 74 73 20 73 6f 6d 65 20 6f 74 68   exists some oth
d140: 65 72 20 63 6f 6e 66 6c 69 63 74 69 6e 67 20 6c  er conflicting l
d150: 6f 63 6b 2c 20 72 65 74 75 72 6e 20 4c 53 4d 5f  ock, return LSM_
d160: 42 55 53 59 2e 20 49 66 20 73 6f 6d 65 20 6f 74  BUSY. If some ot
d170: 68 65 72 0a 2a 2a 20 65 72 72 6f 72 20 6f 63 63  her.** error occ
d180: 75 72 73 2c 20 72 65 74 75 72 6e 20 61 6e 20 4c  urs, return an L
d190: 53 4d 20 65 72 72 6f 72 20 63 6f 64 65 2e 0a 2a  SM error code..*
d1a0: 2a 0a 2a 2a 20 50 61 72 61 6d 65 74 65 72 20 69  *.** Parameter i
d1b0: 4c 6f 63 6b 20 6d 75 73 74 20 62 65 20 6f 6e 65  Lock must be one
d1c0: 20 6f 66 20 4c 53 4d 5f 4c 4f 43 4b 5f 57 52 49   of LSM_LOCK_WRI
d1d0: 54 45 52 2c 20 57 4f 52 4b 45 52 20 6f 72 20 43  TER, WORKER or C
d1e0: 48 45 43 4b 50 4f 49 4e 54 45 52 2c 0a 2a 2a 20  HECKPOINTER,.** 
d1f0: 6f 72 20 65 6c 73 65 20 61 20 76 61 6c 75 65 20  or else a value 
d200: 72 65 74 75 72 6e 65 64 20 62 79 20 74 68 65 20  returned by the 
d210: 4c 53 4d 5f 4c 4f 43 4b 5f 52 45 41 44 45 52 20  LSM_LOCK_READER 
d220: 6d 61 63 72 6f 2e 0a 2a 2f 0a 69 6e 74 20 6c 73  macro..*/.int ls
d230: 6d 53 68 6d 4c 6f 63 6b 28 0a 20 20 6c 73 6d 5f  mShmLock(.  lsm_
d240: 64 62 20 2a 64 62 2c 20 0a 20 20 69 6e 74 20 69  db *db, .  int i
d250: 4c 6f 63 6b 2c 0a 20 20 69 6e 74 20 65 4f 70 2c  Lock,.  int eOp,
d260: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
d270: 20 20 20 20 20 20 20 20 2f 2a 20 4f 6e 65 20 6f          /* One o
d280: 66 20 4c 53 4d 5f 4c 4f 43 4b 5f 55 4e 4c 4f 43  f LSM_LOCK_UNLOC
d290: 4b 2c 20 53 48 41 52 45 44 20 6f 72 20 45 58 43  K, SHARED or EXC
d2a0: 4c 20 2a 2f 0a 20 20 69 6e 74 20 62 42 6c 6f 63  L */.  int bBloc
d2b0: 6b 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  k               
d2c0: 20 20 20 20 20 20 20 2f 2a 20 54 72 75 65 20 66         /* True f
d2d0: 6f 72 20 61 20 62 6c 6f 63 6b 69 6e 67 20 6c 6f  or a blocking lo
d2e0: 63 6b 20 2a 2f 0a 29 7b 0a 20 20 6c 73 6d 5f 64  ck */.){.  lsm_d
d2f0: 62 20 2a 70 49 74 65 72 3b 0a 20 20 63 6f 6e 73  b *pIter;.  cons
d300: 74 20 75 36 34 20 6d 65 20 3d 20 28 28 75 36 34  t u64 me = ((u64
d310: 29 31 20 3c 3c 20 28 69 4c 6f 63 6b 2d 31 29 29  )1 << (iLock-1))
d320: 3b 0a 20 20 63 6f 6e 73 74 20 75 36 34 20 6d 73  ;.  const u64 ms
d330: 20 3d 20 28 28 75 36 34 29 31 20 3c 3c 20 28 69   = ((u64)1 << (i
d340: 4c 6f 63 6b 2b 33 32 2d 31 29 29 3b 0a 20 20 69  Lock+32-1));.  i
d350: 6e 74 20 72 63 20 3d 20 4c 53 4d 5f 4f 4b 3b 0a  nt rc = LSM_OK;.
d360: 20 20 44 61 74 61 62 61 73 65 20 2a 70 20 3d 20    Database *p = 
d370: 64 62 2d 3e 70 44 61 74 61 62 61 73 65 3b 0a 0a  db->pDatabase;..
d380: 20 20 61 73 73 65 72 74 28 20 65 4f 70 21 3d 4c    assert( eOp!=L
d390: 53 4d 5f 4c 4f 43 4b 5f 45 58 43 4c 20 7c 7c 20  SM_LOCK_EXCL || 
d3a0: 70 2d 3e 62 52 65 61 64 6f 6e 6c 79 3d 3d 30 20  p->bReadonly==0 
d3b0: 29 3b 0a 20 20 61 73 73 65 72 74 28 20 69 4c 6f  );.  assert( iLo
d3c0: 63 6b 3e 3d 31 20 26 26 20 69 4c 6f 63 6b 3c 3d  ck>=1 && iLock<=
d3d0: 4c 53 4d 5f 4c 4f 43 4b 5f 52 57 43 4c 49 45 4e  LSM_LOCK_RWCLIEN
d3e0: 54 28 4c 53 4d 5f 4c 4f 43 4b 5f 4e 52 57 43 4c  T(LSM_LOCK_NRWCL
d3f0: 49 45 4e 54 2d 31 29 20 29 3b 0a 20 20 61 73 73  IENT-1) );.  ass
d400: 65 72 74 28 20 4c 53 4d 5f 4c 4f 43 4b 5f 52 57  ert( LSM_LOCK_RW
d410: 43 4c 49 45 4e 54 28 4c 53 4d 5f 4c 4f 43 4b 5f  CLIENT(LSM_LOCK_
d420: 4e 52 57 43 4c 49 45 4e 54 2d 31 29 3c 3d 33 32  NRWCLIENT-1)<=32
d430: 20 29 3b 0a 20 20 61 73 73 65 72 74 28 20 65 4f   );.  assert( eO
d440: 70 3d 3d 4c 53 4d 5f 4c 4f 43 4b 5f 55 4e 4c 4f  p==LSM_LOCK_UNLO
d450: 43 4b 20 7c 7c 20 65 4f 70 3d 3d 4c 53 4d 5f 4c  CK || eOp==LSM_L
d460: 4f 43 4b 5f 53 48 41 52 45 44 20 7c 7c 20 65 4f  OCK_SHARED || eO
d470: 70 3d 3d 4c 53 4d 5f 4c 4f 43 4b 5f 45 58 43 4c  p==LSM_LOCK_EXCL
d480: 20 29 3b 0a 0a 20 20 2f 2a 20 43 68 65 63 6b 20   );..  /* Check 
d490: 66 6f 72 20 61 20 6e 6f 2d 6f 70 2e 20 50 72 6f  for a no-op. Pro
d4a0: 63 65 65 64 20 6f 6e 6c 79 20 69 66 20 74 68 69  ceed only if thi
d4b0: 73 20 69 73 20 6e 6f 74 20 6f 6e 65 20 6f 66 20  s is not one of 
d4c0: 74 68 6f 73 65 2e 20 2a 2f 0a 20 20 69 66 28 20  those. */.  if( 
d4d0: 28 65 4f 70 3d 3d 4c 53 4d 5f 4c 4f 43 4b 5f 55  (eOp==LSM_LOCK_U
d4e0: 4e 4c 4f 43 4b 20 26 26 20 28 64 62 2d 3e 6d 4c  NLOCK && (db->mL
d4f0: 6f 63 6b 20 26 20 28 6d 65 7c 6d 73 29 29 21 3d  ock & (me|ms))!=
d500: 30 29 0a 20 20 20 7c 7c 20 28 65 4f 70 3d 3d 4c  0).   || (eOp==L
d510: 53 4d 5f 4c 4f 43 4b 5f 53 48 41 52 45 44 20 26  SM_LOCK_SHARED &
d520: 26 20 28 64 62 2d 3e 6d 4c 6f 63 6b 20 26 20 28  & (db->mLock & (
d530: 6d 65 7c 6d 73 29 29 21 3d 6d 73 29 0a 20 20 20  me|ms))!=ms).   
d540: 7c 7c 20 28 65 4f 70 3d 3d 4c 53 4d 5f 4c 4f 43  || (eOp==LSM_LOC
d550: 4b 5f 45 58 43 4c 20 20 20 26 26 20 28 64 62 2d  K_EXCL   && (db-
d560: 3e 6d 4c 6f 63 6b 20 26 20 6d 65 29 3d 3d 30 29  >mLock & me)==0)
d570: 0a 20 20 29 7b 0a 20 20 20 20 69 6e 74 20 6e 45  .  ){.    int nE
d580: 78 63 6c 20 3d 20 30 3b 20 20 20 20 20 20 20 20  xcl = 0;        
d590: 20 20 20 20 20 20 20 20 2f 2a 20 4e 75 6d 62 65          /* Numbe
d5a0: 72 20 6f 66 20 63 6f 6e 6e 65 63 74 69 6f 6e 73  r of connections
d5b0: 20 68 6f 6c 64 69 6e 67 20 45 58 43 4c 55 53 49   holding EXCLUSI
d5c0: 56 45 20 2a 2f 0a 20 20 20 20 69 6e 74 20 6e 53  VE */.    int nS
d5d0: 68 61 72 65 64 20 3d 20 30 3b 20 20 20 20 20 20  hared = 0;      
d5e0: 20 20 20 20 20 20 20 20 2f 2a 20 4e 75 6d 62 65          /* Numbe
d5f0: 72 20 6f 66 20 63 6f 6e 6e 65 63 74 69 6f 6e 73  r of connections
d600: 20 68 6f 6c 64 69 6e 67 20 53 48 41 52 45 44 20   holding SHARED 
d610: 2a 2f 0a 20 20 20 20 6c 73 6d 4d 75 74 65 78 45  */.    lsmMutexE
d620: 6e 74 65 72 28 64 62 2d 3e 70 45 6e 76 2c 20 70  nter(db->pEnv, p
d630: 2d 3e 70 43 6c 69 65 6e 74 4d 75 74 65 78 29 3b  ->pClientMutex);
d640: 0a 0a 20 20 20 20 2f 2a 20 46 69 67 75 72 65 20  ..    /* Figure 
d650: 6f 75 74 20 74 68 65 20 6c 6f 63 6b 73 20 63 75  out the locks cu
d660: 72 72 65 6e 74 6c 79 20 68 65 6c 64 20 62 79 20  rrently held by 
d670: 74 68 69 73 20 70 72 6f 63 65 73 73 20 6f 6e 20  this process on 
d680: 69 4c 6f 63 6b 2c 20 6e 6f 74 0a 20 20 20 20 2a  iLock, not.    *
d690: 2a 20 69 6e 63 6c 75 64 69 6e 67 20 61 6e 79 20  * including any 
d6a0: 68 65 6c 64 20 62 79 20 63 6f 6e 6e 65 63 74 69  held by connecti
d6b0: 6f 6e 20 64 62 2e 20 20 2a 2f 0a 20 20 20 20 66  on db.  */.    f
d6c0: 6f 72 28 70 49 74 65 72 3d 70 2d 3e 70 43 6f 6e  or(pIter=p->pCon
d6d0: 6e 3b 20 70 49 74 65 72 3b 20 70 49 74 65 72 3d  n; pIter; pIter=
d6e0: 70 49 74 65 72 2d 3e 70 4e 65 78 74 29 7b 0a 20  pIter->pNext){. 
d6f0: 20 20 20 20 20 61 73 73 65 72 74 28 20 28 70 49       assert( (pI
d700: 74 65 72 2d 3e 6d 4c 6f 63 6b 20 26 20 6d 65 29  ter->mLock & me)
d710: 3d 3d 30 20 7c 7c 20 28 70 49 74 65 72 2d 3e 6d  ==0 || (pIter->m
d720: 4c 6f 63 6b 20 26 20 6d 73 29 21 3d 30 20 29 3b  Lock & ms)!=0 );
d730: 0a 20 20 20 20 20 20 69 66 28 20 70 49 74 65 72  .      if( pIter
d740: 21 3d 64 62 20 29 7b 0a 20 20 20 20 20 20 20 20  !=db ){.        
d750: 69 66 28 20 70 49 74 65 72 2d 3e 6d 4c 6f 63 6b  if( pIter->mLock
d760: 20 26 20 6d 65 20 29 7b 0a 20 20 20 20 20 20 20   & me ){.       
d770: 20 20 20 6e 45 78 63 6c 2b 2b 3b 0a 20 20 20 20     nExcl++;.    
d780: 20 20 20 20 7d 65 6c 73 65 20 69 66 28 20 70 49      }else if( pI
d790: 74 65 72 2d 3e 6d 4c 6f 63 6b 20 26 20 6d 73 20  ter->mLock & ms 
d7a0: 29 7b 0a 20 20 20 20 20 20 20 20 20 20 6e 53 68  ){.          nSh
d7b0: 61 72 65 64 2b 2b 3b 0a 20 20 20 20 20 20 20 20  ared++;.        
d7c0: 7d 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a  }.      }.    }.
d7d0: 20 20 20 20 61 73 73 65 72 74 28 20 6e 45 78 63      assert( nExc
d7e0: 6c 3d 3d 30 20 7c 7c 20 6e 45 78 63 6c 3d 3d 31  l==0 || nExcl==1
d7f0: 20 29 3b 0a 20 20 20 20 61 73 73 65 72 74 28 20   );.    assert( 
d800: 6e 45 78 63 6c 3d 3d 30 20 7c 7c 20 6e 53 68 61  nExcl==0 || nSha
d810: 72 65 64 3d 3d 30 20 29 3b 0a 20 20 20 20 61 73  red==0 );.    as
d820: 73 65 72 74 28 20 6e 45 78 63 6c 3d 3d 30 20 7c  sert( nExcl==0 |
d830: 7c 20 28 64 62 2d 3e 6d 4c 6f 63 6b 20 26 20 28  | (db->mLock & (
d840: 6d 65 7c 6d 73 29 29 3d 3d 30 20 29 3b 0a 0a 20  me|ms))==0 );.. 
d850: 20 20 20 73 77 69 74 63 68 28 20 65 4f 70 20 29     switch( eOp )
d860: 7b 0a 20 20 20 20 20 20 63 61 73 65 20 4c 53 4d  {.      case LSM
d870: 5f 4c 4f 43 4b 5f 55 4e 4c 4f 43 4b 3a 0a 20 20  _LOCK_UNLOCK:.  
d880: 20 20 20 20 20 20 69 66 28 20 6e 53 68 61 72 65        if( nShare
d890: 64 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 20 20  d==0 ){.        
d8a0: 20 20 6c 6f 63 6b 53 68 61 72 65 64 46 69 6c 65    lockSharedFile
d8b0: 28 64 62 2d 3e 70 45 6e 76 2c 20 70 2c 20 69 4c  (db->pEnv, p, iL
d8c0: 6f 63 6b 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 55 4e  ock, LSM_LOCK_UN
d8d0: 4c 4f 43 4b 29 3b 0a 20 20 20 20 20 20 20 20 7d  LOCK);.        }
d8e0: 0a 20 20 20 20 20 20 20 20 64 62 2d 3e 6d 4c 6f  .        db->mLo
d8f0: 63 6b 20 26 3d 20 7e 28 6d 65 7c 6d 73 29 3b 0a  ck &= ~(me|ms);.
d900: 20 20 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 0a          break;..
d910: 20 20 20 20 20 20 63 61 73 65 20 4c 53 4d 5f 4c        case LSM_L
d920: 4f 43 4b 5f 53 48 41 52 45 44 3a 0a 20 20 20 20  OCK_SHARED:.    
d930: 20 20 20 20 69 66 28 20 6e 45 78 63 6c 20 29 7b      if( nExcl ){
d940: 0a 20 20 20 20 20 20 20 20 20 20 72 63 20 3d 20  .          rc = 
d950: 4c 53 4d 5f 42 55 53 59 3b 0a 20 20 20 20 20 20  LSM_BUSY;.      
d960: 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 20    }else{.       
d970: 20 20 20 69 66 28 20 6e 53 68 61 72 65 64 3d 3d     if( nShared==
d980: 30 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20 20  0 ){.           
d990: 20 72 63 20 3d 20 6c 6f 63 6b 53 68 61 72 65 64   rc = lockShared
d9a0: 46 69 6c 65 28 64 62 2d 3e 70 45 6e 76 2c 20 70  File(db->pEnv, p
d9b0: 2c 20 69 4c 6f 63 6b 2c 20 4c 53 4d 5f 4c 4f 43  , iLock, LSM_LOC
d9c0: 4b 5f 53 48 41 52 45 44 29 3b 0a 20 20 20 20 20  K_SHARED);.     
d9d0: 20 20 20 20 20 7d 0a 20 20 20 20 20 20 20 20 20       }.         
d9e0: 20 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20   if( rc==LSM_OK 
d9f0: 29 7b 0a 20 20 20 20 20 20 20 20 20 20 20 20 64  ){.            d
da00: 62 2d 3e 6d 4c 6f 63 6b 20 7c 3d 20 6d 73 3b 0a  b->mLock |= ms;.
da10: 20 20 20 20 20 20 20 20 20 20 20 20 64 62 2d 3e              db->
da20: 6d 4c 6f 63 6b 20 26 3d 20 7e 6d 65 3b 0a 20 20  mLock &= ~me;.  
da30: 20 20 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20          }.      
da40: 20 20 7d 0a 20 20 20 20 20 20 20 20 62 72 65 61    }.        brea
da50: 6b 3b 0a 0a 20 20 20 20 20 20 64 65 66 61 75 6c  k;..      defaul
da60: 74 3a 0a 20 20 20 20 20 20 20 20 61 73 73 65 72  t:.        asser
da70: 74 28 20 65 4f 70 3d 3d 4c 53 4d 5f 4c 4f 43 4b  t( eOp==LSM_LOCK
da80: 5f 45 58 43 4c 20 29 3b 0a 20 20 20 20 20 20 20  _EXCL );.       
da90: 20 69 66 28 20 6e 45 78 63 6c 20 7c 7c 20 6e 53   if( nExcl || nS
daa0: 68 61 72 65 64 20 29 7b 0a 20 20 20 20 20 20 20  hared ){.       
dab0: 20 20 20 72 63 20 3d 20 4c 53 4d 5f 42 55 53 59     rc = LSM_BUSY
dac0: 3b 0a 20 20 20 20 20 20 20 20 7d 65 6c 73 65 7b  ;.        }else{
dad0: 0a 20 20 20 20 20 20 20 20 20 20 72 63 20 3d 20  .          rc = 
dae0: 6c 6f 63 6b 53 68 61 72 65 64 46 69 6c 65 28 64  lockSharedFile(d
daf0: 62 2d 3e 70 45 6e 76 2c 20 70 2c 20 69 4c 6f 63  b->pEnv, p, iLoc
db00: 6b 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 45 58 43 4c  k, LSM_LOCK_EXCL
db10: 29 3b 0a 20 20 20 20 20 20 20 20 20 20 69 66 28  );.          if(
db20: 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 29 7b 0a 20   rc==LSM_OK ){. 
db30: 20 20 20 20 20 20 20 20 20 20 20 64 62 2d 3e 6d             db->m
db40: 4c 6f 63 6b 20 7c 3d 20 28 6d 65 7c 6d 73 29 3b  Lock |= (me|ms);
db50: 0a 20 20 20 20 20 20 20 20 20 20 7d 0a 20 20 20  .          }.   
db60: 20 20 20 20 20 7d 0a 20 20 20 20 20 20 20 20 62       }.        b
db70: 72 65 61 6b 3b 0a 20 20 20 20 7d 0a 0a 20 20 20  reak;.    }..   
db80: 20 6c 73 6d 4d 75 74 65 78 4c 65 61 76 65 28 64   lsmMutexLeave(d
db90: 62 2d 3e 70 45 6e 76 2c 20 70 2d 3e 70 43 6c 69  b->pEnv, p->pCli
dba0: 65 6e 74 4d 75 74 65 78 29 3b 0a 20 20 7d 0a 0a  entMutex);.  }..
dbb0: 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a    return rc;.}..
dbc0: 23 69 66 64 65 66 20 4c 53 4d 5f 44 45 42 55 47  #ifdef LSM_DEBUG
dbd0: 0a 0a 69 6e 74 20 73 68 6d 4c 6f 63 6b 54 79 70  ..int shmLockTyp
dbe0: 65 28 6c 73 6d 5f 64 62 20 2a 64 62 2c 20 69 6e  e(lsm_db *db, in
dbf0: 74 20 69 4c 6f 63 6b 29 7b 0a 20 20 63 6f 6e 73  t iLock){.  cons
dc00: 74 20 75 36 34 20 6d 65 20 3d 20 28 28 75 36 34  t u64 me = ((u64
dc10: 29 31 20 3c 3c 20 28 69 4c 6f 63 6b 2d 31 29 29  )1 << (iLock-1))
dc20: 3b 0a 20 20 63 6f 6e 73 74 20 75 36 34 20 6d 73  ;.  const u64 ms
dc30: 20 3d 20 28 28 75 36 34 29 31 20 3c 3c 20 28 69   = ((u64)1 << (i
dc40: 4c 6f 63 6b 2b 33 32 2d 31 29 29 3b 0a 0a 20 20  Lock+32-1));..  
dc50: 69 66 28 20 64 62 2d 3e 6d 4c 6f 63 6b 20 26 20  if( db->mLock & 
dc60: 6d 65 20 29 20 72 65 74 75 72 6e 20 4c 53 4d 5f  me ) return LSM_
dc70: 4c 4f 43 4b 5f 45 58 43 4c 3b 0a 20 20 69 66 28  LOCK_EXCL;.  if(
dc80: 20 64 62 2d 3e 6d 4c 6f 63 6b 20 26 20 6d 73 20   db->mLock & ms 
dc90: 29 20 72 65 74 75 72 6e 20 4c 53 4d 5f 4c 4f 43  ) return LSM_LOC
dca0: 4b 5f 53 48 41 52 45 44 3b 0a 20 20 72 65 74 75  K_SHARED;.  retu
dcb0: 72 6e 20 4c 53 4d 5f 4c 4f 43 4b 5f 55 4e 4c 4f  rn LSM_LOCK_UNLO
dcc0: 43 4b 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54 68 65  CK;.}../*.** The
dcd0: 20 61 72 67 75 6d 65 6e 74 73 20 70 61 73 73 65   arguments passe
dce0: 64 20 74 6f 20 74 68 69 73 20 66 75 6e 63 74 69  d to this functi
dcf0: 6f 6e 20 61 72 65 20 73 69 6d 69 6c 61 72 20 74  on are similar t
dd00: 6f 20 74 68 6f 73 65 20 70 61 73 73 65 64 20 74  o those passed t
dd10: 6f 0a 2a 2a 20 74 68 65 20 6c 73 6d 53 68 6d 4c  o.** the lsmShmL
dd20: 6f 63 6b 28 29 20 66 75 6e 63 74 69 6f 6e 2e 20  ock() function. 
dd30: 48 6f 77 65 76 65 72 2c 20 69 6e 73 74 65 61 64  However, instead
dd40: 20 6f 66 20 6f 62 74 61 69 6e 69 6e 67 20 61 20   of obtaining a 
dd50: 6e 65 77 20 6c 6f 63 6b 20 0a 2a 2a 20 74 68 69  new lock .** thi
dd60: 73 20 66 75 6e 63 74 69 6f 6e 20 72 65 74 75 72  s function retur
dd70: 6e 73 20 74 72 75 65 20 69 66 20 74 68 65 20 73  ns true if the s
dd80: 70 65 63 69 66 69 65 64 20 63 6f 6e 6e 65 63 74  pecified connect
dd90: 69 6f 6e 20 61 6c 72 65 61 64 79 20 68 6f 6c 64  ion already hold
dda0: 73 20 0a 2a 2a 20 28 6f 72 20 64 6f 65 73 20 6e  s .** (or does n
ddb0: 6f 74 20 68 6f 6c 64 29 20 73 75 63 68 20 61 20  ot hold) such a 
ddc0: 6c 6f 63 6b 2c 20 64 65 70 65 6e 64 69 6e 67 20  lock, depending 
ddd0: 6f 6e 20 74 68 65 20 76 61 6c 75 65 20 6f 66 20  on the value of 
dde0: 65 4f 70 2e 20 41 73 0a 2a 2a 20 66 6f 6c 6c 6f  eOp. As.** follo
ddf0: 77 73 3a 0a 2a 2a 0a 2a 2a 20 20 20 28 65 4f 70  ws:.**.**   (eOp
de00: 3d 3d 4c 53 4d 5f 4c 4f 43 4b 5f 55 4e 4c 4f 43  ==LSM_LOCK_UNLOC
de10: 4b 29 20 2d 3e 20 74 72 75 65 20 69 66 20 64 62  K) -> true if db
de20: 20 68 61 73 20 6e 6f 20 6c 6f 63 6b 20 6f 6e 20   has no lock on 
de30: 69 4c 6f 63 6b 0a 2a 2a 20 20 20 28 65 4f 70 3d  iLock.**   (eOp=
de40: 3d 4c 53 4d 5f 4c 4f 43 4b 5f 53 48 41 52 45 44  =LSM_LOCK_SHARED
de50: 29 20 2d 3e 20 74 72 75 65 20 69 66 20 64 62 20  ) -> true if db 
de60: 68 61 73 20 61 74 20 6c 65 61 73 74 20 61 20 53  has at least a S
de70: 48 41 52 45 44 20 6c 6f 63 6b 20 6f 6e 20 69 4c  HARED lock on iL
de80: 6f 63 6b 2e 0a 2a 2a 20 20 20 28 65 4f 70 3d 3d  ock..**   (eOp==
de90: 4c 53 4d 5f 4c 4f 43 4b 5f 45 58 43 4c 29 20 20  LSM_LOCK_EXCL)  
dea0: 20 2d 3e 20 74 72 75 65 20 69 66 20 64 62 20 68   -> true if db h
deb0: 61 73 20 61 6e 20 45 58 43 4c 55 53 49 56 45 20  as an EXCLUSIVE 
dec0: 6c 6f 63 6b 20 6f 6e 20 69 4c 6f 63 6b 2e 0a 2a  lock on iLock..*
ded0: 2f 0a 69 6e 74 20 6c 73 6d 53 68 6d 41 73 73 65  /.int lsmShmAsse
dee0: 72 74 4c 6f 63 6b 28 6c 73 6d 5f 64 62 20 2a 64  rtLock(lsm_db *d
def0: 62 2c 20 69 6e 74 20 69 4c 6f 63 6b 2c 20 69 6e  b, int iLock, in
df00: 74 20 65 4f 70 29 7b 0a 20 20 69 6e 74 20 72 65  t eOp){.  int re
df10: 74 20 3d 20 30 3b 0a 20 20 69 6e 74 20 65 48 61  t = 0;.  int eHa
df20: 76 65 3b 0a 0a 20 20 61 73 73 65 72 74 28 20 69  ve;..  assert( i
df30: 4c 6f 63 6b 3e 3d 31 20 26 26 20 69 4c 6f 63 6b  Lock>=1 && iLock
df40: 3c 3d 4c 53 4d 5f 4c 4f 43 4b 5f 52 45 41 44 45  <=LSM_LOCK_READE
df50: 52 28 4c 53 4d 5f 4c 4f 43 4b 5f 4e 52 45 41 44  R(LSM_LOCK_NREAD
df60: 45 52 2d 31 29 20 29 3b 0a 20 20 61 73 73 65 72  ER-1) );.  asser
df70: 74 28 20 69 4c 6f 63 6b 3c 3d 31 36 20 29 3b 0a  t( iLock<=16 );.
df80: 20 20 61 73 73 65 72 74 28 20 65 4f 70 3d 3d 4c    assert( eOp==L
df90: 53 4d 5f 4c 4f 43 4b 5f 55 4e 4c 4f 43 4b 20 7c  SM_LOCK_UNLOCK |
dfa0: 7c 20 65 4f 70 3d 3d 4c 53 4d 5f 4c 4f 43 4b 5f  | eOp==LSM_LOCK_
dfb0: 53 48 41 52 45 44 20 7c 7c 20 65 4f 70 3d 3d 4c  SHARED || eOp==L
dfc0: 53 4d 5f 4c 4f 43 4b 5f 45 58 43 4c 20 29 3b 0a  SM_LOCK_EXCL );.
dfd0: 0a 20 20 65 48 61 76 65 20 3d 20 73 68 6d 4c 6f  .  eHave = shmLo
dfe0: 63 6b 54 79 70 65 28 64 62 2c 20 69 4c 6f 63 6b  ckType(db, iLock
dff0: 29 3b 0a 0a 20 20 73 77 69 74 63 68 28 20 65 4f  );..  switch( eO
e000: 70 20 29 7b 0a 20 20 20 20 63 61 73 65 20 4c 53  p ){.    case LS
e010: 4d 5f 4c 4f 43 4b 5f 55 4e 4c 4f 43 4b 3a 0a 20  M_LOCK_UNLOCK:. 
e020: 20 20 20 20 20 72 65 74 20 3d 20 28 65 48 61 76       ret = (eHav
e030: 65 3d 3d 4c 53 4d 5f 4c 4f 43 4b 5f 55 4e 4c 4f  e==LSM_LOCK_UNLO
e040: 43 4b 29 3b 0a 20 20 20 20 20 20 62 72 65 61 6b  CK);.      break
e050: 3b 0a 20 20 20 20 63 61 73 65 20 4c 53 4d 5f 4c  ;.    case LSM_L
e060: 4f 43 4b 5f 53 48 41 52 45 44 3a 0a 20 20 20 20  OCK_SHARED:.    
e070: 20 20 72 65 74 20 3d 20 28 65 48 61 76 65 21 3d    ret = (eHave!=
e080: 4c 53 4d 5f 4c 4f 43 4b 5f 55 4e 4c 4f 43 4b 29  LSM_LOCK_UNLOCK)
e090: 3b 0a 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20  ;.      break;. 
e0a0: 20 20 20 63 61 73 65 20 4c 53 4d 5f 4c 4f 43 4b     case LSM_LOCK
e0b0: 5f 45 58 43 4c 3a 0a 20 20 20 20 20 20 72 65 74  _EXCL:.      ret
e0c0: 20 3d 20 28 65 48 61 76 65 3d 3d 4c 53 4d 5f 4c   = (eHave==LSM_L
e0d0: 4f 43 4b 5f 45 58 43 4c 29 3b 0a 20 20 20 20 20  OCK_EXCL);.     
e0e0: 20 62 72 65 61 6b 3b 0a 20 20 20 20 64 65 66 61   break;.    defa
e0f0: 75 6c 74 3a 0a 20 20 20 20 20 20 61 73 73 65 72  ult:.      asser
e100: 74 28 20 21 22 62 61 64 20 65 4f 70 20 76 61 6c  t( !"bad eOp val
e110: 75 65 20 70 61 73 73 65 64 20 74 6f 20 6c 73 6d  ue passed to lsm
e120: 53 68 6d 41 73 73 65 72 74 4c 6f 63 6b 28 29 22  ShmAssertLock()"
e130: 20 29 3b 0a 20 20 20 20 20 20 62 72 65 61 6b 3b   );.      break;
e140: 0a 20 20 7d 0a 0a 20 20 72 65 74 75 72 6e 20 72  .  }..  return r
e150: 65 74 3b 0a 7d 0a 0a 69 6e 74 20 6c 73 6d 53 68  et;.}..int lsmSh
e160: 6d 41 73 73 65 72 74 57 6f 72 6b 65 72 28 6c 73  mAssertWorker(ls
e170: 6d 5f 64 62 20 2a 64 62 29 7b 0a 20 20 72 65 74  m_db *db){.  ret
e180: 75 72 6e 20 6c 73 6d 53 68 6d 41 73 73 65 72 74  urn lsmShmAssert
e190: 4c 6f 63 6b 28 64 62 2c 20 4c 53 4d 5f 4c 4f 43  Lock(db, LSM_LOC
e1a0: 4b 5f 57 4f 52 4b 45 52 2c 20 4c 53 4d 5f 4c 4f  K_WORKER, LSM_LO
e1b0: 43 4b 5f 45 58 43 4c 29 20 26 26 20 64 62 2d 3e  CK_EXCL) && db->
e1c0: 70 57 6f 72 6b 65 72 3b 0a 7d 0a 0a 2f 2a 0a 2a  pWorker;.}../*.*
e1d0: 2a 20 54 68 69 73 20 66 75 6e 63 74 69 6f 6e 20  * This function 
e1e0: 64 6f 65 73 20 6e 6f 74 20 63 6f 6e 74 72 69 62  does not contrib
e1f0: 75 74 65 20 74 6f 20 6c 69 62 72 61 72 79 20 66  ute to library f
e200: 75 6e 63 74 69 6f 6e 61 6c 69 74 79 2c 20 61 6e  unctionality, an
e210: 64 20 69 73 20 6e 6f 74 0a 2a 2a 20 69 6e 63 6c  d is not.** incl
e220: 75 64 65 64 20 69 6e 20 72 65 6c 65 61 73 65 20  uded in release 
e230: 62 75 69 6c 64 73 2e 20 49 74 20 69 73 20 69 6e  builds. It is in
e240: 74 65 6e 64 65 64 20 74 6f 20 62 65 20 63 61 6c  tended to be cal
e250: 6c 65 64 20 66 72 6f 6d 20 77 69 74 68 69 6e 0a  led from within.
e260: 2a 2a 20 61 6e 20 69 6e 74 65 72 61 63 74 69 76  ** an interactiv
e270: 65 20 64 65 62 75 67 67 65 72 2e 0a 2a 2a 0a 2a  e debugger..**.*
e280: 2a 20 57 68 65 6e 20 63 61 6c 6c 65 64 2c 20 74  * When called, t
e290: 68 69 73 20 66 75 6e 63 74 69 6f 6e 20 70 72 69  his function pri
e2a0: 6e 74 73 20 61 20 73 69 6e 67 6c 65 20 6c 69 6e  nts a single lin
e2b0: 65 20 6f 66 20 68 75 6d 61 6e 20 72 65 61 64 61  e of human reada
e2c0: 62 6c 65 20 6f 75 74 70 75 74 0a 2a 2a 20 74 6f  ble output.** to
e2d0: 20 73 74 64 6f 75 74 20 64 65 73 63 72 69 62 69   stdout describi
e2e0: 6e 67 20 74 68 65 20 6c 6f 63 6b 73 20 63 75 72  ng the locks cur
e2f0: 72 65 6e 74 6c 79 20 68 65 6c 64 20 62 79 20 74  rently held by t
e300: 68 65 20 63 6f 6e 6e 65 63 74 69 6f 6e 2e 20 46  he connection. F
e310: 6f 72 20 0a 2a 2a 20 65 78 61 6d 70 6c 65 3a 0a  or .** example:.
e320: 2a 2a 0a 2a 2a 20 20 20 20 20 28 67 64 62 29 20  **.**     (gdb) 
e330: 63 61 6c 6c 20 70 72 69 6e 74 5f 64 62 5f 6c 6f  call print_db_lo
e340: 63 6b 73 28 70 44 62 29 0a 2a 2a 20 20 20 20 20  cks(pDb).**     
e350: 28 73 68 61 72 65 64 20 6f 6e 20 64 6d 73 32 29  (shared on dms2)
e360: 20 28 65 78 63 6c 75 73 69 76 65 20 6f 6e 20 77   (exclusive on w
e370: 72 69 74 65 72 29 20 0a 2a 2f 0a 76 6f 69 64 20  riter) .*/.void 
e380: 70 72 69 6e 74 5f 64 62 5f 6c 6f 63 6b 73 28 6c  print_db_locks(l
e390: 73 6d 5f 64 62 20 2a 64 62 29 7b 0a 20 20 69 6e  sm_db *db){.  in
e3a0: 74 20 69 4c 6f 63 6b 3b 0a 20 20 66 6f 72 28 69  t iLock;.  for(i
e3b0: 4c 6f 63 6b 3d 30 3b 20 69 4c 6f 63 6b 3c 31 36  Lock=0; iLock<16
e3c0: 3b 20 69 4c 6f 63 6b 2b 2b 29 7b 0a 20 20 20 20  ; iLock++){.    
e3d0: 69 6e 74 20 62 4f 6e 65 20 3d 20 30 3b 0a 20 20  int bOne = 0;.  
e3e0: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 61 7a    const char *az
e3f0: 4c 6f 63 6b 5b 5d 20 3d 20 7b 30 2c 20 22 73 68  Lock[] = {0, "sh
e400: 61 72 65 64 22 2c 20 22 65 78 63 6c 75 73 69 76  ared", "exclusiv
e410: 65 22 7d 3b 0a 20 20 20 20 63 6f 6e 73 74 20 63  e"};.    const c
e420: 68 61 72 20 2a 61 7a 4e 61 6d 65 5b 5d 20 3d 20  har *azName[] = 
e430: 7b 0a 20 20 20 20 20 20 30 2c 20 22 64 6d 73 31  {.      0, "dms1
e440: 22 2c 20 22 64 6d 73 32 22 2c 20 22 77 72 69 74  ", "dms2", "writ
e450: 65 72 22 2c 20 22 77 6f 72 6b 65 72 22 2c 20 22  er", "worker", "
e460: 63 68 65 63 6b 70 6f 69 6e 74 65 72 22 2c 0a 20  checkpointer",. 
e470: 20 20 20 20 20 22 72 65 61 64 65 72 30 22 2c 20       "reader0", 
e480: 22 72 65 61 64 65 72 31 22 2c 20 22 72 65 61 64  "reader1", "read
e490: 65 72 32 22 2c 20 22 72 65 61 64 65 72 33 22 2c  er2", "reader3",
e4a0: 20 22 72 65 61 64 65 72 34 22 2c 20 22 72 65 61   "reader4", "rea
e4b0: 64 65 72 35 22 0a 20 20 20 20 7d 3b 0a 20 20 20  der5".    };.   
e4c0: 20 69 6e 74 20 65 48 61 76 65 20 3d 20 73 68 6d   int eHave = shm
e4d0: 4c 6f 63 6b 54 79 70 65 28 64 62 2c 20 69 4c 6f  LockType(db, iLo
e4e0: 63 6b 29 3b 0a 20 20 20 20 69 66 28 20 61 7a 4c  ck);.    if( azL
e4f0: 6f 63 6b 5b 65 48 61 76 65 5d 20 29 7b 0a 20 20  ock[eHave] ){.  
e500: 20 20 20 20 70 72 69 6e 74 66 28 22 25 73 28 25      printf("%s(%
e510: 73 20 6f 6e 20 25 73 29 22 2c 20 28 62 4f 6e 65  s on %s)", (bOne
e520: 3f 22 20 22 3a 22 22 29 2c 20 61 7a 4c 6f 63 6b  ?" ":""), azLock
e530: 5b 65 48 61 76 65 5d 2c 20 61 7a 4e 61 6d 65 5b  [eHave], azName[
e540: 69 4c 6f 63 6b 5d 29 3b 0a 20 20 20 20 20 20 62  iLock]);.      b
e550: 4f 6e 65 20 3d 20 31 3b 0a 20 20 20 20 7d 0a 20  One = 1;.    }. 
e560: 20 7d 0a 20 20 70 72 69 6e 74 66 28 22 5c 6e 22   }.  printf("\n"
e570: 29 3b 0a 7d 0a 76 6f 69 64 20 70 72 69 6e 74 5f  );.}.void print_
e580: 61 6c 6c 5f 64 62 5f 6c 6f 63 6b 73 28 6c 73 6d  all_db_locks(lsm
e590: 5f 64 62 20 2a 64 62 29 7b 0a 20 20 6c 73 6d 5f  _db *db){.  lsm_
e5a0: 64 62 20 2a 70 3b 0a 20 20 66 6f 72 28 70 3d 64  db *p;.  for(p=d
e5b0: 62 2d 3e 70 44 61 74 61 62 61 73 65 2d 3e 70 43  b->pDatabase->pC
e5c0: 6f 6e 6e 3b 20 70 3b 20 70 3d 70 2d 3e 70 4e 65  onn; p; p=p->pNe
e5d0: 78 74 29 7b 0a 20 20 20 20 70 72 69 6e 74 66 28  xt){.    printf(
e5e0: 22 25 73 20 63 6f 6e 6e 65 63 74 69 6f 6e 20 25  "%s connection %
e5f0: 70 20 22 2c 20 28 28 70 3d 3d 64 62 29 3f 22 2a  p ", ((p==db)?"*
e600: 22 3a 22 22 29 2c 20 70 29 3b 0a 20 20 20 20 70  ":""), p);.    p
e610: 72 69 6e 74 5f 64 62 5f 6c 6f 63 6b 73 28 70 29  rint_db_locks(p)
e620: 3b 0a 20 20 7d 0a 7d 0a 23 65 6e 64 69 66 0a 0a  ;.  }.}.#endif..
e630: 76 6f 69 64 20 6c 73 6d 53 68 6d 42 61 72 72 69  void lsmShmBarri
e640: 65 72 28 6c 73 6d 5f 64 62 20 2a 64 62 29 7b 0a  er(lsm_db *db){.
e650: 20 20 6c 73 6d 45 6e 76 53 68 6d 42 61 72 72 69    lsmEnvShmBarri
e660: 65 72 28 64 62 2d 3e 70 45 6e 76 29 3b 0a 7d 0a  er(db->pEnv);.}.
e670: 0a 69 6e 74 20 6c 73 6d 5f 63 68 65 63 6b 70 6f  .int lsm_checkpo
e680: 69 6e 74 28 6c 73 6d 5f 64 62 20 2a 70 44 62 2c  int(lsm_db *pDb,
e690: 20 69 6e 74 20 2a 70 6e 4b 42 29 7b 0a 20 20 69   int *pnKB){.  i
e6a0: 6e 74 20 72 63 3b 20 20 20 20 20 20 20 20 20 20  nt rc;          
e6b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
e6c0: 2a 20 52 65 74 75 72 6e 20 63 6f 64 65 20 2a 2f  * Return code */
e6d0: 0a 20 20 75 33 32 20 6e 57 72 69 74 65 20 3d 20  .  u32 nWrite = 
e6e0: 30 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  0;              
e6f0: 20 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f 66 20     /* Number of 
e700: 70 61 67 65 73 20 63 68 65 63 6b 70 6f 69 6e 74  pages checkpoint
e710: 65 64 20 2a 2f 0a 0a 20 20 2f 2a 20 41 74 74 65  ed */..  /* Atte
e720: 6d 70 74 20 74 68 65 20 63 68 65 63 6b 70 6f 69  mpt the checkpoi
e730: 6e 74 2e 20 49 66 20 73 75 63 63 65 73 73 66 75  nt. If successfu
e740: 6c 2c 20 6e 57 72 69 74 65 20 69 73 20 73 65 74  l, nWrite is set
e750: 20 74 6f 20 74 68 65 20 6e 75 6d 62 65 72 20 6f   to the number o
e760: 66 0a 20 20 2a 2a 20 70 61 67 65 73 20 77 72 69  f.  ** pages wri
e770: 74 74 65 6e 20 62 65 74 77 65 65 6e 20 74 68 69  tten between thi
e780: 73 20 61 6e 64 20 74 68 65 20 70 72 65 76 69 6f  s and the previo
e790: 75 73 20 63 68 65 63 6b 70 6f 69 6e 74 2e 20 20  us checkpoint.  
e7a0: 2a 2f 0a 20 20 72 63 20 3d 20 6c 73 6d 43 68 65  */.  rc = lsmChe
e7b0: 63 6b 70 6f 69 6e 74 57 72 69 74 65 28 70 44 62  ckpointWrite(pDb
e7c0: 2c 20 26 6e 57 72 69 74 65 29 3b 0a 0a 20 20 2f  , &nWrite);..  /
e7d0: 2a 20 49 66 20 72 65 71 75 69 72 65 64 2c 20 63  * If required, c
e7e0: 61 6c 63 75 6c 61 74 65 20 74 68 65 20 6f 75 74  alculate the out
e7f0: 70 75 74 20 76 61 72 69 61 62 6c 65 20 28 4b 42  put variable (KB
e800: 20 6f 66 20 64 61 74 61 20 63 68 65 63 6b 70 6f   of data checkpo
e810: 69 6e 74 65 64 29 2e 20 0a 20 20 2a 2a 20 53 65  inted). .  ** Se
e820: 74 20 69 74 20 74 6f 20 7a 65 72 6f 20 69 66 20  t it to zero if 
e830: 61 6e 20 65 72 72 6f 72 20 6f 63 63 75 72 65 64  an error occured
e840: 2e 20 20 2a 2f 0a 20 20 69 66 28 20 70 6e 4b 42  .  */.  if( pnKB
e850: 20 29 7b 0a 20 20 20 20 69 6e 74 20 6e 4b 42 20   ){.    int nKB 
e860: 3d 20 30 3b 0a 20 20 20 20 69 66 28 20 72 63 3d  = 0;.    if( rc=
e870: 3d 4c 53 4d 5f 4f 4b 20 26 26 20 6e 57 72 69 74  =LSM_OK && nWrit
e880: 65 20 29 7b 0a 20 20 20 20 20 20 6e 4b 42 20 3d  e ){.      nKB =
e890: 20 28 28 28 69 36 34 29 6e 57 72 69 74 65 20 2a   (((i64)nWrite *
e8a0: 20 6c 73 6d 46 73 50 61 67 65 53 69 7a 65 28 70   lsmFsPageSize(p
e8b0: 44 62 2d 3e 70 46 53 29 29 20 2b 20 31 30 32 33  Db->pFS)) + 1023
e8c0: 29 20 2f 20 31 30 32 34 3b 0a 20 20 20 20 7d 0a  ) / 1024;.    }.
e8d0: 20 20 20 20 2a 70 6e 4b 42 20 3d 20 6e 4b 42 3b      *pnKB = nKB;
e8e0: 0a 20 20 7d 0a 0a 20 20 72 65 74 75 72 6e 20 72  .  }..  return r
e8f0: 63 3b 0a 7d 0a                                   c;.}.