/ Hex Artifact Content
Login

Artifact 1a76b7a5e89a003c24d58f1fb295c4203b48ef6acba9a194ac6003ade09fcd47:


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 70  ned.  */.  if( p
4170: 44 62 2d 3e 62 52 65 61 64 6f 6e 6c 79 3d 3d 30  Db->bReadonly==0
4180: 20 29 7b 0a 20 20 20 20 69 66 28 20 72 63 3d 3d   ){.    if( rc==
4190: 4c 53 4d 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20  LSM_OK ){.      
41a0: 72 63 20 3d 20 6c 73 6d 46 73 43 6f 6e 66 69 67  rc = lsmFsConfig
41b0: 75 72 65 28 70 44 62 29 3b 0a 20 20 20 20 7d 0a  ure(pDb);.    }.
41c0: 20 20 20 20 69 66 28 20 72 63 3d 3d 4c 53 4d 5f      if( rc==LSM_
41d0: 4f 4b 20 29 7b 0a 20 20 20 20 20 20 72 63 20 3d  OK ){.      rc =
41e0: 20 64 6f 44 62 43 6f 6e 6e 65 63 74 28 70 44 62   doDbConnect(pDb
41f0: 29 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 0a 20 20  );.    }.  }..  
4200: 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 73 74  return rc;.}..st
4210: 61 74 69 63 20 76 6f 69 64 20 64 62 44 65 66 65  atic void dbDefe
4220: 72 43 6c 6f 73 65 28 6c 73 6d 5f 64 62 20 2a 70  rClose(lsm_db *p
4230: 44 62 29 7b 0a 20 20 69 66 28 20 70 44 62 2d 3e  Db){.  if( pDb->
4240: 70 46 53 20 29 7b 0a 20 20 20 20 4c 73 6d 46 69  pFS ){.    LsmFi
4250: 6c 65 20 2a 70 4c 73 6d 46 69 6c 65 3b 0a 20 20  le *pLsmFile;.  
4260: 20 20 44 61 74 61 62 61 73 65 20 2a 70 20 3d 20    Database *p = 
4270: 70 44 62 2d 3e 70 44 61 74 61 62 61 73 65 3b 0a  pDb->pDatabase;.
4280: 20 20 20 20 70 4c 73 6d 46 69 6c 65 20 3d 20 6c      pLsmFile = l
4290: 73 6d 46 73 44 65 66 65 72 43 6c 6f 73 65 28 70  smFsDeferClose(p
42a0: 44 62 2d 3e 70 46 53 29 3b 0a 20 20 20 20 70 4c  Db->pFS);.    pL
42b0: 73 6d 46 69 6c 65 2d 3e 70 4e 65 78 74 20 3d 20  smFile->pNext = 
42c0: 70 2d 3e 70 4c 73 6d 46 69 6c 65 3b 0a 20 20 20  p->pLsmFile;.   
42d0: 20 70 2d 3e 70 4c 73 6d 46 69 6c 65 20 3d 20 70   p->pLsmFile = p
42e0: 4c 73 6d 46 69 6c 65 3b 0a 20 20 7d 0a 7d 0a 0a  LsmFile;.  }.}..
42f0: 4c 73 6d 46 69 6c 65 20 2a 6c 73 6d 44 62 52 65  LsmFile *lsmDbRe
4300: 63 79 63 6c 65 46 64 28 6c 73 6d 5f 64 62 20 2a  cycleFd(lsm_db *
4310: 64 62 29 7b 0a 20 20 4c 73 6d 46 69 6c 65 20 2a  db){.  LsmFile *
4320: 70 52 65 74 3b 0a 20 20 44 61 74 61 62 61 73 65  pRet;.  Database
4330: 20 2a 70 20 3d 20 64 62 2d 3e 70 44 61 74 61 62   *p = db->pDatab
4340: 61 73 65 3b 0a 20 20 6c 73 6d 4d 75 74 65 78 45  ase;.  lsmMutexE
4350: 6e 74 65 72 28 64 62 2d 3e 70 45 6e 76 2c 20 70  nter(db->pEnv, p
4360: 2d 3e 70 43 6c 69 65 6e 74 4d 75 74 65 78 29 3b  ->pClientMutex);
4370: 0a 20 20 69 66 28 20 28 70 52 65 74 20 3d 20 70  .  if( (pRet = p
4380: 2d 3e 70 4c 73 6d 46 69 6c 65 29 21 3d 30 20 29  ->pLsmFile)!=0 )
4390: 7b 0a 20 20 20 20 70 2d 3e 70 4c 73 6d 46 69 6c  {.    p->pLsmFil
43a0: 65 20 3d 20 70 52 65 74 2d 3e 70 4e 65 78 74 3b  e = pRet->pNext;
43b0: 0a 20 20 7d 0a 20 20 6c 73 6d 4d 75 74 65 78 4c  .  }.  lsmMutexL
43c0: 65 61 76 65 28 64 62 2d 3e 70 45 6e 76 2c 20 70  eave(db->pEnv, p
43d0: 2d 3e 70 43 6c 69 65 6e 74 4d 75 74 65 78 29 3b  ->pClientMutex);
43e0: 0a 20 20 72 65 74 75 72 6e 20 70 52 65 74 3b 0a  .  return pRet;.
43f0: 7d 0a 0a 2f 2a 0a 2a 2a 20 52 65 6c 65 61 73 65  }../*.** Release
4400: 20 61 20 72 65 66 65 72 65 6e 63 65 20 74 6f 20   a reference to 
4410: 61 20 44 61 74 61 62 61 73 65 20 6f 62 6a 65 63  a Database objec
4420: 74 20 6f 62 74 61 69 6e 65 64 20 66 72 6f 6d 20  t obtained from 
4430: 0a 2a 2a 20 6c 73 6d 44 62 44 61 74 61 62 61 73  .** lsmDbDatabas
4440: 65 43 6f 6e 6e 65 63 74 28 29 2e 20 54 68 65 72  eConnect(). Ther
4450: 65 20 73 68 6f 75 6c 64 20 62 65 20 65 78 61 63  e should be exac
4460: 74 6c 79 20 6f 6e 65 20 63 61 6c 6c 20 74 6f 20  tly one call to 
4470: 74 68 69 73 20 66 75 6e 63 74 69 6f 6e 20 0a 2a  this function .*
4480: 2a 20 66 6f 72 20 65 61 63 68 20 73 75 63 63 65  * for each succe
4490: 73 73 66 75 6c 20 63 61 6c 6c 20 74 6f 20 46 69  ssful call to Fi
44a0: 6e 64 28 29 2e 0a 2a 2f 0a 76 6f 69 64 20 6c 73  nd()..*/.void ls
44b0: 6d 44 62 44 61 74 61 62 61 73 65 52 65 6c 65 61  mDbDatabaseRelea
44c0: 73 65 28 6c 73 6d 5f 64 62 20 2a 70 44 62 29 7b  se(lsm_db *pDb){
44d0: 0a 20 20 44 61 74 61 62 61 73 65 20 2a 70 20 3d  .  Database *p =
44e0: 20 70 44 62 2d 3e 70 44 61 74 61 62 61 73 65 3b   pDb->pDatabase;
44f0: 0a 20 20 69 66 28 20 70 20 29 7b 0a 20 20 20 20  .  if( p ){.    
4500: 6c 73 6d 5f 64 62 20 2a 2a 70 70 44 62 3b 0a 0a  lsm_db **ppDb;..
4510: 20 20 20 20 69 66 28 20 70 44 62 2d 3e 70 53 68      if( pDb->pSh
4520: 6d 68 64 72 20 29 7b 0a 20 20 20 20 20 20 64 6f  mhdr ){.      do
4530: 44 62 44 69 73 63 6f 6e 6e 65 63 74 28 70 44 62  DbDisconnect(pDb
4540: 29 3b 0a 20 20 20 20 7d 0a 0a 20 20 20 20 6c 73  );.    }..    ls
4550: 6d 46 73 55 6e 6d 61 70 28 70 44 62 2d 3e 70 46  mFsUnmap(pDb->pF
4560: 53 29 3b 0a 20 20 20 20 6c 73 6d 4d 75 74 65 78  S);.    lsmMutex
4570: 45 6e 74 65 72 28 70 44 62 2d 3e 70 45 6e 76 2c  Enter(pDb->pEnv,
4580: 20 70 2d 3e 70 43 6c 69 65 6e 74 4d 75 74 65 78   p->pClientMutex
4590: 29 3b 0a 20 20 20 20 66 6f 72 28 70 70 44 62 3d  );.    for(ppDb=
45a0: 26 70 2d 3e 70 43 6f 6e 6e 3b 20 2a 70 70 44 62  &p->pConn; *ppDb
45b0: 21 3d 70 44 62 3b 20 70 70 44 62 3d 26 28 28 2a  !=pDb; ppDb=&((*
45c0: 70 70 44 62 29 2d 3e 70 4e 65 78 74 29 29 3b 0a  ppDb)->pNext));.
45d0: 20 20 20 20 2a 70 70 44 62 20 3d 20 70 44 62 2d      *ppDb = pDb-
45e0: 3e 70 4e 65 78 74 3b 0a 20 20 20 20 64 62 44 65  >pNext;.    dbDe
45f0: 66 65 72 43 6c 6f 73 65 28 70 44 62 29 3b 0a 20  ferClose(pDb);. 
4600: 20 20 20 6c 73 6d 4d 75 74 65 78 4c 65 61 76 65     lsmMutexLeave
4610: 28 70 44 62 2d 3e 70 45 6e 76 2c 20 70 2d 3e 70  (pDb->pEnv, p->p
4620: 43 6c 69 65 6e 74 4d 75 74 65 78 29 3b 0a 0a 20  ClientMutex);.. 
4630: 20 20 20 65 6e 74 65 72 47 6c 6f 62 61 6c 4d 75     enterGlobalMu
4640: 74 65 78 28 70 44 62 2d 3e 70 45 6e 76 29 3b 0a  tex(pDb->pEnv);.
4650: 20 20 20 20 70 2d 3e 6e 44 62 52 65 66 2d 2d 3b      p->nDbRef--;
4660: 0a 20 20 20 20 69 66 28 20 70 2d 3e 6e 44 62 52  .    if( p->nDbR
4670: 65 66 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 4c  ef==0 ){.      L
4680: 73 6d 46 69 6c 65 20 2a 70 49 74 65 72 3b 0a 20  smFile *pIter;. 
4690: 20 20 20 20 20 4c 73 6d 46 69 6c 65 20 2a 70 4e       LsmFile *pN
46a0: 65 78 74 3b 0a 20 20 20 20 20 20 44 61 74 61 62  ext;.      Datab
46b0: 61 73 65 20 2a 2a 70 70 3b 0a 0a 20 20 20 20 20  ase **pp;..     
46c0: 20 2f 2a 20 52 65 6d 6f 76 65 20 74 68 65 20 44   /* Remove the D
46d0: 61 74 61 62 61 73 65 20 73 74 72 75 63 74 75 72  atabase structur
46e0: 65 20 66 72 6f 6d 20 74 68 65 20 6c 69 6e 6b 65  e from the linke
46f0: 64 20 6c 69 73 74 2e 20 2a 2f 0a 20 20 20 20 20  d list. */.     
4700: 20 66 6f 72 28 70 70 3d 26 67 53 68 61 72 65 64   for(pp=&gShared
4710: 2e 70 44 61 74 61 62 61 73 65 3b 20 2a 70 70 21  .pDatabase; *pp!
4720: 3d 70 3b 20 70 70 3d 26 28 28 2a 70 70 29 2d 3e  =p; pp=&((*pp)->
4730: 70 44 62 4e 65 78 74 29 29 3b 0a 20 20 20 20 20  pDbNext));.     
4740: 20 2a 70 70 20 3d 20 70 2d 3e 70 44 62 4e 65 78   *pp = p->pDbNex
4750: 74 3b 0a 0a 20 20 20 20 20 20 2f 2a 20 49 66 20  t;..      /* If 
4760: 74 68 65 79 20 77 65 72 65 20 61 6c 6c 6f 63 61  they were alloca
4770: 74 65 64 20 66 72 6f 6d 20 74 68 65 20 68 65 61  ted from the hea
4780: 70 2c 20 66 72 65 65 20 74 68 65 20 73 68 61 72  p, free the shar
4790: 65 64 20 6d 65 6d 6f 72 79 20 63 68 75 6e 6b 73  ed memory chunks
47a0: 20 2a 2f 0a 20 20 20 20 20 20 69 66 28 20 70 2d   */.      if( p-
47b0: 3e 62 4d 75 6c 74 69 50 72 6f 63 3d 3d 30 20 29  >bMultiProc==0 )
47c0: 7b 0a 20 20 20 20 20 20 20 20 69 6e 74 20 69 3b  {.        int i;
47d0: 0a 20 20 20 20 20 20 20 20 66 6f 72 28 69 3d 30  .        for(i=0
47e0: 3b 20 69 3c 70 2d 3e 6e 53 68 6d 43 68 75 6e 6b  ; i<p->nShmChunk
47f0: 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 20 20 20 20  ; i++){.        
4800: 20 20 6c 73 6d 46 72 65 65 28 70 44 62 2d 3e 70    lsmFree(pDb->p
4810: 45 6e 76 2c 20 70 2d 3e 61 70 53 68 6d 43 68 75  Env, p->apShmChu
4820: 6e 6b 5b 69 5d 29 3b 0a 20 20 20 20 20 20 20 20  nk[i]);.        
4830: 7d 0a 20 20 20 20 20 20 7d 0a 0a 20 20 20 20 20  }.      }..     
4840: 20 2f 2a 20 43 6c 6f 73 65 20 61 6e 79 20 6f 75   /* Close any ou
4850: 74 73 74 61 6e 64 69 6e 67 20 66 69 6c 65 20 64  tstanding file d
4860: 65 73 63 72 69 70 74 6f 72 73 20 2a 2f 0a 20 20  escriptors */.  
4870: 20 20 20 20 66 6f 72 28 70 49 74 65 72 3d 70 2d      for(pIter=p-
4880: 3e 70 4c 73 6d 46 69 6c 65 3b 20 70 49 74 65 72  >pLsmFile; pIter
4890: 3b 20 70 49 74 65 72 3d 70 4e 65 78 74 29 7b 0a  ; pIter=pNext){.
48a0: 20 20 20 20 20 20 20 20 70 4e 65 78 74 20 3d 20          pNext = 
48b0: 70 49 74 65 72 2d 3e 70 4e 65 78 74 3b 0a 20 20  pIter->pNext;.  
48c0: 20 20 20 20 20 20 6c 73 6d 45 6e 76 43 6c 6f 73        lsmEnvClos
48d0: 65 28 70 44 62 2d 3e 70 45 6e 76 2c 20 70 49 74  e(pDb->pEnv, pIt
48e0: 65 72 2d 3e 70 46 69 6c 65 29 3b 0a 20 20 20 20  er->pFile);.    
48f0: 20 20 20 20 6c 73 6d 46 72 65 65 28 70 44 62 2d      lsmFree(pDb-
4900: 3e 70 45 6e 76 2c 20 70 49 74 65 72 29 3b 0a 20  >pEnv, pIter);. 
4910: 20 20 20 20 20 7d 0a 20 20 20 20 20 20 66 72 65       }.      fre
4920: 65 44 61 74 61 62 61 73 65 28 70 44 62 2d 3e 70  eDatabase(pDb->p
4930: 45 6e 76 2c 20 70 29 3b 0a 20 20 20 20 7d 0a 20  Env, p);.    }. 
4940: 20 20 20 6c 65 61 76 65 47 6c 6f 62 61 6c 4d 75     leaveGlobalMu
4950: 74 65 78 28 70 44 62 2d 3e 70 45 6e 76 29 3b 0a  tex(pDb->pEnv);.
4960: 20 20 7d 0a 7d 0a 0a 4c 65 76 65 6c 20 2a 6c 73    }.}..Level *ls
4970: 6d 44 62 53 6e 61 70 73 68 6f 74 4c 65 76 65 6c  mDbSnapshotLevel
4980: 28 53 6e 61 70 73 68 6f 74 20 2a 70 53 6e 61 70  (Snapshot *pSnap
4990: 73 68 6f 74 29 7b 0a 20 20 72 65 74 75 72 6e 20  shot){.  return 
49a0: 70 53 6e 61 70 73 68 6f 74 2d 3e 70 4c 65 76 65  pSnapshot->pLeve
49b0: 6c 3b 0a 7d 0a 0a 76 6f 69 64 20 6c 73 6d 44 62  l;.}..void lsmDb
49c0: 53 6e 61 70 73 68 6f 74 53 65 74 4c 65 76 65 6c  SnapshotSetLevel
49d0: 28 53 6e 61 70 73 68 6f 74 20 2a 70 53 6e 61 70  (Snapshot *pSnap
49e0: 2c 20 4c 65 76 65 6c 20 2a 70 4c 65 76 65 6c 29  , Level *pLevel)
49f0: 7b 0a 20 20 70 53 6e 61 70 2d 3e 70 4c 65 76 65  {.  pSnap->pLeve
4a00: 6c 20 3d 20 70 4c 65 76 65 6c 3b 0a 7d 0a 0a 2f  l = pLevel;.}../
4a10: 2a 20 54 4f 44 4f 3a 20 53 68 75 66 66 6c 65 20  * TODO: Shuffle 
4a20: 74 68 69 6e 67 73 20 61 72 6f 75 6e 64 20 74 6f  things around to
4a30: 20 67 65 74 20 72 69 64 20 6f 66 20 74 68 69 73   get rid of this
4a40: 20 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 66   */.static int f
4a50: 69 72 73 74 53 6e 61 70 73 68 6f 74 49 6e 55 73  irstSnapshotInUs
4a60: 65 28 6c 73 6d 5f 64 62 20 2a 2c 20 69 36 34 20  e(lsm_db *, i64 
4a70: 2a 29 3b 0a 0a 2f 2a 20 0a 2a 2a 20 43 6f 6e 74  *);../* .** Cont
4a80: 65 78 74 20 6f 62 6a 65 63 74 20 75 73 65 64 20  ext object used 
4a90: 62 79 20 74 68 65 20 6c 73 6d 57 61 6c 6b 46 72  by the lsmWalkFr
4aa0: 65 65 6c 69 73 74 28 29 20 75 74 69 6c 69 74 79  eelist() utility
4ab0: 2e 20 0a 2a 2f 0a 74 79 70 65 64 65 66 20 73 74  . .*/.typedef st
4ac0: 72 75 63 74 20 57 61 6c 6b 46 72 65 65 6c 69 73  ruct WalkFreelis
4ad0: 74 43 74 78 20 57 61 6c 6b 46 72 65 65 6c 69 73  tCtx WalkFreelis
4ae0: 74 43 74 78 3b 0a 73 74 72 75 63 74 20 57 61 6c  tCtx;.struct Wal
4af0: 6b 46 72 65 65 6c 69 73 74 43 74 78 20 7b 0a 20  kFreelistCtx {. 
4b00: 20 6c 73 6d 5f 64 62 20 2a 70 44 62 3b 0a 20 20   lsm_db *pDb;.  
4b10: 69 6e 74 20 62 52 65 76 65 72 73 65 3b 0a 20 20  int bReverse;.  
4b20: 46 72 65 65 6c 69 73 74 20 2a 70 46 72 65 65 6c  Freelist *pFreel
4b30: 69 73 74 3b 0a 20 20 69 6e 74 20 69 46 72 65 65  ist;.  int iFree
4b40: 3b 0a 20 20 69 6e 74 20 28 2a 78 55 73 72 29 28  ;.  int (*xUsr)(
4b50: 76 6f 69 64 20 2a 2c 20 69 6e 74 2c 20 69 36 34  void *, int, i64
4b60: 29 3b 20 20 2f 2a 20 55 73 65 72 20 63 61 6c 6c  );  /* User call
4b70: 62 61 63 6b 20 66 75 6e 63 74 69 6f 6e 20 2a 2f  back function */
4b80: 0a 20 20 76 6f 69 64 20 2a 70 55 73 72 63 74 78  .  void *pUsrctx
4b90: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ;               
4ba0: 20 20 20 2f 2a 20 55 73 65 72 20 63 61 6c 6c 62     /* User callb
4bb0: 61 63 6b 20 63 6f 6e 74 65 78 74 20 2a 2f 0a 20  ack context */. 
4bc0: 20 69 6e 74 20 62 44 6f 6e 65 3b 20 20 20 20 20   int bDone;     
4bd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4be0: 20 2f 2a 20 53 65 74 20 74 6f 20 74 72 75 65 20   /* Set to true 
4bf0: 61 66 74 65 72 20 78 55 73 72 28 29 20 72 65 74  after xUsr() ret
4c00: 75 72 6e 73 20 74 72 75 65 20 2a 2f 0a 7d 3b 0a  urns true */.};.
4c10: 0a 2f 2a 20 0a 2a 2a 20 43 61 6c 6c 62 61 63 6b  ./* .** Callback
4c20: 20 75 73 65 64 20 62 79 20 6c 73 6d 57 61 6c 6b   used by lsmWalk
4c30: 46 72 65 65 6c 69 73 74 28 29 2e 0a 2a 2f 0a 73  Freelist()..*/.s
4c40: 74 61 74 69 63 20 69 6e 74 20 77 61 6c 6b 46 72  tatic int walkFr
4c50: 65 65 6c 69 73 74 43 62 28 76 6f 69 64 20 2a 70  eelistCb(void *p
4c60: 43 74 78 2c 20 69 6e 74 20 69 42 6c 6b 2c 20 69  Ctx, int iBlk, i
4c70: 36 34 20 69 53 6e 61 70 73 68 6f 74 29 7b 0a 20  64 iSnapshot){. 
4c80: 20 57 61 6c 6b 46 72 65 65 6c 69 73 74 43 74 78   WalkFreelistCtx
4c90: 20 2a 70 20 3d 20 28 57 61 6c 6b 46 72 65 65 6c   *p = (WalkFreel
4ca0: 69 73 74 43 74 78 20 2a 29 70 43 74 78 3b 0a 20  istCtx *)pCtx;. 
4cb0: 20 63 6f 6e 73 74 20 69 6e 74 20 69 44 69 72 20   const int iDir 
4cc0: 3d 20 28 70 2d 3e 62 52 65 76 65 72 73 65 20 3f  = (p->bReverse ?
4cd0: 20 2d 31 20 3a 20 31 29 3b 0a 20 20 46 72 65 65   -1 : 1);.  Free
4ce0: 6c 69 73 74 20 2a 70 46 72 65 65 20 3d 20 70 2d  list *pFree = p-
4cf0: 3e 70 46 72 65 65 6c 69 73 74 3b 0a 0a 20 20 61  >pFreelist;..  a
4d00: 73 73 65 72 74 28 20 70 2d 3e 62 44 6f 6e 65 3d  ssert( p->bDone=
4d10: 3d 30 20 29 3b 0a 20 20 61 73 73 65 72 74 28 20  =0 );.  assert( 
4d20: 69 42 6c 6b 3e 3d 30 20 29 3b 0a 20 20 69 66 28  iBlk>=0 );.  if(
4d30: 20 70 46 72 65 65 20 29 7b 0a 20 20 20 20 77 68   pFree ){.    wh
4d40: 69 6c 65 28 20 28 70 2d 3e 69 46 72 65 65 20 3c  ile( (p->iFree <
4d50: 20 70 46 72 65 65 2d 3e 6e 45 6e 74 72 79 29 20   pFree->nEntry) 
4d60: 26 26 20 70 2d 3e 69 46 72 65 65 3e 3d 30 20 29  && p->iFree>=0 )
4d70: 7b 0a 20 20 20 20 20 20 46 72 65 65 6c 69 73 74  {.      Freelist
4d80: 45 6e 74 72 79 20 2a 70 45 6e 74 72 79 20 3d 20  Entry *pEntry = 
4d90: 26 70 46 72 65 65 2d 3e 61 45 6e 74 72 79 5b 70  &pFree->aEntry[p
4da0: 2d 3e 69 46 72 65 65 5d 3b 0a 20 20 20 20 20 20  ->iFree];.      
4db0: 69 66 28 20 28 70 2d 3e 62 52 65 76 65 72 73 65  if( (p->bReverse
4dc0: 3d 3d 30 20 26 26 20 70 45 6e 74 72 79 2d 3e 69  ==0 && pEntry->i
4dd0: 42 6c 6b 3e 28 75 33 32 29 69 42 6c 6b 29 0a 20  Blk>(u32)iBlk). 
4de0: 20 20 20 20 20 20 7c 7c 20 28 70 2d 3e 62 52 65        || (p->bRe
4df0: 76 65 72 73 65 21 3d 30 20 26 26 20 70 45 6e 74  verse!=0 && pEnt
4e00: 72 79 2d 3e 69 42 6c 6b 3c 28 75 33 32 29 69 42  ry->iBlk<(u32)iB
4e10: 6c 6b 29 0a 20 20 20 20 20 20 29 7b 0a 20 20 20  lk).      ){.   
4e20: 20 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20       break;.    
4e30: 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 20    }else{.       
4e40: 20 70 2d 3e 69 46 72 65 65 20 2b 3d 20 69 44 69   p->iFree += iDi
4e50: 72 3b 0a 20 20 20 20 20 20 20 20 69 66 28 20 70  r;.        if( p
4e60: 45 6e 74 72 79 2d 3e 69 49 64 3e 3d 30 20 0a 20  Entry->iId>=0 . 
4e70: 20 20 20 20 20 20 20 20 20 20 20 26 26 20 70 2d             && p-
4e80: 3e 78 55 73 72 28 70 2d 3e 70 55 73 72 63 74 78  >xUsr(p->pUsrctx
4e90: 2c 20 70 45 6e 74 72 79 2d 3e 69 42 6c 6b 2c 20  , pEntry->iBlk, 
4ea0: 70 45 6e 74 72 79 2d 3e 69 49 64 29 20 0a 20 20  pEntry->iId) .  
4eb0: 20 20 20 20 20 20 20 20 29 7b 0a 20 20 20 20 20          ){.     
4ec0: 20 20 20 20 20 70 2d 3e 62 44 6f 6e 65 20 3d 20       p->bDone = 
4ed0: 31 3b 0a 20 20 20 20 20 20 20 20 20 20 72 65 74  1;.          ret
4ee0: 75 72 6e 20 31 3b 0a 20 20 20 20 20 20 20 20 7d  urn 1;.        }
4ef0: 0a 20 20 20 20 20 20 20 20 69 66 28 20 70 45 6e  .        if( pEn
4f00: 74 72 79 2d 3e 69 42 6c 6b 3d 3d 28 75 33 32 29  try->iBlk==(u32)
4f10: 69 42 6c 6b 20 29 20 72 65 74 75 72 6e 20 30 3b  iBlk ) return 0;
4f20: 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a 20  .      }.    }. 
4f30: 20 7d 0a 0a 20 20 69 66 28 20 70 2d 3e 78 55 73   }..  if( p->xUs
4f40: 72 28 70 2d 3e 70 55 73 72 63 74 78 2c 20 69 42  r(p->pUsrctx, iB
4f50: 6c 6b 2c 20 69 53 6e 61 70 73 68 6f 74 29 20 29  lk, iSnapshot) )
4f60: 7b 0a 20 20 20 20 70 2d 3e 62 44 6f 6e 65 20 3d  {.    p->bDone =
4f70: 20 31 3b 0a 20 20 20 20 72 65 74 75 72 6e 20 31   1;.    return 1
4f80: 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20 30  ;.  }.  return 0
4f90: 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54 68 65 20 64  ;.}../*.** The d
4fa0: 61 74 61 62 61 73 65 20 68 61 6e 64 6c 65 20 70  atabase handle p
4fb0: 61 73 73 65 64 20 61 73 20 74 68 65 20 66 69 72  assed as the fir
4fc0: 73 74 20 61 72 67 75 6d 65 6e 74 20 6d 75 73 74  st argument must
4fd0: 20 62 65 20 74 68 65 20 77 6f 72 6b 65 72 0a 2a   be the worker.*
4fe0: 2a 20 63 6f 6e 6e 65 63 74 69 6f 6e 2e 20 54 68  * connection. Th
4ff0: 69 73 20 66 75 6e 63 74 69 6f 6e 20 69 74 65 72  is function iter
5000: 61 74 65 73 20 74 68 72 6f 75 67 68 20 74 68 65  ates through the
5010: 20 63 6f 6e 74 65 6e 74 73 20 6f 66 20 74 68 65   contents of the
5020: 20 63 75 72 72 65 6e 74 0a 2a 2a 20 66 72 65 65   current.** free
5030: 20 62 6c 6f 63 6b 20 6c 69 73 74 2c 20 69 6e 76   block list, inv
5040: 6f 6b 69 6e 67 20 74 68 65 20 73 75 70 70 6c 69  oking the suppli
5050: 65 64 20 63 61 6c 6c 62 61 63 6b 20 6f 6e 63 65  ed callback once
5060: 20 66 6f 72 20 65 61 63 68 20 6c 69 73 74 0a 2a   for each list.*
5070: 2a 20 65 6c 65 6d 65 6e 74 2e 0a 2a 2a 0a 2a 2a  * element..**.**
5080: 20 54 68 65 20 64 69 66 66 65 72 65 6e 63 65 20   The difference 
5090: 62 65 74 77 65 65 6e 20 74 68 69 73 20 66 75 6e  between this fun
50a0: 63 74 69 6f 6e 20 61 6e 64 20 6c 73 6d 53 6f 72  ction and lsmSor
50b0: 74 65 64 57 61 6c 6b 46 72 65 65 6c 69 73 74 28  tedWalkFreelist(
50c0: 29 20 69 73 0a 2a 2a 20 74 68 61 74 20 6c 73 6d  ) is.** that lsm
50d0: 53 6f 72 74 65 64 57 61 6c 6b 46 72 65 65 6c 69  SortedWalkFreeli
50e0: 73 74 28 29 20 6f 6e 6c 79 20 63 6f 6e 73 69 64  st() only consid
50f0: 65 72 73 20 74 68 6f 73 65 20 66 72 65 65 2d 6c  ers those free-l
5100: 69 73 74 20 65 6c 65 6d 65 6e 74 73 0a 2a 2a 20  ist elements.** 
5110: 73 74 6f 72 65 64 20 77 69 74 68 69 6e 20 74 68  stored within th
5120: 65 20 4c 53 4d 2e 20 54 68 69 73 20 66 75 6e 63  e LSM. This func
5130: 74 69 6f 6e 20 61 6c 73 6f 20 6d 65 72 67 65 73  tion also merges
5140: 20 69 6e 20 61 6e 79 20 69 6e 2d 6d 65 6d 6f 72   in any in-memor
5150: 79 20 0a 2a 2a 20 65 6c 65 6d 65 6e 74 73 2e 0a  y .** elements..
5160: 2a 2f 0a 69 6e 74 20 6c 73 6d 57 61 6c 6b 46 72  */.int lsmWalkFr
5170: 65 65 6c 69 73 74 28 0a 20 20 6c 73 6d 5f 64 62  eelist(.  lsm_db
5180: 20 2a 70 44 62 2c 20 20 20 20 20 20 20 20 20 20   *pDb,          
5190: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 44 61 74            /* Dat
51a0: 61 62 61 73 65 20 68 61 6e 64 6c 65 20 28 6d 75  abase handle (mu
51b0: 73 74 20 62 65 20 77 6f 72 6b 65 72 29 20 2a 2f  st be worker) */
51c0: 0a 20 20 69 6e 74 20 62 52 65 76 65 72 73 65 2c  .  int bReverse,
51d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
51e0: 20 20 20 2f 2a 20 54 72 75 65 20 74 6f 20 69 74     /* True to it
51f0: 65 72 61 74 65 20 66 72 6f 6d 20 6c 61 72 67 65  erate from large
5200: 73 74 20 74 6f 20 73 6d 61 6c 6c 65 73 74 20 2a  st to smallest *
5210: 2f 0a 20 20 69 6e 74 20 28 2a 78 29 28 76 6f 69  /.  int (*x)(voi
5220: 64 20 2a 2c 20 69 6e 74 2c 20 69 36 34 29 2c 20  d *, int, i64), 
5230: 20 20 20 20 2f 2a 20 43 61 6c 6c 62 61 63 6b 20      /* Callback 
5240: 66 75 6e 63 74 69 6f 6e 20 2a 2f 0a 20 20 76 6f  function */.  vo
5250: 69 64 20 2a 70 43 74 78 20 20 20 20 20 20 20 20  id *pCtx        
5260: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
5270: 20 46 69 72 73 74 20 61 72 67 75 6d 65 6e 74 20   First argument 
5280: 74 6f 20 70 61 73 73 20 74 6f 20 63 61 6c 6c 62  to pass to callb
5290: 61 63 6b 20 2a 2f 0a 29 7b 0a 20 20 63 6f 6e 73  ack */.){.  cons
52a0: 74 20 69 6e 74 20 69 44 69 72 20 3d 20 28 62 52  t int iDir = (bR
52b0: 65 76 65 72 73 65 20 3f 20 2d 31 20 3a 20 31 29  everse ? -1 : 1)
52c0: 3b 0a 20 20 69 6e 74 20 72 63 3b 0a 20 20 69 6e  ;.  int rc;.  in
52d0: 74 20 69 43 74 78 3b 0a 0a 20 20 57 61 6c 6b 46  t iCtx;..  WalkF
52e0: 72 65 65 6c 69 73 74 43 74 78 20 63 74 78 5b 32  reelistCtx ctx[2
52f0: 5d 3b 0a 0a 20 20 63 74 78 5b 30 5d 2e 70 44 62  ];..  ctx[0].pDb
5300: 20 3d 20 70 44 62 3b 0a 20 20 63 74 78 5b 30 5d   = pDb;.  ctx[0]
5310: 2e 62 52 65 76 65 72 73 65 20 3d 20 62 52 65 76  .bReverse = bRev
5320: 65 72 73 65 3b 0a 20 20 63 74 78 5b 30 5d 2e 70  erse;.  ctx[0].p
5330: 46 72 65 65 6c 69 73 74 20 3d 20 26 70 44 62 2d  Freelist = &pDb-
5340: 3e 70 57 6f 72 6b 65 72 2d 3e 66 72 65 65 6c 69  >pWorker->freeli
5350: 73 74 3b 0a 20 20 69 66 28 20 63 74 78 5b 30 5d  st;.  if( ctx[0]
5360: 2e 70 46 72 65 65 6c 69 73 74 20 26 26 20 62 52  .pFreelist && bR
5370: 65 76 65 72 73 65 20 29 7b 0a 20 20 20 20 63 74  everse ){.    ct
5380: 78 5b 30 5d 2e 69 46 72 65 65 20 3d 20 63 74 78  x[0].iFree = ctx
5390: 5b 30 5d 2e 70 46 72 65 65 6c 69 73 74 2d 3e 6e  [0].pFreelist->n
53a0: 45 6e 74 72 79 2d 31 3b 0a 20 20 7d 65 6c 73 65  Entry-1;.  }else
53b0: 7b 0a 20 20 20 20 63 74 78 5b 30 5d 2e 69 46 72  {.    ctx[0].iFr
53c0: 65 65 20 3d 20 30 3b 0a 20 20 7d 0a 20 20 63 74  ee = 0;.  }.  ct
53d0: 78 5b 30 5d 2e 78 55 73 72 20 3d 20 77 61 6c 6b  x[0].xUsr = walk
53e0: 46 72 65 65 6c 69 73 74 43 62 3b 0a 20 20 63 74  FreelistCb;.  ct
53f0: 78 5b 30 5d 2e 70 55 73 72 63 74 78 20 3d 20 28  x[0].pUsrctx = (
5400: 76 6f 69 64 20 2a 29 26 63 74 78 5b 31 5d 3b 0a  void *)&ctx[1];.
5410: 20 20 63 74 78 5b 30 5d 2e 62 44 6f 6e 65 20 3d    ctx[0].bDone =
5420: 20 30 3b 0a 0a 20 20 63 74 78 5b 31 5d 2e 70 44   0;..  ctx[1].pD
5430: 62 20 3d 20 70 44 62 3b 0a 20 20 63 74 78 5b 31  b = pDb;.  ctx[1
5440: 5d 2e 62 52 65 76 65 72 73 65 20 3d 20 62 52 65  ].bReverse = bRe
5450: 76 65 72 73 65 3b 0a 20 20 63 74 78 5b 31 5d 2e  verse;.  ctx[1].
5460: 70 46 72 65 65 6c 69 73 74 20 3d 20 70 44 62 2d  pFreelist = pDb-
5470: 3e 70 46 72 65 65 6c 69 73 74 3b 0a 20 20 69 66  >pFreelist;.  if
5480: 28 20 63 74 78 5b 31 5d 2e 70 46 72 65 65 6c 69  ( ctx[1].pFreeli
5490: 73 74 20 26 26 20 62 52 65 76 65 72 73 65 20 29  st && bReverse )
54a0: 7b 0a 20 20 20 20 63 74 78 5b 31 5d 2e 69 46 72  {.    ctx[1].iFr
54b0: 65 65 20 3d 20 63 74 78 5b 31 5d 2e 70 46 72 65  ee = ctx[1].pFre
54c0: 65 6c 69 73 74 2d 3e 6e 45 6e 74 72 79 2d 31 3b  elist->nEntry-1;
54d0: 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 63 74  .  }else{.    ct
54e0: 78 5b 31 5d 2e 69 46 72 65 65 20 3d 20 30 3b 0a  x[1].iFree = 0;.
54f0: 20 20 7d 0a 20 20 63 74 78 5b 31 5d 2e 78 55 73    }.  ctx[1].xUs
5500: 72 20 3d 20 78 3b 0a 20 20 63 74 78 5b 31 5d 2e  r = x;.  ctx[1].
5510: 70 55 73 72 63 74 78 20 3d 20 70 43 74 78 3b 0a  pUsrctx = pCtx;.
5520: 20 20 63 74 78 5b 31 5d 2e 62 44 6f 6e 65 20 3d    ctx[1].bDone =
5530: 20 30 3b 0a 0a 20 20 72 63 20 3d 20 6c 73 6d 53   0;..  rc = lsmS
5540: 6f 72 74 65 64 57 61 6c 6b 46 72 65 65 6c 69 73  ortedWalkFreelis
5550: 74 28 70 44 62 2c 20 62 52 65 76 65 72 73 65 2c  t(pDb, bReverse,
5560: 20 77 61 6c 6b 46 72 65 65 6c 69 73 74 43 62 2c   walkFreelistCb,
5570: 20 28 76 6f 69 64 20 2a 29 26 63 74 78 5b 30 5d   (void *)&ctx[0]
5580: 29 3b 0a 0a 20 20 69 66 28 20 63 74 78 5b 30 5d  );..  if( ctx[0]
5590: 2e 62 44 6f 6e 65 3d 3d 30 20 29 7b 0a 20 20 20  .bDone==0 ){.   
55a0: 20 66 6f 72 28 69 43 74 78 3d 30 3b 20 69 43 74   for(iCtx=0; iCt
55b0: 78 3c 32 3b 20 69 43 74 78 2b 2b 29 7b 0a 20 20  x<2; iCtx++){.  
55c0: 20 20 20 20 69 6e 74 20 69 3b 0a 20 20 20 20 20      int i;.     
55d0: 20 57 61 6c 6b 46 72 65 65 6c 69 73 74 43 74 78   WalkFreelistCtx
55e0: 20 2a 70 20 3d 20 26 63 74 78 5b 69 43 74 78 5d   *p = &ctx[iCtx]
55f0: 3b 0a 20 20 20 20 20 20 66 6f 72 28 69 3d 70 2d  ;.      for(i=p-
5600: 3e 69 46 72 65 65 3b 20 0a 20 20 20 20 20 20 20  >iFree; .       
5610: 20 20 20 70 2d 3e 70 46 72 65 65 6c 69 73 74 20     p->pFreelist 
5620: 26 26 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 26 26  && rc==LSM_OK &&
5630: 20 69 3c 70 2d 3e 70 46 72 65 65 6c 69 73 74 2d   i<p->pFreelist-
5640: 3e 6e 45 6e 74 72 79 20 26 26 20 69 3e 3d 30 3b  >nEntry && i>=0;
5650: 0a 20 20 20 20 20 20 20 20 20 20 69 20 2b 3d 20  .          i += 
5660: 69 44 69 72 0a 20 20 20 20 20 20 20 20 20 29 7b  iDir.         ){
5670: 0a 20 20 20 20 20 20 20 20 46 72 65 65 6c 69 73  .        Freelis
5680: 74 45 6e 74 72 79 20 2a 70 45 6e 74 72 79 20 3d  tEntry *pEntry =
5690: 20 26 70 2d 3e 70 46 72 65 65 6c 69 73 74 2d 3e   &p->pFreelist->
56a0: 61 45 6e 74 72 79 5b 69 5d 3b 0a 20 20 20 20 20  aEntry[i];.     
56b0: 20 20 20 69 66 28 20 70 45 6e 74 72 79 2d 3e 69     if( pEntry->i
56c0: 49 64 3e 3d 30 20 26 26 20 70 2d 3e 78 55 73 72  Id>=0 && p->xUsr
56d0: 28 70 2d 3e 70 55 73 72 63 74 78 2c 20 70 45 6e  (p->pUsrctx, pEn
56e0: 74 72 79 2d 3e 69 42 6c 6b 2c 20 70 45 6e 74 72  try->iBlk, pEntr
56f0: 79 2d 3e 69 49 64 29 20 29 7b 0a 20 20 20 20 20  y->iId) ){.     
5700: 20 20 20 20 20 72 65 74 75 72 6e 20 4c 53 4d 5f       return LSM_
5710: 4f 4b 3b 0a 20 20 20 20 20 20 20 20 7d 0a 20 20  OK;.        }.  
5720: 20 20 20 20 7d 0a 20 20 20 20 7d 0a 20 20 7d 0a      }.    }.  }.
5730: 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a  .  return rc;.}.
5740: 0a 0a 74 79 70 65 64 65 66 20 73 74 72 75 63 74  ..typedef struct
5750: 20 46 69 6e 64 46 72 65 65 62 6c 6f 63 6b 43 74   FindFreeblockCt
5760: 78 20 46 69 6e 64 46 72 65 65 62 6c 6f 63 6b 43  x FindFreeblockC
5770: 74 78 3b 0a 73 74 72 75 63 74 20 46 69 6e 64 46  tx;.struct FindF
5780: 72 65 65 62 6c 6f 63 6b 43 74 78 20 7b 0a 20 20  reeblockCtx {.  
5790: 69 36 34 20 69 49 6e 55 73 65 3b 0a 20 20 69 6e  i64 iInUse;.  in
57a0: 74 20 69 52 65 74 3b 0a 20 20 69 6e 74 20 62 4e  t iRet;.  int bN
57b0: 6f 74 4f 6e 65 3b 0a 7d 3b 0a 0a 73 74 61 74 69  otOne;.};..stati
57c0: 63 20 69 6e 74 20 66 69 6e 64 46 72 65 65 62 6c  c int findFreebl
57d0: 6f 63 6b 43 62 28 76 6f 69 64 20 2a 70 43 74 78  ockCb(void *pCtx
57e0: 2c 20 69 6e 74 20 69 42 6c 6b 2c 20 69 36 34 20  , int iBlk, i64 
57f0: 69 53 6e 61 70 73 68 6f 74 29 7b 0a 20 20 46 69  iSnapshot){.  Fi
5800: 6e 64 46 72 65 65 62 6c 6f 63 6b 43 74 78 20 2a  ndFreeblockCtx *
5810: 70 20 3d 20 28 46 69 6e 64 46 72 65 65 62 6c 6f  p = (FindFreeblo
5820: 63 6b 43 74 78 20 2a 29 70 43 74 78 3b 0a 20 20  ckCtx *)pCtx;.  
5830: 69 66 28 20 69 53 6e 61 70 73 68 6f 74 3c 70 2d  if( iSnapshot<p-
5840: 3e 69 49 6e 55 73 65 20 26 26 20 28 69 42 6c 6b  >iInUse && (iBlk
5850: 21 3d 31 20 7c 7c 20 70 2d 3e 62 4e 6f 74 4f 6e  !=1 || p->bNotOn
5860: 65 3d 3d 30 29 20 29 7b 0a 20 20 20 20 70 2d 3e  e==0) ){.    p->
5870: 69 52 65 74 20 3d 20 69 42 6c 6b 3b 0a 20 20 20  iRet = iBlk;.   
5880: 20 72 65 74 75 72 6e 20 31 3b 0a 20 20 7d 0a 20   return 1;.  }. 
5890: 20 72 65 74 75 72 6e 20 30 3b 0a 7d 0a 0a 73 74   return 0;.}..st
58a0: 61 74 69 63 20 69 6e 74 20 66 69 6e 64 46 72 65  atic int findFre
58b0: 65 62 6c 6f 63 6b 28 6c 73 6d 5f 64 62 20 2a 70  eblock(lsm_db *p
58c0: 44 62 2c 20 69 36 34 20 69 49 6e 55 73 65 2c 20  Db, i64 iInUse, 
58d0: 69 6e 74 20 62 4e 6f 74 4f 6e 65 2c 20 69 6e 74  int bNotOne, int
58e0: 20 2a 70 69 52 65 74 29 7b 0a 20 20 69 6e 74 20   *piRet){.  int 
58f0: 72 63 3b 20 20 20 20 20 20 20 20 20 20 20 20 20  rc;             
5900: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 52              /* R
5910: 65 74 75 72 6e 20 63 6f 64 65 20 2a 2f 0a 20 20  eturn code */.  
5920: 46 69 6e 64 46 72 65 65 62 6c 6f 63 6b 43 74 78  FindFreeblockCtx
5930: 20 63 74 78 3b 20 20 20 20 20 20 20 20 20 20 20   ctx;           
5940: 2f 2a 20 43 6f 6e 74 65 78 74 20 6f 62 6a 65 63  /* Context objec
5950: 74 20 2a 2f 0a 0a 20 20 63 74 78 2e 69 49 6e 55  t */..  ctx.iInU
5960: 73 65 20 3d 20 69 49 6e 55 73 65 3b 0a 20 20 63  se = iInUse;.  c
5970: 74 78 2e 69 52 65 74 20 3d 20 30 3b 0a 20 20 63  tx.iRet = 0;.  c
5980: 74 78 2e 62 4e 6f 74 4f 6e 65 20 3d 20 62 4e 6f  tx.bNotOne = bNo
5990: 74 4f 6e 65 3b 0a 20 20 72 63 20 3d 20 6c 73 6d  tOne;.  rc = lsm
59a0: 57 61 6c 6b 46 72 65 65 6c 69 73 74 28 70 44 62  WalkFreelist(pDb
59b0: 2c 20 30 2c 20 66 69 6e 64 46 72 65 65 62 6c 6f  , 0, findFreeblo
59c0: 63 6b 43 62 2c 20 28 76 6f 69 64 20 2a 29 26 63  ckCb, (void *)&c
59d0: 74 78 29 3b 0a 20 20 2a 70 69 52 65 74 20 3d 20  tx);.  *piRet = 
59e0: 63 74 78 2e 69 52 65 74 3b 0a 0a 20 20 72 65 74  ctx.iRet;..  ret
59f0: 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a  urn rc;.}../*.**
5a00: 20 41 6c 6c 6f 63 61 74 65 20 61 20 6e 65 77 20   Allocate a new 
5a10: 64 61 74 61 62 61 73 65 20 66 69 6c 65 20 62 6c  database file bl
5a20: 6f 63 6b 20 74 6f 20 77 72 69 74 65 20 64 61 74  ock to write dat
5a30: 61 20 74 6f 2c 20 65 69 74 68 65 72 20 62 79 20  a to, either by 
5a40: 65 78 74 65 6e 64 69 6e 67 0a 2a 2a 20 74 68 65  extending.** the
5a50: 20 64 61 74 61 62 61 73 65 20 66 69 6c 65 20 6f   database file o
5a60: 72 20 62 79 20 72 65 63 79 63 6c 69 6e 67 20 61  r by recycling a
5a70: 20 66 72 65 65 2d 6c 69 73 74 20 65 6e 74 72 79   free-list entry
5a80: 2e 20 54 68 65 20 77 6f 72 6b 65 72 20 73 6e 61  . The worker sna
5a90: 70 73 68 6f 74 20 0a 2a 2a 20 6d 75 73 74 20 62  pshot .** must b
5aa0: 65 20 68 65 6c 64 20 69 6e 20 6f 72 64 65 72 20  e held in order 
5ab0: 74 6f 20 63 61 6c 6c 20 74 68 69 73 20 66 75 6e  to call this fun
5ac0: 63 74 69 6f 6e 2e 0a 2a 2a 0a 2a 2a 20 49 66 20  ction..**.** If 
5ad0: 73 75 63 63 65 73 73 66 75 6c 2c 20 2a 70 69 42  successful, *piB
5ae0: 6c 6b 20 69 73 20 73 65 74 20 74 6f 20 74 68 65  lk is set to the
5af0: 20 62 6c 6f 63 6b 20 6e 75 6d 62 65 72 20 61 6c   block number al
5b00: 6c 6f 63 61 74 65 64 20 61 6e 64 20 4c 53 4d 5f  located and LSM_
5b10: 4f 4b 20 69 73 0a 2a 2a 20 72 65 74 75 72 6e 65  OK is.** returne
5b20: 64 2e 20 4f 74 68 65 72 77 69 73 65 2c 20 2a 70  d. Otherwise, *p
5b30: 69 42 6c 6b 20 69 73 20 7a 65 72 6f 65 64 20 61  iBlk is zeroed a
5b40: 6e 64 20 61 6e 20 6c 73 6d 20 65 72 72 6f 72 20  nd an lsm error 
5b50: 63 6f 64 65 20 72 65 74 75 72 6e 65 64 2e 0a 2a  code returned..*
5b60: 2f 0a 69 6e 74 20 6c 73 6d 42 6c 6f 63 6b 41 6c  /.int lsmBlockAl
5b70: 6c 6f 63 61 74 65 28 6c 73 6d 5f 64 62 20 2a 70  locate(lsm_db *p
5b80: 44 62 2c 20 69 6e 74 20 69 42 65 66 6f 72 65 2c  Db, int iBefore,
5b90: 20 69 6e 74 20 2a 70 69 42 6c 6b 29 7b 0a 20 20   int *piBlk){.  
5ba0: 53 6e 61 70 73 68 6f 74 20 2a 70 20 3d 20 70 44  Snapshot *p = pD
5bb0: 62 2d 3e 70 57 6f 72 6b 65 72 3b 0a 20 20 69 6e  b->pWorker;.  in
5bc0: 74 20 69 52 65 74 20 3d 20 30 3b 20 20 20 20 20  t iRet = 0;     
5bd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
5be0: 20 42 6c 6f 63 6b 20 6e 75 6d 62 65 72 20 6f 66   Block number of
5bf0: 20 61 6c 6c 6f 63 61 74 65 64 20 62 6c 6f 63 6b   allocated block
5c00: 20 2a 2f 0a 20 20 69 6e 74 20 72 63 20 3d 20 4c   */.  int rc = L
5c10: 53 4d 5f 4f 4b 3b 0a 20 20 69 36 34 20 69 49 6e  SM_OK;.  i64 iIn
5c20: 55 73 65 20 3d 20 30 3b 20 20 20 20 20 20 20 20  Use = 0;        
5c30: 20 20 20 20 20 20 20 20 20 2f 2a 20 53 6e 61 70           /* Snap
5c40: 73 68 6f 74 20 69 64 20 73 74 69 6c 6c 20 69 6e  shot id still in
5c50: 20 75 73 65 20 2a 2f 0a 20 20 69 36 34 20 69 53   use */.  i64 iS
5c60: 79 6e 63 65 64 20 3d 20 30 3b 20 20 20 20 20 20  ynced = 0;      
5c70: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 53 6e 61            /* Sna
5c80: 70 73 68 6f 74 20 69 64 20 73 79 6e 63 65 64 20  pshot id synced 
5c90: 74 6f 20 64 69 73 6b 20 2a 2f 0a 0a 20 20 61 73  to disk */..  as
5ca0: 73 65 72 74 28 20 70 20 29 3b 0a 0a 23 69 66 64  sert( p );..#ifd
5cb0: 65 66 20 4c 53 4d 5f 4c 4f 47 5f 46 52 45 45 4c  ef LSM_LOG_FREEL
5cc0: 49 53 54 0a 20 20 7b 0a 20 20 20 20 73 74 61 74  IST.  {.    stat
5cd0: 69 63 20 69 6e 74 20 6e 43 61 6c 6c 20 3d 20 30  ic int nCall = 0
5ce0: 3b 0a 20 20 20 20 63 68 61 72 20 2a 7a 46 72 65  ;.    char *zFre
5cf0: 65 20 3d 20 30 3b 0a 20 20 20 20 6e 43 61 6c 6c  e = 0;.    nCall
5d00: 2b 2b 3b 0a 20 20 20 20 72 63 20 3d 20 6c 73 6d  ++;.    rc = lsm
5d10: 49 6e 66 6f 46 72 65 65 6c 69 73 74 28 70 44 62  InfoFreelist(pDb
5d20: 2c 20 26 7a 46 72 65 65 29 3b 0a 20 20 20 20 69  , &zFree);.    i
5d30: 66 28 20 72 63 21 3d 4c 53 4d 5f 4f 4b 20 29 20  f( rc!=LSM_OK ) 
5d40: 72 65 74 75 72 6e 20 72 63 3b 0a 20 20 20 20 6c  return rc;.    l
5d50: 73 6d 4c 6f 67 4d 65 73 73 61 67 65 28 70 44 62  smLogMessage(pDb
5d60: 2c 20 30 2c 20 22 6c 73 6d 42 6c 6f 63 6b 41 6c  , 0, "lsmBlockAl
5d70: 6c 6f 63 61 74 65 28 29 3a 20 25 64 20 66 72 65  locate(): %d fre
5d80: 65 6c 69 73 74 3a 20 25 73 22 2c 20 6e 43 61 6c  elist: %s", nCal
5d90: 6c 2c 20 7a 46 72 65 65 29 3b 0a 20 20 20 20 6c  l, zFree);.    l
5da0: 73 6d 46 72 65 65 28 70 44 62 2d 3e 70 45 6e 76  smFree(pDb->pEnv
5db0: 2c 20 7a 46 72 65 65 29 3b 0a 20 20 7d 0a 23 65  , zFree);.  }.#e
5dc0: 6e 64 69 66 0a 0a 20 20 2f 2a 20 53 65 74 20 69  ndif..  /* Set i
5dd0: 49 6e 55 73 65 20 74 6f 20 74 68 65 20 73 6d 61  InUse to the sma
5de0: 6c 6c 65 73 74 20 73 6e 61 70 73 68 6f 74 20 69  llest snapshot i
5df0: 64 20 74 68 61 74 20 69 73 20 65 69 74 68 65 72  d that is either
5e00: 3a 0a 20 20 2a 2a 0a 20 20 2a 2a 20 20 20 2a 20  :.  **.  **   * 
5e10: 43 75 72 72 65 6e 74 6c 79 20 69 6e 20 75 73 65  Currently in use
5e20: 20 62 79 20 61 20 64 61 74 61 62 61 73 65 20 63   by a database c
5e30: 6c 69 65 6e 74 2c 0a 20 20 2a 2a 20 20 20 2a 20  lient,.  **   * 
5e40: 4d 61 79 20 62 65 20 75 73 65 64 20 62 79 20 61  May be used by a
5e50: 20 64 61 74 61 62 61 73 65 20 63 6c 69 65 6e 74   database client
5e60: 20 69 6e 20 74 68 65 20 66 75 74 75 72 65 2c 20   in the future, 
5e70: 6f 72 0a 20 20 2a 2a 20 20 20 2a 20 49 73 20 74  or.  **   * Is t
5e80: 68 65 20 6d 6f 73 74 20 72 65 63 65 6e 74 6c 79  he most recently
5e90: 20 63 68 65 63 6b 70 6f 69 6e 74 65 64 20 73 6e   checkpointed sn
5ea0: 61 70 73 68 6f 74 20 28 69 2e 65 2e 20 74 68 65  apshot (i.e. the
5eb0: 20 6f 6e 65 20 74 68 61 74 20 77 69 6c 6c 0a 20   one that will. 
5ec0: 20 2a 2a 20 20 20 20 20 62 65 20 75 73 65 64 20   **     be used 
5ed0: 66 6f 6c 6c 6f 77 69 6e 67 20 72 65 63 6f 76 65  following recove
5ee0: 72 79 20 69 66 20 61 20 66 61 69 6c 75 72 65 20  ry if a failure 
5ef0: 6f 63 63 75 72 73 20 61 74 20 74 68 69 73 20 70  occurs at this p
5f00: 6f 69 6e 74 29 2e 0a 20 20 2a 2f 0a 20 20 72 63  oint)..  */.  rc
5f10: 20 3d 20 6c 73 6d 43 68 65 63 6b 70 6f 69 6e 74   = lsmCheckpoint
5f20: 53 79 6e 63 65 64 28 70 44 62 2c 20 26 69 53 79  Synced(pDb, &iSy
5f30: 6e 63 65 64 2c 20 30 2c 20 30 29 3b 0a 20 20 69  nced, 0, 0);.  i
5f40: 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 26 26  f( rc==LSM_OK &&
5f50: 20 69 53 79 6e 63 65 64 3d 3d 30 20 29 20 69 53   iSynced==0 ) iS
5f60: 79 6e 63 65 64 20 3d 20 70 2d 3e 69 49 64 3b 0a  ynced = p->iId;.
5f70: 20 20 69 49 6e 55 73 65 20 3d 20 69 53 79 6e 63    iInUse = iSync
5f80: 65 64 3b 0a 20 20 69 66 28 20 72 63 3d 3d 4c 53  ed;.  if( rc==LS
5f90: 4d 5f 4f 4b 20 26 26 20 70 44 62 2d 3e 69 52 65  M_OK && pDb->iRe
5fa0: 61 64 65 72 3e 3d 30 20 29 7b 0a 20 20 20 20 61  ader>=0 ){.    a
5fb0: 73 73 65 72 74 28 20 70 44 62 2d 3e 70 43 6c 69  ssert( pDb->pCli
5fc0: 65 6e 74 20 29 3b 0a 20 20 20 20 69 49 6e 55 73  ent );.    iInUs
5fd0: 65 20 3d 20 4c 53 4d 5f 4d 49 4e 28 69 49 6e 55  e = LSM_MIN(iInU
5fe0: 73 65 2c 20 70 44 62 2d 3e 70 43 6c 69 65 6e 74  se, pDb->pClient
5ff0: 2d 3e 69 49 64 29 3b 0a 20 20 7d 0a 20 20 69 66  ->iId);.  }.  if
6000: 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 29 20 72  ( rc==LSM_OK ) r
6010: 63 20 3d 20 66 69 72 73 74 53 6e 61 70 73 68 6f  c = firstSnapsho
6020: 74 49 6e 55 73 65 28 70 44 62 2c 20 26 69 49 6e  tInUse(pDb, &iIn
6030: 55 73 65 29 3b 0a 0a 23 69 66 64 65 66 20 4c 53  Use);..#ifdef LS
6040: 4d 5f 4c 4f 47 5f 46 52 45 45 4c 49 53 54 0a 20  M_LOG_FREELIST. 
6050: 20 7b 0a 20 20 20 20 6c 73 6d 4c 6f 67 4d 65 73   {.    lsmLogMes
6060: 73 61 67 65 28 70 44 62 2c 20 30 2c 20 22 6c 73  sage(pDb, 0, "ls
6070: 6d 42 6c 6f 63 6b 41 6c 6c 6f 63 61 74 65 28 29  mBlockAllocate()
6080: 3a 20 22 0a 20 20 20 20 20 20 20 20 22 73 6e 61  : ".        "sna
6090: 70 73 68 6f 74 2d 69 6e 2d 75 73 65 3a 20 25 6c  pshot-in-use: %l
60a0: 6c 64 20 28 69 53 79 6e 63 65 64 3d 25 6c 6c 64  ld (iSynced=%lld
60b0: 29 20 28 63 6c 69 65 6e 74 2d 69 64 3d 25 6c 6c  ) (client-id=%ll
60c0: 64 29 22 2c 20 0a 20 20 20 20 20 20 20 20 69 49  d)", .        iI
60d0: 6e 55 73 65 2c 20 69 53 79 6e 63 65 64 2c 20 28  nUse, iSynced, (
60e0: 70 44 62 2d 3e 69 52 65 61 64 65 72 3e 3d 30 20  pDb->iReader>=0 
60f0: 3f 20 70 44 62 2d 3e 70 43 6c 69 65 6e 74 2d 3e  ? pDb->pClient->
6100: 69 49 64 20 3a 20 30 29 0a 20 20 20 20 29 3b 0a  iId : 0).    );.
6110: 20 20 7d 0a 23 65 6e 64 69 66 0a 0a 0a 20 20 2f    }.#endif...  /
6120: 2a 20 55 6e 6c 65 73 73 20 74 68 65 72 65 20 65  * Unless there e
6130: 78 69 73 74 73 20 61 20 72 65 61 64 2d 6f 6e 6c  xists a read-onl
6140: 79 20 74 72 61 6e 73 61 63 74 69 6f 6e 20 28 77  y transaction (w
6150: 68 69 63 68 20 70 72 65 76 65 6e 74 73 20 75 73  hich prevents us
6160: 20 66 72 6f 6d 0a 20 20 2a 2a 20 72 65 63 79 63   from.  ** recyc
6170: 6c 69 6e 67 20 61 6e 79 20 62 6c 6f 63 6b 73 20  ling any blocks 
6180: 72 65 67 61 72 64 6c 65 73 73 2c 20 71 75 65 72  regardless, quer
6190: 79 20 74 68 65 20 66 72 65 65 20 62 6c 6f 63 6b  y the free block
61a0: 20 6c 69 73 74 20 66 6f 72 20 61 20 0a 20 20 2a   list for a .  *
61b0: 2a 20 73 75 69 74 61 62 6c 65 20 62 6c 6f 63 6b  * suitable block
61c0: 20 74 6f 20 72 65 75 73 65 2e 20 0a 20 20 2a 2a   to reuse. .  **
61d0: 0a 20 20 2a 2a 20 49 74 20 6d 69 67 68 74 20 73  .  ** It might s
61e0: 65 65 6d 20 6d 6f 72 65 20 6e 61 74 75 72 61 6c  eem more natural
61f0: 20 74 6f 20 63 68 65 63 6b 20 66 6f 72 20 61 20   to check for a 
6200: 72 65 61 64 2d 6f 6e 6c 79 20 74 72 61 6e 73 61  read-only transa
6210: 63 74 69 6f 6e 20 61 74 0a 20 20 2a 2a 20 74 68  ction at.  ** th
6220: 65 20 73 74 61 72 74 20 6f 66 20 74 68 69 73 20  e start of this 
6230: 66 75 6e 63 74 69 6f 6e 2e 20 48 6f 77 65 76 65  function. Howeve
6240: 72 2c 20 69 74 20 69 73 20 62 65 74 74 65 72 20  r, it is better 
6250: 64 6f 20 77 61 69 74 20 75 6e 74 69 6c 20 61 66  do wait until af
6260: 74 65 72 0a 20 20 2a 2a 20 74 68 65 20 63 61 6c  ter.  ** the cal
6270: 6c 20 74 6f 20 6c 73 6d 43 68 65 63 6b 70 6f 69  l to lsmCheckpoi
6280: 6e 74 53 79 6e 63 65 64 28 29 20 74 6f 20 64 6f  ntSynced() to do
6290: 20 73 6f 2e 0a 20 20 2a 2f 0a 20 20 69 66 28 20   so..  */.  if( 
62a0: 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 29 7b 0a 20 20  rc==LSM_OK ){.  
62b0: 20 20 69 6e 74 20 62 52 6f 74 72 61 6e 73 3b 0a    int bRotrans;.
62c0: 20 20 20 20 72 63 20 3d 20 6c 73 6d 44 65 74 65      rc = lsmDete
62d0: 63 74 52 6f 54 72 61 6e 73 28 70 44 62 2c 20 26  ctRoTrans(pDb, &
62e0: 62 52 6f 74 72 61 6e 73 29 3b 0a 0a 20 20 20 20  bRotrans);..    
62f0: 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 26  if( rc==LSM_OK &
6300: 26 20 62 52 6f 74 72 61 6e 73 3d 3d 30 20 29 7b  & bRotrans==0 ){
6310: 0a 20 20 20 20 20 20 72 63 20 3d 20 66 69 6e 64  .      rc = find
6320: 46 72 65 65 62 6c 6f 63 6b 28 70 44 62 2c 20 69  Freeblock(pDb, i
6330: 49 6e 55 73 65 2c 20 28 69 42 65 66 6f 72 65 3e  InUse, (iBefore>
6340: 30 29 2c 20 26 69 52 65 74 29 3b 0a 20 20 20 20  0), &iRet);.    
6350: 7d 0a 20 20 7d 0a 0a 20 20 69 66 28 20 69 42 65  }.  }..  if( iBe
6360: 66 6f 72 65 3e 30 20 26 26 20 28 69 52 65 74 3c  fore>0 && (iRet<
6370: 3d 30 20 7c 7c 20 69 52 65 74 3e 3d 69 42 65 66  =0 || iRet>=iBef
6380: 6f 72 65 29 20 29 7b 0a 20 20 20 20 69 52 65 74  ore) ){.    iRet
6390: 20 3d 20 30 3b 0a 0a 20 20 7d 65 6c 73 65 20 69   = 0;..  }else i
63a0: 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 29 7b  f( rc==LSM_OK ){
63b0: 0a 20 20 20 20 2f 2a 20 49 66 20 61 20 62 6c 6f  .    /* If a blo
63c0: 63 6b 20 77 61 73 20 66 6f 75 6e 64 20 69 6e 20  ck was found in 
63d0: 74 68 65 20 66 72 65 65 20 62 6c 6f 63 6b 20 6c  the free block l
63e0: 69 73 74 2c 20 75 73 65 20 69 74 20 61 6e 64 20  ist, use it and 
63f0: 72 65 6d 6f 76 65 20 69 74 20 66 72 6f 6d 20 0a  remove it from .
6400: 20 20 20 20 2a 2a 20 74 68 65 20 6c 69 73 74 2e      ** the list.
6410: 20 4f 74 68 65 72 77 69 73 65 2c 20 69 66 20 6e   Otherwise, if n
6420: 6f 20 73 75 69 74 61 62 6c 65 20 62 6c 6f 63 6b  o suitable block
6430: 20 77 61 73 20 66 6f 75 6e 64 2c 20 61 6c 6c 6f   was found, allo
6440: 63 61 74 65 20 6f 6e 65 20 66 72 6f 6d 0a 20 20  cate one from.  
6450: 20 20 2a 2a 20 74 68 65 20 65 6e 64 20 6f 66 20    ** the end of 
6460: 74 68 65 20 66 69 6c 65 2e 20 20 2a 2f 0a 20 20  the file.  */.  
6470: 20 20 69 66 28 20 69 52 65 74 3e 30 20 29 7b 0a    if( iRet>0 ){.
6480: 23 69 66 64 65 66 20 4c 53 4d 5f 4c 4f 47 5f 46  #ifdef LSM_LOG_F
6490: 52 45 45 4c 49 53 54 0a 20 20 20 20 20 20 6c 73  REELIST.      ls
64a0: 6d 4c 6f 67 4d 65 73 73 61 67 65 28 70 44 62 2c  mLogMessage(pDb,
64b0: 20 30 2c 20 0a 20 20 20 20 20 20 20 20 20 20 22   0, .          "
64c0: 72 65 75 73 69 6e 67 20 62 6c 6f 63 6b 20 25 64  reusing block %d
64d0: 20 28 73 6e 61 70 73 68 6f 74 2d 69 6e 2d 75 73   (snapshot-in-us
64e0: 65 3d 25 6c 6c 64 29 22 2c 20 69 52 65 74 2c 20  e=%lld)", iRet, 
64f0: 69 49 6e 55 73 65 29 3b 0a 23 65 6e 64 69 66 0a  iInUse);.#endif.
6500: 20 20 20 20 20 20 72 63 20 3d 20 66 72 65 65 6c        rc = freel
6510: 69 73 74 41 70 70 65 6e 64 28 70 44 62 2c 20 69  istAppend(pDb, i
6520: 52 65 74 2c 20 2d 31 29 3b 0a 20 20 20 20 20 20  Ret, -1);.      
6530: 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 29  if( rc==LSM_OK )
6540: 7b 0a 20 20 20 20 20 20 20 20 72 63 20 3d 20 64  {.        rc = d
6550: 62 54 72 75 6e 63 61 74 65 28 70 44 62 2c 20 69  bTruncate(pDb, i
6560: 49 6e 55 73 65 29 3b 0a 20 20 20 20 20 20 7d 0a  InUse);.      }.
6570: 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20      }else{.     
6580: 20 69 52 65 74 20 3d 20 2b 2b 28 70 2d 3e 6e 42   iRet = ++(p->nB
6590: 6c 6f 63 6b 29 3b 0a 23 69 66 64 65 66 20 4c 53  lock);.#ifdef LS
65a0: 4d 5f 4c 4f 47 5f 46 52 45 45 4c 49 53 54 0a 20  M_LOG_FREELIST. 
65b0: 20 20 20 20 20 6c 73 6d 4c 6f 67 4d 65 73 73 61       lsmLogMessa
65c0: 67 65 28 70 44 62 2c 20 30 2c 20 22 65 78 74 65  ge(pDb, 0, "exte
65d0: 6e 64 69 6e 67 20 66 69 6c 65 20 74 6f 20 25 64  nding file to %d
65e0: 20 62 6c 6f 63 6b 73 22 2c 20 69 52 65 74 29 3b   blocks", iRet);
65f0: 0a 23 65 6e 64 69 66 0a 20 20 20 20 7d 0a 20 20  .#endif.    }.  
6600: 7d 0a 0a 20 20 61 73 73 65 72 74 28 20 69 42 65  }..  assert( iBe
6610: 66 6f 72 65 3e 30 20 7c 7c 20 69 52 65 74 3e 30  fore>0 || iRet>0
6620: 20 7c 7c 20 72 63 21 3d 4c 53 4d 5f 4f 4b 20 29   || rc!=LSM_OK )
6630: 3b 0a 20 20 2a 70 69 42 6c 6b 20 3d 20 69 52 65  ;.  *piBlk = iRe
6640: 74 3b 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a  t;.  return rc;.
6650: 7d 0a 0a 2f 2a 0a 2a 2a 20 46 72 65 65 20 61 20  }../*.** Free a 
6660: 64 61 74 61 62 61 73 65 20 62 6c 6f 63 6b 2e 20  database block. 
6670: 54 68 65 20 77 6f 72 6b 65 72 20 73 6e 61 70 73  The worker snaps
6680: 68 6f 74 20 6d 75 73 74 20 62 65 20 68 65 6c 64  hot must be held
6690: 20 69 6e 20 6f 72 64 65 72 20 74 6f 20 63 61 6c   in order to cal
66a0: 6c 20 0a 2a 2a 20 74 68 69 73 20 66 75 6e 63 74  l .** this funct
66b0: 69 6f 6e 2e 0a 2a 2a 0a 2a 2a 20 49 66 20 73 75  ion..**.** If su
66c0: 63 63 65 73 73 66 75 6c 2c 20 4c 53 4d 5f 4f 4b  ccessful, LSM_OK
66d0: 20 69 73 20 72 65 74 75 72 6e 65 64 2e 20 4f 74   is returned. Ot
66e0: 68 65 72 77 69 73 65 2c 20 61 6e 20 6c 73 6d 20  herwise, an lsm 
66f0: 65 72 72 6f 72 20 63 6f 64 65 20 28 65 2e 67 2e  error code (e.g.
6700: 20 0a 2a 2a 20 4c 53 4d 5f 4e 4f 4d 45 4d 29 2e   .** LSM_NOMEM).
6710: 0a 2a 2f 0a 69 6e 74 20 6c 73 6d 42 6c 6f 63 6b  .*/.int lsmBlock
6720: 46 72 65 65 28 6c 73 6d 5f 64 62 20 2a 70 44 62  Free(lsm_db *pDb
6730: 2c 20 69 6e 74 20 69 42 6c 6b 29 7b 0a 20 20 53  , int iBlk){.  S
6740: 6e 61 70 73 68 6f 74 20 2a 70 20 3d 20 70 44 62  napshot *p = pDb
6750: 2d 3e 70 57 6f 72 6b 65 72 3b 0a 20 20 61 73 73  ->pWorker;.  ass
6760: 65 72 74 28 20 6c 73 6d 53 68 6d 41 73 73 65 72  ert( lsmShmAsser
6770: 74 57 6f 72 6b 65 72 28 70 44 62 29 20 29 3b 0a  tWorker(pDb) );.
6780: 0a 23 69 66 64 65 66 20 4c 53 4d 5f 4c 4f 47 5f  .#ifdef LSM_LOG_
6790: 46 52 45 45 4c 49 53 54 0a 20 20 6c 73 6d 4c 6f  FREELIST.  lsmLo
67a0: 67 4d 65 73 73 61 67 65 28 70 44 62 2c 20 4c 53  gMessage(pDb, LS
67b0: 4d 5f 4f 4b 2c 20 22 6c 73 6d 42 6c 6f 63 6b 46  M_OK, "lsmBlockF
67c0: 72 65 65 28 29 3a 20 46 72 65 65 20 62 6c 6f 63  ree(): Free bloc
67d0: 6b 20 25 64 22 2c 20 69 42 6c 6b 29 3b 0a 23 65  k %d", iBlk);.#e
67e0: 6e 64 69 66 0a 0a 20 20 72 65 74 75 72 6e 20 66  ndif..  return f
67f0: 72 65 65 6c 69 73 74 41 70 70 65 6e 64 28 70 44  reelistAppend(pD
6800: 62 2c 20 69 42 6c 6b 2c 20 70 2d 3e 69 49 64 29  b, iBlk, p->iId)
6810: 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 52 65 66 72 65  ;.}../*.** Refre
6820: 65 20 61 20 64 61 74 61 62 61 73 65 20 62 6c 6f  e a database blo
6830: 63 6b 2e 20 54 68 65 20 77 6f 72 6b 65 72 20 73  ck. The worker s
6840: 6e 61 70 73 68 6f 74 20 6d 75 73 74 20 62 65 20  napshot must be 
6850: 68 65 6c 64 20 69 6e 20 6f 72 64 65 72 20 74 6f  held in order to
6860: 20 63 61 6c 6c 20 0a 2a 2a 20 74 68 69 73 20 66   call .** this f
6870: 75 6e 63 74 69 6f 6e 2e 0a 2a 2a 0a 2a 2a 20 52  unction..**.** R
6880: 65 66 72 65 65 69 6e 67 20 69 73 20 72 65 71 75  efreeing is requ
6890: 69 72 65 64 20 77 68 65 6e 20 61 20 62 6c 6f 63  ired when a bloc
68a0: 6b 20 69 73 20 61 6c 6c 6f 63 61 74 65 64 20 75  k is allocated u
68b0: 73 69 6e 67 20 6c 73 6d 42 6c 6f 63 6b 41 6c 6c  sing lsmBlockAll
68c0: 6f 63 61 74 65 28 29 0a 2a 2a 20 62 75 74 20 74  ocate().** but t
68d0: 68 65 6e 20 6e 6f 74 20 75 73 65 64 2e 20 54 68  hen not used. Th
68e0: 69 73 20 66 75 6e 63 74 69 6f 6e 20 69 73 20 75  is function is u
68f0: 73 65 64 20 74 6f 20 70 75 73 68 20 74 68 65 20  sed to push the 
6900: 62 6c 6f 63 6b 20 62 61 63 6b 20 6f 6e 74 6f 0a  block back onto.
6910: 2a 2a 20 74 68 65 20 66 72 65 65 6c 69 73 74 2e  ** the freelist.
6920: 20 52 65 66 72 65 65 69 6e 67 20 61 20 62 6c 6f   Refreeing a blo
6930: 63 6b 20 69 73 20 64 69 66 66 65 72 65 6e 74 20  ck is different 
6940: 66 72 6f 6d 20 66 72 65 65 69 6e 67 20 69 73 2c  from freeing is,
6950: 20 61 73 20 61 20 72 65 66 72 65 65 64 0a 2a 2a   as a refreed.**
6960: 20 62 6c 6f 63 6b 20 6d 61 79 20 62 65 20 72 65   block may be re
6970: 75 73 65 64 20 69 6d 6d 65 64 69 61 74 65 6c 79  used immediately
6980: 2e 20 57 68 65 72 65 61 73 20 61 20 66 72 65 65  . Whereas a free
6990: 64 20 62 6c 6f 63 6b 20 63 61 6e 20 6e 6f 74 20  d block can not 
69a0: 62 65 20 72 65 75 73 65 64 20 0a 2a 2a 20 75 6e  be reused .** un
69b0: 74 69 6c 20 28 61 74 20 6c 65 61 73 74 29 20 61  til (at least) a
69c0: 66 74 65 72 20 74 68 65 20 6e 65 78 74 20 63 68  fter the next ch
69d0: 65 63 6b 70 6f 69 6e 74 2e 0a 2a 2f 0a 69 6e 74  eckpoint..*/.int
69e0: 20 6c 73 6d 42 6c 6f 63 6b 52 65 66 72 65 65 28   lsmBlockRefree(
69f0: 6c 73 6d 5f 64 62 20 2a 70 44 62 2c 20 69 6e 74  lsm_db *pDb, int
6a00: 20 69 42 6c 6b 29 7b 0a 20 20 69 6e 74 20 72 63   iBlk){.  int rc
6a10: 20 3d 20 4c 53 4d 5f 4f 4b 3b 20 20 20 20 20 20   = LSM_OK;      
6a20: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 52 65 74            /* Ret
6a30: 75 72 6e 20 63 6f 64 65 20 2a 2f 0a 0a 23 69 66  urn code */..#if
6a40: 64 65 66 20 4c 53 4d 5f 4c 4f 47 5f 46 52 45 45  def LSM_LOG_FREE
6a50: 4c 49 53 54 0a 20 20 6c 73 6d 4c 6f 67 4d 65 73  LIST.  lsmLogMes
6a60: 73 61 67 65 28 70 44 62 2c 20 4c 53 4d 5f 4f 4b  sage(pDb, LSM_OK
6a70: 2c 20 22 6c 73 6d 42 6c 6f 63 6b 52 65 66 72 65  , "lsmBlockRefre
6a80: 65 28 29 3a 20 52 65 66 72 65 65 20 62 6c 6f 63  e(): Refree bloc
6a90: 6b 20 25 64 22 2c 20 69 42 6c 6b 29 3b 0a 23 65  k %d", iBlk);.#e
6aa0: 6e 64 69 66 0a 0a 20 20 72 63 20 3d 20 66 72 65  ndif..  rc = fre
6ab0: 65 6c 69 73 74 41 70 70 65 6e 64 28 70 44 62 2c  elistAppend(pDb,
6ac0: 20 69 42 6c 6b 2c 20 30 29 3b 0a 20 20 72 65 74   iBlk, 0);.  ret
6ad0: 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a  urn rc;.}../*.**
6ae0: 20 49 66 20 72 65 71 75 69 72 65 64 2c 20 63 6f   If required, co
6af0: 70 79 20 61 20 64 61 74 61 62 61 73 65 20 63 68  py a database ch
6b00: 65 63 6b 70 6f 69 6e 74 20 66 72 6f 6d 20 73 68  eckpoint from sh
6b10: 61 72 65 64 20 6d 65 6d 6f 72 79 20 69 6e 74 6f  ared memory into
6b20: 20 74 68 65 0a 2a 2a 20 64 61 74 61 62 61 73 65   the.** database
6b30: 20 69 74 73 65 6c 66 2e 0a 2a 2a 0a 2a 2a 20 54   itself..**.** T
6b40: 68 65 20 57 4f 52 4b 45 52 20 6c 6f 63 6b 20 6d  he WORKER lock m
6b50: 75 73 74 20 6e 6f 74 20 62 65 20 68 65 6c 64 20  ust not be held 
6b60: 77 68 65 6e 20 74 68 69 73 20 69 73 20 63 61 6c  when this is cal
6b70: 6c 65 64 2e 20 54 68 69 73 20 69 73 20 62 65 63  led. This is bec
6b80: 61 75 73 65 0a 2a 2a 20 74 68 69 73 20 66 75 6e  ause.** this fun
6b90: 63 74 69 6f 6e 20 6d 61 79 20 69 6e 64 69 72 65  ction may indire
6ba0: 63 74 6c 79 20 63 61 6c 6c 20 66 73 79 6e 63 28  ctly call fsync(
6bb0: 29 2e 20 41 6e 64 20 74 68 65 20 57 4f 52 4b 45  ). And the WORKE
6bc0: 52 20 6c 6f 63 6b 20 73 68 6f 75 6c 64 0a 2a 2a  R lock should.**
6bd0: 20 6e 6f 74 20 62 65 20 68 65 6c 64 20 74 68 61   not be held tha
6be0: 74 20 6c 6f 6e 67 20 28 69 6e 20 63 61 73 65 20  t long (in case 
6bf0: 69 74 20 69 73 20 72 65 71 75 69 72 65 64 20 62  it is required b
6c00: 79 20 61 20 63 6c 69 65 6e 74 20 66 6c 75 73 68  y a client flush
6c10: 69 6e 67 20 61 6e 0a 2a 2a 20 69 6e 2d 6d 65 6d  ing an.** in-mem
6c20: 6f 72 79 20 74 72 65 65 20 74 6f 20 64 69 73 6b  ory tree to disk
6c30: 29 2e 0a 2a 2f 0a 69 6e 74 20 6c 73 6d 43 68 65  )..*/.int lsmChe
6c40: 63 6b 70 6f 69 6e 74 57 72 69 74 65 28 6c 73 6d  ckpointWrite(lsm
6c50: 5f 64 62 20 2a 70 44 62 2c 20 75 33 32 20 2a 70  _db *pDb, u32 *p
6c60: 6e 57 72 69 74 65 29 7b 0a 20 20 69 6e 74 20 72  nWrite){.  int r
6c70: 63 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  c;              
6c80: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 52 65             /* Re
6c90: 74 75 72 6e 20 43 6f 64 65 20 2a 2f 0a 20 20 75  turn Code */.  u
6ca0: 33 32 20 6e 57 72 69 74 65 20 3d 20 30 3b 0a 0a  32 nWrite = 0;..
6cb0: 20 20 61 73 73 65 72 74 28 20 70 44 62 2d 3e 70    assert( pDb->p
6cc0: 57 6f 72 6b 65 72 3d 3d 30 20 29 3b 0a 20 20 61  Worker==0 );.  a
6cd0: 73 73 65 72 74 28 20 31 20 7c 7c 20 70 44 62 2d  ssert( 1 || pDb-
6ce0: 3e 70 43 6c 69 65 6e 74 3d 3d 30 20 29 3b 0a 20  >pClient==0 );. 
6cf0: 20 61 73 73 65 72 74 28 20 6c 73 6d 53 68 6d 41   assert( lsmShmA
6d00: 73 73 65 72 74 4c 6f 63 6b 28 70 44 62 2c 20 4c  ssertLock(pDb, L
6d10: 53 4d 5f 4c 4f 43 4b 5f 57 4f 52 4b 45 52 2c 20  SM_LOCK_WORKER, 
6d20: 4c 53 4d 5f 4c 4f 43 4b 5f 55 4e 4c 4f 43 4b 29  LSM_LOCK_UNLOCK)
6d30: 20 29 3b 0a 0a 20 20 72 63 20 3d 20 6c 73 6d 53   );..  rc = lsmS
6d40: 68 6d 4c 6f 63 6b 28 70 44 62 2c 20 4c 53 4d 5f  hmLock(pDb, LSM_
6d50: 4c 4f 43 4b 5f 43 48 45 43 4b 50 4f 49 4e 54 45  LOCK_CHECKPOINTE
6d60: 52 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 45 58 43 4c  R, LSM_LOCK_EXCL
6d70: 2c 20 30 29 3b 0a 20 20 69 66 28 20 72 63 21 3d  , 0);.  if( rc!=
6d80: 4c 53 4d 5f 4f 4b 20 29 20 72 65 74 75 72 6e 20  LSM_OK ) return 
6d90: 72 63 3b 0a 0a 20 20 72 63 20 3d 20 6c 73 6d 43  rc;..  rc = lsmC
6da0: 68 65 63 6b 70 6f 69 6e 74 4c 6f 61 64 28 70 44  heckpointLoad(pD
6db0: 62 2c 20 30 29 3b 0a 20 20 69 66 28 20 72 63 3d  b, 0);.  if( rc=
6dc0: 3d 4c 53 4d 5f 4f 4b 20 29 7b 0a 20 20 20 20 69  =LSM_OK ){.    i
6dd0: 6e 74 20 6e 42 6c 6f 63 6b 20 3d 20 6c 73 6d 43  nt nBlock = lsmC
6de0: 68 65 63 6b 70 6f 69 6e 74 4e 42 6c 6f 63 6b 28  heckpointNBlock(
6df0: 70 44 62 2d 3e 61 53 6e 61 70 73 68 6f 74 29 3b  pDb->aSnapshot);
6e00: 0a 20 20 20 20 53 68 6d 48 65 61 64 65 72 20 2a  .    ShmHeader *
6e10: 70 53 68 6d 20 3d 20 70 44 62 2d 3e 70 53 68 6d  pShm = pDb->pShm
6e20: 68 64 72 3b 0a 20 20 20 20 69 6e 74 20 62 44 6f  hdr;.    int bDo
6e30: 6e 65 20 3d 20 30 3b 20 20 20 20 20 20 20 20 20  ne = 0;         
6e40: 20 20 20 20 20 20 20 2f 2a 20 54 72 75 65 20 69         /* True i
6e50: 66 20 63 68 65 63 6b 70 6f 69 6e 74 20 69 73 20  f checkpoint is 
6e60: 61 6c 72 65 61 64 79 20 73 74 6f 72 65 64 20 2a  already stored *
6e70: 2f 0a 0a 20 20 20 20 2f 2a 20 43 68 65 63 6b 20  /..    /* Check 
6e80: 69 66 20 74 68 69 73 20 63 68 65 63 6b 70 6f 69  if this checkpoi
6e90: 6e 74 20 68 61 73 20 61 6c 72 65 61 64 79 20 62  nt has already b
6ea0: 65 65 6e 20 77 72 69 74 74 65 6e 20 74 6f 20 74  een written to t
6eb0: 68 65 20 64 61 74 61 62 61 73 65 0a 20 20 20 20  he database.    
6ec0: 2a 2a 20 66 69 6c 65 2e 20 49 66 20 73 6f 2c 20  ** file. If so, 
6ed0: 73 65 74 20 76 61 72 69 61 62 6c 65 20 62 44 6f  set variable bDo
6ee0: 6e 65 20 74 6f 20 74 72 75 65 2e 20 20 2a 2f 0a  ne to true.  */.
6ef0: 20 20 20 20 69 66 28 20 70 53 68 6d 2d 3e 69 4d      if( pShm->iM
6f00: 65 74 61 50 61 67 65 20 29 7b 0a 20 20 20 20 20  etaPage ){.     
6f10: 20 4d 65 74 61 50 61 67 65 20 2a 70 50 67 3b 20   MetaPage *pPg; 
6f20: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
6f30: 4d 65 74 61 20 70 61 67 65 20 2a 2f 0a 20 20 20  Meta page */.   
6f40: 20 20 20 75 38 20 2a 61 44 61 74 61 3b 20 20 20     u8 *aData;   
6f50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
6f60: 2a 20 4d 65 74 61 2d 70 61 67 65 20 64 61 74 61  * Meta-page data
6f70: 20 62 75 66 66 65 72 20 2a 2f 0a 20 20 20 20 20   buffer */.     
6f80: 20 69 6e 74 20 6e 44 61 74 61 3b 20 20 20 20 20   int nData;     
6f90: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
6fa0: 53 69 7a 65 20 6f 66 20 61 44 61 74 61 5b 5d 20  Size of aData[] 
6fb0: 69 6e 20 62 79 74 65 73 20 2a 2f 0a 20 20 20 20  in bytes */.    
6fc0: 20 20 69 36 34 20 69 43 6b 70 74 3b 20 20 20 20    i64 iCkpt;    
6fd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
6fe0: 20 49 64 20 6f 66 20 63 68 65 63 6b 70 6f 69 6e   Id of checkpoin
6ff0: 74 20 6a 75 73 74 20 6c 6f 61 64 65 64 20 2a 2f  t just loaded */
7000: 0a 20 20 20 20 20 20 69 36 34 20 69 44 69 73 6b  .      i64 iDisk
7010: 20 3d 20 30 3b 20 20 20 20 20 20 20 20 20 20 20   = 0;           
7020: 20 20 20 2f 2a 20 49 64 20 6f 66 20 63 68 65 63     /* Id of chec
7030: 6b 70 6f 69 6e 74 20 61 6c 72 65 61 64 79 20 73  kpoint already s
7040: 74 6f 72 65 64 20 69 6e 20 64 62 20 2a 2f 0a 20  tored in db */. 
7050: 20 20 20 20 20 69 43 6b 70 74 20 3d 20 6c 73 6d       iCkpt = lsm
7060: 43 68 65 63 6b 70 6f 69 6e 74 49 64 28 70 44 62  CheckpointId(pDb
7070: 2d 3e 61 53 6e 61 70 73 68 6f 74 2c 20 30 29 3b  ->aSnapshot, 0);
7080: 0a 20 20 20 20 20 20 72 63 20 3d 20 6c 73 6d 46  .      rc = lsmF
7090: 73 4d 65 74 61 50 61 67 65 47 65 74 28 70 44 62  sMetaPageGet(pDb
70a0: 2d 3e 70 46 53 2c 20 30 2c 20 70 53 68 6d 2d 3e  ->pFS, 0, pShm->
70b0: 69 4d 65 74 61 50 61 67 65 2c 20 26 70 50 67 29  iMetaPage, &pPg)
70c0: 3b 0a 20 20 20 20 20 20 69 66 28 20 72 63 3d 3d  ;.      if( rc==
70d0: 4c 53 4d 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20  LSM_OK ){.      
70e0: 20 20 61 44 61 74 61 20 3d 20 6c 73 6d 46 73 4d    aData = lsmFsM
70f0: 65 74 61 50 61 67 65 44 61 74 61 28 70 50 67 2c  etaPageData(pPg,
7100: 20 26 6e 44 61 74 61 29 3b 0a 20 20 20 20 20 20   &nData);.      
7110: 20 20 69 44 69 73 6b 20 3d 20 6c 73 6d 43 68 65    iDisk = lsmChe
7120: 63 6b 70 6f 69 6e 74 49 64 28 28 75 33 32 20 2a  ckpointId((u32 *
7130: 29 61 44 61 74 61 2c 20 31 29 3b 0a 20 20 20 20  )aData, 1);.    
7140: 20 20 20 20 6e 57 72 69 74 65 20 3d 20 6c 73 6d      nWrite = lsm
7150: 43 68 65 63 6b 70 6f 69 6e 74 4e 57 72 69 74 65  CheckpointNWrite
7160: 28 28 75 33 32 20 2a 29 61 44 61 74 61 2c 20 31  ((u32 *)aData, 1
7170: 29 3b 0a 20 20 20 20 20 20 20 20 6c 73 6d 46 73  );.        lsmFs
7180: 4d 65 74 61 50 61 67 65 52 65 6c 65 61 73 65 28  MetaPageRelease(
7190: 70 50 67 29 3b 0a 20 20 20 20 20 20 7d 0a 20 20  pPg);.      }.  
71a0: 20 20 20 20 62 44 6f 6e 65 20 3d 20 28 69 44 69      bDone = (iDi
71b0: 73 6b 3e 3d 69 43 6b 70 74 29 3b 0a 20 20 20 20  sk>=iCkpt);.    
71c0: 7d 0a 0a 20 20 20 20 69 66 28 20 72 63 3d 3d 4c  }..    if( rc==L
71d0: 53 4d 5f 4f 4b 20 26 26 20 62 44 6f 6e 65 3d 3d  SM_OK && bDone==
71e0: 30 20 29 7b 0a 20 20 20 20 20 20 69 6e 74 20 69  0 ){.      int i
71f0: 4d 65 74 61 20 3d 20 28 70 53 68 6d 2d 3e 69 4d  Meta = (pShm->iM
7200: 65 74 61 50 61 67 65 20 25 20 32 29 20 2b 20 31  etaPage % 2) + 1
7210: 3b 0a 20 20 20 20 20 20 69 66 28 20 70 44 62 2d  ;.      if( pDb-
7220: 3e 65 53 61 66 65 74 79 21 3d 4c 53 4d 5f 53 41  >eSafety!=LSM_SA
7230: 46 45 54 59 5f 4f 46 46 20 29 7b 0a 20 20 20 20  FETY_OFF ){.    
7240: 20 20 20 20 72 63 20 3d 20 6c 73 6d 46 73 53 79      rc = lsmFsSy
7250: 6e 63 44 62 28 70 44 62 2d 3e 70 46 53 2c 20 6e  ncDb(pDb->pFS, n
7260: 42 6c 6f 63 6b 29 3b 0a 20 20 20 20 20 20 7d 0a  Block);.      }.
7270: 20 20 20 20 20 20 69 66 28 20 72 63 3d 3d 4c 53        if( rc==LS
7280: 4d 5f 4f 4b 20 29 20 72 63 20 3d 20 6c 73 6d 43  M_OK ) rc = lsmC
7290: 68 65 63 6b 70 6f 69 6e 74 53 74 6f 72 65 28 70  heckpointStore(p
72a0: 44 62 2c 20 69 4d 65 74 61 29 3b 0a 20 20 20 20  Db, iMeta);.    
72b0: 20 20 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b    if( rc==LSM_OK
72c0: 20 26 26 20 70 44 62 2d 3e 65 53 61 66 65 74 79   && pDb->eSafety
72d0: 21 3d 4c 53 4d 5f 53 41 46 45 54 59 5f 4f 46 46  !=LSM_SAFETY_OFF
72e0: 29 7b 0a 20 20 20 20 20 20 20 20 72 63 20 3d 20  ){.        rc = 
72f0: 6c 73 6d 46 73 53 79 6e 63 44 62 28 70 44 62 2d  lsmFsSyncDb(pDb-
7300: 3e 70 46 53 2c 20 30 29 3b 0a 20 20 20 20 20 20  >pFS, 0);.      
7310: 7d 0a 20 20 20 20 20 20 69 66 28 20 72 63 3d 3d  }.      if( rc==
7320: 4c 53 4d 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20  LSM_OK ){.      
7330: 20 20 70 53 68 6d 2d 3e 69 4d 65 74 61 50 61 67    pShm->iMetaPag
7340: 65 20 3d 20 69 4d 65 74 61 3b 0a 20 20 20 20 20  e = iMeta;.     
7350: 20 20 20 6e 57 72 69 74 65 20 3d 20 6c 73 6d 43     nWrite = lsmC
7360: 68 65 63 6b 70 6f 69 6e 74 4e 57 72 69 74 65 28  heckpointNWrite(
7370: 70 44 62 2d 3e 61 53 6e 61 70 73 68 6f 74 2c 20  pDb->aSnapshot, 
7380: 30 29 20 2d 20 6e 57 72 69 74 65 3b 0a 20 20 20  0) - nWrite;.   
7390: 20 20 20 7d 0a 23 69 66 64 65 66 20 4c 53 4d 5f     }.#ifdef LSM_
73a0: 4c 4f 47 5f 57 4f 52 4b 0a 20 20 20 20 20 20 6c  LOG_WORK.      l
73b0: 73 6d 4c 6f 67 4d 65 73 73 61 67 65 28 70 44 62  smLogMessage(pDb
73c0: 2c 20 30 2c 20 22 66 69 6e 69 73 68 20 63 68 65  , 0, "finish che
73d0: 63 6b 70 6f 69 6e 74 20 25 64 22 2c 20 0a 20 20  ckpoint %d", .  
73e0: 20 20 20 20 20 20 20 20 28 69 6e 74 29 6c 73 6d          (int)lsm
73f0: 43 68 65 63 6b 70 6f 69 6e 74 49 64 28 70 44 62  CheckpointId(pDb
7400: 2d 3e 61 53 6e 61 70 73 68 6f 74 2c 20 30 29 0a  ->aSnapshot, 0).
7410: 20 20 20 20 20 20 29 3b 0a 23 65 6e 64 69 66 0a        );.#endif.
7420: 20 20 20 20 7d 0a 20 20 7d 0a 0a 20 20 6c 73 6d      }.  }..  lsm
7430: 53 68 6d 4c 6f 63 6b 28 70 44 62 2c 20 4c 53 4d  ShmLock(pDb, LSM
7440: 5f 4c 4f 43 4b 5f 43 48 45 43 4b 50 4f 49 4e 54  _LOCK_CHECKPOINT
7450: 45 52 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 55 4e 4c  ER, LSM_LOCK_UNL
7460: 4f 43 4b 2c 20 30 29 3b 0a 20 20 69 66 28 20 70  OCK, 0);.  if( p
7470: 6e 57 72 69 74 65 20 26 26 20 72 63 3d 3d 4c 53  nWrite && rc==LS
7480: 4d 5f 4f 4b 20 29 20 2a 70 6e 57 72 69 74 65 20  M_OK ) *pnWrite 
7490: 3d 20 6e 57 72 69 74 65 3b 0a 20 20 72 65 74 75  = nWrite;.  retu
74a0: 72 6e 20 72 63 3b 0a 7d 0a 0a 69 6e 74 20 6c 73  rn rc;.}..int ls
74b0: 6d 42 65 67 69 6e 57 6f 72 6b 28 6c 73 6d 5f 64  mBeginWork(lsm_d
74c0: 62 20 2a 70 44 62 29 7b 0a 20 20 69 6e 74 20 72  b *pDb){.  int r
74d0: 63 3b 0a 0a 20 20 2f 2a 20 41 74 74 65 6d 70 74  c;..  /* Attempt
74e0: 20 74 6f 20 74 61 6b 65 20 74 68 65 20 57 4f 52   to take the WOR
74f0: 4b 45 52 20 6c 6f 63 6b 20 2a 2f 0a 20 20 72 63  KER lock */.  rc
7500: 20 3d 20 6c 73 6d 53 68 6d 4c 6f 63 6b 28 70 44   = lsmShmLock(pD
7510: 62 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 57 4f 52 4b  b, LSM_LOCK_WORK
7520: 45 52 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 45 58 43  ER, LSM_LOCK_EXC
7530: 4c 2c 20 30 29 3b 0a 0a 20 20 2f 2a 20 44 65 73  L, 0);..  /* Des
7540: 65 72 69 61 6c 69 7a 65 20 74 68 65 20 63 75 72  erialize the cur
7550: 72 65 6e 74 20 77 6f 72 6b 65 72 20 73 6e 61 70  rent worker snap
7560: 73 68 6f 74 20 2a 2f 0a 20 20 69 66 28 20 72 63  shot */.  if( rc
7570: 3d 3d 4c 53 4d 5f 4f 4b 20 29 7b 0a 20 20 20 20  ==LSM_OK ){.    
7580: 72 63 20 3d 20 6c 73 6d 43 68 65 63 6b 70 6f 69  rc = lsmCheckpoi
7590: 6e 74 4c 6f 61 64 57 6f 72 6b 65 72 28 70 44 62  ntLoadWorker(pDb
75a0: 29 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20  );.  }.  return 
75b0: 72 63 3b 0a 7d 0a 0a 76 6f 69 64 20 6c 73 6d 46  rc;.}..void lsmF
75c0: 72 65 65 53 6e 61 70 73 68 6f 74 28 6c 73 6d 5f  reeSnapshot(lsm_
75d0: 65 6e 76 20 2a 70 45 6e 76 2c 20 53 6e 61 70 73  env *pEnv, Snaps
75e0: 68 6f 74 20 2a 70 29 7b 0a 20 20 69 66 28 20 70  hot *p){.  if( p
75f0: 20 29 7b 0a 20 20 20 20 6c 73 6d 53 6f 72 74 65   ){.    lsmSorte
7600: 64 46 72 65 65 4c 65 76 65 6c 28 70 45 6e 76 2c  dFreeLevel(pEnv,
7610: 20 70 2d 3e 70 4c 65 76 65 6c 29 3b 0a 20 20 20   p->pLevel);.   
7620: 20 6c 73 6d 46 72 65 65 28 70 45 6e 76 2c 20 70   lsmFree(pEnv, p
7630: 2d 3e 66 72 65 65 6c 69 73 74 2e 61 45 6e 74 72  ->freelist.aEntr
7640: 79 29 3b 0a 20 20 20 20 6c 73 6d 46 72 65 65 28  y);.    lsmFree(
7650: 70 45 6e 76 2c 20 70 2d 3e 72 65 64 69 72 65 63  pEnv, p->redirec
7660: 74 2e 61 29 3b 0a 20 20 20 20 6c 73 6d 46 72 65  t.a);.    lsmFre
7670: 65 28 70 45 6e 76 2c 20 70 29 3b 0a 20 20 7d 0a  e(pEnv, p);.  }.
7680: 7d 0a 0a 2f 2a 0a 2a 2a 20 41 74 74 65 6d 70 74  }../*.** Attempt
7690: 20 74 6f 20 70 6f 70 75 6c 61 74 65 20 6f 6e 65   to populate one
76a0: 20 6f 66 20 74 68 65 20 72 65 61 64 2d 6c 6f 63   of the read-loc
76b0: 6b 20 73 6c 6f 74 73 20 74 6f 20 63 6f 6e 74 61  k slots to conta
76c0: 69 6e 20 6c 6f 63 6b 20 76 61 6c 75 65 73 0a 2a  in lock values.*
76d0: 2a 20 69 4c 73 6d 2f 69 53 68 6d 2e 20 4f 72 2c  * iLsm/iShm. Or,
76e0: 20 69 66 20 73 75 63 68 20 61 20 73 6c 6f 74 20   if such a slot 
76f0: 65 78 69 73 74 73 20 61 6c 72 65 61 64 79 2c 20  exists already, 
7700: 74 68 69 73 20 66 75 6e 63 74 69 6f 6e 20 69 73  this function is
7710: 20 61 20 6e 6f 2d 6f 70 2e 0a 2a 2a 0a 2a 2a 20   a no-op..**.** 
7720: 49 74 20 69 73 20 6e 6f 74 20 61 6e 20 65 72 72  It is not an err
7730: 6f 72 20 69 66 20 6e 6f 20 73 6c 6f 74 20 63 61  or if no slot ca
7740: 6e 20 62 65 20 70 6f 70 75 6c 61 74 65 64 20 62  n be populated b
7750: 65 63 61 75 73 65 20 74 68 65 20 77 72 69 74 65  ecause the write
7760: 2d 6c 6f 63 6b 0a 2a 2a 20 63 61 6e 6e 6f 74 20  -lock.** cannot 
7770: 62 65 20 6f 62 74 61 69 6e 65 64 2e 20 49 66 20  be obtained. If 
7780: 61 6e 79 20 6f 74 68 65 72 20 65 72 72 6f 72 20  any other error 
7790: 6f 63 63 75 72 73 2c 20 72 65 74 75 72 6e 20 61  occurs, return a
77a0: 6e 20 4c 53 4d 20 65 72 72 6f 72 20 63 6f 64 65  n LSM error code
77b0: 2e 0a 2a 2a 20 4f 74 68 65 72 77 69 73 65 2c 20  ..** Otherwise, 
77c0: 4c 53 4d 5f 4f 4b 2e 0a 2a 2a 0a 2a 2a 20 54 68  LSM_OK..**.** Th
77d0: 69 73 20 66 75 6e 63 74 69 6f 6e 20 69 73 20 63  is function is c
77e0: 61 6c 6c 65 64 20 61 74 20 76 61 72 69 6f 75 73  alled at various
77f0: 20 70 6f 69 6e 74 73 20 74 6f 20 74 72 79 20 74   points to try t
7800: 6f 20 65 6e 73 75 72 65 20 74 68 61 74 20 74 68  o ensure that th
7810: 65 72 65 0a 2a 2a 20 61 6c 77 61 79 73 20 65 78  ere.** always ex
7820: 69 73 74 73 20 61 74 20 6c 65 61 73 74 20 6f 6e  ists at least on
7830: 65 20 72 65 61 64 2d 6c 6f 63 6b 20 73 6c 6f 74  e read-lock slot
7840: 20 74 68 61 74 20 63 61 6e 20 62 65 20 75 73 65   that can be use
7850: 64 20 62 79 20 61 20 72 65 61 64 2d 6f 6e 6c 79  d by a read-only
7860: 0a 2a 2a 20 63 6c 69 65 6e 74 2e 20 41 6e 64 20  .** client. And 
7870: 73 6f 20 74 68 61 74 2c 20 69 6e 20 74 68 65 20  so that, in the 
7880: 75 73 75 61 6c 20 63 61 73 65 2c 20 74 68 65 72  usual case, ther
7890: 65 20 69 73 20 61 6e 20 22 65 78 61 63 74 20 6d  e is an "exact m
78a0: 61 74 63 68 22 20 61 76 61 69 6c 61 62 6c 65 0a  atch" available.
78b0: 2a 2a 20 77 68 65 6e 65 76 65 72 20 61 20 72 65  ** whenever a re
78c0: 61 64 20 74 72 61 6e 73 61 63 74 69 6f 6e 20 69  ad transaction i
78d0: 73 20 6f 70 65 6e 65 64 20 62 79 20 61 6e 79 20  s opened by any 
78e0: 63 6c 69 65 6e 74 2e 20 41 74 20 70 72 65 73 65  client. At prese
78f0: 6e 74 20 74 68 69 73 0a 2a 2a 20 66 75 6e 63 74  nt this.** funct
7900: 69 6f 6e 20 69 73 20 63 61 6c 6c 65 64 20 77 68  ion is called wh
7910: 65 6e 3a 0a 2a 2a 0a 2a 2a 20 20 20 20 2a 20 41  en:.**.**    * A
7920: 20 77 72 69 74 65 20 74 72 61 6e 73 61 63 74 69   write transacti
7930: 6f 6e 20 74 68 61 74 20 63 61 6c 6c 65 64 20 6c  on that called l
7940: 73 6d 54 72 65 65 44 69 73 63 61 72 64 4f 6c 64  smTreeDiscardOld
7950: 28 29 20 69 73 20 63 6f 6d 6d 69 74 74 65 64 2c  () is committed,
7960: 20 61 6e 64 0a 2a 2a 20 20 20 20 2a 20 57 68 65   and.**    * Whe
7970: 6e 65 76 65 72 20 74 68 65 20 77 6f 72 6b 69 6e  never the workin
7980: 67 20 73 6e 61 70 73 68 6f 74 20 69 73 20 75 70  g snapshot is up
7990: 64 61 74 65 64 20 28 69 2e 65 2e 20 6c 73 6d 46  dated (i.e. lsmF
79a0: 69 6e 69 73 68 57 6f 72 6b 28 29 29 2e 0a 2a 2f  inishWork())..*/
79b0: 0a 73 74 61 74 69 63 20 69 6e 74 20 64 62 53 65  .static int dbSe
79c0: 74 52 65 61 64 4c 6f 63 6b 28 6c 73 6d 5f 64 62  tReadLock(lsm_db
79d0: 20 2a 64 62 2c 20 69 36 34 20 69 4c 73 6d 2c 20   *db, i64 iLsm, 
79e0: 75 33 32 20 69 53 68 6d 29 7b 0a 20 20 69 6e 74  u32 iShm){.  int
79f0: 20 72 63 20 3d 20 4c 53 4d 5f 4f 4b 3b 0a 20 20   rc = LSM_OK;.  
7a00: 53 68 6d 48 65 61 64 65 72 20 2a 70 53 68 6d 20  ShmHeader *pShm 
7a10: 3d 20 64 62 2d 3e 70 53 68 6d 68 64 72 3b 0a 20  = db->pShmhdr;. 
7a20: 20 69 6e 74 20 69 3b 0a 0a 20 20 2f 2a 20 43 68   int i;..  /* Ch
7a30: 65 63 6b 20 69 66 20 74 68 65 72 65 20 69 73 20  eck if there is 
7a40: 61 6c 72 65 61 64 79 20 61 20 73 6c 6f 74 20 63  already a slot c
7a50: 6f 6e 74 61 69 6e 69 6e 67 20 74 68 65 20 72 65  ontaining the re
7a60: 71 75 69 72 65 64 20 76 61 6c 75 65 73 2e 20 2a  quired values. *
7a70: 2f 0a 20 20 66 6f 72 28 69 3d 30 3b 20 69 3c 4c  /.  for(i=0; i<L
7a80: 53 4d 5f 4c 4f 43 4b 5f 4e 52 45 41 44 45 52 3b  SM_LOCK_NREADER;
7a90: 20 69 2b 2b 29 7b 0a 20 20 20 20 53 68 6d 52 65   i++){.    ShmRe
7aa0: 61 64 65 72 20 2a 70 20 3d 20 26 70 53 68 6d 2d  ader *p = &pShm-
7ab0: 3e 61 52 65 61 64 65 72 5b 69 5d 3b 0a 20 20 20  >aReader[i];.   
7ac0: 20 69 66 28 20 70 2d 3e 69 4c 73 6d 49 64 3d 3d   if( p->iLsmId==
7ad0: 69 4c 73 6d 20 26 26 20 70 2d 3e 69 54 72 65 65  iLsm && p->iTree
7ae0: 49 64 3d 3d 69 53 68 6d 20 29 20 72 65 74 75 72  Id==iShm ) retur
7af0: 6e 20 4c 53 4d 5f 4f 4b 3b 0a 20 20 7d 0a 0a 20  n LSM_OK;.  }.. 
7b00: 20 2f 2a 20 49 74 65 72 61 74 65 20 74 68 72 6f   /* Iterate thro
7b10: 75 67 68 20 61 6c 6c 20 72 65 61 64 2d 6c 6f 63  ugh all read-loc
7b20: 6b 20 73 6c 6f 74 73 2c 20 61 74 74 65 6d 70 74  k slots, attempt
7b30: 69 6e 67 20 74 6f 20 74 61 6b 65 20 61 20 77 72  ing to take a wr
7b40: 69 74 65 2d 6c 6f 63 6b 0a 20 20 2a 2a 20 6f 6e  ite-lock.  ** on
7b50: 20 65 61 63 68 20 6f 66 20 74 68 65 6d 2e 20 49   each of them. I
7b60: 66 20 61 20 77 72 69 74 65 2d 6c 6f 63 6b 20 73  f a write-lock s
7b70: 75 63 63 65 65 64 73 2c 20 70 6f 70 75 6c 61 74  ucceeds, populat
7b80: 65 20 74 68 65 20 6c 6f 63 6b 65 64 20 73 6c 6f  e the locked slo
7b90: 74 0a 20 20 2a 2a 20 77 69 74 68 20 74 68 65 20  t.  ** with the 
7ba0: 72 65 71 75 69 72 65 64 20 76 61 6c 75 65 73 20  required values 
7bb0: 61 6e 64 20 62 72 65 61 6b 20 6f 75 74 20 6f 66  and break out of
7bc0: 20 74 68 65 20 6c 6f 6f 70 2e 20 20 2a 2f 0a 20   the loop.  */. 
7bd0: 20 66 6f 72 28 69 3d 30 3b 20 72 63 3d 3d 4c 53   for(i=0; rc==LS
7be0: 4d 5f 4f 4b 20 26 26 20 69 3c 4c 53 4d 5f 4c 4f  M_OK && i<LSM_LO
7bf0: 43 4b 5f 4e 52 45 41 44 45 52 3b 20 69 2b 2b 29  CK_NREADER; i++)
7c00: 7b 0a 20 20 20 20 72 63 20 3d 20 6c 73 6d 53 68  {.    rc = lsmSh
7c10: 6d 4c 6f 63 6b 28 64 62 2c 20 4c 53 4d 5f 4c 4f  mLock(db, LSM_LO
7c20: 43 4b 5f 52 45 41 44 45 52 28 69 29 2c 20 4c 53  CK_READER(i), LS
7c30: 4d 5f 4c 4f 43 4b 5f 45 58 43 4c 2c 20 30 29 3b  M_LOCK_EXCL, 0);
7c40: 0a 20 20 20 20 69 66 28 20 72 63 3d 3d 4c 53 4d  .    if( rc==LSM
7c50: 5f 42 55 53 59 20 29 7b 0a 20 20 20 20 20 20 72  _BUSY ){.      r
7c60: 63 20 3d 20 4c 53 4d 5f 4f 4b 3b 0a 20 20 20 20  c = LSM_OK;.    
7c70: 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 53 68 6d  }else{.      Shm
7c80: 52 65 61 64 65 72 20 2a 70 20 3d 20 26 70 53 68  Reader *p = &pSh
7c90: 6d 2d 3e 61 52 65 61 64 65 72 5b 69 5d 3b 0a 20  m->aReader[i];. 
7ca0: 20 20 20 20 20 70 2d 3e 69 4c 73 6d 49 64 20 3d       p->iLsmId =
7cb0: 20 69 4c 73 6d 3b 0a 20 20 20 20 20 20 70 2d 3e   iLsm;.      p->
7cc0: 69 54 72 65 65 49 64 20 3d 20 69 53 68 6d 3b 0a  iTreeId = iShm;.
7cd0: 20 20 20 20 20 20 6c 73 6d 53 68 6d 4c 6f 63 6b        lsmShmLock
7ce0: 28 64 62 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 52 45  (db, LSM_LOCK_RE
7cf0: 41 44 45 52 28 69 29 2c 20 4c 53 4d 5f 4c 4f 43  ADER(i), LSM_LOC
7d00: 4b 5f 55 4e 4c 4f 43 4b 2c 20 30 29 3b 0a 20 20  K_UNLOCK, 0);.  
7d10: 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 7d      break;.    }
7d20: 0a 20 20 7d 0a 0a 20 20 72 65 74 75 72 6e 20 72  .  }..  return r
7d30: 63 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 52 65 6c 65  c;.}../*.** Rele
7d40: 61 73 65 20 74 68 65 20 72 65 61 64 2d 6c 6f 63  ase the read-loc
7d50: 6b 20 63 75 72 72 65 6e 74 6c 79 20 68 65 6c 64  k currently held
7d60: 20 62 79 20 63 6f 6e 6e 65 63 74 69 6f 6e 20 64   by connection d
7d70: 62 2e 0a 2a 2f 0a 69 6e 74 20 64 62 52 65 6c 65  b..*/.int dbRele
7d80: 61 73 65 52 65 61 64 6c 6f 63 6b 28 6c 73 6d 5f  aseReadlock(lsm_
7d90: 64 62 20 2a 64 62 29 7b 0a 20 20 69 6e 74 20 72  db *db){.  int r
7da0: 63 20 3d 20 4c 53 4d 5f 4f 4b 3b 0a 20 20 69 66  c = LSM_OK;.  if
7db0: 28 20 64 62 2d 3e 69 52 65 61 64 65 72 3e 3d 30  ( db->iReader>=0
7dc0: 20 29 7b 0a 20 20 20 20 72 63 20 3d 20 6c 73 6d   ){.    rc = lsm
7dd0: 53 68 6d 4c 6f 63 6b 28 64 62 2c 20 4c 53 4d 5f  ShmLock(db, LSM_
7de0: 4c 4f 43 4b 5f 52 45 41 44 45 52 28 64 62 2d 3e  LOCK_READER(db->
7df0: 69 52 65 61 64 65 72 29 2c 20 4c 53 4d 5f 4c 4f  iReader), LSM_LO
7e00: 43 4b 5f 55 4e 4c 4f 43 4b 2c 20 30 29 3b 0a 20  CK_UNLOCK, 0);. 
7e10: 20 20 20 64 62 2d 3e 69 52 65 61 64 65 72 20 3d     db->iReader =
7e20: 20 2d 31 3b 0a 20 20 7d 0a 20 20 64 62 2d 3e 62   -1;.  }.  db->b
7e30: 52 6f 54 72 61 6e 73 20 3d 20 30 3b 0a 20 20 72  RoTrans = 0;.  r
7e40: 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 0a 2f 2a  eturn rc;.}.../*
7e50: 0a 2a 2a 20 41 72 67 75 6d 65 6e 74 20 62 46 6c  .** Argument bFl
7e60: 75 73 68 20 69 73 20 74 72 75 65 20 69 66 20 74  ush is true if t
7e70: 68 65 20 63 6f 6e 74 65 6e 74 73 20 6f 66 20 74  he contents of t
7e80: 68 65 20 69 6e 2d 6d 65 6d 6f 72 79 20 74 72 65  he in-memory tre
7e90: 65 20 68 61 73 20 6a 75 73 74 0a 2a 2a 20 62 65  e has just.** be
7ea0: 65 6e 20 66 6c 75 73 68 65 64 20 74 6f 20 64 69  en flushed to di
7eb0: 73 6b 2e 20 54 68 65 20 73 69 67 6e 69 66 69 63  sk. The signific
7ec0: 61 6e 63 65 20 6f 66 20 74 68 69 73 20 69 73 20  ance of this is 
7ed0: 74 68 61 74 20 6f 6e 63 65 20 74 68 65 20 73 6e  that once the sn
7ee0: 61 70 73 68 6f 74 0a 2a 2a 20 63 72 65 61 74 65  apshot.** create
7ef0: 64 20 74 6f 20 68 6f 6c 64 20 74 68 65 20 75 70  d to hold the up
7f00: 64 61 74 65 64 20 73 74 61 74 65 20 6f 66 20 74  dated state of t
7f10: 68 65 20 64 61 74 61 62 61 73 65 20 69 73 20 73  he database is s
7f20: 79 6e 63 65 64 20 74 6f 20 64 69 73 6b 2c 20 6c  ynced to disk, l
7f30: 6f 67 0a 2a 2a 20 66 69 6c 65 20 73 70 61 63 65  og.** file space
7f40: 20 63 61 6e 20 62 65 20 72 65 63 79 63 6c 65 64   can be recycled
7f50: 2e 0a 2a 2f 0a 76 6f 69 64 20 6c 73 6d 46 69 6e  ..*/.void lsmFin
7f60: 69 73 68 57 6f 72 6b 28 6c 73 6d 5f 64 62 20 2a  ishWork(lsm_db *
7f70: 70 44 62 2c 20 69 6e 74 20 62 46 6c 75 73 68 2c  pDb, int bFlush,
7f80: 20 69 6e 74 20 2a 70 52 63 29 7b 0a 20 20 69 6e   int *pRc){.  in
7f90: 74 20 72 63 20 3d 20 2a 70 52 63 3b 0a 20 20 61  t rc = *pRc;.  a
7fa0: 73 73 65 72 74 28 20 72 63 21 3d 30 20 7c 7c 20  ssert( rc!=0 || 
7fb0: 70 44 62 2d 3e 70 57 6f 72 6b 65 72 20 29 3b 0a  pDb->pWorker );.
7fc0: 20 20 69 66 28 20 70 44 62 2d 3e 70 57 6f 72 6b    if( pDb->pWork
7fd0: 65 72 20 29 7b 0a 20 20 20 20 2f 2a 20 49 66 20  er ){.    /* If 
7fe0: 6e 6f 20 65 72 72 6f 72 20 68 61 73 20 6f 63 63  no error has occ
7ff0: 75 72 72 65 64 2c 20 73 65 72 69 61 6c 69 7a 65  urred, serialize
8000: 20 74 68 65 20 77 6f 72 6b 65 72 20 73 6e 61 70   the worker snap
8010: 73 68 6f 74 20 61 6e 64 20 77 72 69 74 65 0a 20  shot and write. 
8020: 20 20 20 2a 2a 20 69 74 20 74 6f 20 73 68 61 72     ** it to shar
8030: 65 64 20 6d 65 6d 6f 72 79 2e 20 20 2a 2f 0a 20  ed memory.  */. 
8040: 20 20 20 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f     if( rc==LSM_O
8050: 4b 20 29 7b 0a 20 20 20 20 20 20 72 63 20 3d 20  K ){.      rc = 
8060: 6c 73 6d 53 61 76 65 57 6f 72 6b 65 72 28 70 44  lsmSaveWorker(pD
8070: 62 2c 20 62 46 6c 75 73 68 29 3b 0a 20 20 20 20  b, bFlush);.    
8080: 7d 0a 0a 20 20 20 20 2f 2a 20 41 73 73 75 6d 69  }..    /* Assumi
8090: 6e 67 20 6e 6f 20 65 72 72 6f 72 20 68 61 73 20  ng no error has 
80a0: 6f 63 63 75 72 72 65 64 2c 20 75 70 64 61 74 65  occurred, update
80b0: 20 61 20 72 65 61 64 20 6c 6f 63 6b 20 73 6c 6f   a read lock slo
80c0: 74 20 77 69 74 68 20 74 68 65 0a 20 20 20 20 2a  t with the.    *
80d0: 2a 20 6e 65 77 20 73 6e 61 70 73 68 6f 74 20 69  * new snapshot i
80e0: 64 20 28 73 65 65 20 63 6f 6d 6d 65 6e 74 73 20  d (see comments 
80f0: 61 62 6f 76 65 20 66 75 6e 63 74 69 6f 6e 20 64  above function d
8100: 62 53 65 74 52 65 61 64 4c 6f 63 6b 28 29 29 2e  bSetReadLock()).
8110: 20 20 2a 2f 0a 20 20 20 20 69 66 28 20 72 63 3d    */.    if( rc=
8120: 3d 4c 53 4d 5f 4f 4b 20 29 7b 0a 20 20 20 20 20  =LSM_OK ){.     
8130: 20 69 66 28 20 70 44 62 2d 3e 69 52 65 61 64 65   if( pDb->iReade
8140: 72 3c 30 20 29 7b 0a 20 20 20 20 20 20 20 20 72  r<0 ){.        r
8150: 63 20 3d 20 6c 73 6d 54 72 65 65 4c 6f 61 64 48  c = lsmTreeLoadH
8160: 65 61 64 65 72 28 70 44 62 2c 20 30 29 3b 0a 20  eader(pDb, 0);. 
8170: 20 20 20 20 20 7d 0a 20 20 20 20 20 20 69 66 28       }.      if(
8180: 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 29 7b 0a 20   rc==LSM_OK ){. 
8190: 20 20 20 20 20 20 20 72 63 20 3d 20 64 62 53 65         rc = dbSe
81a0: 74 52 65 61 64 4c 6f 63 6b 28 70 44 62 2c 20 70  tReadLock(pDb, p
81b0: 44 62 2d 3e 70 57 6f 72 6b 65 72 2d 3e 69 49 64  Db->pWorker->iId
81c0: 2c 20 70 44 62 2d 3e 74 72 65 65 68 64 72 2e 69  , pDb->treehdr.i
81d0: 55 73 65 64 53 68 6d 69 64 29 3b 0a 20 20 20 20  UsedShmid);.    
81e0: 20 20 7d 0a 20 20 20 20 7d 0a 0a 20 20 20 20 2f    }.    }..    /
81f0: 2a 20 46 72 65 65 20 74 68 65 20 73 6e 61 70 73  * Free the snaps
8200: 68 6f 74 20 6f 62 6a 65 63 74 2e 20 2a 2f 0a 20  hot object. */. 
8210: 20 20 20 6c 73 6d 46 72 65 65 53 6e 61 70 73 68     lsmFreeSnapsh
8220: 6f 74 28 70 44 62 2d 3e 70 45 6e 76 2c 20 70 44  ot(pDb->pEnv, pD
8230: 62 2d 3e 70 57 6f 72 6b 65 72 29 3b 0a 20 20 20  b->pWorker);.   
8240: 20 70 44 62 2d 3e 70 57 6f 72 6b 65 72 20 3d 20   pDb->pWorker = 
8250: 30 3b 0a 20 20 7d 0a 0a 20 20 6c 73 6d 53 68 6d  0;.  }..  lsmShm
8260: 4c 6f 63 6b 28 70 44 62 2c 20 4c 53 4d 5f 4c 4f  Lock(pDb, LSM_LO
8270: 43 4b 5f 57 4f 52 4b 45 52 2c 20 4c 53 4d 5f 4c  CK_WORKER, LSM_L
8280: 4f 43 4b 5f 55 4e 4c 4f 43 4b 2c 20 30 29 3b 0a  OCK_UNLOCK, 0);.
8290: 20 20 2a 70 52 63 20 3d 20 72 63 3b 0a 7d 0a 0a    *pRc = rc;.}..
82a0: 2f 2a 0a 2a 2a 20 43 61 6c 6c 65 64 20 77 68 65  /*.** Called whe
82b0: 6e 20 72 65 63 6f 76 65 72 79 20 69 73 20 66 69  n recovery is fi
82c0: 6e 69 73 68 65 64 2e 0a 2a 2f 0a 69 6e 74 20 6c  nished..*/.int l
82d0: 73 6d 46 69 6e 69 73 68 52 65 63 6f 76 65 72 79  smFinishRecovery
82e0: 28 6c 73 6d 5f 64 62 20 2a 70 44 62 29 7b 0a 20  (lsm_db *pDb){. 
82f0: 20 6c 73 6d 54 72 65 65 45 6e 64 54 72 61 6e 73   lsmTreeEndTrans
8300: 61 63 74 69 6f 6e 28 70 44 62 2c 20 31 29 3b 0a  action(pDb, 1);.
8310: 20 20 72 65 74 75 72 6e 20 4c 53 4d 5f 4f 4b 3b    return LSM_OK;
8320: 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 43 68 65 63 6b 20  .}../*.** Check 
8330: 69 66 20 74 68 65 20 63 75 72 72 65 6e 74 6c 79  if the currently
8340: 20 63 6f 6e 66 69 67 75 72 65 64 20 63 6f 6d 70   configured comp
8350: 72 65 73 73 69 6f 6e 20 66 75 6e 63 74 69 6f 6e  ression function
8360: 73 0a 2a 2a 20 28 4c 53 4d 5f 43 4f 4e 46 49 47  s.** (LSM_CONFIG
8370: 5f 53 45 54 5f 43 4f 4d 50 52 45 53 53 49 4f 4e  _SET_COMPRESSION
8380: 29 20 61 72 65 20 63 6f 6d 70 61 74 69 62 6c 65  ) are compatible
8390: 20 77 69 74 68 20 61 20 64 61 74 61 62 61 73 65   with a database
83a0: 20 74 68 61 74 20 68 61 73 20 69 74 73 0a 2a 2a   that has its.**
83b0: 20 63 6f 6d 70 72 65 73 73 69 6f 6e 20 69 64 20   compression id 
83c0: 73 65 74 20 74 6f 20 69 52 65 71 2e 20 43 6f 6d  set to iReq. Com
83d0: 70 72 65 73 73 69 6f 6e 20 72 6f 75 74 69 6e 65  pression routine
83e0: 73 20 61 72 65 20 63 6f 6d 70 61 74 69 62 6c 65  s are compatible
83f0: 20 69 66 20 69 52 65 71 0a 2a 2a 20 69 73 20 7a   if iReq.** is z
8400: 65 72 6f 20 28 69 6e 64 69 63 61 74 69 6e 67 20  ero (indicating 
8410: 74 68 65 20 64 61 74 61 62 61 73 65 20 69 73 20  the database is 
8420: 65 6d 70 74 79 29 2c 20 6f 72 20 69 66 20 69 74  empty), or if it
8430: 20 69 73 20 65 71 75 61 6c 20 74 6f 20 74 68 65   is equal to the
8440: 20 0a 2a 2a 20 63 6f 6d 70 72 65 73 73 69 6f 6e   .** compression
8450: 20 69 64 20 6f 66 20 74 68 65 20 63 6f 6e 66 69   id of the confi
8460: 67 75 72 65 64 20 63 6f 6d 70 72 65 73 73 69 6f  gured compressio
8470: 6e 20 72 6f 75 74 69 6e 65 73 2e 0a 2a 2a 0a 2a  n routines..**.*
8480: 2a 20 49 66 20 74 68 65 20 63 68 65 63 6b 20 73  * If the check s
8490: 68 6f 77 73 20 74 68 61 74 20 74 68 65 20 63 75  hows that the cu
84a0: 72 72 65 6e 74 20 63 6f 6d 70 72 65 73 73 69 6f  rrent compressio
84b0: 6e 20 61 72 65 20 69 6e 63 6f 6d 70 61 74 69 62  n are incompatib
84c0: 6c 65 20 61 6e 64 20 74 68 65 72 65 0a 2a 2a 20  le and there.** 
84d0: 69 73 20 61 20 63 6f 6d 70 72 65 73 73 69 6f 6e  is a compression
84e0: 20 66 61 63 74 6f 72 79 20 72 65 67 69 73 74 65   factory registe
84f0: 72 65 64 2c 20 67 69 76 65 20 69 74 20 61 20 63  red, give it a c
8500: 68 61 6e 63 65 20 74 6f 20 69 6e 73 74 61 6c 6c  hance to install
8510: 20 6e 65 77 0a 2a 2a 20 63 6f 6d 70 72 65 73 73   new.** compress
8520: 69 6f 6e 20 72 6f 75 74 69 6e 65 73 2e 0a 2a 2a  ion routines..**
8530: 0a 2a 2a 20 49 66 2c 20 61 66 74 65 72 20 61 6e  .** If, after an
8540: 79 20 72 65 67 69 73 74 65 72 65 64 20 66 61 63  y registered fac
8550: 74 6f 72 79 20 69 73 20 69 6e 76 6f 6b 65 64 2c  tory is invoked,
8560: 20 74 68 65 20 63 6f 6d 70 72 65 73 73 69 6f 6e   the compression
8570: 20 66 75 6e 63 74 69 6f 6e 73 0a 2a 2a 20 61 72   functions.** ar
8580: 65 20 73 74 69 6c 6c 20 69 6e 63 6f 6d 70 61 74  e still incompat
8590: 69 62 6c 65 2c 20 72 65 74 75 72 6e 20 4c 53 4d  ible, return LSM
85a0: 5f 4d 49 53 4d 41 54 43 48 2e 20 4f 74 68 65 72  _MISMATCH. Other
85b0: 77 69 73 65 2c 20 4c 53 4d 5f 4f 4b 2e 0a 2a 2f  wise, LSM_OK..*/
85c0: 0a 69 6e 74 20 6c 73 6d 43 68 65 63 6b 43 6f 6d  .int lsmCheckCom
85d0: 70 72 65 73 73 69 6f 6e 49 64 28 6c 73 6d 5f 64  pressionId(lsm_d
85e0: 62 20 2a 70 44 62 2c 20 75 33 32 20 69 52 65 71  b *pDb, u32 iReq
85f0: 29 7b 0a 20 20 69 66 28 20 69 52 65 71 21 3d 4c  ){.  if( iReq!=L
8600: 53 4d 5f 43 4f 4d 50 52 45 53 53 49 4f 4e 5f 45  SM_COMPRESSION_E
8610: 4d 50 54 59 20 26 26 20 70 44 62 2d 3e 63 6f 6d  MPTY && pDb->com
8620: 70 72 65 73 73 2e 69 49 64 21 3d 69 52 65 71 20  press.iId!=iReq 
8630: 29 7b 0a 20 20 20 20 69 66 28 20 70 44 62 2d 3e  ){.    if( pDb->
8640: 66 61 63 74 6f 72 79 2e 78 46 61 63 74 6f 72 79  factory.xFactory
8650: 20 29 7b 0a 20 20 20 20 20 20 70 44 62 2d 3e 62   ){.      pDb->b
8660: 49 6e 46 61 63 74 6f 72 79 20 3d 20 31 3b 0a 20  InFactory = 1;. 
8670: 20 20 20 20 20 70 44 62 2d 3e 66 61 63 74 6f 72       pDb->factor
8680: 79 2e 78 46 61 63 74 6f 72 79 28 70 44 62 2d 3e  y.xFactory(pDb->
8690: 66 61 63 74 6f 72 79 2e 70 43 74 78 2c 20 70 44  factory.pCtx, pD
86a0: 62 2c 20 69 52 65 71 29 3b 0a 20 20 20 20 20 20  b, iReq);.      
86b0: 70 44 62 2d 3e 62 49 6e 46 61 63 74 6f 72 79 20  pDb->bInFactory 
86c0: 3d 20 30 3b 0a 20 20 20 20 7d 0a 20 20 20 20 69  = 0;.    }.    i
86d0: 66 28 20 70 44 62 2d 3e 63 6f 6d 70 72 65 73 73  f( pDb->compress
86e0: 2e 69 49 64 21 3d 69 52 65 71 20 29 7b 0a 20 20  .iId!=iReq ){.  
86f0: 20 20 20 20 2f 2a 20 49 6e 63 6f 6d 70 61 74 69      /* Incompati
8700: 62 6c 65 20 2a 2f 0a 20 20 20 20 20 20 72 65 74  ble */.      ret
8710: 75 72 6e 20 4c 53 4d 5f 4d 49 53 4d 41 54 43 48  urn LSM_MISMATCH
8720: 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20 2f 2a  ;.    }.  }.  /*
8730: 20 43 6f 6d 70 61 74 69 62 6c 65 20 2a 2f 0a 20   Compatible */. 
8740: 20 72 65 74 75 72 6e 20 4c 53 4d 5f 4f 4b 3b 0a   return LSM_OK;.
8750: 7d 0a 0a 2f 2a 0a 2a 2a 20 42 65 67 69 6e 20 61  }../*.** Begin a
8760: 20 72 65 61 64 20 74 72 61 6e 73 61 63 74 69 6f   read transactio
8770: 6e 2e 20 54 68 69 73 20 66 75 6e 63 74 69 6f 6e  n. This function
8780: 20 69 73 20 61 20 6e 6f 2d 6f 70 20 69 66 20 74   is a no-op if t
8790: 68 65 20 63 6f 6e 6e 65 63 74 69 6f 6e 0a 2a 2a  he connection.**
87a0: 20 70 61 73 73 65 64 20 61 73 20 74 68 65 20 6f   passed as the o
87b0: 6e 6c 79 20 61 72 67 75 6d 65 6e 74 20 61 6c 72  nly argument alr
87c0: 65 61 64 79 20 68 61 73 20 61 6e 20 6f 70 65 6e  eady has an open
87d0: 20 72 65 61 64 20 74 72 61 6e 73 61 63 74 69 6f   read transactio
87e0: 6e 2e 0a 2a 2f 0a 69 6e 74 20 6c 73 6d 42 65 67  n..*/.int lsmBeg
87f0: 69 6e 52 65 61 64 54 72 61 6e 73 28 6c 73 6d 5f  inReadTrans(lsm_
8800: 64 62 20 2a 70 44 62 29 7b 0a 20 20 63 6f 6e 73  db *pDb){.  cons
8810: 74 20 69 6e 74 20 4d 41 58 5f 52 45 41 44 4c 4f  t int MAX_READLO
8820: 43 4b 5f 41 54 54 45 4d 50 54 53 20 3d 20 31 30  CK_ATTEMPTS = 10
8830: 3b 0a 20 20 63 6f 6e 73 74 20 69 6e 74 20 6e 4d  ;.  const int nM
8840: 61 78 41 74 74 65 6d 70 74 20 3d 20 28 70 44 62  axAttempt = (pDb
8850: 2d 3e 62 52 6f 54 72 61 6e 73 20 3f 20 31 20 3a  ->bRoTrans ? 1 :
8860: 20 4d 41 58 5f 52 45 41 44 4c 4f 43 4b 5f 41 54   MAX_READLOCK_AT
8870: 54 45 4d 50 54 53 29 3b 0a 0a 20 20 69 6e 74 20  TEMPTS);..  int 
8880: 72 63 20 3d 20 4c 53 4d 5f 4f 4b 3b 20 20 20 20  rc = LSM_OK;    
8890: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 52              /* R
88a0: 65 74 75 72 6e 20 63 6f 64 65 20 2a 2f 0a 20 20  eturn code */.  
88b0: 69 6e 74 20 69 41 74 74 65 6d 70 74 20 3d 20 30  int iAttempt = 0
88c0: 3b 0a 0a 20 20 61 73 73 65 72 74 28 20 70 44 62  ;..  assert( pDb
88d0: 2d 3e 70 57 6f 72 6b 65 72 3d 3d 30 20 29 3b 0a  ->pWorker==0 );.
88e0: 0a 20 20 77 68 69 6c 65 28 20 72 63 3d 3d 4c 53  .  while( rc==LS
88f0: 4d 5f 4f 4b 20 26 26 20 70 44 62 2d 3e 69 52 65  M_OK && pDb->iRe
8900: 61 64 65 72 3c 30 20 26 26 20 28 69 41 74 74 65  ader<0 && (iAtte
8910: 6d 70 74 2b 2b 29 3c 6e 4d 61 78 41 74 74 65 6d  mpt++)<nMaxAttem
8920: 70 74 20 29 7b 0a 20 20 20 20 69 6e 74 20 69 54  pt ){.    int iT
8930: 72 65 65 68 64 72 20 3d 20 30 3b 0a 20 20 20 20  reehdr = 0;.    
8940: 69 6e 74 20 69 53 6e 61 70 20 3d 20 30 3b 0a 20  int iSnap = 0;. 
8950: 20 20 20 61 73 73 65 72 74 28 20 70 44 62 2d 3e     assert( pDb->
8960: 70 43 73 72 3d 3d 30 20 26 26 20 70 44 62 2d 3e  pCsr==0 && pDb->
8970: 6e 54 72 61 6e 73 4f 70 65 6e 3d 3d 30 20 29 3b  nTransOpen==0 );
8980: 0a 0a 20 20 20 20 2f 2a 20 4c 6f 61 64 20 74 68  ..    /* Load th
8990: 65 20 69 6e 2d 6d 65 6d 6f 72 79 20 74 72 65 65  e in-memory tree
89a0: 20 68 65 61 64 65 72 2e 20 2a 2f 0a 20 20 20 20   header. */.    
89b0: 72 63 20 3d 20 6c 73 6d 54 72 65 65 4c 6f 61 64  rc = lsmTreeLoad
89c0: 48 65 61 64 65 72 28 70 44 62 2c 20 26 69 54 72  Header(pDb, &iTr
89d0: 65 65 68 64 72 29 3b 0a 0a 20 20 20 20 2f 2a 20  eehdr);..    /* 
89e0: 4c 6f 61 64 20 74 68 65 20 64 61 74 61 62 61 73  Load the databas
89f0: 65 20 73 6e 61 70 73 68 6f 74 20 2a 2f 0a 20 20  e snapshot */.  
8a00: 20 20 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b    if( rc==LSM_OK
8a10: 20 29 7b 0a 20 20 20 20 20 20 69 66 28 20 6c 73   ){.      if( ls
8a20: 6d 43 68 65 63 6b 70 6f 69 6e 74 43 6c 69 65 6e  mCheckpointClien
8a30: 74 43 61 63 68 65 4f 6b 28 70 44 62 29 3d 3d 30  tCacheOk(pDb)==0
8a40: 20 29 7b 0a 20 20 20 20 20 20 20 20 6c 73 6d 46   ){.        lsmF
8a50: 72 65 65 53 6e 61 70 73 68 6f 74 28 70 44 62 2d  reeSnapshot(pDb-
8a60: 3e 70 45 6e 76 2c 20 70 44 62 2d 3e 70 43 6c 69  >pEnv, pDb->pCli
8a70: 65 6e 74 29 3b 0a 20 20 20 20 20 20 20 20 70 44  ent);.        pD
8a80: 62 2d 3e 70 43 6c 69 65 6e 74 20 3d 20 30 3b 0a  b->pClient = 0;.
8a90: 20 20 20 20 20 20 20 20 6c 73 6d 4d 43 75 72 73          lsmMCurs
8aa0: 6f 72 46 72 65 65 43 61 63 68 65 28 70 44 62 29  orFreeCache(pDb)
8ab0: 3b 0a 20 20 20 20 20 20 20 20 6c 73 6d 46 73 50  ;.        lsmFsP
8ac0: 75 72 67 65 43 61 63 68 65 28 70 44 62 2d 3e 70  urgeCache(pDb->p
8ad0: 46 53 29 3b 0a 20 20 20 20 20 20 20 20 72 63 20  FS);.        rc 
8ae0: 3d 20 6c 73 6d 43 68 65 63 6b 70 6f 69 6e 74 4c  = lsmCheckpointL
8af0: 6f 61 64 28 70 44 62 2c 20 26 69 53 6e 61 70 29  oad(pDb, &iSnap)
8b00: 3b 0a 20 20 20 20 20 20 7d 65 6c 73 65 7b 0a 20  ;.      }else{. 
8b10: 20 20 20 20 20 20 20 69 53 6e 61 70 20 3d 20 31         iSnap = 1
8b20: 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a  ;.      }.    }.
8b30: 0a 20 20 20 20 2f 2a 20 54 61 6b 65 20 61 20 72  .    /* Take a r
8b40: 65 61 64 2d 6c 6f 63 6b 20 6f 6e 20 74 68 65 20  ead-lock on the 
8b50: 74 72 65 65 20 61 6e 64 20 73 6e 61 70 73 68 6f  tree and snapsho
8b60: 74 20 6a 75 73 74 20 6c 6f 61 64 65 64 2e 20 54  t just loaded. T
8b70: 68 65 6e 20 63 68 65 63 6b 0a 20 20 20 20 2a 2a  hen check.    **
8b80: 20 74 68 61 74 20 74 68 65 20 73 68 61 72 65 64   that the shared
8b90: 2d 6d 65 6d 6f 72 79 20 73 74 69 6c 6c 20 63 6f  -memory still co
8ba0: 6e 74 61 69 6e 73 20 74 68 65 20 73 61 6d 65 20  ntains the same 
8bb0: 76 61 6c 75 65 73 2e 20 49 66 20 73 6f 2c 20 70  values. If so, p
8bc0: 72 6f 63 65 65 64 2e 0a 20 20 20 20 2a 2a 20 4f  roceed..    ** O
8bd0: 74 68 65 72 77 69 73 65 2c 20 72 65 6c 69 6e 71  therwise, relinq
8be0: 75 69 73 68 20 74 68 65 20 72 65 61 64 2d 6c 6f  uish the read-lo
8bf0: 63 6b 20 61 6e 64 20 72 65 74 72 79 20 74 68 65  ck and retry the
8c00: 20 77 68 6f 6c 65 20 70 72 6f 63 65 64 75 72 65   whole procedure
8c10: 0a 20 20 20 20 2a 2a 20 28 73 74 61 72 74 69 6e  .    ** (startin
8c20: 67 20 77 69 74 68 20 6c 6f 61 64 69 6e 67 20 74  g with loading t
8c30: 68 65 20 69 6e 2d 6d 65 6d 6f 72 79 20 74 72 65  he in-memory tre
8c40: 65 20 68 65 61 64 65 72 29 2e 20 20 2a 2f 0a 20  e header).  */. 
8c50: 20 20 20 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f     if( rc==LSM_O
8c60: 4b 20 29 7b 0a 20 20 20 20 20 20 75 33 32 20 69  K ){.      u32 i
8c70: 53 68 6d 4d 61 78 20 3d 20 70 44 62 2d 3e 74 72  ShmMax = pDb->tr
8c80: 65 65 68 64 72 2e 69 55 73 65 64 53 68 6d 69 64  eehdr.iUsedShmid
8c90: 3b 0a 20 20 20 20 20 20 75 33 32 20 69 53 68 6d  ;.      u32 iShm
8ca0: 4d 69 6e 20 3d 20 70 44 62 2d 3e 74 72 65 65 68  Min = pDb->treeh
8cb0: 64 72 2e 69 4e 65 78 74 53 68 6d 69 64 2b 31 2d  dr.iNextShmid+1-
8cc0: 4c 53 4d 5f 4d 41 58 5f 53 48 4d 43 48 55 4e 4b  LSM_MAX_SHMCHUNK
8cd0: 53 3b 0a 20 20 20 20 20 20 72 63 20 3d 20 6c 73  S;.      rc = ls
8ce0: 6d 52 65 61 64 6c 6f 63 6b 28 0a 20 20 20 20 20  mReadlock(.     
8cf0: 20 20 20 20 20 70 44 62 2c 20 6c 73 6d 43 68 65       pDb, lsmChe
8d00: 63 6b 70 6f 69 6e 74 49 64 28 70 44 62 2d 3e 61  ckpointId(pDb->a
8d10: 53 6e 61 70 73 68 6f 74 2c 20 30 29 2c 20 69 53  Snapshot, 0), iS
8d20: 68 6d 4d 69 6e 2c 20 69 53 68 6d 4d 61 78 0a 20  hmMin, iShmMax. 
8d30: 20 20 20 20 20 29 3b 0a 20 20 20 20 20 20 69 66       );.      if
8d40: 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 29 7b 0a  ( rc==LSM_OK ){.
8d50: 20 20 20 20 20 20 20 20 69 66 28 20 6c 73 6d 54          if( lsmT
8d60: 72 65 65 4c 6f 61 64 48 65 61 64 65 72 4f 6b 28  reeLoadHeaderOk(
8d70: 70 44 62 2c 20 69 54 72 65 65 68 64 72 29 0a 20  pDb, iTreehdr). 
8d80: 20 20 20 20 20 20 20 20 26 26 20 6c 73 6d 43 68          && lsmCh
8d90: 65 63 6b 70 6f 69 6e 74 4c 6f 61 64 4f 6b 28 70  eckpointLoadOk(p
8da0: 44 62 2c 20 69 53 6e 61 70 29 0a 20 20 20 20 20  Db, iSnap).     
8db0: 20 20 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20     ){.          
8dc0: 2f 2a 20 52 65 61 64 20 6c 6f 63 6b 20 68 61 73  /* Read lock has
8dd0: 20 62 65 65 6e 20 73 75 63 63 65 73 73 66 75 6c   been successful
8de0: 6c 79 20 6f 62 74 61 69 6e 65 64 2e 20 44 65 73  ly obtained. Des
8df0: 65 72 69 61 6c 69 7a 65 20 74 68 65 20 0a 20 20  erialize the .  
8e00: 20 20 20 20 20 20 20 20 2a 2a 20 63 68 65 63 6b          ** check
8e10: 70 6f 69 6e 74 20 6a 75 73 74 20 6c 6f 61 64 65  point just loade
8e20: 64 2e 20 54 4f 44 4f 3a 20 54 68 69 73 20 77 69  d. TODO: This wi
8e30: 6c 6c 20 62 65 20 72 65 6d 6f 76 65 64 20 61 66  ll be removed af
8e40: 74 65 72 20 0a 20 20 20 20 20 20 20 20 20 20 2a  ter .          *
8e50: 2a 20 6c 73 6d 5f 73 6f 72 74 65 64 2e 63 20 69  * lsm_sorted.c i
8e60: 73 20 63 68 61 6e 67 65 64 20 74 6f 20 77 6f 72  s changed to wor
8e70: 6b 20 64 69 72 65 63 74 6c 79 20 66 72 6f 6d 20  k directly from 
8e80: 74 68 65 20 73 65 72 69 61 6c 69 7a 65 64 0a 20  the serialized. 
8e90: 20 20 20 20 20 20 20 20 20 2a 2a 20 76 65 72 73           ** vers
8ea0: 69 6f 6e 20 6f 66 20 74 68 65 20 73 6e 61 70 73  ion of the snaps
8eb0: 68 6f 74 2e 20 20 2a 2f 0a 20 20 20 20 20 20 20  hot.  */.       
8ec0: 20 20 20 69 66 28 20 70 44 62 2d 3e 70 43 6c 69     if( pDb->pCli
8ed0: 65 6e 74 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20  ent==0 ){.      
8ee0: 20 20 20 20 20 20 72 63 20 3d 20 6c 73 6d 43 68        rc = lsmCh
8ef0: 65 63 6b 70 6f 69 6e 74 44 65 73 65 72 69 61 6c  eckpointDeserial
8f00: 69 7a 65 28 70 44 62 2c 20 30 2c 20 70 44 62 2d  ize(pDb, 0, pDb-
8f10: 3e 61 53 6e 61 70 73 68 6f 74 2c 26 70 44 62 2d  >aSnapshot,&pDb-
8f20: 3e 70 43 6c 69 65 6e 74 29 3b 0a 20 20 20 20 20  >pClient);.     
8f30: 20 20 20 20 20 7d 0a 20 20 20 20 20 20 20 20 20       }.         
8f40: 20 61 73 73 65 72 74 28 20 28 72 63 3d 3d 4c 53   assert( (rc==LS
8f50: 4d 5f 4f 4b 29 3d 3d 28 70 44 62 2d 3e 70 43 6c  M_OK)==(pDb->pCl
8f60: 69 65 6e 74 21 3d 30 29 20 29 3b 0a 20 20 20 20  ient!=0) );.    
8f70: 20 20 20 20 20 20 61 73 73 65 72 74 28 20 70 44        assert( pD
8f80: 62 2d 3e 69 52 65 61 64 65 72 3e 3d 30 20 29 3b  b->iReader>=0 );
8f90: 0a 0a 20 20 20 20 20 20 20 20 20 20 2f 2a 20 43  ..          /* C
8fa0: 68 65 63 6b 20 74 68 61 74 20 74 68 65 20 63 6c  heck that the cl
8fb0: 69 65 6e 74 20 68 61 73 20 74 68 65 20 72 69 67  ient has the rig
8fc0: 68 74 20 63 6f 6d 70 72 65 73 73 69 6f 6e 20 68  ht compression h
8fd0: 6f 6f 6b 73 20 6c 6f 61 64 65 64 2e 0a 20 20 20  ooks loaded..   
8fe0: 20 20 20 20 20 20 20 2a 2a 20 49 66 20 6e 6f 74         ** If not
8ff0: 2c 20 73 65 74 20 72 63 20 74 6f 20 4c 53 4d 5f  , set rc to LSM_
9000: 4d 49 53 4d 41 54 43 48 2e 20 20 2a 2f 0a 20 20  MISMATCH.  */.  
9010: 20 20 20 20 20 20 20 20 69 66 28 20 72 63 3d 3d          if( rc==
9020: 4c 53 4d 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20  LSM_OK ){.      
9030: 20 20 20 20 20 20 72 63 20 3d 20 6c 73 6d 43 68        rc = lsmCh
9040: 65 63 6b 43 6f 6d 70 72 65 73 73 69 6f 6e 49 64  eckCompressionId
9050: 28 70 44 62 2c 20 70 44 62 2d 3e 70 43 6c 69 65  (pDb, pDb->pClie
9060: 6e 74 2d 3e 69 43 6d 70 49 64 29 3b 0a 20 20 20  nt->iCmpId);.   
9070: 20 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 20         }.       
9080: 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 20 20   }else{.        
9090: 20 20 72 63 20 3d 20 64 62 52 65 6c 65 61 73 65    rc = dbRelease
90a0: 52 65 61 64 6c 6f 63 6b 28 70 44 62 29 3b 0a 20  Readlock(pDb);. 
90b0: 20 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 7d         }.      }
90c0: 0a 0a 20 20 20 20 20 20 69 66 28 20 72 63 3d 3d  ..      if( rc==
90d0: 4c 53 4d 5f 42 55 53 59 20 29 7b 0a 20 20 20 20  LSM_BUSY ){.    
90e0: 20 20 20 20 72 63 20 3d 20 4c 53 4d 5f 4f 4b 3b      rc = LSM_OK;
90f0: 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a 23  .      }.    }.#
9100: 69 66 20 30 0a 69 66 28 20 72 63 3d 3d 4c 53 4d  if 0.if( rc==LSM
9110: 5f 4f 4b 20 26 26 20 70 44 62 2d 3e 70 43 6c 69  _OK && pDb->pCli
9120: 65 6e 74 20 29 7b 0a 20 20 66 70 72 69 6e 74 66  ent ){.  fprintf
9130: 28 73 74 64 65 72 72 2c 20 0a 20 20 20 20 20 20  (stderr, .      
9140: 22 72 65 61 64 69 6e 67 20 25 70 3a 20 73 6e 61  "reading %p: sna
9150: 70 73 68 6f 74 3a 25 64 20 75 73 65 64 2d 73 68  pshot:%d used-sh
9160: 6d 69 64 3a 25 64 20 74 72 61 6e 73 2d 69 64 3a  mid:%d trans-id:
9170: 25 64 20 69 4f 6c 64 53 68 6d 69 64 3d 25 64 5c  %d iOldShmid=%d\
9180: 6e 22 2c 0a 20 20 20 20 20 20 28 76 6f 69 64 20  n",.      (void 
9190: 2a 29 70 44 62 2c 0a 20 20 20 20 20 20 28 69 6e  *)pDb,.      (in
91a0: 74 29 70 44 62 2d 3e 70 43 6c 69 65 6e 74 2d 3e  t)pDb->pClient->
91b0: 69 49 64 2c 20 28 69 6e 74 29 70 44 62 2d 3e 74  iId, (int)pDb->t
91c0: 72 65 65 68 64 72 2e 69 55 73 65 64 53 68 6d 69  reehdr.iUsedShmi
91d0: 64 2c 20 0a 20 20 20 20 20 20 28 69 6e 74 29 70  d, .      (int)p
91e0: 44 62 2d 3e 74 72 65 65 68 64 72 2e 72 6f 6f 74  Db->treehdr.root
91f0: 2e 69 54 72 61 6e 73 49 64 2c 0a 20 20 20 20 20  .iTransId,.     
9200: 20 28 69 6e 74 29 70 44 62 2d 3e 74 72 65 65 68   (int)pDb->treeh
9210: 64 72 2e 69 4f 6c 64 53 68 6d 69 64 0a 20 20 29  dr.iOldShmid.  )
9220: 3b 0a 7d 0a 23 65 6e 64 69 66 0a 20 20 7d 0a 0a  ;.}.#endif.  }..
9230: 20 20 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b    if( rc==LSM_OK
9240: 20 29 7b 0a 20 20 20 20 72 63 20 3d 20 6c 73 6d   ){.    rc = lsm
9250: 53 68 6d 43 61 63 68 65 43 68 75 6e 6b 73 28 70  ShmCacheChunks(p
9260: 44 62 2c 20 70 44 62 2d 3e 74 72 65 65 68 64 72  Db, pDb->treehdr
9270: 2e 6e 43 68 75 6e 6b 29 3b 0a 20 20 7d 0a 20 20  .nChunk);.  }.  
9280: 69 66 28 20 72 63 21 3d 4c 53 4d 5f 4f 4b 20 29  if( rc!=LSM_OK )
9290: 7b 0a 20 20 20 20 64 62 52 65 6c 65 61 73 65 52  {.    dbReleaseR
92a0: 65 61 64 6c 6f 63 6b 28 70 44 62 29 3b 0a 20 20  eadlock(pDb);.  
92b0: 7d 0a 20 20 69 66 28 20 70 44 62 2d 3e 70 43 6c  }.  if( pDb->pCl
92c0: 69 65 6e 74 3d 3d 30 20 26 26 20 72 63 3d 3d 4c  ient==0 && rc==L
92d0: 53 4d 5f 4f 4b 20 29 20 72 63 20 3d 20 4c 53 4d  SM_OK ) rc = LSM
92e0: 5f 42 55 53 59 3b 0a 20 20 72 65 74 75 72 6e 20  _BUSY;.  return 
92f0: 72 63 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54 68 69  rc;.}../*.** Thi
9300: 73 20 66 75 6e 63 74 69 6f 6e 20 69 73 20 75 73  s function is us
9310: 65 64 20 62 79 20 61 20 72 65 61 64 2d 77 72 69  ed by a read-wri
9320: 74 65 20 63 6f 6e 6e 65 63 74 69 6f 6e 20 74 6f  te connection to
9330: 20 64 65 74 65 72 6d 69 6e 65 20 69 66 20 74 68   determine if th
9340: 65 72 65 0a 2a 2a 20 61 72 65 20 63 75 72 72 65  ere.** are curre
9350: 6e 74 6c 79 20 6f 6e 65 20 6f 72 20 6d 6f 72 65  ntly one or more
9360: 20 72 65 61 64 2d 6f 6e 6c 79 20 74 72 61 6e 73   read-only trans
9370: 61 63 74 69 6f 6e 73 20 6f 70 65 6e 20 6f 6e 20  actions open on 
9380: 74 68 65 20 64 61 74 61 62 61 73 65 0a 2a 2a 20  the database.** 
9390: 28 69 6e 20 74 68 69 73 20 63 6f 6e 74 65 78 74  (in this context
93a0: 20 61 20 72 65 61 64 2d 6f 6e 6c 79 20 74 72 61   a read-only tra
93b0: 6e 73 61 63 74 69 6f 6e 20 69 73 20 6f 6e 65 20  nsaction is one 
93c0: 6f 70 65 6e 65 64 20 62 79 20 61 20 72 65 61 64  opened by a read
93d0: 2d 6f 6e 6c 79 0a 2a 2a 20 63 6f 6e 6e 65 63 74  -only.** connect
93e0: 69 6f 6e 20 6f 6e 20 61 20 6e 6f 6e 2d 6c 69 76  ion on a non-liv
93f0: 65 20 64 61 74 61 62 61 73 65 29 2e 0a 2a 2a 0a  e database)..**.
9400: 2a 2a 20 49 66 20 6e 6f 20 65 72 72 6f 72 20 6f  ** If no error o
9410: 63 63 75 72 73 2c 20 4c 53 4d 5f 4f 4b 20 69 73  ccurs, LSM_OK is
9420: 20 72 65 74 75 72 6e 65 64 20 61 6e 64 20 2a 70   returned and *p
9430: 62 45 78 69 73 74 73 20 69 73 20 73 65 74 20 74  bExists is set t
9440: 6f 20 74 72 75 65 20 69 66 0a 2a 2a 20 73 6f 6d  o true if.** som
9450: 65 20 6f 74 68 65 72 20 63 6f 6e 6e 65 63 74 69  e other connecti
9460: 6f 6e 20 68 61 73 20 61 20 72 65 61 64 2d 6f 6e  on has a read-on
9470: 6c 79 20 74 72 61 6e 73 61 63 74 69 6f 6e 20 6f  ly transaction o
9480: 70 65 6e 2c 20 6f 72 20 66 61 6c 73 65 20 0a 2a  pen, or false .*
9490: 2a 20 6f 74 68 65 72 77 69 73 65 2e 20 49 66 20  * otherwise. If 
94a0: 61 6e 20 65 72 72 6f 72 20 6f 63 63 75 72 73 20  an error occurs 
94b0: 61 6e 20 4c 53 4d 20 65 72 72 6f 72 20 63 6f 64  an LSM error cod
94c0: 65 20 69 73 20 72 65 74 75 72 6e 65 64 20 61 6e  e is returned an
94d0: 64 20 74 68 65 20 66 69 6e 61 6c 0a 2a 2a 20 76  d the final.** v
94e0: 61 6c 75 65 20 6f 66 20 2a 70 62 45 78 69 73 74  alue of *pbExist
94f0: 20 69 73 20 75 6e 64 65 66 69 6e 65 64 2e 0a 2a   is undefined..*
9500: 2f 0a 69 6e 74 20 6c 73 6d 44 65 74 65 63 74 52  /.int lsmDetectR
9510: 6f 54 72 61 6e 73 28 6c 73 6d 5f 64 62 20 2a 64  oTrans(lsm_db *d
9520: 62 2c 20 69 6e 74 20 2a 70 62 45 78 69 73 74 29  b, int *pbExist)
9530: 7b 0a 20 20 69 6e 74 20 72 63 3b 0a 0a 20 20 2f  {.  int rc;..  /
9540: 2a 20 4f 6e 6c 79 20 61 20 72 65 61 64 2d 77 72  * Only a read-wr
9550: 69 74 65 20 63 6f 6e 6e 65 63 74 69 6f 6e 20 6d  ite connection m
9560: 61 79 20 75 73 65 20 74 68 69 73 20 66 75 6e 63  ay use this func
9570: 74 69 6f 6e 2e 20 2a 2f 0a 20 20 61 73 73 65 72  tion. */.  asser
9580: 74 28 20 64 62 2d 3e 62 52 65 61 64 6f 6e 6c 79  t( db->bReadonly
9590: 3d 3d 30 20 29 3b 0a 0a 20 20 72 63 20 3d 20 6c  ==0 );..  rc = l
95a0: 73 6d 53 68 6d 54 65 73 74 4c 6f 63 6b 28 64 62  smShmTestLock(db
95b0: 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 52 4f 54 52 41  , LSM_LOCK_ROTRA
95c0: 4e 53 2c 20 31 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f  NS, 1, LSM_LOCK_
95d0: 45 58 43 4c 29 3b 0a 20 20 69 66 28 20 72 63 3d  EXCL);.  if( rc=
95e0: 3d 4c 53 4d 5f 42 55 53 59 20 29 7b 0a 20 20 20  =LSM_BUSY ){.   
95f0: 20 2a 70 62 45 78 69 73 74 20 3d 20 31 3b 0a 20   *pbExist = 1;. 
9600: 20 20 20 72 63 20 3d 20 4c 53 4d 5f 4f 4b 3b 0a     rc = LSM_OK;.
9610: 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 2a 70 62    }else{.    *pb
9620: 45 78 69 73 74 20 3d 20 30 3b 0a 20 20 7d 0a 0a  Exist = 0;.  }..
9630: 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a    return rc;.}..
9640: 2f 2a 0a 2a 2a 20 64 62 20 69 73 20 61 20 72 65  /*.** db is a re
9650: 61 64 2d 6f 6e 6c 79 20 64 61 74 61 62 61 73 65  ad-only database
9660: 20 68 61 6e 64 6c 65 20 69 6e 20 74 68 65 20 64   handle in the d
9670: 69 73 63 6f 6e 6e 65 63 74 65 64 20 73 74 61 74  isconnected stat
9680: 65 2e 20 54 68 69 73 20 66 75 6e 63 74 69 6f 6e  e. This function
9690: 0a 2a 2a 20 61 74 74 65 6d 70 74 73 20 74 6f 20  .** attempts to 
96a0: 6f 70 65 6e 20 61 20 72 65 61 64 2d 74 72 61 6e  open a read-tran
96b0: 73 61 63 74 69 6f 6e 20 6f 6e 20 74 68 65 20 64  saction on the d
96c0: 61 74 61 62 61 73 65 2e 20 54 68 69 73 20 6d 61  atabase. This ma
96d0: 79 20 69 6e 76 6f 6c 76 65 0a 2a 2a 20 63 6f 6e  y involve.** con
96e0: 6e 65 63 74 69 6e 67 20 74 6f 20 74 68 65 20 64  necting to the d
96f0: 61 74 61 62 61 73 65 20 73 79 73 74 65 6d 20 28  atabase system (
9700: 6f 70 65 6e 69 6e 67 20 73 68 61 72 65 64 20 6d  opening shared m
9710: 65 6d 6f 72 79 20 65 74 63 2e 29 2e 0a 2a 2f 0a  emory etc.)..*/.
9720: 69 6e 74 20 6c 73 6d 42 65 67 69 6e 52 6f 54 72  int lsmBeginRoTr
9730: 61 6e 73 28 6c 73 6d 5f 64 62 20 2a 64 62 29 7b  ans(lsm_db *db){
9740: 0a 20 20 69 6e 74 20 72 63 20 3d 20 4c 53 4d 5f  .  int rc = LSM_
9750: 4f 4b 3b 0a 0a 20 20 61 73 73 65 72 74 28 20 64  OK;..  assert( d
9760: 62 2d 3e 62 52 65 61 64 6f 6e 6c 79 20 26 26 20  b->bReadonly && 
9770: 64 62 2d 3e 70 53 68 6d 68 64 72 3d 3d 30 20 29  db->pShmhdr==0 )
9780: 3b 0a 20 20 61 73 73 65 72 74 28 20 64 62 2d 3e  ;.  assert( db->
9790: 69 52 65 61 64 65 72 3c 30 20 29 3b 0a 0a 20 20  iReader<0 );..  
97a0: 69 66 28 20 64 62 2d 3e 62 52 6f 54 72 61 6e 73  if( db->bRoTrans
97b0: 3d 3d 30 20 29 7b 0a 0a 20 20 20 20 2f 2a 20 41  ==0 ){..    /* A
97c0: 74 74 65 6d 70 74 20 61 20 73 68 61 72 65 64 2d  ttempt a shared-
97d0: 6c 6f 63 6b 20 6f 6e 20 44 4d 53 31 2e 20 2a 2f  lock on DMS1. */
97e0: 0a 20 20 20 20 72 63 20 3d 20 6c 73 6d 53 68 6d  .    rc = lsmShm
97f0: 4c 6f 63 6b 28 64 62 2c 20 4c 53 4d 5f 4c 4f 43  Lock(db, LSM_LOC
9800: 4b 5f 44 4d 53 31 2c 20 4c 53 4d 5f 4c 4f 43 4b  K_DMS1, LSM_LOCK
9810: 5f 53 48 41 52 45 44 2c 20 30 29 3b 0a 20 20 20  _SHARED, 0);.   
9820: 20 69 66 28 20 72 63 21 3d 4c 53 4d 5f 4f 4b 20   if( rc!=LSM_OK 
9830: 29 20 72 65 74 75 72 6e 20 72 63 3b 0a 0a 20 20  ) return rc;..  
9840: 20 20 72 63 20 3d 20 6c 73 6d 53 68 6d 54 65 73    rc = lsmShmTes
9850: 74 4c 6f 63 6b 28 0a 20 20 20 20 20 20 20 20 64  tLock(.        d
9860: 62 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 52 57 43 4c  b, LSM_LOCK_RWCL
9870: 49 45 4e 54 28 30 29 2c 20 4c 53 4d 5f 4c 4f 43  IENT(0), LSM_LOC
9880: 4b 5f 4e 52 45 41 44 45 52 2c 20 4c 53 4d 5f 4c  K_NREADER, LSM_L
9890: 4f 43 4b 5f 53 48 41 52 45 44 0a 20 20 20 20 29  OCK_SHARED.    )
98a0: 3b 0a 20 20 20 20 69 66 28 20 72 63 3d 3d 4c 53  ;.    if( rc==LS
98b0: 4d 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 2f 2a  M_OK ){.      /*
98c0: 20 53 79 73 74 65 6d 20 69 73 20 6e 6f 74 20 6c   System is not l
98d0: 69 76 65 2e 20 54 61 6b 65 20 61 20 53 48 41 52  ive. Take a SHAR
98e0: 45 44 20 6c 6f 63 6b 20 6f 6e 20 74 68 65 20 52  ED lock on the R
98f0: 4f 54 52 41 4e 53 20 62 79 74 65 20 61 6e 64 0a  OTRANS byte and.
9900: 20 20 20 20 20 20 2a 2a 20 72 65 6c 65 61 73 65        ** release
9910: 20 44 4d 53 31 2e 20 4c 6f 63 6b 69 6e 67 20 52   DMS1. Locking R
9920: 4f 54 52 41 4e 53 20 74 65 6c 6c 73 20 61 6c 6c  OTRANS tells all
9930: 20 72 65 61 64 2d 77 72 69 74 65 20 63 6c 69 65   read-write clie
9940: 6e 74 73 20 74 68 61 74 20 74 68 65 79 0a 20 20  nts that they.  
9950: 20 20 20 20 2a 2a 20 6d 61 79 20 6e 6f 74 20 72      ** may not r
9960: 65 63 79 63 6c 65 20 61 6e 79 20 64 69 73 6b 20  ecycle any disk 
9970: 73 70 61 63 65 20 66 72 6f 6d 20 77 69 74 68 69  space from withi
9980: 6e 20 74 68 65 20 64 61 74 61 62 61 73 65 20 6f  n the database o
9990: 72 20 6c 6f 67 20 66 69 6c 65 73 2c 0a 20 20 20  r log files,.   
99a0: 20 20 20 2a 2a 20 61 73 20 61 20 72 65 61 64 2d     ** as a read-
99b0: 6f 6e 6c 79 20 63 6c 69 65 6e 74 20 6d 61 79 20  only client may 
99c0: 62 65 20 75 73 69 6e 67 20 69 74 2e 20 20 2a 2f  be using it.  */
99d0: 0a 20 20 20 20 20 20 72 63 20 3d 20 6c 73 6d 53  .      rc = lsmS
99e0: 68 6d 4c 6f 63 6b 28 64 62 2c 20 4c 53 4d 5f 4c  hmLock(db, LSM_L
99f0: 4f 43 4b 5f 52 4f 54 52 41 4e 53 2c 20 4c 53 4d  OCK_ROTRANS, LSM
9a00: 5f 4c 4f 43 4b 5f 53 48 41 52 45 44 2c 20 30 29  _LOCK_SHARED, 0)
9a10: 3b 0a 20 20 20 20 20 20 6c 73 6d 53 68 6d 4c 6f  ;.      lsmShmLo
9a20: 63 6b 28 64 62 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f  ck(db, LSM_LOCK_
9a30: 44 4d 53 31 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 55  DMS1, LSM_LOCK_U
9a40: 4e 4c 4f 43 4b 2c 20 30 29 3b 0a 0a 20 20 20 20  NLOCK, 0);..    
9a50: 20 20 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b    if( rc==LSM_OK
9a60: 20 29 7b 0a 20 20 20 20 20 20 20 20 64 62 2d 3e   ){.        db->
9a70: 62 52 6f 54 72 61 6e 73 20 3d 20 31 3b 0a 20 20  bRoTrans = 1;.  
9a80: 20 20 20 20 20 20 72 63 20 3d 20 6c 73 6d 53 68        rc = lsmSh
9a90: 6d 43 61 63 68 65 43 68 75 6e 6b 73 28 64 62 2c  mCacheChunks(db,
9aa0: 20 31 29 3b 0a 20 20 20 20 20 20 20 20 69 66 28   1);.        if(
9ab0: 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 29 7b 0a 20   rc==LSM_OK ){. 
9ac0: 20 20 20 20 20 20 20 20 20 64 62 2d 3e 70 53 68           db->pSh
9ad0: 6d 68 64 72 20 3d 20 28 53 68 6d 48 65 61 64 65  mhdr = (ShmHeade
9ae0: 72 20 2a 29 64 62 2d 3e 61 70 53 68 6d 5b 30 5d  r *)db->apShm[0]
9af0: 3b 0a 20 20 20 20 20 20 20 20 20 20 6d 65 6d 73  ;.          mems
9b00: 65 74 28 64 62 2d 3e 70 53 68 6d 68 64 72 2c 20  et(db->pShmhdr, 
9b10: 30 2c 20 73 69 7a 65 6f 66 28 53 68 6d 48 65 61  0, sizeof(ShmHea
9b20: 64 65 72 29 29 3b 0a 20 20 20 20 20 20 20 20 20  der));.         
9b30: 20 72 63 20 3d 20 6c 73 6d 43 68 65 63 6b 70 6f   rc = lsmCheckpo
9b40: 69 6e 74 52 65 63 6f 76 65 72 28 64 62 29 3b 0a  intRecover(db);.
9b50: 20 20 20 20 20 20 20 20 20 20 69 66 28 20 72 63            if( rc
9b60: 3d 3d 4c 53 4d 5f 4f 4b 20 29 7b 0a 20 20 20 20  ==LSM_OK ){.    
9b70: 20 20 20 20 20 20 20 20 72 63 20 3d 20 6c 73 6d          rc = lsm
9b80: 4c 6f 67 52 65 63 6f 76 65 72 28 64 62 29 3b 0a  LogRecover(db);.
9b90: 20 20 20 20 20 20 20 20 20 20 7d 0a 20 20 20 20            }.    
9ba0: 20 20 20 20 7d 0a 20 20 20 20 20 20 7d 0a 20 20      }.      }.  
9bb0: 20 20 7d 65 6c 73 65 20 69 66 28 20 72 63 3d 3d    }else if( rc==
9bc0: 4c 53 4d 5f 42 55 53 59 20 29 7b 0a 20 20 20 20  LSM_BUSY ){.    
9bd0: 20 20 2f 2a 20 53 79 73 74 65 6d 20 69 73 20 6c    /* System is l
9be0: 69 76 65 21 20 2a 2f 0a 20 20 20 20 20 20 72 63  ive! */.      rc
9bf0: 20 3d 20 6c 73 6d 53 68 6d 4c 6f 63 6b 28 64 62   = lsmShmLock(db
9c00: 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 44 4d 53 33 2c  , LSM_LOCK_DMS3,
9c10: 20 4c 53 4d 5f 4c 4f 43 4b 5f 53 48 41 52 45 44   LSM_LOCK_SHARED
9c20: 2c 20 30 29 3b 0a 20 20 20 20 20 20 6c 73 6d 53  , 0);.      lsmS
9c30: 68 6d 4c 6f 63 6b 28 64 62 2c 20 4c 53 4d 5f 4c  hmLock(db, LSM_L
9c40: 4f 43 4b 5f 44 4d 53 31 2c 20 4c 53 4d 5f 4c 4f  OCK_DMS1, LSM_LO
9c50: 43 4b 5f 55 4e 4c 4f 43 4b 2c 20 30 29 3b 0a 20  CK_UNLOCK, 0);. 
9c60: 20 20 20 20 20 69 66 28 20 72 63 3d 3d 4c 53 4d       if( rc==LSM
9c70: 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 20 20 72  _OK ){.        r
9c80: 63 20 3d 20 6c 73 6d 53 68 6d 43 61 63 68 65 43  c = lsmShmCacheC
9c90: 68 75 6e 6b 73 28 64 62 2c 20 31 29 3b 0a 20 20  hunks(db, 1);.  
9ca0: 20 20 20 20 20 20 69 66 28 20 72 63 3d 3d 4c 53        if( rc==LS
9cb0: 4d 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 20 20  M_OK ){.        
9cc0: 20 20 64 62 2d 3e 70 53 68 6d 68 64 72 20 3d 20    db->pShmhdr = 
9cd0: 28 53 68 6d 48 65 61 64 65 72 20 2a 29 64 62 2d  (ShmHeader *)db-
9ce0: 3e 61 70 53 68 6d 5b 30 5d 3b 0a 20 20 20 20 20  >apShm[0];.     
9cf0: 20 20 20 7d 0a 20 20 20 20 20 20 7d 0a 20 20 20     }.      }.   
9d00: 20 7d 0a 0a 20 20 20 20 69 66 28 20 72 63 3d 3d   }..    if( rc==
9d10: 4c 53 4d 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20  LSM_OK ){.      
9d20: 72 63 20 3d 20 6c 73 6d 42 65 67 69 6e 52 65 61  rc = lsmBeginRea
9d30: 64 54 72 61 6e 73 28 64 62 29 3b 0a 20 20 20 20  dTrans(db);.    
9d40: 7d 0a 20 20 7d 0a 0a 20 20 72 65 74 75 72 6e 20  }.  }..  return 
9d50: 72 63 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 43 6c 6f  rc;.}../*.** Clo
9d60: 73 65 20 74 68 65 20 63 75 72 72 65 6e 74 6c 79  se the currently
9d70: 20 6f 70 65 6e 20 72 65 61 64 20 74 72 61 6e 73   open read trans
9d80: 61 63 74 69 6f 6e 2e 0a 2a 2f 0a 76 6f 69 64 20  action..*/.void 
9d90: 6c 73 6d 46 69 6e 69 73 68 52 65 61 64 54 72 61  lsmFinishReadTra
9da0: 6e 73 28 6c 73 6d 5f 64 62 20 2a 70 44 62 29 7b  ns(lsm_db *pDb){
9db0: 0a 0a 20 20 2f 2a 20 57 6f 72 6b 65 72 20 63 6f  ..  /* Worker co
9dc0: 6e 6e 65 63 74 69 6f 6e 73 20 73 68 6f 75 6c 64  nnections should
9dd0: 20 6e 6f 74 20 62 65 20 63 6c 6f 73 69 6e 67 20   not be closing 
9de0: 72 65 61 64 20 74 72 61 6e 73 61 63 74 69 6f 6e  read transaction
9df0: 73 2e 20 41 6e 64 0a 20 20 2a 2a 20 72 65 61 64  s. And.  ** read
9e00: 20 74 72 61 6e 73 61 63 74 69 6f 6e 73 20 73 68   transactions sh
9e10: 6f 75 6c 64 20 6f 6e 6c 79 20 62 65 20 63 6c 6f  ould only be clo
9e20: 73 65 64 20 61 66 74 65 72 20 61 6c 6c 20 63 75  sed after all cu
9e30: 72 73 6f 72 73 20 61 6e 64 20 77 72 69 74 65 0a  rsors and write.
9e40: 20 20 2a 2a 20 74 72 61 6e 73 61 63 74 69 6f 6e    ** transaction
9e50: 73 20 68 61 76 65 20 62 65 65 6e 20 63 6c 6f 73  s have been clos
9e60: 65 64 2e 20 46 69 6e 61 6c 6c 79 20 70 43 6c 69  ed. Finally pCli
9e70: 65 6e 74 20 73 68 6f 75 6c 64 20 62 65 20 6e 6f  ent should be no
9e80: 6e 2d 4e 55 4c 4c 0a 20 20 2a 2a 20 6f 6e 6c 79  n-NULL.  ** only
9e90: 20 69 66 66 20 70 44 62 2d 3e 69 52 65 61 64 65   iff pDb->iReade
9ea0: 72 3e 3d 30 2e 20 20 2a 2f 0a 20 20 61 73 73 65  r>=0.  */.  asse
9eb0: 72 74 28 20 70 44 62 2d 3e 70 57 6f 72 6b 65 72  rt( pDb->pWorker
9ec0: 3d 3d 30 20 29 3b 0a 20 20 61 73 73 65 72 74 28  ==0 );.  assert(
9ed0: 20 70 44 62 2d 3e 70 43 73 72 3d 3d 30 20 26 26   pDb->pCsr==0 &&
9ee0: 20 70 44 62 2d 3e 6e 54 72 61 6e 73 4f 70 65 6e   pDb->nTransOpen
9ef0: 3d 3d 30 20 29 3b 0a 0a 20 20 69 66 28 20 70 44  ==0 );..  if( pD
9f00: 62 2d 3e 62 52 6f 54 72 61 6e 73 20 29 7b 0a 20  b->bRoTrans ){. 
9f10: 20 20 20 69 6e 74 20 69 3b 0a 20 20 20 20 66 6f     int i;.    fo
9f20: 72 28 69 3d 30 3b 20 69 3c 70 44 62 2d 3e 6e 53  r(i=0; i<pDb->nS
9f30: 68 6d 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 20 20  hm; i++){.      
9f40: 6c 73 6d 46 72 65 65 28 70 44 62 2d 3e 70 45 6e  lsmFree(pDb->pEn
9f50: 76 2c 20 70 44 62 2d 3e 61 70 53 68 6d 5b 69 5d  v, pDb->apShm[i]
9f60: 29 3b 0a 20 20 20 20 7d 0a 20 20 20 20 6c 73 6d  );.    }.    lsm
9f70: 46 72 65 65 28 70 44 62 2d 3e 70 45 6e 76 2c 20  Free(pDb->pEnv, 
9f80: 70 44 62 2d 3e 61 70 53 68 6d 29 3b 0a 20 20 20  pDb->apShm);.   
9f90: 20 70 44 62 2d 3e 61 70 53 68 6d 20 3d 20 30 3b   pDb->apShm = 0;
9fa0: 0a 20 20 20 20 70 44 62 2d 3e 6e 53 68 6d 20 3d  .    pDb->nShm =
9fb0: 20 30 3b 0a 20 20 20 20 70 44 62 2d 3e 70 53 68   0;.    pDb->pSh
9fc0: 6d 68 64 72 20 3d 20 30 3b 0a 0a 20 20 20 20 6c  mhdr = 0;..    l
9fd0: 73 6d 53 68 6d 4c 6f 63 6b 28 70 44 62 2c 20 4c  smShmLock(pDb, L
9fe0: 53 4d 5f 4c 4f 43 4b 5f 52 4f 54 52 41 4e 53 2c  SM_LOCK_ROTRANS,
9ff0: 20 4c 53 4d 5f 4c 4f 43 4b 5f 55 4e 4c 4f 43 4b   LSM_LOCK_UNLOCK
a000: 2c 20 30 29 3b 0a 20 20 7d 0a 20 20 64 62 52 65  , 0);.  }.  dbRe
a010: 6c 65 61 73 65 52 65 61 64 6c 6f 63 6b 28 70 44  leaseReadlock(pD
a020: 62 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 4f 70 65  b);.}../*.** Ope
a030: 6e 20 61 20 77 72 69 74 65 20 74 72 61 6e 73 61  n a write transa
a040: 63 74 69 6f 6e 2e 0a 2a 2f 0a 69 6e 74 20 6c 73  ction..*/.int ls
a050: 6d 42 65 67 69 6e 57 72 69 74 65 54 72 61 6e 73  mBeginWriteTrans
a060: 28 6c 73 6d 5f 64 62 20 2a 70 44 62 29 7b 0a 20  (lsm_db *pDb){. 
a070: 20 69 6e 74 20 72 63 20 3d 20 4c 53 4d 5f 4f 4b   int rc = LSM_OK
a080: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ;               
a090: 20 2f 2a 20 52 65 74 75 72 6e 20 63 6f 64 65 20   /* Return code 
a0a0: 2a 2f 0a 20 20 53 68 6d 48 65 61 64 65 72 20 2a  */.  ShmHeader *
a0b0: 70 53 68 6d 20 3d 20 70 44 62 2d 3e 70 53 68 6d  pShm = pDb->pShm
a0c0: 68 64 72 3b 20 2f 2a 20 53 68 61 72 65 64 20 6d  hdr; /* Shared m
a0d0: 65 6d 6f 72 79 20 68 65 61 64 65 72 20 2a 2f 0a  emory header */.
a0e0: 0a 20 20 61 73 73 65 72 74 28 20 70 44 62 2d 3e  .  assert( pDb->
a0f0: 6e 54 72 61 6e 73 4f 70 65 6e 3d 3d 30 20 29 3b  nTransOpen==0 );
a100: 0a 20 20 61 73 73 65 72 74 28 20 70 44 62 2d 3e  .  assert( pDb->
a110: 62 44 69 73 63 61 72 64 4f 6c 64 3d 3d 30 20 29  bDiscardOld==0 )
a120: 3b 0a 20 20 61 73 73 65 72 74 28 20 70 44 62 2d  ;.  assert( pDb-
a130: 3e 62 52 65 61 64 6f 6e 6c 79 3d 3d 30 20 29 3b  >bReadonly==0 );
a140: 0a 0a 20 20 2f 2a 20 49 66 20 74 68 65 72 65 20  ..  /* If there 
a150: 69 73 20 6e 6f 20 72 65 61 64 2d 74 72 61 6e 73  is no read-trans
a160: 61 63 74 69 6f 6e 20 6f 70 65 6e 2c 20 6f 70 65  action open, ope
a170: 6e 20 6f 6e 65 20 6e 6f 77 2e 20 2a 2f 0a 20 20  n one now. */.  
a180: 69 66 28 20 70 44 62 2d 3e 69 52 65 61 64 65 72  if( pDb->iReader
a190: 3c 30 20 29 7b 0a 20 20 20 20 72 63 20 3d 20 6c  <0 ){.    rc = l
a1a0: 73 6d 42 65 67 69 6e 52 65 61 64 54 72 61 6e 73  smBeginReadTrans
a1b0: 28 70 44 62 29 3b 0a 20 20 7d 0a 0a 20 20 2f 2a  (pDb);.  }..  /*
a1c0: 20 41 74 74 65 6d 70 74 20 74 6f 20 74 61 6b 65   Attempt to take
a1d0: 20 74 68 65 20 57 52 49 54 45 52 20 6c 6f 63 6b   the WRITER lock
a1e0: 20 2a 2f 0a 20 20 69 66 28 20 72 63 3d 3d 4c 53   */.  if( rc==LS
a1f0: 4d 5f 4f 4b 20 29 7b 0a 20 20 20 20 72 63 20 3d  M_OK ){.    rc =
a200: 20 6c 73 6d 53 68 6d 4c 6f 63 6b 28 70 44 62 2c   lsmShmLock(pDb,
a210: 20 4c 53 4d 5f 4c 4f 43 4b 5f 57 52 49 54 45 52   LSM_LOCK_WRITER
a220: 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 45 58 43 4c 2c  , LSM_LOCK_EXCL,
a230: 20 30 29 3b 0a 20 20 7d 0a 0a 20 20 2f 2a 20 49   0);.  }..  /* I
a240: 66 20 74 68 65 20 70 72 65 76 69 6f 75 73 20 77  f the previous w
a250: 72 69 74 65 72 20 66 61 69 6c 65 64 20 6d 69 64  riter failed mid
a260: 2d 74 72 61 6e 73 61 63 74 69 6f 6e 2c 20 72 75  -transaction, ru
a270: 6e 20 65 6d 65 72 67 65 6e 63 79 20 72 6f 6c 6c  n emergency roll
a280: 62 61 63 6b 2e 20 2a 2f 0a 20 20 69 66 28 20 72  back. */.  if( r
a290: 63 3d 3d 4c 53 4d 5f 4f 4b 20 26 26 20 70 53 68  c==LSM_OK && pSh
a2a0: 6d 2d 3e 62 57 72 69 74 65 72 20 29 7b 0a 20 20  m->bWriter ){.  
a2b0: 20 20 72 63 20 3d 20 6c 73 6d 54 72 65 65 52 65    rc = lsmTreeRe
a2c0: 70 61 69 72 28 70 44 62 29 3b 0a 20 20 20 20 69  pair(pDb);.    i
a2d0: 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 29 20  f( rc==LSM_OK ) 
a2e0: 70 53 68 6d 2d 3e 62 57 72 69 74 65 72 20 3d 20  pShm->bWriter = 
a2f0: 30 3b 0a 20 20 7d 0a 0a 20 20 2f 2a 20 43 68 65  0;.  }..  /* Che
a300: 63 6b 20 74 68 61 74 20 74 68 69 73 20 63 6f 6e  ck that this con
a310: 6e 65 63 74 69 6f 6e 20 69 73 20 63 75 72 72 65  nection is curre
a320: 6e 74 6c 79 20 72 65 61 64 69 6e 67 20 66 72 6f  ntly reading fro
a330: 6d 20 74 68 65 20 6d 6f 73 74 20 72 65 63 65 6e  m the most recen
a340: 74 0a 20 20 2a 2a 20 76 65 72 73 69 6f 6e 20 6f  t.  ** version o
a350: 66 20 74 68 65 20 64 61 74 61 62 61 73 65 2e 20  f the database. 
a360: 49 66 20 6e 6f 74 2c 20 72 65 74 75 72 6e 20 4c  If not, return L
a370: 53 4d 5f 42 55 53 59 2e 20 20 2a 2f 0a 20 20 69  SM_BUSY.  */.  i
a380: 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 26 26  f( rc==LSM_OK &&
a390: 20 6d 65 6d 63 6d 70 28 26 70 53 68 6d 2d 3e 68   memcmp(&pShm->h
a3a0: 64 72 31 2c 20 26 70 44 62 2d 3e 74 72 65 65 68  dr1, &pDb->treeh
a3b0: 64 72 2c 20 73 69 7a 65 6f 66 28 54 72 65 65 48  dr, sizeof(TreeH
a3c0: 65 61 64 65 72 29 29 20 29 7b 0a 20 20 20 20 72  eader)) ){.    r
a3d0: 63 20 3d 20 4c 53 4d 5f 42 55 53 59 3b 0a 20 20  c = LSM_BUSY;.  
a3e0: 7d 0a 0a 20 20 69 66 28 20 72 63 3d 3d 4c 53 4d  }..  if( rc==LSM
a3f0: 5f 4f 4b 20 29 7b 0a 20 20 20 20 72 63 20 3d 20  _OK ){.    rc = 
a400: 6c 73 6d 4c 6f 67 42 65 67 69 6e 28 70 44 62 29  lsmLogBegin(pDb)
a410: 3b 0a 20 20 7d 0a 0a 20 20 2f 2a 20 49 66 20 65  ;.  }..  /* If e
a420: 76 65 72 79 74 68 69 6e 67 20 77 61 73 20 73 75  verything was su
a430: 63 63 65 73 73 66 75 6c 2c 20 73 65 74 20 74 68  ccessful, set th
a440: 65 20 22 74 72 61 6e 73 61 63 74 69 6f 6e 2d 69  e "transaction-i
a450: 6e 2d 70 72 6f 67 72 65 73 73 22 20 66 6c 61 67  n-progress" flag
a460: 0a 20 20 2a 2a 20 61 6e 64 20 72 65 74 75 72 6e  .  ** and return
a470: 20 4c 53 4d 5f 4f 4b 2e 20 4f 74 68 65 72 77 69   LSM_OK. Otherwi
a480: 73 65 2c 20 69 66 20 73 6f 6d 65 20 65 72 72 6f  se, if some erro
a490: 72 20 6f 63 63 75 72 72 65 64 2c 20 72 65 6c 69  r occurred, reli
a4a0: 6e 71 75 69 73 68 20 74 68 65 20 0a 20 20 2a 2a  nquish the .  **
a4b0: 20 57 52 49 54 45 52 20 6c 6f 63 6b 20 61 6e 64   WRITER lock and
a4c0: 20 72 65 74 75 72 6e 20 61 6e 20 65 72 72 6f 72   return an error
a4d0: 20 63 6f 64 65 2e 20 20 2a 2f 0a 20 20 69 66 28   code.  */.  if(
a4e0: 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 29 7b 0a 20   rc==LSM_OK ){. 
a4f0: 20 20 20 54 72 65 65 48 65 61 64 65 72 20 2a 70     TreeHeader *p
a500: 20 3d 20 26 70 44 62 2d 3e 74 72 65 65 68 64 72   = &pDb->treehdr
a510: 3b 0a 20 20 20 20 70 53 68 6d 2d 3e 62 57 72 69  ;.    pShm->bWri
a520: 74 65 72 20 3d 20 31 3b 0a 20 20 20 20 70 2d 3e  ter = 1;.    p->
a530: 72 6f 6f 74 2e 69 54 72 61 6e 73 49 64 2b 2b 3b  root.iTransId++;
a540: 0a 20 20 20 20 69 66 28 20 6c 73 6d 54 72 65 65  .    if( lsmTree
a550: 48 61 73 4f 6c 64 28 70 44 62 29 20 26 26 20 70  HasOld(pDb) && p
a560: 2d 3e 69 4f 6c 64 4c 6f 67 3d 3d 70 44 62 2d 3e  ->iOldLog==pDb->
a570: 70 43 6c 69 65 6e 74 2d 3e 69 4c 6f 67 4f 66 66  pClient->iLogOff
a580: 20 29 7b 0a 20 20 20 20 20 20 6c 73 6d 54 72 65   ){.      lsmTre
a590: 65 44 69 73 63 61 72 64 4f 6c 64 28 70 44 62 29  eDiscardOld(pDb)
a5a0: 3b 0a 20 20 20 20 20 20 70 44 62 2d 3e 62 44 69  ;.      pDb->bDi
a5b0: 73 63 61 72 64 4f 6c 64 20 3d 20 31 3b 0a 20 20  scardOld = 1;.  
a5c0: 20 20 7d 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20    }.  }else{.   
a5d0: 20 6c 73 6d 53 68 6d 4c 6f 63 6b 28 70 44 62 2c   lsmShmLock(pDb,
a5e0: 20 4c 53 4d 5f 4c 4f 43 4b 5f 57 52 49 54 45 52   LSM_LOCK_WRITER
a5f0: 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 55 4e 4c 4f 43  , LSM_LOCK_UNLOC
a600: 4b 2c 20 30 29 3b 0a 20 20 20 20 69 66 28 20 70  K, 0);.    if( p
a610: 44 62 2d 3e 70 43 73 72 3d 3d 30 20 29 20 6c 73  Db->pCsr==0 ) ls
a620: 6d 46 69 6e 69 73 68 52 65 61 64 54 72 61 6e 73  mFinishReadTrans
a630: 28 70 44 62 29 3b 0a 20 20 7d 0a 20 20 72 65 74  (pDb);.  }.  ret
a640: 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a  urn rc;.}../*.**
a650: 20 45 6e 64 20 74 68 65 20 63 75 72 72 65 6e 74   End the current
a660: 20 77 72 69 74 65 20 74 72 61 6e 73 61 63 74 69   write transacti
a670: 6f 6e 2e 20 54 68 65 20 63 6f 6e 6e 65 63 74 69  on. The connecti
a680: 6f 6e 20 69 73 20 6c 65 66 74 20 77 69 74 68 20  on is left with 
a690: 61 6e 20 6f 70 65 6e 0a 2a 2a 20 72 65 61 64 20  an open.** read 
a6a0: 74 72 61 6e 73 61 63 74 69 6f 6e 2e 20 49 74 20  transaction. It 
a6b0: 69 73 20 61 6e 20 65 72 72 6f 72 20 74 6f 20 63  is an error to c
a6c0: 61 6c 6c 20 74 68 69 73 20 69 66 20 74 68 65 72  all this if ther
a6d0: 65 20 69 73 20 6e 6f 20 6f 70 65 6e 20 77 72 69  e is no open wri
a6e0: 74 65 20 0a 2a 2a 20 74 72 61 6e 73 61 63 74 69  te .** transacti
a6f0: 6f 6e 2e 0a 2a 2a 0a 2a 2a 20 49 66 20 74 68 65  on..**.** If the
a700: 20 74 72 61 6e 73 61 63 74 69 6f 6e 20 77 61 73   transaction was
a710: 20 63 6f 6d 6d 69 74 74 65 64 2c 20 74 68 65 6e   committed, then
a720: 20 61 20 63 6f 6d 6d 69 74 20 72 65 63 6f 72 64   a commit record
a730: 20 68 61 73 20 61 6c 72 65 61 64 79 20 62 65 65   has already bee
a740: 6e 0a 2a 2a 20 77 72 69 74 74 65 6e 20 69 6e 74  n.** written int
a750: 6f 20 74 68 65 20 6c 6f 67 20 66 69 6c 65 20 77  o the log file w
a760: 68 65 6e 20 74 68 69 73 20 66 75 6e 63 74 69 6f  hen this functio
a770: 6e 20 69 73 20 63 61 6c 6c 65 64 2e 20 4f 72 2c  n is called. Or,
a780: 20 69 66 20 74 68 65 0a 2a 2a 20 74 72 61 6e 73   if the.** trans
a790: 61 63 74 69 6f 6e 20 77 61 73 20 72 6f 6c 6c 65  action was rolle
a7a0: 64 20 62 61 63 6b 2c 20 62 6f 74 68 20 74 68 65  d back, both the
a7b0: 20 6c 6f 67 20 66 69 6c 65 20 61 6e 64 20 69 6e   log file and in
a7c0: 2d 6d 65 6d 6f 72 79 20 74 72 65 65 20 0a 2a 2a  -memory tree .**
a7d0: 20 73 74 72 75 63 74 75 72 65 20 68 61 76 65 20   structure have 
a7e0: 61 6c 72 65 61 64 79 20 62 65 65 6e 20 72 65 73  already been res
a7f0: 74 6f 72 65 64 2e 20 49 6e 20 65 69 74 68 65 72  tored. In either
a800: 20 63 61 73 65 2c 20 74 68 69 73 20 66 75 6e 63   case, this func
a810: 74 69 6f 6e 20 0a 2a 2a 20 6d 65 72 65 6c 79 20  tion .** merely 
a820: 72 65 6c 65 61 73 65 73 20 6c 6f 63 6b 73 20 61  releases locks a
a830: 6e 64 20 6f 74 68 65 72 20 72 65 73 6f 75 72 63  nd other resourc
a840: 65 73 20 68 65 6c 64 20 62 79 20 74 68 65 20 77  es held by the w
a850: 72 69 74 65 2d 74 72 61 6e 73 61 63 74 69 6f 6e  rite-transaction
a860: 2e 0a 2a 2a 0a 2a 2a 20 4c 53 4d 5f 4f 4b 20 69  ..**.** LSM_OK i
a870: 73 20 72 65 74 75 72 6e 65 64 20 69 66 20 73 75  s returned if su
a880: 63 63 65 73 73 66 75 6c 2c 20 6f 72 20 61 6e 20  ccessful, or an 
a890: 4c 53 4d 20 65 72 72 6f 72 20 63 6f 64 65 20 6f  LSM error code o
a8a0: 74 68 65 72 77 69 73 65 2e 0a 2a 2f 0a 69 6e 74  therwise..*/.int
a8b0: 20 6c 73 6d 46 69 6e 69 73 68 57 72 69 74 65 54   lsmFinishWriteT
a8c0: 72 61 6e 73 28 6c 73 6d 5f 64 62 20 2a 70 44 62  rans(lsm_db *pDb
a8d0: 2c 20 69 6e 74 20 62 43 6f 6d 6d 69 74 29 7b 0a  , int bCommit){.
a8e0: 20 20 69 6e 74 20 72 63 20 3d 20 4c 53 4d 5f 4f    int rc = LSM_O
a8f0: 4b 3b 0a 20 20 69 6e 74 20 62 46 6c 75 73 68 20  K;.  int bFlush 
a900: 3d 20 30 3b 0a 0a 20 20 6c 73 6d 4c 6f 67 45 6e  = 0;..  lsmLogEn
a910: 64 28 70 44 62 2c 20 62 43 6f 6d 6d 69 74 29 3b  d(pDb, bCommit);
a920: 0a 20 20 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f  .  if( rc==LSM_O
a930: 4b 20 26 26 20 62 43 6f 6d 6d 69 74 20 26 26 20  K && bCommit && 
a940: 6c 73 6d 54 72 65 65 53 69 7a 65 28 70 44 62 29  lsmTreeSize(pDb)
a950: 3e 70 44 62 2d 3e 6e 54 72 65 65 4c 69 6d 69 74  >pDb->nTreeLimit
a960: 20 29 7b 0a 20 20 20 20 62 46 6c 75 73 68 20 3d   ){.    bFlush =
a970: 20 31 3b 0a 20 20 20 20 6c 73 6d 54 72 65 65 4d   1;.    lsmTreeM
a980: 61 6b 65 4f 6c 64 28 70 44 62 29 3b 0a 20 20 7d  akeOld(pDb);.  }
a990: 0a 20 20 6c 73 6d 54 72 65 65 45 6e 64 54 72 61  .  lsmTreeEndTra
a9a0: 6e 73 61 63 74 69 6f 6e 28 70 44 62 2c 20 62 43  nsaction(pDb, bC
a9b0: 6f 6d 6d 69 74 29 3b 0a 0a 20 20 69 66 28 20 72  ommit);..  if( r
a9c0: 63 3d 3d 4c 53 4d 5f 4f 4b 20 29 7b 0a 20 20 20  c==LSM_OK ){.   
a9d0: 20 69 66 28 20 62 46 6c 75 73 68 20 26 26 20 70   if( bFlush && p
a9e0: 44 62 2d 3e 62 41 75 74 6f 77 6f 72 6b 20 29 7b  Db->bAutowork ){
a9f0: 0a 20 20 20 20 20 20 72 63 20 3d 20 6c 73 6d 53  .      rc = lsmS
aa00: 6f 72 74 65 64 41 75 74 6f 57 6f 72 6b 28 70 44  ortedAutoWork(pD
aa10: 62 2c 20 31 29 3b 0a 20 20 20 20 7d 65 6c 73 65  b, 1);.    }else
aa20: 20 69 66 28 20 62 43 6f 6d 6d 69 74 20 26 26 20   if( bCommit && 
aa30: 70 44 62 2d 3e 62 44 69 73 63 61 72 64 4f 6c 64  pDb->bDiscardOld
aa40: 20 29 7b 0a 20 20 20 20 20 20 72 63 20 3d 20 64   ){.      rc = d
aa50: 62 53 65 74 52 65 61 64 4c 6f 63 6b 28 70 44 62  bSetReadLock(pDb
aa60: 2c 20 70 44 62 2d 3e 70 43 6c 69 65 6e 74 2d 3e  , pDb->pClient->
aa70: 69 49 64 2c 20 70 44 62 2d 3e 74 72 65 65 68 64  iId, pDb->treehd
aa80: 72 2e 69 55 73 65 64 53 68 6d 69 64 29 3b 0a 20  r.iUsedShmid);. 
aa90: 20 20 20 7d 0a 20 20 7d 0a 20 20 70 44 62 2d 3e     }.  }.  pDb->
aaa0: 62 44 69 73 63 61 72 64 4f 6c 64 20 3d 20 30 3b  bDiscardOld = 0;
aab0: 0a 20 20 6c 73 6d 53 68 6d 4c 6f 63 6b 28 70 44  .  lsmShmLock(pD
aac0: 62 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 57 52 49 54  b, LSM_LOCK_WRIT
aad0: 45 52 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 55 4e 4c  ER, LSM_LOCK_UNL
aae0: 4f 43 4b 2c 20 30 29 3b 0a 0a 20 20 69 66 28 20  OCK, 0);..  if( 
aaf0: 62 46 6c 75 73 68 20 26 26 20 70 44 62 2d 3e 62  bFlush && pDb->b
ab00: 41 75 74 6f 77 6f 72 6b 3d 3d 30 20 26 26 20 70  Autowork==0 && p
ab10: 44 62 2d 3e 78 57 6f 72 6b 20 29 7b 0a 20 20 20  Db->xWork ){.   
ab20: 20 70 44 62 2d 3e 78 57 6f 72 6b 28 70 44 62 2c   pDb->xWork(pDb,
ab30: 20 70 44 62 2d 3e 70 57 6f 72 6b 43 74 78 29 3b   pDb->pWorkCtx);
ab40: 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20 72 63  .  }.  return rc
ab50: 3b 0a 7d 0a 0a 0a 2f 2a 0a 2a 2a 20 52 65 74 75  ;.}.../*.** Retu
ab60: 72 6e 20 6e 6f 6e 2d 7a 65 72 6f 20 69 66 20 74  rn non-zero if t
ab70: 68 65 20 63 61 6c 6c 65 72 20 69 73 20 68 6f 6c  he caller is hol
ab80: 64 69 6e 67 20 74 68 65 20 63 6c 69 65 6e 74 20  ding the client 
ab90: 6d 75 74 65 78 2e 0a 2a 2f 0a 23 69 66 64 65 66  mutex..*/.#ifdef
aba0: 20 4c 53 4d 5f 44 45 42 55 47 0a 69 6e 74 20 6c   LSM_DEBUG.int l
abb0: 73 6d 48 6f 6c 64 69 6e 67 43 6c 69 65 6e 74 4d  smHoldingClientM
abc0: 75 74 65 78 28 6c 73 6d 5f 64 62 20 2a 70 44 62  utex(lsm_db *pDb
abd0: 29 7b 0a 20 20 72 65 74 75 72 6e 20 6c 73 6d 4d  ){.  return lsmM
abe0: 75 74 65 78 48 65 6c 64 28 70 44 62 2d 3e 70 45  utexHeld(pDb->pE
abf0: 6e 76 2c 20 70 44 62 2d 3e 70 44 61 74 61 62 61  nv, pDb->pDataba
ac00: 73 65 2d 3e 70 43 6c 69 65 6e 74 4d 75 74 65 78  se->pClientMutex
ac10: 29 3b 0a 7d 0a 23 65 6e 64 69 66 0a 0a 73 74 61  );.}.#endif..sta
ac20: 74 69 63 20 69 6e 74 20 73 6c 6f 74 49 73 55 73  tic int slotIsUs
ac30: 61 62 6c 65 28 53 68 6d 52 65 61 64 65 72 20 2a  able(ShmReader *
ac40: 70 2c 20 69 36 34 20 69 4c 73 6d 2c 20 75 33 32  p, i64 iLsm, u32
ac50: 20 69 53 68 6d 4d 69 6e 2c 20 75 33 32 20 69 53   iShmMin, u32 iS
ac60: 68 6d 4d 61 78 29 7b 0a 20 20 72 65 74 75 72 6e  hmMax){.  return
ac70: 28 20 0a 20 20 20 20 20 20 70 2d 3e 69 4c 73 6d  ( .      p->iLsm
ac80: 49 64 20 26 26 20 70 2d 3e 69 4c 73 6d 49 64 3c  Id && p->iLsmId<
ac90: 3d 69 4c 73 6d 20 0a 20 20 20 20 20 20 26 26 20  =iLsm .      && 
aca0: 73 68 6d 5f 73 65 71 75 65 6e 63 65 5f 67 65 28  shm_sequence_ge(
acb0: 69 53 68 6d 4d 61 78 2c 20 70 2d 3e 69 54 72 65  iShmMax, p->iTre
acc0: 65 49 64 29 0a 20 20 20 20 20 20 26 26 20 73 68  eId).      && sh
acd0: 6d 5f 73 65 71 75 65 6e 63 65 5f 67 65 28 70 2d  m_sequence_ge(p-
ace0: 3e 69 54 72 65 65 49 64 2c 20 69 53 68 6d 4d 69  >iTreeId, iShmMi
acf0: 6e 29 0a 20 20 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a  n).  );.}../*.**
ad00: 20 4f 62 74 61 69 6e 20 61 20 72 65 61 64 2d 6c   Obtain a read-l
ad10: 6f 63 6b 20 6f 6e 20 64 61 74 61 62 61 73 65 20  ock on database 
ad20: 76 65 72 73 69 6f 6e 20 69 64 65 6e 74 69 66 69  version identifi
ad30: 65 64 20 62 79 20 74 68 65 20 63 6f 6d 62 69 6e  ed by the combin
ad40: 61 74 69 6f 6e 0a 2a 2a 20 6f 66 20 73 6e 61 70  ation.** of snap
ad50: 73 68 6f 74 20 69 4c 73 6d 20 61 6e 64 20 74 72  shot iLsm and tr
ad60: 65 65 20 69 54 72 65 65 2e 20 52 65 74 75 72 6e  ee iTree. Return
ad70: 20 4c 53 4d 5f 4f 4b 20 69 66 20 73 75 63 63 65   LSM_OK if succe
ad80: 73 73 66 75 6c 2c 20 6f 72 0a 2a 2a 20 61 6e 20  ssful, or.** an 
ad90: 4c 53 4d 20 65 72 72 6f 72 20 63 6f 64 65 20 6f  LSM error code o
ada0: 74 68 65 72 77 69 73 65 2e 0a 2a 2f 0a 69 6e 74  therwise..*/.int
adb0: 20 6c 73 6d 52 65 61 64 6c 6f 63 6b 28 6c 73 6d   lsmReadlock(lsm
adc0: 5f 64 62 20 2a 64 62 2c 20 69 36 34 20 69 4c 73  _db *db, i64 iLs
add0: 6d 2c 20 75 33 32 20 69 53 68 6d 4d 69 6e 2c 20  m, u32 iShmMin, 
ade0: 75 33 32 20 69 53 68 6d 4d 61 78 29 7b 0a 20 20  u32 iShmMax){.  
adf0: 69 6e 74 20 72 63 20 3d 20 4c 53 4d 5f 4f 4b 3b  int rc = LSM_OK;
ae00: 0a 20 20 53 68 6d 48 65 61 64 65 72 20 2a 70 53  .  ShmHeader *pS
ae10: 68 6d 20 3d 20 64 62 2d 3e 70 53 68 6d 68 64 72  hm = db->pShmhdr
ae20: 3b 0a 20 20 69 6e 74 20 69 3b 0a 0a 20 20 61 73  ;.  int i;..  as
ae30: 73 65 72 74 28 20 64 62 2d 3e 69 52 65 61 64 65  sert( db->iReade
ae40: 72 3c 30 20 29 3b 0a 20 20 61 73 73 65 72 74 28  r<0 );.  assert(
ae50: 20 73 68 6d 5f 73 65 71 75 65 6e 63 65 5f 67 65   shm_sequence_ge
ae60: 28 69 53 68 6d 4d 61 78 2c 20 69 53 68 6d 4d 69  (iShmMax, iShmMi
ae70: 6e 29 20 29 3b 0a 0a 20 20 2f 2a 20 54 68 69 73  n) );..  /* This
ae80: 20 69 73 20 61 20 6e 6f 2d 6f 70 20 69 66 20 74   is a no-op if t
ae90: 68 65 20 72 65 61 64 2d 6f 6e 6c 79 20 74 72 61  he read-only tra
aea0: 6e 73 61 63 74 69 6f 6e 20 66 6c 61 67 20 69 73  nsaction flag is
aeb0: 20 73 65 74 2e 20 2a 2f 0a 20 20 69 66 28 20 64   set. */.  if( d
aec0: 62 2d 3e 62 52 6f 54 72 61 6e 73 20 29 7b 0a 20  b->bRoTrans ){. 
aed0: 20 20 20 64 62 2d 3e 69 52 65 61 64 65 72 20 3d     db->iReader =
aee0: 20 30 3b 0a 20 20 20 20 72 65 74 75 72 6e 20 4c   0;.    return L
aef0: 53 4d 5f 4f 4b 3b 0a 20 20 7d 0a 0a 20 20 2f 2a  SM_OK;.  }..  /*
af00: 20 53 65 61 72 63 68 20 66 6f 72 20 61 6e 20 65   Search for an e
af10: 78 61 63 74 20 6d 61 74 63 68 2e 20 2a 2f 0a 20  xact match. */. 
af20: 20 66 6f 72 28 69 3d 30 3b 20 64 62 2d 3e 69 52   for(i=0; db->iR
af30: 65 61 64 65 72 3c 30 20 26 26 20 72 63 3d 3d 4c  eader<0 && rc==L
af40: 53 4d 5f 4f 4b 20 26 26 20 69 3c 4c 53 4d 5f 4c  SM_OK && i<LSM_L
af50: 4f 43 4b 5f 4e 52 45 41 44 45 52 3b 20 69 2b 2b  OCK_NREADER; i++
af60: 29 7b 0a 20 20 20 20 53 68 6d 52 65 61 64 65 72  ){.    ShmReader
af70: 20 2a 70 20 3d 20 26 70 53 68 6d 2d 3e 61 52 65   *p = &pShm->aRe
af80: 61 64 65 72 5b 69 5d 3b 0a 20 20 20 20 69 66 28  ader[i];.    if(
af90: 20 70 2d 3e 69 4c 73 6d 49 64 3d 3d 69 4c 73 6d   p->iLsmId==iLsm
afa0: 20 26 26 20 70 2d 3e 69 54 72 65 65 49 64 3d 3d   && p->iTreeId==
afb0: 69 53 68 6d 4d 61 78 20 29 7b 0a 20 20 20 20 20  iShmMax ){.     
afc0: 20 72 63 20 3d 20 6c 73 6d 53 68 6d 4c 6f 63 6b   rc = lsmShmLock
afd0: 28 64 62 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 52 45  (db, LSM_LOCK_RE
afe0: 41 44 45 52 28 69 29 2c 20 4c 53 4d 5f 4c 4f 43  ADER(i), LSM_LOC
aff0: 4b 5f 53 48 41 52 45 44 2c 20 30 29 3b 0a 20 20  K_SHARED, 0);.  
b000: 20 20 20 20 69 66 28 20 72 63 3d 3d 4c 53 4d 5f      if( rc==LSM_
b010: 4f 4b 20 26 26 20 70 2d 3e 69 4c 73 6d 49 64 3d  OK && p->iLsmId=
b020: 3d 69 4c 73 6d 20 26 26 20 70 2d 3e 69 54 72 65  =iLsm && p->iTre
b030: 65 49 64 3d 3d 69 53 68 6d 4d 61 78 20 29 7b 0a  eId==iShmMax ){.
b040: 20 20 20 20 20 20 20 20 64 62 2d 3e 69 52 65 61          db->iRea
b050: 64 65 72 20 3d 20 69 3b 0a 20 20 20 20 20 20 7d  der = i;.      }
b060: 65 6c 73 65 20 69 66 28 20 72 63 3d 3d 4c 53 4d  else if( rc==LSM
b070: 5f 42 55 53 59 20 29 7b 0a 20 20 20 20 20 20 20  _BUSY ){.       
b080: 20 72 63 20 3d 20 4c 53 4d 5f 4f 4b 3b 0a 20 20   rc = LSM_OK;.  
b090: 20 20 20 20 7d 0a 20 20 20 20 7d 0a 20 20 7d 0a      }.    }.  }.
b0a0: 0a 20 20 2f 2a 20 54 72 79 20 74 6f 20 6f 62 74  .  /* Try to obt
b0b0: 61 69 6e 20 61 20 77 72 69 74 65 2d 6c 6f 63 6b  ain a write-lock
b0c0: 20 6f 6e 20 65 61 63 68 20 73 6c 6f 74 2c 20 69   on each slot, i
b0d0: 6e 20 6f 72 64 65 72 2e 20 49 66 20 73 75 63 63  n order. If succ
b0e0: 65 73 73 66 75 6c 2c 20 73 65 74 0a 20 20 2a 2a  essful, set.  **
b0f0: 20 74 68 65 20 73 6c 6f 74 20 76 61 6c 75 65 73   the slot values
b100: 20 74 6f 20 69 4c 73 6d 2f 69 54 72 65 65 2e 20   to iLsm/iTree. 
b110: 20 2a 2f 0a 20 20 66 6f 72 28 69 3d 30 3b 20 64   */.  for(i=0; d
b120: 62 2d 3e 69 52 65 61 64 65 72 3c 30 20 26 26 20  b->iReader<0 && 
b130: 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 26 26 20 69 3c  rc==LSM_OK && i<
b140: 4c 53 4d 5f 4c 4f 43 4b 5f 4e 52 45 41 44 45 52  LSM_LOCK_NREADER
b150: 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 72 63 20 3d  ; i++){.    rc =
b160: 20 6c 73 6d 53 68 6d 4c 6f 63 6b 28 64 62 2c 20   lsmShmLock(db, 
b170: 4c 53 4d 5f 4c 4f 43 4b 5f 52 45 41 44 45 52 28  LSM_LOCK_READER(
b180: 69 29 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 45 58 43  i), LSM_LOCK_EXC
b190: 4c 2c 20 30 29 3b 0a 20 20 20 20 69 66 28 20 72  L, 0);.    if( r
b1a0: 63 3d 3d 4c 53 4d 5f 42 55 53 59 20 29 7b 0a 20  c==LSM_BUSY ){. 
b1b0: 20 20 20 20 20 72 63 20 3d 20 4c 53 4d 5f 4f 4b       rc = LSM_OK
b1c0: 3b 0a 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20  ;.    }else{.   
b1d0: 20 20 20 53 68 6d 52 65 61 64 65 72 20 2a 70 20     ShmReader *p 
b1e0: 3d 20 26 70 53 68 6d 2d 3e 61 52 65 61 64 65 72  = &pShm->aReader
b1f0: 5b 69 5d 3b 0a 20 20 20 20 20 20 70 2d 3e 69 4c  [i];.      p->iL
b200: 73 6d 49 64 20 3d 20 69 4c 73 6d 3b 0a 20 20 20  smId = iLsm;.   
b210: 20 20 20 70 2d 3e 69 54 72 65 65 49 64 20 3d 20     p->iTreeId = 
b220: 69 53 68 6d 4d 61 78 3b 0a 20 20 20 20 20 20 72  iShmMax;.      r
b230: 63 20 3d 20 6c 73 6d 53 68 6d 4c 6f 63 6b 28 64  c = lsmShmLock(d
b240: 62 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 52 45 41 44  b, LSM_LOCK_READ
b250: 45 52 28 69 29 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f  ER(i), LSM_LOCK_
b260: 53 48 41 52 45 44 2c 20 30 29 3b 0a 20 20 20 20  SHARED, 0);.    
b270: 20 20 61 73 73 65 72 74 28 20 72 63 21 3d 4c 53    assert( rc!=LS
b280: 4d 5f 42 55 53 59 20 29 3b 0a 20 20 20 20 20 20  M_BUSY );.      
b290: 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 29  if( rc==LSM_OK )
b2a0: 20 64 62 2d 3e 69 52 65 61 64 65 72 20 3d 20 69   db->iReader = i
b2b0: 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 0a 20 20 2f  ;.    }.  }..  /
b2c0: 2a 20 53 65 61 72 63 68 20 66 6f 72 20 61 6e 79  * Search for any
b2d0: 20 75 73 61 62 6c 65 20 73 6c 6f 74 20 2a 2f 0a   usable slot */.
b2e0: 20 20 66 6f 72 28 69 3d 30 3b 20 64 62 2d 3e 69    for(i=0; db->i
b2f0: 52 65 61 64 65 72 3c 30 20 26 26 20 72 63 3d 3d  Reader<0 && rc==
b300: 4c 53 4d 5f 4f 4b 20 26 26 20 69 3c 4c 53 4d 5f  LSM_OK && i<LSM_
b310: 4c 4f 43 4b 5f 4e 52 45 41 44 45 52 3b 20 69 2b  LOCK_NREADER; i+
b320: 2b 29 7b 0a 20 20 20 20 53 68 6d 52 65 61 64 65  +){.    ShmReade
b330: 72 20 2a 70 20 3d 20 26 70 53 68 6d 2d 3e 61 52  r *p = &pShm->aR
b340: 65 61 64 65 72 5b 69 5d 3b 0a 20 20 20 20 69 66  eader[i];.    if
b350: 28 20 73 6c 6f 74 49 73 55 73 61 62 6c 65 28 70  ( slotIsUsable(p
b360: 2c 20 69 4c 73 6d 2c 20 69 53 68 6d 4d 69 6e 2c  , iLsm, iShmMin,
b370: 20 69 53 68 6d 4d 61 78 29 20 29 7b 0a 20 20 20   iShmMax) ){.   
b380: 20 20 20 72 63 20 3d 20 6c 73 6d 53 68 6d 4c 6f     rc = lsmShmLo
b390: 63 6b 28 64 62 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f  ck(db, LSM_LOCK_
b3a0: 52 45 41 44 45 52 28 69 29 2c 20 4c 53 4d 5f 4c  READER(i), LSM_L
b3b0: 4f 43 4b 5f 53 48 41 52 45 44 2c 20 30 29 3b 0a  OCK_SHARED, 0);.
b3c0: 20 20 20 20 20 20 69 66 28 20 72 63 3d 3d 4c 53        if( rc==LS
b3d0: 4d 5f 4f 4b 20 26 26 20 73 6c 6f 74 49 73 55 73  M_OK && slotIsUs
b3e0: 61 62 6c 65 28 70 2c 20 69 4c 73 6d 2c 20 69 53  able(p, iLsm, iS
b3f0: 68 6d 4d 69 6e 2c 20 69 53 68 6d 4d 61 78 29 20  hmMin, iShmMax) 
b400: 29 7b 0a 20 20 20 20 20 20 20 20 64 62 2d 3e 69  ){.        db->i
b410: 52 65 61 64 65 72 20 3d 20 69 3b 0a 20 20 20 20  Reader = i;.    
b420: 20 20 7d 65 6c 73 65 20 69 66 28 20 72 63 3d 3d    }else if( rc==
b430: 4c 53 4d 5f 42 55 53 59 20 29 7b 0a 20 20 20 20  LSM_BUSY ){.    
b440: 20 20 20 20 72 63 20 3d 20 4c 53 4d 5f 4f 4b 3b      rc = LSM_OK;
b450: 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a 20  .      }.    }. 
b460: 20 7d 0a 0a 20 20 69 66 28 20 72 63 3d 3d 4c 53   }..  if( rc==LS
b470: 4d 5f 4f 4b 20 26 26 20 64 62 2d 3e 69 52 65 61  M_OK && db->iRea
b480: 64 65 72 3c 30 20 29 7b 0a 20 20 20 20 72 63 20  der<0 ){.    rc 
b490: 3d 20 4c 53 4d 5f 42 55 53 59 3b 0a 20 20 7d 0a  = LSM_BUSY;.  }.
b4a0: 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a    return rc;.}..
b4b0: 2f 2a 0a 2a 2a 20 54 68 69 73 20 69 73 20 75 73  /*.** This is us
b4c0: 65 64 20 74 6f 20 63 68 65 63 6b 20 69 66 20 74  ed to check if t
b4d0: 68 65 72 65 20 65 78 69 73 74 73 20 61 20 72 65  here exists a re
b4e0: 61 64 2d 6c 6f 63 6b 20 6c 6f 63 6b 69 6e 67 20  ad-lock locking 
b4f0: 61 20 70 61 72 74 69 63 75 6c 61 72 0a 2a 2a 20  a particular.** 
b500: 76 65 72 73 69 6f 6e 20 6f 66 20 65 69 74 68 65  version of eithe
b510: 72 20 74 68 65 20 69 6e 2d 6d 65 6d 6f 72 79 20  r the in-memory 
b520: 74 72 65 65 20 6f 72 20 64 61 74 61 62 61 73 65  tree or database
b530: 20 66 69 6c 65 2e 20 0a 2a 2a 0a 2a 2a 20 49 66   file. .**.** If
b540: 20 69 4c 73 6d 49 64 20 69 73 20 6e 6f 6e 2d 7a   iLsmId is non-z
b550: 65 72 6f 2c 20 74 68 65 6e 20 69 74 20 69 73 20  ero, then it is 
b560: 61 20 73 6e 61 70 73 68 6f 74 20 69 64 2e 20 49  a snapshot id. I
b570: 66 20 74 68 65 72 65 20 65 78 69 73 74 73 20 61  f there exists a
b580: 20 0a 2a 2a 20 72 65 61 64 2d 6c 6f 63 6b 20 75   .** read-lock u
b590: 73 69 6e 67 20 74 68 69 73 20 73 6e 61 70 73 68  sing this snapsh
b5a0: 6f 74 20 6f 72 20 6e 65 77 65 72 2c 20 73 65 74  ot or newer, set
b5b0: 20 2a 70 62 49 6e 55 73 65 20 74 6f 20 74 72 75   *pbInUse to tru
b5c0: 65 2e 20 4f 72 2c 0a 2a 2a 20 69 66 20 74 68 65  e. Or,.** if the
b5d0: 72 65 20 69 73 20 6e 6f 20 73 75 63 68 20 72 65  re is no such re
b5e0: 61 64 2d 6c 6f 63 6b 2c 20 73 65 74 20 69 74 20  ad-lock, set it 
b5f0: 74 6f 20 66 61 6c 73 65 2e 0a 2a 2a 0a 2a 2a 20  to false..**.** 
b600: 4f 72 2c 20 69 66 20 69 4c 73 6d 49 64 20 69 73  Or, if iLsmId is
b610: 20 7a 65 72 6f 2c 20 74 68 65 6e 20 69 53 68 6d   zero, then iShm
b620: 69 64 20 69 73 20 61 20 73 68 61 72 65 64 2d 6d  id is a shared-m
b630: 65 6d 6f 72 79 20 73 65 71 75 65 6e 63 65 20 69  emory sequence i
b640: 64 2e 0a 2a 2a 20 53 65 61 72 63 68 20 66 6f 72  d..** Search for
b650: 20 61 20 72 65 61 64 2d 6c 6f 63 6b 20 75 73 69   a read-lock usi
b660: 6e 67 20 74 68 69 73 20 73 65 71 75 65 6e 63 65  ng this sequence
b670: 20 69 64 20 6f 72 20 6e 65 77 65 72 2e 20 65 74   id or newer. et
b680: 63 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74  c..*/.static int
b690: 20 69 73 49 6e 55 73 65 28 6c 73 6d 5f 64 62 20   isInUse(lsm_db 
b6a0: 2a 64 62 2c 20 69 36 34 20 69 4c 73 6d 49 64 2c  *db, i64 iLsmId,
b6b0: 20 75 33 32 20 69 53 68 6d 69 64 2c 20 69 6e 74   u32 iShmid, int
b6c0: 20 2a 70 62 49 6e 55 73 65 29 7b 0a 20 20 53 68   *pbInUse){.  Sh
b6d0: 6d 48 65 61 64 65 72 20 2a 70 53 68 6d 20 3d 20  mHeader *pShm = 
b6e0: 64 62 2d 3e 70 53 68 6d 68 64 72 3b 0a 20 20 69  db->pShmhdr;.  i
b6f0: 6e 74 20 69 3b 0a 20 20 69 6e 74 20 72 63 20 3d  nt i;.  int rc =
b700: 20 4c 53 4d 5f 4f 4b 3b 0a 0a 20 20 66 6f 72 28   LSM_OK;..  for(
b710: 69 3d 30 3b 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20  i=0; rc==LSM_OK 
b720: 26 26 20 69 3c 4c 53 4d 5f 4c 4f 43 4b 5f 4e 52  && i<LSM_LOCK_NR
b730: 45 41 44 45 52 3b 20 69 2b 2b 29 7b 0a 20 20 20  EADER; i++){.   
b740: 20 53 68 6d 52 65 61 64 65 72 20 2a 70 20 3d 20   ShmReader *p = 
b750: 26 70 53 68 6d 2d 3e 61 52 65 61 64 65 72 5b 69  &pShm->aReader[i
b760: 5d 3b 0a 20 20 20 20 69 66 28 20 70 2d 3e 69 4c  ];.    if( p->iL
b770: 73 6d 49 64 20 29 7b 0a 20 20 20 20 20 20 69 66  smId ){.      if
b780: 28 20 28 69 4c 73 6d 49 64 21 3d 30 20 26 26 20  ( (iLsmId!=0 && 
b790: 70 2d 3e 69 4c 73 6d 49 64 21 3d 30 20 26 26 20  p->iLsmId!=0 && 
b7a0: 69 4c 73 6d 49 64 3e 3d 70 2d 3e 69 4c 73 6d 49  iLsmId>=p->iLsmI
b7b0: 64 29 20 0a 20 20 20 20 20 20 20 7c 7c 20 28 69  d) .       || (i
b7c0: 4c 73 6d 49 64 3d 3d 30 20 26 26 20 73 68 6d 5f  LsmId==0 && shm_
b7d0: 73 65 71 75 65 6e 63 65 5f 67 65 28 70 2d 3e 69  sequence_ge(p->i
b7e0: 54 72 65 65 49 64 2c 20 69 53 68 6d 69 64 29 29  TreeId, iShmid))
b7f0: 0a 20 20 20 20 20 20 29 7b 0a 20 20 20 20 20 20  .      ){.      
b800: 20 20 72 63 20 3d 20 6c 73 6d 53 68 6d 4c 6f 63    rc = lsmShmLoc
b810: 6b 28 64 62 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 52  k(db, LSM_LOCK_R
b820: 45 41 44 45 52 28 69 29 2c 20 4c 53 4d 5f 4c 4f  EADER(i), LSM_LO
b830: 43 4b 5f 45 58 43 4c 2c 20 30 29 3b 0a 20 20 20  CK_EXCL, 0);.   
b840: 20 20 20 20 20 69 66 28 20 72 63 3d 3d 4c 53 4d       if( rc==LSM
b850: 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 20 20 20  _OK ){.         
b860: 20 70 2d 3e 69 4c 73 6d 49 64 20 3d 20 30 3b 0a   p->iLsmId = 0;.
b870: 20 20 20 20 20 20 20 20 20 20 6c 73 6d 53 68 6d            lsmShm
b880: 4c 6f 63 6b 28 64 62 2c 20 4c 53 4d 5f 4c 4f 43  Lock(db, LSM_LOC
b890: 4b 5f 52 45 41 44 45 52 28 69 29 2c 20 4c 53 4d  K_READER(i), LSM
b8a0: 5f 4c 4f 43 4b 5f 55 4e 4c 4f 43 4b 2c 20 30 29  _LOCK_UNLOCK, 0)
b8b0: 3b 0a 20 20 20 20 20 20 20 20 7d 0a 20 20 20 20  ;.        }.    
b8c0: 20 20 7d 0a 20 20 20 20 7d 0a 20 20 7d 0a 0a 20    }.    }.  }.. 
b8d0: 20 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 42 55 53   if( rc==LSM_BUS
b8e0: 59 20 29 7b 0a 20 20 20 20 2a 70 62 49 6e 55 73  Y ){.    *pbInUs
b8f0: 65 20 3d 20 31 3b 0a 20 20 20 20 72 65 74 75 72  e = 1;.    retur
b900: 6e 20 4c 53 4d 5f 4f 4b 3b 0a 20 20 7d 0a 20 20  n LSM_OK;.  }.  
b910: 2a 70 62 49 6e 55 73 65 20 3d 20 30 3b 0a 20 20  *pbInUse = 0;.  
b920: 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a  return rc;.}../*
b930: 0a 2a 2a 20 54 68 69 73 20 66 75 6e 63 74 69 6f  .** This functio
b940: 6e 20 69 73 20 63 61 6c 6c 65 64 20 62 79 20 77  n is called by w
b950: 6f 72 6b 65 72 20 63 6f 6e 6e 65 63 74 69 6f 6e  orker connection
b960: 73 20 74 6f 20 64 65 74 65 72 6d 69 6e 65 20 74  s to determine t
b970: 68 65 20 73 6d 61 6c 6c 65 73 74 0a 2a 2a 20 73  he smallest.** s
b980: 6e 61 70 73 68 6f 74 20 69 64 20 74 68 61 74 20  napshot id that 
b990: 69 73 20 63 75 72 72 65 6e 74 6c 79 20 69 6e 20  is currently in 
b9a0: 75 73 65 20 62 79 20 61 20 64 61 74 61 62 61 73  use by a databas
b9b0: 65 20 63 6c 69 65 6e 74 2e 20 54 68 65 20 77 6f  e client. The wo
b9c0: 72 6b 65 72 0a 2a 2a 20 63 6f 6e 6e 65 63 74 69  rker.** connecti
b9d0: 6f 6e 20 75 73 65 73 20 74 68 69 73 20 72 65 73  on uses this res
b9e0: 75 6c 74 20 74 6f 20 64 65 74 65 72 6d 69 6e 65  ult to determine
b9f0: 20 77 68 65 74 68 65 72 20 6f 72 20 6e 6f 74 20   whether or not 
ba00: 69 74 20 69 73 20 73 61 66 65 20 74 6f 0a 2a 2a  it is safe to.**
ba10: 20 72 65 63 79 63 6c 65 20 61 20 64 61 74 61 62   recycle a datab
ba20: 61 73 65 20 62 6c 6f 63 6b 2e 0a 2a 2f 0a 73 74  ase block..*/.st
ba30: 61 74 69 63 20 69 6e 74 20 66 69 72 73 74 53 6e  atic int firstSn
ba40: 61 70 73 68 6f 74 49 6e 55 73 65 28 0a 20 20 6c  apshotInUse(.  l
ba50: 73 6d 5f 64 62 20 2a 64 62 2c 20 20 20 20 20 20  sm_db *db,      
ba60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
ba70: 2a 20 44 61 74 61 62 61 73 65 20 68 61 6e 64 6c  * Database handl
ba80: 65 20 2a 2f 0a 20 20 69 36 34 20 2a 70 69 49 6e  e */.  i64 *piIn
ba90: 55 73 65 20 20 20 20 20 20 20 20 20 20 20 20 20  Use             
baa0: 20 20 20 20 20 20 20 2f 2a 20 49 4e 2f 4f 55 54         /* IN/OUT
bab0: 3a 20 53 6d 61 6c 6c 65 73 74 20 73 6e 61 70 73  : Smallest snaps
bac0: 68 6f 74 20 69 64 20 69 6e 20 75 73 65 20 2a 2f  hot id in use */
bad0: 0a 29 7b 0a 20 20 53 68 6d 48 65 61 64 65 72 20  .){.  ShmHeader 
bae0: 2a 70 53 68 6d 20 3d 20 64 62 2d 3e 70 53 68 6d  *pShm = db->pShm
baf0: 68 64 72 3b 0a 20 20 69 36 34 20 69 49 6e 55 73  hdr;.  i64 iInUs
bb00: 65 20 3d 20 2a 70 69 49 6e 55 73 65 3b 0a 20 20  e = *piInUse;.  
bb10: 69 6e 74 20 69 3b 0a 0a 20 20 61 73 73 65 72 74  int i;..  assert
bb20: 28 20 69 49 6e 55 73 65 3e 30 20 29 3b 0a 20 20  ( iInUse>0 );.  
bb30: 66 6f 72 28 69 3d 30 3b 20 69 3c 4c 53 4d 5f 4c  for(i=0; i<LSM_L
bb40: 4f 43 4b 5f 4e 52 45 41 44 45 52 3b 20 69 2b 2b  OCK_NREADER; i++
bb50: 29 7b 0a 20 20 20 20 53 68 6d 52 65 61 64 65 72  ){.    ShmReader
bb60: 20 2a 70 20 3d 20 26 70 53 68 6d 2d 3e 61 52 65   *p = &pShm->aRe
bb70: 61 64 65 72 5b 69 5d 3b 0a 20 20 20 20 69 66 28  ader[i];.    if(
bb80: 20 70 2d 3e 69 4c 73 6d 49 64 20 29 7b 0a 20 20   p->iLsmId ){.  
bb90: 20 20 20 20 69 36 34 20 69 54 68 69 73 20 3d 20      i64 iThis = 
bba0: 70 2d 3e 69 4c 73 6d 49 64 3b 0a 20 20 20 20 20  p->iLsmId;.     
bbb0: 20 69 66 28 20 69 54 68 69 73 21 3d 30 20 26 26   if( iThis!=0 &&
bbc0: 20 69 49 6e 55 73 65 3e 69 54 68 69 73 20 29 7b   iInUse>iThis ){
bbd0: 0a 20 20 20 20 20 20 20 20 69 6e 74 20 72 63 20  .        int rc 
bbe0: 3d 20 6c 73 6d 53 68 6d 4c 6f 63 6b 28 64 62 2c  = lsmShmLock(db,
bbf0: 20 4c 53 4d 5f 4c 4f 43 4b 5f 52 45 41 44 45 52   LSM_LOCK_READER
bc00: 28 69 29 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 45 58  (i), LSM_LOCK_EX
bc10: 43 4c 2c 20 30 29 3b 0a 20 20 20 20 20 20 20 20  CL, 0);.        
bc20: 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 29  if( rc==LSM_OK )
bc30: 7b 0a 20 20 20 20 20 20 20 20 20 20 70 2d 3e 69  {.          p->i
bc40: 4c 73 6d 49 64 20 3d 20 30 3b 0a 20 20 20 20 20  LsmId = 0;.     
bc50: 20 20 20 20 20 6c 73 6d 53 68 6d 4c 6f 63 6b 28       lsmShmLock(
bc60: 64 62 2c 20 4c 53 4d 5f 4c 4f 43 4b 5f 52 45 41  db, LSM_LOCK_REA
bc70: 44 45 52 28 69 29 2c 20 4c 53 4d 5f 4c 4f 43 4b  DER(i), LSM_LOCK
bc80: 5f 55 4e 4c 4f 43 4b 2c 20 30 29 3b 0a 20 20 20  _UNLOCK, 0);.   
bc90: 20 20 20 20 20 7d 65 6c 73 65 20 69 66 28 20 72       }else if( r
bca0: 63 3d 3d 4c 53 4d 5f 42 55 53 59 20 29 7b 0a 20  c==LSM_BUSY ){. 
bcb0: 20 20 20 20 20 20 20 20 20 69 49 6e 55 73 65 20           iInUse 
bcc0: 3d 20 69 54 68 69 73 3b 0a 20 20 20 20 20 20 20  = iThis;.       
bcd0: 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 20 20   }else{.        
bce0: 20 20 2f 2a 20 53 6f 6d 65 20 65 72 72 6f 72 20    /* Some error 
bcf0: 6f 74 68 65 72 20 74 68 61 6e 20 4c 53 4d 5f 42  other than LSM_B
bd00: 55 53 59 2e 20 52 65 74 75 72 6e 20 74 68 65 20  USY. Return the 
bd10: 65 72 72 6f 72 20 63 6f 64 65 20 74 6f 0a 20 20  error code to.  
bd20: 20 20 20 20 20 20 20 20 2a 2a 20 74 68 65 20 63          ** the c
bd30: 61 6c 6c 65 72 20 69 6e 20 74 68 69 73 20 63 61  aller in this ca
bd40: 73 65 2e 20 20 2a 2f 0a 20 20 20 20 20 20 20 20  se.  */.        
bd50: 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 20 20 20    return rc;.   
bd60: 20 20 20 20 20 7d 0a 20 20 20 20 20 20 7d 0a 20       }.      }. 
bd70: 20 20 20 7d 0a 20 20 7d 0a 0a 20 20 2a 70 69 49     }.  }..  *piI
bd80: 6e 55 73 65 20 3d 20 69 49 6e 55 73 65 3b 0a 20  nUse = iInUse;. 
bd90: 20 72 65 74 75 72 6e 20 4c 53 4d 5f 4f 4b 3b 0a   return LSM_OK;.
bda0: 7d 0a 0a 69 6e 74 20 6c 73 6d 54 72 65 65 49 6e  }..int lsmTreeIn
bdb0: 55 73 65 28 6c 73 6d 5f 64 62 20 2a 64 62 2c 20  Use(lsm_db *db, 
bdc0: 75 33 32 20 69 53 68 6d 69 64 2c 20 69 6e 74 20  u32 iShmid, int 
bdd0: 2a 70 62 49 6e 55 73 65 29 7b 0a 20 20 69 66 28  *pbInUse){.  if(
bde0: 20 64 62 2d 3e 74 72 65 65 68 64 72 2e 69 55 73   db->treehdr.iUs
bdf0: 65 64 53 68 6d 69 64 3d 3d 69 53 68 6d 69 64 20  edShmid==iShmid 
be00: 29 7b 0a 20 20 20 20 2a 70 62 49 6e 55 73 65 20  ){.    *pbInUse 
be10: 3d 20 31 3b 0a 20 20 20 20 72 65 74 75 72 6e 20  = 1;.    return 
be20: 4c 53 4d 5f 4f 4b 3b 0a 20 20 7d 0a 20 20 72 65  LSM_OK;.  }.  re
be30: 74 75 72 6e 20 69 73 49 6e 55 73 65 28 64 62 2c  turn isInUse(db,
be40: 20 30 2c 20 69 53 68 6d 69 64 2c 20 70 62 49 6e   0, iShmid, pbIn
be50: 55 73 65 29 3b 0a 7d 0a 0a 69 6e 74 20 6c 73 6d  Use);.}..int lsm
be60: 4c 73 6d 49 6e 55 73 65 28 6c 73 6d 5f 64 62 20  LsmInUse(lsm_db 
be70: 2a 64 62 2c 20 69 36 34 20 69 4c 73 6d 49 64 2c  *db, i64 iLsmId,
be80: 20 69 6e 74 20 2a 70 62 49 6e 55 73 65 29 7b 0a   int *pbInUse){.
be90: 20 20 69 66 28 20 64 62 2d 3e 70 43 6c 69 65 6e    if( db->pClien
bea0: 74 20 26 26 20 64 62 2d 3e 70 43 6c 69 65 6e 74  t && db->pClient
beb0: 2d 3e 69 49 64 3c 3d 69 4c 73 6d 49 64 20 29 7b  ->iId<=iLsmId ){
bec0: 0a 20 20 20 20 2a 70 62 49 6e 55 73 65 20 3d 20  .    *pbInUse = 
bed0: 31 3b 0a 20 20 20 20 72 65 74 75 72 6e 20 4c 53  1;.    return LS
bee0: 4d 5f 4f 4b 3b 0a 20 20 7d 0a 20 20 72 65 74 75  M_OK;.  }.  retu
bef0: 72 6e 20 69 73 49 6e 55 73 65 28 64 62 2c 20 69  rn isInUse(db, i
bf00: 4c 73 6d 49 64 2c 20 30 2c 20 70 62 49 6e 55 73  LsmId, 0, pbInUs
bf10: 65 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54 68 69  e);.}../*.** Thi
bf20: 73 20 66 75 6e 63 74 69 6f 6e 20 6d 61 79 20 6f  s function may o
bf30: 6e 6c 79 20 62 65 20 63 61 6c 6c 65 64 20 61 66  nly be called af
bf40: 74 65 72 20 61 20 73 75 63 63 65 73 73 66 75 6c  ter a successful
bf50: 20 63 61 6c 6c 20 74 6f 0a 2a 2a 20 6c 73 6d 44   call to.** lsmD
bf60: 62 44 61 74 61 62 61 73 65 43 6f 6e 6e 65 63 74  bDatabaseConnect
bf70: 28 29 2e 20 49 74 20 72 65 74 75 72 6e 73 20 74  (). It returns t
bf80: 72 75 65 20 69 66 20 74 68 65 20 63 6f 6e 6e 65  rue if the conne
bf90: 63 74 69 6f 6e 20 69 73 20 69 6e 0a 2a 2a 20 6d  ction is in.** m
bfa0: 75 6c 74 69 2d 70 72 6f 63 65 73 73 20 6d 6f 64  ulti-process mod
bfb0: 65 2c 20 6f 72 20 66 61 6c 73 65 20 6f 74 68 65  e, or false othe
bfc0: 72 77 69 73 65 2e 0a 2a 2f 0a 69 6e 74 20 6c 73  rwise..*/.int ls
bfd0: 6d 44 62 4d 75 6c 74 69 50 72 6f 63 28 6c 73 6d  mDbMultiProc(lsm
bfe0: 5f 64 62 20 2a 70 44 62 29 7b 0a 20 20 72 65 74  _db *pDb){.  ret
bff0: 75 72 6e 20 70 44 62 2d 3e 70 44 61 74 61 62 61  urn pDb->pDataba
c000: 73 65 20 26 26 20 70 44 62 2d 3e 70 44 61 74 61  se && pDb->pData
c010: 62 61 73 65 2d 3e 62 4d 75 6c 74 69 50 72 6f 63  base->bMultiProc
c020: 3b 0a 7d 0a 0a 0a 2f 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 2a 2a 2a 2a 2a 2a  ****************
c060: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
c070: 0a 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 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
c0b0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 0a 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: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
c100: 2a 2a 2a 2a 2a 2a 0a 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 2a 2a 2a 2a 2a  ****************
c140: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
c150: 2a 0a 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 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
c190: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 0a 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: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
c1e0: 2a 2a 2a 2a 2a 2a 2f 0a 0a 2f 2a 0a 2a 2a 20 45  ******/../*.** E
c1f0: 6e 73 75 72 65 20 74 68 61 74 20 64 61 74 61 62  nsure that datab
c200: 61 73 65 20 63 6f 6e 6e 65 63 74 69 6f 6e 20 64  ase connection d
c210: 62 20 68 61 73 20 63 61 63 68 65 64 20 70 6f 69  b has cached poi
c220: 6e 74 65 72 73 20 74 6f 20 61 74 20 6c 65 61 73  nters to at leas
c230: 74 20 74 68 65 20 0a 2a 2a 20 66 69 72 73 74 20  t the .** first 
c240: 6e 43 68 75 6e 6b 20 63 68 75 6e 6b 73 20 6f 66  nChunk chunks of
c250: 20 73 68 61 72 65 64 20 6d 65 6d 6f 72 79 2e 0a   shared memory..
c260: 2a 2f 0a 69 6e 74 20 6c 73 6d 53 68 6d 43 61 63  */.int lsmShmCac
c270: 68 65 43 68 75 6e 6b 73 28 6c 73 6d 5f 64 62 20  heChunks(lsm_db 
c280: 2a 64 62 2c 20 69 6e 74 20 6e 43 68 75 6e 6b 29  *db, int nChunk)
c290: 7b 0a 20 20 69 6e 74 20 72 63 20 3d 20 4c 53 4d  {.  int rc = LSM
c2a0: 5f 4f 4b 3b 0a 20 20 69 66 28 20 6e 43 68 75 6e  _OK;.  if( nChun
c2b0: 6b 3e 64 62 2d 3e 6e 53 68 6d 20 29 7b 0a 20 20  k>db->nShm ){.  
c2c0: 20 20 73 74 61 74 69 63 20 63 6f 6e 73 74 20 69    static const i
c2d0: 6e 74 20 4e 49 4e 43 52 20 3d 20 31 36 3b 0a 20  nt NINCR = 16;. 
c2e0: 20 20 20 44 61 74 61 62 61 73 65 20 2a 70 20 3d     Database *p =
c2f0: 20 64 62 2d 3e 70 44 61 74 61 62 61 73 65 3b 0a   db->pDatabase;.
c300: 20 20 20 20 6c 73 6d 5f 65 6e 76 20 2a 70 45 6e      lsm_env *pEn
c310: 76 20 3d 20 64 62 2d 3e 70 45 6e 76 3b 0a 20 20  v = db->pEnv;.  
c320: 20 20 69 6e 74 20 6e 41 6c 6c 6f 63 3b 0a 20 20    int nAlloc;.  
c330: 20 20 69 6e 74 20 69 3b 0a 0a 20 20 20 20 2f 2a    int i;..    /*
c340: 20 45 6e 73 75 72 65 20 74 68 61 74 20 74 68 65   Ensure that the
c350: 20 64 62 2d 3e 61 70 53 68 6d 5b 5d 20 61 72 72   db->apShm[] arr
c360: 61 79 20 69 73 20 6c 61 72 67 65 20 65 6e 6f 75  ay is large enou
c370: 67 68 2e 20 49 66 20 61 6e 20 61 74 74 65 6d 70  gh. If an attemp
c380: 74 20 74 6f 0a 20 20 20 20 2a 2a 20 61 6c 6c 6f  t to.    ** allo
c390: 63 61 74 65 20 6d 65 6d 6f 72 79 20 66 61 69 6c  cate memory fail
c3a0: 73 2c 20 72 65 74 75 72 6e 20 4c 53 4d 5f 4e 4f  s, return LSM_NO
c3b0: 4d 45 4d 20 69 6d 6d 65 64 69 61 74 65 6c 79 2e  MEM immediately.
c3c0: 20 54 68 65 20 61 70 53 68 6d 5b 5d 20 61 72 72   The apShm[] arr
c3d0: 61 79 0a 20 20 20 20 2a 2a 20 69 73 20 61 6c 77  ay.    ** is alw
c3e0: 61 79 73 20 65 78 74 65 6e 64 65 64 20 69 6e 20  ays extended in 
c3f0: 6d 75 6c 74 69 70 6c 65 73 20 6f 66 20 31 36 20  multiples of 16 
c400: 65 6e 74 72 69 65 73 20 2d 20 73 6f 20 74 68 65  entries - so the
c410: 20 61 63 74 75 61 6c 20 61 6c 6c 6f 63 61 74 65   actual allocate
c420: 64 0a 20 20 20 20 2a 2a 20 73 69 7a 65 20 63 61  d.    ** size ca
c430: 6e 20 62 65 20 69 6e 66 65 72 72 65 64 20 66 72  n be inferred fr
c440: 6f 6d 20 6e 53 68 6d 2e 20 20 2a 2f 20 0a 20 20  om nShm.  */ .  
c450: 20 20 6e 41 6c 6c 6f 63 20 3d 20 28 28 64 62 2d    nAlloc = ((db-
c460: 3e 6e 53 68 6d 20 2b 20 4e 49 4e 43 52 20 2d 20  >nShm + NINCR - 
c470: 31 29 20 2f 20 4e 49 4e 43 52 29 20 2a 20 4e 49  1) / NINCR) * NI
c480: 4e 43 52 3b 0a 20 20 20 20 77 68 69 6c 65 28 20  NCR;.    while( 
c490: 6e 43 68 75 6e 6b 3e 3d 6e 41 6c 6c 6f 63 20 29  nChunk>=nAlloc )
c4a0: 7b 0a 20 20 20 20 20 20 76 6f 69 64 20 2a 2a 61  {.      void **a
c4b0: 70 53 68 6d 3b 0a 20 20 20 20 20 20 6e 41 6c 6c  pShm;.      nAll
c4c0: 6f 63 20 2b 3d 20 4e 49 4e 43 52 3b 0a 20 20 20  oc += NINCR;.   
c4d0: 20 20 20 61 70 53 68 6d 20 3d 20 6c 73 6d 52 65     apShm = lsmRe
c4e0: 61 6c 6c 6f 63 28 70 45 6e 76 2c 20 64 62 2d 3e  alloc(pEnv, db->
c4f0: 61 70 53 68 6d 2c 20 73 69 7a 65 6f 66 28 76 6f  apShm, sizeof(vo
c500: 69 64 2a 29 2a 6e 41 6c 6c 6f 63 29 3b 0a 20 20  id*)*nAlloc);.  
c510: 20 20 20 20 69 66 28 20 21 61 70 53 68 6d 20 29      if( !apShm )
c520: 20 72 65 74 75 72 6e 20 4c 53 4d 5f 4e 4f 4d 45   return LSM_NOME
c530: 4d 5f 42 4b 50 54 3b 0a 20 20 20 20 20 20 64 62  M_BKPT;.      db
c540: 2d 3e 61 70 53 68 6d 20 3d 20 61 70 53 68 6d 3b  ->apShm = apShm;
c550: 0a 20 20 20 20 7d 0a 0a 20 20 20 20 69 66 28 20  .    }..    if( 
c560: 64 62 2d 3e 62 52 6f 54 72 61 6e 73 20 29 7b 0a  db->bRoTrans ){.
c570: 20 20 20 20 20 20 66 6f 72 28 69 3d 64 62 2d 3e        for(i=db->
c580: 6e 53 68 6d 3b 20 72 63 3d 3d 4c 53 4d 5f 4f 4b  nShm; rc==LSM_OK
c590: 20 26 26 20 69 3c 6e 43 68 75 6e 6b 3b 20 69 2b   && i<nChunk; i+
c5a0: 2b 29 7b 0a 20 20 20 20 20 20 20 20 64 62 2d 3e  +){.        db->
c5b0: 61 70 53 68 6d 5b 69 5d 20 3d 20 6c 73 6d 4d 61  apShm[i] = lsmMa
c5c0: 6c 6c 6f 63 5a 65 72 6f 52 63 28 70 45 6e 76 2c  llocZeroRc(pEnv,
c5d0: 20 4c 53 4d 5f 53 48 4d 5f 43 48 55 4e 4b 5f 53   LSM_SHM_CHUNK_S
c5e0: 49 5a 45 2c 20 26 72 63 29 3b 0a 20 20 20 20 20  IZE, &rc);.     
c5f0: 20 20 20 64 62 2d 3e 6e 53 68 6d 2b 2b 3b 0a 20     db->nShm++;. 
c600: 20 20 20 20 20 7d 0a 0a 20 20 20 20 7d 65 6c 73       }..    }els
c610: 65 7b 0a 0a 20 20 20 20 20 20 2f 2a 20 45 6e 74  e{..      /* Ent
c620: 65 72 20 74 68 65 20 63 6c 69 65 6e 74 20 6d 75  er the client mu
c630: 74 65 78 20 2a 2f 0a 20 20 20 20 20 20 6c 73 6d  tex */.      lsm
c640: 4d 75 74 65 78 45 6e 74 65 72 28 70 45 6e 76 2c  MutexEnter(pEnv,
c650: 20 70 2d 3e 70 43 6c 69 65 6e 74 4d 75 74 65 78   p->pClientMutex
c660: 29 3b 0a 0a 20 20 20 20 20 20 2f 2a 20 45 78 74  );..      /* Ext
c670: 65 6e 64 20 74 68 65 20 44 61 74 61 62 61 73 65  end the Database
c680: 20 6f 62 6a 65 63 74 73 20 61 70 53 68 6d 43 68   objects apShmCh
c690: 75 6e 6b 5b 5d 20 61 72 72 61 79 20 69 66 20 6e  unk[] array if n
c6a0: 65 63 65 73 73 61 72 79 2e 20 55 73 69 6e 67 20  ecessary. Using 
c6b0: 74 68 65 0a 20 20 20 20 20 20 20 2a 2a 20 73 61  the.       ** sa
c6c0: 6d 65 20 70 61 74 74 65 72 6e 20 61 73 20 66 6f  me pattern as fo
c6d0: 72 20 74 68 65 20 6c 73 6d 5f 64 62 2e 61 70 53  r the lsm_db.apS
c6e0: 68 6d 5b 5d 20 61 72 72 61 79 20 61 62 6f 76 65  hm[] array above
c6f0: 2e 20 20 2a 2f 0a 20 20 20 20 20 20 6e 41 6c 6c  .  */.      nAll
c700: 6f 63 20 3d 20 28 28 70 2d 3e 6e 53 68 6d 43 68  oc = ((p->nShmCh
c710: 75 6e 6b 20 2b 20 4e 49 4e 43 52 20 2d 20 31 29  unk + NINCR - 1)
c720: 20 2f 20 4e 49 4e 43 52 29 20 2a 20 4e 49 4e 43   / NINCR) * NINC
c730: 52 3b 0a 20 20 20 20 20 20 77 68 69 6c 65 28 20  R;.      while( 
c740: 6e 43 68 75 6e 6b 3e 3d 6e 41 6c 6c 6f 63 20 29  nChunk>=nAlloc )
c750: 7b 0a 20 20 20 20 20 20 20 20 76 6f 69 64 20 2a  {.        void *
c760: 2a 61 70 53 68 6d 3b 0a 20 20 20 20 20 20 20 20  *apShm;.        
c770: 6e 41 6c 6c 6f 63 20 2b 3d 20 20 4e 49 4e 43 52  nAlloc +=  NINCR
c780: 3b 0a 20 20 20 20 20 20 20 20 61 70 53 68 6d 20  ;.        apShm 
c790: 3d 20 6c 73 6d 52 65 61 6c 6c 6f 63 28 70 45 6e  = lsmRealloc(pEn
c7a0: 76 2c 20 70 2d 3e 61 70 53 68 6d 43 68 75 6e 6b  v, p->apShmChunk
c7b0: 2c 20 73 69 7a 65 6f 66 28 76 6f 69 64 2a 29 2a  , sizeof(void*)*
c7c0: 6e 41 6c 6c 6f 63 29 3b 0a 20 20 20 20 20 20 20  nAlloc);.       
c7d0: 20 69 66 28 20 21 61 70 53 68 6d 20 29 7b 0a 20   if( !apShm ){. 
c7e0: 20 20 20 20 20 20 20 20 20 72 63 20 3d 20 4c 53           rc = LS
c7f0: 4d 5f 4e 4f 4d 45 4d 5f 42 4b 50 54 3b 0a 20 20  M_NOMEM_BKPT;.  
c800: 20 20 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20          break;. 
c810: 20 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 20         }.       
c820: 20 70 2d 3e 61 70 53 68 6d 43 68 75 6e 6b 20 3d   p->apShmChunk =
c830: 20 61 70 53 68 6d 3b 0a 20 20 20 20 20 20 7d 0a   apShm;.      }.
c840: 0a 20 20 20 20 20 20 66 6f 72 28 69 3d 64 62 2d  .      for(i=db-
c850: 3e 6e 53 68 6d 3b 20 72 63 3d 3d 4c 53 4d 5f 4f  >nShm; rc==LSM_O
c860: 4b 20 26 26 20 69 3c 6e 43 68 75 6e 6b 3b 20 69  K && i<nChunk; i
c870: 2b 2b 29 7b 0a 20 20 20 20 20 20 20 20 69 66 28  ++){.        if(
c880: 20 69 3e 3d 70 2d 3e 6e 53 68 6d 43 68 75 6e 6b   i>=p->nShmChunk
c890: 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20 76 6f   ){.          vo
c8a0: 69 64 20 2a 70 43 68 75 6e 6b 20 3d 20 30 3b 0a  id *pChunk = 0;.
c8b0: 20 20 20 20 20 20 20 20 20 20 69 66 28 20 70 2d            if( p-
c8c0: 3e 62 4d 75 6c 74 69 50 72 6f 63 3d 3d 30 20 29  >bMultiProc==0 )
c8d0: 7b 0a 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a  {.            /*
c8e0: 20 53 69 6e 67 6c 65 20 70 72 6f 63 65 73 73 20   Single process 
c8f0: 6d 6f 64 65 20 2a 2f 0a 20 20 20 20 20 20 20 20  mode */.        
c900: 20 20 20 20 70 43 68 75 6e 6b 20 3d 20 6c 73 6d      pChunk = lsm
c910: 4d 61 6c 6c 6f 63 5a 65 72 6f 52 63 28 70 45 6e  MallocZeroRc(pEn
c920: 76 2c 20 4c 53 4d 5f 53 48 4d 5f 43 48 55 4e 4b  v, LSM_SHM_CHUNK
c930: 5f 53 49 5a 45 2c 20 26 72 63 29 3b 0a 20 20 20  _SIZE, &rc);.   
c940: 20 20 20 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20         }else{.  
c950: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4d 75 6c            /* Mul
c960: 74 69 2d 70 72 6f 63 65 73 73 20 6d 6f 64 65 20  ti-process mode 
c970: 2a 2f 0a 20 20 20 20 20 20 20 20 20 20 20 20 72  */.            r
c980: 63 20 3d 20 6c 73 6d 45 6e 76 53 68 6d 4d 61 70  c = lsmEnvShmMap
c990: 28 70 45 6e 76 2c 20 70 2d 3e 70 46 69 6c 65 2c  (pEnv, p->pFile,
c9a0: 20 69 2c 20 4c 53 4d 5f 53 48 4d 5f 43 48 55 4e   i, LSM_SHM_CHUN
c9b0: 4b 5f 53 49 5a 45 2c 20 26 70 43 68 75 6e 6b 29  K_SIZE, &pChunk)
c9c0: 3b 0a 20 20 20 20 20 20 20 20 20 20 7d 0a 20 20  ;.          }.  
c9d0: 20 20 20 20 20 20 20 20 69 66 28 20 72 63 3d 3d          if( rc==
c9e0: 4c 53 4d 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20  LSM_OK ){.      
c9f0: 20 20 20 20 20 20 70 2d 3e 61 70 53 68 6d 43 68        p->apShmCh
ca00: 75 6e 6b 5b 69 5d 20 3d 20 70 43 68 75 6e 6b 3b  unk[i] = pChunk;
ca10: 0a 20 20 20 20 20 20 20 20 20 20 20 20 70 2d 3e  .            p->
ca20: 6e 53 68 6d 43 68 75 6e 6b 2b 2b 3b 0a 20 20 20  nShmChunk++;.   
ca30: 20 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 20         }.       
ca40: 20 7d 0a 20 20 20 20 20 20 20 20 69 66 28 20 72   }.        if( r
ca50: 63 3d 3d 4c 53 4d 5f 4f 4b 20 29 7b 0a 20 20 20  c==LSM_OK ){.   
ca60: 20 20 20 20 20 20 20 64 62 2d 3e 61 70 53 68 6d         db->apShm
ca70: 5b 69 5d 20 3d 20 70 2d 3e 61 70 53 68 6d 43 68  [i] = p->apShmCh
ca80: 75 6e 6b 5b 69 5d 3b 0a 20 20 20 20 20 20 20 20  unk[i];.        
ca90: 20 20 64 62 2d 3e 6e 53 68 6d 2b 2b 3b 0a 20 20    db->nShm++;.  
caa0: 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 7d 0a        }.      }.
cab0: 0a 20 20 20 20 20 20 2f 2a 20 52 65 6c 65 61 73  .      /* Releas
cac0: 65 20 74 68 65 20 63 6c 69 65 6e 74 20 6d 75 74  e the client mut
cad0: 65 78 20 2a 2f 0a 20 20 20 20 20 20 6c 73 6d 4d  ex */.      lsmM
cae0: 75 74 65 78 4c 65 61 76 65 28 70 45 6e 76 2c 20  utexLeave(pEnv, 
caf0: 70 2d 3e 70 43 6c 69 65 6e 74 4d 75 74 65 78 29  p->pClientMutex)
cb00: 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 0a 20 20 72  ;.    }.  }..  r
cb10: 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 73 74 61  eturn rc;.}..sta
cb20: 74 69 63 20 69 6e 74 20 6c 6f 63 6b 53 68 61 72  tic int lockShar
cb30: 65 64 46 69 6c 65 28 6c 73 6d 5f 65 6e 76 20 2a  edFile(lsm_env *
cb40: 70 45 6e 76 2c 20 44 61 74 61 62 61 73 65 20 2a  pEnv, Database *
cb50: 70 2c 20 69 6e 74 20 69 4c 6f 63 6b 2c 20 69 6e  p, int iLock, in
cb60: 74 20 65 4f 70 29 7b 0a 20 20 69 6e 74 20 72 63  t eOp){.  int rc
cb70: 20 3d 20 4c 53 4d 5f 4f 4b 3b 0a 20 20 69 66 28   = LSM_OK;.  if(
cb80: 20 70 2d 3e 62 4d 75 6c 74 69 50 72 6f 63 20 29   p->bMultiProc )
cb90: 7b 0a 20 20 20 20 72 63 20 3d 20 6c 73 6d 45 6e  {.    rc = lsmEn
cba0: 76 4c 6f 63 6b 28 70 45 6e 76 2c 20 70 2d 3e 70  vLock(pEnv, p->p
cbb0: 46 69 6c 65 2c 20 69 4c 6f 63 6b 2c 20 65 4f 70  File, iLock, eOp
cbc0: 29 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20  );.  }.  return 
cbd0: 72 63 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54 65 73  rc;.}../*.** Tes
cbe0: 74 20 69 66 20 69 74 20 77 6f 75 6c 64 20 62 65  t if it would be
cbf0: 20 70 6f 73 73 69 62 6c 65 20 66 6f 72 20 63 6f   possible for co
cc00: 6e 6e 65 63 74 69 6f 6e 20 64 62 20 74 6f 20 6f  nnection db to o
cc10: 62 74 61 69 6e 20 61 20 6c 6f 63 6b 20 6f 66 20  btain a lock of 
cc20: 74 79 70 65 0a 2a 2a 20 65 54 79 70 65 20 6f 6e  type.** eType on
cc30: 20 74 68 65 20 6e 4c 6f 63 6b 20 6c 6f 63 6b 73   the nLock locks
cc40: 20 73 74 61 72 74 69 6e 67 20 61 74 20 69 4c 6f   starting at iLo
cc50: 63 6b 2e 20 49 66 20 73 6f 2c 20 72 65 74 75 72  ck. If so, retur
cc60: 6e 20 4c 53 4d 5f 4f 4b 2e 20 49 66 20 69 74 0a  n LSM_OK. If it.
cc70: 2a 2a 20 77 6f 75 6c 64 20 6e 6f 74 20 62 65 20  ** would not be 
cc80: 70 6f 73 73 69 62 6c 65 20 74 6f 20 6f 62 74 61  possible to obta
cc90: 69 6e 20 74 68 65 20 6c 6f 63 6b 20 64 75 65 20  in the lock due 
cca0: 74 6f 20 61 20 6c 6f 63 6b 20 68 65 6c 64 20 62  to a lock held b
ccb0: 79 20 61 6e 6f 74 68 65 72 0a 2a 2a 20 63 6f 6e  y another.** con
ccc0: 6e 65 63 74 69 6f 6e 2c 20 72 65 74 75 72 6e 20  nection, return 
ccd0: 4c 53 4d 5f 42 55 53 59 2e 20 49 66 20 61 6e 20  LSM_BUSY. If an 
cce0: 49 4f 20 6f 72 20 6f 74 68 65 72 20 65 72 72 6f  IO or other erro
ccf0: 72 20 6f 63 63 75 72 73 20 28 69 2e 65 2e 20 69  r occurs (i.e. i
cd00: 6e 20 74 68 65 20 0a 2a 2a 20 6c 73 6d 5f 65 6e  n the .** lsm_en
cd10: 76 2e 78 54 65 73 74 4c 6f 63 6b 20 66 75 6e 63  v.xTestLock func
cd20: 74 69 6f 6e 29 2c 20 72 65 74 75 72 6e 20 73 6f  tion), return so
cd30: 6d 65 20 6f 74 68 65 72 20 4c 53 4d 20 65 72 72  me other LSM err
cd40: 6f 72 20 63 6f 64 65 2e 0a 2a 2a 0a 2a 2a 20 4e  or code..**.** N
cd50: 6f 74 65 20 74 68 61 74 20 74 68 69 73 20 66 75  ote that this fu
cd60: 6e 63 74 69 6f 6e 20 6e 65 76 65 72 20 61 63 74  nction never act
cd70: 75 61 6c 6c 79 20 6c 6f 63 6b 73 20 74 68 65 20  ually locks the 
cd80: 64 61 74 61 62 61 73 65 20 2d 20 69 74 20 6d 65  database - it me
cd90: 72 65 6c 79 0a 2a 2a 20 71 75 65 72 69 65 73 20  rely.** queries 
cda0: 74 68 65 20 73 79 73 74 65 6d 20 74 6f 20 73 65  the system to se
cdb0: 65 20 69 66 20 74 68 65 72 65 20 65 78 69 73 74  e if there exist
cdc0: 73 20 61 20 6c 6f 63 6b 20 74 68 61 74 20 77 6f  s a lock that wo
cdd0: 75 6c 64 20 70 72 65 76 65 6e 74 0a 2a 2a 20 69  uld prevent.** i
cde0: 74 20 66 72 6f 6d 20 64 6f 69 6e 67 20 73 6f 2e  t from doing so.
cdf0: 0a 2a 2f 0a 69 6e 74 20 6c 73 6d 53 68 6d 54 65  .*/.int lsmShmTe
ce00: 73 74 4c 6f 63 6b 28 0a 20 20 6c 73 6d 5f 64 62  stLock(.  lsm_db
ce10: 20 2a 64 62 2c 0a 20 20 69 6e 74 20 69 4c 6f 63   *db,.  int iLoc
ce20: 6b 2c 0a 20 20 69 6e 74 20 6e 4c 6f 63 6b 2c 0a  k,.  int nLock,.
ce30: 20 20 69 6e 74 20 65 4f 70 0a 29 7b 0a 20 20 69    int eOp.){.  i
ce40: 6e 74 20 72 63 20 3d 20 4c 53 4d 5f 4f 4b 3b 0a  nt rc = LSM_OK;.
ce50: 20 20 6c 73 6d 5f 64 62 20 2a 70 49 74 65 72 3b    lsm_db *pIter;
ce60: 0a 20 20 44 61 74 61 62 61 73 65 20 2a 70 20 3d  .  Database *p =
ce70: 20 64 62 2d 3e 70 44 61 74 61 62 61 73 65 3b 0a   db->pDatabase;.
ce80: 20 20 69 6e 74 20 69 3b 0a 20 20 75 36 34 20 6d    int i;.  u64 m
ce90: 61 73 6b 20 3d 20 30 3b 0a 0a 20 20 66 6f 72 28  ask = 0;..  for(
cea0: 69 3d 69 4c 6f 63 6b 3b 20 69 3c 28 69 4c 6f 63  i=iLock; i<(iLoc
ceb0: 6b 2b 6e 4c 6f 63 6b 29 3b 20 69 2b 2b 29 7b 0a  k+nLock); i++){.
cec0: 20 20 20 20 6d 61 73 6b 20 7c 3d 20 28 28 75 36      mask |= ((u6
ced0: 34 29 31 20 3c 3c 20 28 69 4c 6f 63 6b 2d 31 29  4)1 << (iLock-1)
cee0: 29 3b 0a 20 20 20 20 69 66 28 20 65 4f 70 3d 3d  );.    if( eOp==
cef0: 4c 53 4d 5f 4c 4f 43 4b 5f 45 58 43 4c 20 29 20  LSM_LOCK_EXCL ) 
cf00: 6d 61 73 6b 20 7c 3d 20 28 28 75 36 34 29 31 20  mask |= ((u64)1 
cf10: 3c 3c 20 28 69 4c 6f 63 6b 2b 33 32 2d 31 29 29  << (iLock+32-1))
cf20: 3b 0a 20 20 7d 0a 0a 20 20 6c 73 6d 4d 75 74 65  ;.  }..  lsmMute
cf30: 78 45 6e 74 65 72 28 64 62 2d 3e 70 45 6e 76 2c  xEnter(db->pEnv,
cf40: 20 70 2d 3e 70 43 6c 69 65 6e 74 4d 75 74 65 78   p->pClientMutex
cf50: 29 3b 0a 20 20 66 6f 72 28 70 49 74 65 72 3d 70  );.  for(pIter=p
cf60: 2d 3e 70 43 6f 6e 6e 3b 20 70 49 74 65 72 3b 20  ->pConn; pIter; 
cf70: 70 49 74 65 72 3d 70 49 74 65 72 2d 3e 70 4e 65  pIter=pIter->pNe
cf80: 78 74 29 7b 0a 20 20 20 20 69 66 28 20 70 49 74  xt){.    if( pIt
cf90: 65 72 21 3d 64 62 20 26 26 20 28 70 49 74 65 72  er!=db && (pIter
cfa0: 2d 3e 6d 4c 6f 63 6b 20 26 20 6d 61 73 6b 29 20  ->mLock & mask) 
cfb0: 29 7b 0a 20 20 20 20 20 20 61 73 73 65 72 74 28  ){.      assert(
cfc0: 20 70 49 74 65 72 21 3d 64 62 20 29 3b 0a 20 20   pIter!=db );.  
cfd0: 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 7d      break;.    }
cfe0: 0a 20 20 7d 0a 0a 20 20 69 66 28 20 70 49 74 65  .  }..  if( pIte
cff0: 72 20 29 7b 0a 20 20 20 20 72 63 20 3d 20 4c 53  r ){.    rc = LS
d000: 4d 5f 42 55 53 59 3b 0a 20 20 7d 65 6c 73 65 20  M_BUSY;.  }else 
d010: 69 66 28 20 70 2d 3e 62 4d 75 6c 74 69 50 72 6f  if( p->bMultiPro
d020: 63 20 29 7b 0a 20 20 20 20 72 63 20 3d 20 6c 73  c ){.    rc = ls
d030: 6d 45 6e 76 54 65 73 74 4c 6f 63 6b 28 64 62 2d  mEnvTestLock(db-
d040: 3e 70 45 6e 76 2c 20 70 2d 3e 70 46 69 6c 65 2c  >pEnv, p->pFile,
d050: 20 69 4c 6f 63 6b 2c 20 6e 4c 6f 63 6b 2c 20 65   iLock, nLock, e
d060: 4f 70 29 3b 0a 20 20 7d 0a 0a 20 20 6c 73 6d 4d  Op);.  }..  lsmM
d070: 75 74 65 78 4c 65 61 76 65 28 64 62 2d 3e 70 45  utexLeave(db->pE
d080: 6e 76 2c 20 70 2d 3e 70 43 6c 69 65 6e 74 4d 75  nv, p->pClientMu
d090: 74 65 78 29 3b 0a 20 20 72 65 74 75 72 6e 20 72  tex);.  return r
d0a0: 63 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 41 74 74 65  c;.}../*.** Atte
d0b0: 6d 70 74 20 74 6f 20 6f 62 74 61 69 6e 20 74 68  mpt to obtain th
d0c0: 65 20 6c 6f 63 6b 20 69 64 65 6e 74 69 66 69 65  e lock identifie
d0d0: 64 20 62 79 20 74 68 65 20 69 4c 6f 63 6b 20 61  d by the iLock a
d0e0: 6e 64 20 62 45 78 63 6c 20 70 61 72 61 6d 65 74  nd bExcl paramet
d0f0: 65 72 73 2e 0a 2a 2a 20 49 66 20 73 75 63 63 65  ers..** If succe
d100: 73 73 66 75 6c 2c 20 72 65 74 75 72 6e 20 4c 53  ssful, return LS
d110: 4d 5f 4f 4b 2e 20 49 66 20 74 68 65 20 6c 6f 63  M_OK. If the loc
d120: 6b 20 63 61 6e 6e 6f 74 20 62 65 20 6f 62 74 61  k cannot be obta
d130: 69 6e 65 64 20 62 65 63 61 75 73 65 20 0a 2a 2a  ined because .**
d140: 20 74 68 65 72 65 20 65 78 69 73 74 73 20 73 6f   there exists so
d150: 6d 65 20 6f 74 68 65 72 20 63 6f 6e 66 6c 69 63  me other conflic
d160: 74 69 6e 67 20 6c 6f 63 6b 2c 20 72 65 74 75 72  ting lock, retur
d170: 6e 20 4c 53 4d 5f 42 55 53 59 2e 20 49 66 20 73  n LSM_BUSY. If s
d180: 6f 6d 65 20 6f 74 68 65 72 0a 2a 2a 20 65 72 72  ome other.** err
d190: 6f 72 20 6f 63 63 75 72 73 2c 20 72 65 74 75 72  or occurs, retur
d1a0: 6e 20 61 6e 20 4c 53 4d 20 65 72 72 6f 72 20 63  n an LSM error c
d1b0: 6f 64 65 2e 0a 2a 2a 0a 2a 2a 20 50 61 72 61 6d  ode..**.** Param
d1c0: 65 74 65 72 20 69 4c 6f 63 6b 20 6d 75 73 74 20  eter iLock must 
d1d0: 62 65 20 6f 6e 65 20 6f 66 20 4c 53 4d 5f 4c 4f  be one of LSM_LO
d1e0: 43 4b 5f 57 52 49 54 45 52 2c 20 57 4f 52 4b 45  CK_WRITER, WORKE
d1f0: 52 20 6f 72 20 43 48 45 43 4b 50 4f 49 4e 54 45  R or CHECKPOINTE
d200: 52 2c 0a 2a 2a 20 6f 72 20 65 6c 73 65 20 61 20  R,.** or else a 
d210: 76 61 6c 75 65 20 72 65 74 75 72 6e 65 64 20 62  value returned b
d220: 79 20 74 68 65 20 4c 53 4d 5f 4c 4f 43 4b 5f 52  y the LSM_LOCK_R
d230: 45 41 44 45 52 20 6d 61 63 72 6f 2e 0a 2a 2f 0a  EADER macro..*/.
d240: 69 6e 74 20 6c 73 6d 53 68 6d 4c 6f 63 6b 28 0a  int lsmShmLock(.
d250: 20 20 6c 73 6d 5f 64 62 20 2a 64 62 2c 20 0a 20    lsm_db *db, . 
d260: 20 69 6e 74 20 69 4c 6f 63 6b 2c 0a 20 20 69 6e   int iLock,.  in
d270: 74 20 65 4f 70 2c 20 20 20 20 20 20 20 20 20 20  t eOp,          
d280: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
d290: 20 4f 6e 65 20 6f 66 20 4c 53 4d 5f 4c 4f 43 4b   One of LSM_LOCK
d2a0: 5f 55 4e 4c 4f 43 4b 2c 20 53 48 41 52 45 44 20  _UNLOCK, SHARED 
d2b0: 6f 72 20 45 58 43 4c 20 2a 2f 0a 20 20 69 6e 74  or EXCL */.  int
d2c0: 20 62 42 6c 6f 63 6b 20 20 20 20 20 20 20 20 20   bBlock         
d2d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
d2e0: 54 72 75 65 20 66 6f 72 20 61 20 62 6c 6f 63 6b  True for a block
d2f0: 69 6e 67 20 6c 6f 63 6b 20 2a 2f 0a 29 7b 0a 20  ing lock */.){. 
d300: 20 6c 73 6d 5f 64 62 20 2a 70 49 74 65 72 3b 0a   lsm_db *pIter;.
d310: 20 20 63 6f 6e 73 74 20 75 36 34 20 6d 65 20 3d    const u64 me =
d320: 20 28 28 75 36 34 29 31 20 3c 3c 20 28 69 4c 6f   ((u64)1 << (iLo
d330: 63 6b 2d 31 29 29 3b 0a 20 20 63 6f 6e 73 74 20  ck-1));.  const 
d340: 75 36 34 20 6d 73 20 3d 20 28 28 75 36 34 29 31  u64 ms = ((u64)1
d350: 20 3c 3c 20 28 69 4c 6f 63 6b 2b 33 32 2d 31 29   << (iLock+32-1)
d360: 29 3b 0a 20 20 69 6e 74 20 72 63 20 3d 20 4c 53  );.  int rc = LS
d370: 4d 5f 4f 4b 3b 0a 20 20 44 61 74 61 62 61 73 65  M_OK;.  Database
d380: 20 2a 70 20 3d 20 64 62 2d 3e 70 44 61 74 61 62   *p = db->pDatab
d390: 61 73 65 3b 0a 0a 20 20 61 73 73 65 72 74 28 20  ase;..  assert( 
d3a0: 65 4f 70 21 3d 4c 53 4d 5f 4c 4f 43 4b 5f 45 58  eOp!=LSM_LOCK_EX
d3b0: 43 4c 20 7c 7c 20 70 2d 3e 62 52 65 61 64 6f 6e  CL || p->bReadon
d3c0: 6c 79 3d 3d 30 20 29 3b 0a 20 20 61 73 73 65 72  ly==0 );.  asser
d3d0: 74 28 20 69 4c 6f 63 6b 3e 3d 31 20 26 26 20 69  t( iLock>=1 && i
d3e0: 4c 6f 63 6b 3c 3d 4c 53 4d 5f 4c 4f 43 4b 5f 52  Lock<=LSM_LOCK_R
d3f0: 57 43 4c 49 45 4e 54 28 4c 53 4d 5f 4c 4f 43 4b  WCLIENT(LSM_LOCK
d400: 5f 4e 52 57 43 4c 49 45 4e 54 2d 31 29 20 29 3b  _NRWCLIENT-1) );
d410: 0a 20 20 61 73 73 65 72 74 28 20 4c 53 4d 5f 4c  .  assert( LSM_L
d420: 4f 43 4b 5f 52 57 43 4c 49 45 4e 54 28 4c 53 4d  OCK_RWCLIENT(LSM
d430: 5f 4c 4f 43 4b 5f 4e 52 57 43 4c 49 45 4e 54 2d  _LOCK_NRWCLIENT-
d440: 31 29 3c 3d 33 32 20 29 3b 0a 20 20 61 73 73 65  1)<=32 );.  asse
d450: 72 74 28 20 65 4f 70 3d 3d 4c 53 4d 5f 4c 4f 43  rt( eOp==LSM_LOC
d460: 4b 5f 55 4e 4c 4f 43 4b 20 7c 7c 20 65 4f 70 3d  K_UNLOCK || eOp=
d470: 3d 4c 53 4d 5f 4c 4f 43 4b 5f 53 48 41 52 45 44  =LSM_LOCK_SHARED
d480: 20 7c 7c 20 65 4f 70 3d 3d 4c 53 4d 5f 4c 4f 43   || eOp==LSM_LOC
d490: 4b 5f 45 58 43 4c 20 29 3b 0a 0a 20 20 2f 2a 20  K_EXCL );..  /* 
d4a0: 43 68 65 63 6b 20 66 6f 72 20 61 20 6e 6f 2d 6f  Check for a no-o
d4b0: 70 2e 20 50 72 6f 63 65 65 64 20 6f 6e 6c 79 20  p. Proceed only 
d4c0: 69 66 20 74 68 69 73 20 69 73 20 6e 6f 74 20 6f  if this is not o
d4d0: 6e 65 20 6f 66 20 74 68 6f 73 65 2e 20 2a 2f 0a  ne of those. */.
d4e0: 20 20 69 66 28 20 28 65 4f 70 3d 3d 4c 53 4d 5f    if( (eOp==LSM_
d4f0: 4c 4f 43 4b 5f 55 4e 4c 4f 43 4b 20 26 26 20 28  LOCK_UNLOCK && (
d500: 64 62 2d 3e 6d 4c 6f 63 6b 20 26 20 28 6d 65 7c  db->mLock & (me|
d510: 6d 73 29 29 21 3d 30 29 0a 20 20 20 7c 7c 20 28  ms))!=0).   || (
d520: 65 4f 70 3d 3d 4c 53 4d 5f 4c 4f 43 4b 5f 53 48  eOp==LSM_LOCK_SH
d530: 41 52 45 44 20 26 26 20 28 64 62 2d 3e 6d 4c 6f  ARED && (db->mLo
d540: 63 6b 20 26 20 28 6d 65 7c 6d 73 29 29 21 3d 6d  ck & (me|ms))!=m
d550: 73 29 0a 20 20 20 7c 7c 20 28 65 4f 70 3d 3d 4c  s).   || (eOp==L
d560: 53 4d 5f 4c 4f 43 4b 5f 45 58 43 4c 20 20 20 26  SM_LOCK_EXCL   &
d570: 26 20 28 64 62 2d 3e 6d 4c 6f 63 6b 20 26 20 6d  & (db->mLock & m
d580: 65 29 3d 3d 30 29 0a 20 20 29 7b 0a 20 20 20 20  e)==0).  ){.    
d590: 69 6e 74 20 6e 45 78 63 6c 20 3d 20 30 3b 20 20  int nExcl = 0;  
d5a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
d5b0: 20 4e 75 6d 62 65 72 20 6f 66 20 63 6f 6e 6e 65   Number of conne
d5c0: 63 74 69 6f 6e 73 20 68 6f 6c 64 69 6e 67 20 45  ctions holding E
d5d0: 58 43 4c 55 53 49 56 45 20 2a 2f 0a 20 20 20 20  XCLUSIVE */.    
d5e0: 69 6e 74 20 6e 53 68 61 72 65 64 20 3d 20 30 3b  int nShared = 0;
d5f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
d600: 20 4e 75 6d 62 65 72 20 6f 66 20 63 6f 6e 6e 65   Number of conne
d610: 63 74 69 6f 6e 73 20 68 6f 6c 64 69 6e 67 20 53  ctions holding S
d620: 48 41 52 45 44 20 2a 2f 0a 20 20 20 20 6c 73 6d  HARED */.    lsm
d630: 4d 75 74 65 78 45 6e 74 65 72 28 64 62 2d 3e 70  MutexEnter(db->p
d640: 45 6e 76 2c 20 70 2d 3e 70 43 6c 69 65 6e 74 4d  Env, p->pClientM
d650: 75 74 65 78 29 3b 0a 0a 20 20 20 20 2f 2a 20 46  utex);..    /* F
d660: 69 67 75 72 65 20 6f 75 74 20 74 68 65 20 6c 6f  igure out the lo
d670: 63 6b 73 20 63 75 72 72 65 6e 74 6c 79 20 68 65  cks currently he
d680: 6c 64 20 62 79 20 74 68 69 73 20 70 72 6f 63 65  ld by this proce
d690: 73 73 20 6f 6e 20 69 4c 6f 63 6b 2c 20 6e 6f 74  ss on iLock, not
d6a0: 0a 20 20 20 20 2a 2a 20 69 6e 63 6c 75 64 69 6e  .    ** includin
d6b0: 67 20 61 6e 79 20 68 65 6c 64 20 62 79 20 63 6f  g any held by co
d6c0: 6e 6e 65 63 74 69 6f 6e 20 64 62 2e 20 20 2a 2f  nnection db.  */
d6d0: 0a 20 20 20 20 66 6f 72 28 70 49 74 65 72 3d 70  .    for(pIter=p
d6e0: 2d 3e 70 43 6f 6e 6e 3b 20 70 49 74 65 72 3b 20  ->pConn; pIter; 
d6f0: 70 49 74 65 72 3d 70 49 74 65 72 2d 3e 70 4e 65  pIter=pIter->pNe
d700: 78 74 29 7b 0a 20 20 20 20 20 20 61 73 73 65 72  xt){.      asser
d710: 74 28 20 28 70 49 74 65 72 2d 3e 6d 4c 6f 63 6b  t( (pIter->mLock
d720: 20 26 20 6d 65 29 3d 3d 30 20 7c 7c 20 28 70 49   & me)==0 || (pI
d730: 74 65 72 2d 3e 6d 4c 6f 63 6b 20 26 20 6d 73 29  ter->mLock & ms)
d740: 21 3d 30 20 29 3b 0a 20 20 20 20 20 20 69 66 28  !=0 );.      if(
d750: 20 70 49 74 65 72 21 3d 64 62 20 29 7b 0a 20 20   pIter!=db ){.  
d760: 20 20 20 20 20 20 69 66 28 20 70 49 74 65 72 2d        if( pIter-
d770: 3e 6d 4c 6f 63 6b 20 26 20 6d 65 20 29 7b 0a 20  >mLock & me ){. 
d780: 20 20 20 20 20 20 20 20 20 6e 45 78 63 6c 2b 2b           nExcl++
d790: 3b 0a 20 20 20 20 20 20 20 20 7d 65 6c 73 65 20  ;.        }else 
d7a0: 69 66 28 20 70 49 74 65 72 2d 3e 6d 4c 6f 63 6b  if( pIter->mLock
d7b0: 20 26 20 6d 73 20 29 7b 0a 20 20 20 20 20 20 20   & ms ){.       
d7c0: 20 20 20 6e 53 68 61 72 65 64 2b 2b 3b 0a 20 20     nShared++;.  
d7d0: 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 7d 0a        }.      }.
d7e0: 20 20 20 20 7d 0a 20 20 20 20 61 73 73 65 72 74      }.    assert
d7f0: 28 20 6e 45 78 63 6c 3d 3d 30 20 7c 7c 20 6e 45  ( nExcl==0 || nE
d800: 78 63 6c 3d 3d 31 20 29 3b 0a 20 20 20 20 61 73  xcl==1 );.    as
d810: 73 65 72 74 28 20 6e 45 78 63 6c 3d 3d 30 20 7c  sert( nExcl==0 |
d820: 7c 20 6e 53 68 61 72 65 64 3d 3d 30 20 29 3b 0a  | nShared==0 );.
d830: 20 20 20 20 61 73 73 65 72 74 28 20 6e 45 78 63      assert( nExc
d840: 6c 3d 3d 30 20 7c 7c 20 28 64 62 2d 3e 6d 4c 6f  l==0 || (db->mLo
d850: 63 6b 20 26 20 28 6d 65 7c 6d 73 29 29 3d 3d 30  ck & (me|ms))==0
d860: 20 29 3b 0a 0a 20 20 20 20 73 77 69 74 63 68 28   );..    switch(
d870: 20 65 4f 70 20 29 7b 0a 20 20 20 20 20 20 63 61   eOp ){.      ca
d880: 73 65 20 4c 53 4d 5f 4c 4f 43 4b 5f 55 4e 4c 4f  se LSM_LOCK_UNLO
d890: 43 4b 3a 0a 20 20 20 20 20 20 20 20 69 66 28 20  CK:.        if( 
d8a0: 6e 53 68 61 72 65 64 3d 3d 30 20 29 7b 0a 20 20  nShared==0 ){.  
d8b0: 20 20 20 20 20 20 20 20 6c 6f 63 6b 53 68 61 72          lockShar
d8c0: 65 64 46 69 6c 65 28 64 62 2d 3e 70 45 6e 76 2c  edFile(db->pEnv,
d8d0: 20 70 2c 20 69 4c 6f 63 6b 2c 20 4c 53 4d 5f 4c   p, iLock, LSM_L
d8e0: 4f 43 4b 5f 55 4e 4c 4f 43 4b 29 3b 0a 20 20 20  OCK_UNLOCK);.   
d8f0: 20 20 20 20 20 7d 0a 20 20 20 20 20 20 20 20 64       }.        d
d900: 62 2d 3e 6d 4c 6f 63 6b 20 26 3d 20 7e 28 6d 65  b->mLock &= ~(me
d910: 7c 6d 73 29 3b 0a 20 20 20 20 20 20 20 20 62 72  |ms);.        br
d920: 65 61 6b 3b 0a 0a 20 20 20 20 20 20 63 61 73 65  eak;..      case
d930: 20 4c 53 4d 5f 4c 4f 43 4b 5f 53 48 41 52 45 44   LSM_LOCK_SHARED
d940: 3a 0a 20 20 20 20 20 20 20 20 69 66 28 20 6e 45  :.        if( nE
d950: 78 63 6c 20 29 7b 0a 20 20 20 20 20 20 20 20 20  xcl ){.         
d960: 20 72 63 20 3d 20 4c 53 4d 5f 42 55 53 59 3b 0a   rc = LSM_BUSY;.
d970: 20 20 20 20 20 20 20 20 7d 65 6c 73 65 7b 0a 20          }else{. 
d980: 20 20 20 20 20 20 20 20 20 69 66 28 20 6e 53 68           if( nSh
d990: 61 72 65 64 3d 3d 30 20 29 7b 0a 20 20 20 20 20  ared==0 ){.     
d9a0: 20 20 20 20 20 20 20 72 63 20 3d 20 6c 6f 63 6b         rc = lock
d9b0: 53 68 61 72 65 64 46 69 6c 65 28 64 62 2d 3e 70  SharedFile(db->p
d9c0: 45 6e 76 2c 20 70 2c 20 69 4c 6f 63 6b 2c 20 4c  Env, p, iLock, L
d9d0: 53 4d 5f 4c 4f 43 4b 5f 53 48 41 52 45 44 29 3b  SM_LOCK_SHARED);
d9e0: 0a 20 20 20 20 20 20 20 20 20 20 7d 0a 20 20 20  .          }.   
d9f0: 20 20 20 20 20 20 20 69 66 28 20 72 63 3d 3d 4c         if( rc==L
da00: 53 4d 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 20  SM_OK ){.       
da10: 20 20 20 20 20 64 62 2d 3e 6d 4c 6f 63 6b 20 7c       db->mLock |
da20: 3d 20 6d 73 3b 0a 20 20 20 20 20 20 20 20 20 20  = ms;.          
da30: 20 20 64 62 2d 3e 6d 4c 6f 63 6b 20 26 3d 20 7e    db->mLock &= ~
da40: 6d 65 3b 0a 20 20 20 20 20 20 20 20 20 20 7d 0a  me;.          }.
da50: 20 20 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20          }.      
da60: 20 20 62 72 65 61 6b 3b 0a 0a 20 20 20 20 20 20    break;..      
da70: 64 65 66 61 75 6c 74 3a 0a 20 20 20 20 20 20 20  default:.       
da80: 20 61 73 73 65 72 74 28 20 65 4f 70 3d 3d 4c 53   assert( eOp==LS
da90: 4d 5f 4c 4f 43 4b 5f 45 58 43 4c 20 29 3b 0a 20  M_LOCK_EXCL );. 
daa0: 20 20 20 20 20 20 20 69 66 28 20 6e 45 78 63 6c         if( nExcl
dab0: 20 7c 7c 20 6e 53 68 61 72 65 64 20 29 7b 0a 20   || nShared ){. 
dac0: 20 20 20 20 20 20 20 20 20 72 63 20 3d 20 4c 53           rc = LS
dad0: 4d 5f 42 55 53 59 3b 0a 20 20 20 20 20 20 20 20  M_BUSY;.        
dae0: 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 20 20 20  }else{.         
daf0: 20 72 63 20 3d 20 6c 6f 63 6b 53 68 61 72 65 64   rc = lockShared
db00: 46 69 6c 65 28 64 62 2d 3e 70 45 6e 76 2c 20 70  File(db->pEnv, p
db10: 2c 20 69 4c 6f 63 6b 2c 20 4c 53 4d 5f 4c 4f 43  , iLock, LSM_LOC
db20: 4b 5f 45 58 43 4c 29 3b 0a 20 20 20 20 20 20 20  K_EXCL);.       
db30: 20 20 20 69 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f     if( rc==LSM_O
db40: 4b 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20 20  K ){.           
db50: 20 64 62 2d 3e 6d 4c 6f 63 6b 20 7c 3d 20 28 6d   db->mLock |= (m
db60: 65 7c 6d 73 29 3b 0a 20 20 20 20 20 20 20 20 20  e|ms);.         
db70: 20 7d 0a 20 20 20 20 20 20 20 20 7d 0a 20 20 20   }.        }.   
db80: 20 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20       break;.    
db90: 7d 0a 0a 20 20 20 20 6c 73 6d 4d 75 74 65 78 4c  }..    lsmMutexL
dba0: 65 61 76 65 28 64 62 2d 3e 70 45 6e 76 2c 20 70  eave(db->pEnv, p
dbb0: 2d 3e 70 43 6c 69 65 6e 74 4d 75 74 65 78 29 3b  ->pClientMutex);
dbc0: 0a 20 20 7d 0a 0a 20 20 72 65 74 75 72 6e 20 72  .  }..  return r
dbd0: 63 3b 0a 7d 0a 0a 23 69 66 64 65 66 20 4c 53 4d  c;.}..#ifdef LSM
dbe0: 5f 44 45 42 55 47 0a 0a 69 6e 74 20 73 68 6d 4c  _DEBUG..int shmL
dbf0: 6f 63 6b 54 79 70 65 28 6c 73 6d 5f 64 62 20 2a  ockType(lsm_db *
dc00: 64 62 2c 20 69 6e 74 20 69 4c 6f 63 6b 29 7b 0a  db, int iLock){.
dc10: 20 20 63 6f 6e 73 74 20 75 36 34 20 6d 65 20 3d    const u64 me =
dc20: 20 28 28 75 36 34 29 31 20 3c 3c 20 28 69 4c 6f   ((u64)1 << (iLo
dc30: 63 6b 2d 31 29 29 3b 0a 20 20 63 6f 6e 73 74 20  ck-1));.  const 
dc40: 75 36 34 20 6d 73 20 3d 20 28 28 75 36 34 29 31  u64 ms = ((u64)1
dc50: 20 3c 3c 20 28 69 4c 6f 63 6b 2b 33 32 2d 31 29   << (iLock+32-1)
dc60: 29 3b 0a 0a 20 20 69 66 28 20 64 62 2d 3e 6d 4c  );..  if( db->mL
dc70: 6f 63 6b 20 26 20 6d 65 20 29 20 72 65 74 75 72  ock & me ) retur
dc80: 6e 20 4c 53 4d 5f 4c 4f 43 4b 5f 45 58 43 4c 3b  n LSM_LOCK_EXCL;
dc90: 0a 20 20 69 66 28 20 64 62 2d 3e 6d 4c 6f 63 6b  .  if( db->mLock
dca0: 20 26 20 6d 73 20 29 20 72 65 74 75 72 6e 20 4c   & ms ) return L
dcb0: 53 4d 5f 4c 4f 43 4b 5f 53 48 41 52 45 44 3b 0a  SM_LOCK_SHARED;.
dcc0: 20 20 72 65 74 75 72 6e 20 4c 53 4d 5f 4c 4f 43    return LSM_LOC
dcd0: 4b 5f 55 4e 4c 4f 43 4b 3b 0a 7d 0a 0a 2f 2a 0a  K_UNLOCK;.}../*.
dce0: 2a 2a 20 54 68 65 20 61 72 67 75 6d 65 6e 74 73  ** The arguments
dcf0: 20 70 61 73 73 65 64 20 74 6f 20 74 68 69 73 20   passed to this 
dd00: 66 75 6e 63 74 69 6f 6e 20 61 72 65 20 73 69 6d  function are sim
dd10: 69 6c 61 72 20 74 6f 20 74 68 6f 73 65 20 70 61  ilar to those pa
dd20: 73 73 65 64 20 74 6f 0a 2a 2a 20 74 68 65 20 6c  ssed to.** the l
dd30: 73 6d 53 68 6d 4c 6f 63 6b 28 29 20 66 75 6e 63  smShmLock() func
dd40: 74 69 6f 6e 2e 20 48 6f 77 65 76 65 72 2c 20 69  tion. However, i
dd50: 6e 73 74 65 61 64 20 6f 66 20 6f 62 74 61 69 6e  nstead of obtain
dd60: 69 6e 67 20 61 20 6e 65 77 20 6c 6f 63 6b 20 0a  ing a new lock .
dd70: 2a 2a 20 74 68 69 73 20 66 75 6e 63 74 69 6f 6e  ** this function
dd80: 20 72 65 74 75 72 6e 73 20 74 72 75 65 20 69 66   returns true if
dd90: 20 74 68 65 20 73 70 65 63 69 66 69 65 64 20 63   the specified c
dda0: 6f 6e 6e 65 63 74 69 6f 6e 20 61 6c 72 65 61 64  onnection alread
ddb0: 79 20 68 6f 6c 64 73 20 0a 2a 2a 20 28 6f 72 20  y holds .** (or 
ddc0: 64 6f 65 73 20 6e 6f 74 20 68 6f 6c 64 29 20 73  does not hold) s
ddd0: 75 63 68 20 61 20 6c 6f 63 6b 2c 20 64 65 70 65  uch a lock, depe
dde0: 6e 64 69 6e 67 20 6f 6e 20 74 68 65 20 76 61 6c  nding on the val
ddf0: 75 65 20 6f 66 20 65 4f 70 2e 20 41 73 0a 2a 2a  ue of eOp. As.**
de00: 20 66 6f 6c 6c 6f 77 73 3a 0a 2a 2a 0a 2a 2a 20   follows:.**.** 
de10: 20 20 28 65 4f 70 3d 3d 4c 53 4d 5f 4c 4f 43 4b    (eOp==LSM_LOCK
de20: 5f 55 4e 4c 4f 43 4b 29 20 2d 3e 20 74 72 75 65  _UNLOCK) -> true
de30: 20 69 66 20 64 62 20 68 61 73 20 6e 6f 20 6c 6f   if db has no lo
de40: 63 6b 20 6f 6e 20 69 4c 6f 63 6b 0a 2a 2a 20 20  ck on iLock.**  
de50: 20 28 65 4f 70 3d 3d 4c 53 4d 5f 4c 4f 43 4b 5f   (eOp==LSM_LOCK_
de60: 53 48 41 52 45 44 29 20 2d 3e 20 74 72 75 65 20  SHARED) -> true 
de70: 69 66 20 64 62 20 68 61 73 20 61 74 20 6c 65 61  if db has at lea
de80: 73 74 20 61 20 53 48 41 52 45 44 20 6c 6f 63 6b  st a SHARED lock
de90: 20 6f 6e 20 69 4c 6f 63 6b 2e 0a 2a 2a 20 20 20   on iLock..**   
dea0: 28 65 4f 70 3d 3d 4c 53 4d 5f 4c 4f 43 4b 5f 45  (eOp==LSM_LOCK_E
deb0: 58 43 4c 29 20 20 20 2d 3e 20 74 72 75 65 20 69  XCL)   -> true i
dec0: 66 20 64 62 20 68 61 73 20 61 6e 20 45 58 43 4c  f db has an EXCL
ded0: 55 53 49 56 45 20 6c 6f 63 6b 20 6f 6e 20 69 4c  USIVE lock on iL
dee0: 6f 63 6b 2e 0a 2a 2f 0a 69 6e 74 20 6c 73 6d 53  ock..*/.int lsmS
def0: 68 6d 41 73 73 65 72 74 4c 6f 63 6b 28 6c 73 6d  hmAssertLock(lsm
df00: 5f 64 62 20 2a 64 62 2c 20 69 6e 74 20 69 4c 6f  _db *db, int iLo
df10: 63 6b 2c 20 69 6e 74 20 65 4f 70 29 7b 0a 20 20  ck, int eOp){.  
df20: 69 6e 74 20 72 65 74 20 3d 20 30 3b 0a 20 20 69  int ret = 0;.  i
df30: 6e 74 20 65 48 61 76 65 3b 0a 0a 20 20 61 73 73  nt eHave;..  ass
df40: 65 72 74 28 20 69 4c 6f 63 6b 3e 3d 31 20 26 26  ert( iLock>=1 &&
df50: 20 69 4c 6f 63 6b 3c 3d 4c 53 4d 5f 4c 4f 43 4b   iLock<=LSM_LOCK
df60: 5f 52 45 41 44 45 52 28 4c 53 4d 5f 4c 4f 43 4b  _READER(LSM_LOCK
df70: 5f 4e 52 45 41 44 45 52 2d 31 29 20 29 3b 0a 20  _NREADER-1) );. 
df80: 20 61 73 73 65 72 74 28 20 69 4c 6f 63 6b 3c 3d   assert( iLock<=
df90: 31 36 20 29 3b 0a 20 20 61 73 73 65 72 74 28 20  16 );.  assert( 
dfa0: 65 4f 70 3d 3d 4c 53 4d 5f 4c 4f 43 4b 5f 55 4e  eOp==LSM_LOCK_UN
dfb0: 4c 4f 43 4b 20 7c 7c 20 65 4f 70 3d 3d 4c 53 4d  LOCK || eOp==LSM
dfc0: 5f 4c 4f 43 4b 5f 53 48 41 52 45 44 20 7c 7c 20  _LOCK_SHARED || 
dfd0: 65 4f 70 3d 3d 4c 53 4d 5f 4c 4f 43 4b 5f 45 58  eOp==LSM_LOCK_EX
dfe0: 43 4c 20 29 3b 0a 0a 20 20 65 48 61 76 65 20 3d  CL );..  eHave =
dff0: 20 73 68 6d 4c 6f 63 6b 54 79 70 65 28 64 62 2c   shmLockType(db,
e000: 20 69 4c 6f 63 6b 29 3b 0a 0a 20 20 73 77 69 74   iLock);..  swit
e010: 63 68 28 20 65 4f 70 20 29 7b 0a 20 20 20 20 63  ch( eOp ){.    c
e020: 61 73 65 20 4c 53 4d 5f 4c 4f 43 4b 5f 55 4e 4c  ase LSM_LOCK_UNL
e030: 4f 43 4b 3a 0a 20 20 20 20 20 20 72 65 74 20 3d  OCK:.      ret =
e040: 20 28 65 48 61 76 65 3d 3d 4c 53 4d 5f 4c 4f 43   (eHave==LSM_LOC
e050: 4b 5f 55 4e 4c 4f 43 4b 29 3b 0a 20 20 20 20 20  K_UNLOCK);.     
e060: 20 62 72 65 61 6b 3b 0a 20 20 20 20 63 61 73 65   break;.    case
e070: 20 4c 53 4d 5f 4c 4f 43 4b 5f 53 48 41 52 45 44   LSM_LOCK_SHARED
e080: 3a 0a 20 20 20 20 20 20 72 65 74 20 3d 20 28 65  :.      ret = (e
e090: 48 61 76 65 21 3d 4c 53 4d 5f 4c 4f 43 4b 5f 55  Have!=LSM_LOCK_U
e0a0: 4e 4c 4f 43 4b 29 3b 0a 20 20 20 20 20 20 62 72  NLOCK);.      br
e0b0: 65 61 6b 3b 0a 20 20 20 20 63 61 73 65 20 4c 53  eak;.    case LS
e0c0: 4d 5f 4c 4f 43 4b 5f 45 58 43 4c 3a 0a 20 20 20  M_LOCK_EXCL:.   
e0d0: 20 20 20 72 65 74 20 3d 20 28 65 48 61 76 65 3d     ret = (eHave=
e0e0: 3d 4c 53 4d 5f 4c 4f 43 4b 5f 45 58 43 4c 29 3b  =LSM_LOCK_EXCL);
e0f0: 0a 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20 20  .      break;.  
e100: 20 20 64 65 66 61 75 6c 74 3a 0a 20 20 20 20 20    default:.     
e110: 20 61 73 73 65 72 74 28 20 21 22 62 61 64 20 65   assert( !"bad e
e120: 4f 70 20 76 61 6c 75 65 20 70 61 73 73 65 64 20  Op value passed 
e130: 74 6f 20 6c 73 6d 53 68 6d 41 73 73 65 72 74 4c  to lsmShmAssertL
e140: 6f 63 6b 28 29 22 20 29 3b 0a 20 20 20 20 20 20  ock()" );.      
e150: 62 72 65 61 6b 3b 0a 20 20 7d 0a 0a 20 20 72 65  break;.  }..  re
e160: 74 75 72 6e 20 72 65 74 3b 0a 7d 0a 0a 69 6e 74  turn ret;.}..int
e170: 20 6c 73 6d 53 68 6d 41 73 73 65 72 74 57 6f 72   lsmShmAssertWor
e180: 6b 65 72 28 6c 73 6d 5f 64 62 20 2a 64 62 29 7b  ker(lsm_db *db){
e190: 0a 20 20 72 65 74 75 72 6e 20 6c 73 6d 53 68 6d  .  return lsmShm
e1a0: 41 73 73 65 72 74 4c 6f 63 6b 28 64 62 2c 20 4c  AssertLock(db, L
e1b0: 53 4d 5f 4c 4f 43 4b 5f 57 4f 52 4b 45 52 2c 20  SM_LOCK_WORKER, 
e1c0: 4c 53 4d 5f 4c 4f 43 4b 5f 45 58 43 4c 29 20 26  LSM_LOCK_EXCL) &
e1d0: 26 20 64 62 2d 3e 70 57 6f 72 6b 65 72 3b 0a 7d  & db->pWorker;.}
e1e0: 0a 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20 66 75 6e  ../*.** This fun
e1f0: 63 74 69 6f 6e 20 64 6f 65 73 20 6e 6f 74 20 63  ction does not c
e200: 6f 6e 74 72 69 62 75 74 65 20 74 6f 20 6c 69 62  ontribute to lib
e210: 72 61 72 79 20 66 75 6e 63 74 69 6f 6e 61 6c 69  rary functionali
e220: 74 79 2c 20 61 6e 64 20 69 73 20 6e 6f 74 0a 2a  ty, and is not.*
e230: 2a 20 69 6e 63 6c 75 64 65 64 20 69 6e 20 72 65  * included in re
e240: 6c 65 61 73 65 20 62 75 69 6c 64 73 2e 20 49 74  lease builds. It
e250: 20 69 73 20 69 6e 74 65 6e 64 65 64 20 74 6f 20   is intended to 
e260: 62 65 20 63 61 6c 6c 65 64 20 66 72 6f 6d 20 77  be called from w
e270: 69 74 68 69 6e 0a 2a 2a 20 61 6e 20 69 6e 74 65  ithin.** an inte
e280: 72 61 63 74 69 76 65 20 64 65 62 75 67 67 65 72  ractive debugger
e290: 2e 0a 2a 2a 0a 2a 2a 20 57 68 65 6e 20 63 61 6c  ..**.** When cal
e2a0: 6c 65 64 2c 20 74 68 69 73 20 66 75 6e 63 74 69  led, this functi
e2b0: 6f 6e 20 70 72 69 6e 74 73 20 61 20 73 69 6e 67  on prints a sing
e2c0: 6c 65 20 6c 69 6e 65 20 6f 66 20 68 75 6d 61 6e  le line of human
e2d0: 20 72 65 61 64 61 62 6c 65 20 6f 75 74 70 75 74   readable output
e2e0: 0a 2a 2a 20 74 6f 20 73 74 64 6f 75 74 20 64 65  .** to stdout de
e2f0: 73 63 72 69 62 69 6e 67 20 74 68 65 20 6c 6f 63  scribing the loc
e300: 6b 73 20 63 75 72 72 65 6e 74 6c 79 20 68 65 6c  ks currently hel
e310: 64 20 62 79 20 74 68 65 20 63 6f 6e 6e 65 63 74  d by the connect
e320: 69 6f 6e 2e 20 46 6f 72 20 0a 2a 2a 20 65 78 61  ion. For .** exa
e330: 6d 70 6c 65 3a 0a 2a 2a 0a 2a 2a 20 20 20 20 20  mple:.**.**     
e340: 28 67 64 62 29 20 63 61 6c 6c 20 70 72 69 6e 74  (gdb) call print
e350: 5f 64 62 5f 6c 6f 63 6b 73 28 70 44 62 29 0a 2a  _db_locks(pDb).*
e360: 2a 20 20 20 20 20 28 73 68 61 72 65 64 20 6f 6e  *     (shared on
e370: 20 64 6d 73 32 29 20 28 65 78 63 6c 75 73 69 76   dms2) (exclusiv
e380: 65 20 6f 6e 20 77 72 69 74 65 72 29 20 0a 2a 2f  e on writer) .*/
e390: 0a 76 6f 69 64 20 70 72 69 6e 74 5f 64 62 5f 6c  .void print_db_l
e3a0: 6f 63 6b 73 28 6c 73 6d 5f 64 62 20 2a 64 62 29  ocks(lsm_db *db)
e3b0: 7b 0a 20 20 69 6e 74 20 69 4c 6f 63 6b 3b 0a 20  {.  int iLock;. 
e3c0: 20 66 6f 72 28 69 4c 6f 63 6b 3d 30 3b 20 69 4c   for(iLock=0; iL
e3d0: 6f 63 6b 3c 31 36 3b 20 69 4c 6f 63 6b 2b 2b 29  ock<16; iLock++)
e3e0: 7b 0a 20 20 20 20 69 6e 74 20 62 4f 6e 65 20 3d  {.    int bOne =
e3f0: 20 30 3b 0a 20 20 20 20 63 6f 6e 73 74 20 63 68   0;.    const ch
e400: 61 72 20 2a 61 7a 4c 6f 63 6b 5b 5d 20 3d 20 7b  ar *azLock[] = {
e410: 30 2c 20 22 73 68 61 72 65 64 22 2c 20 22 65 78  0, "shared", "ex
e420: 63 6c 75 73 69 76 65 22 7d 3b 0a 20 20 20 20 63  clusive"};.    c
e430: 6f 6e 73 74 20 63 68 61 72 20 2a 61 7a 4e 61 6d  onst char *azNam
e440: 65 5b 5d 20 3d 20 7b 0a 20 20 20 20 20 20 30 2c  e[] = {.      0,
e450: 20 22 64 6d 73 31 22 2c 20 22 64 6d 73 32 22 2c   "dms1", "dms2",
e460: 20 22 77 72 69 74 65 72 22 2c 20 22 77 6f 72 6b   "writer", "work
e470: 65 72 22 2c 20 22 63 68 65 63 6b 70 6f 69 6e 74  er", "checkpoint
e480: 65 72 22 2c 0a 20 20 20 20 20 20 22 72 65 61 64  er",.      "read
e490: 65 72 30 22 2c 20 22 72 65 61 64 65 72 31 22 2c  er0", "reader1",
e4a0: 20 22 72 65 61 64 65 72 32 22 2c 20 22 72 65 61   "reader2", "rea
e4b0: 64 65 72 33 22 2c 20 22 72 65 61 64 65 72 34 22  der3", "reader4"
e4c0: 2c 20 22 72 65 61 64 65 72 35 22 0a 20 20 20 20  , "reader5".    
e4d0: 7d 3b 0a 20 20 20 20 69 6e 74 20 65 48 61 76 65  };.    int eHave
e4e0: 20 3d 20 73 68 6d 4c 6f 63 6b 54 79 70 65 28 64   = shmLockType(d
e4f0: 62 2c 20 69 4c 6f 63 6b 29 3b 0a 20 20 20 20 69  b, iLock);.    i
e500: 66 28 20 61 7a 4c 6f 63 6b 5b 65 48 61 76 65 5d  f( azLock[eHave]
e510: 20 29 7b 0a 20 20 20 20 20 20 70 72 69 6e 74 66   ){.      printf
e520: 28 22 25 73 28 25 73 20 6f 6e 20 25 73 29 22 2c  ("%s(%s on %s)",
e530: 20 28 62 4f 6e 65 3f 22 20 22 3a 22 22 29 2c 20   (bOne?" ":""), 
e540: 61 7a 4c 6f 63 6b 5b 65 48 61 76 65 5d 2c 20 61  azLock[eHave], a
e550: 7a 4e 61 6d 65 5b 69 4c 6f 63 6b 5d 29 3b 0a 20  zName[iLock]);. 
e560: 20 20 20 20 20 62 4f 6e 65 20 3d 20 31 3b 0a 20       bOne = 1;. 
e570: 20 20 20 7d 0a 20 20 7d 0a 20 20 70 72 69 6e 74     }.  }.  print
e580: 66 28 22 5c 6e 22 29 3b 0a 7d 0a 76 6f 69 64 20  f("\n");.}.void 
e590: 70 72 69 6e 74 5f 61 6c 6c 5f 64 62 5f 6c 6f 63  print_all_db_loc
e5a0: 6b 73 28 6c 73 6d 5f 64 62 20 2a 64 62 29 7b 0a  ks(lsm_db *db){.
e5b0: 20 20 6c 73 6d 5f 64 62 20 2a 70 3b 0a 20 20 66    lsm_db *p;.  f
e5c0: 6f 72 28 70 3d 64 62 2d 3e 70 44 61 74 61 62 61  or(p=db->pDataba
e5d0: 73 65 2d 3e 70 43 6f 6e 6e 3b 20 70 3b 20 70 3d  se->pConn; p; p=
e5e0: 70 2d 3e 70 4e 65 78 74 29 7b 0a 20 20 20 20 70  p->pNext){.    p
e5f0: 72 69 6e 74 66 28 22 25 73 20 63 6f 6e 6e 65 63  rintf("%s connec
e600: 74 69 6f 6e 20 25 70 20 22 2c 20 28 28 70 3d 3d  tion %p ", ((p==
e610: 64 62 29 3f 22 2a 22 3a 22 22 29 2c 20 70 29 3b  db)?"*":""), p);
e620: 0a 20 20 20 20 70 72 69 6e 74 5f 64 62 5f 6c 6f  .    print_db_lo
e630: 63 6b 73 28 70 29 3b 0a 20 20 7d 0a 7d 0a 23 65  cks(p);.  }.}.#e
e640: 6e 64 69 66 0a 0a 76 6f 69 64 20 6c 73 6d 53 68  ndif..void lsmSh
e650: 6d 42 61 72 72 69 65 72 28 6c 73 6d 5f 64 62 20  mBarrier(lsm_db 
e660: 2a 64 62 29 7b 0a 20 20 6c 73 6d 45 6e 76 53 68  *db){.  lsmEnvSh
e670: 6d 42 61 72 72 69 65 72 28 64 62 2d 3e 70 45 6e  mBarrier(db->pEn
e680: 76 29 3b 0a 7d 0a 0a 69 6e 74 20 6c 73 6d 5f 63  v);.}..int lsm_c
e690: 68 65 63 6b 70 6f 69 6e 74 28 6c 73 6d 5f 64 62  heckpoint(lsm_db
e6a0: 20 2a 70 44 62 2c 20 69 6e 74 20 2a 70 6e 4b 42   *pDb, int *pnKB
e6b0: 29 7b 0a 20 20 69 6e 74 20 72 63 3b 20 20 20 20  ){.  int rc;    
e6c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
e6d0: 20 20 20 20 20 2f 2a 20 52 65 74 75 72 6e 20 63       /* Return c
e6e0: 6f 64 65 20 2a 2f 0a 20 20 75 33 32 20 6e 57 72  ode */.  u32 nWr
e6f0: 69 74 65 20 3d 20 30 3b 20 20 20 20 20 20 20 20  ite = 0;        
e700: 20 20 20 20 20 20 20 20 20 2f 2a 20 4e 75 6d 62           /* Numb
e710: 65 72 20 6f 66 20 70 61 67 65 73 20 63 68 65 63  er of pages chec
e720: 6b 70 6f 69 6e 74 65 64 20 2a 2f 0a 0a 20 20 2f  kpointed */..  /
e730: 2a 20 41 74 74 65 6d 70 74 20 74 68 65 20 63 68  * Attempt the ch
e740: 65 63 6b 70 6f 69 6e 74 2e 20 49 66 20 73 75 63  eckpoint. If suc
e750: 63 65 73 73 66 75 6c 2c 20 6e 57 72 69 74 65 20  cessful, nWrite 
e760: 69 73 20 73 65 74 20 74 6f 20 74 68 65 20 6e 75  is set to the nu
e770: 6d 62 65 72 20 6f 66 0a 20 20 2a 2a 20 70 61 67  mber of.  ** pag
e780: 65 73 20 77 72 69 74 74 65 6e 20 62 65 74 77 65  es written betwe
e790: 65 6e 20 74 68 69 73 20 61 6e 64 20 74 68 65 20  en this and the 
e7a0: 70 72 65 76 69 6f 75 73 20 63 68 65 63 6b 70 6f  previous checkpo
e7b0: 69 6e 74 2e 20 20 2a 2f 0a 20 20 72 63 20 3d 20  int.  */.  rc = 
e7c0: 6c 73 6d 43 68 65 63 6b 70 6f 69 6e 74 57 72 69  lsmCheckpointWri
e7d0: 74 65 28 70 44 62 2c 20 26 6e 57 72 69 74 65 29  te(pDb, &nWrite)
e7e0: 3b 0a 0a 20 20 2f 2a 20 49 66 20 72 65 71 75 69  ;..  /* If requi
e7f0: 72 65 64 2c 20 63 61 6c 63 75 6c 61 74 65 20 74  red, calculate t
e800: 68 65 20 6f 75 74 70 75 74 20 76 61 72 69 61 62  he output variab
e810: 6c 65 20 28 4b 42 20 6f 66 20 64 61 74 61 20 63  le (KB of data c
e820: 68 65 63 6b 70 6f 69 6e 74 65 64 29 2e 20 0a 20  heckpointed). . 
e830: 20 2a 2a 20 53 65 74 20 69 74 20 74 6f 20 7a 65   ** Set it to ze
e840: 72 6f 20 69 66 20 61 6e 20 65 72 72 6f 72 20 6f  ro if an error o
e850: 63 63 75 72 65 64 2e 20 20 2a 2f 0a 20 20 69 66  ccured.  */.  if
e860: 28 20 70 6e 4b 42 20 29 7b 0a 20 20 20 20 69 6e  ( pnKB ){.    in
e870: 74 20 6e 4b 42 20 3d 20 30 3b 0a 20 20 20 20 69  t nKB = 0;.    i
e880: 66 28 20 72 63 3d 3d 4c 53 4d 5f 4f 4b 20 26 26  f( rc==LSM_OK &&
e890: 20 6e 57 72 69 74 65 20 29 7b 0a 20 20 20 20 20   nWrite ){.     
e8a0: 20 6e 4b 42 20 3d 20 28 28 28 69 36 34 29 6e 57   nKB = (((i64)nW
e8b0: 72 69 74 65 20 2a 20 6c 73 6d 46 73 50 61 67 65  rite * lsmFsPage
e8c0: 53 69 7a 65 28 70 44 62 2d 3e 70 46 53 29 29 20  Size(pDb->pFS)) 
e8d0: 2b 20 31 30 32 33 29 20 2f 20 31 30 32 34 3b 0a  + 1023) / 1024;.
e8e0: 20 20 20 20 7d 0a 20 20 20 20 2a 70 6e 4b 42 20      }.    *pnKB 
e8f0: 3d 20 6e 4b 42 3b 0a 20 20 7d 0a 0a 20 20 72 65  = nKB;.  }..  re
e900: 74 75 72 6e 20 72 63 3b 0a 7d 0a                 turn rc;.}.