/ Hex Artifact Content
Login

Artifact 0decc630b683979cb32d4b965efd90b6e55a786e:


0000: 2f 2a 0a 2a 2a 20 32 30 31 30 20 4f 63 74 6f 62  /*.** 2010 Octob
0010: 65 72 20 32 38 0a 2a 2a 0a 2a 2a 20 54 68 65 20  er 28.**.** The 
0020: 61 75 74 68 6f 72 20 64 69 73 63 6c 61 69 6d 73  author disclaims
0030: 20 63 6f 70 79 72 69 67 68 74 20 74 6f 20 74 68   copyright to th
0040: 69 73 20 73 6f 75 72 63 65 20 63 6f 64 65 2e 20  is source code. 
0050: 20 49 6e 20 70 6c 61 63 65 20 6f 66 0a 2a 2a 20   In place of.** 
0060: 61 20 6c 65 67 61 6c 20 6e 6f 74 69 63 65 2c 20  a legal notice, 
0070: 68 65 72 65 20 69 73 20 61 20 62 6c 65 73 73 69  here is a blessi
0080: 6e 67 3a 0a 2a 2a 0a 2a 2a 20 20 20 20 4d 61 79  ng:.**.**    May
0090: 20 79 6f 75 20 64 6f 20 67 6f 6f 64 20 61 6e 64   you do good and
00a0: 20 6e 6f 74 20 65 76 69 6c 2e 0a 2a 2a 20 20 20   not evil..**   
00b0: 20 4d 61 79 20 79 6f 75 20 66 69 6e 64 20 66 6f   May you find fo
00c0: 72 67 69 76 65 6e 65 73 73 20 66 6f 72 20 79 6f  rgiveness for yo
00d0: 75 72 73 65 6c 66 20 61 6e 64 20 66 6f 72 67 69  urself and forgi
00e0: 76 65 20 6f 74 68 65 72 73 2e 0a 2a 2a 20 20 20  ve others..**   
00f0: 20 4d 61 79 20 79 6f 75 20 73 68 61 72 65 20 66   May you share f
0100: 72 65 65 6c 79 2c 20 6e 65 76 65 72 20 74 61 6b  reely, never tak
0110: 69 6e 67 20 6d 6f 72 65 20 74 68 61 6e 20 79 6f  ing more than yo
0120: 75 20 67 69 76 65 2e 0a 2a 2a 0a 2a 2a 2a 2a 2a  u give..**.*****
0130: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0140: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0150: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0160: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0170: 2a 2a 2a 2a 0a 2a 2a 0a 2a 2a 20 54 68 69 73 20  ****.**.** This 
0180: 66 69 6c 65 20 63 6f 6e 74 61 69 6e 73 20 61 20  file contains a 
0190: 56 46 53 20 22 73 68 69 6d 22 20 2d 20 61 20 6c  VFS "shim" - a l
01a0: 61 79 65 72 20 74 68 61 74 20 73 69 74 73 20 69  ayer that sits i
01b0: 6e 20 62 65 74 77 65 65 6e 20 74 68 65 0a 2a 2a  n between the.**
01c0: 20 70 61 67 65 72 20 61 6e 64 20 74 68 65 20 72   pager and the r
01d0: 65 61 6c 20 56 46 53 20 2d 20 74 68 61 74 20 62  eal VFS - that b
01e0: 72 65 61 6b 73 20 75 70 20 61 20 76 65 72 79 20  reaks up a very 
01f0: 6c 61 72 67 65 20 64 61 74 61 62 61 73 65 20 66  large database f
0200: 69 6c 65 0a 2a 2a 20 69 6e 74 6f 20 74 77 6f 20  ile.** into two 
0210: 6f 72 20 6d 6f 72 65 20 73 6d 61 6c 6c 65 72 20  or more smaller 
0220: 66 69 6c 65 73 20 6f 6e 20 64 69 73 6b 2e 20 20  files on disk.  
0230: 54 68 69 73 20 69 73 20 75 73 65 66 75 6c 2c 20  This is useful, 
0240: 66 6f 72 20 65 78 61 6d 70 6c 65 2c 0a 2a 2a 20  for example,.** 
0250: 69 6e 20 6f 72 64 65 72 20 74 6f 20 73 75 70 70  in order to supp
0260: 6f 72 74 20 6c 61 72 67 65 2c 20 6d 75 6c 74 69  ort large, multi
0270: 2d 67 69 67 61 62 79 74 65 20 64 61 74 61 62 61  -gigabyte databa
0280: 73 65 73 20 6f 6e 20 6f 6c 64 65 72 20 66 69 6c  ses on older fil
0290: 65 73 79 73 74 65 6d 73 0a 2a 2a 20 74 68 61 74  esystems.** that
02a0: 20 6c 69 6d 69 74 20 74 68 65 20 6d 61 78 69 6d   limit the maxim
02b0: 75 6d 20 66 69 6c 65 20 73 69 7a 65 20 74 6f 20  um file size to 
02c0: 32 20 47 69 42 2e 0a 2a 2a 0a 2a 2a 20 55 53 41  2 GiB..**.** USA
02d0: 47 45 3a 0a 2a 2a 0a 2a 2a 20 43 6f 6d 70 69 6c  GE:.**.** Compil
02e0: 65 20 74 68 69 73 20 73 6f 75 72 63 65 20 66 69  e this source fi
02f0: 6c 65 20 61 6e 64 20 6c 69 6e 6b 20 69 74 20 77  le and link it w
0300: 69 74 68 20 79 6f 75 72 20 61 70 70 6c 69 63 61  ith your applica
0310: 74 69 6f 6e 2e 20 20 54 68 65 6e 0a 2a 2a 20 61  tion.  Then.** a
0320: 74 20 73 74 61 72 74 2d 74 69 6d 65 2c 20 69 6e  t start-time, in
0330: 76 6f 6b 65 20 74 68 65 20 66 6f 6c 6c 6f 77 69  voke the followi
0340: 6e 67 20 70 72 6f 63 65 64 75 72 65 3a 0a 2a 2a  ng procedure:.**
0350: 0a 2a 2a 20 20 20 69 6e 74 20 73 71 6c 69 74 65  .**   int sqlite
0360: 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 69 6e 69 74  3_multiplex_init
0370: 69 61 6c 69 7a 65 28 0a 2a 2a 20 20 20 20 20 20  ialize(.**      
0380: 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 4f 72 69  const char *zOri
0390: 67 56 66 73 4e 61 6d 65 2c 20 20 20 20 2f 2f 20  gVfsName,    // 
03a0: 54 68 65 20 75 6e 64 65 72 6c 79 69 6e 67 20 72  The underlying r
03b0: 65 61 6c 20 56 46 53 0a 2a 2a 20 20 20 20 20 20  eal VFS.**      
03c0: 69 6e 74 20 6d 61 6b 65 44 65 66 61 75 6c 74 20  int makeDefault 
03d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2f 20               // 
03e0: 54 72 75 65 20 74 6f 20 6d 61 6b 65 20 6d 75 6c  True to make mul
03f0: 74 69 70 6c 65 78 20 74 68 65 20 64 65 66 61 75  tiplex the defau
0400: 6c 74 20 56 46 53 0a 2a 2a 20 20 20 29 3b 0a 2a  lt VFS.**   );.*
0410: 2a 0a 2a 2a 20 54 68 65 20 70 72 6f 63 65 64 75  *.** The procedu
0420: 72 65 20 63 61 6c 6c 20 61 62 6f 76 65 20 77 69  re call above wi
0430: 6c 6c 20 63 72 65 61 74 65 20 61 6e 64 20 72 65  ll create and re
0440: 67 69 73 74 65 72 20 61 20 6e 65 77 20 56 46 53  gister a new VFS
0450: 20 73 68 69 6d 20 6e 61 6d 65 64 0a 2a 2a 20 22   shim named.** "
0460: 6d 75 6c 74 69 70 6c 65 78 22 2e 20 20 54 68 65  multiplex".  The
0470: 20 6d 75 6c 74 69 70 6c 65 78 20 56 46 53 20 77   multiplex VFS w
0480: 69 6c 6c 20 75 73 65 20 74 68 65 20 56 46 53 20  ill use the VFS 
0490: 6e 61 6d 65 64 20 62 79 20 7a 4f 72 69 67 56 66  named by zOrigVf
04a0: 73 4e 61 6d 65 20 74 6f 0a 2a 2a 20 64 6f 20 74  sName to.** do t
04b0: 68 65 20 61 63 74 75 61 6c 20 64 69 73 6b 20 49  he actual disk I
04c0: 2f 4f 2e 20 20 28 54 68 65 20 7a 4f 72 69 67 56  /O.  (The zOrigV
04d0: 66 73 4e 61 6d 65 20 70 61 72 61 6d 65 74 65 72  fsName parameter
04e0: 20 6d 61 79 20 62 65 20 4e 55 4c 4c 2c 20 69 6e   may be NULL, in
04f0: 20 0a 2a 2a 20 77 68 69 63 68 20 63 61 73 65 20   .** which case 
0500: 74 68 65 20 64 65 66 61 75 6c 74 20 56 46 53 20  the default VFS 
0510: 61 74 20 74 68 65 20 6d 6f 6d 65 6e 74 20 73 71  at the moment sq
0520: 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f  lite3_multiplex_
0530: 69 6e 69 74 69 61 6c 69 7a 65 28 29 0a 2a 2a 20  initialize().** 
0540: 69 73 20 63 61 6c 6c 65 64 20 77 69 6c 6c 20 62  is called will b
0550: 65 20 75 73 65 64 20 61 73 20 74 68 65 20 75 6e  e used as the un
0560: 64 65 72 6c 79 69 6e 67 20 72 65 61 6c 20 56 46  derlying real VF
0570: 53 2e 29 20 20 0a 2a 2a 0a 2a 2a 20 49 66 20 74  S.)  .**.** If t
0580: 68 65 20 6d 61 6b 65 44 65 66 61 75 6c 74 20 70  he makeDefault p
0590: 61 72 61 6d 65 74 65 72 20 69 73 20 54 52 55 45  arameter is TRUE
05a0: 20 74 68 65 6e 20 6d 75 6c 74 69 70 6c 65 78 20   then multiplex 
05b0: 62 65 63 6f 6d 65 73 20 74 68 65 20 6e 65 77 0a  becomes the new.
05c0: 2a 2a 20 64 65 66 61 75 6c 74 20 56 46 53 2e 20  ** default VFS. 
05d0: 20 4f 74 68 65 72 77 69 73 65 2c 20 79 6f 75 20   Otherwise, you 
05e0: 63 61 6e 20 75 73 65 20 74 68 65 20 6d 75 6c 74  can use the mult
05f0: 69 70 6c 65 78 20 56 46 53 20 62 79 20 73 70 65  iplex VFS by spe
0600: 63 69 66 79 69 6e 67 0a 2a 2a 20 22 6d 75 6c 74  cifying.** "mult
0610: 69 70 6c 65 78 22 20 61 73 20 74 68 65 20 34 74  iplex" as the 4t
0620: 68 20 70 61 72 61 6d 65 74 65 72 20 74 6f 20 73  h parameter to s
0630: 71 6c 69 74 65 33 5f 6f 70 65 6e 5f 76 32 28 29  qlite3_open_v2()
0640: 20 6f 72 20 62 79 20 65 6d 70 6c 6f 79 69 6e 67   or by employing
0650: 0a 2a 2a 20 55 52 49 20 66 69 6c 65 6e 61 6d 65  .** URI filename
0660: 73 20 61 6e 64 20 61 64 64 69 6e 67 20 22 76 66  s and adding "vf
0670: 73 3d 6d 75 6c 74 69 70 6c 65 78 22 20 61 73 20  s=multiplex" as 
0680: 61 20 70 61 72 61 6d 65 74 65 72 20 74 6f 20 74  a parameter to t
0690: 68 65 20 66 69 6c 65 6e 61 6d 65 0a 2a 2a 20 55  he filename.** U
06a0: 52 49 2e 0a 2a 2a 0a 2a 2a 20 54 68 65 20 6d 75  RI..**.** The mu
06b0: 6c 74 69 70 6c 65 78 20 56 46 53 20 61 6c 6c 6f  ltiplex VFS allo
06c0: 77 73 20 64 61 74 61 62 61 73 65 73 20 75 70 20  ws databases up 
06d0: 74 6f 20 33 32 20 47 69 42 20 69 6e 20 73 69 7a  to 32 GiB in siz
06e0: 65 2e 20 20 42 75 74 20 69 74 20 73 70 6c 69 74  e.  But it split
06f0: 73 0a 2a 2a 20 74 68 65 20 66 69 6c 65 73 20 75  s.** the files u
0700: 70 20 69 6e 74 6f 20 73 6d 61 6c 6c 65 72 20 70  p into smaller p
0710: 69 65 63 65 73 2c 20 73 6f 20 74 68 61 74 20 74  ieces, so that t
0720: 68 65 79 20 77 69 6c 6c 20 77 6f 72 6b 20 65 76  hey will work ev
0730: 65 6e 20 6f 6e 20 0a 2a 2a 20 66 69 6c 65 73 79  en on .** filesy
0740: 73 74 65 6d 73 20 74 68 61 74 20 64 6f 20 6e 6f  stems that do no
0750: 74 20 73 75 70 70 6f 72 74 20 6c 61 72 67 65 20  t support large 
0760: 66 69 6c 65 73 2e 20 20 54 68 65 20 64 65 66 61  files.  The defa
0770: 75 6c 74 20 63 68 75 6e 6b 20 73 69 7a 65 0a 2a  ult chunk size.*
0780: 2a 20 69 73 20 32 31 34 37 34 31 38 31 31 32 20  * is 2147418112 
0790: 62 79 74 65 73 20 28 77 68 69 63 68 20 69 73 20  bytes (which is 
07a0: 36 34 4b 69 42 20 6c 65 73 73 20 74 68 61 6e 20  64KiB less than 
07b0: 32 47 69 42 29 20 62 75 74 20 74 68 69 73 20 63  2GiB) but this c
07c0: 61 6e 20 62 65 0a 2a 2a 20 63 68 61 6e 67 65 64  an be.** changed
07d0: 20 61 74 20 63 6f 6d 70 69 6c 65 2d 74 69 6d 65   at compile-time
07e0: 20 62 79 20 64 65 66 69 6e 69 6e 67 20 74 68 65   by defining the
07f0: 20 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45   SQLITE_MULTIPLE
0800: 58 5f 43 48 55 4e 4b 5f 53 49 5a 45 0a 2a 2a 20  X_CHUNK_SIZE.** 
0810: 6d 61 63 72 6f 2e 20 20 55 73 65 20 74 68 65 20  macro.  Use the 
0820: 22 63 68 75 6e 6b 73 69 7a 65 3d 4e 4e 4e 4e 22  "chunksize=NNNN"
0830: 20 71 75 65 72 79 20 70 61 72 61 6d 65 74 65 72   query parameter
0840: 20 77 69 74 68 20 61 20 55 52 49 20 66 69 6c 65   with a URI file
0850: 6e 61 6d 65 0a 2a 2a 20 69 6e 20 6f 72 64 65 72  name.** in order
0860: 20 74 6f 20 73 65 6c 65 63 74 20 61 6e 20 61 6c   to select an al
0870: 74 65 72 6e 61 74 69 76 65 20 63 68 75 6e 6b 20  ternative chunk 
0880: 73 69 7a 65 20 66 6f 72 20 69 6e 64 69 76 69 64  size for individ
0890: 75 61 6c 20 63 6f 6e 6e 65 63 74 69 6f 6e 73 0a  ual connections.
08a0: 2a 2a 20 61 74 20 72 75 6e 2d 74 69 6d 65 2e 0a  ** at run-time..
08b0: 2a 2f 0a 23 69 6e 63 6c 75 64 65 20 22 73 71 6c  */.#include "sql
08c0: 69 74 65 33 2e 68 22 0a 23 69 6e 63 6c 75 64 65  ite3.h".#include
08d0: 20 3c 73 74 72 69 6e 67 2e 68 3e 0a 23 69 6e 63   <string.h>.#inc
08e0: 6c 75 64 65 20 3c 61 73 73 65 72 74 2e 68 3e 0a  lude <assert.h>.
08f0: 23 69 6e 63 6c 75 64 65 20 3c 73 74 64 6c 69 62  #include <stdlib
0900: 2e 68 3e 0a 23 69 6e 63 6c 75 64 65 20 22 74 65  .h>.#include "te
0910: 73 74 5f 6d 75 6c 74 69 70 6c 65 78 2e 68 22 0a  st_multiplex.h".
0920: 0a 23 69 66 6e 64 65 66 20 53 51 4c 49 54 45 5f  .#ifndef SQLITE_
0930: 43 4f 52 45 0a 20 20 23 64 65 66 69 6e 65 20 53  CORE.  #define S
0940: 51 4c 49 54 45 5f 43 4f 52 45 20 31 20 20 2f 2a  QLITE_CORE 1  /*
0950: 20 44 69 73 61 62 6c 65 20 74 68 65 20 41 50 49   Disable the API
0960: 20 72 65 64 65 66 69 6e 69 74 69 6f 6e 20 69 6e   redefinition in
0970: 20 73 71 6c 69 74 65 33 65 78 74 2e 68 20 2a 2f   sqlite3ext.h */
0980: 0a 23 65 6e 64 69 66 0a 23 69 6e 63 6c 75 64 65  .#endif.#include
0990: 20 22 73 71 6c 69 74 65 33 65 78 74 2e 68 22 0a   "sqlite3ext.h".
09a0: 0a 2f 2a 20 0a 2a 2a 20 54 68 65 73 65 20 73 68  ./* .** These sh
09b0: 6f 75 6c 64 20 62 65 20 64 65 66 69 6e 65 64 20  ould be defined 
09c0: 74 6f 20 62 65 20 74 68 65 20 73 61 6d 65 20 61  to be the same a
09d0: 73 20 74 68 65 20 76 61 6c 75 65 73 20 69 6e 20  s the values in 
09e0: 0a 2a 2a 20 73 71 6c 69 74 65 49 6e 74 2e 68 2e  .** sqliteInt.h.
09f0: 20 20 54 68 65 79 20 61 72 65 20 64 65 66 69 6e    They are defin
0a00: 65 64 20 73 65 70 61 72 61 74 65 6c 79 20 68 65  ed separately he
0a10: 72 65 20 73 6f 20 74 68 61 74 0a 2a 2a 20 74 68  re so that.** th
0a20: 65 20 6d 75 6c 74 69 70 6c 65 78 20 56 46 53 20  e multiplex VFS 
0a30: 73 68 69 6d 20 63 61 6e 20 62 65 20 62 75 69 6c  shim can be buil
0a40: 74 20 61 73 20 61 20 6c 6f 61 64 61 62 6c 65 20  t as a loadable 
0a50: 0a 2a 2a 20 6d 6f 64 75 6c 65 2e 0a 2a 2f 0a 23  .** module..*/.#
0a60: 64 65 66 69 6e 65 20 55 4e 55 53 45 44 5f 50 41  define UNUSED_PA
0a70: 52 41 4d 45 54 45 52 28 78 29 20 28 76 6f 69 64  RAMETER(x) (void
0a80: 29 28 78 29 0a 23 64 65 66 69 6e 65 20 4d 41 58  )(x).#define MAX
0a90: 5f 50 41 47 45 5f 53 49 5a 45 20 20 20 20 20 20  _PAGE_SIZE      
0aa0: 20 30 78 31 30 30 30 30 0a 23 64 65 66 69 6e 65   0x10000.#define
0ab0: 20 44 45 46 41 55 4c 54 5f 53 45 43 54 4f 52 5f   DEFAULT_SECTOR_
0ac0: 53 49 5a 45 20 30 78 31 30 30 30 0a 0a 2f 2a 0a  SIZE 0x1000../*.
0ad0: 2a 2a 20 46 6f 72 20 61 20 62 75 69 6c 64 20 77  ** For a build w
0ae0: 69 74 68 6f 75 74 20 6d 75 74 65 78 65 73 2c 20  ithout mutexes, 
0af0: 6e 6f 2d 6f 70 20 74 68 65 20 6d 75 74 65 78 20  no-op the mutex 
0b00: 63 61 6c 6c 73 2e 0a 2a 2f 0a 23 69 66 20 64 65  calls..*/.#if de
0b10: 66 69 6e 65 64 28 53 51 4c 49 54 45 5f 54 48 52  fined(SQLITE_THR
0b20: 45 41 44 53 41 46 45 29 20 26 26 20 53 51 4c 49  EADSAFE) && SQLI
0b30: 54 45 5f 54 48 52 45 41 44 53 41 46 45 3d 3d 30  TE_THREADSAFE==0
0b40: 0a 23 64 65 66 69 6e 65 20 73 71 6c 69 74 65 33  .#define sqlite3
0b50: 5f 6d 75 74 65 78 5f 61 6c 6c 6f 63 28 58 29 20  _mutex_alloc(X) 
0b60: 20 20 20 28 28 73 71 6c 69 74 65 33 5f 6d 75 74     ((sqlite3_mut
0b70: 65 78 2a 29 38 29 0a 23 64 65 66 69 6e 65 20 73  ex*)8).#define s
0b80: 71 6c 69 74 65 33 5f 6d 75 74 65 78 5f 66 72 65  qlite3_mutex_fre
0b90: 65 28 58 29 0a 23 64 65 66 69 6e 65 20 73 71 6c  e(X).#define sql
0ba0: 69 74 65 33 5f 6d 75 74 65 78 5f 65 6e 74 65 72  ite3_mutex_enter
0bb0: 28 58 29 0a 23 64 65 66 69 6e 65 20 73 71 6c 69  (X).#define sqli
0bc0: 74 65 33 5f 6d 75 74 65 78 5f 74 72 79 28 58 29  te3_mutex_try(X)
0bd0: 20 20 20 20 20 20 53 51 4c 49 54 45 5f 4f 4b 0a        SQLITE_OK.
0be0: 23 64 65 66 69 6e 65 20 73 71 6c 69 74 65 33 5f  #define sqlite3_
0bf0: 6d 75 74 65 78 5f 6c 65 61 76 65 28 58 29 0a 23  mutex_leave(X).#
0c00: 64 65 66 69 6e 65 20 73 71 6c 69 74 65 33 5f 6d  define sqlite3_m
0c10: 75 74 65 78 5f 68 65 6c 64 28 58 29 20 20 20 20  utex_held(X)    
0c20: 20 28 28 76 6f 69 64 29 28 58 29 2c 31 29 0a 23   ((void)(X),1).#
0c30: 64 65 66 69 6e 65 20 73 71 6c 69 74 65 33 5f 6d  define sqlite3_m
0c40: 75 74 65 78 5f 6e 6f 74 68 65 6c 64 28 58 29 20  utex_notheld(X) 
0c50: 20 28 28 76 6f 69 64 29 28 58 29 2c 31 29 0a 23   ((void)(X),1).#
0c60: 65 6e 64 69 66 20 2f 2a 20 53 51 4c 49 54 45 5f  endif /* SQLITE_
0c70: 54 48 52 45 41 44 53 41 46 45 3d 3d 30 20 2a 2f  THREADSAFE==0 */
0c80: 0a 0a 2f 2a 20 4d 61 78 69 6d 75 6d 20 63 68 75  ../* Maximum chu
0c90: 6e 6b 20 6e 75 6d 62 65 72 20 2a 2f 0a 23 64 65  nk number */.#de
0ca0: 66 69 6e 65 20 4d 58 5f 43 48 55 4e 4b 5f 4e 55  fine MX_CHUNK_NU
0cb0: 4d 42 45 52 20 32 39 39 0a 0a 2f 2a 20 46 69 72  MBER 299../* Fir
0cc0: 73 74 20 63 68 75 6e 6b 20 66 6f 72 20 72 6f 6c  st chunk for rol
0cd0: 6c 62 61 63 6b 20 6a 6f 75 72 6e 61 6c 20 66 69  lback journal fi
0ce0: 6c 65 73 20 2a 2f 0a 23 64 65 66 69 6e 65 20 53  les */.#define S
0cf0: 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f  QLITE_MULTIPLEX_
0d00: 4a 4f 55 52 4e 41 4c 5f 38 5f 33 5f 4f 46 46 53  JOURNAL_8_3_OFFS
0d10: 45 54 20 34 30 30 0a 23 64 65 66 69 6e 65 20 53  ET 400.#define S
0d20: 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f  QLITE_MULTIPLEX_
0d30: 57 41 4c 5f 38 5f 33 5f 4f 46 46 53 45 54 20 37  WAL_8_3_OFFSET 7
0d40: 30 30 0a 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  00.../**********
0d50: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20 53  ************** S
0d60: 68 69 6d 20 44 65 66 69 6e 69 74 69 6f 6e 73 20  him Definitions 
0d70: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0d80: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2f 0a  **************/.
0d90: 0a 23 69 66 6e 64 65 66 20 53 51 4c 49 54 45 5f  .#ifndef SQLITE_
0da0: 4d 55 4c 54 49 50 4c 45 58 5f 56 46 53 5f 4e 41  MULTIPLEX_VFS_NA
0db0: 4d 45 0a 23 20 64 65 66 69 6e 65 20 53 51 4c 49  ME.# define SQLI
0dc0: 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 56 46 53  TE_MULTIPLEX_VFS
0dd0: 5f 4e 41 4d 45 20 22 6d 75 6c 74 69 70 6c 65 78  _NAME "multiplex
0de0: 22 0a 23 65 6e 64 69 66 0a 0a 2f 2a 20 54 68 69  ".#endif../* Thi
0df0: 73 20 69 73 20 74 68 65 20 6c 69 6d 69 74 20 6f  s is the limit o
0e00: 6e 20 74 68 65 20 63 68 75 6e 6b 20 73 69 7a 65  n the chunk size
0e10: 2e 20 20 49 74 20 6d 61 79 20 62 65 20 63 68 61  .  It may be cha
0e20: 6e 67 65 64 20 62 79 20 63 61 6c 6c 69 6e 67 0a  nged by calling.
0e30: 2a 2a 20 74 68 65 20 78 46 69 6c 65 43 6f 6e 74  ** the xFileCont
0e40: 72 6f 6c 28 29 20 69 6e 74 65 72 66 61 63 65 2e  rol() interface.
0e50: 20 20 49 74 20 77 69 6c 6c 20 62 65 20 72 6f 75    It will be rou
0e60: 6e 64 65 64 20 75 70 20 74 6f 20 61 20 0a 2a 2a  nded up to a .**
0e70: 20 6d 75 6c 74 69 70 6c 65 20 6f 66 20 4d 41 58   multiple of MAX
0e80: 5f 50 41 47 45 5f 53 49 5a 45 2e 20 20 57 65 20  _PAGE_SIZE.  We 
0e90: 64 65 66 61 75 6c 74 20 69 74 20 68 65 72 65 20  default it here 
0ea0: 74 6f 20 32 47 69 42 20 6c 65 73 73 20 36 34 4b  to 2GiB less 64K
0eb0: 69 42 2e 0a 2a 2f 0a 23 69 66 6e 64 65 66 20 53  iB..*/.#ifndef S
0ec0: 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f  QLITE_MULTIPLEX_
0ed0: 43 48 55 4e 4b 5f 53 49 5a 45 0a 23 20 64 65 66  CHUNK_SIZE.# def
0ee0: 69 6e 65 20 53 51 4c 49 54 45 5f 4d 55 4c 54 49  ine SQLITE_MULTI
0ef0: 50 4c 45 58 5f 43 48 55 4e 4b 5f 53 49 5a 45 20  PLEX_CHUNK_SIZE 
0f00: 32 31 34 37 34 31 38 31 31 32 0a 23 65 6e 64 69  2147418112.#endi
0f10: 66 0a 0a 2f 2a 20 54 68 69 73 20 75 73 65 64 20  f../* This used 
0f20: 74 6f 20 62 65 20 74 68 65 20 64 65 66 61 75 6c  to be the defaul
0f30: 74 20 6c 69 6d 69 74 20 6f 6e 20 6e 75 6d 62 65  t limit on numbe
0f40: 72 20 6f 66 20 63 68 75 6e 6b 73 2c 20 62 75 74  r of chunks, but
0f50: 0a 2a 2a 20 69 74 20 69 73 20 6e 6f 20 6c 6f 6e  .** it is no lon
0f60: 67 65 72 20 65 6e 66 6f 72 63 65 64 2e 20 54 68  ger enforced. Th
0f70: 65 72 65 20 69 73 20 63 75 72 72 65 6e 74 6c 79  ere is currently
0f80: 20 6e 6f 20 6c 69 6d 69 74 20 74 6f 20 74 68 65   no limit to the
0f90: 0a 2a 2a 20 6e 75 6d 62 65 72 20 6f 66 20 63 68  .** number of ch
0fa0: 75 6e 6b 73 2e 0a 2a 2a 0a 2a 2a 20 4d 61 79 20  unks..**.** May 
0fb0: 62 65 20 63 68 61 6e 67 65 64 20 62 79 20 63 61  be changed by ca
0fc0: 6c 6c 69 6e 67 20 74 68 65 20 78 46 69 6c 65 43  lling the xFileC
0fd0: 6f 6e 74 72 6f 6c 28 29 20 69 6e 74 65 72 66 61  ontrol() interfa
0fe0: 63 65 2e 0a 2a 2f 0a 23 69 66 6e 64 65 66 20 53  ce..*/.#ifndef S
0ff0: 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f  QLITE_MULTIPLEX_
1000: 4d 41 58 5f 43 48 55 4e 4b 53 0a 23 20 64 65 66  MAX_CHUNKS.# def
1010: 69 6e 65 20 53 51 4c 49 54 45 5f 4d 55 4c 54 49  ine SQLITE_MULTI
1020: 50 4c 45 58 5f 4d 41 58 5f 43 48 55 4e 4b 53 20  PLEX_MAX_CHUNKS 
1030: 31 32 0a 23 65 6e 64 69 66 0a 0a 2f 2a 2a 2a 2a  12.#endif../****
1040: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1050: 2a 2a 2a 2a 20 4f 62 6a 65 63 74 20 44 65 66 69  **** Object Defi
1060: 6e 69 74 69 6f 6e 73 20 2a 2a 2a 2a 2a 2a 2a 2a  nitions ********
1070: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1080: 2a 2a 2a 2a 2a 2a 2f 0a 0a 2f 2a 20 46 6f 72 77  ******/../* Forw
1090: 61 72 64 20 64 65 63 6c 61 72 61 74 69 6f 6e 20  ard declaration 
10a0: 6f 66 20 61 6c 6c 20 6f 62 6a 65 63 74 20 74 79  of all object ty
10b0: 70 65 73 20 2a 2f 0a 74 79 70 65 64 65 66 20 73  pes */.typedef s
10c0: 74 72 75 63 74 20 6d 75 6c 74 69 70 6c 65 78 47  truct multiplexG
10d0: 72 6f 75 70 20 6d 75 6c 74 69 70 6c 65 78 47 72  roup multiplexGr
10e0: 6f 75 70 3b 0a 74 79 70 65 64 65 66 20 73 74 72  oup;.typedef str
10f0: 75 63 74 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e  uct multiplexCon
1100: 6e 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 3b  n multiplexConn;
1110: 0a 0a 2f 2a 0a 2a 2a 20 41 20 22 6d 75 6c 74 69  ../*.** A "multi
1120: 70 6c 65 78 20 67 72 6f 75 70 22 20 69 73 20 61  plex group" is a
1130: 20 63 6f 6c 6c 65 63 74 69 6f 6e 20 6f 66 20 66   collection of f
1140: 69 6c 65 73 20 74 68 61 74 20 63 6f 6c 6c 65 63  iles that collec
1150: 74 69 76 65 6c 79 0a 2a 2a 20 6d 61 6b 65 75 70  tively.** makeup
1160: 20 61 20 73 69 6e 67 6c 65 20 53 51 4c 69 74 65   a single SQLite
1170: 20 44 42 20 66 69 6c 65 2e 20 20 54 68 69 73 20   DB file.  This 
1180: 61 6c 6c 6f 77 73 20 74 68 65 20 73 69 7a 65 20  allows the size 
1190: 6f 66 20 74 68 65 20 44 42 0a 2a 2a 20 74 6f 20  of the DB.** to 
11a0: 65 78 63 65 65 64 20 74 68 65 20 6c 69 6d 69 74  exceed the limit
11b0: 73 20 69 6d 70 6f 73 65 64 20 62 79 20 74 68 65  s imposed by the
11c0: 20 66 69 6c 65 20 73 79 73 74 65 6d 2e 0a 2a 2a   file system..**
11d0: 0a 2a 2a 20 54 68 65 72 65 20 69 73 20 61 6e 20  .** There is an 
11e0: 69 6e 73 74 61 6e 63 65 20 6f 66 20 74 68 65 20  instance of the 
11f0: 66 6f 6c 6c 6f 77 69 6e 67 20 6f 62 6a 65 63 74  following object
1200: 20 66 6f 72 20 65 61 63 68 20 64 65 66 69 6e 65   for each define
1210: 64 20 6d 75 6c 74 69 70 6c 65 78 0a 2a 2a 20 67  d multiplex.** g
1220: 72 6f 75 70 2e 0a 2a 2f 0a 73 74 72 75 63 74 20  roup..*/.struct 
1230: 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 7b  multiplexGroup {
1240: 0a 20 20 73 74 72 75 63 74 20 6d 75 6c 74 69 70  .  struct multip
1250: 6c 65 78 52 65 61 6c 20 7b 20 20 20 20 20 20 20  lexReal {       
1260: 20 20 20 20 2f 2a 20 46 6f 72 20 65 61 63 68 20      /* For each 
1270: 63 68 75 6e 6b 20 2a 2f 0a 20 20 20 20 73 71 6c  chunk */.    sql
1280: 69 74 65 33 5f 66 69 6c 65 20 2a 70 3b 20 20 20  ite3_file *p;   
1290: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
12a0: 2a 20 48 61 6e 64 6c 65 20 66 6f 72 20 74 68 65  * Handle for the
12b0: 20 63 68 75 6e 6b 20 2a 2f 0a 20 20 20 20 63 68   chunk */.    ch
12c0: 61 72 20 2a 7a 3b 20 20 20 20 20 20 20 20 20 20  ar *z;          
12d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
12e0: 2f 2a 20 4e 61 6d 65 20 6f 66 20 74 68 69 73 20  /* Name of this 
12f0: 63 68 75 6e 6b 20 2a 2f 0a 20 20 7d 20 2a 61 52  chunk */.  } *aR
1300: 65 61 6c 3b 20 20 20 20 20 20 20 20 20 20 20 20  eal;            
1310: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 6c              /* l
1320: 69 73 74 20 6f 66 20 61 6c 6c 20 63 68 75 6e 6b  ist of all chunk
1330: 73 20 2a 2f 0a 20 20 69 6e 74 20 6e 52 65 61 6c  s */.  int nReal
1340: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ;               
1350: 20 20 20 20 20 20 20 20 2f 2a 20 4e 75 6d 62 65          /* Numbe
1360: 72 20 6f 66 20 63 68 75 6e 6b 73 20 2a 2f 0a 20  r of chunks */. 
1370: 20 63 68 61 72 20 2a 7a 4e 61 6d 65 3b 20 20 20   char *zName;   
1380: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1390: 20 20 2f 2a 20 42 61 73 65 20 66 69 6c 65 6e 61    /* Base filena
13a0: 6d 65 20 6f 66 20 74 68 69 73 20 67 72 6f 75 70  me of this group
13b0: 20 2a 2f 0a 20 20 69 6e 74 20 6e 4e 61 6d 65 3b   */.  int nName;
13c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
13d0: 20 20 20 20 20 20 20 2f 2a 20 4c 65 6e 67 74 68         /* Length
13e0: 20 6f 66 20 62 61 73 65 20 66 69 6c 65 6e 61 6d   of base filenam
13f0: 65 20 2a 2f 0a 20 20 69 6e 74 20 66 6c 61 67 73  e */.  int flags
1400: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ;               
1410: 20 20 20 20 20 20 20 20 2f 2a 20 46 6c 61 67 73          /* Flags
1420: 20 75 73 65 64 20 66 6f 72 20 6f 72 69 67 69 6e   used for origin
1430: 61 6c 20 6f 70 65 6e 69 6e 67 20 2a 2f 0a 20 20  al opening */.  
1440: 75 6e 73 69 67 6e 65 64 20 69 6e 74 20 73 7a 43  unsigned int szC
1450: 68 75 6e 6b 3b 20 20 20 20 20 20 20 20 20 20 20  hunk;           
1460: 20 2f 2a 20 43 68 75 6e 6b 20 73 69 7a 65 20 75   /* Chunk size u
1470: 73 65 64 20 66 6f 72 20 74 68 69 73 20 67 72 6f  sed for this gro
1480: 75 70 20 2a 2f 0a 20 20 75 6e 73 69 67 6e 65 64  up */.  unsigned
1490: 20 63 68 61 72 20 62 45 6e 61 62 6c 65 64 3b 20   char bEnabled; 
14a0: 20 20 20 20 20 20 20 20 20 2f 2a 20 54 52 55 45           /* TRUE
14b0: 20 74 6f 20 75 73 65 20 4d 75 6c 74 69 70 6c 65   to use Multiple
14c0: 78 20 56 46 53 20 66 6f 72 20 74 68 69 73 20 66  x VFS for this f
14d0: 69 6c 65 20 2a 2f 0a 20 20 75 6e 73 69 67 6e 65  ile */.  unsigne
14e0: 64 20 63 68 61 72 20 62 54 72 75 6e 63 61 74 65  d char bTruncate
14f0: 3b 20 20 20 20 20 20 20 20 20 2f 2a 20 54 52 55  ;         /* TRU
1500: 45 20 74 6f 20 65 6e 61 62 6c 65 20 74 72 75 6e  E to enable trun
1510: 63 61 74 69 6f 6e 20 6f 66 20 64 61 74 61 62 61  cation of databa
1520: 73 65 73 20 2a 2f 0a 20 20 6d 75 6c 74 69 70 6c  ses */.  multipl
1530: 65 78 47 72 6f 75 70 20 2a 70 4e 65 78 74 2c 20  exGroup *pNext, 
1540: 2a 70 50 72 65 76 3b 20 20 20 2f 2a 20 44 6f 75  *pPrev;   /* Dou
1550: 62 6c 79 20 6c 69 6e 6b 65 64 20 6c 69 73 74 20  bly linked list 
1560: 6f 66 20 61 6c 6c 20 67 72 6f 75 70 20 6f 62 6a  of all group obj
1570: 65 63 74 73 20 2a 2f 0a 7d 3b 0a 0a 2f 2a 0a 2a  ects */.};../*.*
1580: 2a 20 41 6e 20 69 6e 73 74 61 6e 63 65 20 6f 66  * An instance of
1590: 20 74 68 65 20 66 6f 6c 6c 6f 77 69 6e 67 20 6f   the following o
15a0: 62 6a 65 63 74 20 72 65 70 72 65 73 65 6e 74 73  bject represents
15b0: 20 65 61 63 68 20 6f 70 65 6e 20 63 6f 6e 6e 65   each open conne
15c0: 63 74 69 6f 6e 0a 2a 2a 20 74 6f 20 61 20 66 69  ction.** to a fi
15d0: 6c 65 20 74 68 61 74 20 69 73 20 6d 75 6c 74 69  le that is multi
15e0: 70 6c 65 78 27 65 64 2e 20 20 54 68 69 73 20 6f  plex'ed.  This o
15f0: 62 6a 65 63 74 20 69 73 20 61 20 0a 2a 2a 20 73  bject is a .** s
1600: 75 62 63 6c 61 73 73 20 6f 66 20 73 71 6c 69 74  ubclass of sqlit
1610: 65 33 5f 66 69 6c 65 2e 20 20 54 68 65 20 73 71  e3_file.  The sq
1620: 6c 69 74 65 33 5f 66 69 6c 65 20 6f 62 6a 65 63  lite3_file objec
1630: 74 20 66 6f 72 20 74 68 65 20 75 6e 64 65 72 6c  t for the underl
1640: 79 69 6e 67 0a 2a 2a 20 56 46 53 20 69 73 20 61  ying.** VFS is a
1650: 70 70 65 6e 64 65 64 20 74 6f 20 74 68 69 73 20  ppended to this 
1660: 73 74 72 75 63 74 75 72 65 2e 0a 2a 2f 0a 73 74  structure..*/.st
1670: 72 75 63 74 20 6d 75 6c 74 69 70 6c 65 78 43 6f  ruct multiplexCo
1680: 6e 6e 20 7b 0a 20 20 73 71 6c 69 74 65 33 5f 66  nn {.  sqlite3_f
1690: 69 6c 65 20 62 61 73 65 3b 20 20 20 20 20 20 20  ile base;       
16a0: 20 20 20 20 20 20 20 2f 2a 20 42 61 73 65 20 63         /* Base c
16b0: 6c 61 73 73 20 2d 20 6d 75 73 74 20 62 65 20 66  lass - must be f
16c0: 69 72 73 74 20 2a 2f 0a 20 20 6d 75 6c 74 69 70  irst */.  multip
16d0: 6c 65 78 47 72 6f 75 70 20 2a 70 47 72 6f 75 70  lexGroup *pGroup
16e0: 3b 20 20 20 20 20 20 20 20 20 2f 2a 20 54 68 65  ;         /* The
16f0: 20 75 6e 64 65 72 6c 79 69 6e 67 20 67 72 6f 75   underlying grou
1700: 70 20 6f 66 20 66 69 6c 65 73 20 2a 2f 0a 7d 3b  p of files */.};
1710: 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ../*************
1720: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20 47 6c 6f  ************ Glo
1730: 62 61 6c 20 56 61 72 69 61 62 6c 65 73 20 2a 2a  bal Variables **
1740: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1750: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1760: 2f 0a 2f 2a 0a 2a 2a 20 41 6c 6c 20 67 6c 6f 62  /./*.** All glob
1770: 61 6c 20 76 61 72 69 61 62 6c 65 73 20 75 73 65  al variables use
1780: 64 20 62 79 20 74 68 69 73 20 66 69 6c 65 20 61  d by this file a
1790: 72 65 20 63 6f 6e 74 61 69 6e 69 6e 67 20 77 69  re containing wi
17a0: 74 68 69 6e 20 74 68 65 20 66 6f 6c 6c 6f 77 69  thin the followi
17b0: 6e 67 0a 2a 2a 20 67 4d 75 6c 74 69 70 6c 65 78  ng.** gMultiplex
17c0: 20 73 74 72 75 63 74 75 72 65 2e 0a 2a 2f 0a 73   structure..*/.s
17d0: 74 61 74 69 63 20 73 74 72 75 63 74 20 7b 0a 20  tatic struct {. 
17e0: 20 2f 2a 20 54 68 65 20 70 4f 72 69 67 56 66 73   /* The pOrigVfs
17f0: 20 69 73 20 74 68 65 20 72 65 61 6c 2c 20 6f 72   is the real, or
1800: 69 67 69 6e 61 6c 20 75 6e 64 65 72 6c 79 69 6e  iginal underlyin
1810: 67 20 56 46 53 20 69 6d 70 6c 65 6d 65 6e 74 61  g VFS implementa
1820: 74 69 6f 6e 2e 0a 20 20 2a 2a 20 4d 6f 73 74 20  tion..  ** Most 
1830: 6f 70 65 72 61 74 69 6f 6e 73 20 70 61 73 73 2d  operations pass-
1840: 74 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20 72  through to the r
1850: 65 61 6c 20 56 46 53 2e 20 20 54 68 69 73 20 76  eal VFS.  This v
1860: 61 6c 75 65 20 69 73 20 72 65 61 64 2d 6f 6e 6c  alue is read-onl
1870: 79 0a 20 20 2a 2a 20 64 75 72 69 6e 67 20 6f 70  y.  ** during op
1880: 65 72 61 74 69 6f 6e 2e 20 20 49 74 20 69 73 20  eration.  It is 
1890: 6f 6e 6c 79 20 6d 6f 64 69 66 69 65 64 20 61 74  only modified at
18a0: 20 73 74 61 72 74 2d 74 69 6d 65 20 61 6e 64 20   start-time and 
18b0: 74 68 75 73 20 64 6f 65 73 20 6e 6f 74 0a 20 20  thus does not.  
18c0: 2a 2a 20 72 65 71 75 69 72 65 20 61 20 6d 75 74  ** require a mut
18d0: 65 78 2e 0a 20 20 2a 2f 0a 20 20 73 71 6c 69 74  ex..  */.  sqlit
18e0: 65 33 5f 76 66 73 20 2a 70 4f 72 69 67 56 66 73  e3_vfs *pOrigVfs
18f0: 3b 0a 0a 20 20 2f 2a 20 54 68 65 20 73 54 68 69  ;..  /* The sThi
1900: 73 56 66 73 20 69 73 20 74 68 65 20 56 46 53 20  sVfs is the VFS 
1910: 73 74 72 75 63 74 75 72 65 20 75 73 65 64 20 62  structure used b
1920: 79 20 74 68 69 73 20 73 68 69 6d 2e 20 20 49 74  y this shim.  It
1930: 20 69 73 20 69 6e 69 74 69 61 6c 69 7a 65 64 0a   is initialized.
1940: 20 20 2a 2a 20 61 74 20 73 74 61 72 74 2d 74 69    ** at start-ti
1950: 6d 65 20 61 6e 64 20 74 68 75 73 20 64 6f 65 73  me and thus does
1960: 20 6e 6f 74 20 72 65 71 75 69 72 65 20 61 20 6d   not require a m
1970: 75 74 65 78 0a 20 20 2a 2f 0a 20 20 73 71 6c 69  utex.  */.  sqli
1980: 74 65 33 5f 76 66 73 20 73 54 68 69 73 56 66 73  te3_vfs sThisVfs
1990: 3b 0a 0a 20 20 2f 2a 20 54 68 65 20 73 49 6f 4d  ;..  /* The sIoM
19a0: 65 74 68 6f 64 73 20 64 65 66 69 6e 65 73 20 74  ethods defines t
19b0: 68 65 20 6d 65 74 68 6f 64 73 20 75 73 65 64 20  he methods used 
19c0: 62 79 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20  by sqlite3_file 
19d0: 6f 62 6a 65 63 74 73 20 0a 20 20 2a 2a 20 61 73  objects .  ** as
19e0: 73 6f 63 69 61 74 65 64 20 77 69 74 68 20 74 68  sociated with th
19f0: 69 73 20 73 68 69 6d 2e 20 20 49 74 20 69 73 20  is shim.  It is 
1a00: 69 6e 69 74 69 61 6c 69 7a 65 64 20 61 74 20 73  initialized at s
1a10: 74 61 72 74 2d 74 69 6d 65 20 61 6e 64 20 64 6f  tart-time and do
1a20: 65 73 0a 20 20 2a 2a 20 6e 6f 74 20 72 65 71 75  es.  ** not requ
1a30: 69 72 65 20 61 20 6d 75 74 65 78 2e 0a 20 20 2a  ire a mutex..  *
1a40: 2a 0a 20 20 2a 2a 20 57 68 65 6e 20 74 68 65 20  *.  ** When the 
1a50: 75 6e 64 65 72 6c 79 69 6e 67 20 56 46 53 20 69  underlying VFS i
1a60: 73 20 63 61 6c 6c 65 64 20 74 6f 20 6f 70 65 6e  s called to open
1a70: 20 61 20 66 69 6c 65 2c 20 69 74 20 6d 69 67 68   a file, it migh
1a80: 74 20 72 65 74 75 72 6e 20 0a 20 20 2a 2a 20 65  t return .  ** e
1a90: 69 74 68 65 72 20 61 20 76 65 72 73 69 6f 6e 20  ither a version 
1aa0: 31 20 6f 72 20 61 20 76 65 72 73 69 6f 6e 20 32  1 or a version 2
1ab0: 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 6f 62   sqlite3_file ob
1ac0: 6a 65 63 74 2e 20 20 54 68 69 73 20 73 68 69 6d  ject.  This shim
1ad0: 0a 20 20 2a 2a 20 68 61 73 20 74 6f 20 63 72 65  .  ** has to cre
1ae0: 61 74 65 20 61 20 77 72 61 70 70 65 72 20 73 71  ate a wrapper sq
1af0: 6c 69 74 65 33 5f 66 69 6c 65 20 6f 66 20 74 68  lite3_file of th
1b00: 65 20 73 61 6d 65 20 76 65 72 73 69 6f 6e 2e 20  e same version. 
1b10: 20 48 65 6e 63 65 0a 20 20 2a 2a 20 74 68 65 72   Hence.  ** ther
1b20: 65 20 61 72 65 20 74 77 6f 20 49 2f 4f 20 6d 65  e are two I/O me
1b30: 74 68 6f 64 20 73 74 72 75 63 74 75 72 65 73 2c  thod structures,
1b40: 20 6f 6e 65 20 66 6f 72 20 76 65 72 73 69 6f 6e   one for version
1b50: 20 31 20 61 6e 64 20 74 68 65 20 6f 74 68 65 72   1 and the other
1b60: 0a 20 20 2a 2a 20 66 6f 72 20 76 65 72 73 69 6f  .  ** for versio
1b70: 6e 20 32 2e 0a 20 20 2a 2f 0a 20 20 73 71 6c 69  n 2..  */.  sqli
1b80: 74 65 33 5f 69 6f 5f 6d 65 74 68 6f 64 73 20 73  te3_io_methods s
1b90: 49 6f 4d 65 74 68 6f 64 73 56 31 3b 0a 20 20 73  IoMethodsV1;.  s
1ba0: 71 6c 69 74 65 33 5f 69 6f 5f 6d 65 74 68 6f 64  qlite3_io_method
1bb0: 73 20 73 49 6f 4d 65 74 68 6f 64 73 56 32 3b 0a  s sIoMethodsV2;.
1bc0: 0a 20 20 2f 2a 20 54 72 75 65 20 77 68 65 6e 20  .  /* True when 
1bd0: 74 68 69 73 20 73 68 69 6d 20 68 61 73 20 62 65  this shim has be
1be0: 65 6e 20 69 6e 69 74 69 61 6c 69 7a 65 64 2e 0a  en initialized..
1bf0: 20 20 2a 2f 0a 20 20 69 6e 74 20 69 73 49 6e 69    */.  int isIni
1c00: 74 69 61 6c 69 7a 65 64 3b 0a 0a 20 20 2f 2a 20  tialized;..  /* 
1c10: 46 6f 72 20 72 75 6e 2d 74 69 6d 65 20 61 63 63  For run-time acc
1c20: 65 73 73 20 61 6e 79 20 6f 66 20 74 68 65 20 6f  ess any of the o
1c30: 74 68 65 72 20 67 6c 6f 62 61 6c 20 64 61 74 61  ther global data
1c40: 20 73 74 72 75 63 74 75 72 65 73 20 69 6e 20 74   structures in t
1c50: 68 69 73 0a 20 20 2a 2a 20 73 68 69 6d 2c 20 74  his.  ** shim, t
1c60: 68 65 20 66 6f 6c 6c 6f 77 69 6e 67 20 6d 75 74  he following mut
1c70: 65 78 20 6d 75 73 74 20 62 65 20 68 65 6c 64 2e  ex must be held.
1c80: 0a 20 20 2a 2f 0a 20 20 73 71 6c 69 74 65 33 5f  .  */.  sqlite3_
1c90: 6d 75 74 65 78 20 2a 70 4d 75 74 65 78 3b 0a 0a  mutex *pMutex;..
1ca0: 20 20 2f 2a 20 4c 69 73 74 20 6f 66 20 6d 75 6c    /* List of mul
1cb0: 74 69 70 6c 65 78 47 72 6f 75 70 20 6f 62 6a 65  tiplexGroup obje
1cc0: 63 74 73 2e 0a 20 20 2a 2f 0a 20 20 6d 75 6c 74  cts..  */.  mult
1cd0: 69 70 6c 65 78 47 72 6f 75 70 20 2a 70 47 72 6f  iplexGroup *pGro
1ce0: 75 70 73 3b 0a 7d 20 67 4d 75 6c 74 69 70 6c 65  ups;.} gMultiple
1cf0: 78 3b 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  x;../***********
1d00: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20 55  ************** U
1d10: 74 69 6c 69 74 79 20 52 6f 75 74 69 6e 65 73 20  tility Routines 
1d20: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1d30: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1d40: 2a 2f 0a 2f 2a 0a 2a 2a 20 41 63 71 75 69 72 65  */./*.** Acquire
1d50: 20 61 6e 64 20 72 65 6c 65 61 73 65 20 74 68 65   and release the
1d60: 20 6d 75 74 65 78 20 75 73 65 64 20 74 6f 20 73   mutex used to s
1d70: 65 72 69 61 6c 69 7a 65 20 61 63 63 65 73 73 20  erialize access 
1d80: 74 6f 20 74 68 65 0a 2a 2a 20 6c 69 73 74 20 6f  to the.** list o
1d90: 66 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70  f multiplexGroup
1da0: 73 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 76 6f 69  s..*/.static voi
1db0: 64 20 6d 75 6c 74 69 70 6c 65 78 45 6e 74 65 72  d multiplexEnter
1dc0: 28 76 6f 69 64 29 7b 20 73 71 6c 69 74 65 33 5f  (void){ sqlite3_
1dd0: 6d 75 74 65 78 5f 65 6e 74 65 72 28 67 4d 75 6c  mutex_enter(gMul
1de0: 74 69 70 6c 65 78 2e 70 4d 75 74 65 78 29 3b 20  tiplex.pMutex); 
1df0: 7d 0a 73 74 61 74 69 63 20 76 6f 69 64 20 6d 75  }.static void mu
1e00: 6c 74 69 70 6c 65 78 4c 65 61 76 65 28 76 6f 69  ltiplexLeave(voi
1e10: 64 29 7b 20 73 71 6c 69 74 65 33 5f 6d 75 74 65  d){ sqlite3_mute
1e20: 78 5f 6c 65 61 76 65 28 67 4d 75 6c 74 69 70 6c  x_leave(gMultipl
1e30: 65 78 2e 70 4d 75 74 65 78 29 3b 20 7d 0a 0a 2f  ex.pMutex); }../
1e40: 2a 0a 2a 2a 20 43 6f 6d 70 75 74 65 20 61 20 73  *.** Compute a s
1e50: 74 72 69 6e 67 20 6c 65 6e 67 74 68 20 74 68 61  tring length tha
1e60: 74 20 69 73 20 6c 69 6d 69 74 65 64 20 74 6f 20  t is limited to 
1e70: 77 68 61 74 20 63 61 6e 20 62 65 20 73 74 6f 72  what can be stor
1e80: 65 64 20 69 6e 0a 2a 2a 20 6c 6f 77 65 72 20 33  ed in.** lower 3
1e90: 30 20 62 69 74 73 20 6f 66 20 61 20 33 32 2d 62  0 bits of a 32-b
1ea0: 69 74 20 73 69 67 6e 65 64 20 69 6e 74 65 67 65  it signed intege
1eb0: 72 2e 0a 2a 2a 0a 2a 2a 20 54 68 65 20 76 61 6c  r..**.** The val
1ec0: 75 65 20 72 65 74 75 72 6e 65 64 20 77 69 6c 6c  ue returned will
1ed0: 20 6e 65 76 65 72 20 62 65 20 6e 65 67 61 74 69   never be negati
1ee0: 76 65 2e 20 20 4e 6f 72 20 77 69 6c 6c 20 69 74  ve.  Nor will it
1ef0: 20 65 76 65 72 20 62 65 20 67 72 65 61 74 65 72   ever be greater
1f00: 0a 2a 2a 20 74 68 61 6e 20 74 68 65 20 61 63 74  .** than the act
1f10: 75 61 6c 20 6c 65 6e 67 74 68 20 6f 66 20 74 68  ual length of th
1f20: 65 20 73 74 72 69 6e 67 2e 20 20 46 6f 72 20 76  e string.  For v
1f30: 65 72 79 20 6c 6f 6e 67 20 73 74 72 69 6e 67 73  ery long strings
1f40: 20 28 67 72 65 61 74 65 72 0a 2a 2a 20 74 68 61   (greater.** tha
1f50: 6e 20 31 47 69 42 29 20 74 68 65 20 76 61 6c 75  n 1GiB) the valu
1f60: 65 20 72 65 74 75 72 6e 65 64 20 6d 69 67 68 74  e returned might
1f70: 20 62 65 20 6c 65 73 73 20 74 68 61 6e 20 74 68   be less than th
1f80: 65 20 74 72 75 65 20 73 74 72 69 6e 67 20 6c 65  e true string le
1f90: 6e 67 74 68 2e 0a 2a 2f 0a 73 74 61 74 69 63 20  ngth..*/.static 
1fa0: 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 53 74 72  int multiplexStr
1fb0: 6c 65 6e 33 30 28 63 6f 6e 73 74 20 63 68 61 72  len30(const char
1fc0: 20 2a 7a 29 7b 0a 20 20 63 6f 6e 73 74 20 63 68   *z){.  const ch
1fd0: 61 72 20 2a 7a 32 20 3d 20 7a 3b 0a 20 20 69 66  ar *z2 = z;.  if
1fe0: 28 20 7a 3d 3d 30 20 29 20 72 65 74 75 72 6e 20  ( z==0 ) return 
1ff0: 30 3b 0a 20 20 77 68 69 6c 65 28 20 2a 7a 32 20  0;.  while( *z2 
2000: 29 7b 20 7a 32 2b 2b 3b 20 7d 0a 20 20 72 65 74  ){ z2++; }.  ret
2010: 75 72 6e 20 30 78 33 66 66 66 66 66 66 66 20 26  urn 0x3fffffff &
2020: 20 28 69 6e 74 29 28 7a 32 20 2d 20 7a 29 3b 0a   (int)(z2 - z);.
2030: 7d 0a 0a 2f 2a 0a 2a 2a 20 47 65 6e 65 72 61 74  }../*.** Generat
2040: 65 20 74 68 65 20 66 69 6c 65 2d 6e 61 6d 65 20  e the file-name 
2050: 66 6f 72 20 63 68 75 6e 6b 20 69 43 68 75 6e 6b  for chunk iChunk
2060: 20 6f 66 20 74 68 65 20 67 72 6f 75 70 20 77 69   of the group wi
2070: 74 68 20 62 61 73 65 20 6e 61 6d 65 0a 2a 2a 20  th base name.** 
2080: 7a 42 61 73 65 2e 20 54 68 65 20 66 69 6c 65 2d  zBase. The file-
2090: 6e 61 6d 65 20 69 73 20 77 72 69 74 74 65 6e 20  name is written 
20a0: 74 6f 20 62 75 66 66 65 72 20 7a 4f 75 74 20 62  to buffer zOut b
20b0: 65 66 6f 72 65 20 72 65 74 75 72 6e 69 6e 67 2e  efore returning.
20c0: 20 42 75 66 66 65 72 0a 2a 2a 20 7a 4f 75 74 20   Buffer.** zOut 
20d0: 6d 75 73 74 20 62 65 20 61 6c 6c 6f 63 61 74 65  must be allocate
20e0: 64 20 62 79 20 74 68 65 20 63 61 6c 6c 65 72 20  d by the caller 
20f0: 73 6f 20 74 68 61 74 20 69 74 20 69 73 20 61 74  so that it is at
2100: 20 6c 65 61 73 74 20 28 6e 42 61 73 65 2b 35 29   least (nBase+5)
2110: 0a 2a 2a 20 62 79 74 65 73 20 69 6e 20 73 69 7a  .** bytes in siz
2120: 65 2c 20 77 68 65 72 65 20 6e 42 61 73 65 20 69  e, where nBase i
2130: 73 20 74 68 65 20 6c 65 6e 67 74 68 20 6f 66 20  s the length of 
2140: 7a 42 61 73 65 2c 20 6e 6f 74 20 69 6e 63 6c 75  zBase, not inclu
2150: 64 69 6e 67 20 74 68 65 0a 2a 2a 20 6e 75 6c 2d  ding the.** nul-
2160: 74 65 72 6d 69 6e 61 74 6f 72 2e 0a 2a 2a 0a 2a  terminator..**.*
2170: 2a 20 49 66 20 69 43 68 75 6e 6b 20 69 73 20 30  * If iChunk is 0
2180: 20 28 6f 72 20 34 30 30 20 2d 20 74 68 65 20 6e   (or 400 - the n
2190: 75 6d 62 65 72 20 66 6f 72 20 74 68 65 20 66 69  umber for the fi
21a0: 72 73 74 20 6a 6f 75 72 6e 61 6c 20 66 69 6c 65  rst journal file
21b0: 20 63 68 75 6e 6b 29 2c 0a 2a 2a 20 74 68 65 20   chunk),.** the 
21c0: 6f 75 74 70 75 74 20 69 73 20 61 20 63 6f 70 79  output is a copy
21d0: 20 6f 66 20 74 68 65 20 69 6e 70 75 74 20 73 74   of the input st
21e0: 72 69 6e 67 2e 20 4f 74 68 65 72 77 69 73 65 2c  ring. Otherwise,
21f0: 20 69 66 20 0a 2a 2a 20 53 51 4c 49 54 45 5f 45   if .** SQLITE_E
2200: 4e 41 42 4c 45 5f 38 5f 33 5f 4e 41 4d 45 53 20  NABLE_8_3_NAMES 
2210: 69 73 20 6e 6f 74 20 64 65 66 69 6e 65 64 20 6f  is not defined o
2220: 72 20 74 68 65 20 69 6e 70 75 74 20 62 75 66 66  r the input buff
2230: 65 72 20 64 6f 65 73 20 6e 6f 74 20 63 6f 6e 74  er does not cont
2240: 61 69 6e 0a 2a 2a 20 61 20 22 2e 22 20 63 68 61  ain.** a "." cha
2250: 72 61 63 74 65 72 2c 20 74 68 65 6e 20 74 68 65  racter, then the
2260: 20 6f 75 74 70 75 74 20 69 73 20 61 20 63 6f 70   output is a cop
2270: 79 20 6f 66 20 74 68 65 20 69 6e 70 75 74 20 73  y of the input s
2280: 74 72 69 6e 67 20 77 69 74 68 20 74 68 65 20 0a  tring with the .
2290: 2a 2a 20 74 68 72 65 65 2d 64 69 67 69 74 20 7a  ** three-digit z
22a0: 65 72 6f 2d 70 61 64 64 65 64 20 64 65 63 69 6d  ero-padded decim
22b0: 61 6c 20 72 65 70 72 65 73 65 6e 74 61 74 69 6f  al representatio
22c0: 6e 20 69 66 20 69 43 68 75 6e 6b 20 61 70 70 65  n if iChunk appe
22d0: 6e 64 65 64 20 74 6f 20 69 74 2e 20 0a 2a 2a 20  nded to it. .** 
22e0: 46 6f 72 20 65 78 61 6d 70 6c 65 3a 0a 2a 2a 0a  For example:.**.
22f0: 2a 2a 20 20 20 7a 42 61 73 65 3d 22 74 65 73 74  **   zBase="test
2300: 2e 64 62 22 2c 20 69 43 68 75 6e 6b 3d 34 20 20  .db", iChunk=4  
2310: 2d 3e 20 20 7a 4f 75 74 3d 22 74 65 73 74 2e 64  ->  zOut="test.d
2320: 62 30 30 34 22 0a 2a 2a 0a 2a 2a 20 4f 72 2c 20  b004".**.** Or, 
2330: 69 66 20 53 51 4c 49 54 45 5f 45 4e 41 42 4c 45  if SQLITE_ENABLE
2340: 5f 38 5f 33 5f 4e 41 4d 45 53 20 69 73 20 64 65  _8_3_NAMES is de
2350: 66 69 6e 65 64 20 61 6e 64 20 74 68 65 20 69 6e  fined and the in
2360: 70 75 74 20 62 75 66 66 65 72 20 63 6f 6e 74 61  put buffer conta
2370: 69 6e 73 0a 2a 2a 20 61 20 22 2e 22 20 63 68 61  ins.** a "." cha
2380: 72 61 63 74 65 72 2c 20 74 68 65 6e 20 65 76 65  racter, then eve
2390: 72 79 74 68 69 6e 67 20 61 66 74 65 72 20 74 68  rything after th
23a0: 65 20 22 2e 22 20 69 73 20 72 65 70 6c 61 63 65  e "." is replace
23b0: 64 20 62 79 20 74 68 65 20 0a 2a 2a 20 74 68 72  d by the .** thr
23c0: 65 65 2d 64 69 67 69 74 20 72 65 70 72 65 73 65  ee-digit represe
23d0: 6e 74 61 74 69 6f 6e 20 6f 66 20 69 43 68 75 6e  ntation of iChun
23e0: 6b 2e 0a 2a 2a 0a 2a 2a 20 20 20 7a 42 61 73 65  k..**.**   zBase
23f0: 3d 22 74 65 73 74 2e 64 62 22 2c 20 69 43 68 75  ="test.db", iChu
2400: 6e 6b 3d 34 20 20 2d 3e 20 20 7a 4f 75 74 3d 22  nk=4  ->  zOut="
2410: 74 65 73 74 2e 30 30 34 22 0a 2a 2a 0a 2a 2a 20  test.004".**.** 
2420: 54 68 65 20 6f 75 74 70 75 74 20 62 75 66 66 65  The output buffe
2430: 72 20 73 74 72 69 6e 67 20 69 73 20 74 65 72 6d  r string is term
2440: 69 6e 61 74 65 64 20 62 79 20 32 20 30 78 30 30  inated by 2 0x00
2450: 20 62 79 74 65 73 2e 20 54 68 69 73 20 6d 61 6b   bytes. This mak
2460: 65 73 20 69 74 20 73 61 66 65 0a 2a 2a 20 74 6f  es it safe.** to
2470: 20 70 61 73 73 20 74 6f 20 73 71 6c 69 74 65 33   pass to sqlite3
2480: 5f 75 72 69 5f 70 61 72 61 6d 65 74 65 72 28 29  _uri_parameter()
2490: 20 61 6e 64 20 73 69 6d 69 6c 61 72 2e 0a 2a 2f   and similar..*/
24a0: 0a 73 74 61 74 69 63 20 76 6f 69 64 20 6d 75 6c  .static void mul
24b0: 74 69 70 6c 65 78 46 69 6c 65 6e 61 6d 65 28 0a  tiplexFilename(.
24c0: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 42    const char *zB
24d0: 61 73 65 2c 20 20 20 20 20 20 20 20 20 20 20 20  ase,            
24e0: 20 20 2f 2a 20 46 69 6c 65 6e 61 6d 65 20 66 6f    /* Filename fo
24f0: 72 20 63 68 75 6e 6b 20 30 20 2a 2f 0a 20 20 69  r chunk 0 */.  i
2500: 6e 74 20 6e 42 61 73 65 2c 20 20 20 20 20 20 20  nt nBase,       
2510: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
2520: 2a 20 53 69 7a 65 20 6f 66 20 7a 42 61 73 65 20  * Size of zBase 
2530: 69 6e 20 62 79 74 65 73 20 28 77 69 74 68 6f 75  in bytes (withou
2540: 74 20 5c 30 29 20 2a 2f 0a 20 20 69 6e 74 20 66  t \0) */.  int f
2550: 6c 61 67 73 2c 20 20 20 20 20 20 20 20 20 20 20  lags,           
2560: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 46 6c             /* Fl
2570: 61 67 73 20 75 73 65 64 20 74 6f 20 6f 70 65 6e  ags used to open
2580: 20 66 69 6c 65 20 2a 2f 0a 20 20 69 6e 74 20 69   file */.  int i
2590: 43 68 75 6e 6b 2c 20 20 20 20 20 20 20 20 20 20  Chunk,          
25a0: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 43 68             /* Ch
25b0: 75 6e 6b 20 74 6f 20 67 65 6e 65 72 61 74 65 20  unk to generate 
25c0: 66 69 6c 65 6e 61 6d 65 20 66 6f 72 20 2a 2f 0a  filename for */.
25d0: 20 20 63 68 61 72 20 2a 7a 4f 75 74 20 20 20 20    char *zOut    
25e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
25f0: 20 20 2f 2a 20 42 75 66 66 65 72 20 74 6f 20 77    /* Buffer to w
2600: 72 69 74 65 20 67 65 6e 65 72 61 74 65 64 20 6e  rite generated n
2610: 61 6d 65 20 74 6f 20 2a 2f 0a 29 7b 0a 20 20 69  ame to */.){.  i
2620: 6e 74 20 6e 20 3d 20 6e 42 61 73 65 3b 0a 20 20  nt n = nBase;.  
2630: 6d 65 6d 63 70 79 28 7a 4f 75 74 2c 20 7a 42 61  memcpy(zOut, zBa
2640: 73 65 2c 20 6e 2b 31 29 3b 0a 20 20 69 66 28 20  se, n+1);.  if( 
2650: 69 43 68 75 6e 6b 21 3d 30 20 26 26 20 69 43 68  iChunk!=0 && iCh
2660: 75 6e 6b 3c 3d 4d 58 5f 43 48 55 4e 4b 5f 4e 55  unk<=MX_CHUNK_NU
2670: 4d 42 45 52 20 29 7b 0a 23 69 66 64 65 66 20 53  MBER ){.#ifdef S
2680: 51 4c 49 54 45 5f 45 4e 41 42 4c 45 5f 38 5f 33  QLITE_ENABLE_8_3
2690: 5f 4e 41 4d 45 53 0a 20 20 20 20 69 6e 74 20 69  _NAMES.    int i
26a0: 3b 0a 20 20 20 20 66 6f 72 28 69 3d 6e 2d 31 3b  ;.    for(i=n-1;
26b0: 20 69 3e 30 20 26 26 20 69 3e 3d 6e 2d 34 20 26   i>0 && i>=n-4 &
26c0: 26 20 7a 4f 75 74 5b 69 5d 21 3d 27 2e 27 3b 20  & zOut[i]!='.'; 
26d0: 69 2d 2d 29 7b 7d 0a 20 20 20 20 69 66 28 20 69  i--){}.    if( i
26e0: 3e 3d 6e 2d 34 20 29 20 6e 20 3d 20 69 2b 31 3b  >=n-4 ) n = i+1;
26f0: 0a 20 20 20 20 69 66 28 20 66 6c 61 67 73 20 26  .    if( flags &
2700: 20 53 51 4c 49 54 45 5f 4f 50 45 4e 5f 4d 41 49   SQLITE_OPEN_MAI
2710: 4e 5f 4a 4f 55 52 4e 41 4c 20 29 7b 0a 20 20 20  N_JOURNAL ){.   
2720: 20 20 20 2f 2a 20 54 68 65 20 65 78 74 65 6e 73     /* The extens
2730: 69 6f 6e 73 20 6f 6e 20 6f 76 65 72 66 6c 6f 77  ions on overflow
2740: 20 66 69 6c 65 73 20 66 6f 72 20 6d 61 69 6e 20   files for main 
2750: 64 61 74 61 62 61 73 65 73 20 61 72 65 20 30 30  databases are 00
2760: 31 2c 20 30 30 32 2c 0a 20 20 20 20 20 20 2a 2a  1, 002,.      **
2770: 20 30 30 33 20 61 6e 64 20 73 6f 20 66 6f 72 74   003 and so fort
2780: 68 2e 20 20 54 6f 20 61 76 6f 69 64 20 6e 61 6d  h.  To avoid nam
2790: 65 20 63 6f 6c 6c 69 73 69 6f 6e 73 2c 20 61 64  e collisions, ad
27a0: 64 20 34 30 30 20 74 6f 20 74 68 65 20 0a 20 20  d 400 to the .  
27b0: 20 20 20 20 2a 2a 20 65 78 74 65 6e 73 69 6f 6e      ** extension
27c0: 73 20 6f 66 20 6a 6f 75 72 6e 61 6c 20 66 69 6c  s of journal fil
27d0: 65 73 20 73 6f 20 74 68 61 74 20 74 68 65 79 20  es so that they 
27e0: 61 72 65 20 34 30 31 2c 20 34 30 32 2c 20 34 30  are 401, 402, 40
27f0: 33 2c 20 2e 2e 2e 2e 0a 20 20 20 20 20 20 2a 2f  3, .....      */
2800: 0a 20 20 20 20 20 20 69 43 68 75 6e 6b 20 2b 3d  .      iChunk +=
2810: 20 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45   SQLITE_MULTIPLE
2820: 58 5f 4a 4f 55 52 4e 41 4c 5f 38 5f 33 5f 4f 46  X_JOURNAL_8_3_OF
2830: 46 53 45 54 3b 0a 20 20 20 20 7d 65 6c 73 65 20  FSET;.    }else 
2840: 69 66 28 20 66 6c 61 67 73 20 26 20 53 51 4c 49  if( flags & SQLI
2850: 54 45 5f 4f 50 45 4e 5f 57 41 4c 20 29 7b 0a 20  TE_OPEN_WAL ){. 
2860: 20 20 20 20 20 2f 2a 20 54 6f 20 61 76 6f 69 64       /* To avoid
2870: 20 6e 61 6d 65 20 63 6f 6c 6c 69 73 69 6f 6e 73   name collisions
2880: 2c 20 61 64 64 20 37 30 30 20 74 6f 20 74 68 65  , add 700 to the
2890: 20 0a 20 20 20 20 20 20 2a 2a 20 65 78 74 65 6e   .      ** exten
28a0: 73 69 6f 6e 73 20 6f 66 20 57 41 4c 20 66 69 6c  sions of WAL fil
28b0: 65 73 20 73 6f 20 74 68 61 74 20 74 68 65 79 20  es so that they 
28c0: 61 72 65 20 37 30 31 2c 20 37 30 32 2c 20 37 30  are 701, 702, 70
28d0: 33 2c 20 2e 2e 2e 2e 0a 20 20 20 20 20 20 2a 2f  3, .....      */
28e0: 0a 20 20 20 20 20 20 69 43 68 75 6e 6b 20 2b 3d  .      iChunk +=
28f0: 20 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45   SQLITE_MULTIPLE
2900: 58 5f 57 41 4c 5f 38 5f 33 5f 4f 46 46 53 45 54  X_WAL_8_3_OFFSET
2910: 3b 0a 20 20 20 20 7d 0a 23 65 6e 64 69 66 0a 20  ;.    }.#endif. 
2920: 20 20 20 73 71 6c 69 74 65 33 5f 73 6e 70 72 69     sqlite3_snpri
2930: 6e 74 66 28 34 2c 26 7a 4f 75 74 5b 6e 5d 2c 22  ntf(4,&zOut[n],"
2940: 25 30 33 64 22 2c 69 43 68 75 6e 6b 29 3b 0a 20  %03d",iChunk);. 
2950: 20 20 20 6e 20 2b 3d 20 33 3b 0a 20 20 7d 0a 0a     n += 3;.  }..
2960: 20 20 61 73 73 65 72 74 28 20 7a 4f 75 74 5b 6e    assert( zOut[n
2970: 5d 3d 3d 27 5c 30 27 20 29 3b 0a 20 20 7a 4f 75  ]=='\0' );.  zOu
2980: 74 5b 6e 2b 31 5d 20 3d 20 27 5c 30 27 3b 0a 7d  t[n+1] = '\0';.}
2990: 0a 0a 2f 2a 20 43 6f 6d 70 75 74 65 20 74 68 65  ../* Compute the
29a0: 20 66 69 6c 65 6e 61 6d 65 20 66 6f 72 20 74 68   filename for th
29b0: 65 20 69 43 68 75 6e 6b 2d 74 68 20 63 68 75 6e  e iChunk-th chun
29c0: 6b 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20  k.*/.static int 
29d0: 6d 75 6c 74 69 70 6c 65 78 53 75 62 46 69 6c 65  multiplexSubFile
29e0: 6e 61 6d 65 28 6d 75 6c 74 69 70 6c 65 78 47 72  name(multiplexGr
29f0: 6f 75 70 20 2a 70 47 72 6f 75 70 2c 20 69 6e 74  oup *pGroup, int
2a00: 20 69 43 68 75 6e 6b 29 7b 0a 20 20 69 66 28 20   iChunk){.  if( 
2a10: 69 43 68 75 6e 6b 3e 3d 70 47 72 6f 75 70 2d 3e  iChunk>=pGroup->
2a20: 6e 52 65 61 6c 20 29 7b 0a 20 20 20 20 73 74 72  nReal ){.    str
2a30: 75 63 74 20 6d 75 6c 74 69 70 6c 65 78 52 65 61  uct multiplexRea
2a40: 6c 20 2a 70 3b 0a 20 20 20 20 70 20 3d 20 73 71  l *p;.    p = sq
2a50: 6c 69 74 65 33 5f 72 65 61 6c 6c 6f 63 28 70 47  lite3_realloc(pG
2a60: 72 6f 75 70 2d 3e 61 52 65 61 6c 2c 20 28 69 43  roup->aReal, (iC
2a70: 68 75 6e 6b 2b 31 29 2a 73 69 7a 65 6f 66 28 2a  hunk+1)*sizeof(*
2a80: 70 29 29 3b 0a 20 20 20 20 69 66 28 20 70 3d 3d  p));.    if( p==
2a90: 30 20 29 7b 0a 20 20 20 20 20 20 72 65 74 75 72  0 ){.      retur
2aa0: 6e 20 53 51 4c 49 54 45 5f 4e 4f 4d 45 4d 3b 0a  n SQLITE_NOMEM;.
2ab0: 20 20 20 20 7d 0a 20 20 20 20 6d 65 6d 73 65 74      }.    memset
2ac0: 28 26 70 5b 70 47 72 6f 75 70 2d 3e 6e 52 65 61  (&p[pGroup->nRea
2ad0: 6c 5d 2c 20 30 2c 20 73 69 7a 65 6f 66 28 70 5b  l], 0, sizeof(p[
2ae0: 30 5d 29 2a 28 69 43 68 75 6e 6b 2b 31 2d 70 47  0])*(iChunk+1-pG
2af0: 72 6f 75 70 2d 3e 6e 52 65 61 6c 29 29 3b 0a 20  roup->nReal));. 
2b00: 20 20 20 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c     pGroup->aReal
2b10: 20 3d 20 70 3b 0a 20 20 20 20 70 47 72 6f 75 70   = p;.    pGroup
2b20: 2d 3e 6e 52 65 61 6c 20 3d 20 69 43 68 75 6e 6b  ->nReal = iChunk
2b30: 2b 31 3b 0a 20 20 7d 0a 20 20 69 66 28 20 70 47  +1;.  }.  if( pG
2b40: 72 6f 75 70 2d 3e 7a 4e 61 6d 65 20 26 26 20 70  roup->zName && p
2b50: 47 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68  Group->aReal[iCh
2b60: 75 6e 6b 5d 2e 7a 3d 3d 30 20 29 7b 0a 20 20 20  unk].z==0 ){.   
2b70: 20 63 68 61 72 20 2a 7a 3b 0a 20 20 20 20 69 6e   char *z;.    in
2b80: 74 20 6e 20 3d 20 70 47 72 6f 75 70 2d 3e 6e 4e  t n = pGroup->nN
2b90: 61 6d 65 3b 0a 20 20 20 20 70 47 72 6f 75 70 2d  ame;.    pGroup-
2ba0: 3e 61 52 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e 7a  >aReal[iChunk].z
2bb0: 20 3d 20 7a 20 3d 20 73 71 6c 69 74 65 33 5f 6d   = z = sqlite3_m
2bc0: 61 6c 6c 6f 63 28 20 6e 2b 35 20 29 3b 0a 20 20  alloc( n+5 );.  
2bd0: 20 20 69 66 28 20 7a 3d 3d 30 20 29 7b 0a 20 20    if( z==0 ){.  
2be0: 20 20 20 20 72 65 74 75 72 6e 20 53 51 4c 49 54      return SQLIT
2bf0: 45 5f 4e 4f 4d 45 4d 3b 0a 20 20 20 20 7d 0a 20  E_NOMEM;.    }. 
2c00: 20 20 20 6d 75 6c 74 69 70 6c 65 78 46 69 6c 65     multiplexFile
2c10: 6e 61 6d 65 28 70 47 72 6f 75 70 2d 3e 7a 4e 61  name(pGroup->zNa
2c20: 6d 65 2c 20 70 47 72 6f 75 70 2d 3e 6e 4e 61 6d  me, pGroup->nNam
2c30: 65 2c 20 70 47 72 6f 75 70 2d 3e 66 6c 61 67 73  e, pGroup->flags
2c40: 2c 20 69 43 68 75 6e 6b 2c 20 7a 29 3b 0a 20 20  , iChunk, z);.  
2c50: 7d 0a 20 20 72 65 74 75 72 6e 20 53 51 4c 49 54  }.  return SQLIT
2c60: 45 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a 20 54 72 61 6e  E_OK;.}../* Tran
2c70: 73 6c 61 74 65 20 61 6e 20 73 71 6c 69 74 65 33  slate an sqlite3
2c80: 5f 66 69 6c 65 2a 20 74 68 61 74 20 69 73 20 72  _file* that is r
2c90: 65 61 6c 6c 79 20 61 20 6d 75 6c 74 69 70 6c 65  eally a multiple
2ca0: 78 47 72 6f 75 70 2a 20 69 6e 74 6f 0a 2a 2a 20  xGroup* into.** 
2cb0: 74 68 65 20 73 71 6c 69 74 65 33 5f 66 69 6c 65  the sqlite3_file
2cc0: 2a 20 66 6f 72 20 74 68 65 20 75 6e 64 65 72 6c  * for the underl
2cd0: 79 69 6e 67 20 6f 72 69 67 69 6e 61 6c 20 56 46  ying original VF
2ce0: 53 2e 0a 2a 2a 0a 2a 2a 20 46 6f 72 20 63 68 75  S..**.** For chu
2cf0: 6e 6b 20 30 2c 20 74 68 65 20 70 47 72 6f 75 70  nk 0, the pGroup
2d00: 2d 3e 66 6c 61 67 73 20 64 65 74 65 72 6d 69 6e  ->flags determin
2d10: 65 73 20 77 68 65 74 68 65 72 20 6f 72 20 6e 6f  es whether or no
2d20: 74 20 61 20 6e 65 77 20 66 69 6c 65 0a 2a 2a 20  t a new file.** 
2d30: 69 73 20 63 72 65 61 74 65 64 20 69 66 20 69 74  is created if it
2d40: 20 64 6f 65 73 20 6e 6f 74 20 61 6c 72 65 61 64   does not alread
2d50: 79 20 65 78 69 73 74 2e 20 20 46 6f 72 20 63 68  y exist.  For ch
2d60: 75 6e 6b 73 20 31 20 61 6e 64 20 68 69 67 68 65  unks 1 and highe
2d70: 72 2c 20 74 68 65 0a 2a 2a 20 66 69 6c 65 20 69  r, the.** file i
2d80: 73 20 63 72 65 61 74 65 64 20 6f 6e 6c 79 20 69  s created only i
2d90: 66 20 63 72 65 61 74 65 46 6c 61 67 20 69 73 20  f createFlag is 
2da0: 31 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 73 71 6c  1..*/.static sql
2db0: 69 74 65 33 5f 66 69 6c 65 20 2a 6d 75 6c 74 69  ite3_file *multi
2dc0: 70 6c 65 78 53 75 62 4f 70 65 6e 28 0a 20 20 6d  plexSubOpen(.  m
2dd0: 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 2a 70  ultiplexGroup *p
2de0: 47 72 6f 75 70 2c 20 20 20 20 2f 2a 20 54 68 65  Group,    /* The
2df0: 20 6d 75 6c 74 69 70 6c 65 78 6f 72 20 67 72 6f   multiplexor gro
2e00: 75 70 20 2a 2f 0a 20 20 69 6e 74 20 69 43 68 75  up */.  int iChu
2e10: 6e 6b 2c 20 20 20 20 20 20 20 20 20 20 20 20 20  nk,             
2e20: 20 20 20 2f 2a 20 57 68 69 63 68 20 63 68 75 6e     /* Which chun
2e30: 6b 20 74 6f 20 6f 70 65 6e 2e 20 20 30 3d 3d 6f  k to open.  0==o
2e40: 72 69 67 69 6e 61 6c 20 66 69 6c 65 20 2a 2f 0a  riginal file */.
2e50: 20 20 69 6e 74 20 2a 72 63 2c 20 20 20 20 20 20    int *rc,      
2e60: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
2e70: 52 65 73 75 6c 74 20 63 6f 64 65 20 69 6e 20 61  Result code in a
2e80: 6e 64 20 6f 75 74 20 2a 2f 0a 20 20 69 6e 74 20  nd out */.  int 
2e90: 2a 70 4f 75 74 46 6c 61 67 73 2c 20 20 20 20 20  *pOutFlags,     
2ea0: 20 20 20 20 20 20 20 2f 2a 20 4f 75 74 70 75 74         /* Output
2eb0: 20 66 6c 61 67 73 20 2a 2f 0a 20 20 69 6e 74 20   flags */.  int 
2ec0: 63 72 65 61 74 65 46 6c 61 67 20 20 20 20 20 20  createFlag      
2ed0: 20 20 20 20 20 20 20 2f 2a 20 54 72 75 65 20 74         /* True t
2ee0: 6f 20 63 72 65 61 74 65 20 69 66 20 69 43 68 75  o create if iChu
2ef0: 6e 6b 3e 30 20 2a 2f 0a 29 7b 0a 20 20 73 71 6c  nk>0 */.){.  sql
2f00: 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f  ite3_file *pSubO
2f10: 70 65 6e 20 3d 20 30 3b 0a 20 20 73 71 6c 69 74  pen = 0;.  sqlit
2f20: 65 33 5f 76 66 73 20 2a 70 4f 72 69 67 56 66 73  e3_vfs *pOrigVfs
2f30: 20 3d 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f   = gMultiplex.pO
2f40: 72 69 67 56 66 73 3b 20 20 20 20 20 20 20 20 2f  rigVfs;        /
2f50: 2a 20 52 65 61 6c 20 56 46 53 20 2a 2f 0a 0a 23  * Real VFS */..#
2f60: 69 66 64 65 66 20 53 51 4c 49 54 45 5f 45 4e 41  ifdef SQLITE_ENA
2f70: 42 4c 45 5f 38 5f 33 5f 4e 41 4d 45 53 0a 20 20  BLE_8_3_NAMES.  
2f80: 2f 2a 20 49 66 20 4a 4f 55 52 4e 41 4c 5f 38 5f  /* If JOURNAL_8_
2f90: 33 5f 4f 46 46 53 45 54 20 69 73 20 73 65 74 20  3_OFFSET is set 
2fa0: 74 6f 20 28 73 61 79 29 20 34 30 30 2c 20 74 68  to (say) 400, th
2fb0: 65 6e 20 61 6e 79 20 6f 76 65 72 66 6c 6f 77 20  en any overflow 
2fc0: 66 69 6c 65 73 20 61 72 65 20 0a 20 20 2a 2a 20  files are .  ** 
2fd0: 70 61 72 74 20 6f 66 20 61 20 64 61 74 61 62 61  part of a databa
2fe0: 73 65 20 6a 6f 75 72 6e 61 6c 20 61 72 65 20 6e  se journal are n
2ff0: 61 6d 65 64 20 64 62 2e 34 30 31 2c 20 64 62 2e  amed db.401, db.
3000: 34 30 32 2c 20 61 6e 64 20 73 6f 20 6f 6e 2e 20  402, and so on. 
3010: 41 20 0a 20 20 2a 2a 20 64 61 74 61 62 61 73 65  A .  ** database
3020: 20 6d 61 79 20 74 68 65 72 65 66 6f 72 65 20 6e   may therefore n
3030: 6f 74 20 67 72 6f 77 20 74 6f 20 6c 61 72 67 65  ot grow to large
3040: 72 20 74 68 61 6e 20 34 30 30 20 63 68 75 6e 6b  r than 400 chunk
3050: 73 2e 20 41 74 74 65 6d 70 74 69 6e 67 0a 20 20  s. Attempting.  
3060: 2a 2a 20 74 6f 20 6f 70 65 6e 20 63 68 75 6e 6b  ** to open chunk
3070: 20 34 30 31 20 69 6e 64 69 63 61 74 65 73 20 74   401 indicates t
3080: 68 65 20 64 61 74 61 62 61 73 65 20 69 73 20 66  he database is f
3090: 75 6c 6c 2e 20 2a 2f 0a 20 20 69 66 28 20 69 43  ull. */.  if( iC
30a0: 68 75 6e 6b 3e 3d 53 51 4c 49 54 45 5f 4d 55 4c  hunk>=SQLITE_MUL
30b0: 54 49 50 4c 45 58 5f 4a 4f 55 52 4e 41 4c 5f 38  TIPLEX_JOURNAL_8
30c0: 5f 33 5f 4f 46 46 53 45 54 20 29 7b 0a 20 20 20  _3_OFFSET ){.   
30d0: 20 73 71 6c 69 74 65 33 5f 6c 6f 67 28 53 51 4c   sqlite3_log(SQL
30e0: 49 54 45 5f 46 55 4c 4c 2c 20 22 6d 75 6c 74 69  ITE_FULL, "multi
30f0: 70 6c 65 78 65 64 20 63 68 75 6e 6b 20 6f 76 65  plexed chunk ove
3100: 72 66 6c 6f 77 3a 20 25 73 22 2c 20 70 47 72 6f  rflow: %s", pGro
3110: 75 70 2d 3e 7a 4e 61 6d 65 29 3b 0a 20 20 20 20  up->zName);.    
3120: 2a 72 63 20 3d 20 53 51 4c 49 54 45 5f 46 55 4c  *rc = SQLITE_FUL
3130: 4c 3b 0a 20 20 20 20 72 65 74 75 72 6e 20 30 3b  L;.    return 0;
3140: 0a 20 20 7d 0a 23 65 6e 64 69 66 0a 0a 20 20 2a  .  }.#endif..  *
3150: 72 63 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75  rc = multiplexSu
3160: 62 46 69 6c 65 6e 61 6d 65 28 70 47 72 6f 75 70  bFilename(pGroup
3170: 2c 20 69 43 68 75 6e 6b 29 3b 0a 20 20 69 66 28  , iChunk);.  if(
3180: 20 28 2a 72 63 29 3d 3d 53 51 4c 49 54 45 5f 4f   (*rc)==SQLITE_O
3190: 4b 20 26 26 20 28 70 53 75 62 4f 70 65 6e 20 3d  K && (pSubOpen =
31a0: 20 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69   pGroup->aReal[i
31b0: 43 68 75 6e 6b 5d 2e 70 29 3d 3d 30 20 29 7b 0a  Chunk].p)==0 ){.
31c0: 20 20 20 20 69 6e 74 20 66 6c 61 67 73 2c 20 62      int flags, b
31d0: 45 78 69 73 74 73 3b 0a 20 20 20 20 66 6c 61 67  Exists;.    flag
31e0: 73 20 3d 20 70 47 72 6f 75 70 2d 3e 66 6c 61 67  s = pGroup->flag
31f0: 73 3b 0a 20 20 20 20 69 66 28 20 63 72 65 61 74  s;.    if( creat
3200: 65 46 6c 61 67 20 29 7b 0a 20 20 20 20 20 20 66  eFlag ){.      f
3210: 6c 61 67 73 20 7c 3d 20 53 51 4c 49 54 45 5f 4f  lags |= SQLITE_O
3220: 50 45 4e 5f 43 52 45 41 54 45 3b 0a 20 20 20 20  PEN_CREATE;.    
3230: 7d 65 6c 73 65 20 69 66 28 20 69 43 68 75 6e 6b  }else if( iChunk
3240: 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 2f 2a 20  ==0 ){.      /* 
3250: 46 61 6c 6c 20 74 68 72 6f 75 67 68 20 2a 2f 0a  Fall through */.
3260: 20 20 20 20 7d 65 6c 73 65 20 69 66 28 20 70 47      }else if( pG
3270: 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68 75  roup->aReal[iChu
3280: 6e 6b 5d 2e 7a 3d 3d 30 20 29 7b 0a 20 20 20 20  nk].z==0 ){.    
3290: 20 20 72 65 74 75 72 6e 20 30 3b 0a 20 20 20 20    return 0;.    
32a0: 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 2a 72 63  }else{.      *rc
32b0: 20 3d 20 70 4f 72 69 67 56 66 73 2d 3e 78 41 63   = pOrigVfs->xAc
32c0: 63 65 73 73 28 70 4f 72 69 67 56 66 73 2c 20 70  cess(pOrigVfs, p
32d0: 47 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68  Group->aReal[iCh
32e0: 75 6e 6b 5d 2e 7a 2c 0a 20 20 20 20 20 20 20 20  unk].z,.        
32f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3300: 20 20 20 20 20 20 53 51 4c 49 54 45 5f 41 43 43        SQLITE_ACC
3310: 45 53 53 5f 45 58 49 53 54 53 2c 20 26 62 45 78  ESS_EXISTS, &bEx
3320: 69 73 74 73 29 3b 0a 20 20 20 20 20 69 66 28 20  ists);.     if( 
3330: 2a 72 63 20 7c 7c 20 21 62 45 78 69 73 74 73 20  *rc || !bExists 
3340: 29 7b 0a 20 20 20 20 20 20 20 20 69 66 28 20 2a  ){.        if( *
3350: 72 63 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20  rc ){.          
3360: 73 71 6c 69 74 65 33 5f 6c 6f 67 28 2a 72 63 2c  sqlite3_log(*rc,
3370: 20 22 6d 75 6c 74 69 70 6c 65 78 6f 72 2e 78 41   "multiplexor.xA
3380: 63 63 65 73 73 20 66 61 69 6c 75 72 65 20 6f 6e  ccess failure on
3390: 20 25 73 22 2c 0a 20 20 20 20 20 20 20 20 20 20   %s",.          
33a0: 20 20 20 20 20 20 20 20 20 20 20 20 70 47 72 6f              pGro
33b0: 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68 75 6e 6b  up->aReal[iChunk
33c0: 5d 2e 7a 29 3b 0a 20 20 20 20 20 20 20 20 7d 0a  ].z);.        }.
33d0: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 30          return 0
33e0: 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20  ;.      }.      
33f0: 66 6c 61 67 73 20 26 3d 20 7e 53 51 4c 49 54 45  flags &= ~SQLITE
3400: 5f 4f 50 45 4e 5f 43 52 45 41 54 45 3b 0a 20 20  _OPEN_CREATE;.  
3410: 20 20 7d 0a 20 20 20 20 70 53 75 62 4f 70 65 6e    }.    pSubOpen
3420: 20 3d 20 73 71 6c 69 74 65 33 5f 6d 61 6c 6c 6f   = sqlite3_mallo
3430: 63 28 20 70 4f 72 69 67 56 66 73 2d 3e 73 7a 4f  c( pOrigVfs->szO
3440: 73 46 69 6c 65 20 29 3b 0a 20 20 20 20 69 66 28  sFile );.    if(
3450: 20 70 53 75 62 4f 70 65 6e 3d 3d 30 20 29 7b 0a   pSubOpen==0 ){.
3460: 20 20 20 20 20 20 2a 72 63 20 3d 20 53 51 4c 49        *rc = SQLI
3470: 54 45 5f 49 4f 45 52 52 5f 4e 4f 4d 45 4d 3b 0a  TE_IOERR_NOMEM;.
3480: 20 20 20 20 20 20 72 65 74 75 72 6e 20 30 3b 0a        return 0;.
3490: 20 20 20 20 7d 0a 20 20 20 20 70 47 72 6f 75 70      }.    pGroup
34a0: 2d 3e 61 52 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e  ->aReal[iChunk].
34b0: 70 20 3d 20 70 53 75 62 4f 70 65 6e 3b 0a 20 20  p = pSubOpen;.  
34c0: 20 20 2a 72 63 20 3d 20 70 4f 72 69 67 56 66 73    *rc = pOrigVfs
34d0: 2d 3e 78 4f 70 65 6e 28 70 4f 72 69 67 56 66 73  ->xOpen(pOrigVfs
34e0: 2c 20 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c 5b  , pGroup->aReal[
34f0: 69 43 68 75 6e 6b 5d 2e 7a 2c 20 70 53 75 62 4f  iChunk].z, pSubO
3500: 70 65 6e 2c 0a 20 20 20 20 20 20 20 20 20 20 20  pen,.           
3510: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 66                 f
3520: 6c 61 67 73 2c 20 70 4f 75 74 46 6c 61 67 73 29  lags, pOutFlags)
3530: 3b 0a 20 20 20 20 69 66 28 20 28 2a 72 63 29 21  ;.    if( (*rc)!
3540: 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20  =SQLITE_OK ){.  
3550: 20 20 20 20 73 71 6c 69 74 65 33 5f 6c 6f 67 28      sqlite3_log(
3560: 2a 72 63 2c 20 22 6d 75 6c 74 69 70 6c 65 78 6f  *rc, "multiplexo
3570: 72 2e 78 4f 70 65 6e 20 66 61 69 6c 75 72 65 20  r.xOpen failure 
3580: 6f 6e 20 25 73 22 2c 0a 20 20 20 20 20 20 20 20  on %s",.        
3590: 20 20 20 20 20 20 20 20 20 20 70 47 72 6f 75 70            pGroup
35a0: 2d 3e 61 52 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e  ->aReal[iChunk].
35b0: 7a 29 3b 0a 20 20 20 20 20 20 73 71 6c 69 74 65  z);.      sqlite
35c0: 33 5f 66 72 65 65 28 70 53 75 62 4f 70 65 6e 29  3_free(pSubOpen)
35d0: 3b 0a 20 20 20 20 20 20 70 47 72 6f 75 70 2d 3e  ;.      pGroup->
35e0: 61 52 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e 70 20  aReal[iChunk].p 
35f0: 3d 20 30 3b 0a 20 20 20 20 20 20 72 65 74 75 72  = 0;.      retur
3600: 6e 20 30 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 20  n 0;.    }.  }. 
3610: 20 72 65 74 75 72 6e 20 70 53 75 62 4f 70 65 6e   return pSubOpen
3620: 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 52 65 74 75 72  ;.}../*.** Retur
3630: 6e 20 74 68 65 20 73 69 7a 65 2c 20 69 6e 20 62  n the size, in b
3640: 79 74 65 73 2c 20 6f 66 20 63 68 75 6e 6b 20 6e  ytes, of chunk n
3650: 75 6d 62 65 72 20 69 43 68 75 6e 6b 2e 20 20 49  umber iChunk.  I
3660: 66 20 74 68 61 74 20 63 68 75 6e 6b 0a 2a 2a 20  f that chunk.** 
3670: 64 6f 65 73 20 6e 6f 74 20 65 78 69 73 74 2c 20  does not exist, 
3680: 74 68 65 6e 20 72 65 74 75 72 6e 20 30 2e 20 20  then return 0.  
3690: 54 68 69 73 20 66 75 6e 63 74 69 6f 6e 20 64 6f  This function do
36a0: 65 73 20 6e 6f 74 20 64 69 73 74 69 6e 67 69 73  es not distingis
36b0: 68 20 62 65 74 77 65 65 6e 0a 2a 2a 20 6e 6f 6e  h between.** non
36c0: 2d 65 78 69 73 74 61 6e 74 20 66 69 6c 65 73 20  -existant files 
36d0: 61 6e 64 20 7a 65 72 6f 2d 6c 65 6e 67 74 68 20  and zero-length 
36e0: 66 69 6c 65 73 2e 0a 2a 2f 0a 73 74 61 74 69 63  files..*/.static
36f0: 20 73 71 6c 69 74 65 33 5f 69 6e 74 36 34 20 6d   sqlite3_int64 m
3700: 75 6c 74 69 70 6c 65 78 53 75 62 53 69 7a 65 28  ultiplexSubSize(
3710: 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75  .  multiplexGrou
3720: 70 20 2a 70 47 72 6f 75 70 2c 20 20 20 20 2f 2a  p *pGroup,    /*
3730: 20 54 68 65 20 6d 75 6c 74 69 70 6c 65 78 6f 72   The multiplexor
3740: 20 67 72 6f 75 70 20 2a 2f 0a 20 20 69 6e 74 20   group */.  int 
3750: 69 43 68 75 6e 6b 2c 20 20 20 20 20 20 20 20 20  iChunk,         
3760: 20 20 20 20 20 20 20 2f 2a 20 57 68 69 63 68 20         /* Which 
3770: 63 68 75 6e 6b 20 74 6f 20 6f 70 65 6e 2e 20 20  chunk to open.  
3780: 30 3d 3d 6f 72 69 67 69 6e 61 6c 20 66 69 6c 65  0==original file
3790: 20 2a 2f 0a 20 20 69 6e 74 20 2a 72 63 20 20 20   */.  int *rc   
37a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
37b0: 20 2f 2a 20 52 65 73 75 6c 74 20 63 6f 64 65 20   /* Result code 
37c0: 69 6e 20 61 6e 64 20 6f 75 74 20 2a 2f 0a 29 7b  in and out */.){
37d0: 0a 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20  .  sqlite3_file 
37e0: 2a 70 53 75 62 3b 0a 20 20 73 71 6c 69 74 65 33  *pSub;.  sqlite3
37f0: 5f 69 6e 74 36 34 20 73 7a 20 3d 20 30 3b 0a 0a  _int64 sz = 0;..
3800: 20 20 69 66 28 20 2a 72 63 20 29 20 72 65 74 75    if( *rc ) retu
3810: 72 6e 20 30 3b 0a 20 20 70 53 75 62 20 3d 20 6d  rn 0;.  pSub = m
3820: 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28  ultiplexSubOpen(
3830: 70 47 72 6f 75 70 2c 20 69 43 68 75 6e 6b 2c 20  pGroup, iChunk, 
3840: 72 63 2c 20 4e 55 4c 4c 2c 20 30 29 3b 0a 20 20  rc, NULL, 0);.  
3850: 69 66 28 20 70 53 75 62 3d 3d 30 20 29 20 72 65  if( pSub==0 ) re
3860: 74 75 72 6e 20 30 3b 0a 20 20 2a 72 63 20 3d 20  turn 0;.  *rc = 
3870: 70 53 75 62 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e  pSub->pMethods->
3880: 78 46 69 6c 65 53 69 7a 65 28 70 53 75 62 2c 20  xFileSize(pSub, 
3890: 26 73 7a 29 3b 0a 20 20 72 65 74 75 72 6e 20 73  &sz);.  return s
38a0: 7a 3b 0a 7d 20 20 20 20 0a 0a 2f 2a 0a 2a 2a 20  z;.}    ../*.** 
38b0: 54 68 69 73 20 69 73 20 74 68 65 20 69 6d 70 6c  This is the impl
38c0: 65 6d 65 6e 74 61 74 69 6f 6e 20 6f 66 20 74 68  ementation of th
38d0: 65 20 6d 75 6c 74 69 70 6c 65 78 5f 63 6f 6e 74  e multiplex_cont
38e0: 72 6f 6c 28 29 20 53 51 4c 20 66 75 6e 63 74 69  rol() SQL functi
38f0: 6f 6e 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 76 6f  on..*/.static vo
3900: 69 64 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 74  id multiplexCont
3910: 72 6f 6c 46 75 6e 63 28 0a 20 20 73 71 6c 69 74  rolFunc(.  sqlit
3920: 65 33 5f 63 6f 6e 74 65 78 74 20 2a 63 6f 6e 74  e3_context *cont
3930: 65 78 74 2c 0a 20 20 69 6e 74 20 61 72 67 63 2c  ext,.  int argc,
3940: 0a 20 20 73 71 6c 69 74 65 33 5f 76 61 6c 75 65  .  sqlite3_value
3950: 20 2a 2a 61 72 67 76 0a 29 7b 0a 20 20 69 6e 74   **argv.){.  int
3960: 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b   rc = SQLITE_OK;
3970: 0a 20 20 73 71 6c 69 74 65 33 20 2a 64 62 20 3d  .  sqlite3 *db =
3980: 20 73 71 6c 69 74 65 33 5f 63 6f 6e 74 65 78 74   sqlite3_context
3990: 5f 64 62 5f 68 61 6e 64 6c 65 28 63 6f 6e 74 65  _db_handle(conte
39a0: 78 74 29 3b 0a 20 20 69 6e 74 20 6f 70 3b 0a 20  xt);.  int op;. 
39b0: 20 69 6e 74 20 69 56 61 6c 3b 0a 0a 20 20 69 66   int iVal;..  if
39c0: 28 20 21 64 62 20 7c 7c 20 61 72 67 63 21 3d 32  ( !db || argc!=2
39d0: 20 29 7b 20 0a 20 20 20 20 72 63 20 3d 20 53 51   ){ .    rc = SQ
39e0: 4c 49 54 45 5f 45 52 52 4f 52 3b 20 0a 20 20 7d  LITE_ERROR; .  }
39f0: 65 6c 73 65 7b 0a 20 20 20 20 2f 2a 20 65 78 74  else{.    /* ext
3a00: 72 61 63 74 20 70 61 72 61 6d 73 20 2a 2f 0a 20  ract params */. 
3a10: 20 20 20 6f 70 20 3d 20 73 71 6c 69 74 65 33 5f     op = sqlite3_
3a20: 76 61 6c 75 65 5f 69 6e 74 28 61 72 67 76 5b 30  value_int(argv[0
3a30: 5d 29 3b 0a 20 20 20 20 69 56 61 6c 20 3d 20 73  ]);.    iVal = s
3a40: 71 6c 69 74 65 33 5f 76 61 6c 75 65 5f 69 6e 74  qlite3_value_int
3a50: 28 61 72 67 76 5b 31 5d 29 3b 0a 20 20 20 20 2f  (argv[1]);.    /
3a60: 2a 20 6d 61 70 20 66 75 6e 63 74 69 6f 6e 20 6f  * map function o
3a70: 70 20 74 6f 20 66 69 6c 65 5f 63 6f 6e 74 72 6f  p to file_contro
3a80: 6c 20 6f 70 20 2a 2f 0a 20 20 20 20 73 77 69 74  l op */.    swit
3a90: 63 68 28 20 6f 70 20 29 7b 0a 20 20 20 20 20 20  ch( op ){.      
3aa0: 63 61 73 65 20 31 3a 20 0a 20 20 20 20 20 20 20  case 1: .       
3ab0: 20 6f 70 20 3d 20 4d 55 4c 54 49 50 4c 45 58 5f   op = MULTIPLEX_
3ac0: 43 54 52 4c 5f 45 4e 41 42 4c 45 3b 20 0a 20 20  CTRL_ENABLE; .  
3ad0: 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20        break;.   
3ae0: 20 20 20 63 61 73 65 20 32 3a 20 0a 20 20 20 20     case 2: .    
3af0: 20 20 20 20 6f 70 20 3d 20 4d 55 4c 54 49 50 4c      op = MULTIPL
3b00: 45 58 5f 43 54 52 4c 5f 53 45 54 5f 43 48 55 4e  EX_CTRL_SET_CHUN
3b10: 4b 5f 53 49 5a 45 3b 20 0a 20 20 20 20 20 20 20  K_SIZE; .       
3b20: 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 63 61   break;.      ca
3b30: 73 65 20 33 3a 20 0a 20 20 20 20 20 20 20 20 6f  se 3: .        o
3b40: 70 20 3d 20 4d 55 4c 54 49 50 4c 45 58 5f 43 54  p = MULTIPLEX_CT
3b50: 52 4c 5f 53 45 54 5f 4d 41 58 5f 43 48 55 4e 4b  RL_SET_MAX_CHUNK
3b60: 53 3b 20 0a 20 20 20 20 20 20 20 20 62 72 65 61  S; .        brea
3b70: 6b 3b 0a 20 20 20 20 20 20 64 65 66 61 75 6c 74  k;.      default
3b80: 3a 0a 20 20 20 20 20 20 20 20 72 63 20 3d 20 53  :.        rc = S
3b90: 51 4c 49 54 45 5f 4e 4f 54 46 4f 55 4e 44 3b 0a  QLITE_NOTFOUND;.
3ba0: 20 20 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20          break;. 
3bb0: 20 20 20 7d 0a 20 20 7d 0a 20 20 69 66 28 20 72     }.  }.  if( r
3bc0: 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a  c==SQLITE_OK ){.
3bd0: 20 20 20 20 72 63 20 3d 20 73 71 6c 69 74 65 33      rc = sqlite3
3be0: 5f 66 69 6c 65 5f 63 6f 6e 74 72 6f 6c 28 64 62  _file_control(db
3bf0: 2c 20 30 2c 20 6f 70 2c 20 26 69 56 61 6c 29 3b  , 0, op, &iVal);
3c00: 0a 20 20 7d 0a 20 20 73 71 6c 69 74 65 33 5f 72  .  }.  sqlite3_r
3c10: 65 73 75 6c 74 5f 65 72 72 6f 72 5f 63 6f 64 65  esult_error_code
3c20: 28 63 6f 6e 74 65 78 74 2c 20 72 63 29 3b 0a 7d  (context, rc);.}
3c30: 0a 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20 69 73 20  ../*.** This is 
3c40: 74 68 65 20 65 6e 74 72 79 20 70 6f 69 6e 74 20  the entry point 
3c50: 74 6f 20 72 65 67 69 73 74 65 72 20 74 68 65 20  to register the 
3c60: 61 75 74 6f 2d 65 78 74 65 6e 73 69 6f 6e 20 66  auto-extension f
3c70: 6f 72 20 74 68 65 20 0a 2a 2a 20 6d 75 6c 74 69  or the .** multi
3c80: 70 6c 65 78 5f 63 6f 6e 74 72 6f 6c 28 29 20 66  plex_control() f
3c90: 75 6e 63 74 69 6f 6e 2e 0a 2a 2f 0a 73 74 61 74  unction..*/.stat
3ca0: 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78  ic int multiplex
3cb0: 46 75 6e 63 49 6e 69 74 28 0a 20 20 73 71 6c 69  FuncInit(.  sqli
3cc0: 74 65 33 20 2a 64 62 2c 20 0a 20 20 63 68 61 72  te3 *db, .  char
3cd0: 20 2a 2a 70 7a 45 72 72 4d 73 67 2c 20 0a 20 20   **pzErrMsg, .  
3ce0: 63 6f 6e 73 74 20 73 71 6c 69 74 65 33 5f 61 70  const sqlite3_ap
3cf0: 69 5f 72 6f 75 74 69 6e 65 73 20 2a 70 41 70 69  i_routines *pApi
3d00: 0a 29 7b 0a 20 20 69 6e 74 20 72 63 3b 0a 20 20  .){.  int rc;.  
3d10: 72 63 20 3d 20 73 71 6c 69 74 65 33 5f 63 72 65  rc = sqlite3_cre
3d20: 61 74 65 5f 66 75 6e 63 74 69 6f 6e 28 64 62 2c  ate_function(db,
3d30: 20 22 6d 75 6c 74 69 70 6c 65 78 5f 63 6f 6e 74   "multiplex_cont
3d40: 72 6f 6c 22 2c 20 32 2c 20 53 51 4c 49 54 45 5f  rol", 2, SQLITE_
3d50: 41 4e 59 2c 20 0a 20 20 20 20 20 20 30 2c 20 6d  ANY, .      0, m
3d60: 75 6c 74 69 70 6c 65 78 43 6f 6e 74 72 6f 6c 46  ultiplexControlF
3d70: 75 6e 63 2c 20 30 2c 20 30 29 3b 0a 20 20 72 65  unc, 0, 0);.  re
3d80: 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 0a 2a  turn rc;.}../*.*
3d90: 2a 20 43 6c 6f 73 65 20 61 20 73 69 6e 67 6c 65  * Close a single
3da0: 20 73 75 62 2d 66 69 6c 65 20 69 6e 20 74 68 65   sub-file in the
3db0: 20 63 6f 6e 6e 65 63 74 69 6f 6e 20 67 72 6f 75   connection grou
3dc0: 70 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 76 6f 69  p..*/.static voi
3dd0: 64 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 43 6c  d multiplexSubCl
3de0: 6f 73 65 28 0a 20 20 6d 75 6c 74 69 70 6c 65 78  ose(.  multiplex
3df0: 47 72 6f 75 70 20 2a 70 47 72 6f 75 70 2c 0a 20  Group *pGroup,. 
3e00: 20 69 6e 74 20 69 43 68 75 6e 6b 2c 0a 20 20 73   int iChunk,.  s
3e10: 71 6c 69 74 65 33 5f 76 66 73 20 2a 70 4f 72 69  qlite3_vfs *pOri
3e20: 67 56 66 73 0a 29 7b 0a 20 20 73 71 6c 69 74 65  gVfs.){.  sqlite
3e30: 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e  3_file *pSubOpen
3e40: 20 3d 20 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c   = pGroup->aReal
3e50: 5b 69 43 68 75 6e 6b 5d 2e 70 3b 0a 20 20 69 66  [iChunk].p;.  if
3e60: 28 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20  ( pSubOpen ){.  
3e70: 20 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74    pSubOpen->pMet
3e80: 68 6f 64 73 2d 3e 78 43 6c 6f 73 65 28 70 53 75  hods->xClose(pSu
3e90: 62 4f 70 65 6e 29 3b 0a 20 20 20 20 69 66 28 20  bOpen);.    if( 
3ea0: 70 4f 72 69 67 56 66 73 20 26 26 20 70 47 72 6f  pOrigVfs && pGro
3eb0: 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68 75 6e 6b  up->aReal[iChunk
3ec0: 5d 2e 7a 20 29 7b 0a 20 20 20 20 20 20 70 4f 72  ].z ){.      pOr
3ed0: 69 67 56 66 73 2d 3e 78 44 65 6c 65 74 65 28 70  igVfs->xDelete(p
3ee0: 4f 72 69 67 56 66 73 2c 20 70 47 72 6f 75 70 2d  OrigVfs, pGroup-
3ef0: 3e 61 52 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e 7a  >aReal[iChunk].z
3f00: 2c 20 30 29 3b 0a 20 20 20 20 7d 0a 20 20 20 20  , 0);.    }.    
3f10: 73 71 6c 69 74 65 33 5f 66 72 65 65 28 70 47 72  sqlite3_free(pGr
3f20: 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68 75 6e  oup->aReal[iChun
3f30: 6b 5d 2e 70 29 3b 0a 20 20 7d 0a 20 20 73 71 6c  k].p);.  }.  sql
3f40: 69 74 65 33 5f 66 72 65 65 28 70 47 72 6f 75 70  ite3_free(pGroup
3f50: 2d 3e 61 52 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e  ->aReal[iChunk].
3f60: 7a 29 3b 0a 20 20 6d 65 6d 73 65 74 28 26 70 47  z);.  memset(&pG
3f70: 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68 75  roup->aReal[iChu
3f80: 6e 6b 5d 2c 20 30 2c 20 73 69 7a 65 6f 66 28 70  nk], 0, sizeof(p
3f90: 47 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68  Group->aReal[iCh
3fa0: 75 6e 6b 5d 29 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a  unk]));.}../*.**
3fb0: 20 44 65 61 6c 6c 6f 63 61 74 65 20 6d 65 6d 6f   Deallocate memo
3fc0: 72 79 20 68 65 6c 64 20 62 79 20 61 20 6d 75 6c  ry held by a mul
3fd0: 74 69 70 6c 65 78 47 72 6f 75 70 0a 2a 2f 0a 73  tiplexGroup.*/.s
3fe0: 74 61 74 69 63 20 76 6f 69 64 20 6d 75 6c 74 69  tatic void multi
3ff0: 70 6c 65 78 46 72 65 65 43 6f 6d 70 6f 6e 65 6e  plexFreeComponen
4000: 74 73 28 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75  ts(multiplexGrou
4010: 70 20 2a 70 47 72 6f 75 70 29 7b 0a 20 20 69 6e  p *pGroup){.  in
4020: 74 20 69 3b 0a 20 20 66 6f 72 28 69 3d 30 3b 20  t i;.  for(i=0; 
4030: 69 3c 70 47 72 6f 75 70 2d 3e 6e 52 65 61 6c 3b  i<pGroup->nReal;
4040: 20 69 2b 2b 29 7b 20 6d 75 6c 74 69 70 6c 65 78   i++){ multiplex
4050: 53 75 62 43 6c 6f 73 65 28 70 47 72 6f 75 70 2c  SubClose(pGroup,
4060: 20 69 2c 20 30 29 3b 20 7d 0a 20 20 73 71 6c 69   i, 0); }.  sqli
4070: 74 65 33 5f 66 72 65 65 28 70 47 72 6f 75 70 2d  te3_free(pGroup-
4080: 3e 61 52 65 61 6c 29 3b 0a 20 20 70 47 72 6f 75  >aReal);.  pGrou
4090: 70 2d 3e 61 52 65 61 6c 20 3d 20 30 3b 0a 20 20  p->aReal = 0;.  
40a0: 70 47 72 6f 75 70 2d 3e 6e 52 65 61 6c 20 3d 20  pGroup->nReal = 
40b0: 30 3b 0a 7d 0a 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a  0;.}.../********
40c0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
40d0: 2a 20 56 46 53 20 4d 65 74 68 6f 64 20 57 72 61  * VFS Method Wra
40e0: 70 70 65 72 73 20 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ppers **********
40f0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
4100: 2a 2a 2a 2f 0a 0a 2f 2a 0a 2a 2a 20 54 68 69 73  ***/../*.** This
4110: 20 69 73 20 74 68 65 20 78 4f 70 65 6e 20 6d 65   is the xOpen me
4120: 74 68 6f 64 20 75 73 65 64 20 66 6f 72 20 74 68  thod used for th
4130: 65 20 22 6d 75 6c 74 69 70 6c 65 78 22 20 56 46  e "multiplex" VF
4140: 53 2e 0a 2a 2a 0a 2a 2a 20 4d 6f 73 74 20 6f 66  S..**.** Most of
4150: 20 74 68 65 20 77 6f 72 6b 20 69 73 20 64 6f 6e   the work is don
4160: 65 20 62 79 20 74 68 65 20 75 6e 64 65 72 6c 79  e by the underly
4170: 69 6e 67 20 6f 72 69 67 69 6e 61 6c 20 56 46 53  ing original VFS
4180: 2e 20 20 54 68 69 73 20 6d 65 74 68 6f 64 0a 2a  .  This method.*
4190: 2a 20 73 69 6d 70 6c 79 20 6c 69 6e 6b 73 20 74  * simply links t
41a0: 68 65 20 6e 65 77 20 66 69 6c 65 20 69 6e 74 6f  he new file into
41b0: 20 74 68 65 20 61 70 70 72 6f 70 72 69 61 74 65   the appropriate
41c0: 20 6d 75 6c 74 69 70 6c 65 78 20 67 72 6f 75 70   multiplex group
41d0: 20 69 66 20 69 74 20 69 73 20 61 0a 2a 2a 20 66   if it is a.** f
41e0: 69 6c 65 20 74 68 61 74 20 6e 65 65 64 73 20 74  ile that needs t
41f0: 6f 20 62 65 20 74 72 61 63 6b 65 64 2e 0a 2a 2f  o be tracked..*/
4200: 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74  .static int mult
4210: 69 70 6c 65 78 4f 70 65 6e 28 0a 20 20 73 71 6c  iplexOpen(.  sql
4220: 69 74 65 33 5f 76 66 73 20 2a 70 56 66 73 2c 20  ite3_vfs *pVfs, 
4230: 20 20 20 20 20 20 20 20 2f 2a 20 54 68 65 20 6d          /* The m
4240: 75 6c 74 69 70 6c 65 78 20 56 46 53 20 2a 2f 0a  ultiplex VFS */.
4250: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 4e    const char *zN
4260: 61 6d 65 2c 20 20 20 20 20 20 20 20 20 2f 2a 20  ame,         /* 
4270: 4e 61 6d 65 20 6f 66 20 66 69 6c 65 20 74 6f 20  Name of file to 
4280: 62 65 20 6f 70 65 6e 65 64 20 2a 2f 0a 20 20 73  be opened */.  s
4290: 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f  qlite3_file *pCo
42a0: 6e 6e 2c 20 20 20 20 20 20 20 2f 2a 20 46 69 6c  nn,       /* Fil
42b0: 6c 20 69 6e 20 74 68 69 73 20 66 69 6c 65 20 64  l in this file d
42c0: 65 73 63 72 69 70 74 6f 72 20 2a 2f 0a 20 20 69  escriptor */.  i
42d0: 6e 74 20 66 6c 61 67 73 2c 20 20 20 20 20 20 20  nt flags,       
42e0: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 46 6c 61            /* Fla
42f0: 67 73 20 74 6f 20 63 6f 6e 74 72 6f 6c 20 74 68  gs to control th
4300: 65 20 6f 70 65 6e 69 6e 67 20 2a 2f 0a 20 20 69  e opening */.  i
4310: 6e 74 20 2a 70 4f 75 74 46 6c 61 67 73 20 20 20  nt *pOutFlags   
4320: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 46 6c 61            /* Fla
4330: 67 73 20 73 68 6f 77 69 6e 67 20 72 65 73 75 6c  gs showing resul
4340: 74 73 20 6f 66 20 6f 70 65 6e 69 6e 67 20 2a 2f  ts of opening */
4350: 0a 29 7b 0a 20 20 69 6e 74 20 72 63 20 3d 20 53  .){.  int rc = S
4360: 51 4c 49 54 45 5f 4f 4b 3b 20 20 20 20 20 20 20  QLITE_OK;       
4370: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 52 65             /* Re
4380: 73 75 6c 74 20 63 6f 64 65 20 2a 2f 0a 20 20 6d  sult code */.  m
4390: 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70 4d  ultiplexConn *pM
43a0: 75 6c 74 69 70 6c 65 78 4f 70 65 6e 3b 20 20 20  ultiplexOpen;   
43b0: 20 20 20 20 2f 2a 20 54 68 65 20 6e 65 77 20 6d      /* The new m
43c0: 75 6c 74 69 70 6c 65 78 20 66 69 6c 65 20 64 65  ultiplex file de
43d0: 73 63 72 69 70 74 6f 72 20 2a 2f 0a 20 20 6d 75  scriptor */.  mu
43e0: 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 2a 70 47  ltiplexGroup *pG
43f0: 72 6f 75 70 20 3d 20 30 3b 20 20 20 20 20 20 20  roup = 0;       
4400: 20 20 20 2f 2a 20 43 6f 72 72 65 73 70 6f 6e 64     /* Correspond
4410: 69 6e 67 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f  ing multiplexGro
4420: 75 70 20 6f 62 6a 65 63 74 20 2a 2f 0a 20 20 73  up object */.  s
4430: 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75  qlite3_file *pSu
4440: 62 4f 70 65 6e 20 3d 20 30 3b 20 20 20 20 20 20  bOpen = 0;      
4450: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
4460: 20 52 65 61 6c 20 66 69 6c 65 20 64 65 73 63 72   Real file descr
4470: 69 70 74 6f 72 20 2a 2f 0a 20 20 73 71 6c 69 74  iptor */.  sqlit
4480: 65 33 5f 76 66 73 20 2a 70 4f 72 69 67 56 66 73  e3_vfs *pOrigVfs
4490: 20 3d 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f   = gMultiplex.pO
44a0: 72 69 67 56 66 73 3b 20 20 20 2f 2a 20 52 65 61  rigVfs;   /* Rea
44b0: 6c 20 56 46 53 20 2a 2f 0a 20 20 69 6e 74 20 6e  l VFS */.  int n
44c0: 4e 61 6d 65 20 3d 20 30 3b 0a 20 20 69 6e 74 20  Name = 0;.  int 
44d0: 73 7a 20 3d 20 30 3b 0a 20 20 63 68 61 72 20 2a  sz = 0;.  char *
44e0: 7a 54 6f 46 72 65 65 20 3d 20 30 3b 0a 0a 20 20  zToFree = 0;..  
44f0: 55 4e 55 53 45 44 5f 50 41 52 41 4d 45 54 45 52  UNUSED_PARAMETER
4500: 28 70 56 66 73 29 3b 0a 20 20 6d 65 6d 73 65 74  (pVfs);.  memset
4510: 28 70 43 6f 6e 6e 2c 20 30 2c 20 70 56 66 73 2d  (pConn, 0, pVfs-
4520: 3e 73 7a 4f 73 46 69 6c 65 29 3b 0a 20 20 61 73  >szOsFile);.  as
4530: 73 65 72 74 28 20 7a 4e 61 6d 65 20 7c 7c 20 28  sert( zName || (
4540: 66 6c 61 67 73 20 26 20 53 51 4c 49 54 45 5f 4f  flags & SQLITE_O
4550: 50 45 4e 5f 44 45 4c 45 54 45 4f 4e 43 4c 4f 53  PEN_DELETEONCLOS
4560: 45 29 20 29 3b 0a 0a 20 20 2f 2a 20 57 65 20 6e  E) );..  /* We n
4570: 65 65 64 20 74 6f 20 63 72 65 61 74 65 20 61 20  eed to create a 
4580: 67 72 6f 75 70 20 73 74 72 75 63 74 75 72 65 20  group structure 
4590: 61 6e 64 20 6d 61 6e 61 67 65 0a 20 20 2a 2a 20  and manage.  ** 
45a0: 61 63 63 65 73 73 20 74 6f 20 74 68 69 73 20 67  access to this g
45b0: 72 6f 75 70 20 6f 66 20 66 69 6c 65 73 2e 0a 20  roup of files.. 
45c0: 20 2a 2f 0a 20 20 6d 75 6c 74 69 70 6c 65 78 45   */.  multiplexE
45d0: 6e 74 65 72 28 29 3b 0a 20 20 70 4d 75 6c 74 69  nter();.  pMulti
45e0: 70 6c 65 78 4f 70 65 6e 20 3d 20 28 6d 75 6c 74  plexOpen = (mult
45f0: 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e  iplexConn*)pConn
4600: 3b 0a 0a 20 20 69 66 28 20 72 63 3d 3d 53 51 4c  ;..  if( rc==SQL
4610: 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 2f 2a  ITE_OK ){.    /*
4620: 20 61 6c 6c 6f 63 61 74 65 20 73 70 61 63 65 20   allocate space 
4630: 66 6f 72 20 67 72 6f 75 70 20 2a 2f 0a 20 20 20  for group */.   
4640: 20 6e 4e 61 6d 65 20 3d 20 7a 4e 61 6d 65 20 3f   nName = zName ?
4650: 20 6d 75 6c 74 69 70 6c 65 78 53 74 72 6c 65 6e   multiplexStrlen
4660: 33 30 28 7a 4e 61 6d 65 29 20 3a 20 30 3b 0a 20  30(zName) : 0;. 
4670: 20 20 20 73 7a 20 3d 20 73 69 7a 65 6f 66 28 6d     sz = sizeof(m
4680: 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 29 20 20  ultiplexGroup)  
4690: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
46a0: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 6d 75             /* mu
46b0: 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 2a 2f 0a  ltiplexGroup */.
46c0: 20 20 20 20 20 20 20 2b 20 6e 4e 61 6d 65 20 2b         + nName +
46d0: 20 31 3b 20 20 20 20 20 20 20 20 20 20 20 20 20   1;             
46e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
46f0: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 7a              /* z
4700: 4e 61 6d 65 20 2a 2f 0a 20 20 20 20 70 47 72 6f  Name */.    pGro
4710: 75 70 20 3d 20 73 71 6c 69 74 65 33 5f 6d 61 6c  up = sqlite3_mal
4720: 6c 6f 63 28 20 73 7a 20 29 3b 0a 20 20 20 20 69  loc( sz );.    i
4730: 66 28 20 70 47 72 6f 75 70 3d 3d 30 20 29 7b 0a  f( pGroup==0 ){.
4740: 20 20 20 20 20 20 72 63 20 3d 20 53 51 4c 49 54        rc = SQLIT
4750: 45 5f 4e 4f 4d 45 4d 3b 0a 20 20 20 20 7d 0a 20  E_NOMEM;.    }. 
4760: 20 7d 0a 0a 20 20 69 66 28 20 72 63 3d 3d 53 51   }..  if( rc==SQ
4770: 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 63  LITE_OK ){.    c
4780: 6f 6e 73 74 20 63 68 61 72 20 2a 7a 55 72 69 20  onst char *zUri 
4790: 3d 20 28 66 6c 61 67 73 20 26 20 53 51 4c 49 54  = (flags & SQLIT
47a0: 45 5f 4f 50 45 4e 5f 55 52 49 29 20 3f 20 7a 4e  E_OPEN_URI) ? zN
47b0: 61 6d 65 20 3a 20 30 3b 0a 20 20 20 20 2f 2a 20  ame : 0;.    /* 
47c0: 61 73 73 69 67 6e 20 70 6f 69 6e 74 65 72 73 20  assign pointers 
47d0: 74 6f 20 65 78 74 72 61 20 73 70 61 63 65 20 61  to extra space a
47e0: 6c 6c 6f 63 61 74 65 64 20 2a 2f 0a 20 20 20 20  llocated */.    
47f0: 6d 65 6d 73 65 74 28 70 47 72 6f 75 70 2c 20 30  memset(pGroup, 0
4800: 2c 20 73 7a 29 3b 0a 20 20 20 20 70 4d 75 6c 74  , sz);.    pMult
4810: 69 70 6c 65 78 4f 70 65 6e 2d 3e 70 47 72 6f 75  iplexOpen->pGrou
4820: 70 20 3d 20 70 47 72 6f 75 70 3b 0a 20 20 20 20  p = pGroup;.    
4830: 70 47 72 6f 75 70 2d 3e 62 45 6e 61 62 6c 65 64  pGroup->bEnabled
4840: 20 3d 20 2d 31 3b 0a 20 20 20 20 70 47 72 6f 75   = -1;.    pGrou
4850: 70 2d 3e 62 54 72 75 6e 63 61 74 65 20 3d 20 73  p->bTruncate = s
4860: 71 6c 69 74 65 33 5f 75 72 69 5f 62 6f 6f 6c 65  qlite3_uri_boole
4870: 61 6e 28 7a 55 72 69 2c 20 22 74 72 75 6e 63 61  an(zUri, "trunca
4880: 74 65 22 2c 20 0a 20 20 20 20 20 20 20 20 20 20  te", .          
4890: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
48a0: 20 20 20 20 20 20 20 20 20 28 66 6c 61 67 73 20           (flags 
48b0: 26 20 53 51 4c 49 54 45 5f 4f 50 45 4e 5f 4d 41  & SQLITE_OPEN_MA
48c0: 49 4e 5f 44 42 29 3d 3d 30 29 3b 0a 20 20 20 20  IN_DB)==0);.    
48d0: 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 20  pGroup->szChunk 
48e0: 3d 20 28 69 6e 74 29 73 71 6c 69 74 65 33 5f 75  = (int)sqlite3_u
48f0: 72 69 5f 69 6e 74 36 34 28 7a 55 72 69 2c 20 22  ri_int64(zUri, "
4900: 63 68 75 6e 6b 73 69 7a 65 22 2c 0a 20 20 20 20  chunksize",.    
4910: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4920: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4930: 20 20 20 20 53 51 4c 49 54 45 5f 4d 55 4c 54 49      SQLITE_MULTI
4940: 50 4c 45 58 5f 43 48 55 4e 4b 5f 53 49 5a 45 29  PLEX_CHUNK_SIZE)
4950: 3b 0a 20 20 20 20 70 47 72 6f 75 70 2d 3e 73 7a  ;.    pGroup->sz
4960: 43 68 75 6e 6b 20 3d 20 28 70 47 72 6f 75 70 2d  Chunk = (pGroup-
4970: 3e 73 7a 43 68 75 6e 6b 2b 30 78 66 66 66 66 29  >szChunk+0xffff)
4980: 26 7e 30 78 66 66 66 66 3b 0a 20 20 20 20 69 66  &~0xffff;.    if
4990: 28 20 7a 4e 61 6d 65 20 29 7b 0a 20 20 20 20 20  ( zName ){.     
49a0: 20 63 68 61 72 20 2a 70 20 3d 20 28 63 68 61 72   char *p = (char
49b0: 20 2a 29 26 70 47 72 6f 75 70 5b 31 5d 3b 0a 20   *)&pGroup[1];. 
49c0: 20 20 20 20 20 70 47 72 6f 75 70 2d 3e 7a 4e 61       pGroup->zNa
49d0: 6d 65 20 3d 20 70 3b 0a 20 20 20 20 20 20 6d 65  me = p;.      me
49e0: 6d 63 70 79 28 70 47 72 6f 75 70 2d 3e 7a 4e 61  mcpy(pGroup->zNa
49f0: 6d 65 2c 20 7a 4e 61 6d 65 2c 20 6e 4e 61 6d 65  me, zName, nName
4a00: 2b 31 29 3b 0a 20 20 20 20 20 20 70 47 72 6f 75  +1);.      pGrou
4a10: 70 2d 3e 6e 4e 61 6d 65 20 3d 20 6e 4e 61 6d 65  p->nName = nName
4a20: 3b 0a 20 20 20 20 7d 0a 20 20 20 20 69 66 28 20  ;.    }.    if( 
4a30: 70 47 72 6f 75 70 2d 3e 62 45 6e 61 62 6c 65 64  pGroup->bEnabled
4a40: 20 29 7b 0a 20 20 20 20 20 20 2f 2a 20 4d 61 6b   ){.      /* Mak
4a50: 65 20 73 75 72 65 20 74 68 61 74 20 74 68 65 20  e sure that the 
4a60: 63 68 75 6e 6b 73 69 7a 65 20 69 73 20 73 75 63  chunksize is suc
4a70: 68 20 74 68 61 74 20 74 68 65 20 70 65 6e 64 69  h that the pendi
4a80: 6e 67 20 62 79 74 65 20 64 6f 65 73 20 6e 6f 74  ng byte does not
4a90: 0a 20 20 20 20 20 20 2a 2a 20 66 61 6c 6c 73 20  .      ** falls 
4aa0: 61 74 20 74 68 65 20 65 6e 64 20 6f 66 20 61 20  at the end of a 
4ab0: 63 68 75 6e 6b 2e 20 20 41 20 72 65 67 69 6f 6e  chunk.  A region
4ac0: 20 6f 66 20 75 70 20 74 6f 20 36 34 4b 20 66 6f   of up to 64K fo
4ad0: 6c 6c 6f 77 69 6e 67 0a 20 20 20 20 20 20 2a 2a  llowing.      **
4ae0: 20 74 68 65 20 70 65 6e 64 69 6e 67 20 62 79 74   the pending byt
4af0: 65 20 69 73 20 6e 65 76 65 72 20 77 72 69 74 74  e is never writt
4b00: 65 6e 2c 20 73 6f 20 69 66 20 74 68 65 20 70 65  en, so if the pe
4b10: 6e 64 69 6e 67 20 62 79 74 65 20 6f 63 63 75 72  nding byte occur
4b20: 73 0a 20 20 20 20 20 20 2a 2a 20 6e 65 61 72 20  s.      ** near 
4b30: 74 68 65 20 65 6e 64 20 6f 66 20 61 20 63 68 75  the end of a chu
4b40: 6e 6b 2c 20 74 68 61 74 20 63 68 75 6e 6b 20 77  nk, that chunk w
4b50: 69 6c 6c 20 62 65 20 74 6f 6f 20 73 6d 61 6c 6c  ill be too small
4b60: 2e 20 2a 2f 0a 23 69 66 6e 64 65 66 20 53 51 4c  . */.#ifndef SQL
4b70: 49 54 45 5f 4f 4d 49 54 5f 57 53 44 0a 20 20 20  ITE_OMIT_WSD.   
4b80: 20 20 20 65 78 74 65 72 6e 20 69 6e 74 20 73 71     extern int sq
4b90: 6c 69 74 65 33 50 65 6e 64 69 6e 67 42 79 74 65  lite3PendingByte
4ba0: 3b 0a 23 65 6c 73 65 0a 20 20 20 20 20 20 69 6e  ;.#else.      in
4bb0: 74 20 73 71 6c 69 74 65 33 50 65 6e 64 69 6e 67  t sqlite3Pending
4bc0: 42 79 74 65 20 3d 20 30 78 34 30 30 30 30 30 30  Byte = 0x4000000
4bd0: 30 3b 0a 23 65 6e 64 69 66 0a 20 20 20 20 20 20  0;.#endif.      
4be0: 77 68 69 6c 65 28 20 28 73 71 6c 69 74 65 33 50  while( (sqlite3P
4bf0: 65 6e 64 69 6e 67 42 79 74 65 20 25 20 70 47 72  endingByte % pGr
4c00: 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 29 3e 3d 28  oup->szChunk)>=(
4c10: 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 2d  pGroup->szChunk-
4c20: 36 35 35 33 36 29 20 29 7b 0a 20 20 20 20 20 20  65536) ){.      
4c30: 20 20 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e    pGroup->szChun
4c40: 6b 20 2b 3d 20 36 35 35 33 36 3b 0a 20 20 20 20  k += 65536;.    
4c50: 20 20 7d 0a 20 20 20 20 7d 0a 20 20 20 20 70 47    }.    }.    pG
4c60: 72 6f 75 70 2d 3e 66 6c 61 67 73 20 3d 20 66 6c  roup->flags = fl
4c70: 61 67 73 3b 0a 20 20 20 20 72 63 20 3d 20 6d 75  ags;.    rc = mu
4c80: 6c 74 69 70 6c 65 78 53 75 62 46 69 6c 65 6e 61  ltiplexSubFilena
4c90: 6d 65 28 70 47 72 6f 75 70 2c 20 31 29 3b 0a 20  me(pGroup, 1);. 
4ca0: 20 20 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54     if( rc==SQLIT
4cb0: 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 70 53  E_OK ){.      pS
4cc0: 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c  ubOpen = multipl
4cd0: 65 78 53 75 62 4f 70 65 6e 28 70 47 72 6f 75 70  exSubOpen(pGroup
4ce0: 2c 20 30 2c 20 26 72 63 2c 20 70 4f 75 74 46 6c  , 0, &rc, pOutFl
4cf0: 61 67 73 2c 20 30 29 3b 0a 20 20 20 20 20 20 69  ags, 0);.      i
4d00: 66 28 20 70 53 75 62 4f 70 65 6e 3d 3d 30 20 26  f( pSubOpen==0 &
4d10: 26 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20  & rc==SQLITE_OK 
4d20: 29 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 43 41  ) rc = SQLITE_CA
4d30: 4e 54 4f 50 45 4e 3b 0a 20 20 20 20 7d 0a 20 20  NTOPEN;.    }.  
4d40: 20 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54 45    if( rc==SQLITE
4d50: 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 73 71 6c  _OK ){.      sql
4d60: 69 74 65 33 5f 69 6e 74 36 34 20 73 7a 3b 0a 0a  ite3_int64 sz;..
4d70: 20 20 20 20 20 20 72 63 20 3d 20 70 53 75 62 4f        rc = pSubO
4d80: 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e 78  pen->pMethods->x
4d90: 46 69 6c 65 53 69 7a 65 28 70 53 75 62 4f 70 65  FileSize(pSubOpe
4da0: 6e 2c 20 26 73 7a 29 3b 0a 20 20 20 20 20 20 69  n, &sz);.      i
4db0: 66 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b  f( rc==SQLITE_OK
4dc0: 20 26 26 20 7a 4e 61 6d 65 20 29 7b 0a 20 20 20   && zName ){.   
4dd0: 20 20 20 20 20 69 6e 74 20 62 45 78 69 73 74 73       int bExists
4de0: 3b 0a 20 20 20 20 20 20 20 20 69 66 28 20 73 7a  ;.        if( sz
4df0: 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 20 20 20  ==0 ){.         
4e00: 20 69 66 28 20 66 6c 61 67 73 20 26 20 53 51 4c   if( flags & SQL
4e10: 49 54 45 5f 4f 50 45 4e 5f 4d 41 49 4e 5f 4a 4f  ITE_OPEN_MAIN_JO
4e20: 55 52 4e 41 4c 20 29 7b 0a 20 20 20 20 20 20 20  URNAL ){.       
4e30: 20 20 20 20 20 2f 2a 20 49 66 20 6f 70 65 6e 69       /* If openi
4e40: 6e 67 20 61 20 6d 61 69 6e 20 6a 6f 75 72 6e 61  ng a main journa
4e50: 6c 20 66 69 6c 65 20 61 6e 64 20 74 68 65 20 66  l file and the f
4e60: 69 72 73 74 20 63 68 75 6e 6b 20 69 73 20 7a 65  irst chunk is ze
4e70: 72 6f 0a 20 20 20 20 20 20 20 20 20 20 20 20 2a  ro.            *
4e80: 2a 20 62 79 74 65 73 20 69 6e 20 73 69 7a 65 2c  * bytes in size,
4e90: 20 64 65 6c 65 74 65 20 61 6e 79 20 73 75 62 73   delete any subs
4ea0: 65 71 75 65 6e 74 20 63 68 75 6e 6b 73 20 66 72  equent chunks fr
4eb0: 6f 6d 20 74 68 65 20 0a 20 20 20 20 20 20 20 20  om the .        
4ec0: 20 20 20 20 2a 2a 20 66 69 6c 65 2d 73 79 73 74      ** file-syst
4ed0: 65 6d 2e 20 2a 2f 0a 20 20 20 20 20 20 20 20 20  em. */.         
4ee0: 20 20 20 69 6e 74 20 69 43 68 75 6e 6b 20 3d 20     int iChunk = 
4ef0: 31 3b 0a 20 20 20 20 20 20 20 20 20 20 20 20 64  1;.            d
4f00: 6f 20 7b 0a 20 20 20 20 20 20 20 20 20 20 20 20  o {.            
4f10: 20 20 72 63 20 3d 20 70 4f 72 69 67 56 66 73 2d    rc = pOrigVfs-
4f20: 3e 78 41 63 63 65 73 73 28 70 4f 72 69 67 56 66  >xAccess(pOrigVf
4f30: 73 2c 20 0a 20 20 20 20 20 20 20 20 20 20 20 20  s, .            
4f40: 20 20 20 20 20 20 70 47 72 6f 75 70 2d 3e 61 52        pGroup->aR
4f50: 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e 7a 2c 20 53  eal[iChunk].z, S
4f60: 51 4c 49 54 45 5f 41 43 43 45 53 53 5f 45 58 49  QLITE_ACCESS_EXI
4f70: 53 54 53 2c 20 26 62 45 78 69 73 74 73 0a 20 20  STS, &bExists.  
4f80: 20 20 20 20 20 20 20 20 20 20 20 20 29 3b 0a 20              );. 
4f90: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66 28               if(
4fa0: 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 26   rc==SQLITE_OK &
4fb0: 26 20 62 45 78 69 73 74 73 20 29 7b 0a 20 20 20  & bExists ){.   
4fc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 72 63 20               rc 
4fd0: 3d 20 70 4f 72 69 67 56 66 73 2d 3e 78 44 65 6c  = pOrigVfs->xDel
4fe0: 65 74 65 28 70 4f 72 69 67 56 66 73 2c 20 70 47  ete(pOrigVfs, pG
4ff0: 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68 75  roup->aReal[iChu
5000: 6e 6b 5d 2e 7a 2c 20 30 29 3b 0a 20 20 20 20 20  nk].z, 0);.     
5010: 20 20 20 20 20 20 20 20 20 20 20 69 66 28 20 72             if( r
5020: 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a  c==SQLITE_OK ){.
5030: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5040: 20 20 72 63 20 3d 20 6d 75 6c 74 69 70 6c 65 78    rc = multiplex
5050: 53 75 62 46 69 6c 65 6e 61 6d 65 28 70 47 72 6f  SubFilename(pGro
5060: 75 70 2c 20 2b 2b 69 43 68 75 6e 6b 29 3b 0a 20  up, ++iChunk);. 
5070: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 7d                 }
5080: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 7d  .              }
5090: 0a 20 20 20 20 20 20 20 20 20 20 20 20 7d 77 68  .            }wh
50a0: 69 6c 65 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f  ile( rc==SQLITE_
50b0: 4f 4b 20 26 26 20 62 45 78 69 73 74 73 20 29 3b  OK && bExists );
50c0: 0a 20 20 20 20 20 20 20 20 20 20 7d 0a 20 20 20  .          }.   
50d0: 20 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20       }else{.    
50e0: 20 20 20 20 20 20 2f 2a 20 49 66 20 74 68 65 20        /* If the 
50f0: 66 69 72 73 74 20 6f 76 65 72 66 6c 6f 77 20 66  first overflow f
5100: 69 6c 65 20 65 78 69 73 74 73 20 61 6e 64 20 69  ile exists and i
5110: 66 20 74 68 65 20 73 69 7a 65 20 6f 66 20 74 68  f the size of th
5120: 65 20 6d 61 69 6e 20 66 69 6c 65 0a 20 20 20 20  e main file.    
5130: 20 20 20 20 20 20 2a 2a 20 69 73 20 64 69 66 66        ** is diff
5140: 65 72 65 6e 74 20 66 72 6f 6d 20 74 68 65 20 63  erent from the c
5150: 68 75 6e 6b 20 73 69 7a 65 2c 20 74 68 61 74 20  hunk size, that 
5160: 6d 65 61 6e 73 20 74 68 65 20 63 68 75 6e 6b 20  means the chunk 
5170: 73 69 7a 65 20 69 73 20 73 65 74 0a 20 20 20 20  size is set.    
5180: 20 20 20 20 20 20 2a 2a 20 73 65 74 20 69 6e 63        ** set inc
5190: 6f 72 72 65 63 74 6c 79 2e 20 20 53 6f 20 66 69  orrectly.  So fi
51a0: 78 20 69 74 2e 0a 20 20 20 20 20 20 20 20 20 20  x it..          
51b0: 2a 2a 0a 20 20 20 20 20 20 20 20 20 20 2a 2a 20  **.          ** 
51c0: 4f 72 2c 20 69 66 20 74 68 65 20 66 69 72 73 74  Or, if the first
51d0: 20 6f 76 65 72 66 6c 6f 77 20 66 69 6c 65 20 64   overflow file d
51e0: 6f 65 73 20 6e 6f 74 20 65 78 69 73 74 20 61 6e  oes not exist an
51f0: 64 20 74 68 65 20 6d 61 69 6e 20 66 69 6c 65 20  d the main file 
5200: 69 73 0a 20 20 20 20 20 20 20 20 20 20 2a 2a 20  is.          ** 
5210: 6c 61 72 67 65 72 20 74 68 61 6e 20 74 68 65 20  larger than the 
5220: 63 68 75 6e 6b 20 73 69 7a 65 2c 20 74 68 61 74  chunk size, that
5230: 20 6d 65 61 6e 73 20 74 68 65 20 63 68 75 6e 6b   means the chunk
5240: 20 73 69 7a 65 20 69 73 20 74 6f 6f 20 73 6d 61   size is too sma
5250: 6c 6c 2e 0a 20 20 20 20 20 20 20 20 20 20 2a 2a  ll..          **
5260: 20 42 75 74 20 77 65 20 68 61 76 65 20 6e 6f 20   But we have no 
5270: 77 61 79 20 6f 66 20 64 65 74 65 72 6d 69 6e 69  way of determini
5280: 6e 67 20 74 68 65 20 69 6e 74 65 6e 64 65 64 20  ng the intended 
5290: 63 68 75 6e 6b 20 73 69 7a 65 2c 20 73 6f 20 0a  chunk size, so .
52a0: 20 20 20 20 20 20 20 20 20 20 2a 2a 20 6a 75 73            ** jus
52b0: 74 20 64 69 73 61 62 6c 65 20 74 68 65 20 6d 75  t disable the mu
52c0: 6c 74 69 70 6c 65 78 6f 72 20 61 6c 6c 20 74 6f  ltiplexor all to
52d0: 67 65 74 68 72 65 2e 0a 20 20 20 20 20 20 20 20  gethre..        
52e0: 20 20 2a 2f 0a 20 20 20 20 20 20 20 20 20 20 72    */.          r
52f0: 63 20 3d 20 70 4f 72 69 67 56 66 73 2d 3e 78 41  c = pOrigVfs->xA
5300: 63 63 65 73 73 28 70 4f 72 69 67 56 66 73 2c 20  ccess(pOrigVfs, 
5310: 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 31 5d  pGroup->aReal[1]
5320: 2e 7a 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20  .z,.            
5330: 20 20 53 51 4c 49 54 45 5f 41 43 43 45 53 53 5f    SQLITE_ACCESS_
5340: 45 58 49 53 54 53 2c 20 26 62 45 78 69 73 74 73  EXISTS, &bExists
5350: 29 3b 0a 20 20 20 20 20 20 20 20 20 20 62 45 78  );.          bEx
5360: 69 73 74 73 20 3d 20 6d 75 6c 74 69 70 6c 65 78  ists = multiplex
5370: 53 75 62 53 69 7a 65 28 70 47 72 6f 75 70 2c 20  SubSize(pGroup, 
5380: 31 2c 20 26 72 63 29 3e 30 3b 0a 20 20 20 20 20  1, &rc)>0;.     
5390: 20 20 20 20 20 69 66 28 20 72 63 3d 3d 53 51 4c       if( rc==SQL
53a0: 49 54 45 5f 4f 4b 20 26 26 20 62 45 78 69 73 74  ITE_OK && bExist
53b0: 73 20 20 26 26 20 73 7a 3d 3d 28 73 7a 26 30 78  s  && sz==(sz&0x
53c0: 66 66 66 66 30 30 30 30 29 20 26 26 20 73 7a 3e  ffff0000) && sz>
53d0: 30 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  0.              
53e0: 26 26 20 73 7a 21 3d 70 47 72 6f 75 70 2d 3e 73  && sz!=pGroup->s
53f0: 7a 43 68 75 6e 6b 20 29 7b 0a 20 20 20 20 20 20  zChunk ){.      
5400: 20 20 20 20 20 20 70 47 72 6f 75 70 2d 3e 73 7a        pGroup->sz
5410: 43 68 75 6e 6b 20 3d 20 28 69 6e 74 29 73 7a 3b  Chunk = (int)sz;
5420: 0a 20 20 20 20 20 20 20 20 20 20 7d 65 6c 73 65  .          }else
5430: 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f   if( rc==SQLITE_
5440: 4f 4b 20 26 26 20 21 62 45 78 69 73 74 73 20 26  OK && !bExists &
5450: 26 20 73 7a 3e 70 47 72 6f 75 70 2d 3e 73 7a 43  & sz>pGroup->szC
5460: 68 75 6e 6b 20 29 7b 0a 20 20 20 20 20 20 20 20  hunk ){.        
5470: 20 20 20 20 70 47 72 6f 75 70 2d 3e 62 45 6e 61      pGroup->bEna
5480: 62 6c 65 64 20 3d 20 30 3b 0a 20 20 20 20 20 20  bled = 0;.      
5490: 20 20 20 20 7d 0a 20 20 20 20 20 20 20 20 7d 0a      }.        }.
54a0: 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a 0a 20        }.    }.. 
54b0: 20 20 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54     if( rc==SQLIT
54c0: 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 69 66  E_OK ){.      if
54d0: 28 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74  ( pSubOpen->pMet
54e0: 68 6f 64 73 2d 3e 69 56 65 72 73 69 6f 6e 3d 3d  hods->iVersion==
54f0: 31 20 29 7b 0a 20 20 20 20 20 20 20 20 70 4d 75  1 ){.        pMu
5500: 6c 74 69 70 6c 65 78 4f 70 65 6e 2d 3e 62 61 73  ltiplexOpen->bas
5510: 65 2e 70 4d 65 74 68 6f 64 73 20 3d 20 26 67 4d  e.pMethods = &gM
5520: 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68  ultiplex.sIoMeth
5530: 6f 64 73 56 31 3b 0a 20 20 20 20 20 20 7d 65 6c  odsV1;.      }el
5540: 73 65 7b 0a 20 20 20 20 20 20 20 20 70 4d 75 6c  se{.        pMul
5550: 74 69 70 6c 65 78 4f 70 65 6e 2d 3e 62 61 73 65  tiplexOpen->base
5560: 2e 70 4d 65 74 68 6f 64 73 20 3d 20 26 67 4d 75  .pMethods = &gMu
5570: 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f  ltiplex.sIoMetho
5580: 64 73 56 32 3b 0a 20 20 20 20 20 20 7d 0a 20 20  dsV2;.      }.  
5590: 20 20 20 20 2f 2a 20 70 6c 61 63 65 20 74 68 69      /* place thi
55a0: 73 20 67 72 6f 75 70 20 61 74 20 74 68 65 20 68  s group at the h
55b0: 65 61 64 20 6f 66 20 6f 75 72 20 6c 69 73 74 20  ead of our list 
55c0: 2a 2f 0a 20 20 20 20 20 20 70 47 72 6f 75 70 2d  */.      pGroup-
55d0: 3e 70 4e 65 78 74 20 3d 20 67 4d 75 6c 74 69 70  >pNext = gMultip
55e0: 6c 65 78 2e 70 47 72 6f 75 70 73 3b 0a 20 20 20  lex.pGroups;.   
55f0: 20 20 20 69 66 28 20 67 4d 75 6c 74 69 70 6c 65     if( gMultiple
5600: 78 2e 70 47 72 6f 75 70 73 20 29 20 67 4d 75 6c  x.pGroups ) gMul
5610: 74 69 70 6c 65 78 2e 70 47 72 6f 75 70 73 2d 3e  tiplex.pGroups->
5620: 70 50 72 65 76 20 3d 20 70 47 72 6f 75 70 3b 0a  pPrev = pGroup;.
5630: 20 20 20 20 20 20 67 4d 75 6c 74 69 70 6c 65 78        gMultiplex
5640: 2e 70 47 72 6f 75 70 73 20 3d 20 70 47 72 6f 75  .pGroups = pGrou
5650: 70 3b 0a 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20  p;.    }else{.  
5660: 20 20 20 20 6d 75 6c 74 69 70 6c 65 78 46 72 65      multiplexFre
5670: 65 43 6f 6d 70 6f 6e 65 6e 74 73 28 70 47 72 6f  eComponents(pGro
5680: 75 70 29 3b 0a 20 20 20 20 20 20 73 71 6c 69 74  up);.      sqlit
5690: 65 33 5f 66 72 65 65 28 70 47 72 6f 75 70 29 3b  e3_free(pGroup);
56a0: 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20 6d 75 6c  .    }.  }.  mul
56b0: 74 69 70 6c 65 78 4c 65 61 76 65 28 29 3b 0a 20  tiplexLeave();. 
56c0: 20 73 71 6c 69 74 65 33 5f 66 72 65 65 28 7a 54   sqlite3_free(zT
56d0: 6f 46 72 65 65 29 3b 0a 20 20 72 65 74 75 72 6e  oFree);.  return
56e0: 20 72 63 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54 68   rc;.}../*.** Th
56f0: 69 73 20 69 73 20 74 68 65 20 78 44 65 6c 65 74  is is the xDelet
5700: 65 20 6d 65 74 68 6f 64 20 75 73 65 64 20 66 6f  e method used fo
5710: 72 20 74 68 65 20 22 6d 75 6c 74 69 70 6c 65 78  r the "multiplex
5720: 22 20 56 46 53 2e 0a 2a 2a 20 49 74 20 61 74 74  " VFS..** It att
5730: 65 6d 70 74 73 20 74 6f 20 64 65 6c 65 74 65 20  empts to delete 
5740: 74 68 65 20 66 69 6c 65 6e 61 6d 65 20 73 70 65  the filename spe
5750: 63 69 66 69 65 64 2e 0a 2a 2f 0a 73 74 61 74 69  cified..*/.stati
5760: 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 44  c int multiplexD
5770: 65 6c 65 74 65 28 0a 20 20 73 71 6c 69 74 65 33  elete(.  sqlite3
5780: 5f 76 66 73 20 2a 70 56 66 73 2c 20 20 20 20 20  _vfs *pVfs,     
5790: 20 20 20 20 2f 2a 20 54 68 65 20 6d 75 6c 74 69      /* The multi
57a0: 70 6c 65 78 20 56 46 53 20 2a 2f 0a 20 20 63 6f  plex VFS */.  co
57b0: 6e 73 74 20 63 68 61 72 20 2a 7a 4e 61 6d 65 2c  nst char *zName,
57c0: 20 20 20 20 20 20 20 20 20 2f 2a 20 4e 61 6d 65           /* Name
57d0: 20 6f 66 20 66 69 6c 65 20 74 6f 20 64 65 6c 65   of file to dele
57e0: 74 65 20 2a 2f 0a 20 20 69 6e 74 20 73 79 6e 63  te */.  int sync
57f0: 44 69 72 0a 29 7b 0a 20 20 69 6e 74 20 72 63 3b  Dir.){.  int rc;
5800: 0a 20 20 73 71 6c 69 74 65 33 5f 76 66 73 20 2a  .  sqlite3_vfs *
5810: 70 4f 72 69 67 56 66 73 20 3d 20 67 4d 75 6c 74  pOrigVfs = gMult
5820: 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 3b 20  iplex.pOrigVfs; 
5830: 20 20 2f 2a 20 52 65 61 6c 20 56 46 53 20 2a 2f    /* Real VFS */
5840: 0a 20 20 72 63 20 3d 20 70 4f 72 69 67 56 66 73  .  rc = pOrigVfs
5850: 2d 3e 78 44 65 6c 65 74 65 28 70 4f 72 69 67 56  ->xDelete(pOrigV
5860: 66 73 2c 20 7a 4e 61 6d 65 2c 20 73 79 6e 63 44  fs, zName, syncD
5870: 69 72 29 3b 0a 20 20 69 66 28 20 72 63 3d 3d 53  ir);.  if( rc==S
5880: 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20  QLITE_OK ){.    
5890: 2f 2a 20 49 66 20 74 68 65 20 6d 61 69 6e 20 63  /* If the main c
58a0: 68 75 6e 6b 20 77 61 73 20 64 65 6c 65 74 65 64  hunk was deleted
58b0: 20 73 75 63 63 65 73 73 66 75 6c 6c 79 2c 20 61   successfully, a
58c0: 6c 73 6f 20 64 65 6c 65 74 65 20 61 6e 79 20 73  lso delete any s
58d0: 75 62 73 65 71 75 65 6e 74 0a 20 20 20 20 2a 2a  ubsequent.    **
58e0: 20 63 68 75 6e 6b 73 20 2d 20 73 74 61 72 74 69   chunks - starti
58f0: 6e 67 20 77 69 74 68 20 74 68 65 20 6c 61 73 74  ng with the last
5900: 20 28 68 69 67 68 65 73 74 20 6e 75 6d 62 65 72   (highest number
5910: 65 64 29 2e 20 0a 20 20 20 20 2a 2f 0a 20 20 20  ed). .    */.   
5920: 20 69 6e 74 20 6e 4e 61 6d 65 20 3d 20 28 69 6e   int nName = (in
5930: 74 29 73 74 72 6c 65 6e 28 7a 4e 61 6d 65 29 3b  t)strlen(zName);
5940: 0a 20 20 20 20 63 68 61 72 20 2a 7a 3b 0a 20 20  .    char *z;.  
5950: 20 20 7a 20 3d 20 73 71 6c 69 74 65 33 5f 6d 61    z = sqlite3_ma
5960: 6c 6c 6f 63 28 6e 4e 61 6d 65 20 2b 20 35 29 3b  lloc(nName + 5);
5970: 0a 20 20 20 20 69 66 28 20 7a 3d 3d 30 20 29 7b  .    if( z==0 ){
5980: 0a 20 20 20 20 20 20 72 63 20 3d 20 53 51 4c 49  .      rc = SQLI
5990: 54 45 5f 49 4f 45 52 52 5f 4e 4f 4d 45 4d 3b 0a  TE_IOERR_NOMEM;.
59a0: 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20      }else{.     
59b0: 20 69 6e 74 20 69 43 68 75 6e 6b 20 3d 20 30 3b   int iChunk = 0;
59c0: 0a 20 20 20 20 20 20 69 6e 74 20 62 45 78 69 73  .      int bExis
59d0: 74 73 3b 0a 20 20 20 20 20 20 64 6f 7b 0a 20 20  ts;.      do{.  
59e0: 20 20 20 20 20 20 6d 75 6c 74 69 70 6c 65 78 46        multiplexF
59f0: 69 6c 65 6e 61 6d 65 28 7a 4e 61 6d 65 2c 20 6e  ilename(zName, n
5a00: 4e 61 6d 65 2c 20 53 51 4c 49 54 45 5f 4f 50 45  Name, SQLITE_OPE
5a10: 4e 5f 4d 41 49 4e 5f 4a 4f 55 52 4e 41 4c 2c 20  N_MAIN_JOURNAL, 
5a20: 2b 2b 69 43 68 75 6e 6b 2c 20 7a 29 3b 0a 20 20  ++iChunk, z);.  
5a30: 20 20 20 20 20 20 72 63 20 3d 20 70 4f 72 69 67        rc = pOrig
5a40: 56 66 73 2d 3e 78 41 63 63 65 73 73 28 70 4f 72  Vfs->xAccess(pOr
5a50: 69 67 56 66 73 2c 20 7a 2c 20 53 51 4c 49 54 45  igVfs, z, SQLITE
5a60: 5f 41 43 43 45 53 53 5f 45 58 49 53 54 53 2c 20  _ACCESS_EXISTS, 
5a70: 26 62 45 78 69 73 74 73 29 3b 0a 20 20 20 20 20  &bExists);.     
5a80: 20 7d 77 68 69 6c 65 28 20 72 63 3d 3d 53 51 4c   }while( rc==SQL
5a90: 49 54 45 5f 4f 4b 20 26 26 20 62 45 78 69 73 74  ITE_OK && bExist
5aa0: 73 20 29 3b 0a 20 20 20 20 20 20 77 68 69 6c 65  s );.      while
5ab0: 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20  ( rc==SQLITE_OK 
5ac0: 26 26 20 69 43 68 75 6e 6b 3e 31 20 29 7b 0a 20  && iChunk>1 ){. 
5ad0: 20 20 20 20 20 20 20 6d 75 6c 74 69 70 6c 65 78         multiplex
5ae0: 46 69 6c 65 6e 61 6d 65 28 7a 4e 61 6d 65 2c 20  Filename(zName, 
5af0: 6e 4e 61 6d 65 2c 20 53 51 4c 49 54 45 5f 4f 50  nName, SQLITE_OP
5b00: 45 4e 5f 4d 41 49 4e 5f 4a 4f 55 52 4e 41 4c 2c  EN_MAIN_JOURNAL,
5b10: 20 2d 2d 69 43 68 75 6e 6b 2c 20 7a 29 3b 0a 20   --iChunk, z);. 
5b20: 20 20 20 20 20 20 20 72 63 20 3d 20 70 4f 72 69         rc = pOri
5b30: 67 56 66 73 2d 3e 78 44 65 6c 65 74 65 28 70 4f  gVfs->xDelete(pO
5b40: 72 69 67 56 66 73 2c 20 7a 2c 20 73 79 6e 63 44  rigVfs, z, syncD
5b50: 69 72 29 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20  ir);.      }.   
5b60: 20 20 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54     if( rc==SQLIT
5b70: 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 20 20  E_OK ){.        
5b80: 69 43 68 75 6e 6b 20 3d 20 30 3b 0a 20 20 20 20  iChunk = 0;.    
5b90: 20 20 20 20 64 6f 7b 0a 20 20 20 20 20 20 20 20      do{.        
5ba0: 20 20 6d 75 6c 74 69 70 6c 65 78 46 69 6c 65 6e    multiplexFilen
5bb0: 61 6d 65 28 7a 4e 61 6d 65 2c 20 6e 4e 61 6d 65  ame(zName, nName
5bc0: 2c 20 53 51 4c 49 54 45 5f 4f 50 45 4e 5f 57 41  , SQLITE_OPEN_WA
5bd0: 4c 2c 20 2b 2b 69 43 68 75 6e 6b 2c 20 7a 29 3b  L, ++iChunk, z);
5be0: 0a 20 20 20 20 20 20 20 20 20 20 72 63 20 3d 20  .          rc = 
5bf0: 70 4f 72 69 67 56 66 73 2d 3e 78 41 63 63 65 73  pOrigVfs->xAcces
5c00: 73 28 70 4f 72 69 67 56 66 73 2c 20 7a 2c 20 53  s(pOrigVfs, z, S
5c10: 51 4c 49 54 45 5f 41 43 43 45 53 53 5f 45 58 49  QLITE_ACCESS_EXI
5c20: 53 54 53 2c 20 26 62 45 78 69 73 74 73 29 3b 0a  STS, &bExists);.
5c30: 20 20 20 20 20 20 20 20 7d 77 68 69 6c 65 28 20          }while( 
5c40: 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 26 26  rc==SQLITE_OK &&
5c50: 20 62 45 78 69 73 74 73 20 29 3b 0a 20 20 20 20   bExists );.    
5c60: 20 20 20 20 77 68 69 6c 65 28 20 72 63 3d 3d 53      while( rc==S
5c70: 51 4c 49 54 45 5f 4f 4b 20 26 26 20 69 43 68 75  QLITE_OK && iChu
5c80: 6e 6b 3e 31 20 29 7b 0a 20 20 20 20 20 20 20 20  nk>1 ){.        
5c90: 20 20 6d 75 6c 74 69 70 6c 65 78 46 69 6c 65 6e    multiplexFilen
5ca0: 61 6d 65 28 7a 4e 61 6d 65 2c 20 6e 4e 61 6d 65  ame(zName, nName
5cb0: 2c 20 53 51 4c 49 54 45 5f 4f 50 45 4e 5f 57 41  , SQLITE_OPEN_WA
5cc0: 4c 2c 20 2d 2d 69 43 68 75 6e 6b 2c 20 7a 29 3b  L, --iChunk, z);
5cd0: 0a 20 20 20 20 20 20 20 20 20 20 72 63 20 3d 20  .          rc = 
5ce0: 70 4f 72 69 67 56 66 73 2d 3e 78 44 65 6c 65 74  pOrigVfs->xDelet
5cf0: 65 28 70 4f 72 69 67 56 66 73 2c 20 7a 2c 20 73  e(pOrigVfs, z, s
5d00: 79 6e 63 44 69 72 29 3b 0a 20 20 20 20 20 20 20  yncDir);.       
5d10: 20 7d 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 7d   }.      }.    }
5d20: 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 66 72 65  .    sqlite3_fre
5d30: 65 28 7a 29 3b 0a 20 20 7d 0a 20 20 72 65 74 75  e(z);.  }.  retu
5d40: 72 6e 20 72 63 3b 0a 7d 0a 0a 73 74 61 74 69 63  rn rc;.}..static
5d50: 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 41 63   int multiplexAc
5d60: 63 65 73 73 28 73 71 6c 69 74 65 33 5f 76 66 73  cess(sqlite3_vfs
5d70: 20 2a 61 2c 20 63 6f 6e 73 74 20 63 68 61 72 20   *a, const char 
5d80: 2a 62 2c 20 69 6e 74 20 63 2c 20 69 6e 74 20 2a  *b, int c, int *
5d90: 64 29 7b 0a 20 20 72 65 74 75 72 6e 20 67 4d 75  d){.  return gMu
5da0: 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73  ltiplex.pOrigVfs
5db0: 2d 3e 78 41 63 63 65 73 73 28 67 4d 75 6c 74 69  ->xAccess(gMulti
5dc0: 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2c 20 62  plex.pOrigVfs, b
5dd0: 2c 20 63 2c 20 64 29 3b 0a 7d 0a 73 74 61 74 69  , c, d);.}.stati
5de0: 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 46  c int multiplexF
5df0: 75 6c 6c 50 61 74 68 6e 61 6d 65 28 73 71 6c 69  ullPathname(sqli
5e00: 74 65 33 5f 76 66 73 20 2a 61 2c 20 63 6f 6e 73  te3_vfs *a, cons
5e10: 74 20 63 68 61 72 20 2a 62 2c 20 69 6e 74 20 63  t char *b, int c
5e20: 2c 20 63 68 61 72 20 2a 64 29 7b 0a 20 20 72 65  , char *d){.  re
5e30: 74 75 72 6e 20 67 4d 75 6c 74 69 70 6c 65 78 2e  turn gMultiplex.
5e40: 70 4f 72 69 67 56 66 73 2d 3e 78 46 75 6c 6c 50  pOrigVfs->xFullP
5e50: 61 74 68 6e 61 6d 65 28 67 4d 75 6c 74 69 70 6c  athname(gMultipl
5e60: 65 78 2e 70 4f 72 69 67 56 66 73 2c 20 62 2c 20  ex.pOrigVfs, b, 
5e70: 63 2c 20 64 29 3b 0a 7d 0a 73 74 61 74 69 63 20  c, d);.}.static 
5e80: 76 6f 69 64 20 2a 6d 75 6c 74 69 70 6c 65 78 44  void *multiplexD
5e90: 6c 4f 70 65 6e 28 73 71 6c 69 74 65 33 5f 76 66  lOpen(sqlite3_vf
5ea0: 73 20 2a 61 2c 20 63 6f 6e 73 74 20 63 68 61 72  s *a, const char
5eb0: 20 2a 62 29 7b 0a 20 20 72 65 74 75 72 6e 20 67   *b){.  return g
5ec0: 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56  Multiplex.pOrigV
5ed0: 66 73 2d 3e 78 44 6c 4f 70 65 6e 28 67 4d 75 6c  fs->xDlOpen(gMul
5ee0: 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2c  tiplex.pOrigVfs,
5ef0: 20 62 29 3b 0a 7d 0a 73 74 61 74 69 63 20 76 6f   b);.}.static vo
5f00: 69 64 20 6d 75 6c 74 69 70 6c 65 78 44 6c 45 72  id multiplexDlEr
5f10: 72 6f 72 28 73 71 6c 69 74 65 33 5f 76 66 73 20  ror(sqlite3_vfs 
5f20: 2a 61 2c 20 69 6e 74 20 62 2c 20 63 68 61 72 20  *a, int b, char 
5f30: 2a 63 29 7b 0a 20 20 67 4d 75 6c 74 69 70 6c 65  *c){.  gMultiple
5f40: 78 2e 70 4f 72 69 67 56 66 73 2d 3e 78 44 6c 45  x.pOrigVfs->xDlE
5f50: 72 72 6f 72 28 67 4d 75 6c 74 69 70 6c 65 78 2e  rror(gMultiplex.
5f60: 70 4f 72 69 67 56 66 73 2c 20 62 2c 20 63 29 3b  pOrigVfs, b, c);
5f70: 0a 7d 0a 73 74 61 74 69 63 20 76 6f 69 64 20 28  .}.static void (
5f80: 2a 6d 75 6c 74 69 70 6c 65 78 44 6c 53 79 6d 28  *multiplexDlSym(
5f90: 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 61 2c 20  sqlite3_vfs *a, 
5fa0: 76 6f 69 64 20 2a 62 2c 20 63 6f 6e 73 74 20 63  void *b, const c
5fb0: 68 61 72 20 2a 63 29 29 28 76 6f 69 64 29 7b 0a  har *c))(void){.
5fc0: 20 20 72 65 74 75 72 6e 20 67 4d 75 6c 74 69 70    return gMultip
5fd0: 6c 65 78 2e 70 4f 72 69 67 56 66 73 2d 3e 78 44  lex.pOrigVfs->xD
5fe0: 6c 53 79 6d 28 67 4d 75 6c 74 69 70 6c 65 78 2e  lSym(gMultiplex.
5ff0: 70 4f 72 69 67 56 66 73 2c 20 62 2c 20 63 29 3b  pOrigVfs, b, c);
6000: 0a 7d 0a 73 74 61 74 69 63 20 76 6f 69 64 20 6d  .}.static void m
6010: 75 6c 74 69 70 6c 65 78 44 6c 43 6c 6f 73 65 28  ultiplexDlClose(
6020: 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 61 2c 20  sqlite3_vfs *a, 
6030: 76 6f 69 64 20 2a 62 29 7b 0a 20 20 67 4d 75 6c  void *b){.  gMul
6040: 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2d  tiplex.pOrigVfs-
6050: 3e 78 44 6c 43 6c 6f 73 65 28 67 4d 75 6c 74 69  >xDlClose(gMulti
6060: 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2c 20 62  plex.pOrigVfs, b
6070: 29 3b 0a 7d 0a 73 74 61 74 69 63 20 69 6e 74 20  );.}.static int 
6080: 6d 75 6c 74 69 70 6c 65 78 52 61 6e 64 6f 6d 6e  multiplexRandomn
6090: 65 73 73 28 73 71 6c 69 74 65 33 5f 76 66 73 20  ess(sqlite3_vfs 
60a0: 2a 61 2c 20 69 6e 74 20 62 2c 20 63 68 61 72 20  *a, int b, char 
60b0: 2a 63 29 7b 0a 20 20 72 65 74 75 72 6e 20 67 4d  *c){.  return gM
60c0: 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66  ultiplex.pOrigVf
60d0: 73 2d 3e 78 52 61 6e 64 6f 6d 6e 65 73 73 28 67  s->xRandomness(g
60e0: 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56  Multiplex.pOrigV
60f0: 66 73 2c 20 62 2c 20 63 29 3b 0a 7d 0a 73 74 61  fs, b, c);.}.sta
6100: 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65  tic int multiple
6110: 78 53 6c 65 65 70 28 73 71 6c 69 74 65 33 5f 76  xSleep(sqlite3_v
6120: 66 73 20 2a 61 2c 20 69 6e 74 20 62 29 7b 0a 20  fs *a, int b){. 
6130: 20 72 65 74 75 72 6e 20 67 4d 75 6c 74 69 70 6c   return gMultipl
6140: 65 78 2e 70 4f 72 69 67 56 66 73 2d 3e 78 53 6c  ex.pOrigVfs->xSl
6150: 65 65 70 28 67 4d 75 6c 74 69 70 6c 65 78 2e 70  eep(gMultiplex.p
6160: 4f 72 69 67 56 66 73 2c 20 62 29 3b 0a 7d 0a 73  OrigVfs, b);.}.s
6170: 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70  tatic int multip
6180: 6c 65 78 43 75 72 72 65 6e 74 54 69 6d 65 28 73  lexCurrentTime(s
6190: 71 6c 69 74 65 33 5f 76 66 73 20 2a 61 2c 20 64  qlite3_vfs *a, d
61a0: 6f 75 62 6c 65 20 2a 62 29 7b 0a 20 20 72 65 74  ouble *b){.  ret
61b0: 75 72 6e 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70  urn gMultiplex.p
61c0: 4f 72 69 67 56 66 73 2d 3e 78 43 75 72 72 65 6e  OrigVfs->xCurren
61d0: 74 54 69 6d 65 28 67 4d 75 6c 74 69 70 6c 65 78  tTime(gMultiplex
61e0: 2e 70 4f 72 69 67 56 66 73 2c 20 62 29 3b 0a 7d  .pOrigVfs, b);.}
61f0: 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74  .static int mult
6200: 69 70 6c 65 78 47 65 74 4c 61 73 74 45 72 72 6f  iplexGetLastErro
6210: 72 28 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 61  r(sqlite3_vfs *a
6220: 2c 20 69 6e 74 20 62 2c 20 63 68 61 72 20 2a 63  , int b, char *c
6230: 29 7b 0a 20 20 72 65 74 75 72 6e 20 67 4d 75 6c  ){.  return gMul
6240: 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2d  tiplex.pOrigVfs-
6250: 3e 78 47 65 74 4c 61 73 74 45 72 72 6f 72 28 67  >xGetLastError(g
6260: 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56  Multiplex.pOrigV
6270: 66 73 2c 20 62 2c 20 63 29 3b 0a 7d 0a 73 74 61  fs, b, c);.}.sta
6280: 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65  tic int multiple
6290: 78 43 75 72 72 65 6e 74 54 69 6d 65 49 6e 74 36  xCurrentTimeInt6
62a0: 34 28 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 61  4(sqlite3_vfs *a
62b0: 2c 20 73 71 6c 69 74 65 33 5f 69 6e 74 36 34 20  , sqlite3_int64 
62c0: 2a 62 29 7b 0a 20 20 72 65 74 75 72 6e 20 67 4d  *b){.  return gM
62d0: 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66  ultiplex.pOrigVf
62e0: 73 2d 3e 78 43 75 72 72 65 6e 74 54 69 6d 65 49  s->xCurrentTimeI
62f0: 6e 74 36 34 28 67 4d 75 6c 74 69 70 6c 65 78 2e  nt64(gMultiplex.
6300: 70 4f 72 69 67 56 66 73 2c 20 62 29 3b 0a 7d 0a  pOrigVfs, b);.}.
6310: 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ./**************
6320: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20 49 2f 4f 20 4d  ********** I/O M
6330: 65 74 68 6f 64 20 57 72 61 70 70 65 72 73 20 2a  ethod Wrappers *
6340: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
6350: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2f 0a  **************/.
6360: 0a 2f 2a 20 78 43 6c 6f 73 65 20 72 65 71 75 65  ./* xClose reque
6370: 73 74 73 20 67 65 74 20 70 61 73 73 65 64 20 74  sts get passed t
6380: 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20 6f 72  hrough to the or
6390: 69 67 69 6e 61 6c 20 56 46 53 2e 0a 2a 2a 20 57  iginal VFS..** W
63a0: 65 20 6c 6f 6f 70 20 6f 76 65 72 20 61 6c 6c 20  e loop over all 
63b0: 6f 70 65 6e 20 63 68 75 6e 6b 20 68 61 6e 64 6c  open chunk handl
63c0: 65 73 20 61 6e 64 20 63 6c 6f 73 65 20 74 68 65  es and close the
63d0: 6d 2e 0a 2a 2a 20 54 68 65 20 67 72 6f 75 70 20  m..** The group 
63e0: 73 74 72 75 63 74 75 72 65 20 66 6f 72 20 74 68  structure for th
63f0: 69 73 20 66 69 6c 65 20 69 73 20 75 6e 6c 69 6e  is file is unlin
6400: 6b 65 64 20 66 72 6f 6d 20 0a 2a 2a 20 6f 75 72  ked from .** our
6410: 20 6c 69 73 74 20 6f 66 20 67 72 6f 75 70 73 20   list of groups 
6420: 61 6e 64 20 66 72 65 65 64 2e 0a 2a 2f 0a 73 74  and freed..*/.st
6430: 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c  atic int multipl
6440: 65 78 43 6c 6f 73 65 28 73 71 6c 69 74 65 33 5f  exClose(sqlite3_
6450: 66 69 6c 65 20 2a 70 43 6f 6e 6e 29 7b 0a 20 20  file *pConn){.  
6460: 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70  multiplexConn *p
6470: 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e   = (multiplexCon
6480: 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 6d 75 6c 74  n*)pConn;.  mult
6490: 69 70 6c 65 78 47 72 6f 75 70 20 2a 70 47 72 6f  iplexGroup *pGro
64a0: 75 70 20 3d 20 70 2d 3e 70 47 72 6f 75 70 3b 0a  up = p->pGroup;.
64b0: 20 20 69 6e 74 20 72 63 20 3d 20 53 51 4c 49 54    int rc = SQLIT
64c0: 45 5f 4f 4b 3b 0a 20 20 6d 75 6c 74 69 70 6c 65  E_OK;.  multiple
64d0: 78 45 6e 74 65 72 28 29 3b 0a 20 20 6d 75 6c 74  xEnter();.  mult
64e0: 69 70 6c 65 78 46 72 65 65 43 6f 6d 70 6f 6e 65  iplexFreeCompone
64f0: 6e 74 73 28 70 47 72 6f 75 70 29 3b 0a 20 20 2f  nts(pGroup);.  /
6500: 2a 20 72 65 6d 6f 76 65 20 66 72 6f 6d 20 6c 69  * remove from li
6510: 6e 6b 65 64 20 6c 69 73 74 20 2a 2f 0a 20 20 69  nked list */.  i
6520: 66 28 20 70 47 72 6f 75 70 2d 3e 70 4e 65 78 74  f( pGroup->pNext
6530: 20 29 20 70 47 72 6f 75 70 2d 3e 70 4e 65 78 74   ) pGroup->pNext
6540: 2d 3e 70 50 72 65 76 20 3d 20 70 47 72 6f 75 70  ->pPrev = pGroup
6550: 2d 3e 70 50 72 65 76 3b 0a 20 20 69 66 28 20 70  ->pPrev;.  if( p
6560: 47 72 6f 75 70 2d 3e 70 50 72 65 76 20 29 7b 0a  Group->pPrev ){.
6570: 20 20 20 20 70 47 72 6f 75 70 2d 3e 70 50 72 65      pGroup->pPre
6580: 76 2d 3e 70 4e 65 78 74 20 3d 20 70 47 72 6f 75  v->pNext = pGrou
6590: 70 2d 3e 70 4e 65 78 74 3b 0a 20 20 7d 65 6c 73  p->pNext;.  }els
65a0: 65 7b 0a 20 20 20 20 67 4d 75 6c 74 69 70 6c 65  e{.    gMultiple
65b0: 78 2e 70 47 72 6f 75 70 73 20 3d 20 70 47 72 6f  x.pGroups = pGro
65c0: 75 70 2d 3e 70 4e 65 78 74 3b 0a 20 20 7d 0a 20  up->pNext;.  }. 
65d0: 20 73 71 6c 69 74 65 33 5f 66 72 65 65 28 70 47   sqlite3_free(pG
65e0: 72 6f 75 70 29 3b 0a 20 20 6d 75 6c 74 69 70 6c  roup);.  multipl
65f0: 65 78 4c 65 61 76 65 28 29 3b 0a 20 20 72 65 74  exLeave();.  ret
6600: 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 20 50 61  urn rc;.}../* Pa
6610: 73 73 20 78 52 65 61 64 20 72 65 71 75 65 73 74  ss xRead request
6620: 73 20 74 68 72 75 20 74 6f 20 74 68 65 20 6f 72  s thru to the or
6630: 69 67 69 6e 61 6c 20 56 46 53 20 61 66 74 65 72  iginal VFS after
6640: 0a 2a 2a 20 64 65 74 65 72 6d 69 6e 69 6e 67 20  .** determining 
6650: 74 68 65 20 63 6f 72 72 65 63 74 20 63 68 75 6e  the correct chun
6660: 6b 20 74 6f 20 6f 70 65 72 61 74 65 20 6f 6e 2e  k to operate on.
6670: 0a 2a 2a 20 42 72 65 61 6b 20 75 70 20 72 65 61  .** Break up rea
6680: 64 73 20 61 63 72 6f 73 73 20 63 68 75 6e 6b 20  ds across chunk 
6690: 62 6f 75 6e 64 61 72 69 65 73 2e 0a 2a 2f 0a 73  boundaries..*/.s
66a0: 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70  tatic int multip
66b0: 6c 65 78 52 65 61 64 28 0a 20 20 73 71 6c 69 74  lexRead(.  sqlit
66c0: 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c 0a  e3_file *pConn,.
66d0: 20 20 76 6f 69 64 20 2a 70 42 75 66 2c 0a 20 20    void *pBuf,.  
66e0: 69 6e 74 20 69 41 6d 74 2c 0a 20 20 73 71 6c 69  int iAmt,.  sqli
66f0: 74 65 33 5f 69 6e 74 36 34 20 69 4f 66 73 74 0a  te3_int64 iOfst.
6700: 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f  ){.  multiplexCo
6710: 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c  nn *p = (multipl
6720: 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20  exConn*)pConn;. 
6730: 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 20   multiplexGroup 
6740: 2a 70 47 72 6f 75 70 20 3d 20 70 2d 3e 70 47 72  *pGroup = p->pGr
6750: 6f 75 70 3b 0a 20 20 69 6e 74 20 72 63 20 3d 20  oup;.  int rc = 
6760: 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 6d 75 6c  SQLITE_OK;.  mul
6770: 74 69 70 6c 65 78 45 6e 74 65 72 28 29 3b 0a 20  tiplexEnter();. 
6780: 20 69 66 28 20 21 70 47 72 6f 75 70 2d 3e 62 45   if( !pGroup->bE
6790: 6e 61 62 6c 65 64 20 29 7b 0a 20 20 20 20 73 71  nabled ){.    sq
67a0: 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62  lite3_file *pSub
67b0: 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78  Open = multiplex
67c0: 53 75 62 4f 70 65 6e 28 70 47 72 6f 75 70 2c 20  SubOpen(pGroup, 
67d0: 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 2c 20 30 29  0, &rc, NULL, 0)
67e0: 3b 0a 20 20 20 20 69 66 28 20 70 53 75 62 4f 70  ;.    if( pSubOp
67f0: 65 6e 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 72  en==0 ){.      r
6800: 63 20 3d 20 53 51 4c 49 54 45 5f 49 4f 45 52 52  c = SQLITE_IOERR
6810: 5f 52 45 41 44 3b 0a 20 20 20 20 7d 65 6c 73 65  _READ;.    }else
6820: 7b 0a 20 20 20 20 20 20 72 63 20 3d 20 70 53 75  {.      rc = pSu
6830: 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d  bOpen->pMethods-
6840: 3e 78 52 65 61 64 28 70 53 75 62 4f 70 65 6e 2c  >xRead(pSubOpen,
6850: 20 70 42 75 66 2c 20 69 41 6d 74 2c 20 69 4f 66   pBuf, iAmt, iOf
6860: 73 74 29 3b 0a 20 20 20 20 7d 0a 20 20 7d 65 6c  st);.    }.  }el
6870: 73 65 7b 0a 20 20 20 20 77 68 69 6c 65 28 20 69  se{.    while( i
6880: 41 6d 74 20 3e 20 30 20 29 7b 0a 20 20 20 20 20  Amt > 0 ){.     
6890: 20 69 6e 74 20 69 20 3d 20 28 69 6e 74 29 28 69   int i = (int)(i
68a0: 4f 66 73 74 20 2f 20 70 47 72 6f 75 70 2d 3e 73  Ofst / pGroup->s
68b0: 7a 43 68 75 6e 6b 29 3b 0a 20 20 20 20 20 20 73  zChunk);.      s
68c0: 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75  qlite3_file *pSu
68d0: 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65  bOpen = multiple
68e0: 78 53 75 62 4f 70 65 6e 28 70 47 72 6f 75 70 2c  xSubOpen(pGroup,
68f0: 20 69 2c 20 26 72 63 2c 20 4e 55 4c 4c 2c 20 31   i, &rc, NULL, 1
6900: 29 3b 0a 20 20 20 20 20 20 69 66 28 20 70 53 75  );.      if( pSu
6910: 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20 20 20 20  bOpen ){.       
6920: 20 69 6e 74 20 65 78 74 72 61 20 3d 20 28 28 69   int extra = ((i
6930: 6e 74 29 28 69 4f 66 73 74 20 25 20 70 47 72 6f  nt)(iOfst % pGro
6940: 75 70 2d 3e 73 7a 43 68 75 6e 6b 29 20 2b 20 69  up->szChunk) + i
6950: 41 6d 74 29 20 2d 20 70 47 72 6f 75 70 2d 3e 73  Amt) - pGroup->s
6960: 7a 43 68 75 6e 6b 3b 0a 20 20 20 20 20 20 20 20  zChunk;.        
6970: 69 66 28 20 65 78 74 72 61 3c 30 20 29 20 65 78  if( extra<0 ) ex
6980: 74 72 61 20 3d 20 30 3b 0a 20 20 20 20 20 20 20  tra = 0;.       
6990: 20 69 41 6d 74 20 2d 3d 20 65 78 74 72 61 3b 0a   iAmt -= extra;.
69a0: 20 20 20 20 20 20 20 20 72 63 20 3d 20 70 53 75          rc = pSu
69b0: 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d  bOpen->pMethods-
69c0: 3e 78 52 65 61 64 28 70 53 75 62 4f 70 65 6e 2c  >xRead(pSubOpen,
69d0: 20 70 42 75 66 2c 20 69 41 6d 74 2c 0a 20 20 20   pBuf, iAmt,.   
69e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
69f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6a00: 20 20 20 20 69 4f 66 73 74 20 25 20 70 47 72 6f      iOfst % pGro
6a10: 75 70 2d 3e 73 7a 43 68 75 6e 6b 29 3b 0a 20 20  up->szChunk);.  
6a20: 20 20 20 20 20 20 69 66 28 20 72 63 21 3d 53 51        if( rc!=SQ
6a30: 4c 49 54 45 5f 4f 4b 20 29 20 62 72 65 61 6b 3b  LITE_OK ) break;
6a40: 0a 20 20 20 20 20 20 20 20 70 42 75 66 20 3d 20  .        pBuf = 
6a50: 28 63 68 61 72 20 2a 29 70 42 75 66 20 2b 20 69  (char *)pBuf + i
6a60: 41 6d 74 3b 0a 20 20 20 20 20 20 20 20 69 4f 66  Amt;.        iOf
6a70: 73 74 20 2b 3d 20 69 41 6d 74 3b 0a 20 20 20 20  st += iAmt;.    
6a80: 20 20 20 20 69 41 6d 74 20 3d 20 65 78 74 72 61      iAmt = extra
6a90: 3b 0a 20 20 20 20 20 20 7d 65 6c 73 65 7b 0a 20  ;.      }else{. 
6aa0: 20 20 20 20 20 20 20 72 63 20 3d 20 53 51 4c 49         rc = SQLI
6ab0: 54 45 5f 49 4f 45 52 52 5f 52 45 41 44 3b 0a 20  TE_IOERR_READ;. 
6ac0: 20 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20 20         break;.  
6ad0: 20 20 20 20 7d 0a 20 20 20 20 7d 0a 20 20 7d 0a      }.    }.  }.
6ae0: 20 20 6d 75 6c 74 69 70 6c 65 78 4c 65 61 76 65    multiplexLeave
6af0: 28 29 3b 0a 20 20 72 65 74 75 72 6e 20 72 63 3b  ();.  return rc;
6b00: 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 57 72 69  .}../* Pass xWri
6b10: 74 65 20 72 65 71 75 65 73 74 73 20 74 68 72 75  te requests thru
6b20: 20 74 6f 20 74 68 65 20 6f 72 69 67 69 6e 61 6c   to the original
6b30: 20 56 46 53 20 61 66 74 65 72 0a 2a 2a 20 64 65   VFS after.** de
6b40: 74 65 72 6d 69 6e 69 6e 67 20 74 68 65 20 63 6f  termining the co
6b50: 72 72 65 63 74 20 63 68 75 6e 6b 20 74 6f 20 6f  rrect chunk to o
6b60: 70 65 72 61 74 65 20 6f 6e 2e 0a 2a 2a 20 42 72  perate on..** Br
6b70: 65 61 6b 20 75 70 20 77 72 69 74 65 73 20 61 63  eak up writes ac
6b80: 72 6f 73 73 20 63 68 75 6e 6b 20 62 6f 75 6e 64  ross chunk bound
6b90: 61 72 69 65 73 2e 0a 2a 2f 0a 73 74 61 74 69 63  aries..*/.static
6ba0: 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 57 72   int multiplexWr
6bb0: 69 74 65 28 0a 20 20 73 71 6c 69 74 65 33 5f 66  ite(.  sqlite3_f
6bc0: 69 6c 65 20 2a 70 43 6f 6e 6e 2c 0a 20 20 63 6f  ile *pConn,.  co
6bd0: 6e 73 74 20 76 6f 69 64 20 2a 70 42 75 66 2c 0a  nst void *pBuf,.
6be0: 20 20 69 6e 74 20 69 41 6d 74 2c 0a 20 20 73 71    int iAmt,.  sq
6bf0: 6c 69 74 65 33 5f 69 6e 74 36 34 20 69 4f 66 73  lite3_int64 iOfs
6c00: 74 0a 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78  t.){.  multiplex
6c10: 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69  Conn *p = (multi
6c20: 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b  plexConn*)pConn;
6c30: 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75  .  multiplexGrou
6c40: 70 20 2a 70 47 72 6f 75 70 20 3d 20 70 2d 3e 70  p *pGroup = p->p
6c50: 47 72 6f 75 70 3b 0a 20 20 69 6e 74 20 72 63 20  Group;.  int rc 
6c60: 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 6d  = SQLITE_OK;.  m
6c70: 75 6c 74 69 70 6c 65 78 45 6e 74 65 72 28 29 3b  ultiplexEnter();
6c80: 0a 20 20 69 66 28 20 21 70 47 72 6f 75 70 2d 3e  .  if( !pGroup->
6c90: 62 45 6e 61 62 6c 65 64 20 29 7b 0a 20 20 20 20  bEnabled ){.    
6ca0: 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53  sqlite3_file *pS
6cb0: 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c  ubOpen = multipl
6cc0: 65 78 53 75 62 4f 70 65 6e 28 70 47 72 6f 75 70  exSubOpen(pGroup
6cd0: 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 2c 20  , 0, &rc, NULL, 
6ce0: 30 29 3b 0a 20 20 20 20 69 66 28 20 70 53 75 62  0);.    if( pSub
6cf0: 4f 70 65 6e 3d 3d 30 20 29 7b 0a 20 20 20 20 20  Open==0 ){.     
6d00: 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 49 4f 45   rc = SQLITE_IOE
6d10: 52 52 5f 57 52 49 54 45 3b 0a 20 20 20 20 7d 65  RR_WRITE;.    }e
6d20: 6c 73 65 7b 0a 20 20 20 20 20 20 72 63 20 3d 20  lse{.      rc = 
6d30: 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f  pSubOpen->pMetho
6d40: 64 73 2d 3e 78 57 72 69 74 65 28 70 53 75 62 4f  ds->xWrite(pSubO
6d50: 70 65 6e 2c 20 70 42 75 66 2c 20 69 41 6d 74 2c  pen, pBuf, iAmt,
6d60: 20 69 4f 66 73 74 29 3b 0a 20 20 20 20 7d 0a 20   iOfst);.    }. 
6d70: 20 7d 65 6c 73 65 7b 0a 20 20 20 20 77 68 69 6c   }else{.    whil
6d80: 65 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b  e( rc==SQLITE_OK
6d90: 20 26 26 20 69 41 6d 74 3e 30 20 29 7b 0a 20 20   && iAmt>0 ){.  
6da0: 20 20 20 20 69 6e 74 20 69 20 3d 20 28 69 6e 74      int i = (int
6db0: 29 28 69 4f 66 73 74 20 2f 20 70 47 72 6f 75 70  )(iOfst / pGroup
6dc0: 2d 3e 73 7a 43 68 75 6e 6b 29 3b 0a 20 20 20 20  ->szChunk);.    
6dd0: 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a    sqlite3_file *
6de0: 70 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69  pSubOpen = multi
6df0: 70 6c 65 78 53 75 62 4f 70 65 6e 28 70 47 72 6f  plexSubOpen(pGro
6e00: 75 70 2c 20 69 2c 20 26 72 63 2c 20 4e 55 4c 4c  up, i, &rc, NULL
6e10: 2c 20 31 29 3b 0a 20 20 20 20 20 20 69 66 28 20  , 1);.      if( 
6e20: 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20  pSubOpen ){.    
6e30: 20 20 20 20 69 6e 74 20 65 78 74 72 61 20 3d 20      int extra = 
6e40: 28 28 69 6e 74 29 28 69 4f 66 73 74 20 25 20 70  ((int)(iOfst % p
6e50: 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 29 20  Group->szChunk) 
6e60: 2b 20 69 41 6d 74 29 20 2d 0a 20 20 20 20 20 20  + iAmt) -.      
6e70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 70 47                pG
6e80: 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 3b 0a 20  roup->szChunk;. 
6e90: 20 20 20 20 20 20 20 69 66 28 20 65 78 74 72 61         if( extra
6ea0: 3c 30 20 29 20 65 78 74 72 61 20 3d 20 30 3b 0a  <0 ) extra = 0;.
6eb0: 20 20 20 20 20 20 20 20 69 41 6d 74 20 2d 3d 20          iAmt -= 
6ec0: 65 78 74 72 61 3b 0a 20 20 20 20 20 20 20 20 72  extra;.        r
6ed0: 63 20 3d 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d  c = pSubOpen->pM
6ee0: 65 74 68 6f 64 73 2d 3e 78 57 72 69 74 65 28 70  ethods->xWrite(p
6ef0: 53 75 62 4f 70 65 6e 2c 20 70 42 75 66 2c 20 69  SubOpen, pBuf, i
6f00: 41 6d 74 2c 0a 20 20 20 20 20 20 20 20 20 20 20  Amt,.           
6f10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6f20: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 4f 66               iOf
6f30: 73 74 20 25 20 70 47 72 6f 75 70 2d 3e 73 7a 43  st % pGroup->szC
6f40: 68 75 6e 6b 29 3b 0a 20 20 20 20 20 20 20 20 70  hunk);.        p
6f50: 42 75 66 20 3d 20 28 63 68 61 72 20 2a 29 70 42  Buf = (char *)pB
6f60: 75 66 20 2b 20 69 41 6d 74 3b 0a 20 20 20 20 20  uf + iAmt;.     
6f70: 20 20 20 69 4f 66 73 74 20 2b 3d 20 69 41 6d 74     iOfst += iAmt
6f80: 3b 0a 20 20 20 20 20 20 20 20 69 41 6d 74 20 3d  ;.        iAmt =
6f90: 20 65 78 74 72 61 3b 0a 20 20 20 20 20 20 7d 0a   extra;.      }.
6fa0: 20 20 20 20 7d 0a 20 20 7d 0a 20 20 6d 75 6c 74      }.  }.  mult
6fb0: 69 70 6c 65 78 4c 65 61 76 65 28 29 3b 0a 20 20  iplexLeave();.  
6fc0: 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a  return rc;.}../*
6fd0: 20 50 61 73 73 20 78 54 72 75 6e 63 61 74 65 20   Pass xTruncate 
6fe0: 72 65 71 75 65 73 74 73 20 74 68 72 75 20 74 6f  requests thru to
6ff0: 20 74 68 65 20 6f 72 69 67 69 6e 61 6c 20 56 46   the original VF
7000: 53 20 61 66 74 65 72 0a 2a 2a 20 64 65 74 65 72  S after.** deter
7010: 6d 69 6e 69 6e 67 20 74 68 65 20 63 6f 72 72 65  mining the corre
7020: 63 74 20 63 68 75 6e 6b 20 74 6f 20 6f 70 65 72  ct chunk to oper
7030: 61 74 65 20 6f 6e 2e 20 20 44 65 6c 65 74 65 20  ate on.  Delete 
7040: 61 6e 79 0a 2a 2a 20 63 68 75 6e 6b 73 20 61 62  any.** chunks ab
7050: 6f 76 65 20 74 68 65 20 74 72 75 6e 63 61 74 65  ove the truncate
7060: 20 6d 61 72 6b 2e 0a 2a 2f 0a 73 74 61 74 69 63   mark..*/.static
7070: 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 54 72   int multiplexTr
7080: 75 6e 63 61 74 65 28 73 71 6c 69 74 65 33 5f 66  uncate(sqlite3_f
7090: 69 6c 65 20 2a 70 43 6f 6e 6e 2c 20 73 71 6c 69  ile *pConn, sqli
70a0: 74 65 33 5f 69 6e 74 36 34 20 73 69 7a 65 29 7b  te3_int64 size){
70b0: 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e  .  multiplexConn
70c0: 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78   *p = (multiplex
70d0: 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 6d  Conn*)pConn;.  m
70e0: 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 2a 70  ultiplexGroup *p
70f0: 47 72 6f 75 70 20 3d 20 70 2d 3e 70 47 72 6f 75  Group = p->pGrou
7100: 70 3b 0a 20 20 69 6e 74 20 72 63 20 3d 20 53 51  p;.  int rc = SQ
7110: 4c 49 54 45 5f 4f 4b 3b 0a 20 20 6d 75 6c 74 69  LITE_OK;.  multi
7120: 70 6c 65 78 45 6e 74 65 72 28 29 3b 0a 20 20 69  plexEnter();.  i
7130: 66 28 20 21 70 47 72 6f 75 70 2d 3e 62 45 6e 61  f( !pGroup->bEna
7140: 62 6c 65 64 20 29 7b 0a 20 20 20 20 73 71 6c 69  bled ){.    sqli
7150: 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70  te3_file *pSubOp
7160: 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75  en = multiplexSu
7170: 62 4f 70 65 6e 28 70 47 72 6f 75 70 2c 20 30 2c  bOpen(pGroup, 0,
7180: 20 26 72 63 2c 20 4e 55 4c 4c 2c 20 30 29 3b 0a   &rc, NULL, 0);.
7190: 20 20 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e      if( pSubOpen
71a0: 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 72 63 20  ==0 ){.      rc 
71b0: 3d 20 53 51 4c 49 54 45 5f 49 4f 45 52 52 5f 54  = SQLITE_IOERR_T
71c0: 52 55 4e 43 41 54 45 3b 0a 20 20 20 20 7d 65 6c  RUNCATE;.    }el
71d0: 73 65 7b 0a 20 20 20 20 20 20 72 63 20 3d 20 70  se{.      rc = p
71e0: 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64  SubOpen->pMethod
71f0: 73 2d 3e 78 54 72 75 6e 63 61 74 65 28 70 53 75  s->xTruncate(pSu
7200: 62 4f 70 65 6e 2c 20 73 69 7a 65 29 3b 0a 20 20  bOpen, size);.  
7210: 20 20 7d 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20    }.  }else{.   
7220: 20 69 6e 74 20 69 3b 0a 20 20 20 20 69 6e 74 20   int i;.    int 
7230: 69 42 61 73 65 47 72 6f 75 70 20 3d 20 28 69 6e  iBaseGroup = (in
7240: 74 29 28 73 69 7a 65 20 2f 20 70 47 72 6f 75 70  t)(size / pGroup
7250: 2d 3e 73 7a 43 68 75 6e 6b 29 3b 0a 20 20 20 20  ->szChunk);.    
7260: 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53  sqlite3_file *pS
7270: 75 62 4f 70 65 6e 3b 0a 20 20 20 20 73 71 6c 69  ubOpen;.    sqli
7280: 74 65 33 5f 76 66 73 20 2a 70 4f 72 69 67 56 66  te3_vfs *pOrigVf
7290: 73 20 3d 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70  s = gMultiplex.p
72a0: 4f 72 69 67 56 66 73 3b 20 20 20 2f 2a 20 52 65  OrigVfs;   /* Re
72b0: 61 6c 20 56 46 53 20 2a 2f 0a 20 20 20 20 2f 2a  al VFS */.    /*
72c0: 20 64 65 6c 65 74 65 20 74 68 65 20 63 68 75 6e   delete the chun
72d0: 6b 73 20 61 62 6f 76 65 20 74 68 65 20 74 72 75  ks above the tru
72e0: 6e 63 61 74 65 20 6c 69 6d 69 74 20 2a 2f 0a 20  ncate limit */. 
72f0: 20 20 20 66 6f 72 28 69 20 3d 20 70 47 72 6f 75     for(i = pGrou
7300: 70 2d 3e 6e 52 65 61 6c 2d 31 3b 20 69 3e 69 42  p->nReal-1; i>iB
7310: 61 73 65 47 72 6f 75 70 20 26 26 20 72 63 3d 3d  aseGroup && rc==
7320: 53 51 4c 49 54 45 5f 4f 4b 3b 20 69 2d 2d 29 7b  SQLITE_OK; i--){
7330: 0a 20 20 20 20 20 20 69 66 28 20 70 47 72 6f 75  .      if( pGrou
7340: 70 2d 3e 62 54 72 75 6e 63 61 74 65 20 29 7b 0a  p->bTruncate ){.
7350: 20 20 20 20 20 20 20 20 6d 75 6c 74 69 70 6c 65          multiple
7360: 78 53 75 62 43 6c 6f 73 65 28 70 47 72 6f 75 70  xSubClose(pGroup
7370: 2c 20 69 2c 20 70 4f 72 69 67 56 66 73 29 3b 0a  , i, pOrigVfs);.
7380: 20 20 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20        }else{.   
7390: 20 20 20 20 20 70 53 75 62 4f 70 65 6e 20 3d 20       pSubOpen = 
73a0: 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e  multiplexSubOpen
73b0: 28 70 47 72 6f 75 70 2c 20 69 2c 20 26 72 63 2c  (pGroup, i, &rc,
73c0: 20 30 2c 20 30 29 3b 0a 20 20 20 20 20 20 20 20   0, 0);.        
73d0: 69 66 28 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a  if( pSubOpen ){.
73e0: 20 20 20 20 20 20 20 20 20 20 72 63 20 3d 20 70            rc = p
73f0: 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64  SubOpen->pMethod
7400: 73 2d 3e 78 54 72 75 6e 63 61 74 65 28 70 53 75  s->xTruncate(pSu
7410: 62 4f 70 65 6e 2c 20 30 29 3b 0a 20 20 20 20 20  bOpen, 0);.     
7420: 20 20 20 7d 0a 20 20 20 20 20 20 7d 0a 20 20 20     }.      }.   
7430: 20 7d 0a 20 20 20 20 69 66 28 20 72 63 3d 3d 53   }.    if( rc==S
7440: 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20  QLITE_OK ){.    
7450: 20 20 70 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c    pSubOpen = mul
7460: 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28 70 47  tiplexSubOpen(pG
7470: 72 6f 75 70 2c 20 69 42 61 73 65 47 72 6f 75 70  roup, iBaseGroup
7480: 2c 20 26 72 63 2c 20 30 2c 20 30 29 3b 0a 20 20  , &rc, 0, 0);.  
7490: 20 20 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e      if( pSubOpen
74a0: 20 29 7b 0a 20 20 20 20 20 20 20 20 72 63 20 3d   ){.        rc =
74b0: 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68   pSubOpen->pMeth
74c0: 6f 64 73 2d 3e 78 54 72 75 6e 63 61 74 65 28 70  ods->xTruncate(p
74d0: 53 75 62 4f 70 65 6e 2c 20 73 69 7a 65 20 25 20  SubOpen, size % 
74e0: 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 29  pGroup->szChunk)
74f0: 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a  ;.      }.    }.
7500: 20 20 20 20 69 66 28 20 72 63 20 29 20 72 63 20      if( rc ) rc 
7510: 3d 20 53 51 4c 49 54 45 5f 49 4f 45 52 52 5f 54  = SQLITE_IOERR_T
7520: 52 55 4e 43 41 54 45 3b 0a 20 20 7d 0a 20 20 6d  RUNCATE;.  }.  m
7530: 75 6c 74 69 70 6c 65 78 4c 65 61 76 65 28 29 3b  ultiplexLeave();
7540: 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a  .  return rc;.}.
7550: 0a 2f 2a 20 50 61 73 73 20 78 53 79 6e 63 20 72  ./* Pass xSync r
7560: 65 71 75 65 73 74 73 20 74 68 72 6f 75 67 68 20  equests through 
7570: 74 6f 20 74 68 65 20 6f 72 69 67 69 6e 61 6c 20  to the original 
7580: 56 46 53 20 77 69 74 68 6f 75 74 20 63 68 61 6e  VFS without chan
7590: 67 65 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74  ge.*/.static int
75a0: 20 6d 75 6c 74 69 70 6c 65 78 53 79 6e 63 28 73   multiplexSync(s
75b0: 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f  qlite3_file *pCo
75c0: 6e 6e 2c 20 69 6e 74 20 66 6c 61 67 73 29 7b 0a  nn, int flags){.
75d0: 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20    multiplexConn 
75e0: 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43  *p = (multiplexC
75f0: 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 6d 75  onn*)pConn;.  mu
7600: 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 2a 70 47  ltiplexGroup *pG
7610: 72 6f 75 70 20 3d 20 70 2d 3e 70 47 72 6f 75 70  roup = p->pGroup
7620: 3b 0a 20 20 69 6e 74 20 72 63 20 3d 20 53 51 4c  ;.  int rc = SQL
7630: 49 54 45 5f 4f 4b 3b 0a 20 20 69 6e 74 20 69 3b  ITE_OK;.  int i;
7640: 0a 20 20 6d 75 6c 74 69 70 6c 65 78 45 6e 74 65  .  multiplexEnte
7650: 72 28 29 3b 0a 20 20 66 6f 72 28 69 3d 30 3b 20  r();.  for(i=0; 
7660: 69 3c 70 47 72 6f 75 70 2d 3e 6e 52 65 61 6c 3b  i<pGroup->nReal;
7670: 20 69 2b 2b 29 7b 0a 20 20 20 20 73 71 6c 69 74   i++){.    sqlit
7680: 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70 65  e3_file *pSubOpe
7690: 6e 20 3d 20 70 47 72 6f 75 70 2d 3e 61 52 65 61  n = pGroup->aRea
76a0: 6c 5b 69 5d 2e 70 3b 0a 20 20 20 20 69 66 28 20  l[i].p;.    if( 
76b0: 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20  pSubOpen ){.    
76c0: 20 20 69 6e 74 20 72 63 32 20 3d 20 70 53 75 62    int rc2 = pSub
76d0: 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e  Open->pMethods->
76e0: 78 53 79 6e 63 28 70 53 75 62 4f 70 65 6e 2c 20  xSync(pSubOpen, 
76f0: 66 6c 61 67 73 29 3b 0a 20 20 20 20 20 20 69 66  flags);.      if
7700: 28 20 72 63 32 21 3d 53 51 4c 49 54 45 5f 4f 4b  ( rc2!=SQLITE_OK
7710: 20 29 20 72 63 20 3d 20 72 63 32 3b 0a 20 20 20   ) rc = rc2;.   
7720: 20 7d 0a 20 20 7d 0a 20 20 6d 75 6c 74 69 70 6c   }.  }.  multipl
7730: 65 78 4c 65 61 76 65 28 29 3b 0a 20 20 72 65 74  exLeave();.  ret
7740: 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 20 50 61  urn rc;.}../* Pa
7750: 73 73 20 78 46 69 6c 65 53 69 7a 65 20 72 65 71  ss xFileSize req
7760: 75 65 73 74 73 20 74 68 72 6f 75 67 68 20 74 6f  uests through to
7770: 20 74 68 65 20 6f 72 69 67 69 6e 61 6c 20 56 46   the original VF
7780: 53 2e 0a 2a 2a 20 41 67 67 72 65 67 61 74 65 20  S..** Aggregate 
7790: 74 68 65 20 73 69 7a 65 20 6f 66 20 61 6c 6c 20  the size of all 
77a0: 74 68 65 20 63 68 75 6e 6b 73 20 62 65 66 6f 72  the chunks befor
77b0: 65 20 72 65 74 75 72 6e 69 6e 67 2e 0a 2a 2f 0a  e returning..*/.
77c0: 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69  static int multi
77d0: 70 6c 65 78 46 69 6c 65 53 69 7a 65 28 73 71 6c  plexFileSize(sql
77e0: 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e  ite3_file *pConn
77f0: 2c 20 73 71 6c 69 74 65 33 5f 69 6e 74 36 34 20  , sqlite3_int64 
7800: 2a 70 53 69 7a 65 29 7b 0a 20 20 6d 75 6c 74 69  *pSize){.  multi
7810: 70 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d  plexConn *p = (m
7820: 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43  ultiplexConn*)pC
7830: 6f 6e 6e 3b 0a 20 20 6d 75 6c 74 69 70 6c 65 78  onn;.  multiplex
7840: 47 72 6f 75 70 20 2a 70 47 72 6f 75 70 20 3d 20  Group *pGroup = 
7850: 70 2d 3e 70 47 72 6f 75 70 3b 0a 20 20 69 6e 74  p->pGroup;.  int
7860: 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b   rc = SQLITE_OK;
7870: 0a 20 20 69 6e 74 20 69 3b 0a 20 20 6d 75 6c 74  .  int i;.  mult
7880: 69 70 6c 65 78 45 6e 74 65 72 28 29 3b 0a 20 20  iplexEnter();.  
7890: 69 66 28 20 21 70 47 72 6f 75 70 2d 3e 62 45 6e  if( !pGroup->bEn
78a0: 61 62 6c 65 64 20 29 7b 0a 20 20 20 20 73 71 6c  abled ){.    sql
78b0: 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f  ite3_file *pSubO
78c0: 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53  pen = multiplexS
78d0: 75 62 4f 70 65 6e 28 70 47 72 6f 75 70 2c 20 30  ubOpen(pGroup, 0
78e0: 2c 20 26 72 63 2c 20 4e 55 4c 4c 2c 20 30 29 3b  , &rc, NULL, 0);
78f0: 0a 20 20 20 20 69 66 28 20 70 53 75 62 4f 70 65  .    if( pSubOpe
7900: 6e 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 72 63  n==0 ){.      rc
7910: 20 3d 20 53 51 4c 49 54 45 5f 49 4f 45 52 52 5f   = SQLITE_IOERR_
7920: 46 53 54 41 54 3b 0a 20 20 20 20 7d 65 6c 73 65  FSTAT;.    }else
7930: 7b 0a 20 20 20 20 20 20 72 63 20 3d 20 70 53 75  {.      rc = pSu
7940: 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d  bOpen->pMethods-
7950: 3e 78 46 69 6c 65 53 69 7a 65 28 70 53 75 62 4f  >xFileSize(pSubO
7960: 70 65 6e 2c 20 70 53 69 7a 65 29 3b 0a 20 20 20  pen, pSize);.   
7970: 20 7d 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20   }.  }else{.    
7980: 2a 70 53 69 7a 65 20 3d 20 30 3b 0a 20 20 20 20  *pSize = 0;.    
7990: 66 6f 72 28 69 3d 30 3b 20 72 63 3d 3d 53 51 4c  for(i=0; rc==SQL
79a0: 49 54 45 5f 4f 4b 3b 20 69 2b 2b 29 7b 0a 20 20  ITE_OK; i++){.  
79b0: 20 20 20 20 73 71 6c 69 74 65 33 5f 69 6e 74 36      sqlite3_int6
79c0: 34 20 73 7a 20 3d 20 6d 75 6c 74 69 70 6c 65 78  4 sz = multiplex
79d0: 53 75 62 53 69 7a 65 28 70 47 72 6f 75 70 2c 20  SubSize(pGroup, 
79e0: 69 2c 20 26 72 63 29 3b 0a 20 20 20 20 20 20 69  i, &rc);.      i
79f0: 66 28 20 73 7a 3d 3d 30 20 29 20 62 72 65 61 6b  f( sz==0 ) break
7a00: 3b 0a 20 20 20 20 20 20 2a 70 53 69 7a 65 20 3d  ;.      *pSize =
7a10: 20 69 2a 28 73 71 6c 69 74 65 33 5f 69 6e 74 36   i*(sqlite3_int6
7a20: 34 29 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e  4)pGroup->szChun
7a30: 6b 20 2b 20 73 7a 3b 0a 20 20 20 20 7d 0a 20 20  k + sz;.    }.  
7a40: 7d 0a 20 20 6d 75 6c 74 69 70 6c 65 78 4c 65 61  }.  multiplexLea
7a50: 76 65 28 29 3b 0a 20 20 72 65 74 75 72 6e 20 72  ve();.  return r
7a60: 63 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 4c  c;.}../* Pass xL
7a70: 6f 63 6b 20 72 65 71 75 65 73 74 73 20 74 68 72  ock requests thr
7a80: 6f 75 67 68 20 74 6f 20 74 68 65 20 6f 72 69 67  ough to the orig
7a90: 69 6e 61 6c 20 56 46 53 20 75 6e 63 68 61 6e 67  inal VFS unchang
7aa0: 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e  ed..*/.static in
7ab0: 74 20 6d 75 6c 74 69 70 6c 65 78 4c 6f 63 6b 28  t multiplexLock(
7ac0: 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 43  sqlite3_file *pC
7ad0: 6f 6e 6e 2c 20 69 6e 74 20 6c 6f 63 6b 29 7b 0a  onn, int lock){.
7ae0: 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20    multiplexConn 
7af0: 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43  *p = (multiplexC
7b00: 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 69 6e  onn*)pConn;.  in
7b10: 74 20 72 63 3b 0a 20 20 73 71 6c 69 74 65 33 5f  t rc;.  sqlite3_
7b20: 66 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d  file *pSubOpen =
7b30: 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65   multiplexSubOpe
7b40: 6e 28 70 2d 3e 70 47 72 6f 75 70 2c 20 30 2c 20  n(p->pGroup, 0, 
7b50: 26 72 63 2c 20 4e 55 4c 4c 2c 20 30 29 3b 0a 20  &rc, NULL, 0);. 
7b60: 20 69 66 28 20 70 53 75 62 4f 70 65 6e 20 29 7b   if( pSubOpen ){
7b70: 0a 20 20 20 20 72 65 74 75 72 6e 20 70 53 75 62  .    return pSub
7b80: 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e  Open->pMethods->
7b90: 78 4c 6f 63 6b 28 70 53 75 62 4f 70 65 6e 2c 20  xLock(pSubOpen, 
7ba0: 6c 6f 63 6b 29 3b 0a 20 20 7d 0a 20 20 72 65 74  lock);.  }.  ret
7bb0: 75 72 6e 20 53 51 4c 49 54 45 5f 42 55 53 59 3b  urn SQLITE_BUSY;
7bc0: 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 55 6e 6c  .}../* Pass xUnl
7bd0: 6f 63 6b 20 72 65 71 75 65 73 74 73 20 74 68 72  ock requests thr
7be0: 6f 75 67 68 20 74 6f 20 74 68 65 20 6f 72 69 67  ough to the orig
7bf0: 69 6e 61 6c 20 56 46 53 20 75 6e 63 68 61 6e 67  inal VFS unchang
7c00: 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e  ed..*/.static in
7c10: 74 20 6d 75 6c 74 69 70 6c 65 78 55 6e 6c 6f 63  t multiplexUnloc
7c20: 6b 28 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a  k(sqlite3_file *
7c30: 70 43 6f 6e 6e 2c 20 69 6e 74 20 6c 6f 63 6b 29  pConn, int lock)
7c40: 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e  {.  multiplexCon
7c50: 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65  n *p = (multiple
7c60: 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20  xConn*)pConn;.  
7c70: 69 6e 74 20 72 63 3b 0a 20 20 73 71 6c 69 74 65  int rc;.  sqlite
7c80: 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e  3_file *pSubOpen
7c90: 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f   = multiplexSubO
7ca0: 70 65 6e 28 70 2d 3e 70 47 72 6f 75 70 2c 20 30  pen(p->pGroup, 0
7cb0: 2c 20 26 72 63 2c 20 4e 55 4c 4c 2c 20 30 29 3b  , &rc, NULL, 0);
7cc0: 0a 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e 20  .  if( pSubOpen 
7cd0: 29 7b 0a 20 20 20 20 72 65 74 75 72 6e 20 70 53  ){.    return pS
7ce0: 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73  ubOpen->pMethods
7cf0: 2d 3e 78 55 6e 6c 6f 63 6b 28 70 53 75 62 4f 70  ->xUnlock(pSubOp
7d00: 65 6e 2c 20 6c 6f 63 6b 29 3b 0a 20 20 7d 0a 20  en, lock);.  }. 
7d10: 20 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 49   return SQLITE_I
7d20: 4f 45 52 52 5f 55 4e 4c 4f 43 4b 3b 0a 7d 0a 0a  OERR_UNLOCK;.}..
7d30: 2f 2a 20 50 61 73 73 20 78 43 68 65 63 6b 52 65  /* Pass xCheckRe
7d40: 73 65 72 76 65 64 4c 6f 63 6b 20 72 65 71 75 65  servedLock reque
7d50: 73 74 73 20 74 68 72 6f 75 67 68 20 74 6f 20 74  sts through to t
7d60: 68 65 20 6f 72 69 67 69 6e 61 6c 20 56 46 53 20  he original VFS 
7d70: 75 6e 63 68 61 6e 67 65 64 2e 0a 2a 2f 0a 73 74  unchanged..*/.st
7d80: 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c  atic int multipl
7d90: 65 78 43 68 65 63 6b 52 65 73 65 72 76 65 64 4c  exCheckReservedL
7da0: 6f 63 6b 28 73 71 6c 69 74 65 33 5f 66 69 6c 65  ock(sqlite3_file
7db0: 20 2a 70 43 6f 6e 6e 2c 20 69 6e 74 20 2a 70 52   *pConn, int *pR
7dc0: 65 73 4f 75 74 29 7b 0a 20 20 6d 75 6c 74 69 70  esOut){.  multip
7dd0: 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75  lexConn *p = (mu
7de0: 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f  ltiplexConn*)pCo
7df0: 6e 6e 3b 0a 20 20 69 6e 74 20 72 63 3b 0a 20 20  nn;.  int rc;.  
7e00: 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53  sqlite3_file *pS
7e10: 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c  ubOpen = multipl
7e20: 65 78 53 75 62 4f 70 65 6e 28 70 2d 3e 70 47 72  exSubOpen(p->pGr
7e30: 6f 75 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c  oup, 0, &rc, NUL
7e40: 4c 2c 20 30 29 3b 0a 20 20 69 66 28 20 70 53 75  L, 0);.  if( pSu
7e50: 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20 72 65 74  bOpen ){.    ret
7e60: 75 72 6e 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d  urn pSubOpen->pM
7e70: 65 74 68 6f 64 73 2d 3e 78 43 68 65 63 6b 52 65  ethods->xCheckRe
7e80: 73 65 72 76 65 64 4c 6f 63 6b 28 70 53 75 62 4f  servedLock(pSubO
7e90: 70 65 6e 2c 20 70 52 65 73 4f 75 74 29 3b 0a 20  pen, pResOut);. 
7ea0: 20 7d 0a 20 20 72 65 74 75 72 6e 20 53 51 4c 49   }.  return SQLI
7eb0: 54 45 5f 49 4f 45 52 52 5f 43 48 45 43 4b 52 45  TE_IOERR_CHECKRE
7ec0: 53 45 52 56 45 44 4c 4f 43 4b 3b 0a 7d 0a 0a 2f  SERVEDLOCK;.}../
7ed0: 2a 20 50 61 73 73 20 78 46 69 6c 65 43 6f 6e 74  * Pass xFileCont
7ee0: 72 6f 6c 20 72 65 71 75 65 73 74 73 20 74 68 72  rol requests thr
7ef0: 6f 75 67 68 20 74 6f 20 74 68 65 20 6f 72 69 67  ough to the orig
7f00: 69 6e 61 6c 20 56 46 53 20 75 6e 63 68 61 6e 67  inal VFS unchang
7f10: 65 64 2c 0a 2a 2a 20 65 78 63 65 70 74 20 66 6f  ed,.** except fo
7f20: 72 20 61 6e 79 20 4d 55 4c 54 49 50 4c 45 58 5f  r any MULTIPLEX_
7f30: 43 54 52 4c 5f 2a 20 72 65 71 75 65 73 74 73 20  CTRL_* requests 
7f40: 68 65 72 65 2e 0a 2a 2f 0a 73 74 61 74 69 63 20  here..*/.static 
7f50: 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 46 69 6c  int multiplexFil
7f60: 65 43 6f 6e 74 72 6f 6c 28 73 71 6c 69 74 65 33  eControl(sqlite3
7f70: 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c 20 69 6e  _file *pConn, in
7f80: 74 20 6f 70 2c 20 76 6f 69 64 20 2a 70 41 72 67  t op, void *pArg
7f90: 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f  ){.  multiplexCo
7fa0: 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c  nn *p = (multipl
7fb0: 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20  exConn*)pConn;. 
7fc0: 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 20   multiplexGroup 
7fd0: 2a 70 47 72 6f 75 70 20 3d 20 70 2d 3e 70 47 72  *pGroup = p->pGr
7fe0: 6f 75 70 3b 0a 20 20 69 6e 74 20 72 63 20 3d 20  oup;.  int rc = 
7ff0: 53 51 4c 49 54 45 5f 45 52 52 4f 52 3b 0a 20 20  SQLITE_ERROR;.  
8000: 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53  sqlite3_file *pS
8010: 75 62 4f 70 65 6e 3b 0a 0a 20 20 69 66 28 20 21  ubOpen;..  if( !
8020: 67 4d 75 6c 74 69 70 6c 65 78 2e 69 73 49 6e 69  gMultiplex.isIni
8030: 74 69 61 6c 69 7a 65 64 20 29 20 72 65 74 75 72  tialized ) retur
8040: 6e 20 53 51 4c 49 54 45 5f 4d 49 53 55 53 45 3b  n SQLITE_MISUSE;
8050: 0a 20 20 73 77 69 74 63 68 28 20 6f 70 20 29 7b  .  switch( op ){
8060: 0a 20 20 20 20 63 61 73 65 20 4d 55 4c 54 49 50  .    case MULTIP
8070: 4c 45 58 5f 43 54 52 4c 5f 45 4e 41 42 4c 45 3a  LEX_CTRL_ENABLE:
8080: 0a 20 20 20 20 20 20 69 66 28 20 70 41 72 67 20  .      if( pArg 
8090: 29 20 7b 0a 20 20 20 20 20 20 20 20 69 6e 74 20  ) {.        int 
80a0: 62 45 6e 61 62 6c 65 64 20 3d 20 2a 28 69 6e 74  bEnabled = *(int
80b0: 20 2a 29 70 41 72 67 3b 0a 20 20 20 20 20 20 20   *)pArg;.       
80c0: 20 70 47 72 6f 75 70 2d 3e 62 45 6e 61 62 6c 65   pGroup->bEnable
80d0: 64 20 3d 20 62 45 6e 61 62 6c 65 64 3b 0a 20 20  d = bEnabled;.  
80e0: 20 20 20 20 20 20 72 63 20 3d 20 53 51 4c 49 54        rc = SQLIT
80f0: 45 5f 4f 4b 3b 0a 20 20 20 20 20 20 7d 0a 20 20  E_OK;.      }.  
8100: 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 63      break;.    c
8110: 61 73 65 20 4d 55 4c 54 49 50 4c 45 58 5f 43 54  ase MULTIPLEX_CT
8120: 52 4c 5f 53 45 54 5f 43 48 55 4e 4b 5f 53 49 5a  RL_SET_CHUNK_SIZ
8130: 45 3a 0a 20 20 20 20 20 20 69 66 28 20 70 41 72  E:.      if( pAr
8140: 67 20 29 20 7b 0a 20 20 20 20 20 20 20 20 75 6e  g ) {.        un
8150: 73 69 67 6e 65 64 20 69 6e 74 20 73 7a 43 68 75  signed int szChu
8160: 6e 6b 20 3d 20 2a 28 75 6e 73 69 67 6e 65 64 2a  nk = *(unsigned*
8170: 29 70 41 72 67 3b 0a 20 20 20 20 20 20 20 20 69  )pArg;.        i
8180: 66 28 20 73 7a 43 68 75 6e 6b 3c 31 20 29 7b 0a  f( szChunk<1 ){.
8190: 20 20 20 20 20 20 20 20 20 20 72 63 20 3d 20 53            rc = S
81a0: 51 4c 49 54 45 5f 4d 49 53 55 53 45 3b 0a 20 20  QLITE_MISUSE;.  
81b0: 20 20 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20        }else{.   
81c0: 20 20 20 20 20 20 20 2f 2a 20 52 6f 75 6e 64 20         /* Round 
81d0: 75 70 20 74 6f 20 6e 65 61 72 65 73 74 20 6d 75  up to nearest mu
81e0: 6c 74 69 70 6c 65 20 6f 66 20 4d 41 58 5f 50 41  ltiple of MAX_PA
81f0: 47 45 5f 53 49 5a 45 2e 20 2a 2f 0a 20 20 20 20  GE_SIZE. */.    
8200: 20 20 20 20 20 20 73 7a 43 68 75 6e 6b 20 3d 20        szChunk = 
8210: 28 73 7a 43 68 75 6e 6b 20 2b 20 28 4d 41 58 5f  (szChunk + (MAX_
8220: 50 41 47 45 5f 53 49 5a 45 2d 31 29 29 3b 0a 20  PAGE_SIZE-1));. 
8230: 20 20 20 20 20 20 20 20 20 73 7a 43 68 75 6e 6b           szChunk
8240: 20 26 3d 20 7e 28 4d 41 58 5f 50 41 47 45 5f 53   &= ~(MAX_PAGE_S
8250: 49 5a 45 2d 31 29 3b 0a 20 20 20 20 20 20 20 20  IZE-1);.        
8260: 20 20 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e    pGroup->szChun
8270: 6b 20 3d 20 73 7a 43 68 75 6e 6b 3b 0a 20 20 20  k = szChunk;.   
8280: 20 20 20 20 20 20 20 72 63 20 3d 20 53 51 4c 49         rc = SQLI
8290: 54 45 5f 4f 4b 3b 0a 20 20 20 20 20 20 20 20 7d  TE_OK;.        }
82a0: 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 62  .      }.      b
82b0: 72 65 61 6b 3b 0a 20 20 20 20 63 61 73 65 20 4d  reak;.    case M
82c0: 55 4c 54 49 50 4c 45 58 5f 43 54 52 4c 5f 53 45  ULTIPLEX_CTRL_SE
82d0: 54 5f 4d 41 58 5f 43 48 55 4e 4b 53 3a 0a 20 20  T_MAX_CHUNKS:.  
82e0: 20 20 20 20 72 63 20 3d 20 53 51 4c 49 54 45 5f      rc = SQLITE_
82f0: 4f 4b 3b 0a 20 20 20 20 20 20 62 72 65 61 6b 3b  OK;.      break;
8300: 0a 20 20 20 20 63 61 73 65 20 53 51 4c 49 54 45  .    case SQLITE
8310: 5f 46 43 4e 54 4c 5f 53 49 5a 45 5f 48 49 4e 54  _FCNTL_SIZE_HINT
8320: 3a 0a 20 20 20 20 63 61 73 65 20 53 51 4c 49 54  :.    case SQLIT
8330: 45 5f 46 43 4e 54 4c 5f 43 48 55 4e 4b 5f 53 49  E_FCNTL_CHUNK_SI
8340: 5a 45 3a 0a 20 20 20 20 20 20 2f 2a 20 6e 6f 2d  ZE:.      /* no-
8350: 6f 70 20 74 68 65 73 65 20 2a 2f 0a 20 20 20 20  op these */.    
8360: 20 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b    rc = SQLITE_OK
8370: 3b 0a 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20  ;.      break;. 
8380: 20 20 20 64 65 66 61 75 6c 74 3a 0a 20 20 20 20     default:.    
8390: 20 20 70 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c    pSubOpen = mul
83a0: 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28 70 47  tiplexSubOpen(pG
83b0: 72 6f 75 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55  roup, 0, &rc, NU
83c0: 4c 4c 2c 20 30 29 3b 0a 20 20 20 20 20 20 69 66  LL, 0);.      if
83d0: 28 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20  ( pSubOpen ){.  
83e0: 20 20 20 20 20 20 72 63 20 3d 20 70 53 75 62 4f        rc = pSubO
83f0: 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e 78  pen->pMethods->x
8400: 46 69 6c 65 43 6f 6e 74 72 6f 6c 28 70 53 75 62  FileControl(pSub
8410: 4f 70 65 6e 2c 20 6f 70 2c 20 70 41 72 67 29 3b  Open, op, pArg);
8420: 0a 20 20 20 20 20 20 20 20 69 66 28 20 6f 70 3d  .        if( op=
8430: 3d 53 51 4c 49 54 45 5f 46 43 4e 54 4c 5f 56 46  =SQLITE_FCNTL_VF
8440: 53 4e 41 4d 45 20 26 26 20 72 63 3d 3d 53 51 4c  SNAME && rc==SQL
8450: 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20  ITE_OK ){.      
8460: 20 20 20 2a 28 63 68 61 72 2a 2a 29 70 41 72 67     *(char**)pArg
8470: 20 3d 20 73 71 6c 69 74 65 33 5f 6d 70 72 69 6e   = sqlite3_mprin
8480: 74 66 28 22 6d 75 6c 74 69 70 6c 65 78 2f 25 7a  tf("multiplex/%z
8490: 22 2c 20 2a 28 63 68 61 72 2a 2a 29 70 41 72 67  ", *(char**)pArg
84a0: 29 3b 0a 20 20 20 20 20 20 20 20 7d 0a 20 20 20  );.        }.   
84b0: 20 20 20 7d 0a 20 20 20 20 20 20 62 72 65 61 6b     }.      break
84c0: 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20 72  ;.  }.  return r
84d0: 63 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 53  c;.}../* Pass xS
84e0: 65 63 74 6f 72 53 69 7a 65 20 72 65 71 75 65 73  ectorSize reques
84f0: 74 73 20 74 68 72 6f 75 67 68 20 74 6f 20 74 68  ts through to th
8500: 65 20 6f 72 69 67 69 6e 61 6c 20 56 46 53 20 75  e original VFS u
8510: 6e 63 68 61 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61  nchanged..*/.sta
8520: 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65  tic int multiple
8530: 78 53 65 63 74 6f 72 53 69 7a 65 28 73 71 6c 69  xSectorSize(sqli
8540: 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 29  te3_file *pConn)
8550: 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e  {.  multiplexCon
8560: 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65  n *p = (multiple
8570: 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20  xConn*)pConn;.  
8580: 69 6e 74 20 72 63 3b 0a 20 20 73 71 6c 69 74 65  int rc;.  sqlite
8590: 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e  3_file *pSubOpen
85a0: 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f   = multiplexSubO
85b0: 70 65 6e 28 70 2d 3e 70 47 72 6f 75 70 2c 20 30  pen(p->pGroup, 0
85c0: 2c 20 26 72 63 2c 20 4e 55 4c 4c 2c 20 30 29 3b  , &rc, NULL, 0);
85d0: 0a 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e 20  .  if( pSubOpen 
85e0: 26 26 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65  && pSubOpen->pMe
85f0: 74 68 6f 64 73 2d 3e 78 53 65 63 74 6f 72 53 69  thods->xSectorSi
8600: 7a 65 20 29 7b 0a 20 20 20 20 72 65 74 75 72 6e  ze ){.    return
8610: 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68   pSubOpen->pMeth
8620: 6f 64 73 2d 3e 78 53 65 63 74 6f 72 53 69 7a 65  ods->xSectorSize
8630: 28 70 53 75 62 4f 70 65 6e 29 3b 0a 20 20 7d 0a  (pSubOpen);.  }.
8640: 20 20 72 65 74 75 72 6e 20 44 45 46 41 55 4c 54    return DEFAULT
8650: 5f 53 45 43 54 4f 52 5f 53 49 5a 45 3b 0a 7d 0a  _SECTOR_SIZE;.}.
8660: 0a 2f 2a 20 50 61 73 73 20 78 44 65 76 69 63 65  ./* Pass xDevice
8670: 43 68 61 72 61 63 74 65 72 69 73 74 69 63 73 20  Characteristics 
8680: 72 65 71 75 65 73 74 73 20 74 68 72 6f 75 67 68  requests through
8690: 20 74 6f 20 74 68 65 20 6f 72 69 67 69 6e 61 6c   to the original
86a0: 20 56 46 53 20 75 6e 63 68 61 6e 67 65 64 2e 0a   VFS unchanged..
86b0: 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75  */.static int mu
86c0: 6c 74 69 70 6c 65 78 44 65 76 69 63 65 43 68 61  ltiplexDeviceCha
86d0: 72 61 63 74 65 72 69 73 74 69 63 73 28 73 71 6c  racteristics(sql
86e0: 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e  ite3_file *pConn
86f0: 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f  ){.  multiplexCo
8700: 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c  nn *p = (multipl
8710: 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20  exConn*)pConn;. 
8720: 20 69 6e 74 20 72 63 3b 0a 20 20 73 71 6c 69 74   int rc;.  sqlit
8730: 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70 65  e3_file *pSubOpe
8740: 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75 62  n = multiplexSub
8750: 4f 70 65 6e 28 70 2d 3e 70 47 72 6f 75 70 2c 20  Open(p->pGroup, 
8760: 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 2c 20 30 29  0, &rc, NULL, 0)
8770: 3b 0a 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e  ;.  if( pSubOpen
8780: 20 29 7b 0a 20 20 20 20 72 65 74 75 72 6e 20 70   ){.    return p
8790: 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64  SubOpen->pMethod
87a0: 73 2d 3e 78 44 65 76 69 63 65 43 68 61 72 61 63  s->xDeviceCharac
87b0: 74 65 72 69 73 74 69 63 73 28 70 53 75 62 4f 70  teristics(pSubOp
87c0: 65 6e 29 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72  en);.  }.  retur
87d0: 6e 20 30 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20  n 0;.}../* Pass 
87e0: 78 53 68 6d 4d 61 70 20 72 65 71 75 65 73 74 73  xShmMap requests
87f0: 20 74 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20   through to the 
8800: 6f 72 69 67 69 6e 61 6c 20 56 46 53 20 75 6e 63  original VFS unc
8810: 68 61 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61 74 69  hanged..*/.stati
8820: 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 53  c int multiplexS
8830: 68 6d 4d 61 70 28 0a 20 20 73 71 6c 69 74 65 33  hmMap(.  sqlite3
8840: 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c 20 20 20  _file *pConn,   
8850: 20 20 20 20 20 20 20 20 20 2f 2a 20 48 61 6e 64           /* Hand
8860: 6c 65 20 6f 70 65 6e 20 6f 6e 20 64 61 74 61 62  le open on datab
8870: 61 73 65 20 66 69 6c 65 20 2a 2f 0a 20 20 69 6e  ase file */.  in
8880: 74 20 69 52 65 67 69 6f 6e 2c 20 20 20 20 20 20  t iRegion,      
8890: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
88a0: 20 52 65 67 69 6f 6e 20 74 6f 20 72 65 74 72 69   Region to retri
88b0: 65 76 65 20 2a 2f 0a 20 20 69 6e 74 20 73 7a 52  eve */.  int szR
88c0: 65 67 69 6f 6e 2c 20 20 20 20 20 20 20 20 20 20  egion,          
88d0: 20 20 20 20 20 20 20 20 20 2f 2a 20 53 69 7a 65           /* Size
88e0: 20 6f 66 20 72 65 67 69 6f 6e 73 20 2a 2f 0a 20   of regions */. 
88f0: 20 69 6e 74 20 62 45 78 74 65 6e 64 2c 20 20 20   int bExtend,   
8900: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8910: 20 2f 2a 20 54 72 75 65 20 74 6f 20 65 78 74 65   /* True to exte
8920: 6e 64 20 66 69 6c 65 20 69 66 20 6e 65 63 65 73  nd file if neces
8930: 73 61 72 79 20 2a 2f 0a 20 20 76 6f 69 64 20 76  sary */.  void v
8940: 6f 6c 61 74 69 6c 65 20 2a 2a 70 70 20 20 20 20  olatile **pp    
8950: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4f 55 54            /* OUT
8960: 3a 20 4d 61 70 70 65 64 20 6d 65 6d 6f 72 79 20  : Mapped memory 
8970: 2a 2f 0a 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65  */.){.  multiple
8980: 78 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74  xConn *p = (mult
8990: 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e  iplexConn*)pConn
89a0: 3b 0a 20 20 69 6e 74 20 72 63 3b 0a 20 20 73 71  ;.  int rc;.  sq
89b0: 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62  lite3_file *pSub
89c0: 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78  Open = multiplex
89d0: 53 75 62 4f 70 65 6e 28 70 2d 3e 70 47 72 6f 75  SubOpen(p->pGrou
89e0: 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 2c  p, 0, &rc, NULL,
89f0: 20 30 29 3b 0a 20 20 69 66 28 20 70 53 75 62 4f   0);.  if( pSubO
8a00: 70 65 6e 20 29 7b 0a 20 20 20 20 72 65 74 75 72  pen ){.    retur
8a10: 6e 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74  n pSubOpen->pMet
8a20: 68 6f 64 73 2d 3e 78 53 68 6d 4d 61 70 28 70 53  hods->xShmMap(pS
8a30: 75 62 4f 70 65 6e 2c 20 69 52 65 67 69 6f 6e 2c  ubOpen, iRegion,
8a40: 20 73 7a 52 65 67 69 6f 6e 2c 20 62 45 78 74 65   szRegion, bExte
8a50: 6e 64 2c 70 70 29 3b 0a 20 20 7d 0a 20 20 72 65  nd,pp);.  }.  re
8a60: 74 75 72 6e 20 53 51 4c 49 54 45 5f 49 4f 45 52  turn SQLITE_IOER
8a70: 52 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 53  R;.}../* Pass xS
8a80: 68 6d 4c 6f 63 6b 20 72 65 71 75 65 73 74 73 20  hmLock requests 
8a90: 74 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20 6f  through to the o
8aa0: 72 69 67 69 6e 61 6c 20 56 46 53 20 75 6e 63 68  riginal VFS unch
8ab0: 61 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63  anged..*/.static
8ac0: 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 53 68   int multiplexSh
8ad0: 6d 4c 6f 63 6b 28 0a 20 20 73 71 6c 69 74 65 33  mLock(.  sqlite3
8ae0: 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c 20 20 20  _file *pConn,   
8af0: 20 20 20 20 2f 2a 20 44 61 74 61 62 61 73 65 20      /* Database 
8b00: 66 69 6c 65 20 68 6f 6c 64 69 6e 67 20 74 68 65  file holding the
8b10: 20 73 68 61 72 65 64 20 6d 65 6d 6f 72 79 20 2a   shared memory *
8b20: 2f 0a 20 20 69 6e 74 20 6f 66 73 74 2c 20 20 20  /.  int ofst,   
8b30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
8b40: 2a 20 46 69 72 73 74 20 6c 6f 63 6b 20 74 6f 20  * First lock to 
8b50: 61 63 71 75 69 72 65 20 6f 72 20 72 65 6c 65 61  acquire or relea
8b60: 73 65 20 2a 2f 0a 20 20 69 6e 74 20 6e 2c 20 20  se */.  int n,  
8b70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8b80: 20 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f 66 20     /* Number of 
8b90: 6c 6f 63 6b 73 20 74 6f 20 61 63 71 75 69 72 65  locks to acquire
8ba0: 20 6f 72 20 72 65 6c 65 61 73 65 20 2a 2f 0a 20   or release */. 
8bb0: 20 69 6e 74 20 66 6c 61 67 73 20 20 20 20 20 20   int flags      
8bc0: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 57              /* W
8bd0: 68 61 74 20 74 6f 20 64 6f 20 77 69 74 68 20 74  hat to do with t
8be0: 68 65 20 6c 6f 63 6b 20 2a 2f 0a 29 7b 0a 20 20  he lock */.){.  
8bf0: 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70  multiplexConn *p
8c00: 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e   = (multiplexCon
8c10: 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 69 6e 74 20  n*)pConn;.  int 
8c20: 72 63 3b 0a 20 20 73 71 6c 69 74 65 33 5f 66 69  rc;.  sqlite3_fi
8c30: 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20 6d  le *pSubOpen = m
8c40: 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28  ultiplexSubOpen(
8c50: 70 2d 3e 70 47 72 6f 75 70 2c 20 30 2c 20 26 72  p->pGroup, 0, &r
8c60: 63 2c 20 4e 55 4c 4c 2c 20 30 29 3b 0a 20 20 69  c, NULL, 0);.  i
8c70: 66 28 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20  f( pSubOpen ){. 
8c80: 20 20 20 72 65 74 75 72 6e 20 70 53 75 62 4f 70     return pSubOp
8c90: 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e 78 53  en->pMethods->xS
8ca0: 68 6d 4c 6f 63 6b 28 70 53 75 62 4f 70 65 6e 2c  hmLock(pSubOpen,
8cb0: 20 6f 66 73 74 2c 20 6e 2c 20 66 6c 61 67 73 29   ofst, n, flags)
8cc0: 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20 53  ;.  }.  return S
8cd0: 51 4c 49 54 45 5f 42 55 53 59 3b 0a 7d 0a 0a 2f  QLITE_BUSY;.}../
8ce0: 2a 20 50 61 73 73 20 78 53 68 6d 42 61 72 72 69  * Pass xShmBarri
8cf0: 65 72 20 72 65 71 75 65 73 74 73 20 74 68 72 6f  er requests thro
8d00: 75 67 68 20 74 6f 20 74 68 65 20 6f 72 69 67 69  ugh to the origi
8d10: 6e 61 6c 20 56 46 53 20 75 6e 63 68 61 6e 67 65  nal VFS unchange
8d20: 64 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 76 6f 69  d..*/.static voi
8d30: 64 20 6d 75 6c 74 69 70 6c 65 78 53 68 6d 42 61  d multiplexShmBa
8d40: 72 72 69 65 72 28 73 71 6c 69 74 65 33 5f 66 69  rrier(sqlite3_fi
8d50: 6c 65 20 2a 70 43 6f 6e 6e 29 7b 0a 20 20 6d 75  le *pConn){.  mu
8d60: 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d  ltiplexConn *p =
8d70: 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a   (multiplexConn*
8d80: 29 70 43 6f 6e 6e 3b 0a 20 20 69 6e 74 20 72 63  )pConn;.  int rc
8d90: 3b 0a 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65  ;.  sqlite3_file
8da0: 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c   *pSubOpen = mul
8db0: 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28 70 2d  tiplexSubOpen(p-
8dc0: 3e 70 47 72 6f 75 70 2c 20 30 2c 20 26 72 63 2c  >pGroup, 0, &rc,
8dd0: 20 4e 55 4c 4c 2c 20 30 29 3b 0a 20 20 69 66 28   NULL, 0);.  if(
8de0: 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20   pSubOpen ){.   
8df0: 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68   pSubOpen->pMeth
8e00: 6f 64 73 2d 3e 78 53 68 6d 42 61 72 72 69 65 72  ods->xShmBarrier
8e10: 28 70 53 75 62 4f 70 65 6e 29 3b 0a 20 20 7d 0a  (pSubOpen);.  }.
8e20: 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 53 68 6d 55  }../* Pass xShmU
8e30: 6e 6d 61 70 20 72 65 71 75 65 73 74 73 20 74 68  nmap requests th
8e40: 72 6f 75 67 68 20 74 6f 20 74 68 65 20 6f 72 69  rough to the ori
8e50: 67 69 6e 61 6c 20 56 46 53 20 75 6e 63 68 61 6e  ginal VFS unchan
8e60: 67 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69  ged..*/.static i
8e70: 6e 74 20 6d 75 6c 74 69 70 6c 65 78 53 68 6d 55  nt multiplexShmU
8e80: 6e 6d 61 70 28 73 71 6c 69 74 65 33 5f 66 69 6c  nmap(sqlite3_fil
8e90: 65 20 2a 70 43 6f 6e 6e 2c 20 69 6e 74 20 64 65  e *pConn, int de
8ea0: 6c 65 74 65 46 6c 61 67 29 7b 0a 20 20 6d 75 6c  leteFlag){.  mul
8eb0: 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d 20  tiplexConn *p = 
8ec0: 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a 29  (multiplexConn*)
8ed0: 70 43 6f 6e 6e 3b 0a 20 20 69 6e 74 20 72 63 3b  pConn;.  int rc;
8ee0: 0a 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20  .  sqlite3_file 
8ef0: 2a 70 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74  *pSubOpen = mult
8f00: 69 70 6c 65 78 53 75 62 4f 70 65 6e 28 70 2d 3e  iplexSubOpen(p->
8f10: 70 47 72 6f 75 70 2c 20 30 2c 20 26 72 63 2c 20  pGroup, 0, &rc, 
8f20: 4e 55 4c 4c 2c 20 30 29 3b 0a 20 20 69 66 28 20  NULL, 0);.  if( 
8f30: 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20  pSubOpen ){.    
8f40: 72 65 74 75 72 6e 20 70 53 75 62 4f 70 65 6e 2d  return pSubOpen-
8f50: 3e 70 4d 65 74 68 6f 64 73 2d 3e 78 53 68 6d 55  >pMethods->xShmU
8f60: 6e 6d 61 70 28 70 53 75 62 4f 70 65 6e 2c 20 64  nmap(pSubOpen, d
8f70: 65 6c 65 74 65 46 6c 61 67 29 3b 0a 20 20 7d 0a  eleteFlag);.  }.
8f80: 20 20 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f    return SQLITE_
8f90: 4f 4b 3b 0a 7d 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a  OK;.}../********
8fa0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
8fb0: 2a 2a 20 50 75 62 6c 69 63 20 49 6e 74 65 72 66  ** Public Interf
8fc0: 61 63 65 73 20 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  aces ***********
8fd0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
8fe0: 2a 2a 2f 0a 2f 2a 0a 2a 2a 20 43 41 50 49 3a 20  **/./*.** CAPI: 
8ff0: 49 6e 69 74 69 61 6c 69 7a 65 20 74 68 65 20 6d  Initialize the m
9000: 75 6c 74 69 70 6c 65 78 20 56 46 53 20 73 68 69  ultiplex VFS shi
9010: 6d 20 2d 20 73 71 6c 69 74 65 33 5f 6d 75 6c 74  m - sqlite3_mult
9020: 69 70 6c 65 78 5f 69 6e 69 74 69 61 6c 69 7a 65  iplex_initialize
9030: 28 29 0a 2a 2a 0a 2a 2a 20 55 73 65 20 74 68 65  ().**.** Use the
9040: 20 56 46 53 20 6e 61 6d 65 64 20 7a 4f 72 69 67   VFS named zOrig
9050: 56 66 73 4e 61 6d 65 20 61 73 20 74 68 65 20 56  VfsName as the V
9060: 46 53 20 74 68 61 74 20 64 6f 65 73 20 74 68 65  FS that does the
9070: 20 61 63 74 75 61 6c 20 77 6f 72 6b 2e 20 20 0a   actual work.  .
9080: 2a 2a 20 55 73 65 20 74 68 65 20 64 65 66 61 75  ** Use the defau
9090: 6c 74 20 69 66 20 7a 4f 72 69 67 56 66 73 4e 61  lt if zOrigVfsNa
90a0: 6d 65 3d 3d 4e 55 4c 4c 2e 20 20 0a 2a 2a 0a 2a  me==NULL.  .**.*
90b0: 2a 20 54 68 65 20 6d 75 6c 74 69 70 6c 65 78 20  * The multiplex 
90c0: 56 46 53 20 73 68 69 6d 20 69 73 20 6e 61 6d 65  VFS shim is name
90d0: 64 20 22 6d 75 6c 74 69 70 6c 65 78 22 2e 20 20  d "multiplex".  
90e0: 49 74 20 77 69 6c 6c 20 62 65 63 6f 6d 65 20 74  It will become t
90f0: 68 65 20 64 65 66 61 75 6c 74 0a 2a 2a 20 56 46  he default.** VF
9100: 53 20 69 66 20 6d 61 6b 65 44 65 66 61 75 6c 74  S if makeDefault
9110: 20 69 73 20 6e 6f 6e 2d 7a 65 72 6f 2e 0a 2a 2a   is non-zero..**
9120: 0a 2a 2a 20 54 48 49 53 20 52 4f 55 54 49 4e 45  .** THIS ROUTINE
9130: 20 49 53 20 4e 4f 54 20 54 48 52 45 41 44 53 41   IS NOT THREADSA
9140: 46 45 2e 20 20 43 61 6c 6c 20 74 68 69 73 20 72  FE.  Call this r
9150: 6f 75 74 69 6e 65 20 65 78 61 63 74 6c 79 20 6f  outine exactly o
9160: 6e 63 65 0a 2a 2a 20 64 75 72 69 6e 67 20 73 74  nce.** during st
9170: 61 72 74 2d 75 70 2e 0a 2a 2f 0a 69 6e 74 20 73  art-up..*/.int s
9180: 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78  qlite3_multiplex
9190: 5f 69 6e 69 74 69 61 6c 69 7a 65 28 63 6f 6e 73  _initialize(cons
91a0: 74 20 63 68 61 72 20 2a 7a 4f 72 69 67 56 66 73  t char *zOrigVfs
91b0: 4e 61 6d 65 2c 20 69 6e 74 20 6d 61 6b 65 44 65  Name, int makeDe
91c0: 66 61 75 6c 74 29 7b 0a 20 20 73 71 6c 69 74 65  fault){.  sqlite
91d0: 33 5f 76 66 73 20 2a 70 4f 72 69 67 56 66 73 3b  3_vfs *pOrigVfs;
91e0: 0a 20 20 69 66 28 20 67 4d 75 6c 74 69 70 6c 65  .  if( gMultiple
91f0: 78 2e 69 73 49 6e 69 74 69 61 6c 69 7a 65 64 20  x.isInitialized 
9200: 29 20 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f  ) return SQLITE_
9210: 4d 49 53 55 53 45 3b 0a 20 20 70 4f 72 69 67 56  MISUSE;.  pOrigV
9220: 66 73 20 3d 20 73 71 6c 69 74 65 33 5f 76 66 73  fs = sqlite3_vfs
9230: 5f 66 69 6e 64 28 7a 4f 72 69 67 56 66 73 4e 61  _find(zOrigVfsNa
9240: 6d 65 29 3b 0a 20 20 69 66 28 20 70 4f 72 69 67  me);.  if( pOrig
9250: 56 66 73 3d 3d 30 20 29 20 72 65 74 75 72 6e 20  Vfs==0 ) return 
9260: 53 51 4c 49 54 45 5f 45 52 52 4f 52 3b 0a 20 20  SQLITE_ERROR;.  
9270: 61 73 73 65 72 74 28 20 70 4f 72 69 67 56 66 73  assert( pOrigVfs
9280: 21 3d 26 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54  !=&gMultiplex.sT
9290: 68 69 73 56 66 73 20 29 3b 0a 20 20 67 4d 75 6c  hisVfs );.  gMul
92a0: 74 69 70 6c 65 78 2e 70 4d 75 74 65 78 20 3d 20  tiplex.pMutex = 
92b0: 73 71 6c 69 74 65 33 5f 6d 75 74 65 78 5f 61 6c  sqlite3_mutex_al
92c0: 6c 6f 63 28 53 51 4c 49 54 45 5f 4d 55 54 45 58  loc(SQLITE_MUTEX
92d0: 5f 46 41 53 54 29 3b 0a 20 20 69 66 28 20 21 67  _FAST);.  if( !g
92e0: 4d 75 6c 74 69 70 6c 65 78 2e 70 4d 75 74 65 78  Multiplex.pMutex
92f0: 20 29 7b 0a 20 20 20 20 72 65 74 75 72 6e 20 53   ){.    return S
9300: 51 4c 49 54 45 5f 4e 4f 4d 45 4d 3b 0a 20 20 7d  QLITE_NOMEM;.  }
9310: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 47  .  gMultiplex.pG
9320: 72 6f 75 70 73 20 3d 20 4e 55 4c 4c 3b 0a 20 20  roups = NULL;.  
9330: 67 4d 75 6c 74 69 70 6c 65 78 2e 69 73 49 6e 69  gMultiplex.isIni
9340: 74 69 61 6c 69 7a 65 64 20 3d 20 31 3b 0a 20 20  tialized = 1;.  
9350: 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67  gMultiplex.pOrig
9360: 56 66 73 20 3d 20 70 4f 72 69 67 56 66 73 3b 0a  Vfs = pOrigVfs;.
9370: 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54 68    gMultiplex.sTh
9380: 69 73 56 66 73 20 3d 20 2a 70 4f 72 69 67 56 66  isVfs = *pOrigVf
9390: 73 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e  s;.  gMultiplex.
93a0: 73 54 68 69 73 56 66 73 2e 73 7a 4f 73 46 69 6c  sThisVfs.szOsFil
93b0: 65 20 2b 3d 20 73 69 7a 65 6f 66 28 6d 75 6c 74  e += sizeof(mult
93c0: 69 70 6c 65 78 43 6f 6e 6e 29 3b 0a 20 20 67 4d  iplexConn);.  gM
93d0: 75 6c 74 69 70 6c 65 78 2e 73 54 68 69 73 56 66  ultiplex.sThisVf
93e0: 73 2e 7a 4e 61 6d 65 20 3d 20 53 51 4c 49 54 45  s.zName = SQLITE
93f0: 5f 4d 55 4c 54 49 50 4c 45 58 5f 56 46 53 5f 4e  _MULTIPLEX_VFS_N
9400: 41 4d 45 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65  AME;.  gMultiple
9410: 78 2e 73 54 68 69 73 56 66 73 2e 78 4f 70 65 6e  x.sThisVfs.xOpen
9420: 20 3d 20 6d 75 6c 74 69 70 6c 65 78 4f 70 65 6e   = multiplexOpen
9430: 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73  ;.  gMultiplex.s
9440: 54 68 69 73 56 66 73 2e 78 44 65 6c 65 74 65 20  ThisVfs.xDelete 
9450: 3d 20 6d 75 6c 74 69 70 6c 65 78 44 65 6c 65 74  = multiplexDelet
9460: 65 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e  e;.  gMultiplex.
9470: 73 54 68 69 73 56 66 73 2e 78 41 63 63 65 73 73  sThisVfs.xAccess
9480: 20 3d 20 6d 75 6c 74 69 70 6c 65 78 41 63 63 65   = multiplexAcce
9490: 73 73 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78  ss;.  gMultiplex
94a0: 2e 73 54 68 69 73 56 66 73 2e 78 46 75 6c 6c 50  .sThisVfs.xFullP
94b0: 61 74 68 6e 61 6d 65 20 3d 20 6d 75 6c 74 69 70  athname = multip
94c0: 6c 65 78 46 75 6c 6c 50 61 74 68 6e 61 6d 65 3b  lexFullPathname;
94d0: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54  .  gMultiplex.sT
94e0: 68 69 73 56 66 73 2e 78 44 6c 4f 70 65 6e 20 3d  hisVfs.xDlOpen =
94f0: 20 6d 75 6c 74 69 70 6c 65 78 44 6c 4f 70 65 6e   multiplexDlOpen
9500: 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73  ;.  gMultiplex.s
9510: 54 68 69 73 56 66 73 2e 78 44 6c 45 72 72 6f 72  ThisVfs.xDlError
9520: 20 3d 20 6d 75 6c 74 69 70 6c 65 78 44 6c 45 72   = multiplexDlEr
9530: 72 6f 72 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65  ror;.  gMultiple
9540: 78 2e 73 54 68 69 73 56 66 73 2e 78 44 6c 53 79  x.sThisVfs.xDlSy
9550: 6d 20 3d 20 6d 75 6c 74 69 70 6c 65 78 44 6c 53  m = multiplexDlS
9560: 79 6d 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78  ym;.  gMultiplex
9570: 2e 73 54 68 69 73 56 66 73 2e 78 44 6c 43 6c 6f  .sThisVfs.xDlClo
9580: 73 65 20 3d 20 6d 75 6c 74 69 70 6c 65 78 44 6c  se = multiplexDl
9590: 43 6c 6f 73 65 3b 0a 20 20 67 4d 75 6c 74 69 70  Close;.  gMultip
95a0: 6c 65 78 2e 73 54 68 69 73 56 66 73 2e 78 52 61  lex.sThisVfs.xRa
95b0: 6e 64 6f 6d 6e 65 73 73 20 3d 20 6d 75 6c 74 69  ndomness = multi
95c0: 70 6c 65 78 52 61 6e 64 6f 6d 6e 65 73 73 3b 0a  plexRandomness;.
95d0: 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54 68    gMultiplex.sTh
95e0: 69 73 56 66 73 2e 78 53 6c 65 65 70 20 3d 20 6d  isVfs.xSleep = m
95f0: 75 6c 74 69 70 6c 65 78 53 6c 65 65 70 3b 0a 20  ultiplexSleep;. 
9600: 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54 68 69   gMultiplex.sThi
9610: 73 56 66 73 2e 78 43 75 72 72 65 6e 74 54 69 6d  sVfs.xCurrentTim
9620: 65 20 3d 20 6d 75 6c 74 69 70 6c 65 78 43 75 72  e = multiplexCur
9630: 72 65 6e 74 54 69 6d 65 3b 0a 20 20 67 4d 75 6c  rentTime;.  gMul
9640: 74 69 70 6c 65 78 2e 73 54 68 69 73 56 66 73 2e  tiplex.sThisVfs.
9650: 78 47 65 74 4c 61 73 74 45 72 72 6f 72 20 3d 20  xGetLastError = 
9660: 6d 75 6c 74 69 70 6c 65 78 47 65 74 4c 61 73 74  multiplexGetLast
9670: 45 72 72 6f 72 3b 0a 20 20 67 4d 75 6c 74 69 70  Error;.  gMultip
9680: 6c 65 78 2e 73 54 68 69 73 56 66 73 2e 78 43 75  lex.sThisVfs.xCu
9690: 72 72 65 6e 74 54 69 6d 65 49 6e 74 36 34 20 3d  rrentTimeInt64 =
96a0: 20 6d 75 6c 74 69 70 6c 65 78 43 75 72 72 65 6e   multiplexCurren
96b0: 74 54 69 6d 65 49 6e 74 36 34 3b 0a 0a 20 20 67  tTimeInt64;..  g
96c0: 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74  Multiplex.sIoMet
96d0: 68 6f 64 73 56 31 2e 69 56 65 72 73 69 6f 6e 20  hodsV1.iVersion 
96e0: 3d 20 31 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65  = 1;.  gMultiple
96f0: 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31 2e 78  x.sIoMethodsV1.x
9700: 43 6c 6f 73 65 20 3d 20 6d 75 6c 74 69 70 6c 65  Close = multiple
9710: 78 43 6c 6f 73 65 3b 0a 20 20 67 4d 75 6c 74 69  xClose;.  gMulti
9720: 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56  plex.sIoMethodsV
9730: 31 2e 78 52 65 61 64 20 3d 20 6d 75 6c 74 69 70  1.xRead = multip
9740: 6c 65 78 52 65 61 64 3b 0a 20 20 67 4d 75 6c 74  lexRead;.  gMult
9750: 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73  iplex.sIoMethods
9760: 56 31 2e 78 57 72 69 74 65 20 3d 20 6d 75 6c 74  V1.xWrite = mult
9770: 69 70 6c 65 78 57 72 69 74 65 3b 0a 20 20 67 4d  iplexWrite;.  gM
9780: 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68  ultiplex.sIoMeth
9790: 6f 64 73 56 31 2e 78 54 72 75 6e 63 61 74 65 20  odsV1.xTruncate 
97a0: 3d 20 6d 75 6c 74 69 70 6c 65 78 54 72 75 6e 63  = multiplexTrunc
97b0: 61 74 65 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65  ate;.  gMultiple
97c0: 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31 2e 78  x.sIoMethodsV1.x
97d0: 53 79 6e 63 20 3d 20 6d 75 6c 74 69 70 6c 65 78  Sync = multiplex
97e0: 53 79 6e 63 3b 0a 20 20 67 4d 75 6c 74 69 70 6c  Sync;.  gMultipl
97f0: 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31 2e  ex.sIoMethodsV1.
9800: 78 46 69 6c 65 53 69 7a 65 20 3d 20 6d 75 6c 74  xFileSize = mult
9810: 69 70 6c 65 78 46 69 6c 65 53 69 7a 65 3b 0a 20  iplexFileSize;. 
9820: 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d   gMultiplex.sIoM
9830: 65 74 68 6f 64 73 56 31 2e 78 4c 6f 63 6b 20 3d  ethodsV1.xLock =
9840: 20 6d 75 6c 74 69 70 6c 65 78 4c 6f 63 6b 3b 0a   multiplexLock;.
9850: 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f    gMultiplex.sIo
9860: 4d 65 74 68 6f 64 73 56 31 2e 78 55 6e 6c 6f 63  MethodsV1.xUnloc
9870: 6b 20 3d 20 6d 75 6c 74 69 70 6c 65 78 55 6e 6c  k = multiplexUnl
9880: 6f 63 6b 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65  ock;.  gMultiple
9890: 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31 2e 78  x.sIoMethodsV1.x
98a0: 43 68 65 63 6b 52 65 73 65 72 76 65 64 4c 6f 63  CheckReservedLoc
98b0: 6b 20 3d 20 6d 75 6c 74 69 70 6c 65 78 43 68 65  k = multiplexChe
98c0: 63 6b 52 65 73 65 72 76 65 64 4c 6f 63 6b 3b 0a  ckReservedLock;.
98d0: 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f    gMultiplex.sIo
98e0: 4d 65 74 68 6f 64 73 56 31 2e 78 46 69 6c 65 43  MethodsV1.xFileC
98f0: 6f 6e 74 72 6f 6c 20 3d 20 6d 75 6c 74 69 70 6c  ontrol = multipl
9900: 65 78 46 69 6c 65 43 6f 6e 74 72 6f 6c 3b 0a 20  exFileControl;. 
9910: 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d   gMultiplex.sIoM
9920: 65 74 68 6f 64 73 56 31 2e 78 53 65 63 74 6f 72  ethodsV1.xSector
9930: 53 69 7a 65 20 3d 20 6d 75 6c 74 69 70 6c 65 78  Size = multiplex
9940: 53 65 63 74 6f 72 53 69 7a 65 3b 0a 20 20 67 4d  SectorSize;.  gM
9950: 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68  ultiplex.sIoMeth
9960: 6f 64 73 56 31 2e 78 44 65 76 69 63 65 43 68 61  odsV1.xDeviceCha
9970: 72 61 63 74 65 72 69 73 74 69 63 73 20 3d 0a 20  racteristics =. 
9980: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9990: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
99a0: 20 20 20 20 20 20 20 20 20 20 20 6d 75 6c 74 69             multi
99b0: 70 6c 65 78 44 65 76 69 63 65 43 68 61 72 61 63  plexDeviceCharac
99c0: 74 65 72 69 73 74 69 63 73 3b 0a 20 20 67 4d 75  teristics;.  gMu
99d0: 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f  ltiplex.sIoMetho
99e0: 64 73 56 32 20 3d 20 67 4d 75 6c 74 69 70 6c 65  dsV2 = gMultiple
99f0: 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31 3b 0a  x.sIoMethodsV1;.
9a00: 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f    gMultiplex.sIo
9a10: 4d 65 74 68 6f 64 73 56 32 2e 69 56 65 72 73 69  MethodsV2.iVersi
9a20: 6f 6e 20 3d 20 32 3b 0a 20 20 67 4d 75 6c 74 69  on = 2;.  gMulti
9a30: 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56  plex.sIoMethodsV
9a40: 32 2e 78 53 68 6d 4d 61 70 20 3d 20 6d 75 6c 74  2.xShmMap = mult
9a50: 69 70 6c 65 78 53 68 6d 4d 61 70 3b 0a 20 20 67  iplexShmMap;.  g
9a60: 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74  Multiplex.sIoMet
9a70: 68 6f 64 73 56 32 2e 78 53 68 6d 4c 6f 63 6b 20  hodsV2.xShmLock 
9a80: 3d 20 6d 75 6c 74 69 70 6c 65 78 53 68 6d 4c 6f  = multiplexShmLo
9a90: 63 6b 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78  ck;.  gMultiplex
9aa0: 2e 73 49 6f 4d 65 74 68 6f 64 73 56 32 2e 78 53  .sIoMethodsV2.xS
9ab0: 68 6d 42 61 72 72 69 65 72 20 3d 20 6d 75 6c 74  hmBarrier = mult
9ac0: 69 70 6c 65 78 53 68 6d 42 61 72 72 69 65 72 3b  iplexShmBarrier;
9ad0: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49  .  gMultiplex.sI
9ae0: 6f 4d 65 74 68 6f 64 73 56 32 2e 78 53 68 6d 55  oMethodsV2.xShmU
9af0: 6e 6d 61 70 20 3d 20 6d 75 6c 74 69 70 6c 65 78  nmap = multiplex
9b00: 53 68 6d 55 6e 6d 61 70 3b 0a 20 20 73 71 6c 69  ShmUnmap;.  sqli
9b10: 74 65 33 5f 76 66 73 5f 72 65 67 69 73 74 65 72  te3_vfs_register
9b20: 28 26 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54 68  (&gMultiplex.sTh
9b30: 69 73 56 66 73 2c 20 6d 61 6b 65 44 65 66 61 75  isVfs, makeDefau
9b40: 6c 74 29 3b 0a 0a 20 20 73 71 6c 69 74 65 33 5f  lt);..  sqlite3_
9b50: 61 75 74 6f 5f 65 78 74 65 6e 73 69 6f 6e 28 28  auto_extension((
9b60: 76 6f 69 64 2a 29 6d 75 6c 74 69 70 6c 65 78 46  void*)multiplexF
9b70: 75 6e 63 49 6e 69 74 29 3b 0a 0a 20 20 72 65 74  uncInit);..  ret
9b80: 75 72 6e 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 7d  urn SQLITE_OK;.}
9b90: 0a 0a 2f 2a 0a 2a 2a 20 43 41 50 49 3a 20 53 68  ../*.** CAPI: Sh
9ba0: 75 74 64 6f 77 6e 20 74 68 65 20 6d 75 6c 74 69  utdown the multi
9bb0: 70 6c 65 78 20 73 79 73 74 65 6d 20 2d 20 73 71  plex system - sq
9bc0: 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f  lite3_multiplex_
9bd0: 73 68 75 74 64 6f 77 6e 28 29 0a 2a 2a 0a 2a 2a  shutdown().**.**
9be0: 20 41 6c 6c 20 53 51 4c 69 74 65 20 64 61 74 61   All SQLite data
9bf0: 62 61 73 65 20 63 6f 6e 6e 65 63 74 69 6f 6e 73  base connections
9c00: 20 6d 75 73 74 20 62 65 20 63 6c 6f 73 65 64 20   must be closed 
9c10: 62 65 66 6f 72 65 20 63 61 6c 6c 69 6e 67 20 74  before calling t
9c20: 68 69 73 0a 2a 2a 20 72 6f 75 74 69 6e 65 2e 0a  his.** routine..
9c30: 2a 2a 0a 2a 2a 20 54 48 49 53 20 52 4f 55 54 49  **.** THIS ROUTI
9c40: 4e 45 20 49 53 20 4e 4f 54 20 54 48 52 45 41 44  NE IS NOT THREAD
9c50: 53 41 46 45 2e 20 20 43 61 6c 6c 20 74 68 69 73  SAFE.  Call this
9c60: 20 72 6f 75 74 69 6e 65 20 65 78 61 63 74 6c 79   routine exactly
9c70: 20 6f 6e 63 65 20 77 68 69 6c 65 0a 2a 2a 20 73   once while.** s
9c80: 68 75 74 74 69 6e 67 20 64 6f 77 6e 20 69 6e 20  hutting down in 
9c90: 6f 72 64 65 72 20 74 6f 20 66 72 65 65 20 61 6c  order to free al
9ca0: 6c 20 72 65 6d 61 69 6e 69 6e 67 20 6d 75 6c 74  l remaining mult
9cb0: 69 70 6c 65 78 20 67 72 6f 75 70 73 2e 0a 2a 2f  iplex groups..*/
9cc0: 0a 69 6e 74 20 73 71 6c 69 74 65 33 5f 6d 75 6c  .int sqlite3_mul
9cd0: 74 69 70 6c 65 78 5f 73 68 75 74 64 6f 77 6e 28  tiplex_shutdown(
9ce0: 76 6f 69 64 29 7b 0a 20 20 69 66 28 20 67 4d 75  void){.  if( gMu
9cf0: 6c 74 69 70 6c 65 78 2e 69 73 49 6e 69 74 69 61  ltiplex.isInitia
9d00: 6c 69 7a 65 64 3d 3d 30 20 29 20 72 65 74 75 72  lized==0 ) retur
9d10: 6e 20 53 51 4c 49 54 45 5f 4d 49 53 55 53 45 3b  n SQLITE_MISUSE;
9d20: 0a 20 20 69 66 28 20 67 4d 75 6c 74 69 70 6c 65  .  if( gMultiple
9d30: 78 2e 70 47 72 6f 75 70 73 20 29 20 72 65 74 75  x.pGroups ) retu
9d40: 72 6e 20 53 51 4c 49 54 45 5f 4d 49 53 55 53 45  rn SQLITE_MISUSE
9d50: 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 69  ;.  gMultiplex.i
9d60: 73 49 6e 69 74 69 61 6c 69 7a 65 64 20 3d 20 30  sInitialized = 0
9d70: 3b 0a 20 20 73 71 6c 69 74 65 33 5f 6d 75 74 65  ;.  sqlite3_mute
9d80: 78 5f 66 72 65 65 28 67 4d 75 6c 74 69 70 6c 65  x_free(gMultiple
9d90: 78 2e 70 4d 75 74 65 78 29 3b 0a 20 20 73 71 6c  x.pMutex);.  sql
9da0: 69 74 65 33 5f 76 66 73 5f 75 6e 72 65 67 69 73  ite3_vfs_unregis
9db0: 74 65 72 28 26 67 4d 75 6c 74 69 70 6c 65 78 2e  ter(&gMultiplex.
9dc0: 73 54 68 69 73 56 66 73 29 3b 0a 20 20 6d 65 6d  sThisVfs);.  mem
9dd0: 73 65 74 28 26 67 4d 75 6c 74 69 70 6c 65 78 2c  set(&gMultiplex,
9de0: 20 30 2c 20 73 69 7a 65 6f 66 28 67 4d 75 6c 74   0, sizeof(gMult
9df0: 69 70 6c 65 78 29 29 3b 0a 20 20 72 65 74 75 72  iplex));.  retur
9e00: 6e 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 7d 0a 0a  n SQLITE_OK;.}..
9e10: 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  /***************
9e20: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20 54  ************** T
9e30: 65 73 74 20 43 6f 64 65 20 2a 2a 2a 2a 2a 2a 2a  est Code *******
9e40: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
9e50: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2f 0a 23 69  ************/.#i
9e60: 66 64 65 66 20 53 51 4c 49 54 45 5f 54 45 53 54  fdef SQLITE_TEST
9e70: 0a 23 69 6e 63 6c 75 64 65 20 3c 74 63 6c 2e 68  .#include <tcl.h
9e80: 3e 0a 65 78 74 65 72 6e 20 63 6f 6e 73 74 20 63  >.extern const c
9e90: 68 61 72 20 2a 73 71 6c 69 74 65 33 54 65 73 74  har *sqlite3Test
9ea0: 45 72 72 6f 72 4e 61 6d 65 28 69 6e 74 29 3b 0a  ErrorName(int);.
9eb0: 0a 0a 2f 2a 0a 2a 2a 20 74 63 6c 63 6d 64 3a 20  ../*.** tclcmd: 
9ec0: 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65  sqlite3_multiple
9ed0: 78 5f 69 6e 69 74 69 61 6c 69 7a 65 20 4e 41 4d  x_initialize NAM
9ee0: 45 20 4d 41 4b 45 44 45 46 41 55 4c 54 0a 2a 2f  E MAKEDEFAULT.*/
9ef0: 0a 73 74 61 74 69 63 20 69 6e 74 20 74 65 73 74  .static int test
9f00: 5f 6d 75 6c 74 69 70 6c 65 78 5f 69 6e 69 74 69  _multiplex_initi
9f10: 61 6c 69 7a 65 28 0a 20 20 76 6f 69 64 20 2a 20  alize(.  void * 
9f20: 63 6c 69 65 6e 74 44 61 74 61 2c 0a 20 20 54 63  clientData,.  Tc
9f30: 6c 5f 49 6e 74 65 72 70 20 2a 69 6e 74 65 72 70  l_Interp *interp
9f40: 2c 0a 20 20 69 6e 74 20 6f 62 6a 63 2c 0a 20 20  ,.  int objc,.  
9f50: 54 63 6c 5f 4f 62 6a 20 2a 43 4f 4e 53 54 20 6f  Tcl_Obj *CONST o
9f60: 62 6a 76 5b 5d 0a 29 7b 0a 20 20 63 6f 6e 73 74  bjv[].){.  const
9f70: 20 63 68 61 72 20 2a 7a 4e 61 6d 65 3b 20 20 20   char *zName;   
9f80: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4e 61             /* Na
9f90: 6d 65 20 6f 66 20 6e 65 77 20 6d 75 6c 74 69 70  me of new multip
9fa0: 6c 65 78 20 56 46 53 20 2a 2f 0a 20 20 69 6e 74  lex VFS */.  int
9fb0: 20 6d 61 6b 65 44 65 66 61 75 6c 74 3b 20 20 20   makeDefault;   
9fc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
9fd0: 54 72 75 65 20 74 6f 20 6d 61 6b 65 20 74 68 65  True to make the
9fe0: 20 6e 65 77 20 56 46 53 20 74 68 65 20 64 65 66   new VFS the def
9ff0: 61 75 6c 74 20 2a 2f 0a 20 20 69 6e 74 20 72 63  ault */.  int rc
a000: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ;               
a010: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 56 61 6c            /* Val
a020: 75 65 20 72 65 74 75 72 6e 65 64 20 62 79 20 6d  ue returned by m
a030: 75 6c 74 69 70 6c 65 78 5f 69 6e 69 74 69 61 6c  ultiplex_initial
a040: 69 7a 65 28 29 20 2a 2f 0a 0a 20 20 55 4e 55 53  ize() */..  UNUS
a050: 45 44 5f 50 41 52 41 4d 45 54 45 52 28 63 6c 69  ED_PARAMETER(cli
a060: 65 6e 74 44 61 74 61 29 3b 0a 0a 20 20 2f 2a 20  entData);..  /* 
a070: 50 72 6f 63 65 73 73 20 61 72 67 75 6d 65 6e 74  Process argument
a080: 73 20 2a 2f 0a 20 20 69 66 28 20 6f 62 6a 63 21  s */.  if( objc!
a090: 3d 33 20 29 7b 0a 20 20 20 20 54 63 6c 5f 57 72  =3 ){.    Tcl_Wr
a0a0: 6f 6e 67 4e 75 6d 41 72 67 73 28 69 6e 74 65 72  ongNumArgs(inter
a0b0: 70 2c 20 31 2c 20 6f 62 6a 76 2c 20 22 4e 41 4d  p, 1, objv, "NAM
a0c0: 45 20 4d 41 4b 45 44 45 46 41 55 4c 54 22 29 3b  E MAKEDEFAULT");
a0d0: 0a 20 20 20 20 72 65 74 75 72 6e 20 54 43 4c 5f  .    return TCL_
a0e0: 45 52 52 4f 52 3b 0a 20 20 7d 0a 20 20 7a 4e 61  ERROR;.  }.  zNa
a0f0: 6d 65 20 3d 20 54 63 6c 5f 47 65 74 53 74 72 69  me = Tcl_GetStri
a100: 6e 67 28 6f 62 6a 76 5b 31 5d 29 3b 0a 20 20 69  ng(objv[1]);.  i
a110: 66 28 20 54 63 6c 5f 47 65 74 42 6f 6f 6c 65 61  f( Tcl_GetBoolea
a120: 6e 46 72 6f 6d 4f 62 6a 28 69 6e 74 65 72 70 2c  nFromObj(interp,
a130: 20 6f 62 6a 76 5b 32 5d 2c 20 26 6d 61 6b 65 44   objv[2], &makeD
a140: 65 66 61 75 6c 74 29 20 29 20 72 65 74 75 72 6e  efault) ) return
a150: 20 54 43 4c 5f 45 52 52 4f 52 3b 0a 20 20 69 66   TCL_ERROR;.  if
a160: 28 20 7a 4e 61 6d 65 5b 30 5d 3d 3d 27 5c 30 27  ( zName[0]=='\0'
a170: 20 29 20 7a 4e 61 6d 65 20 3d 20 30 3b 0a 0a 20   ) zName = 0;.. 
a180: 20 2f 2a 20 43 61 6c 6c 20 73 71 6c 69 74 65 33   /* Call sqlite3
a190: 5f 6d 75 6c 74 69 70 6c 65 78 5f 69 6e 69 74 69  _multiplex_initi
a1a0: 61 6c 69 7a 65 28 29 20 2a 2f 0a 20 20 72 63 20  alize() */.  rc 
a1b0: 3d 20 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70  = sqlite3_multip
a1c0: 6c 65 78 5f 69 6e 69 74 69 61 6c 69 7a 65 28 7a  lex_initialize(z
a1d0: 4e 61 6d 65 2c 20 6d 61 6b 65 44 65 66 61 75 6c  Name, makeDefaul
a1e0: 74 29 3b 0a 20 20 54 63 6c 5f 53 65 74 52 65 73  t);.  Tcl_SetRes
a1f0: 75 6c 74 28 69 6e 74 65 72 70 2c 20 28 63 68 61  ult(interp, (cha
a200: 72 20 2a 29 73 71 6c 69 74 65 33 54 65 73 74 45  r *)sqlite3TestE
a210: 72 72 6f 72 4e 61 6d 65 28 72 63 29 2c 20 54 43  rrorName(rc), TC
a220: 4c 5f 53 54 41 54 49 43 29 3b 0a 0a 20 20 72 65  L_STATIC);..  re
a230: 74 75 72 6e 20 54 43 4c 5f 4f 4b 3b 0a 7d 0a 0a  turn TCL_OK;.}..
a240: 2f 2a 0a 2a 2a 20 74 63 6c 63 6d 64 3a 20 73 71  /*.** tclcmd: sq
a250: 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f  lite3_multiplex_
a260: 73 68 75 74 64 6f 77 6e 0a 2a 2f 0a 73 74 61 74  shutdown.*/.stat
a270: 69 63 20 69 6e 74 20 74 65 73 74 5f 6d 75 6c 74  ic int test_mult
a280: 69 70 6c 65 78 5f 73 68 75 74 64 6f 77 6e 28 0a  iplex_shutdown(.
a290: 20 20 76 6f 69 64 20 2a 20 63 6c 69 65 6e 74 44    void * clientD
a2a0: 61 74 61 2c 0a 20 20 54 63 6c 5f 49 6e 74 65 72  ata,.  Tcl_Inter
a2b0: 70 20 2a 69 6e 74 65 72 70 2c 0a 20 20 69 6e 74  p *interp,.  int
a2c0: 20 6f 62 6a 63 2c 0a 20 20 54 63 6c 5f 4f 62 6a   objc,.  Tcl_Obj
a2d0: 20 2a 43 4f 4e 53 54 20 6f 62 6a 76 5b 5d 0a 29   *CONST objv[].)
a2e0: 7b 0a 20 20 69 6e 74 20 72 63 3b 20 20 20 20 20  {.  int rc;     
a2f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a300: 20 20 20 20 2f 2a 20 56 61 6c 75 65 20 72 65 74      /* Value ret
a310: 75 72 6e 65 64 20 62 79 20 6d 75 6c 74 69 70 6c  urned by multipl
a320: 65 78 5f 73 68 75 74 64 6f 77 6e 28 29 20 2a 2f  ex_shutdown() */
a330: 0a 0a 20 20 55 4e 55 53 45 44 5f 50 41 52 41 4d  ..  UNUSED_PARAM
a340: 45 54 45 52 28 63 6c 69 65 6e 74 44 61 74 61 29  ETER(clientData)
a350: 3b 0a 0a 20 20 69 66 28 20 6f 62 6a 63 21 3d 31  ;..  if( objc!=1
a360: 20 29 7b 0a 20 20 20 20 54 63 6c 5f 57 72 6f 6e   ){.    Tcl_Wron
a370: 67 4e 75 6d 41 72 67 73 28 69 6e 74 65 72 70 2c  gNumArgs(interp,
a380: 20 31 2c 20 6f 62 6a 76 2c 20 22 22 29 3b 0a 20   1, objv, "");. 
a390: 20 20 20 72 65 74 75 72 6e 20 54 43 4c 5f 45 52     return TCL_ER
a3a0: 52 4f 52 3b 0a 20 20 7d 0a 0a 20 20 2f 2a 20 43  ROR;.  }..  /* C
a3b0: 61 6c 6c 20 73 71 6c 69 74 65 33 5f 6d 75 6c 74  all sqlite3_mult
a3c0: 69 70 6c 65 78 5f 73 68 75 74 64 6f 77 6e 28 29  iplex_shutdown()
a3d0: 20 2a 2f 0a 20 20 72 63 20 3d 20 73 71 6c 69 74   */.  rc = sqlit
a3e0: 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 73 68 75  e3_multiplex_shu
a3f0: 74 64 6f 77 6e 28 29 3b 0a 20 20 54 63 6c 5f 53  tdown();.  Tcl_S
a400: 65 74 52 65 73 75 6c 74 28 69 6e 74 65 72 70 2c  etResult(interp,
a410: 20 28 63 68 61 72 20 2a 29 73 71 6c 69 74 65 33   (char *)sqlite3
a420: 54 65 73 74 45 72 72 6f 72 4e 61 6d 65 28 72 63  TestErrorName(rc
a430: 29 2c 20 54 43 4c 5f 53 54 41 54 49 43 29 3b 0a  ), TCL_STATIC);.
a440: 0a 20 20 72 65 74 75 72 6e 20 54 43 4c 5f 4f 4b  .  return TCL_OK
a450: 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 74 63 6c 63 6d  ;.}../*.** tclcm
a460: 64 3a 20 20 73 71 6c 69 74 65 33 5f 6d 75 6c 74  d:  sqlite3_mult
a470: 69 70 6c 65 78 5f 64 75 6d 70 0a 2a 2f 0a 73 74  iplex_dump.*/.st
a480: 61 74 69 63 20 69 6e 74 20 74 65 73 74 5f 6d 75  atic int test_mu
a490: 6c 74 69 70 6c 65 78 5f 64 75 6d 70 28 0a 20 20  ltiplex_dump(.  
a4a0: 76 6f 69 64 20 2a 20 63 6c 69 65 6e 74 44 61 74  void * clientDat
a4b0: 61 2c 0a 20 20 54 63 6c 5f 49 6e 74 65 72 70 20  a,.  Tcl_Interp 
a4c0: 2a 69 6e 74 65 72 70 2c 0a 20 20 69 6e 74 20 6f  *interp,.  int o
a4d0: 62 6a 63 2c 0a 20 20 54 63 6c 5f 4f 62 6a 20 2a  bjc,.  Tcl_Obj *
a4e0: 43 4f 4e 53 54 20 6f 62 6a 76 5b 5d 0a 29 7b 0a  CONST objv[].){.
a4f0: 20 20 54 63 6c 5f 4f 62 6a 20 2a 70 52 65 73 75    Tcl_Obj *pResu
a500: 6c 74 3b 0a 20 20 54 63 6c 5f 4f 62 6a 20 2a 70  lt;.  Tcl_Obj *p
a510: 47 72 6f 75 70 54 65 72 6d 3b 0a 20 20 6d 75 6c  GroupTerm;.  mul
a520: 74 69 70 6c 65 78 47 72 6f 75 70 20 2a 70 47 72  tiplexGroup *pGr
a530: 6f 75 70 3b 0a 20 20 69 6e 74 20 69 3b 0a 20 20  oup;.  int i;.  
a540: 69 6e 74 20 6e 43 68 75 6e 6b 73 20 3d 20 30 3b  int nChunks = 0;
a550: 0a 0a 20 20 55 4e 55 53 45 44 5f 50 41 52 41 4d  ..  UNUSED_PARAM
a560: 45 54 45 52 28 63 6c 69 65 6e 74 44 61 74 61 29  ETER(clientData)
a570: 3b 0a 20 20 55 4e 55 53 45 44 5f 50 41 52 41 4d  ;.  UNUSED_PARAM
a580: 45 54 45 52 28 6f 62 6a 63 29 3b 0a 20 20 55 4e  ETER(objc);.  UN
a590: 55 53 45 44 5f 50 41 52 41 4d 45 54 45 52 28 6f  USED_PARAMETER(o
a5a0: 62 6a 76 29 3b 0a 0a 20 20 70 52 65 73 75 6c 74  bjv);..  pResult
a5b0: 20 3d 20 54 63 6c 5f 4e 65 77 4f 62 6a 28 29 3b   = Tcl_NewObj();
a5c0: 0a 20 20 6d 75 6c 74 69 70 6c 65 78 45 6e 74 65  .  multiplexEnte
a5d0: 72 28 29 3b 0a 20 20 66 6f 72 28 70 47 72 6f 75  r();.  for(pGrou
a5e0: 70 3d 67 4d 75 6c 74 69 70 6c 65 78 2e 70 47 72  p=gMultiplex.pGr
a5f0: 6f 75 70 73 3b 20 70 47 72 6f 75 70 3b 20 70 47  oups; pGroup; pG
a600: 72 6f 75 70 3d 70 47 72 6f 75 70 2d 3e 70 4e 65  roup=pGroup->pNe
a610: 78 74 29 7b 0a 20 20 20 20 70 47 72 6f 75 70 54  xt){.    pGroupT
a620: 65 72 6d 20 3d 20 54 63 6c 5f 4e 65 77 4f 62 6a  erm = Tcl_NewObj
a630: 28 29 3b 0a 0a 20 20 20 20 69 66 28 20 70 47 72  ();..    if( pGr
a640: 6f 75 70 2d 3e 7a 4e 61 6d 65 20 29 7b 0a 20 20  oup->zName ){.  
a650: 20 20 20 20 70 47 72 6f 75 70 2d 3e 7a 4e 61 6d      pGroup->zNam
a660: 65 5b 70 47 72 6f 75 70 2d 3e 6e 4e 61 6d 65 5d  e[pGroup->nName]
a670: 20 3d 20 27 5c 30 27 3b 0a 20 20 20 20 20 20 54   = '\0';.      T
a680: 63 6c 5f 4c 69 73 74 4f 62 6a 41 70 70 65 6e 64  cl_ListObjAppend
a690: 45 6c 65 6d 65 6e 74 28 69 6e 74 65 72 70 2c 20  Element(interp, 
a6a0: 70 47 72 6f 75 70 54 65 72 6d 2c 0a 20 20 20 20  pGroupTerm,.    
a6b0: 20 20 20 20 20 20 54 63 6c 5f 4e 65 77 53 74 72        Tcl_NewStr
a6c0: 69 6e 67 4f 62 6a 28 70 47 72 6f 75 70 2d 3e 7a  ingObj(pGroup->z
a6d0: 4e 61 6d 65 2c 20 2d 31 29 29 3b 0a 20 20 20 20  Name, -1));.    
a6e0: 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 54 63 6c  }else{.      Tcl
a6f0: 5f 4c 69 73 74 4f 62 6a 41 70 70 65 6e 64 45 6c  _ListObjAppendEl
a700: 65 6d 65 6e 74 28 69 6e 74 65 72 70 2c 20 70 47  ement(interp, pG
a710: 72 6f 75 70 54 65 72 6d 2c 20 54 63 6c 5f 4e 65  roupTerm, Tcl_Ne
a720: 77 4f 62 6a 28 29 29 3b 0a 20 20 20 20 7d 0a 20  wObj());.    }. 
a730: 20 20 20 54 63 6c 5f 4c 69 73 74 4f 62 6a 41 70     Tcl_ListObjAp
a740: 70 65 6e 64 45 6c 65 6d 65 6e 74 28 69 6e 74 65  pendElement(inte
a750: 72 70 2c 20 70 47 72 6f 75 70 54 65 72 6d 2c 0a  rp, pGroupTerm,.
a760: 20 20 20 20 20 20 20 20 20 20 54 63 6c 5f 4e 65            Tcl_Ne
a770: 77 49 6e 74 4f 62 6a 28 70 47 72 6f 75 70 2d 3e  wIntObj(pGroup->
a780: 6e 4e 61 6d 65 29 29 3b 0a 20 20 20 20 54 63 6c  nName));.    Tcl
a790: 5f 4c 69 73 74 4f 62 6a 41 70 70 65 6e 64 45 6c  _ListObjAppendEl
a7a0: 65 6d 65 6e 74 28 69 6e 74 65 72 70 2c 20 70 47  ement(interp, pG
a7b0: 72 6f 75 70 54 65 72 6d 2c 0a 20 20 20 20 20 20  roupTerm,.      
a7c0: 20 20 20 20 54 63 6c 5f 4e 65 77 49 6e 74 4f 62      Tcl_NewIntOb
a7d0: 6a 28 70 47 72 6f 75 70 2d 3e 66 6c 61 67 73 29  j(pGroup->flags)
a7e0: 29 3b 0a 0a 20 20 20 20 2f 2a 20 63 6f 75 6e 74  );..    /* count
a7f0: 20 6e 75 6d 62 65 72 20 6f 66 20 63 68 75 6e 6b   number of chunk
a800: 73 20 77 69 74 68 20 6f 70 65 6e 20 68 61 6e 64  s with open hand
a810: 6c 65 73 20 2a 2f 0a 20 20 20 20 66 6f 72 28 69  les */.    for(i
a820: 3d 30 3b 20 69 3c 70 47 72 6f 75 70 2d 3e 6e 52  =0; i<pGroup->nR
a830: 65 61 6c 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 20  eal; i++){.     
a840: 20 69 66 28 20 70 47 72 6f 75 70 2d 3e 61 52 65   if( pGroup->aRe
a850: 61 6c 5b 69 5d 2e 70 21 3d 30 20 29 20 6e 43 68  al[i].p!=0 ) nCh
a860: 75 6e 6b 73 2b 2b 3b 0a 20 20 20 20 7d 0a 20 20  unks++;.    }.  
a870: 20 20 54 63 6c 5f 4c 69 73 74 4f 62 6a 41 70 70    Tcl_ListObjApp
a880: 65 6e 64 45 6c 65 6d 65 6e 74 28 69 6e 74 65 72  endElement(inter
a890: 70 2c 20 70 47 72 6f 75 70 54 65 72 6d 2c 0a 20  p, pGroupTerm,. 
a8a0: 20 20 20 20 20 20 20 20 20 54 63 6c 5f 4e 65 77           Tcl_New
a8b0: 49 6e 74 4f 62 6a 28 6e 43 68 75 6e 6b 73 29 29  IntObj(nChunks))
a8c0: 3b 0a 0a 20 20 20 20 54 63 6c 5f 4c 69 73 74 4f  ;..    Tcl_ListO
a8d0: 62 6a 41 70 70 65 6e 64 45 6c 65 6d 65 6e 74 28  bjAppendElement(
a8e0: 69 6e 74 65 72 70 2c 20 70 47 72 6f 75 70 54 65  interp, pGroupTe
a8f0: 72 6d 2c 0a 20 20 20 20 20 20 20 20 20 20 54 63  rm,.          Tc
a900: 6c 5f 4e 65 77 49 6e 74 4f 62 6a 28 70 47 72 6f  l_NewIntObj(pGro
a910: 75 70 2d 3e 73 7a 43 68 75 6e 6b 29 29 3b 0a 20  up->szChunk));. 
a920: 20 20 20 54 63 6c 5f 4c 69 73 74 4f 62 6a 41 70     Tcl_ListObjAp
a930: 70 65 6e 64 45 6c 65 6d 65 6e 74 28 69 6e 74 65  pendElement(inte
a940: 72 70 2c 20 70 47 72 6f 75 70 54 65 72 6d 2c 0a  rp, pGroupTerm,.
a950: 20 20 20 20 20 20 20 20 20 20 54 63 6c 5f 4e 65            Tcl_Ne
a960: 77 49 6e 74 4f 62 6a 28 70 47 72 6f 75 70 2d 3e  wIntObj(pGroup->
a970: 6e 52 65 61 6c 29 29 3b 0a 0a 20 20 20 20 54 63  nReal));..    Tc
a980: 6c 5f 4c 69 73 74 4f 62 6a 41 70 70 65 6e 64 45  l_ListObjAppendE
a990: 6c 65 6d 65 6e 74 28 69 6e 74 65 72 70 2c 20 70  lement(interp, p
a9a0: 52 65 73 75 6c 74 2c 20 70 47 72 6f 75 70 54 65  Result, pGroupTe
a9b0: 72 6d 29 3b 0a 20 20 7d 0a 20 20 6d 75 6c 74 69  rm);.  }.  multi
a9c0: 70 6c 65 78 4c 65 61 76 65 28 29 3b 0a 20 20 54  plexLeave();.  T
a9d0: 63 6c 5f 53 65 74 4f 62 6a 52 65 73 75 6c 74 28  cl_SetObjResult(
a9e0: 69 6e 74 65 72 70 2c 20 70 52 65 73 75 6c 74 29  interp, pResult)
a9f0: 3b 0a 20 20 72 65 74 75 72 6e 20 54 43 4c 5f 4f  ;.  return TCL_O
aa00: 4b 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54 63 6c 63  K;.}../*.** Tclc
aa10: 6d 64 3a 20 74 65 73 74 5f 6d 75 6c 74 69 70 6c  md: test_multipl
aa20: 65 78 5f 63 6f 6e 74 72 6f 6c 20 48 41 4e 44 4c  ex_control HANDL
aa30: 45 20 44 42 4e 41 4d 45 20 53 55 42 2d 43 4f 4d  E DBNAME SUB-COM
aa40: 4d 41 4e 44 20 3f 49 4e 54 2d 56 41 4c 55 45 3f  MAND ?INT-VALUE?
aa50: 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 74  .*/.static int t
aa60: 65 73 74 5f 6d 75 6c 74 69 70 6c 65 78 5f 63 6f  est_multiplex_co
aa70: 6e 74 72 6f 6c 28 0a 20 20 43 6c 69 65 6e 74 44  ntrol(.  ClientD
aa80: 61 74 61 20 63 64 2c 0a 20 20 54 63 6c 5f 49 6e  ata cd,.  Tcl_In
aa90: 74 65 72 70 20 2a 69 6e 74 65 72 70 2c 0a 20 20  terp *interp,.  
aaa0: 69 6e 74 20 6f 62 6a 63 2c 0a 20 20 54 63 6c 5f  int objc,.  Tcl_
aab0: 4f 62 6a 20 2a 43 4f 4e 53 54 20 6f 62 6a 76 5b  Obj *CONST objv[
aac0: 5d 0a 29 7b 0a 20 20 69 6e 74 20 72 63 3b 20 20  ].){.  int rc;  
aad0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
aae0: 20 20 20 20 20 20 20 2f 2a 20 52 65 74 75 72 6e         /* Return
aaf0: 20 63 6f 64 65 20 66 72 6f 6d 20 66 69 6c 65 5f   code from file_
ab00: 63 6f 6e 74 72 6f 6c 28 29 20 2a 2f 0a 20 20 69  control() */.  i
ab10: 6e 74 20 69 64 78 3b 20 20 20 20 20 20 20 20 20  nt idx;         
ab20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
ab30: 2a 20 49 6e 64 65 78 20 69 6e 20 61 53 75 62 5b  * Index in aSub[
ab40: 5d 20 2a 2f 0a 20 20 54 63 6c 5f 43 6d 64 49 6e  ] */.  Tcl_CmdIn
ab50: 66 6f 20 63 6d 64 49 6e 66 6f 3b 20 20 20 20 20  fo cmdInfo;     
ab60: 20 20 20 20 20 20 20 2f 2a 20 43 6f 6d 6d 61 6e         /* Comman
ab70: 64 20 69 6e 66 6f 20 73 74 72 75 63 74 75 72 65  d info structure
ab80: 20 66 6f 72 20 48 41 4e 44 4c 45 20 2a 2f 0a 20   for HANDLE */. 
ab90: 20 73 71 6c 69 74 65 33 20 2a 64 62 3b 20 20 20   sqlite3 *db;   
aba0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
abb0: 20 2f 2a 20 55 6e 64 65 72 6c 79 69 6e 67 20 64   /* Underlying d
abc0: 62 20 68 61 6e 64 6c 65 20 66 6f 72 20 48 41 4e  b handle for HAN
abd0: 44 4c 45 20 2a 2f 0a 20 20 69 6e 74 20 69 56 61  DLE */.  int iVa
abe0: 6c 75 65 20 3d 20 30 3b 0a 20 20 76 6f 69 64 20  lue = 0;.  void 
abf0: 2a 70 41 72 67 20 3d 20 30 3b 0a 0a 20 20 73 74  *pArg = 0;..  st
ac00: 72 75 63 74 20 53 75 62 43 6f 6d 6d 61 6e 64 20  ruct SubCommand 
ac10: 7b 0a 20 20 20 20 63 6f 6e 73 74 20 63 68 61 72  {.    const char
ac20: 20 2a 7a 4e 61 6d 65 3b 0a 20 20 20 20 69 6e 74   *zName;.    int
ac30: 20 6f 70 3b 0a 20 20 20 20 69 6e 74 20 61 72 67   op;.    int arg
ac40: 74 79 70 65 3b 0a 20 20 7d 20 61 53 75 62 5b 5d  type;.  } aSub[]
ac50: 20 3d 20 7b 0a 20 20 20 20 7b 20 22 65 6e 61 62   = {.    { "enab
ac60: 6c 65 22 2c 20 20 20 20 20 20 20 4d 55 4c 54 49  le",       MULTI
ac70: 50 4c 45 58 5f 43 54 52 4c 5f 45 4e 41 42 4c 45  PLEX_CTRL_ENABLE
ac80: 2c 20 20 20 20 20 20 20 20 20 20 20 31 20 7d 2c  ,           1 },
ac90: 0a 20 20 20 20 7b 20 22 63 68 75 6e 6b 5f 73 69  .    { "chunk_si
aca0: 7a 65 22 2c 20 20 20 4d 55 4c 54 49 50 4c 45 58  ze",   MULTIPLEX
acb0: 5f 43 54 52 4c 5f 53 45 54 5f 43 48 55 4e 4b 5f  _CTRL_SET_CHUNK_
acc0: 53 49 5a 45 2c 20 20 20 31 20 7d 2c 0a 20 20 20  SIZE,   1 },.   
acd0: 20 7b 20 22 6d 61 78 5f 63 68 75 6e 6b 73 22 2c   { "max_chunks",
ace0: 20 20 20 4d 55 4c 54 49 50 4c 45 58 5f 43 54 52     MULTIPLEX_CTR
acf0: 4c 5f 53 45 54 5f 4d 41 58 5f 43 48 55 4e 4b 53  L_SET_MAX_CHUNKS
ad00: 2c 20 20 20 31 20 7d 2c 0a 20 20 20 20 7b 20 30  ,   1 },.    { 0
ad10: 2c 20 30 2c 20 30 20 7d 0a 20 20 7d 3b 0a 0a 20  , 0, 0 }.  };.. 
ad20: 20 69 66 28 20 6f 62 6a 63 21 3d 35 20 29 7b 0a   if( objc!=5 ){.
ad30: 20 20 20 20 54 63 6c 5f 57 72 6f 6e 67 4e 75 6d      Tcl_WrongNum
ad40: 41 72 67 73 28 69 6e 74 65 72 70 2c 20 31 2c 20  Args(interp, 1, 
ad50: 6f 62 6a 76 2c 20 22 48 41 4e 44 4c 45 20 44 42  objv, "HANDLE DB
ad60: 4e 41 4d 45 20 53 55 42 2d 43 4f 4d 4d 41 4e 44  NAME SUB-COMMAND
ad70: 20 49 4e 54 2d 56 41 4c 55 45 22 29 3b 0a 20 20   INT-VALUE");.  
ad80: 20 20 72 65 74 75 72 6e 20 54 43 4c 5f 45 52 52    return TCL_ERR
ad90: 4f 52 3b 0a 20 20 7d 0a 0a 20 20 69 66 28 20 30  OR;.  }..  if( 0
ada0: 3d 3d 54 63 6c 5f 47 65 74 43 6f 6d 6d 61 6e 64  ==Tcl_GetCommand
adb0: 49 6e 66 6f 28 69 6e 74 65 72 70 2c 20 54 63 6c  Info(interp, Tcl
adc0: 5f 47 65 74 53 74 72 69 6e 67 28 6f 62 6a 76 5b  _GetString(objv[
add0: 31 5d 29 2c 20 26 63 6d 64 49 6e 66 6f 29 20 29  1]), &cmdInfo) )
ade0: 7b 0a 20 20 20 20 54 63 6c 5f 41 70 70 65 6e 64  {.    Tcl_Append
adf0: 52 65 73 75 6c 74 28 69 6e 74 65 72 70 2c 20 22  Result(interp, "
ae00: 65 78 70 65 63 74 65 64 20 64 61 74 61 62 61 73  expected databas
ae10: 65 20 68 61 6e 64 6c 65 2c 20 67 6f 74 20 5c 22  e handle, got \"
ae20: 22 2c 20 30 29 3b 0a 20 20 20 20 54 63 6c 5f 41  ", 0);.    Tcl_A
ae30: 70 70 65 6e 64 52 65 73 75 6c 74 28 69 6e 74 65  ppendResult(inte
ae40: 72 70 2c 20 54 63 6c 5f 47 65 74 53 74 72 69 6e  rp, Tcl_GetStrin
ae50: 67 28 6f 62 6a 76 5b 31 5d 29 2c 20 22 5c 22 22  g(objv[1]), "\""
ae60: 2c 20 30 29 3b 0a 20 20 20 20 72 65 74 75 72 6e  , 0);.    return
ae70: 20 54 43 4c 5f 45 52 52 4f 52 3b 0a 20 20 7d 65   TCL_ERROR;.  }e
ae80: 6c 73 65 7b 0a 20 20 20 20 64 62 20 3d 20 2a 28  lse{.    db = *(
ae90: 73 71 6c 69 74 65 33 20 2a 2a 29 63 6d 64 49 6e  sqlite3 **)cmdIn
aea0: 66 6f 2e 6f 62 6a 43 6c 69 65 6e 74 44 61 74 61  fo.objClientData
aeb0: 3b 0a 20 20 7d 0a 0a 20 20 72 63 20 3d 20 54 63  ;.  }..  rc = Tc
aec0: 6c 5f 47 65 74 49 6e 64 65 78 46 72 6f 6d 4f 62  l_GetIndexFromOb
aed0: 6a 53 74 72 75 63 74 28 0a 20 20 20 20 20 20 69  jStruct(.      i
aee0: 6e 74 65 72 70 2c 20 6f 62 6a 76 5b 33 5d 2c 20  nterp, objv[3], 
aef0: 61 53 75 62 2c 20 73 69 7a 65 6f 66 28 61 53 75  aSub, sizeof(aSu
af00: 62 5b 30 5d 29 2c 20 22 73 75 62 2d 63 6f 6d 6d  b[0]), "sub-comm
af10: 61 6e 64 22 2c 20 30 2c 20 26 69 64 78 0a 20 20  and", 0, &idx.  
af20: 29 3b 0a 20 20 69 66 28 20 72 63 21 3d 54 43 4c  );.  if( rc!=TCL
af30: 5f 4f 4b 20 29 20 72 65 74 75 72 6e 20 72 63 3b  _OK ) return rc;
af40: 0a 0a 20 20 73 77 69 74 63 68 28 20 61 53 75 62  ..  switch( aSub
af50: 5b 69 64 78 5d 2e 61 72 67 74 79 70 65 20 29 7b  [idx].argtype ){
af60: 0a 20 20 20 20 63 61 73 65 20 31 3a 0a 20 20 20  .    case 1:.   
af70: 20 20 20 69 66 28 20 54 63 6c 5f 47 65 74 49 6e     if( Tcl_GetIn
af80: 74 46 72 6f 6d 4f 62 6a 28 69 6e 74 65 72 70 2c  tFromObj(interp,
af90: 20 6f 62 6a 76 5b 34 5d 2c 20 26 69 56 61 6c 75   objv[4], &iValu
afa0: 65 29 20 29 7b 0a 20 20 20 20 20 20 20 20 72 65  e) ){.        re
afb0: 74 75 72 6e 20 54 43 4c 5f 45 52 52 4f 52 3b 0a  turn TCL_ERROR;.
afc0: 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 70 41        }.      pA
afd0: 72 67 20 3d 20 28 76 6f 69 64 20 2a 29 26 69 56  rg = (void *)&iV
afe0: 61 6c 75 65 3b 0a 20 20 20 20 20 20 62 72 65 61  alue;.      brea
aff0: 6b 3b 0a 20 20 20 20 64 65 66 61 75 6c 74 3a 0a  k;.    default:.
b000: 20 20 20 20 20 20 54 63 6c 5f 57 72 6f 6e 67 4e        Tcl_WrongN
b010: 75 6d 41 72 67 73 28 69 6e 74 65 72 70 2c 20 34  umArgs(interp, 4
b020: 2c 20 6f 62 6a 76 2c 20 22 53 55 42 2d 43 4f 4d  , objv, "SUB-COM
b030: 4d 41 4e 44 22 29 3b 0a 20 20 20 20 20 20 72 65  MAND");.      re
b040: 74 75 72 6e 20 54 43 4c 5f 45 52 52 4f 52 3b 0a  turn TCL_ERROR;.
b050: 20 20 7d 0a 0a 20 20 72 63 20 3d 20 73 71 6c 69    }..  rc = sqli
b060: 74 65 33 5f 66 69 6c 65 5f 63 6f 6e 74 72 6f 6c  te3_file_control
b070: 28 64 62 2c 20 54 63 6c 5f 47 65 74 53 74 72 69  (db, Tcl_GetStri
b080: 6e 67 28 6f 62 6a 76 5b 32 5d 29 2c 20 61 53 75  ng(objv[2]), aSu
b090: 62 5b 69 64 78 5d 2e 6f 70 2c 20 70 41 72 67 29  b[idx].op, pArg)
b0a0: 3b 0a 20 20 54 63 6c 5f 53 65 74 52 65 73 75 6c  ;.  Tcl_SetResul
b0b0: 74 28 69 6e 74 65 72 70 2c 20 28 63 68 61 72 20  t(interp, (char 
b0c0: 2a 29 73 71 6c 69 74 65 33 54 65 73 74 45 72 72  *)sqlite3TestErr
b0d0: 6f 72 4e 61 6d 65 28 72 63 29 2c 20 54 43 4c 5f  orName(rc), TCL_
b0e0: 53 54 41 54 49 43 29 3b 0a 20 20 72 65 74 75 72  STATIC);.  retur
b0f0: 6e 20 28 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b  n (rc==SQLITE_OK
b100: 29 20 3f 20 54 43 4c 5f 4f 4b 20 3a 20 54 43 4c  ) ? TCL_OK : TCL
b110: 5f 45 52 52 4f 52 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a  _ERROR;.}../*.**
b120: 20 54 68 69 73 20 72 6f 75 74 69 6e 65 20 72 65   This routine re
b130: 67 69 73 74 65 72 73 20 74 68 65 20 63 75 73 74  gisters the cust
b140: 6f 6d 20 54 43 4c 20 63 6f 6d 6d 61 6e 64 73 20  om TCL commands 
b150: 64 65 66 69 6e 65 64 20 69 6e 20 74 68 69 73 0a  defined in this.
b160: 2a 2a 20 6d 6f 64 75 6c 65 2e 20 20 54 68 69 73  ** module.  This
b170: 20 73 68 6f 75 6c 64 20 62 65 20 74 68 65 20 6f   should be the o
b180: 6e 6c 79 20 70 72 6f 63 65 64 75 72 65 20 76 69  nly procedure vi
b190: 73 69 62 6c 65 20 66 72 6f 6d 20 6f 75 74 73 69  sible from outsi
b1a0: 64 65 0a 2a 2a 20 6f 66 20 74 68 69 73 20 6d 6f  de.** of this mo
b1b0: 64 75 6c 65 2e 0a 2a 2f 0a 69 6e 74 20 53 71 6c  dule..*/.int Sql
b1c0: 69 74 65 6d 75 6c 74 69 70 6c 65 78 5f 49 6e 69  itemultiplex_Ini
b1d0: 74 28 54 63 6c 5f 49 6e 74 65 72 70 20 2a 69 6e  t(Tcl_Interp *in
b1e0: 74 65 72 70 29 7b 0a 20 20 73 74 61 74 69 63 20  terp){.  static 
b1f0: 73 74 72 75 63 74 20 7b 0a 20 20 20 20 20 63 68  struct {.     ch
b200: 61 72 20 2a 7a 4e 61 6d 65 3b 0a 20 20 20 20 20  ar *zName;.     
b210: 54 63 6c 5f 4f 62 6a 43 6d 64 50 72 6f 63 20 2a  Tcl_ObjCmdProc *
b220: 78 50 72 6f 63 3b 0a 20 20 7d 20 61 43 6d 64 5b  xProc;.  } aCmd[
b230: 5d 20 3d 20 7b 0a 20 20 20 20 7b 20 22 73 71 6c  ] = {.    { "sql
b240: 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 69  ite3_multiplex_i
b250: 6e 69 74 69 61 6c 69 7a 65 22 2c 20 74 65 73 74  nitialize", test
b260: 5f 6d 75 6c 74 69 70 6c 65 78 5f 69 6e 69 74 69  _multiplex_initi
b270: 61 6c 69 7a 65 20 7d 2c 0a 20 20 20 20 7b 20 22  alize },.    { "
b280: 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65  sqlite3_multiple
b290: 78 5f 73 68 75 74 64 6f 77 6e 22 2c 20 74 65 73  x_shutdown", tes
b2a0: 74 5f 6d 75 6c 74 69 70 6c 65 78 5f 73 68 75 74  t_multiplex_shut
b2b0: 64 6f 77 6e 20 7d 2c 0a 20 20 20 20 7b 20 22 73  down },.    { "s
b2c0: 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78  qlite3_multiplex
b2d0: 5f 64 75 6d 70 22 2c 20 74 65 73 74 5f 6d 75 6c  _dump", test_mul
b2e0: 74 69 70 6c 65 78 5f 64 75 6d 70 20 7d 2c 0a 20  tiplex_dump },. 
b2f0: 20 20 20 7b 20 22 73 71 6c 69 74 65 33 5f 6d 75     { "sqlite3_mu
b300: 6c 74 69 70 6c 65 78 5f 63 6f 6e 74 72 6f 6c 22  ltiplex_control"
b310: 2c 20 74 65 73 74 5f 6d 75 6c 74 69 70 6c 65 78  , test_multiplex
b320: 5f 63 6f 6e 74 72 6f 6c 20 7d 2c 0a 20 20 7d 3b  _control },.  };
b330: 0a 20 20 69 6e 74 20 69 3b 0a 0a 20 20 66 6f 72  .  int i;..  for
b340: 28 69 3d 30 3b 20 69 3c 73 69 7a 65 6f 66 28 61  (i=0; i<sizeof(a
b350: 43 6d 64 29 2f 73 69 7a 65 6f 66 28 61 43 6d 64  Cmd)/sizeof(aCmd
b360: 5b 30 5d 29 3b 20 69 2b 2b 29 7b 0a 20 20 20 20  [0]); i++){.    
b370: 54 63 6c 5f 43 72 65 61 74 65 4f 62 6a 43 6f 6d  Tcl_CreateObjCom
b380: 6d 61 6e 64 28 69 6e 74 65 72 70 2c 20 61 43 6d  mand(interp, aCm
b390: 64 5b 69 5d 2e 7a 4e 61 6d 65 2c 20 61 43 6d 64  d[i].zName, aCmd
b3a0: 5b 69 5d 2e 78 50 72 6f 63 2c 20 30 2c 20 30 29  [i].xProc, 0, 0)
b3b0: 3b 0a 20 20 7d 0a 0a 20 20 72 65 74 75 72 6e 20  ;.  }..  return 
b3c0: 54 43 4c 5f 4f 4b 3b 0a 7d 0a 23 65 6e 64 69 66  TCL_OK;.}.#endif
b3d0: 0a                                               .