/ Hex Artifact Content
Login

Artifact 0b3111a8c1b11963b2ca17a4b47219a5942bc9c0:


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 65 72 61 74 65 6c 79 20 68 65  ed seperately 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 2a 72 63 20 3d 20 53 51 4c 49 54 45 5f 46 55   *rc = SQLITE_FU
30e0: 4c 4c 3b 0a 20 20 20 20 72 65 74 75 72 6e 20 30  LL;.    return 0
30f0: 3b 0a 20 20 7d 0a 23 65 6e 64 69 66 0a 0a 20 20  ;.  }.#endif..  
3100: 2a 72 63 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53  *rc = multiplexS
3110: 75 62 46 69 6c 65 6e 61 6d 65 28 70 47 72 6f 75  ubFilename(pGrou
3120: 70 2c 20 69 43 68 75 6e 6b 29 3b 0a 20 20 69 66  p, iChunk);.  if
3130: 28 20 28 2a 72 63 29 3d 3d 53 51 4c 49 54 45 5f  ( (*rc)==SQLITE_
3140: 4f 4b 20 26 26 20 28 70 53 75 62 4f 70 65 6e 20  OK && (pSubOpen 
3150: 3d 20 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c 5b  = pGroup->aReal[
3160: 69 43 68 75 6e 6b 5d 2e 70 29 3d 3d 30 20 29 7b  iChunk].p)==0 ){
3170: 0a 20 20 20 20 69 6e 74 20 66 6c 61 67 73 2c 20  .    int flags, 
3180: 62 45 78 69 73 74 73 3b 0a 20 20 20 20 66 6c 61  bExists;.    fla
3190: 67 73 20 3d 20 70 47 72 6f 75 70 2d 3e 66 6c 61  gs = pGroup->fla
31a0: 67 73 3b 0a 20 20 20 20 69 66 28 20 63 72 65 61  gs;.    if( crea
31b0: 74 65 46 6c 61 67 20 29 7b 0a 20 20 20 20 20 20  teFlag ){.      
31c0: 66 6c 61 67 73 20 7c 3d 20 53 51 4c 49 54 45 5f  flags |= SQLITE_
31d0: 4f 50 45 4e 5f 43 52 45 41 54 45 3b 0a 20 20 20  OPEN_CREATE;.   
31e0: 20 7d 65 6c 73 65 20 69 66 28 20 69 43 68 75 6e   }else if( iChun
31f0: 6b 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 2f 2a  k==0 ){.      /*
3200: 20 46 61 6c 6c 20 74 68 72 6f 75 67 68 20 2a 2f   Fall through */
3210: 0a 20 20 20 20 7d 65 6c 73 65 20 69 66 28 20 70  .    }else if( p
3220: 47 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68  Group->aReal[iCh
3230: 75 6e 6b 5d 2e 7a 3d 3d 30 20 29 7b 0a 20 20 20  unk].z==0 ){.   
3240: 20 20 20 72 65 74 75 72 6e 20 30 3b 0a 20 20 20     return 0;.   
3250: 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 2a 72   }else{.      *r
3260: 63 20 3d 20 70 4f 72 69 67 56 66 73 2d 3e 78 41  c = pOrigVfs->xA
3270: 63 63 65 73 73 28 70 4f 72 69 67 56 66 73 2c 20  ccess(pOrigVfs, 
3280: 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43  pGroup->aReal[iC
3290: 68 75 6e 6b 5d 2e 7a 2c 0a 20 20 20 20 20 20 20  hunk].z,.       
32a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
32b0: 20 20 20 20 20 20 20 53 51 4c 49 54 45 5f 41 43         SQLITE_AC
32c0: 43 45 53 53 5f 45 58 49 53 54 53 2c 20 26 62 45  CESS_EXISTS, &bE
32d0: 78 69 73 74 73 29 3b 0a 20 20 20 20 20 20 69 66  xists);.      if
32e0: 28 20 2a 72 63 20 7c 7c 20 21 62 45 78 69 73 74  ( *rc || !bExist
32f0: 73 20 29 20 72 65 74 75 72 6e 20 30 3b 0a 20 20  s ) return 0;.  
3300: 20 20 20 20 66 6c 61 67 73 20 26 3d 20 7e 53 51      flags &= ~SQ
3310: 4c 49 54 45 5f 4f 50 45 4e 5f 43 52 45 41 54 45  LITE_OPEN_CREATE
3320: 3b 0a 20 20 20 20 7d 0a 20 20 20 20 70 53 75 62  ;.    }.    pSub
3330: 4f 70 65 6e 20 3d 20 73 71 6c 69 74 65 33 5f 6d  Open = sqlite3_m
3340: 61 6c 6c 6f 63 28 20 70 4f 72 69 67 56 66 73 2d  alloc( pOrigVfs-
3350: 3e 73 7a 4f 73 46 69 6c 65 20 29 3b 0a 20 20 20  >szOsFile );.   
3360: 20 69 66 28 20 70 53 75 62 4f 70 65 6e 3d 3d 30   if( pSubOpen==0
3370: 20 29 7b 0a 20 20 20 20 20 20 2a 72 63 20 3d 20   ){.      *rc = 
3380: 53 51 4c 49 54 45 5f 49 4f 45 52 52 5f 4e 4f 4d  SQLITE_IOERR_NOM
3390: 45 4d 3b 0a 20 20 20 20 20 20 72 65 74 75 72 6e  EM;.      return
33a0: 20 30 3b 0a 20 20 20 20 7d 0a 20 20 20 20 70 47   0;.    }.    pG
33b0: 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68 75  roup->aReal[iChu
33c0: 6e 6b 5d 2e 70 20 3d 20 70 53 75 62 4f 70 65 6e  nk].p = pSubOpen
33d0: 3b 0a 20 20 20 20 2a 72 63 20 3d 20 70 4f 72 69  ;.    *rc = pOri
33e0: 67 56 66 73 2d 3e 78 4f 70 65 6e 28 70 4f 72 69  gVfs->xOpen(pOri
33f0: 67 56 66 73 2c 20 70 47 72 6f 75 70 2d 3e 61 52  gVfs, pGroup->aR
3400: 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e 7a 2c 20 70  eal[iChunk].z, p
3410: 53 75 62 4f 70 65 6e 2c 0a 20 20 20 20 20 20 20  SubOpen,.       
3420: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3430: 20 20 20 66 6c 61 67 73 2c 20 70 4f 75 74 46 6c     flags, pOutFl
3440: 61 67 73 29 3b 0a 20 20 20 20 69 66 28 20 28 2a  ags);.    if( (*
3450: 72 63 29 21 3d 53 51 4c 49 54 45 5f 4f 4b 20 29  rc)!=SQLITE_OK )
3460: 7b 0a 20 20 20 20 20 20 73 71 6c 69 74 65 33 5f  {.      sqlite3_
3470: 66 72 65 65 28 70 53 75 62 4f 70 65 6e 29 3b 0a  free(pSubOpen);.
3480: 20 20 20 20 20 20 70 47 72 6f 75 70 2d 3e 61 52        pGroup->aR
3490: 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e 70 20 3d 20  eal[iChunk].p = 
34a0: 30 3b 0a 20 20 20 20 20 20 72 65 74 75 72 6e 20  0;.      return 
34b0: 30 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20 72  0;.    }.  }.  r
34c0: 65 74 75 72 6e 20 70 53 75 62 4f 70 65 6e 3b 0a  eturn pSubOpen;.
34d0: 7d 0a 0a 2f 2a 0a 2a 2a 20 52 65 74 75 72 6e 20  }../*.** Return 
34e0: 74 68 65 20 73 69 7a 65 2c 20 69 6e 20 62 79 74  the size, in byt
34f0: 65 73 2c 20 6f 66 20 63 68 75 6e 6b 20 6e 75 6d  es, of chunk num
3500: 62 65 72 20 69 43 68 75 6e 6b 2e 20 20 49 66 20  ber iChunk.  If 
3510: 74 68 61 74 20 63 68 75 6e 6b 0a 2a 2a 20 64 6f  that chunk.** do
3520: 65 73 20 6e 6f 74 20 65 78 69 73 74 2c 20 74 68  es not exist, th
3530: 65 6e 20 72 65 74 75 72 6e 20 30 2e 20 20 54 68  en return 0.  Th
3540: 69 73 20 66 75 6e 63 74 69 6f 6e 20 64 6f 65 73  is function does
3550: 20 6e 6f 74 20 64 69 73 74 69 6e 67 69 73 68 20   not distingish 
3560: 62 65 74 77 65 65 6e 0a 2a 2a 20 6e 6f 6e 2d 65  between.** non-e
3570: 78 69 73 74 61 6e 74 20 66 69 6c 65 73 20 61 6e  xistant files an
3580: 64 20 7a 65 72 6f 2d 6c 65 6e 67 74 68 20 66 69  d zero-length fi
3590: 6c 65 73 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 73  les..*/.static s
35a0: 71 6c 69 74 65 33 5f 69 6e 74 36 34 20 6d 75 6c  qlite3_int64 mul
35b0: 74 69 70 6c 65 78 53 75 62 53 69 7a 65 28 0a 20  tiplexSubSize(. 
35c0: 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 20   multiplexGroup 
35d0: 2a 70 47 72 6f 75 70 2c 20 20 20 20 2f 2a 20 54  *pGroup,    /* T
35e0: 68 65 20 6d 75 6c 74 69 70 6c 65 78 6f 72 20 67  he multiplexor g
35f0: 72 6f 75 70 20 2a 2f 0a 20 20 69 6e 74 20 69 43  roup */.  int iC
3600: 68 75 6e 6b 2c 20 20 20 20 20 20 20 20 20 20 20  hunk,           
3610: 20 20 20 20 20 2f 2a 20 57 68 69 63 68 20 63 68       /* Which ch
3620: 75 6e 6b 20 74 6f 20 6f 70 65 6e 2e 20 20 30 3d  unk to open.  0=
3630: 3d 6f 72 69 67 69 6e 61 6c 20 66 69 6c 65 20 2a  =original file *
3640: 2f 0a 20 20 69 6e 74 20 2a 72 63 20 20 20 20 20  /.  int *rc     
3650: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
3660: 2a 20 52 65 73 75 6c 74 20 63 6f 64 65 20 69 6e  * Result code in
3670: 20 61 6e 64 20 6f 75 74 20 2a 2f 0a 29 7b 0a 20   and out */.){. 
3680: 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70   sqlite3_file *p
3690: 53 75 62 3b 0a 20 20 73 71 6c 69 74 65 33 5f 69  Sub;.  sqlite3_i
36a0: 6e 74 36 34 20 73 7a 20 3d 20 30 3b 0a 0a 20 20  nt64 sz = 0;..  
36b0: 69 66 28 20 2a 72 63 20 29 20 72 65 74 75 72 6e  if( *rc ) return
36c0: 20 30 3b 0a 20 20 70 53 75 62 20 3d 20 6d 75 6c   0;.  pSub = mul
36d0: 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28 70 47  tiplexSubOpen(pG
36e0: 72 6f 75 70 2c 20 69 43 68 75 6e 6b 2c 20 72 63  roup, iChunk, rc
36f0: 2c 20 4e 55 4c 4c 2c 20 30 29 3b 0a 20 20 69 66  , NULL, 0);.  if
3700: 28 20 70 53 75 62 3d 3d 30 20 29 20 72 65 74 75  ( pSub==0 ) retu
3710: 72 6e 20 30 3b 0a 20 20 2a 72 63 20 3d 20 70 53  rn 0;.  *rc = pS
3720: 75 62 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e 78 46  ub->pMethods->xF
3730: 69 6c 65 53 69 7a 65 28 70 53 75 62 2c 20 26 73  ileSize(pSub, &s
3740: 7a 29 3b 0a 20 20 72 65 74 75 72 6e 20 73 7a 3b  z);.  return sz;
3750: 0a 7d 20 20 20 20 0a 0a 2f 2a 0a 2a 2a 20 54 68  .}    ../*.** Th
3760: 69 73 20 69 73 20 74 68 65 20 69 6d 70 6c 65 6d  is is the implem
3770: 65 6e 74 61 74 69 6f 6e 20 6f 66 20 74 68 65 20  entation of the 
3780: 6d 75 6c 74 69 70 6c 65 78 5f 63 6f 6e 74 72 6f  multiplex_contro
3790: 6c 28 29 20 53 51 4c 20 66 75 6e 63 74 69 6f 6e  l() SQL function
37a0: 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 76 6f 69 64  ..*/.static void
37b0: 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 74 72 6f   multiplexContro
37c0: 6c 46 75 6e 63 28 0a 20 20 73 71 6c 69 74 65 33  lFunc(.  sqlite3
37d0: 5f 63 6f 6e 74 65 78 74 20 2a 63 6f 6e 74 65 78  _context *contex
37e0: 74 2c 0a 20 20 69 6e 74 20 61 72 67 63 2c 0a 20  t,.  int argc,. 
37f0: 20 73 71 6c 69 74 65 33 5f 76 61 6c 75 65 20 2a   sqlite3_value *
3800: 2a 61 72 67 76 0a 29 7b 0a 20 20 69 6e 74 20 72  *argv.){.  int r
3810: 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20  c = SQLITE_OK;. 
3820: 20 73 71 6c 69 74 65 33 20 2a 64 62 20 3d 20 73   sqlite3 *db = s
3830: 71 6c 69 74 65 33 5f 63 6f 6e 74 65 78 74 5f 64  qlite3_context_d
3840: 62 5f 68 61 6e 64 6c 65 28 63 6f 6e 74 65 78 74  b_handle(context
3850: 29 3b 0a 20 20 69 6e 74 20 6f 70 3b 0a 20 20 69  );.  int op;.  i
3860: 6e 74 20 69 56 61 6c 3b 0a 0a 20 20 69 66 28 20  nt iVal;..  if( 
3870: 21 64 62 20 7c 7c 20 61 72 67 63 21 3d 32 20 29  !db || argc!=2 )
3880: 7b 20 0a 20 20 20 20 72 63 20 3d 20 53 51 4c 49  { .    rc = SQLI
3890: 54 45 5f 45 52 52 4f 52 3b 20 0a 20 20 7d 65 6c  TE_ERROR; .  }el
38a0: 73 65 7b 0a 20 20 20 20 2f 2a 20 65 78 74 72 61  se{.    /* extra
38b0: 63 74 20 70 61 72 61 6d 73 20 2a 2f 0a 20 20 20  ct params */.   
38c0: 20 6f 70 20 3d 20 73 71 6c 69 74 65 33 5f 76 61   op = sqlite3_va
38d0: 6c 75 65 5f 69 6e 74 28 61 72 67 76 5b 30 5d 29  lue_int(argv[0])
38e0: 3b 0a 20 20 20 20 69 56 61 6c 20 3d 20 73 71 6c  ;.    iVal = sql
38f0: 69 74 65 33 5f 76 61 6c 75 65 5f 69 6e 74 28 61  ite3_value_int(a
3900: 72 67 76 5b 31 5d 29 3b 0a 20 20 20 20 2f 2a 20  rgv[1]);.    /* 
3910: 6d 61 70 20 66 75 6e 63 74 69 6f 6e 20 6f 70 20  map function op 
3920: 74 6f 20 66 69 6c 65 5f 63 6f 6e 74 72 6f 6c 20  to file_control 
3930: 6f 70 20 2a 2f 0a 20 20 20 20 73 77 69 74 63 68  op */.    switch
3940: 28 20 6f 70 20 29 7b 0a 20 20 20 20 20 20 63 61  ( op ){.      ca
3950: 73 65 20 31 3a 20 0a 20 20 20 20 20 20 20 20 6f  se 1: .        o
3960: 70 20 3d 20 4d 55 4c 54 49 50 4c 45 58 5f 43 54  p = MULTIPLEX_CT
3970: 52 4c 5f 45 4e 41 42 4c 45 3b 20 0a 20 20 20 20  RL_ENABLE; .    
3980: 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20      break;.     
3990: 20 63 61 73 65 20 32 3a 20 0a 20 20 20 20 20 20   case 2: .      
39a0: 20 20 6f 70 20 3d 20 4d 55 4c 54 49 50 4c 45 58    op = MULTIPLEX
39b0: 5f 43 54 52 4c 5f 53 45 54 5f 43 48 55 4e 4b 5f  _CTRL_SET_CHUNK_
39c0: 53 49 5a 45 3b 20 0a 20 20 20 20 20 20 20 20 62  SIZE; .        b
39d0: 72 65 61 6b 3b 0a 20 20 20 20 20 20 63 61 73 65  reak;.      case
39e0: 20 33 3a 20 0a 20 20 20 20 20 20 20 20 6f 70 20   3: .        op 
39f0: 3d 20 4d 55 4c 54 49 50 4c 45 58 5f 43 54 52 4c  = MULTIPLEX_CTRL
3a00: 5f 53 45 54 5f 4d 41 58 5f 43 48 55 4e 4b 53 3b  _SET_MAX_CHUNKS;
3a10: 20 0a 20 20 20 20 20 20 20 20 62 72 65 61 6b 3b   .        break;
3a20: 0a 20 20 20 20 20 20 64 65 66 61 75 6c 74 3a 0a  .      default:.
3a30: 20 20 20 20 20 20 20 20 72 63 20 3d 20 53 51 4c          rc = SQL
3a40: 49 54 45 5f 4e 4f 54 46 4f 55 4e 44 3b 0a 20 20  ITE_NOTFOUND;.  
3a50: 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20        break;.   
3a60: 20 7d 0a 20 20 7d 0a 20 20 69 66 28 20 72 63 3d   }.  }.  if( rc=
3a70: 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20  =SQLITE_OK ){.  
3a80: 20 20 72 63 20 3d 20 73 71 6c 69 74 65 33 5f 66    rc = sqlite3_f
3a90: 69 6c 65 5f 63 6f 6e 74 72 6f 6c 28 64 62 2c 20  ile_control(db, 
3aa0: 30 2c 20 6f 70 2c 20 26 69 56 61 6c 29 3b 0a 20  0, op, &iVal);. 
3ab0: 20 7d 0a 20 20 73 71 6c 69 74 65 33 5f 72 65 73   }.  sqlite3_res
3ac0: 75 6c 74 5f 65 72 72 6f 72 5f 63 6f 64 65 28 63  ult_error_code(c
3ad0: 6f 6e 74 65 78 74 2c 20 72 63 29 3b 0a 7d 0a 0a  ontext, rc);.}..
3ae0: 2f 2a 0a 2a 2a 20 54 68 69 73 20 69 73 20 74 68  /*.** This is th
3af0: 65 20 65 6e 74 72 79 20 70 6f 69 6e 74 20 74 6f  e entry point to
3b00: 20 72 65 67 69 73 74 65 72 20 74 68 65 20 61 75   register the au
3b10: 74 6f 2d 65 78 74 65 6e 73 69 6f 6e 20 66 6f 72  to-extension for
3b20: 20 74 68 65 20 0a 2a 2a 20 6d 75 6c 74 69 70 6c   the .** multipl
3b30: 65 78 5f 63 6f 6e 74 72 6f 6c 28 29 20 66 75 6e  ex_control() fun
3b40: 63 74 69 6f 6e 2e 0a 2a 2f 0a 73 74 61 74 69 63  ction..*/.static
3b50: 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 46 75   int multiplexFu
3b60: 6e 63 49 6e 69 74 28 0a 20 20 73 71 6c 69 74 65  ncInit(.  sqlite
3b70: 33 20 2a 64 62 2c 20 0a 20 20 63 68 61 72 20 2a  3 *db, .  char *
3b80: 2a 70 7a 45 72 72 4d 73 67 2c 20 0a 20 20 63 6f  *pzErrMsg, .  co
3b90: 6e 73 74 20 73 71 6c 69 74 65 33 5f 61 70 69 5f  nst sqlite3_api_
3ba0: 72 6f 75 74 69 6e 65 73 20 2a 70 41 70 69 0a 29  routines *pApi.)
3bb0: 7b 0a 20 20 69 6e 74 20 72 63 3b 0a 20 20 72 63  {.  int rc;.  rc
3bc0: 20 3d 20 73 71 6c 69 74 65 33 5f 63 72 65 61 74   = sqlite3_creat
3bd0: 65 5f 66 75 6e 63 74 69 6f 6e 28 64 62 2c 20 22  e_function(db, "
3be0: 6d 75 6c 74 69 70 6c 65 78 5f 63 6f 6e 74 72 6f  multiplex_contro
3bf0: 6c 22 2c 20 32 2c 20 53 51 4c 49 54 45 5f 41 4e  l", 2, SQLITE_AN
3c00: 59 2c 20 0a 20 20 20 20 20 20 30 2c 20 6d 75 6c  Y, .      0, mul
3c10: 74 69 70 6c 65 78 43 6f 6e 74 72 6f 6c 46 75 6e  tiplexControlFun
3c20: 63 2c 20 30 2c 20 30 29 3b 0a 20 20 72 65 74 75  c, 0, 0);.  retu
3c30: 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20  rn rc;.}../*.** 
3c40: 43 6c 6f 73 65 20 61 20 73 69 6e 67 6c 65 20 73  Close a single s
3c50: 75 62 2d 66 69 6c 65 20 69 6e 20 74 68 65 20 63  ub-file in the c
3c60: 6f 6e 6e 65 63 74 69 6f 6e 20 67 72 6f 75 70 2e  onnection group.
3c70: 0a 2a 2f 0a 73 74 61 74 69 63 20 76 6f 69 64 20  .*/.static void 
3c80: 6d 75 6c 74 69 70 6c 65 78 53 75 62 43 6c 6f 73  multiplexSubClos
3c90: 65 28 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47 72  e(.  multiplexGr
3ca0: 6f 75 70 20 2a 70 47 72 6f 75 70 2c 0a 20 20 69  oup *pGroup,.  i
3cb0: 6e 74 20 69 43 68 75 6e 6b 2c 0a 20 20 73 71 6c  nt iChunk,.  sql
3cc0: 69 74 65 33 5f 76 66 73 20 2a 70 4f 72 69 67 56  ite3_vfs *pOrigV
3cd0: 66 73 0a 29 7b 0a 20 20 73 71 6c 69 74 65 33 5f  fs.){.  sqlite3_
3ce0: 66 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d  file *pSubOpen =
3cf0: 20 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69   pGroup->aReal[i
3d00: 43 68 75 6e 6b 5d 2e 70 3b 0a 20 20 69 66 28 20  Chunk].p;.  if( 
3d10: 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20  pSubOpen ){.    
3d20: 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f  pSubOpen->pMetho
3d30: 64 73 2d 3e 78 43 6c 6f 73 65 28 70 53 75 62 4f  ds->xClose(pSubO
3d40: 70 65 6e 29 3b 0a 20 20 20 20 69 66 28 20 70 4f  pen);.    if( pO
3d50: 72 69 67 56 66 73 20 26 26 20 70 47 72 6f 75 70  rigVfs && pGroup
3d60: 2d 3e 61 52 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e  ->aReal[iChunk].
3d70: 7a 20 29 7b 0a 20 20 20 20 20 20 70 4f 72 69 67  z ){.      pOrig
3d80: 56 66 73 2d 3e 78 44 65 6c 65 74 65 28 70 4f 72  Vfs->xDelete(pOr
3d90: 69 67 56 66 73 2c 20 70 47 72 6f 75 70 2d 3e 61  igVfs, pGroup->a
3da0: 52 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e 7a 2c 20  Real[iChunk].z, 
3db0: 30 29 3b 0a 20 20 20 20 7d 0a 20 20 20 20 73 71  0);.    }.    sq
3dc0: 6c 69 74 65 33 5f 66 72 65 65 28 70 47 72 6f 75  lite3_free(pGrou
3dd0: 70 2d 3e 61 52 65 61 6c 5b 69 43 68 75 6e 6b 5d  p->aReal[iChunk]
3de0: 2e 70 29 3b 0a 20 20 7d 0a 20 20 73 71 6c 69 74  .p);.  }.  sqlit
3df0: 65 33 5f 66 72 65 65 28 70 47 72 6f 75 70 2d 3e  e3_free(pGroup->
3e00: 61 52 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e 7a 29  aReal[iChunk].z)
3e10: 3b 0a 20 20 6d 65 6d 73 65 74 28 26 70 47 72 6f  ;.  memset(&pGro
3e20: 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68 75 6e 6b  up->aReal[iChunk
3e30: 5d 2c 20 30 2c 20 73 69 7a 65 6f 66 28 70 47 72  ], 0, sizeof(pGr
3e40: 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68 75 6e  oup->aReal[iChun
3e50: 6b 5d 29 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 44  k]));.}../*.** D
3e60: 65 61 6c 6c 6f 63 61 74 65 20 6d 65 6d 6f 72 79  eallocate memory
3e70: 20 68 65 6c 64 20 62 79 20 61 20 6d 75 6c 74 69   held by a multi
3e80: 70 6c 65 78 47 72 6f 75 70 0a 2a 2f 0a 73 74 61  plexGroup.*/.sta
3e90: 74 69 63 20 76 6f 69 64 20 6d 75 6c 74 69 70 6c  tic void multipl
3ea0: 65 78 46 72 65 65 43 6f 6d 70 6f 6e 65 6e 74 73  exFreeComponents
3eb0: 28 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 20  (multiplexGroup 
3ec0: 2a 70 47 72 6f 75 70 29 7b 0a 20 20 69 6e 74 20  *pGroup){.  int 
3ed0: 69 3b 0a 20 20 66 6f 72 28 69 3d 30 3b 20 69 3c  i;.  for(i=0; i<
3ee0: 70 47 72 6f 75 70 2d 3e 6e 52 65 61 6c 3b 20 69  pGroup->nReal; i
3ef0: 2b 2b 29 7b 20 6d 75 6c 74 69 70 6c 65 78 53 75  ++){ multiplexSu
3f00: 62 43 6c 6f 73 65 28 70 47 72 6f 75 70 2c 20 69  bClose(pGroup, i
3f10: 2c 20 30 29 3b 20 7d 0a 20 20 73 71 6c 69 74 65  , 0); }.  sqlite
3f20: 33 5f 66 72 65 65 28 70 47 72 6f 75 70 2d 3e 61  3_free(pGroup->a
3f30: 52 65 61 6c 29 3b 0a 20 20 70 47 72 6f 75 70 2d  Real);.  pGroup-
3f40: 3e 61 52 65 61 6c 20 3d 20 30 3b 0a 20 20 70 47  >aReal = 0;.  pG
3f50: 72 6f 75 70 2d 3e 6e 52 65 61 6c 20 3d 20 30 3b  roup->nReal = 0;
3f60: 0a 7d 0a 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  .}.../**********
3f70: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20  *************** 
3f80: 56 46 53 20 4d 65 74 68 6f 64 20 57 72 61 70 70  VFS Method Wrapp
3f90: 65 72 73 20 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ers ************
3fa0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
3fb0: 2a 2f 0a 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20 69  */../*.** This i
3fc0: 73 20 74 68 65 20 78 4f 70 65 6e 20 6d 65 74 68  s the xOpen meth
3fd0: 6f 64 20 75 73 65 64 20 66 6f 72 20 74 68 65 20  od used for the 
3fe0: 22 6d 75 6c 74 69 70 6c 65 78 22 20 56 46 53 2e  "multiplex" VFS.
3ff0: 0a 2a 2a 0a 2a 2a 20 4d 6f 73 74 20 6f 66 20 74  .**.** Most of t
4000: 68 65 20 77 6f 72 6b 20 69 73 20 64 6f 6e 65 20  he work is done 
4010: 62 79 20 74 68 65 20 75 6e 64 65 72 6c 79 69 6e  by the underlyin
4020: 67 20 6f 72 69 67 69 6e 61 6c 20 56 46 53 2e 20  g original VFS. 
4030: 20 54 68 69 73 20 6d 65 74 68 6f 64 0a 2a 2a 20   This method.** 
4040: 73 69 6d 70 6c 79 20 6c 69 6e 6b 73 20 74 68 65  simply links the
4050: 20 6e 65 77 20 66 69 6c 65 20 69 6e 74 6f 20 74   new file into t
4060: 68 65 20 61 70 70 72 6f 70 72 69 61 74 65 20 6d  he appropriate m
4070: 75 6c 74 69 70 6c 65 78 20 67 72 6f 75 70 20 69  ultiplex group i
4080: 66 20 69 74 20 69 73 20 61 0a 2a 2a 20 66 69 6c  f it is a.** fil
4090: 65 20 74 68 61 74 20 6e 65 65 64 73 20 74 6f 20  e that needs to 
40a0: 62 65 20 74 72 61 63 6b 65 64 2e 0a 2a 2f 0a 73  be tracked..*/.s
40b0: 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70  tatic int multip
40c0: 6c 65 78 4f 70 65 6e 28 0a 20 20 73 71 6c 69 74  lexOpen(.  sqlit
40d0: 65 33 5f 76 66 73 20 2a 70 56 66 73 2c 20 20 20  e3_vfs *pVfs,   
40e0: 20 20 20 20 20 20 2f 2a 20 54 68 65 20 6d 75 6c        /* The mul
40f0: 74 69 70 6c 65 78 20 56 46 53 20 2a 2f 0a 20 20  tiplex VFS */.  
4100: 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 4e 61 6d  const char *zNam
4110: 65 2c 20 20 20 20 20 20 20 20 20 2f 2a 20 4e 61  e,         /* Na
4120: 6d 65 20 6f 66 20 66 69 6c 65 20 74 6f 20 62 65  me of file to be
4130: 20 6f 70 65 6e 65 64 20 2a 2f 0a 20 20 73 71 6c   opened */.  sql
4140: 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e  ite3_file *pConn
4150: 2c 20 20 20 20 20 20 20 2f 2a 20 46 69 6c 6c 20  ,       /* Fill 
4160: 69 6e 20 74 68 69 73 20 66 69 6c 65 20 64 65 73  in this file des
4170: 63 72 69 70 74 6f 72 20 2a 2f 0a 20 20 69 6e 74  criptor */.  int
4180: 20 66 6c 61 67 73 2c 20 20 20 20 20 20 20 20 20   flags,         
4190: 20 20 20 20 20 20 20 20 2f 2a 20 46 6c 61 67 73          /* Flags
41a0: 20 74 6f 20 63 6f 6e 74 72 6f 6c 20 74 68 65 20   to control the 
41b0: 6f 70 65 6e 69 6e 67 20 2a 2f 0a 20 20 69 6e 74  opening */.  int
41c0: 20 2a 70 4f 75 74 46 6c 61 67 73 20 20 20 20 20   *pOutFlags     
41d0: 20 20 20 20 20 20 20 20 2f 2a 20 46 6c 61 67 73          /* Flags
41e0: 20 73 68 6f 77 69 6e 67 20 72 65 73 75 6c 74 73   showing results
41f0: 20 6f 66 20 6f 70 65 6e 69 6e 67 20 2a 2f 0a 29   of opening */.)
4200: 7b 0a 20 20 69 6e 74 20 72 63 20 3d 20 53 51 4c  {.  int rc = SQL
4210: 49 54 45 5f 4f 4b 3b 20 20 20 20 20 20 20 20 20  ITE_OK;         
4220: 20 20 20 20 20 20 20 20 20 2f 2a 20 52 65 73 75           /* Resu
4230: 6c 74 20 63 6f 64 65 20 2a 2f 0a 20 20 6d 75 6c  lt code */.  mul
4240: 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70 4d 75 6c  tiplexConn *pMul
4250: 74 69 70 6c 65 78 4f 70 65 6e 3b 20 20 20 20 20  tiplexOpen;     
4260: 20 20 2f 2a 20 54 68 65 20 6e 65 77 20 6d 75 6c    /* The new mul
4270: 74 69 70 6c 65 78 20 66 69 6c 65 20 64 65 73 63  tiplex file desc
4280: 72 69 70 74 6f 72 20 2a 2f 0a 20 20 6d 75 6c 74  riptor */.  mult
4290: 69 70 6c 65 78 47 72 6f 75 70 20 2a 70 47 72 6f  iplexGroup *pGro
42a0: 75 70 3b 20 20 20 20 20 20 20 20 20 20 20 20 20  up;             
42b0: 20 2f 2a 20 43 6f 72 72 65 73 70 6f 6e 64 69 6e   /* Correspondin
42c0: 67 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70  g multiplexGroup
42d0: 20 6f 62 6a 65 63 74 20 2a 2f 0a 20 20 73 71 6c   object */.  sql
42e0: 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f  ite3_file *pSubO
42f0: 70 65 6e 20 3d 20 30 3b 20 20 20 20 20 20 20 20  pen = 0;        
4300: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 52              /* R
4310: 65 61 6c 20 66 69 6c 65 20 64 65 73 63 72 69 70  eal file descrip
4320: 74 6f 72 20 2a 2f 0a 20 20 73 71 6c 69 74 65 33  tor */.  sqlite3
4330: 5f 76 66 73 20 2a 70 4f 72 69 67 56 66 73 20 3d  _vfs *pOrigVfs =
4340: 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69   gMultiplex.pOri
4350: 67 56 66 73 3b 20 20 20 2f 2a 20 52 65 61 6c 20  gVfs;   /* Real 
4360: 56 46 53 20 2a 2f 0a 20 20 69 6e 74 20 6e 4e 61  VFS */.  int nNa
4370: 6d 65 3b 0a 20 20 69 6e 74 20 73 7a 3b 0a 20 20  me;.  int sz;.  
4380: 63 68 61 72 20 2a 7a 54 6f 46 72 65 65 20 3d 20  char *zToFree = 
4390: 30 3b 0a 0a 20 20 55 4e 55 53 45 44 5f 50 41 52  0;..  UNUSED_PAR
43a0: 41 4d 45 54 45 52 28 70 56 66 73 29 3b 0a 20 20  AMETER(pVfs);.  
43b0: 6d 65 6d 73 65 74 28 70 43 6f 6e 6e 2c 20 30 2c  memset(pConn, 0,
43c0: 20 70 56 66 73 2d 3e 73 7a 4f 73 46 69 6c 65 29   pVfs->szOsFile)
43d0: 3b 0a 20 20 61 73 73 65 72 74 28 20 7a 4e 61 6d  ;.  assert( zNam
43e0: 65 20 7c 7c 20 28 66 6c 61 67 73 20 26 20 53 51  e || (flags & SQ
43f0: 4c 49 54 45 5f 4f 50 45 4e 5f 44 45 4c 45 54 45  LITE_OPEN_DELETE
4400: 4f 4e 43 4c 4f 53 45 29 20 29 3b 0a 0a 20 20 2f  ONCLOSE) );..  /
4410: 2a 20 57 65 20 6e 65 65 64 20 74 6f 20 63 72 65  * We need to cre
4420: 61 74 65 20 61 20 67 72 6f 75 70 20 73 74 72 75  ate a group stru
4430: 63 74 75 72 65 20 61 6e 64 20 6d 61 6e 61 67 65  cture and manage
4440: 0a 20 20 2a 2a 20 61 63 63 65 73 73 20 74 6f 20  .  ** access to 
4450: 74 68 69 73 20 67 72 6f 75 70 20 6f 66 20 66 69  this group of fi
4460: 6c 65 73 2e 0a 20 20 2a 2f 0a 20 20 6d 75 6c 74  les..  */.  mult
4470: 69 70 6c 65 78 45 6e 74 65 72 28 29 3b 0a 20 20  iplexEnter();.  
4480: 70 4d 75 6c 74 69 70 6c 65 78 4f 70 65 6e 20 3d  pMultiplexOpen =
4490: 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a   (multiplexConn*
44a0: 29 70 43 6f 6e 6e 3b 0a 0a 20 20 69 66 28 20 72  )pConn;..  if( r
44b0: 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a  c==SQLITE_OK ){.
44c0: 20 20 20 20 2f 2a 20 61 6c 6c 6f 63 61 74 65 20      /* allocate 
44d0: 73 70 61 63 65 20 66 6f 72 20 67 72 6f 75 70 20  space for group 
44e0: 2a 2f 0a 20 20 20 20 6e 4e 61 6d 65 20 3d 20 7a  */.    nName = z
44f0: 4e 61 6d 65 20 3f 20 6d 75 6c 74 69 70 6c 65 78  Name ? multiplex
4500: 53 74 72 6c 65 6e 33 30 28 7a 4e 61 6d 65 29 20  Strlen30(zName) 
4510: 3a 20 30 3b 0a 20 20 20 20 73 7a 20 3d 20 73 69  : 0;.    sz = si
4520: 7a 65 6f 66 28 6d 75 6c 74 69 70 6c 65 78 47 72  zeof(multiplexGr
4530: 6f 75 70 29 20 20 20 20 20 20 20 20 20 20 20 20  oup)            
4540: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4550: 20 2f 2a 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f   /* multiplexGro
4560: 75 70 20 2a 2f 0a 20 20 20 20 20 20 20 2b 20 6e  up */.       + n
4570: 4e 61 6d 65 20 2b 20 31 3b 20 20 20 20 20 20 20  Name + 1;       
4580: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4590: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
45a0: 20 20 2f 2a 20 7a 4e 61 6d 65 20 2a 2f 0a 20 20    /* zName */.  
45b0: 20 20 70 47 72 6f 75 70 20 3d 20 73 71 6c 69 74    pGroup = sqlit
45c0: 65 33 5f 6d 61 6c 6c 6f 63 28 20 73 7a 20 29 3b  e3_malloc( sz );
45d0: 0a 20 20 20 20 69 66 28 20 70 47 72 6f 75 70 3d  .    if( pGroup=
45e0: 3d 30 20 29 7b 0a 20 20 20 20 20 20 72 63 20 3d  =0 ){.      rc =
45f0: 20 53 51 4c 49 54 45 5f 4e 4f 4d 45 4d 3b 0a 20   SQLITE_NOMEM;. 
4600: 20 20 20 7d 0a 20 20 7d 0a 0a 20 20 69 66 28 20     }.  }..  if( 
4610: 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b  rc==SQLITE_OK ){
4620: 0a 20 20 20 20 63 6f 6e 73 74 20 63 68 61 72 20  .    const char 
4630: 2a 7a 55 72 69 20 3d 20 28 66 6c 61 67 73 20 26  *zUri = (flags &
4640: 20 53 51 4c 49 54 45 5f 4f 50 45 4e 5f 55 52 49   SQLITE_OPEN_URI
4650: 29 20 3f 20 7a 4e 61 6d 65 20 3a 20 30 3b 0a 20  ) ? zName : 0;. 
4660: 20 20 20 2f 2a 20 61 73 73 69 67 6e 20 70 6f 69     /* assign poi
4670: 6e 74 65 72 73 20 74 6f 20 65 78 74 72 61 20 73  nters to extra s
4680: 70 61 63 65 20 61 6c 6c 6f 63 61 74 65 64 20 2a  pace allocated *
4690: 2f 0a 20 20 20 20 6d 65 6d 73 65 74 28 70 47 72  /.    memset(pGr
46a0: 6f 75 70 2c 20 30 2c 20 73 7a 29 3b 0a 20 20 20  oup, 0, sz);.   
46b0: 20 70 4d 75 6c 74 69 70 6c 65 78 4f 70 65 6e 2d   pMultiplexOpen-
46c0: 3e 70 47 72 6f 75 70 20 3d 20 70 47 72 6f 75 70  >pGroup = pGroup
46d0: 3b 0a 20 20 20 20 70 47 72 6f 75 70 2d 3e 62 45  ;.    pGroup->bE
46e0: 6e 61 62 6c 65 64 20 3d 20 2d 31 3b 0a 20 20 20  nabled = -1;.   
46f0: 20 70 47 72 6f 75 70 2d 3e 62 54 72 75 6e 63 61   pGroup->bTrunca
4700: 74 65 20 3d 20 73 71 6c 69 74 65 33 5f 75 72 69  te = sqlite3_uri
4710: 5f 62 6f 6f 6c 65 61 6e 28 7a 55 72 69 2c 20 22  _boolean(zUri, "
4720: 74 72 75 6e 63 61 74 65 22 2c 20 0a 20 20 20 20  truncate", .    
4730: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4740: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 28                 (
4750: 66 6c 61 67 73 20 26 20 53 51 4c 49 54 45 5f 4f  flags & SQLITE_O
4760: 50 45 4e 5f 4d 41 49 4e 5f 44 42 29 3d 3d 30 29  PEN_MAIN_DB)==0)
4770: 3b 0a 20 20 20 20 70 47 72 6f 75 70 2d 3e 73 7a  ;.    pGroup->sz
4780: 43 68 75 6e 6b 20 3d 20 73 71 6c 69 74 65 33 5f  Chunk = sqlite3_
4790: 75 72 69 5f 69 6e 74 36 34 28 7a 55 72 69 2c 20  uri_int64(zUri, 
47a0: 22 63 68 75 6e 6b 73 69 7a 65 22 2c 0a 20 20 20  "chunksize",.   
47b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
47c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
47d0: 20 20 20 20 20 53 51 4c 49 54 45 5f 4d 55 4c 54       SQLITE_MULT
47e0: 49 50 4c 45 58 5f 43 48 55 4e 4b 5f 53 49 5a 45  IPLEX_CHUNK_SIZE
47f0: 29 3b 0a 20 20 20 20 70 47 72 6f 75 70 2d 3e 73  );.    pGroup->s
4800: 7a 43 68 75 6e 6b 20 3d 20 28 70 47 72 6f 75 70  zChunk = (pGroup
4810: 2d 3e 73 7a 43 68 75 6e 6b 2b 30 78 66 66 66 66  ->szChunk+0xffff
4820: 29 26 7e 30 78 66 66 66 66 3b 0a 20 20 20 20 69  )&~0xffff;.    i
4830: 66 28 20 7a 4e 61 6d 65 20 29 7b 0a 20 20 20 20  f( zName ){.    
4840: 20 20 63 68 61 72 20 2a 70 20 3d 20 28 63 68 61    char *p = (cha
4850: 72 20 2a 29 26 70 47 72 6f 75 70 5b 31 5d 3b 0a  r *)&pGroup[1];.
4860: 20 20 20 20 20 20 70 47 72 6f 75 70 2d 3e 7a 4e        pGroup->zN
4870: 61 6d 65 20 3d 20 70 3b 0a 20 20 20 20 20 20 6d  ame = p;.      m
4880: 65 6d 63 70 79 28 70 47 72 6f 75 70 2d 3e 7a 4e  emcpy(pGroup->zN
4890: 61 6d 65 2c 20 7a 4e 61 6d 65 2c 20 6e 4e 61 6d  ame, zName, nNam
48a0: 65 2b 31 29 3b 0a 20 20 20 20 20 20 70 47 72 6f  e+1);.      pGro
48b0: 75 70 2d 3e 6e 4e 61 6d 65 20 3d 20 6e 4e 61 6d  up->nName = nNam
48c0: 65 3b 0a 20 20 20 20 7d 0a 20 20 20 20 69 66 28  e;.    }.    if(
48d0: 20 70 47 72 6f 75 70 2d 3e 62 45 6e 61 62 6c 65   pGroup->bEnable
48e0: 64 20 29 7b 0a 20 20 20 20 20 20 2f 2a 20 4d 61  d ){.      /* Ma
48f0: 6b 65 20 73 75 72 65 20 74 68 61 74 20 74 68 65  ke sure that the
4900: 20 63 68 75 6e 6b 73 69 7a 65 20 69 73 20 73 75   chunksize is su
4910: 63 68 20 74 68 61 74 20 74 68 65 20 70 65 6e 64  ch that the pend
4920: 69 6e 67 20 62 79 74 65 20 64 6f 65 73 20 6e 6f  ing byte does no
4930: 74 0a 20 20 20 20 20 20 2a 2a 20 66 61 6c 6c 73  t.      ** falls
4940: 20 61 74 20 74 68 65 20 65 6e 64 20 6f 66 20 61   at the end of a
4950: 20 63 68 75 6e 6b 2e 20 20 41 20 72 65 67 69 6f   chunk.  A regio
4960: 6e 20 6f 66 20 75 70 20 74 6f 20 36 34 4b 20 66  n of up to 64K f
4970: 6f 6c 6c 6f 77 69 6e 67 0a 20 20 20 20 20 20 2a  ollowing.      *
4980: 2a 20 74 68 65 20 70 65 6e 64 69 6e 67 20 62 79  * the pending by
4990: 74 65 20 69 73 20 6e 65 76 65 72 20 77 72 69 74  te is never writ
49a0: 74 65 6e 2c 20 73 6f 20 69 66 20 74 68 65 20 70  ten, so if the p
49b0: 65 6e 64 69 6e 67 20 62 79 74 65 20 6f 63 63 75  ending byte occu
49c0: 72 73 0a 20 20 20 20 20 20 2a 2a 20 6e 65 61 72  rs.      ** near
49d0: 20 74 68 65 20 65 6e 64 20 6f 66 20 61 20 63 68   the end of a ch
49e0: 75 6e 6b 2c 20 74 68 61 74 20 63 68 75 6e 6b 20  unk, that chunk 
49f0: 77 69 6c 6c 20 62 65 20 74 6f 6f 20 73 6d 61 6c  will be too smal
4a00: 6c 2e 20 2a 2f 0a 23 69 66 6e 64 65 66 20 53 51  l. */.#ifndef SQ
4a10: 4c 49 54 45 5f 4f 4d 49 54 5f 57 53 44 0a 20 20  LITE_OMIT_WSD.  
4a20: 20 20 20 20 65 78 74 65 72 6e 20 69 6e 74 20 73      extern int s
4a30: 71 6c 69 74 65 33 50 65 6e 64 69 6e 67 42 79 74  qlite3PendingByt
4a40: 65 3b 0a 23 65 6c 73 65 0a 20 20 20 20 20 20 69  e;.#else.      i
4a50: 6e 74 20 73 71 6c 69 74 65 33 50 65 6e 64 69 6e  nt sqlite3Pendin
4a60: 67 42 79 74 65 20 3d 20 30 78 34 30 30 30 30 30  gByte = 0x400000
4a70: 30 30 3b 0a 23 65 6e 64 69 66 0a 20 20 20 20 20  00;.#endif.     
4a80: 20 77 68 69 6c 65 28 20 28 73 71 6c 69 74 65 33   while( (sqlite3
4a90: 50 65 6e 64 69 6e 67 42 79 74 65 20 25 20 70 47  PendingByte % pG
4aa0: 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 29 3e 3d  roup->szChunk)>=
4ab0: 28 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b  (pGroup->szChunk
4ac0: 2d 36 35 35 33 36 29 20 29 7b 0a 20 20 20 20 20  -65536) ){.     
4ad0: 20 20 20 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75     pGroup->szChu
4ae0: 6e 6b 20 2b 3d 20 36 35 35 33 36 3b 0a 20 20 20  nk += 65536;.   
4af0: 20 20 20 7d 0a 20 20 20 20 7d 0a 20 20 20 20 70     }.    }.    p
4b00: 47 72 6f 75 70 2d 3e 66 6c 61 67 73 20 3d 20 66  Group->flags = f
4b10: 6c 61 67 73 3b 0a 20 20 20 20 72 63 20 3d 20 6d  lags;.    rc = m
4b20: 75 6c 74 69 70 6c 65 78 53 75 62 46 69 6c 65 6e  ultiplexSubFilen
4b30: 61 6d 65 28 70 47 72 6f 75 70 2c 20 31 29 3b 0a  ame(pGroup, 1);.
4b40: 20 20 20 20 69 66 28 20 72 63 3d 3d 53 51 4c 49      if( rc==SQLI
4b50: 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 70  TE_OK ){.      p
4b60: 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70  SubOpen = multip
4b70: 6c 65 78 53 75 62 4f 70 65 6e 28 70 47 72 6f 75  lexSubOpen(pGrou
4b80: 70 2c 20 30 2c 20 26 72 63 2c 20 70 4f 75 74 46  p, 0, &rc, pOutF
4b90: 6c 61 67 73 2c 20 30 29 3b 0a 20 20 20 20 20 20  lags, 0);.      
4ba0: 69 66 28 20 70 53 75 62 4f 70 65 6e 3d 3d 30 20  if( pSubOpen==0 
4bb0: 26 26 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b  && rc==SQLITE_OK
4bc0: 20 29 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 43   ) rc = SQLITE_C
4bd0: 41 4e 54 4f 50 45 4e 3b 0a 20 20 20 20 7d 0a 20  ANTOPEN;.    }. 
4be0: 20 20 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54     if( rc==SQLIT
4bf0: 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 73 71  E_OK ){.      sq
4c00: 6c 69 74 65 33 5f 69 6e 74 36 34 20 73 7a 3b 0a  lite3_int64 sz;.
4c10: 0a 20 20 20 20 20 20 72 63 20 3d 20 70 53 75 62  .      rc = pSub
4c20: 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e  Open->pMethods->
4c30: 78 46 69 6c 65 53 69 7a 65 28 70 53 75 62 4f 70  xFileSize(pSubOp
4c40: 65 6e 2c 20 26 73 7a 29 3b 0a 20 20 20 20 20 20  en, &sz);.      
4c50: 69 66 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f  if( rc==SQLITE_O
4c60: 4b 20 26 26 20 7a 4e 61 6d 65 20 29 7b 0a 20 20  K && zName ){.  
4c70: 20 20 20 20 20 20 69 6e 74 20 62 45 78 69 73 74        int bExist
4c80: 73 3b 0a 20 20 20 20 20 20 20 20 69 66 28 20 73  s;.        if( s
4c90: 7a 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 20 20  z==0 ){.        
4ca0: 20 20 69 66 28 20 66 6c 61 67 73 20 26 20 53 51    if( flags & SQ
4cb0: 4c 49 54 45 5f 4f 50 45 4e 5f 4d 41 49 4e 5f 4a  LITE_OPEN_MAIN_J
4cc0: 4f 55 52 4e 41 4c 20 29 7b 0a 20 20 20 20 20 20  OURNAL ){.      
4cd0: 20 20 20 20 20 20 2f 2a 20 49 66 20 6f 70 65 6e        /* If open
4ce0: 69 6e 67 20 61 20 6d 61 69 6e 20 6a 6f 75 72 6e  ing a main journ
4cf0: 61 6c 20 66 69 6c 65 20 61 6e 64 20 74 68 65 20  al file and the 
4d00: 66 69 72 73 74 20 63 68 75 6e 6b 20 69 73 20 7a  first chunk is z
4d10: 65 72 6f 0a 20 20 20 20 20 20 20 20 20 20 20 20  ero.            
4d20: 2a 2a 20 62 79 74 65 73 20 69 6e 20 73 69 7a 65  ** bytes in size
4d30: 2c 20 64 65 6c 65 74 65 20 61 6e 79 20 73 75 62  , delete any sub
4d40: 73 65 71 75 65 6e 74 20 63 68 75 6e 6b 73 20 66  sequent chunks f
4d50: 72 6f 6d 20 74 68 65 20 0a 20 20 20 20 20 20 20  rom the .       
4d60: 20 20 20 20 20 2a 2a 20 66 69 6c 65 2d 73 79 73       ** file-sys
4d70: 74 65 6d 2e 20 2a 2f 0a 20 20 20 20 20 20 20 20  tem. */.        
4d80: 20 20 20 20 69 6e 74 20 69 43 68 75 6e 6b 20 3d      int iChunk =
4d90: 20 31 3b 0a 20 20 20 20 20 20 20 20 20 20 20 20   1;.            
4da0: 64 6f 20 7b 0a 20 20 20 20 20 20 20 20 20 20 20  do {.           
4db0: 20 20 20 72 63 20 3d 20 70 4f 72 69 67 56 66 73     rc = pOrigVfs
4dc0: 2d 3e 78 41 63 63 65 73 73 28 70 4f 72 69 67 56  ->xAccess(pOrigV
4dd0: 66 73 2c 20 0a 20 20 20 20 20 20 20 20 20 20 20  fs, .           
4de0: 20 20 20 20 20 20 20 70 47 72 6f 75 70 2d 3e 61         pGroup->a
4df0: 52 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e 7a 2c 20  Real[iChunk].z, 
4e00: 53 51 4c 49 54 45 5f 41 43 43 45 53 53 5f 45 58  SQLITE_ACCESS_EX
4e10: 49 53 54 53 2c 20 26 62 45 78 69 73 74 73 0a 20  ISTS, &bExists. 
4e20: 20 20 20 20 20 20 20 20 20 20 20 20 20 29 3b 0a               );.
4e30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66                if
4e40: 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20  ( rc==SQLITE_OK 
4e50: 26 26 20 62 45 78 69 73 74 73 20 29 7b 0a 20 20  && bExists ){.  
4e60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 72 63                rc
4e70: 20 3d 20 70 4f 72 69 67 56 66 73 2d 3e 78 44 65   = pOrigVfs->xDe
4e80: 6c 65 74 65 28 70 4f 72 69 67 56 66 73 2c 20 70  lete(pOrigVfs, p
4e90: 47 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68  Group->aReal[iCh
4ea0: 75 6e 6b 5d 2e 7a 2c 20 30 29 3b 0a 20 20 20 20  unk].z, 0);.    
4eb0: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 28 20              if( 
4ec0: 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b  rc==SQLITE_OK ){
4ed0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
4ee0: 20 20 20 72 63 20 3d 20 6d 75 6c 74 69 70 6c 65     rc = multiple
4ef0: 78 53 75 62 46 69 6c 65 6e 61 6d 65 28 70 47 72  xSubFilename(pGr
4f00: 6f 75 70 2c 20 2b 2b 69 43 68 75 6e 6b 29 3b 0a  oup, ++iChunk);.
4f10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4f20: 7d 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  }.              
4f30: 7d 0a 20 20 20 20 20 20 20 20 20 20 20 20 7d 77  }.            }w
4f40: 68 69 6c 65 28 20 72 63 3d 3d 53 51 4c 49 54 45  hile( rc==SQLITE
4f50: 5f 4f 4b 20 26 26 20 62 45 78 69 73 74 73 20 29  _OK && bExists )
4f60: 3b 0a 20 20 20 20 20 20 20 20 20 20 7d 0a 20 20  ;.          }.  
4f70: 20 20 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20        }else{.   
4f80: 20 20 20 20 20 20 20 2f 2a 20 49 66 20 74 68 65         /* If the
4f90: 20 66 69 72 73 74 20 6f 76 65 72 66 6c 6f 77 20   first overflow 
4fa0: 66 69 6c 65 20 65 78 69 73 74 73 20 61 6e 64 20  file exists and 
4fb0: 69 66 20 74 68 65 20 73 69 7a 65 20 6f 66 20 74  if the size of t
4fc0: 68 65 20 6d 61 69 6e 20 66 69 6c 65 0a 20 20 20  he main file.   
4fd0: 20 20 20 20 20 20 20 2a 2a 20 69 73 20 64 69 66         ** is dif
4fe0: 66 65 72 65 6e 74 20 66 72 6f 6d 20 74 68 65 20  ferent from the 
4ff0: 63 68 75 6e 6b 20 73 69 7a 65 2c 20 74 68 61 74  chunk size, that
5000: 20 6d 65 61 6e 73 20 74 68 65 20 63 68 75 6e 6b   means the chunk
5010: 20 73 69 7a 65 20 69 73 20 73 65 74 0a 20 20 20   size is set.   
5020: 20 20 20 20 20 20 20 2a 2a 20 73 65 74 20 69 6e         ** set in
5030: 63 6f 72 72 65 63 74 6c 79 2e 20 20 53 6f 20 66  correctly.  So f
5040: 69 78 20 69 74 2e 0a 20 20 20 20 20 20 20 20 20  ix it..         
5050: 20 2a 2a 0a 20 20 20 20 20 20 20 20 20 20 2a 2a   **.          **
5060: 20 4f 72 2c 20 69 66 20 74 68 65 20 66 69 72 73   Or, if the firs
5070: 74 20 6f 76 65 72 66 6c 6f 77 20 66 69 6c 65 20  t overflow file 
5080: 64 6f 65 73 20 6e 6f 74 20 65 78 69 73 74 20 61  does not exist a
5090: 6e 64 20 74 68 65 20 6d 61 69 6e 20 66 69 6c 65  nd the main file
50a0: 20 69 73 0a 20 20 20 20 20 20 20 20 20 20 2a 2a   is.          **
50b0: 20 6c 61 72 67 65 72 20 74 68 61 6e 20 74 68 65   larger than the
50c0: 20 63 68 75 6e 6b 20 73 69 7a 65 2c 20 74 68 61   chunk size, tha
50d0: 74 20 6d 65 61 6e 73 20 74 68 65 20 63 68 75 6e  t means the chun
50e0: 6b 20 73 69 7a 65 20 69 73 20 74 6f 6f 20 73 6d  k size is too sm
50f0: 61 6c 6c 2e 0a 20 20 20 20 20 20 20 20 20 20 2a  all..          *
5100: 2a 20 42 75 74 20 77 65 20 68 61 76 65 20 6e 6f  * But we have no
5110: 20 77 61 79 20 6f 66 20 64 65 74 65 72 6d 69 6e   way of determin
5120: 69 6e 67 20 74 68 65 20 69 6e 74 65 6e 64 65 64  ing the intended
5130: 20 63 68 75 6e 6b 20 73 69 7a 65 2c 20 73 6f 20   chunk size, so 
5140: 0a 20 20 20 20 20 20 20 20 20 20 2a 2a 20 6a 75  .          ** ju
5150: 73 74 20 64 69 73 61 62 6c 65 20 74 68 65 20 6d  st disable the m
5160: 75 6c 74 69 70 6c 65 78 6f 72 20 61 6c 6c 20 74  ultiplexor all t
5170: 6f 67 65 74 68 72 65 2e 0a 20 20 20 20 20 20 20  ogethre..       
5180: 20 20 20 2a 2f 0a 20 20 20 20 20 20 20 20 20 20     */.          
5190: 72 63 20 3d 20 70 4f 72 69 67 56 66 73 2d 3e 78  rc = pOrigVfs->x
51a0: 41 63 63 65 73 73 28 70 4f 72 69 67 56 66 73 2c  Access(pOrigVfs,
51b0: 20 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 31   pGroup->aReal[1
51c0: 5d 2e 7a 2c 0a 20 20 20 20 20 20 20 20 20 20 20  ].z,.           
51d0: 20 20 20 53 51 4c 49 54 45 5f 41 43 43 45 53 53     SQLITE_ACCESS
51e0: 5f 45 58 49 53 54 53 2c 20 26 62 45 78 69 73 74  _EXISTS, &bExist
51f0: 73 29 3b 0a 20 20 20 20 20 20 20 20 20 20 62 45  s);.          bE
5200: 78 69 73 74 73 20 3d 20 6d 75 6c 74 69 70 6c 65  xists = multiple
5210: 78 53 75 62 53 69 7a 65 28 70 47 72 6f 75 70 2c  xSubSize(pGroup,
5220: 20 31 2c 20 26 72 63 29 3e 30 3b 0a 20 20 20 20   1, &rc)>0;.    
5230: 20 20 20 20 20 20 69 66 28 20 72 63 3d 3d 53 51        if( rc==SQ
5240: 4c 49 54 45 5f 4f 4b 20 26 26 20 62 45 78 69 73  LITE_OK && bExis
5250: 74 73 20 20 26 26 20 73 7a 3d 3d 28 73 7a 26 30  ts  && sz==(sz&0
5260: 78 66 66 66 66 30 30 30 30 29 20 26 26 20 73 7a  xffff0000) && sz
5270: 3e 30 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  >0.             
5280: 20 26 26 20 73 7a 21 3d 70 47 72 6f 75 70 2d 3e   && sz!=pGroup->
5290: 73 7a 43 68 75 6e 6b 20 29 7b 0a 20 20 20 20 20  szChunk ){.     
52a0: 20 20 20 20 20 20 20 70 47 72 6f 75 70 2d 3e 73         pGroup->s
52b0: 7a 43 68 75 6e 6b 20 3d 20 73 7a 3b 0a 20 20 20  zChunk = sz;.   
52c0: 20 20 20 20 20 20 20 7d 65 6c 73 65 20 69 66 28         }else if(
52d0: 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 26   rc==SQLITE_OK &
52e0: 26 20 21 62 45 78 69 73 74 73 20 26 26 20 73 7a  & !bExists && sz
52f0: 3e 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b  >pGroup->szChunk
5300: 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20 20 20   ){.            
5310: 70 47 72 6f 75 70 2d 3e 62 45 6e 61 62 6c 65 64  pGroup->bEnabled
5320: 20 3d 20 30 3b 0a 20 20 20 20 20 20 20 20 20 20   = 0;.          
5330: 7d 0a 20 20 20 20 20 20 20 20 7d 0a 20 20 20 20  }.        }.    
5340: 20 20 7d 0a 20 20 20 20 7d 0a 0a 20 20 20 20 69    }.    }..    i
5350: 66 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b  f( rc==SQLITE_OK
5360: 20 29 7b 0a 20 20 20 20 20 20 69 66 28 20 70 53   ){.      if( pS
5370: 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73  ubOpen->pMethods
5380: 2d 3e 69 56 65 72 73 69 6f 6e 3d 3d 31 20 29 7b  ->iVersion==1 ){
5390: 0a 20 20 20 20 20 20 20 20 70 4d 75 6c 74 69 70  .        pMultip
53a0: 6c 65 78 4f 70 65 6e 2d 3e 62 61 73 65 2e 70 4d  lexOpen->base.pM
53b0: 65 74 68 6f 64 73 20 3d 20 26 67 4d 75 6c 74 69  ethods = &gMulti
53c0: 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56  plex.sIoMethodsV
53d0: 31 3b 0a 20 20 20 20 20 20 7d 65 6c 73 65 7b 0a  1;.      }else{.
53e0: 20 20 20 20 20 20 20 20 70 4d 75 6c 74 69 70 6c          pMultipl
53f0: 65 78 4f 70 65 6e 2d 3e 62 61 73 65 2e 70 4d 65  exOpen->base.pMe
5400: 74 68 6f 64 73 20 3d 20 26 67 4d 75 6c 74 69 70  thods = &gMultip
5410: 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 32  lex.sIoMethodsV2
5420: 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20  ;.      }.      
5430: 2f 2a 20 70 6c 61 63 65 20 74 68 69 73 20 67 72  /* place this gr
5440: 6f 75 70 20 61 74 20 74 68 65 20 68 65 61 64 20  oup at the head 
5450: 6f 66 20 6f 75 72 20 6c 69 73 74 20 2a 2f 0a 20  of our list */. 
5460: 20 20 20 20 20 70 47 72 6f 75 70 2d 3e 70 4e 65       pGroup->pNe
5470: 78 74 20 3d 20 67 4d 75 6c 74 69 70 6c 65 78 2e  xt = gMultiplex.
5480: 70 47 72 6f 75 70 73 3b 0a 20 20 20 20 20 20 69  pGroups;.      i
5490: 66 28 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 47  f( gMultiplex.pG
54a0: 72 6f 75 70 73 20 29 20 67 4d 75 6c 74 69 70 6c  roups ) gMultipl
54b0: 65 78 2e 70 47 72 6f 75 70 73 2d 3e 70 50 72 65  ex.pGroups->pPre
54c0: 76 20 3d 20 70 47 72 6f 75 70 3b 0a 20 20 20 20  v = pGroup;.    
54d0: 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 47 72    gMultiplex.pGr
54e0: 6f 75 70 73 20 3d 20 70 47 72 6f 75 70 3b 0a 20  oups = pGroup;. 
54f0: 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20     }else{.      
5500: 6d 75 6c 74 69 70 6c 65 78 46 72 65 65 43 6f 6d  multiplexFreeCom
5510: 70 6f 6e 65 6e 74 73 28 70 47 72 6f 75 70 29 3b  ponents(pGroup);
5520: 0a 20 20 20 20 20 20 73 71 6c 69 74 65 33 5f 66  .      sqlite3_f
5530: 72 65 65 28 70 47 72 6f 75 70 29 3b 0a 20 20 20  ree(pGroup);.   
5540: 20 7d 0a 20 20 7d 0a 20 20 6d 75 6c 74 69 70 6c   }.  }.  multipl
5550: 65 78 4c 65 61 76 65 28 29 3b 0a 20 20 73 71 6c  exLeave();.  sql
5560: 69 74 65 33 5f 66 72 65 65 28 7a 54 6f 46 72 65  ite3_free(zToFre
5570: 65 29 3b 0a 20 20 72 65 74 75 72 6e 20 72 63 3b  e);.  return rc;
5580: 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20 69  .}../*.** This i
5590: 73 20 74 68 65 20 78 44 65 6c 65 74 65 20 6d 65  s the xDelete me
55a0: 74 68 6f 64 20 75 73 65 64 20 66 6f 72 20 74 68  thod used for th
55b0: 65 20 22 6d 75 6c 74 69 70 6c 65 78 22 20 56 46  e "multiplex" VF
55c0: 53 2e 0a 2a 2a 20 49 74 20 61 74 74 65 6d 70 74  S..** It attempt
55d0: 73 20 74 6f 20 64 65 6c 65 74 65 20 74 68 65 20  s to delete the 
55e0: 66 69 6c 65 6e 61 6d 65 20 73 70 65 63 69 66 69  filename specifi
55f0: 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e  ed..*/.static in
5600: 74 20 6d 75 6c 74 69 70 6c 65 78 44 65 6c 65 74  t multiplexDelet
5610: 65 28 0a 20 20 73 71 6c 69 74 65 33 5f 76 66 73  e(.  sqlite3_vfs
5620: 20 2a 70 56 66 73 2c 20 20 20 20 20 20 20 20 20   *pVfs,         
5630: 2f 2a 20 54 68 65 20 6d 75 6c 74 69 70 6c 65 78  /* The multiplex
5640: 20 56 46 53 20 2a 2f 0a 20 20 63 6f 6e 73 74 20   VFS */.  const 
5650: 63 68 61 72 20 2a 7a 4e 61 6d 65 2c 20 20 20 20  char *zName,    
5660: 20 20 20 20 20 2f 2a 20 4e 61 6d 65 20 6f 66 20       /* Name of 
5670: 66 69 6c 65 20 74 6f 20 64 65 6c 65 74 65 20 2a  file to delete *
5680: 2f 0a 20 20 69 6e 74 20 73 79 6e 63 44 69 72 0a  /.  int syncDir.
5690: 29 7b 0a 20 20 69 6e 74 20 72 63 3b 0a 20 20 73  ){.  int rc;.  s
56a0: 71 6c 69 74 65 33 5f 76 66 73 20 2a 70 4f 72 69  qlite3_vfs *pOri
56b0: 67 56 66 73 20 3d 20 67 4d 75 6c 74 69 70 6c 65  gVfs = gMultiple
56c0: 78 2e 70 4f 72 69 67 56 66 73 3b 20 20 20 2f 2a  x.pOrigVfs;   /*
56d0: 20 52 65 61 6c 20 56 46 53 20 2a 2f 0a 20 20 72   Real VFS */.  r
56e0: 63 20 3d 20 70 4f 72 69 67 56 66 73 2d 3e 78 44  c = pOrigVfs->xD
56f0: 65 6c 65 74 65 28 70 4f 72 69 67 56 66 73 2c 20  elete(pOrigVfs, 
5700: 7a 4e 61 6d 65 2c 20 73 79 6e 63 44 69 72 29 3b  zName, syncDir);
5710: 0a 20 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54  .  if( rc==SQLIT
5720: 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 2f 2a 20 49  E_OK ){.    /* I
5730: 66 20 74 68 65 20 6d 61 69 6e 20 63 68 75 6e 6b  f the main chunk
5740: 20 77 61 73 20 64 65 6c 65 74 65 64 20 73 75 63   was deleted suc
5750: 63 65 73 73 66 75 6c 6c 79 2c 20 61 6c 73 6f 20  cessfully, also 
5760: 64 65 6c 65 74 65 20 61 6e 79 20 73 75 62 73 65  delete any subse
5770: 71 75 65 6e 74 0a 20 20 20 20 2a 2a 20 63 68 75  quent.    ** chu
5780: 6e 6b 73 20 2d 20 73 74 61 72 74 69 6e 67 20 77  nks - starting w
5790: 69 74 68 20 74 68 65 20 6c 61 73 74 20 28 68 69  ith the last (hi
57a0: 67 68 65 73 74 20 6e 75 6d 62 65 72 65 64 29 2e  ghest numbered).
57b0: 20 0a 20 20 20 20 2a 2f 0a 20 20 20 20 69 6e 74   .    */.    int
57c0: 20 6e 4e 61 6d 65 20 3d 20 73 74 72 6c 65 6e 28   nName = strlen(
57d0: 7a 4e 61 6d 65 29 3b 0a 20 20 20 20 63 68 61 72  zName);.    char
57e0: 20 2a 7a 3b 0a 20 20 20 20 7a 20 3d 20 73 71 6c   *z;.    z = sql
57f0: 69 74 65 33 5f 6d 61 6c 6c 6f 63 28 6e 4e 61 6d  ite3_malloc(nNam
5800: 65 20 2b 20 35 29 3b 0a 20 20 20 20 69 66 28 20  e + 5);.    if( 
5810: 7a 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 72 63  z==0 ){.      rc
5820: 20 3d 20 53 51 4c 49 54 45 5f 49 4f 45 52 52 5f   = SQLITE_IOERR_
5830: 4e 4f 4d 45 4d 3b 0a 20 20 20 20 7d 65 6c 73 65  NOMEM;.    }else
5840: 7b 0a 20 20 20 20 20 20 69 6e 74 20 69 43 68 75  {.      int iChu
5850: 6e 6b 20 3d 20 30 3b 0a 20 20 20 20 20 20 69 6e  nk = 0;.      in
5860: 74 20 62 45 78 69 73 74 73 3b 0a 20 20 20 20 20  t bExists;.     
5870: 20 64 6f 7b 0a 20 20 20 20 20 20 20 20 6d 75 6c   do{.        mul
5880: 74 69 70 6c 65 78 46 69 6c 65 6e 61 6d 65 28 7a  tiplexFilename(z
5890: 4e 61 6d 65 2c 20 6e 4e 61 6d 65 2c 20 53 51 4c  Name, nName, SQL
58a0: 49 54 45 5f 4f 50 45 4e 5f 4d 41 49 4e 5f 4a 4f  ITE_OPEN_MAIN_JO
58b0: 55 52 4e 41 4c 2c 20 2b 2b 69 43 68 75 6e 6b 2c  URNAL, ++iChunk,
58c0: 20 7a 29 3b 0a 20 20 20 20 20 20 20 20 72 63 20   z);.        rc 
58d0: 3d 20 70 4f 72 69 67 56 66 73 2d 3e 78 41 63 63  = pOrigVfs->xAcc
58e0: 65 73 73 28 70 4f 72 69 67 56 66 73 2c 20 7a 2c  ess(pOrigVfs, z,
58f0: 20 53 51 4c 49 54 45 5f 41 43 43 45 53 53 5f 45   SQLITE_ACCESS_E
5900: 58 49 53 54 53 2c 20 26 62 45 78 69 73 74 73 29  XISTS, &bExists)
5910: 3b 0a 20 20 20 20 20 20 7d 77 68 69 6c 65 28 20  ;.      }while( 
5920: 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 26 26  rc==SQLITE_OK &&
5930: 20 62 45 78 69 73 74 73 20 29 3b 0a 20 20 20 20   bExists );.    
5940: 20 20 77 68 69 6c 65 28 20 72 63 3d 3d 53 51 4c    while( rc==SQL
5950: 49 54 45 5f 4f 4b 20 26 26 20 69 43 68 75 6e 6b  ITE_OK && iChunk
5960: 3e 31 20 29 7b 0a 20 20 20 20 20 20 20 20 6d 75  >1 ){.        mu
5970: 6c 74 69 70 6c 65 78 46 69 6c 65 6e 61 6d 65 28  ltiplexFilename(
5980: 7a 4e 61 6d 65 2c 20 6e 4e 61 6d 65 2c 20 53 51  zName, nName, SQ
5990: 4c 49 54 45 5f 4f 50 45 4e 5f 4d 41 49 4e 5f 4a  LITE_OPEN_MAIN_J
59a0: 4f 55 52 4e 41 4c 2c 20 2d 2d 69 43 68 75 6e 6b  OURNAL, --iChunk
59b0: 2c 20 7a 29 3b 0a 20 20 20 20 20 20 20 20 72 63  , z);.        rc
59c0: 20 3d 20 70 4f 72 69 67 56 66 73 2d 3e 78 44 65   = pOrigVfs->xDe
59d0: 6c 65 74 65 28 70 4f 72 69 67 56 66 73 2c 20 7a  lete(pOrigVfs, z
59e0: 2c 20 73 79 6e 63 44 69 72 29 3b 0a 20 20 20 20  , syncDir);.    
59f0: 20 20 7d 0a 20 20 20 20 20 20 69 43 68 75 6e 6b    }.      iChunk
5a00: 20 3d 20 30 3b 0a 20 20 20 20 20 20 64 6f 7b 0a   = 0;.      do{.
5a10: 20 20 20 20 20 20 20 20 6d 75 6c 74 69 70 6c 65          multiple
5a20: 78 46 69 6c 65 6e 61 6d 65 28 7a 4e 61 6d 65 2c  xFilename(zName,
5a30: 20 6e 4e 61 6d 65 2c 20 53 51 4c 49 54 45 5f 4f   nName, SQLITE_O
5a40: 50 45 4e 5f 57 41 4c 2c 20 2b 2b 69 43 68 75 6e  PEN_WAL, ++iChun
5a50: 6b 2c 20 7a 29 3b 0a 20 20 20 20 20 20 20 20 72  k, z);.        r
5a60: 63 20 3d 20 70 4f 72 69 67 56 66 73 2d 3e 78 41  c = pOrigVfs->xA
5a70: 63 63 65 73 73 28 70 4f 72 69 67 56 66 73 2c 20  ccess(pOrigVfs, 
5a80: 7a 2c 20 53 51 4c 49 54 45 5f 41 43 43 45 53 53  z, SQLITE_ACCESS
5a90: 5f 45 58 49 53 54 53 2c 20 26 62 45 78 69 73 74  _EXISTS, &bExist
5aa0: 73 29 3b 0a 20 20 20 20 20 20 7d 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 62 45 78 69 73 74 73 20 29 3b 0a 20 20  && bExists );.  
5ad0: 20 20 20 20 77 68 69 6c 65 28 20 72 63 3d 3d 53      while( rc==S
5ae0: 51 4c 49 54 45 5f 4f 4b 20 26 26 20 69 43 68 75  QLITE_OK && iChu
5af0: 6e 6b 3e 31 20 29 7b 0a 20 20 20 20 20 20 20 20  nk>1 ){.        
5b00: 6d 75 6c 74 69 70 6c 65 78 46 69 6c 65 6e 61 6d  multiplexFilenam
5b10: 65 28 7a 4e 61 6d 65 2c 20 6e 4e 61 6d 65 2c 20  e(zName, nName, 
5b20: 53 51 4c 49 54 45 5f 4f 50 45 4e 5f 57 41 4c 2c  SQLITE_OPEN_WAL,
5b30: 20 2d 2d 69 43 68 75 6e 6b 2c 20 7a 29 3b 0a 20   --iChunk, z);. 
5b40: 20 20 20 20 20 20 20 72 63 20 3d 20 70 4f 72 69         rc = pOri
5b50: 67 56 66 73 2d 3e 78 44 65 6c 65 74 65 28 70 4f  gVfs->xDelete(pO
5b60: 72 69 67 56 66 73 2c 20 7a 2c 20 73 79 6e 63 44  rigVfs, z, syncD
5b70: 69 72 29 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20  ir);.      }.   
5b80: 20 7d 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 66   }.    sqlite3_f
5b90: 72 65 65 28 7a 29 3b 0a 20 20 7d 0a 20 20 72 65  ree(z);.  }.  re
5ba0: 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 73 74 61 74  turn rc;.}..stat
5bb0: 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78  ic int multiplex
5bc0: 41 63 63 65 73 73 28 73 71 6c 69 74 65 33 5f 76  Access(sqlite3_v
5bd0: 66 73 20 2a 61 2c 20 63 6f 6e 73 74 20 63 68 61  fs *a, const cha
5be0: 72 20 2a 62 2c 20 69 6e 74 20 63 2c 20 69 6e 74  r *b, int c, int
5bf0: 20 2a 64 29 7b 0a 20 20 72 65 74 75 72 6e 20 67   *d){.  return g
5c00: 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56  Multiplex.pOrigV
5c10: 66 73 2d 3e 78 41 63 63 65 73 73 28 67 4d 75 6c  fs->xAccess(gMul
5c20: 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2c  tiplex.pOrigVfs,
5c30: 20 62 2c 20 63 2c 20 64 29 3b 0a 7d 0a 73 74 61   b, c, d);.}.sta
5c40: 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65  tic int multiple
5c50: 78 46 75 6c 6c 50 61 74 68 6e 61 6d 65 28 73 71  xFullPathname(sq
5c60: 6c 69 74 65 33 5f 76 66 73 20 2a 61 2c 20 63 6f  lite3_vfs *a, co
5c70: 6e 73 74 20 63 68 61 72 20 2a 62 2c 20 69 6e 74  nst char *b, int
5c80: 20 63 2c 20 63 68 61 72 20 2a 64 29 7b 0a 20 20   c, char *d){.  
5c90: 72 65 74 75 72 6e 20 67 4d 75 6c 74 69 70 6c 65  return gMultiple
5ca0: 78 2e 70 4f 72 69 67 56 66 73 2d 3e 78 46 75 6c  x.pOrigVfs->xFul
5cb0: 6c 50 61 74 68 6e 61 6d 65 28 67 4d 75 6c 74 69  lPathname(gMulti
5cc0: 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2c 20 62  plex.pOrigVfs, b
5cd0: 2c 20 63 2c 20 64 29 3b 0a 7d 0a 73 74 61 74 69  , c, d);.}.stati
5ce0: 63 20 76 6f 69 64 20 2a 6d 75 6c 74 69 70 6c 65  c void *multiple
5cf0: 78 44 6c 4f 70 65 6e 28 73 71 6c 69 74 65 33 5f  xDlOpen(sqlite3_
5d00: 76 66 73 20 2a 61 2c 20 63 6f 6e 73 74 20 63 68  vfs *a, const ch
5d10: 61 72 20 2a 62 29 7b 0a 20 20 72 65 74 75 72 6e  ar *b){.  return
5d20: 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69   gMultiplex.pOri
5d30: 67 56 66 73 2d 3e 78 44 6c 4f 70 65 6e 28 67 4d  gVfs->xDlOpen(gM
5d40: 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66  ultiplex.pOrigVf
5d50: 73 2c 20 62 29 3b 0a 7d 0a 73 74 61 74 69 63 20  s, b);.}.static 
5d60: 76 6f 69 64 20 6d 75 6c 74 69 70 6c 65 78 44 6c  void multiplexDl
5d70: 45 72 72 6f 72 28 73 71 6c 69 74 65 33 5f 76 66  Error(sqlite3_vf
5d80: 73 20 2a 61 2c 20 69 6e 74 20 62 2c 20 63 68 61  s *a, int b, cha
5d90: 72 20 2a 63 29 7b 0a 20 20 67 4d 75 6c 74 69 70  r *c){.  gMultip
5da0: 6c 65 78 2e 70 4f 72 69 67 56 66 73 2d 3e 78 44  lex.pOrigVfs->xD
5db0: 6c 45 72 72 6f 72 28 67 4d 75 6c 74 69 70 6c 65  lError(gMultiple
5dc0: 78 2e 70 4f 72 69 67 56 66 73 2c 20 62 2c 20 63  x.pOrigVfs, b, c
5dd0: 29 3b 0a 7d 0a 73 74 61 74 69 63 20 76 6f 69 64  );.}.static void
5de0: 20 28 2a 6d 75 6c 74 69 70 6c 65 78 44 6c 53 79   (*multiplexDlSy
5df0: 6d 28 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 61  m(sqlite3_vfs *a
5e00: 2c 20 76 6f 69 64 20 2a 62 2c 20 63 6f 6e 73 74  , void *b, const
5e10: 20 63 68 61 72 20 2a 63 29 29 28 76 6f 69 64 29   char *c))(void)
5e20: 7b 0a 20 20 72 65 74 75 72 6e 20 67 4d 75 6c 74  {.  return gMult
5e30: 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2d 3e  iplex.pOrigVfs->
5e40: 78 44 6c 53 79 6d 28 67 4d 75 6c 74 69 70 6c 65  xDlSym(gMultiple
5e50: 78 2e 70 4f 72 69 67 56 66 73 2c 20 62 2c 20 63  x.pOrigVfs, b, c
5e60: 29 3b 0a 7d 0a 73 74 61 74 69 63 20 76 6f 69 64  );.}.static void
5e70: 20 6d 75 6c 74 69 70 6c 65 78 44 6c 43 6c 6f 73   multiplexDlClos
5e80: 65 28 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 61  e(sqlite3_vfs *a
5e90: 2c 20 76 6f 69 64 20 2a 62 29 7b 0a 20 20 67 4d  , void *b){.  gM
5ea0: 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66  ultiplex.pOrigVf
5eb0: 73 2d 3e 78 44 6c 43 6c 6f 73 65 28 67 4d 75 6c  s->xDlClose(gMul
5ec0: 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2c  tiplex.pOrigVfs,
5ed0: 20 62 29 3b 0a 7d 0a 73 74 61 74 69 63 20 69 6e   b);.}.static in
5ee0: 74 20 6d 75 6c 74 69 70 6c 65 78 52 61 6e 64 6f  t multiplexRando
5ef0: 6d 6e 65 73 73 28 73 71 6c 69 74 65 33 5f 76 66  mness(sqlite3_vf
5f00: 73 20 2a 61 2c 20 69 6e 74 20 62 2c 20 63 68 61  s *a, int b, cha
5f10: 72 20 2a 63 29 7b 0a 20 20 72 65 74 75 72 6e 20  r *c){.  return 
5f20: 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67  gMultiplex.pOrig
5f30: 56 66 73 2d 3e 78 52 61 6e 64 6f 6d 6e 65 73 73  Vfs->xRandomness
5f40: 28 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69  (gMultiplex.pOri
5f50: 67 56 66 73 2c 20 62 2c 20 63 29 3b 0a 7d 0a 73  gVfs, b, c);.}.s
5f60: 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70  tatic int multip
5f70: 6c 65 78 53 6c 65 65 70 28 73 71 6c 69 74 65 33  lexSleep(sqlite3
5f80: 5f 76 66 73 20 2a 61 2c 20 69 6e 74 20 62 29 7b  _vfs *a, int b){
5f90: 0a 20 20 72 65 74 75 72 6e 20 67 4d 75 6c 74 69  .  return gMulti
5fa0: 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2d 3e 78  plex.pOrigVfs->x
5fb0: 53 6c 65 65 70 28 67 4d 75 6c 74 69 70 6c 65 78  Sleep(gMultiplex
5fc0: 2e 70 4f 72 69 67 56 66 73 2c 20 62 29 3b 0a 7d  .pOrigVfs, b);.}
5fd0: 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74  .static int mult
5fe0: 69 70 6c 65 78 43 75 72 72 65 6e 74 54 69 6d 65  iplexCurrentTime
5ff0: 28 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 61 2c  (sqlite3_vfs *a,
6000: 20 64 6f 75 62 6c 65 20 2a 62 29 7b 0a 20 20 72   double *b){.  r
6010: 65 74 75 72 6e 20 67 4d 75 6c 74 69 70 6c 65 78  eturn gMultiplex
6020: 2e 70 4f 72 69 67 56 66 73 2d 3e 78 43 75 72 72  .pOrigVfs->xCurr
6030: 65 6e 74 54 69 6d 65 28 67 4d 75 6c 74 69 70 6c  entTime(gMultipl
6040: 65 78 2e 70 4f 72 69 67 56 66 73 2c 20 62 29 3b  ex.pOrigVfs, b);
6050: 0a 7d 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75  .}.static int mu
6060: 6c 74 69 70 6c 65 78 47 65 74 4c 61 73 74 45 72  ltiplexGetLastEr
6070: 72 6f 72 28 73 71 6c 69 74 65 33 5f 76 66 73 20  ror(sqlite3_vfs 
6080: 2a 61 2c 20 69 6e 74 20 62 2c 20 63 68 61 72 20  *a, int b, char 
6090: 2a 63 29 7b 0a 20 20 72 65 74 75 72 6e 20 67 4d  *c){.  return gM
60a0: 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66  ultiplex.pOrigVf
60b0: 73 2d 3e 78 47 65 74 4c 61 73 74 45 72 72 6f 72  s->xGetLastError
60c0: 28 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69  (gMultiplex.pOri
60d0: 67 56 66 73 2c 20 62 2c 20 63 29 3b 0a 7d 0a 73  gVfs, b, c);.}.s
60e0: 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70  tatic int multip
60f0: 6c 65 78 43 75 72 72 65 6e 74 54 69 6d 65 49 6e  lexCurrentTimeIn
6100: 74 36 34 28 73 71 6c 69 74 65 33 5f 76 66 73 20  t64(sqlite3_vfs 
6110: 2a 61 2c 20 73 71 6c 69 74 65 33 5f 69 6e 74 36  *a, sqlite3_int6
6120: 34 20 2a 62 29 7b 0a 20 20 72 65 74 75 72 6e 20  4 *b){.  return 
6130: 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67  gMultiplex.pOrig
6140: 56 66 73 2d 3e 78 43 75 72 72 65 6e 74 54 69 6d  Vfs->xCurrentTim
6150: 65 49 6e 74 36 34 28 67 4d 75 6c 74 69 70 6c 65  eInt64(gMultiple
6160: 78 2e 70 4f 72 69 67 56 66 73 2c 20 62 29 3b 0a  x.pOrigVfs, b);.
6170: 7d 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  }../************
6180: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20 49 2f 4f  ************ I/O
6190: 20 4d 65 74 68 6f 64 20 57 72 61 70 70 65 72 73   Method Wrappers
61a0: 20 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a   ***************
61b0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
61c0: 2f 0a 0a 2f 2a 20 78 43 6c 6f 73 65 20 72 65 71  /../* xClose req
61d0: 75 65 73 74 73 20 67 65 74 20 70 61 73 73 65 64  uests get passed
61e0: 20 74 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20   through to the 
61f0: 6f 72 69 67 69 6e 61 6c 20 56 46 53 2e 0a 2a 2a  original VFS..**
6200: 20 57 65 20 6c 6f 6f 70 20 6f 76 65 72 20 61 6c   We loop over al
6210: 6c 20 6f 70 65 6e 20 63 68 75 6e 6b 20 68 61 6e  l open chunk han
6220: 64 6c 65 73 20 61 6e 64 20 63 6c 6f 73 65 20 74  dles and close t
6230: 68 65 6d 2e 0a 2a 2a 20 54 68 65 20 67 72 6f 75  hem..** The grou
6240: 70 20 73 74 72 75 63 74 75 72 65 20 66 6f 72 20  p structure for 
6250: 74 68 69 73 20 66 69 6c 65 20 69 73 20 75 6e 6c  this file is unl
6260: 69 6e 6b 65 64 20 66 72 6f 6d 20 0a 2a 2a 20 6f  inked from .** o
6270: 75 72 20 6c 69 73 74 20 6f 66 20 67 72 6f 75 70  ur list of group
6280: 73 20 61 6e 64 20 66 72 65 65 64 2e 0a 2a 2f 0a  s and freed..*/.
6290: 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69  static int multi
62a0: 70 6c 65 78 43 6c 6f 73 65 28 73 71 6c 69 74 65  plexClose(sqlite
62b0: 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 29 7b 0a  3_file *pConn){.
62c0: 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20    multiplexConn 
62d0: 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43  *p = (multiplexC
62e0: 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 6d 75  onn*)pConn;.  mu
62f0: 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 2a 70 47  ltiplexGroup *pG
6300: 72 6f 75 70 20 3d 20 70 2d 3e 70 47 72 6f 75 70  roup = p->pGroup
6310: 3b 0a 20 20 69 6e 74 20 72 63 20 3d 20 53 51 4c  ;.  int rc = SQL
6320: 49 54 45 5f 4f 4b 3b 0a 20 20 6d 75 6c 74 69 70  ITE_OK;.  multip
6330: 6c 65 78 45 6e 74 65 72 28 29 3b 0a 20 20 6d 75  lexEnter();.  mu
6340: 6c 74 69 70 6c 65 78 46 72 65 65 43 6f 6d 70 6f  ltiplexFreeCompo
6350: 6e 65 6e 74 73 28 70 47 72 6f 75 70 29 3b 0a 20  nents(pGroup);. 
6360: 20 2f 2a 20 72 65 6d 6f 76 65 20 66 72 6f 6d 20   /* remove from 
6370: 6c 69 6e 6b 65 64 20 6c 69 73 74 20 2a 2f 0a 20  linked list */. 
6380: 20 69 66 28 20 70 47 72 6f 75 70 2d 3e 70 4e 65   if( pGroup->pNe
6390: 78 74 20 29 20 70 47 72 6f 75 70 2d 3e 70 4e 65  xt ) pGroup->pNe
63a0: 78 74 2d 3e 70 50 72 65 76 20 3d 20 70 47 72 6f  xt->pPrev = pGro
63b0: 75 70 2d 3e 70 50 72 65 76 3b 0a 20 20 69 66 28  up->pPrev;.  if(
63c0: 20 70 47 72 6f 75 70 2d 3e 70 50 72 65 76 20 29   pGroup->pPrev )
63d0: 7b 0a 20 20 20 20 70 47 72 6f 75 70 2d 3e 70 50  {.    pGroup->pP
63e0: 72 65 76 2d 3e 70 4e 65 78 74 20 3d 20 70 47 72  rev->pNext = pGr
63f0: 6f 75 70 2d 3e 70 4e 65 78 74 3b 0a 20 20 7d 65  oup->pNext;.  }e
6400: 6c 73 65 7b 0a 20 20 20 20 67 4d 75 6c 74 69 70  lse{.    gMultip
6410: 6c 65 78 2e 70 47 72 6f 75 70 73 20 3d 20 70 47  lex.pGroups = pG
6420: 72 6f 75 70 2d 3e 70 4e 65 78 74 3b 0a 20 20 7d  roup->pNext;.  }
6430: 0a 20 20 73 71 6c 69 74 65 33 5f 66 72 65 65 28  .  sqlite3_free(
6440: 70 47 72 6f 75 70 29 3b 0a 20 20 6d 75 6c 74 69  pGroup);.  multi
6450: 70 6c 65 78 4c 65 61 76 65 28 29 3b 0a 20 20 72  plexLeave();.  r
6460: 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 20  eturn rc;.}../* 
6470: 50 61 73 73 20 78 52 65 61 64 20 72 65 71 75 65  Pass xRead reque
6480: 73 74 73 20 74 68 72 75 20 74 6f 20 74 68 65 20  sts thru to the 
6490: 6f 72 69 67 69 6e 61 6c 20 56 46 53 20 61 66 74  original VFS aft
64a0: 65 72 0a 2a 2a 20 64 65 74 65 72 6d 69 6e 69 6e  er.** determinin
64b0: 67 20 74 68 65 20 63 6f 72 72 65 63 74 20 63 68  g the correct ch
64c0: 75 6e 6b 20 74 6f 20 6f 70 65 72 61 74 65 20 6f  unk to operate o
64d0: 6e 2e 0a 2a 2a 20 42 72 65 61 6b 20 75 70 20 72  n..** Break up r
64e0: 65 61 64 73 20 61 63 72 6f 73 73 20 63 68 75 6e  eads across chun
64f0: 6b 20 62 6f 75 6e 64 61 72 69 65 73 2e 0a 2a 2f  k boundaries..*/
6500: 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74  .static int mult
6510: 69 70 6c 65 78 52 65 61 64 28 0a 20 20 73 71 6c  iplexRead(.  sql
6520: 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e  ite3_file *pConn
6530: 2c 0a 20 20 76 6f 69 64 20 2a 70 42 75 66 2c 0a  ,.  void *pBuf,.
6540: 20 20 69 6e 74 20 69 41 6d 74 2c 0a 20 20 73 71    int iAmt,.  sq
6550: 6c 69 74 65 33 5f 69 6e 74 36 34 20 69 4f 66 73  lite3_int64 iOfs
6560: 74 0a 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78  t.){.  multiplex
6570: 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69  Conn *p = (multi
6580: 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b  plexConn*)pConn;
6590: 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75  .  multiplexGrou
65a0: 70 20 2a 70 47 72 6f 75 70 20 3d 20 70 2d 3e 70  p *pGroup = p->p
65b0: 47 72 6f 75 70 3b 0a 20 20 69 6e 74 20 72 63 20  Group;.  int rc 
65c0: 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 6d  = SQLITE_OK;.  m
65d0: 75 6c 74 69 70 6c 65 78 45 6e 74 65 72 28 29 3b  ultiplexEnter();
65e0: 0a 20 20 69 66 28 20 21 70 47 72 6f 75 70 2d 3e  .  if( !pGroup->
65f0: 62 45 6e 61 62 6c 65 64 20 29 7b 0a 20 20 20 20  bEnabled ){.    
6600: 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53  sqlite3_file *pS
6610: 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c  ubOpen = multipl
6620: 65 78 53 75 62 4f 70 65 6e 28 70 47 72 6f 75 70  exSubOpen(pGroup
6630: 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 2c 20  , 0, &rc, NULL, 
6640: 30 29 3b 0a 20 20 20 20 69 66 28 20 70 53 75 62  0);.    if( pSub
6650: 4f 70 65 6e 3d 3d 30 20 29 7b 0a 20 20 20 20 20  Open==0 ){.     
6660: 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 49 4f 45   rc = SQLITE_IOE
6670: 52 52 5f 52 45 41 44 3b 0a 20 20 20 20 7d 65 6c  RR_READ;.    }el
6680: 73 65 7b 0a 20 20 20 20 20 20 72 63 20 3d 20 70  se{.      rc = p
6690: 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64  SubOpen->pMethod
66a0: 73 2d 3e 78 52 65 61 64 28 70 53 75 62 4f 70 65  s->xRead(pSubOpe
66b0: 6e 2c 20 70 42 75 66 2c 20 69 41 6d 74 2c 20 69  n, pBuf, iAmt, i
66c0: 4f 66 73 74 29 3b 0a 20 20 20 20 7d 0a 20 20 7d  Ofst);.    }.  }
66d0: 65 6c 73 65 7b 0a 20 20 20 20 77 68 69 6c 65 28  else{.    while(
66e0: 20 69 41 6d 74 20 3e 20 30 20 29 7b 0a 20 20 20   iAmt > 0 ){.   
66f0: 20 20 20 69 6e 74 20 69 20 3d 20 28 69 6e 74 29     int i = (int)
6700: 28 69 4f 66 73 74 20 2f 20 70 47 72 6f 75 70 2d  (iOfst / pGroup-
6710: 3e 73 7a 43 68 75 6e 6b 29 3b 0a 20 20 20 20 20  >szChunk);.     
6720: 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70   sqlite3_file *p
6730: 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70  SubOpen = multip
6740: 6c 65 78 53 75 62 4f 70 65 6e 28 70 47 72 6f 75  lexSubOpen(pGrou
6750: 70 2c 20 69 2c 20 26 72 63 2c 20 4e 55 4c 4c 2c  p, i, &rc, NULL,
6760: 20 31 29 3b 0a 20 20 20 20 20 20 69 66 28 20 70   1);.      if( p
6770: 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20 20  SubOpen ){.     
6780: 20 20 20 69 6e 74 20 65 78 74 72 61 20 3d 20 28     int extra = (
6790: 28 69 6e 74 29 28 69 4f 66 73 74 20 25 20 70 47  (int)(iOfst % pG
67a0: 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 29 20 2b  roup->szChunk) +
67b0: 20 69 41 6d 74 29 20 2d 20 70 47 72 6f 75 70 2d   iAmt) - pGroup-
67c0: 3e 73 7a 43 68 75 6e 6b 3b 0a 20 20 20 20 20 20  >szChunk;.      
67d0: 20 20 69 66 28 20 65 78 74 72 61 3c 30 20 29 20    if( extra<0 ) 
67e0: 65 78 74 72 61 20 3d 20 30 3b 0a 20 20 20 20 20  extra = 0;.     
67f0: 20 20 20 69 41 6d 74 20 2d 3d 20 65 78 74 72 61     iAmt -= extra
6800: 3b 0a 20 20 20 20 20 20 20 20 72 63 20 3d 20 70  ;.        rc = p
6810: 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64  SubOpen->pMethod
6820: 73 2d 3e 78 52 65 61 64 28 70 53 75 62 4f 70 65  s->xRead(pSubOpe
6830: 6e 2c 20 70 42 75 66 2c 20 69 41 6d 74 2c 0a 20  n, pBuf, iAmt,. 
6840: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6850: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6860: 20 20 20 20 20 20 69 4f 66 73 74 20 25 20 70 47        iOfst % pG
6870: 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 29 3b 0a  roup->szChunk);.
6880: 20 20 20 20 20 20 20 20 69 66 28 20 72 63 21 3d          if( rc!=
6890: 53 51 4c 49 54 45 5f 4f 4b 20 29 20 62 72 65 61  SQLITE_OK ) brea
68a0: 6b 3b 0a 20 20 20 20 20 20 20 20 70 42 75 66 20  k;.        pBuf 
68b0: 3d 20 28 63 68 61 72 20 2a 29 70 42 75 66 20 2b  = (char *)pBuf +
68c0: 20 69 41 6d 74 3b 0a 20 20 20 20 20 20 20 20 69   iAmt;.        i
68d0: 4f 66 73 74 20 2b 3d 20 69 41 6d 74 3b 0a 20 20  Ofst += iAmt;.  
68e0: 20 20 20 20 20 20 69 41 6d 74 20 3d 20 65 78 74        iAmt = ext
68f0: 72 61 3b 0a 20 20 20 20 20 20 7d 65 6c 73 65 7b  ra;.      }else{
6900: 0a 20 20 20 20 20 20 20 20 72 63 20 3d 20 53 51  .        rc = SQ
6910: 4c 49 54 45 5f 49 4f 45 52 52 5f 52 45 41 44 3b  LITE_IOERR_READ;
6920: 0a 20 20 20 20 20 20 20 20 62 72 65 61 6b 3b 0a  .        break;.
6930: 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a 20 20        }.    }.  
6940: 7d 0a 20 20 6d 75 6c 74 69 70 6c 65 78 4c 65 61  }.  multiplexLea
6950: 76 65 28 29 3b 0a 20 20 72 65 74 75 72 6e 20 72  ve();.  return r
6960: 63 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 57  c;.}../* Pass xW
6970: 72 69 74 65 20 72 65 71 75 65 73 74 73 20 74 68  rite requests th
6980: 72 75 20 74 6f 20 74 68 65 20 6f 72 69 67 69 6e  ru to the origin
6990: 61 6c 20 56 46 53 20 61 66 74 65 72 0a 2a 2a 20  al VFS after.** 
69a0: 64 65 74 65 72 6d 69 6e 69 6e 67 20 74 68 65 20  determining the 
69b0: 63 6f 72 72 65 63 74 20 63 68 75 6e 6b 20 74 6f  correct chunk to
69c0: 20 6f 70 65 72 61 74 65 20 6f 6e 2e 0a 2a 2a 20   operate on..** 
69d0: 42 72 65 61 6b 20 75 70 20 77 72 69 74 65 73 20  Break up writes 
69e0: 61 63 72 6f 73 73 20 63 68 75 6e 6b 20 62 6f 75  across chunk bou
69f0: 6e 64 61 72 69 65 73 2e 0a 2a 2f 0a 73 74 61 74  ndaries..*/.stat
6a00: 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78  ic int multiplex
6a10: 57 72 69 74 65 28 0a 20 20 73 71 6c 69 74 65 33  Write(.  sqlite3
6a20: 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c 0a 20 20  _file *pConn,.  
6a30: 63 6f 6e 73 74 20 76 6f 69 64 20 2a 70 42 75 66  const void *pBuf
6a40: 2c 0a 20 20 69 6e 74 20 69 41 6d 74 2c 0a 20 20  ,.  int iAmt,.  
6a50: 73 71 6c 69 74 65 33 5f 69 6e 74 36 34 20 69 4f  sqlite3_int64 iO
6a60: 66 73 74 0a 29 7b 0a 20 20 6d 75 6c 74 69 70 6c  fst.){.  multipl
6a70: 65 78 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c  exConn *p = (mul
6a80: 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e  tiplexConn*)pCon
6a90: 6e 3b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47 72  n;.  multiplexGr
6aa0: 6f 75 70 20 2a 70 47 72 6f 75 70 20 3d 20 70 2d  oup *pGroup = p-
6ab0: 3e 70 47 72 6f 75 70 3b 0a 20 20 69 6e 74 20 72  >pGroup;.  int r
6ac0: 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20  c = SQLITE_OK;. 
6ad0: 20 6d 75 6c 74 69 70 6c 65 78 45 6e 74 65 72 28   multiplexEnter(
6ae0: 29 3b 0a 20 20 69 66 28 20 21 70 47 72 6f 75 70  );.  if( !pGroup
6af0: 2d 3e 62 45 6e 61 62 6c 65 64 20 29 7b 0a 20 20  ->bEnabled ){.  
6b00: 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a    sqlite3_file *
6b10: 70 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69  pSubOpen = multi
6b20: 70 6c 65 78 53 75 62 4f 70 65 6e 28 70 47 72 6f  plexSubOpen(pGro
6b30: 75 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c  up, 0, &rc, NULL
6b40: 2c 20 30 29 3b 0a 20 20 20 20 69 66 28 20 70 53  , 0);.    if( pS
6b50: 75 62 4f 70 65 6e 3d 3d 30 20 29 7b 0a 20 20 20  ubOpen==0 ){.   
6b60: 20 20 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 49     rc = SQLITE_I
6b70: 4f 45 52 52 5f 57 52 49 54 45 3b 0a 20 20 20 20  OERR_WRITE;.    
6b80: 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 72 63 20  }else{.      rc 
6b90: 3d 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74  = pSubOpen->pMet
6ba0: 68 6f 64 73 2d 3e 78 57 72 69 74 65 28 70 53 75  hods->xWrite(pSu
6bb0: 62 4f 70 65 6e 2c 20 70 42 75 66 2c 20 69 41 6d  bOpen, pBuf, iAm
6bc0: 74 2c 20 69 4f 66 73 74 29 3b 0a 20 20 20 20 7d  t, iOfst);.    }
6bd0: 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 77 68  .  }else{.    wh
6be0: 69 6c 65 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f  ile( rc==SQLITE_
6bf0: 4f 4b 20 26 26 20 69 41 6d 74 3e 30 20 29 7b 0a  OK && iAmt>0 ){.
6c00: 20 20 20 20 20 20 69 6e 74 20 69 20 3d 20 28 69        int i = (i
6c10: 6e 74 29 28 69 4f 66 73 74 20 2f 20 70 47 72 6f  nt)(iOfst / pGro
6c20: 75 70 2d 3e 73 7a 43 68 75 6e 6b 29 3b 0a 20 20  up->szChunk);.  
6c30: 20 20 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65      sqlite3_file
6c40: 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c   *pSubOpen = mul
6c50: 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28 70 47  tiplexSubOpen(pG
6c60: 72 6f 75 70 2c 20 69 2c 20 26 72 63 2c 20 4e 55  roup, i, &rc, NU
6c70: 4c 4c 2c 20 31 29 3b 0a 20 20 20 20 20 20 69 66  LL, 1);.      if
6c80: 28 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20  ( pSubOpen ){.  
6c90: 20 20 20 20 20 20 69 6e 74 20 65 78 74 72 61 20        int extra 
6ca0: 3d 20 28 28 69 6e 74 29 28 69 4f 66 73 74 20 25  = ((int)(iOfst %
6cb0: 20 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b   pGroup->szChunk
6cc0: 29 20 2b 20 69 41 6d 74 29 20 2d 0a 20 20 20 20  ) + iAmt) -.    
6cd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6ce0: 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 3b  pGroup->szChunk;
6cf0: 0a 20 20 20 20 20 20 20 20 69 66 28 20 65 78 74  .        if( ext
6d00: 72 61 3c 30 20 29 20 65 78 74 72 61 20 3d 20 30  ra<0 ) extra = 0
6d10: 3b 0a 20 20 20 20 20 20 20 20 69 41 6d 74 20 2d  ;.        iAmt -
6d20: 3d 20 65 78 74 72 61 3b 0a 20 20 20 20 20 20 20  = extra;.       
6d30: 20 72 63 20 3d 20 70 53 75 62 4f 70 65 6e 2d 3e   rc = pSubOpen->
6d40: 70 4d 65 74 68 6f 64 73 2d 3e 78 57 72 69 74 65  pMethods->xWrite
6d50: 28 70 53 75 62 4f 70 65 6e 2c 20 70 42 75 66 2c  (pSubOpen, pBuf,
6d60: 20 69 41 6d 74 2c 0a 20 20 20 20 20 20 20 20 20   iAmt,.         
6d70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6d80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69                 i
6d90: 4f 66 73 74 20 25 20 70 47 72 6f 75 70 2d 3e 73  Ofst % pGroup->s
6da0: 7a 43 68 75 6e 6b 29 3b 0a 20 20 20 20 20 20 20  zChunk);.       
6db0: 20 70 42 75 66 20 3d 20 28 63 68 61 72 20 2a 29   pBuf = (char *)
6dc0: 70 42 75 66 20 2b 20 69 41 6d 74 3b 0a 20 20 20  pBuf + iAmt;.   
6dd0: 20 20 20 20 20 69 4f 66 73 74 20 2b 3d 20 69 41       iOfst += iA
6de0: 6d 74 3b 0a 20 20 20 20 20 20 20 20 69 41 6d 74  mt;.        iAmt
6df0: 20 3d 20 65 78 74 72 61 3b 0a 20 20 20 20 20 20   = extra;.      
6e00: 7d 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20 6d 75  }.    }.  }.  mu
6e10: 6c 74 69 70 6c 65 78 4c 65 61 76 65 28 29 3b 0a  ltiplexLeave();.
6e20: 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a    return rc;.}..
6e30: 2f 2a 20 50 61 73 73 20 78 54 72 75 6e 63 61 74  /* Pass xTruncat
6e40: 65 20 72 65 71 75 65 73 74 73 20 74 68 72 75 20  e requests thru 
6e50: 74 6f 20 74 68 65 20 6f 72 69 67 69 6e 61 6c 20  to the original 
6e60: 56 46 53 20 61 66 74 65 72 0a 2a 2a 20 64 65 74  VFS after.** det
6e70: 65 72 6d 69 6e 69 6e 67 20 74 68 65 20 63 6f 72  ermining the cor
6e80: 72 65 63 74 20 63 68 75 6e 6b 20 74 6f 20 6f 70  rect chunk to op
6e90: 65 72 61 74 65 20 6f 6e 2e 20 20 44 65 6c 65 74  erate on.  Delet
6ea0: 65 20 61 6e 79 0a 2a 2a 20 63 68 75 6e 6b 73 20  e any.** chunks 
6eb0: 61 62 6f 76 65 20 74 68 65 20 74 72 75 6e 63 61  above the trunca
6ec0: 74 65 20 6d 61 72 6b 2e 0a 2a 2f 0a 73 74 61 74  te mark..*/.stat
6ed0: 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78  ic int multiplex
6ee0: 54 72 75 6e 63 61 74 65 28 73 71 6c 69 74 65 33  Truncate(sqlite3
6ef0: 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c 20 73 71  _file *pConn, sq
6f00: 6c 69 74 65 33 5f 69 6e 74 36 34 20 73 69 7a 65  lite3_int64 size
6f10: 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f  ){.  multiplexCo
6f20: 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c  nn *p = (multipl
6f30: 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20  exConn*)pConn;. 
6f40: 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 20   multiplexGroup 
6f50: 2a 70 47 72 6f 75 70 20 3d 20 70 2d 3e 70 47 72  *pGroup = p->pGr
6f60: 6f 75 70 3b 0a 20 20 69 6e 74 20 72 63 20 3d 20  oup;.  int rc = 
6f70: 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 6d 75 6c  SQLITE_OK;.  mul
6f80: 74 69 70 6c 65 78 45 6e 74 65 72 28 29 3b 0a 20  tiplexEnter();. 
6f90: 20 69 66 28 20 21 70 47 72 6f 75 70 2d 3e 62 45   if( !pGroup->bE
6fa0: 6e 61 62 6c 65 64 20 29 7b 0a 20 20 20 20 73 71  nabled ){.    sq
6fb0: 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62  lite3_file *pSub
6fc0: 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78  Open = multiplex
6fd0: 53 75 62 4f 70 65 6e 28 70 47 72 6f 75 70 2c 20  SubOpen(pGroup, 
6fe0: 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 2c 20 30 29  0, &rc, NULL, 0)
6ff0: 3b 0a 20 20 20 20 69 66 28 20 70 53 75 62 4f 70  ;.    if( pSubOp
7000: 65 6e 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 72  en==0 ){.      r
7010: 63 20 3d 20 53 51 4c 49 54 45 5f 49 4f 45 52 52  c = SQLITE_IOERR
7020: 5f 54 52 55 4e 43 41 54 45 3b 0a 20 20 20 20 7d  _TRUNCATE;.    }
7030: 65 6c 73 65 7b 0a 20 20 20 20 20 20 72 63 20 3d  else{.      rc =
7040: 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68   pSubOpen->pMeth
7050: 6f 64 73 2d 3e 78 54 72 75 6e 63 61 74 65 28 70  ods->xTruncate(p
7060: 53 75 62 4f 70 65 6e 2c 20 73 69 7a 65 29 3b 0a  SubOpen, size);.
7070: 20 20 20 20 7d 0a 20 20 7d 65 6c 73 65 7b 0a 20      }.  }else{. 
7080: 20 20 20 69 6e 74 20 69 3b 0a 20 20 20 20 69 6e     int i;.    in
7090: 74 20 69 42 61 73 65 47 72 6f 75 70 20 3d 20 28  t iBaseGroup = (
70a0: 69 6e 74 29 28 73 69 7a 65 20 2f 20 70 47 72 6f  int)(size / pGro
70b0: 75 70 2d 3e 73 7a 43 68 75 6e 6b 29 3b 0a 20 20  up->szChunk);.  
70c0: 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a    sqlite3_file *
70d0: 70 53 75 62 4f 70 65 6e 3b 0a 20 20 20 20 73 71  pSubOpen;.    sq
70e0: 6c 69 74 65 33 5f 76 66 73 20 2a 70 4f 72 69 67  lite3_vfs *pOrig
70f0: 56 66 73 20 3d 20 67 4d 75 6c 74 69 70 6c 65 78  Vfs = gMultiplex
7100: 2e 70 4f 72 69 67 56 66 73 3b 20 20 20 2f 2a 20  .pOrigVfs;   /* 
7110: 52 65 61 6c 20 56 46 53 20 2a 2f 0a 20 20 20 20  Real VFS */.    
7120: 2f 2a 20 64 65 6c 65 74 65 20 74 68 65 20 63 68  /* delete the ch
7130: 75 6e 6b 73 20 61 62 6f 76 65 20 74 68 65 20 74  unks above the t
7140: 72 75 6e 63 61 74 65 20 6c 69 6d 69 74 20 2a 2f  runcate limit */
7150: 0a 20 20 20 20 66 6f 72 28 69 20 3d 20 70 47 72  .    for(i = pGr
7160: 6f 75 70 2d 3e 6e 52 65 61 6c 2d 31 3b 20 69 3e  oup->nReal-1; i>
7170: 69 42 61 73 65 47 72 6f 75 70 20 26 26 20 72 63  iBaseGroup && rc
7180: 3d 3d 53 51 4c 49 54 45 5f 4f 4b 3b 20 69 2d 2d  ==SQLITE_OK; i--
7190: 29 7b 0a 20 20 20 20 20 20 69 66 28 20 70 47 72  ){.      if( pGr
71a0: 6f 75 70 2d 3e 62 54 72 75 6e 63 61 74 65 20 29  oup->bTruncate )
71b0: 7b 0a 20 20 20 20 20 20 20 20 6d 75 6c 74 69 70  {.        multip
71c0: 6c 65 78 53 75 62 43 6c 6f 73 65 28 70 47 72 6f  lexSubClose(pGro
71d0: 75 70 2c 20 69 2c 20 70 4f 72 69 67 56 66 73 29  up, i, pOrigVfs)
71e0: 3b 0a 20 20 20 20 20 20 7d 65 6c 73 65 7b 0a 20  ;.      }else{. 
71f0: 20 20 20 20 20 20 20 70 53 75 62 4f 70 65 6e 20         pSubOpen 
7200: 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70  = multiplexSubOp
7210: 65 6e 28 70 47 72 6f 75 70 2c 20 69 2c 20 26 72  en(pGroup, i, &r
7220: 63 2c 20 30 2c 20 30 29 3b 0a 20 20 20 20 20 20  c, 0, 0);.      
7230: 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e 20 29    if( pSubOpen )
7240: 7b 0a 20 20 20 20 20 20 20 20 20 20 72 63 20 3d  {.          rc =
7250: 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68   pSubOpen->pMeth
7260: 6f 64 73 2d 3e 78 54 72 75 6e 63 61 74 65 28 70  ods->xTruncate(p
7270: 53 75 62 4f 70 65 6e 2c 20 30 29 3b 0a 20 20 20  SubOpen, 0);.   
7280: 20 20 20 20 20 7d 0a 20 20 20 20 20 20 7d 0a 20       }.      }. 
7290: 20 20 20 7d 0a 20 20 20 20 69 66 28 20 72 63 3d     }.    if( rc=
72a0: 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20  =SQLITE_OK ){.  
72b0: 20 20 20 20 70 53 75 62 4f 70 65 6e 20 3d 20 6d      pSubOpen = m
72c0: 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28  ultiplexSubOpen(
72d0: 70 47 72 6f 75 70 2c 20 69 42 61 73 65 47 72 6f  pGroup, iBaseGro
72e0: 75 70 2c 20 26 72 63 2c 20 30 2c 20 30 29 3b 0a  up, &rc, 0, 0);.
72f0: 20 20 20 20 20 20 69 66 28 20 70 53 75 62 4f 70        if( pSubOp
7300: 65 6e 20 29 7b 0a 20 20 20 20 20 20 20 20 72 63  en ){.        rc
7310: 20 3d 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65   = pSubOpen->pMe
7320: 74 68 6f 64 73 2d 3e 78 54 72 75 6e 63 61 74 65  thods->xTruncate
7330: 28 70 53 75 62 4f 70 65 6e 2c 20 73 69 7a 65 20  (pSubOpen, size 
7340: 25 20 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e  % pGroup->szChun
7350: 6b 29 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20 20  k);.      }.    
7360: 7d 0a 20 20 20 20 69 66 28 20 72 63 20 29 20 72  }.    if( rc ) r
7370: 63 20 3d 20 53 51 4c 49 54 45 5f 49 4f 45 52 52  c = SQLITE_IOERR
7380: 5f 54 52 55 4e 43 41 54 45 3b 0a 20 20 7d 0a 20  _TRUNCATE;.  }. 
7390: 20 6d 75 6c 74 69 70 6c 65 78 4c 65 61 76 65 28   multiplexLeave(
73a0: 29 3b 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a  );.  return rc;.
73b0: 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 53 79 6e 63  }../* Pass xSync
73c0: 20 72 65 71 75 65 73 74 73 20 74 68 72 6f 75 67   requests throug
73d0: 68 20 74 6f 20 74 68 65 20 6f 72 69 67 69 6e 61  h to the origina
73e0: 6c 20 56 46 53 20 77 69 74 68 6f 75 74 20 63 68  l VFS without ch
73f0: 61 6e 67 65 0a 2a 2f 0a 73 74 61 74 69 63 20 69  ange.*/.static i
7400: 6e 74 20 6d 75 6c 74 69 70 6c 65 78 53 79 6e 63  nt multiplexSync
7410: 28 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70  (sqlite3_file *p
7420: 43 6f 6e 6e 2c 20 69 6e 74 20 66 6c 61 67 73 29  Conn, int flags)
7430: 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e  {.  multiplexCon
7440: 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65  n *p = (multiple
7450: 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20  xConn*)pConn;.  
7460: 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 2a  multiplexGroup *
7470: 70 47 72 6f 75 70 20 3d 20 70 2d 3e 70 47 72 6f  pGroup = p->pGro
7480: 75 70 3b 0a 20 20 69 6e 74 20 72 63 20 3d 20 53  up;.  int rc = S
7490: 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 69 6e 74 20  QLITE_OK;.  int 
74a0: 69 3b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 45 6e  i;.  multiplexEn
74b0: 74 65 72 28 29 3b 0a 20 20 66 6f 72 28 69 3d 30  ter();.  for(i=0
74c0: 3b 20 69 3c 70 47 72 6f 75 70 2d 3e 6e 52 65 61  ; i<pGroup->nRea
74d0: 6c 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 73 71 6c  l; i++){.    sql
74e0: 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f  ite3_file *pSubO
74f0: 70 65 6e 20 3d 20 70 47 72 6f 75 70 2d 3e 61 52  pen = pGroup->aR
7500: 65 61 6c 5b 69 5d 2e 70 3b 0a 20 20 20 20 69 66  eal[i].p;.    if
7510: 28 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20  ( pSubOpen ){.  
7520: 20 20 20 20 69 6e 74 20 72 63 32 20 3d 20 70 53      int rc2 = pS
7530: 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73  ubOpen->pMethods
7540: 2d 3e 78 53 79 6e 63 28 70 53 75 62 4f 70 65 6e  ->xSync(pSubOpen
7550: 2c 20 66 6c 61 67 73 29 3b 0a 20 20 20 20 20 20  , flags);.      
7560: 69 66 28 20 72 63 32 21 3d 53 51 4c 49 54 45 5f  if( rc2!=SQLITE_
7570: 4f 4b 20 29 20 72 63 20 3d 20 72 63 32 3b 0a 20  OK ) rc = rc2;. 
7580: 20 20 20 7d 0a 20 20 7d 0a 20 20 6d 75 6c 74 69     }.  }.  multi
7590: 70 6c 65 78 4c 65 61 76 65 28 29 3b 0a 20 20 72  plexLeave();.  r
75a0: 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 20  eturn rc;.}../* 
75b0: 50 61 73 73 20 78 46 69 6c 65 53 69 7a 65 20 72  Pass xFileSize r
75c0: 65 71 75 65 73 74 73 20 74 68 72 6f 75 67 68 20  equests through 
75d0: 74 6f 20 74 68 65 20 6f 72 69 67 69 6e 61 6c 20  to the original 
75e0: 56 46 53 2e 0a 2a 2a 20 41 67 67 72 65 67 61 74  VFS..** Aggregat
75f0: 65 20 74 68 65 20 73 69 7a 65 20 6f 66 20 61 6c  e the size of al
7600: 6c 20 74 68 65 20 63 68 75 6e 6b 73 20 62 65 66  l the chunks bef
7610: 6f 72 65 20 72 65 74 75 72 6e 69 6e 67 2e 0a 2a  ore returning..*
7620: 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c  /.static int mul
7630: 74 69 70 6c 65 78 46 69 6c 65 53 69 7a 65 28 73  tiplexFileSize(s
7640: 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f  qlite3_file *pCo
7650: 6e 6e 2c 20 73 71 6c 69 74 65 33 5f 69 6e 74 36  nn, sqlite3_int6
7660: 34 20 2a 70 53 69 7a 65 29 7b 0a 20 20 6d 75 6c  4 *pSize){.  mul
7670: 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d 20  tiplexConn *p = 
7680: 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a 29  (multiplexConn*)
7690: 70 43 6f 6e 6e 3b 0a 20 20 6d 75 6c 74 69 70 6c  pConn;.  multipl
76a0: 65 78 47 72 6f 75 70 20 2a 70 47 72 6f 75 70 20  exGroup *pGroup 
76b0: 3d 20 70 2d 3e 70 47 72 6f 75 70 3b 0a 20 20 69  = p->pGroup;.  i
76c0: 6e 74 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f  nt rc = SQLITE_O
76d0: 4b 3b 0a 20 20 69 6e 74 20 69 3b 0a 20 20 6d 75  K;.  int i;.  mu
76e0: 6c 74 69 70 6c 65 78 45 6e 74 65 72 28 29 3b 0a  ltiplexEnter();.
76f0: 20 20 69 66 28 20 21 70 47 72 6f 75 70 2d 3e 62    if( !pGroup->b
7700: 45 6e 61 62 6c 65 64 20 29 7b 0a 20 20 20 20 73  Enabled ){.    s
7710: 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75  qlite3_file *pSu
7720: 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65  bOpen = multiple
7730: 78 53 75 62 4f 70 65 6e 28 70 47 72 6f 75 70 2c  xSubOpen(pGroup,
7740: 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 2c 20 30   0, &rc, NULL, 0
7750: 29 3b 0a 20 20 20 20 69 66 28 20 70 53 75 62 4f  );.    if( pSubO
7760: 70 65 6e 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20  pen==0 ){.      
7770: 72 63 20 3d 20 53 51 4c 49 54 45 5f 49 4f 45 52  rc = SQLITE_IOER
7780: 52 5f 46 53 54 41 54 3b 0a 20 20 20 20 7d 65 6c  R_FSTAT;.    }el
7790: 73 65 7b 0a 20 20 20 20 20 20 72 63 20 3d 20 70  se{.      rc = p
77a0: 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64  SubOpen->pMethod
77b0: 73 2d 3e 78 46 69 6c 65 53 69 7a 65 28 70 53 75  s->xFileSize(pSu
77c0: 62 4f 70 65 6e 2c 20 70 53 69 7a 65 29 3b 0a 20  bOpen, pSize);. 
77d0: 20 20 20 7d 0a 20 20 7d 65 6c 73 65 7b 0a 20 20     }.  }else{.  
77e0: 20 20 2a 70 53 69 7a 65 20 3d 20 30 3b 0a 20 20    *pSize = 0;.  
77f0: 20 20 66 6f 72 28 69 3d 30 3b 20 72 63 3d 3d 53    for(i=0; rc==S
7800: 51 4c 49 54 45 5f 4f 4b 3b 20 69 2b 2b 29 7b 0a  QLITE_OK; i++){.
7810: 20 20 20 20 20 20 73 71 6c 69 74 65 33 5f 69 6e        sqlite3_in
7820: 74 36 34 20 73 7a 20 3d 20 6d 75 6c 74 69 70 6c  t64 sz = multipl
7830: 65 78 53 75 62 53 69 7a 65 28 70 47 72 6f 75 70  exSubSize(pGroup
7840: 2c 20 69 2c 20 26 72 63 29 3b 0a 20 20 20 20 20  , i, &rc);.     
7850: 20 69 66 28 20 73 7a 3d 3d 30 20 29 20 62 72 65   if( sz==0 ) bre
7860: 61 6b 3b 0a 20 20 20 20 20 20 2a 70 53 69 7a 65  ak;.      *pSize
7870: 20 3d 20 69 2a 28 73 71 6c 69 74 65 33 5f 69 6e   = i*(sqlite3_in
7880: 74 36 34 29 70 47 72 6f 75 70 2d 3e 73 7a 43 68  t64)pGroup->szCh
7890: 75 6e 6b 20 2b 20 73 7a 3b 0a 20 20 20 20 7d 0a  unk + sz;.    }.
78a0: 20 20 7d 0a 20 20 6d 75 6c 74 69 70 6c 65 78 4c    }.  multiplexL
78b0: 65 61 76 65 28 29 3b 0a 20 20 72 65 74 75 72 6e  eave();.  return
78c0: 20 72 63 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20   rc;.}../* Pass 
78d0: 78 4c 6f 63 6b 20 72 65 71 75 65 73 74 73 20 74  xLock requests t
78e0: 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20 6f 72  hrough to the or
78f0: 69 67 69 6e 61 6c 20 56 46 53 20 75 6e 63 68 61  iginal VFS uncha
7900: 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63 20  nged..*/.static 
7910: 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 4c 6f 63  int multiplexLoc
7920: 6b 28 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a  k(sqlite3_file *
7930: 70 43 6f 6e 6e 2c 20 69 6e 74 20 6c 6f 63 6b 29  pConn, int lock)
7940: 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e  {.  multiplexCon
7950: 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65  n *p = (multiple
7960: 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20  xConn*)pConn;.  
7970: 69 6e 74 20 72 63 3b 0a 20 20 73 71 6c 69 74 65  int rc;.  sqlite
7980: 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e  3_file *pSubOpen
7990: 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f   = multiplexSubO
79a0: 70 65 6e 28 70 2d 3e 70 47 72 6f 75 70 2c 20 30  pen(p->pGroup, 0
79b0: 2c 20 26 72 63 2c 20 4e 55 4c 4c 2c 20 30 29 3b  , &rc, NULL, 0);
79c0: 0a 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e 20  .  if( pSubOpen 
79d0: 29 7b 0a 20 20 20 20 72 65 74 75 72 6e 20 70 53  ){.    return pS
79e0: 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73  ubOpen->pMethods
79f0: 2d 3e 78 4c 6f 63 6b 28 70 53 75 62 4f 70 65 6e  ->xLock(pSubOpen
7a00: 2c 20 6c 6f 63 6b 29 3b 0a 20 20 7d 0a 20 20 72  , lock);.  }.  r
7a10: 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 42 55 53  eturn SQLITE_BUS
7a20: 59 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 55  Y;.}../* Pass xU
7a30: 6e 6c 6f 63 6b 20 72 65 71 75 65 73 74 73 20 74  nlock requests t
7a40: 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20 6f 72  hrough to the or
7a50: 69 67 69 6e 61 6c 20 56 46 53 20 75 6e 63 68 61  iginal VFS uncha
7a60: 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63 20  nged..*/.static 
7a70: 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 55 6e 6c  int multiplexUnl
7a80: 6f 63 6b 28 73 71 6c 69 74 65 33 5f 66 69 6c 65  ock(sqlite3_file
7a90: 20 2a 70 43 6f 6e 6e 2c 20 69 6e 74 20 6c 6f 63   *pConn, int loc
7aa0: 6b 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43  k){.  multiplexC
7ab0: 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70  onn *p = (multip
7ac0: 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a  lexConn*)pConn;.
7ad0: 20 20 69 6e 74 20 72 63 3b 0a 20 20 73 71 6c 69    int rc;.  sqli
7ae0: 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70  te3_file *pSubOp
7af0: 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75  en = multiplexSu
7b00: 62 4f 70 65 6e 28 70 2d 3e 70 47 72 6f 75 70 2c  bOpen(p->pGroup,
7b10: 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 2c 20 30   0, &rc, NULL, 0
7b20: 29 3b 0a 20 20 69 66 28 20 70 53 75 62 4f 70 65  );.  if( pSubOpe
7b30: 6e 20 29 7b 0a 20 20 20 20 72 65 74 75 72 6e 20  n ){.    return 
7b40: 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f  pSubOpen->pMetho
7b50: 64 73 2d 3e 78 55 6e 6c 6f 63 6b 28 70 53 75 62  ds->xUnlock(pSub
7b60: 4f 70 65 6e 2c 20 6c 6f 63 6b 29 3b 0a 20 20 7d  Open, lock);.  }
7b70: 0a 20 20 72 65 74 75 72 6e 20 53 51 4c 49 54 45  .  return SQLITE
7b80: 5f 49 4f 45 52 52 5f 55 4e 4c 4f 43 4b 3b 0a 7d  _IOERR_UNLOCK;.}
7b90: 0a 0a 2f 2a 20 50 61 73 73 20 78 43 68 65 63 6b  ../* Pass xCheck
7ba0: 52 65 73 65 72 76 65 64 4c 6f 63 6b 20 72 65 71  ReservedLock req
7bb0: 75 65 73 74 73 20 74 68 72 6f 75 67 68 20 74 6f  uests through to
7bc0: 20 74 68 65 20 6f 72 69 67 69 6e 61 6c 20 56 46   the original VF
7bd0: 53 20 75 6e 63 68 61 6e 67 65 64 2e 0a 2a 2f 0a  S unchanged..*/.
7be0: 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69  static int multi
7bf0: 70 6c 65 78 43 68 65 63 6b 52 65 73 65 72 76 65  plexCheckReserve
7c00: 64 4c 6f 63 6b 28 73 71 6c 69 74 65 33 5f 66 69  dLock(sqlite3_fi
7c10: 6c 65 20 2a 70 43 6f 6e 6e 2c 20 69 6e 74 20 2a  le *pConn, int *
7c20: 70 52 65 73 4f 75 74 29 7b 0a 20 20 6d 75 6c 74  pResOut){.  mult
7c30: 69 70 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d 20 28  iplexConn *p = (
7c40: 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70  multiplexConn*)p
7c50: 43 6f 6e 6e 3b 0a 20 20 69 6e 74 20 72 63 3b 0a  Conn;.  int rc;.
7c60: 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a    sqlite3_file *
7c70: 70 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69  pSubOpen = multi
7c80: 70 6c 65 78 53 75 62 4f 70 65 6e 28 70 2d 3e 70  plexSubOpen(p->p
7c90: 47 72 6f 75 70 2c 20 30 2c 20 26 72 63 2c 20 4e  Group, 0, &rc, N
7ca0: 55 4c 4c 2c 20 30 29 3b 0a 20 20 69 66 28 20 70  ULL, 0);.  if( p
7cb0: 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20 72  SubOpen ){.    r
7cc0: 65 74 75 72 6e 20 70 53 75 62 4f 70 65 6e 2d 3e  eturn pSubOpen->
7cd0: 70 4d 65 74 68 6f 64 73 2d 3e 78 43 68 65 63 6b  pMethods->xCheck
7ce0: 52 65 73 65 72 76 65 64 4c 6f 63 6b 28 70 53 75  ReservedLock(pSu
7cf0: 62 4f 70 65 6e 2c 20 70 52 65 73 4f 75 74 29 3b  bOpen, pResOut);
7d00: 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20 53 51  .  }.  return SQ
7d10: 4c 49 54 45 5f 49 4f 45 52 52 5f 43 48 45 43 4b  LITE_IOERR_CHECK
7d20: 52 45 53 45 52 56 45 44 4c 4f 43 4b 3b 0a 7d 0a  RESERVEDLOCK;.}.
7d30: 0a 2f 2a 20 50 61 73 73 20 78 46 69 6c 65 43 6f  ./* Pass xFileCo
7d40: 6e 74 72 6f 6c 20 72 65 71 75 65 73 74 73 20 74  ntrol requests t
7d50: 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20 6f 72  hrough to the or
7d60: 69 67 69 6e 61 6c 20 56 46 53 20 75 6e 63 68 61  iginal VFS uncha
7d70: 6e 67 65 64 2c 0a 2a 2a 20 65 78 63 65 70 74 20  nged,.** except 
7d80: 66 6f 72 20 61 6e 79 20 4d 55 4c 54 49 50 4c 45  for any MULTIPLE
7d90: 58 5f 43 54 52 4c 5f 2a 20 72 65 71 75 65 73 74  X_CTRL_* request
7da0: 73 20 68 65 72 65 2e 0a 2a 2f 0a 73 74 61 74 69  s here..*/.stati
7db0: 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 46  c int multiplexF
7dc0: 69 6c 65 43 6f 6e 74 72 6f 6c 28 73 71 6c 69 74  ileControl(sqlit
7dd0: 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c 20  e3_file *pConn, 
7de0: 69 6e 74 20 6f 70 2c 20 76 6f 69 64 20 2a 70 41  int op, void *pA
7df0: 72 67 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78  rg){.  multiplex
7e00: 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69  Conn *p = (multi
7e10: 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b  plexConn*)pConn;
7e20: 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75  .  multiplexGrou
7e30: 70 20 2a 70 47 72 6f 75 70 20 3d 20 70 2d 3e 70  p *pGroup = p->p
7e40: 47 72 6f 75 70 3b 0a 20 20 69 6e 74 20 72 63 20  Group;.  int rc 
7e50: 3d 20 53 51 4c 49 54 45 5f 45 52 52 4f 52 3b 0a  = SQLITE_ERROR;.
7e60: 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a    sqlite3_file *
7e70: 70 53 75 62 4f 70 65 6e 3b 0a 0a 20 20 69 66 28  pSubOpen;..  if(
7e80: 20 21 67 4d 75 6c 74 69 70 6c 65 78 2e 69 73 49   !gMultiplex.isI
7e90: 6e 69 74 69 61 6c 69 7a 65 64 20 29 20 72 65 74  nitialized ) ret
7ea0: 75 72 6e 20 53 51 4c 49 54 45 5f 4d 49 53 55 53  urn SQLITE_MISUS
7eb0: 45 3b 0a 20 20 73 77 69 74 63 68 28 20 6f 70 20  E;.  switch( op 
7ec0: 29 7b 0a 20 20 20 20 63 61 73 65 20 4d 55 4c 54  ){.    case MULT
7ed0: 49 50 4c 45 58 5f 43 54 52 4c 5f 45 4e 41 42 4c  IPLEX_CTRL_ENABL
7ee0: 45 3a 0a 20 20 20 20 20 20 69 66 28 20 70 41 72  E:.      if( pAr
7ef0: 67 20 29 20 7b 0a 20 20 20 20 20 20 20 20 69 6e  g ) {.        in
7f00: 74 20 62 45 6e 61 62 6c 65 64 20 3d 20 2a 28 69  t bEnabled = *(i
7f10: 6e 74 20 2a 29 70 41 72 67 3b 0a 20 20 20 20 20  nt *)pArg;.     
7f20: 20 20 20 70 47 72 6f 75 70 2d 3e 62 45 6e 61 62     pGroup->bEnab
7f30: 6c 65 64 20 3d 20 62 45 6e 61 62 6c 65 64 3b 0a  led = bEnabled;.
7f40: 20 20 20 20 20 20 20 20 72 63 20 3d 20 53 51 4c          rc = SQL
7f50: 49 54 45 5f 4f 4b 3b 0a 20 20 20 20 20 20 7d 0a  ITE_OK;.      }.
7f60: 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20        break;.   
7f70: 20 63 61 73 65 20 4d 55 4c 54 49 50 4c 45 58 5f   case MULTIPLEX_
7f80: 43 54 52 4c 5f 53 45 54 5f 43 48 55 4e 4b 5f 53  CTRL_SET_CHUNK_S
7f90: 49 5a 45 3a 0a 20 20 20 20 20 20 69 66 28 20 70  IZE:.      if( p
7fa0: 41 72 67 20 29 20 7b 0a 20 20 20 20 20 20 20 20  Arg ) {.        
7fb0: 75 6e 73 69 67 6e 65 64 20 69 6e 74 20 73 7a 43  unsigned int szC
7fc0: 68 75 6e 6b 20 3d 20 2a 28 75 6e 73 69 67 6e 65  hunk = *(unsigne
7fd0: 64 2a 29 70 41 72 67 3b 0a 20 20 20 20 20 20 20  d*)pArg;.       
7fe0: 20 69 66 28 20 73 7a 43 68 75 6e 6b 3c 31 20 29   if( szChunk<1 )
7ff0: 7b 0a 20 20 20 20 20 20 20 20 20 20 72 63 20 3d  {.          rc =
8000: 20 53 51 4c 49 54 45 5f 4d 49 53 55 53 45 3b 0a   SQLITE_MISUSE;.
8010: 20 20 20 20 20 20 20 20 7d 65 6c 73 65 7b 0a 20          }else{. 
8020: 20 20 20 20 20 20 20 20 20 2f 2a 20 52 6f 75 6e           /* Roun
8030: 64 20 75 70 20 74 6f 20 6e 65 61 72 65 73 74 20  d up to nearest 
8040: 6d 75 6c 74 69 70 6c 65 20 6f 66 20 4d 41 58 5f  multiple of MAX_
8050: 50 41 47 45 5f 53 49 5a 45 2e 20 2a 2f 0a 20 20  PAGE_SIZE. */.  
8060: 20 20 20 20 20 20 20 20 73 7a 43 68 75 6e 6b 20          szChunk 
8070: 3d 20 28 73 7a 43 68 75 6e 6b 20 2b 20 28 4d 41  = (szChunk + (MA
8080: 58 5f 50 41 47 45 5f 53 49 5a 45 2d 31 29 29 3b  X_PAGE_SIZE-1));
8090: 0a 20 20 20 20 20 20 20 20 20 20 73 7a 43 68 75  .          szChu
80a0: 6e 6b 20 26 3d 20 7e 28 4d 41 58 5f 50 41 47 45  nk &= ~(MAX_PAGE
80b0: 5f 53 49 5a 45 2d 31 29 3b 0a 20 20 20 20 20 20  _SIZE-1);.      
80c0: 20 20 20 20 70 47 72 6f 75 70 2d 3e 73 7a 43 68      pGroup->szCh
80d0: 75 6e 6b 20 3d 20 73 7a 43 68 75 6e 6b 3b 0a 20  unk = szChunk;. 
80e0: 20 20 20 20 20 20 20 20 20 72 63 20 3d 20 53 51           rc = SQ
80f0: 4c 49 54 45 5f 4f 4b 3b 0a 20 20 20 20 20 20 20  LITE_OK;.       
8100: 20 7d 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 20   }.      }.     
8110: 20 62 72 65 61 6b 3b 0a 20 20 20 20 63 61 73 65   break;.    case
8120: 20 4d 55 4c 54 49 50 4c 45 58 5f 43 54 52 4c 5f   MULTIPLEX_CTRL_
8130: 53 45 54 5f 4d 41 58 5f 43 48 55 4e 4b 53 3a 0a  SET_MAX_CHUNKS:.
8140: 20 20 20 20 20 20 72 63 20 3d 20 53 51 4c 49 54        rc = SQLIT
8150: 45 5f 4f 4b 3b 0a 20 20 20 20 20 20 62 72 65 61  E_OK;.      brea
8160: 6b 3b 0a 20 20 20 20 63 61 73 65 20 53 51 4c 49  k;.    case SQLI
8170: 54 45 5f 46 43 4e 54 4c 5f 53 49 5a 45 5f 48 49  TE_FCNTL_SIZE_HI
8180: 4e 54 3a 0a 20 20 20 20 63 61 73 65 20 53 51 4c  NT:.    case SQL
8190: 49 54 45 5f 46 43 4e 54 4c 5f 43 48 55 4e 4b 5f  ITE_FCNTL_CHUNK_
81a0: 53 49 5a 45 3a 0a 20 20 20 20 20 20 2f 2a 20 6e  SIZE:.      /* n
81b0: 6f 2d 6f 70 20 74 68 65 73 65 20 2a 2f 0a 20 20  o-op these */.  
81c0: 20 20 20 20 72 63 20 3d 20 53 51 4c 49 54 45 5f      rc = SQLITE_
81d0: 4f 4b 3b 0a 20 20 20 20 20 20 62 72 65 61 6b 3b  OK;.      break;
81e0: 0a 20 20 20 20 64 65 66 61 75 6c 74 3a 0a 20 20  .    default:.  
81f0: 20 20 20 20 70 53 75 62 4f 70 65 6e 20 3d 20 6d      pSubOpen = m
8200: 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28  ultiplexSubOpen(
8210: 70 47 72 6f 75 70 2c 20 30 2c 20 26 72 63 2c 20  pGroup, 0, &rc, 
8220: 4e 55 4c 4c 2c 20 30 29 3b 0a 20 20 20 20 20 20  NULL, 0);.      
8230: 69 66 28 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a  if( pSubOpen ){.
8240: 20 20 20 20 20 20 20 20 72 63 20 3d 20 70 53 75          rc = pSu
8250: 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d  bOpen->pMethods-
8260: 3e 78 46 69 6c 65 43 6f 6e 74 72 6f 6c 28 70 53  >xFileControl(pS
8270: 75 62 4f 70 65 6e 2c 20 6f 70 2c 20 70 41 72 67  ubOpen, op, pArg
8280: 29 3b 0a 20 20 20 20 20 20 20 20 69 66 28 20 6f  );.        if( o
8290: 70 3d 3d 53 51 4c 49 54 45 5f 46 43 4e 54 4c 5f  p==SQLITE_FCNTL_
82a0: 56 46 53 4e 41 4d 45 20 26 26 20 72 63 3d 3d 53  VFSNAME && rc==S
82b0: 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20  QLITE_OK ){.    
82c0: 20 20 20 20 20 2a 28 63 68 61 72 2a 2a 29 70 41       *(char**)pA
82d0: 72 67 20 3d 20 73 71 6c 69 74 65 33 5f 6d 70 72  rg = sqlite3_mpr
82e0: 69 6e 74 66 28 22 6d 75 6c 74 69 70 6c 65 78 2f  intf("multiplex/
82f0: 25 7a 22 2c 20 2a 28 63 68 61 72 2a 2a 29 70 41  %z", *(char**)pA
8300: 72 67 29 3b 0a 20 20 20 20 20 20 20 20 7d 0a 20  rg);.        }. 
8310: 20 20 20 20 20 7d 0a 20 20 20 20 20 20 62 72 65       }.      bre
8320: 61 6b 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e  ak;.  }.  return
8330: 20 72 63 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20   rc;.}../* Pass 
8340: 78 53 65 63 74 6f 72 53 69 7a 65 20 72 65 71 75  xSectorSize requ
8350: 65 73 74 73 20 74 68 72 6f 75 67 68 20 74 6f 20  ests through to 
8360: 74 68 65 20 6f 72 69 67 69 6e 61 6c 20 56 46 53  the original VFS
8370: 20 75 6e 63 68 61 6e 67 65 64 2e 0a 2a 2f 0a 73   unchanged..*/.s
8380: 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70  tatic int multip
8390: 6c 65 78 53 65 63 74 6f 72 53 69 7a 65 28 73 71  lexSectorSize(sq
83a0: 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e  lite3_file *pCon
83b0: 6e 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43  n){.  multiplexC
83c0: 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70  onn *p = (multip
83d0: 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a  lexConn*)pConn;.
83e0: 20 20 69 6e 74 20 72 63 3b 0a 20 20 73 71 6c 69    int rc;.  sqli
83f0: 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70  te3_file *pSubOp
8400: 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75  en = multiplexSu
8410: 62 4f 70 65 6e 28 70 2d 3e 70 47 72 6f 75 70 2c  bOpen(p->pGroup,
8420: 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 2c 20 30   0, &rc, NULL, 0
8430: 29 3b 0a 20 20 69 66 28 20 70 53 75 62 4f 70 65  );.  if( pSubOpe
8440: 6e 20 26 26 20 70 53 75 62 4f 70 65 6e 2d 3e 70  n && pSubOpen->p
8450: 4d 65 74 68 6f 64 73 2d 3e 78 53 65 63 74 6f 72  Methods->xSector
8460: 53 69 7a 65 20 29 7b 0a 20 20 20 20 72 65 74 75  Size ){.    retu
8470: 72 6e 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65  rn pSubOpen->pMe
8480: 74 68 6f 64 73 2d 3e 78 53 65 63 74 6f 72 53 69  thods->xSectorSi
8490: 7a 65 28 70 53 75 62 4f 70 65 6e 29 3b 0a 20 20  ze(pSubOpen);.  
84a0: 7d 0a 20 20 72 65 74 75 72 6e 20 44 45 46 41 55  }.  return DEFAU
84b0: 4c 54 5f 53 45 43 54 4f 52 5f 53 49 5a 45 3b 0a  LT_SECTOR_SIZE;.
84c0: 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 44 65 76 69  }../* Pass xDevi
84d0: 63 65 43 68 61 72 61 63 74 65 72 69 73 74 69 63  ceCharacteristic
84e0: 73 20 72 65 71 75 65 73 74 73 20 74 68 72 6f 75  s requests throu
84f0: 67 68 20 74 6f 20 74 68 65 20 6f 72 69 67 69 6e  gh to the origin
8500: 61 6c 20 56 46 53 20 75 6e 63 68 61 6e 67 65 64  al VFS unchanged
8510: 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20  ..*/.static int 
8520: 6d 75 6c 74 69 70 6c 65 78 44 65 76 69 63 65 43  multiplexDeviceC
8530: 68 61 72 61 63 74 65 72 69 73 74 69 63 73 28 73  haracteristics(s
8540: 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f  qlite3_file *pCo
8550: 6e 6e 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78  nn){.  multiplex
8560: 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69  Conn *p = (multi
8570: 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b  plexConn*)pConn;
8580: 0a 20 20 69 6e 74 20 72 63 3b 0a 20 20 73 71 6c  .  int rc;.  sql
8590: 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f  ite3_file *pSubO
85a0: 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53  pen = multiplexS
85b0: 75 62 4f 70 65 6e 28 70 2d 3e 70 47 72 6f 75 70  ubOpen(p->pGroup
85c0: 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 2c 20  , 0, &rc, NULL, 
85d0: 30 29 3b 0a 20 20 69 66 28 20 70 53 75 62 4f 70  0);.  if( pSubOp
85e0: 65 6e 20 29 7b 0a 20 20 20 20 72 65 74 75 72 6e  en ){.    return
85f0: 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68   pSubOpen->pMeth
8600: 6f 64 73 2d 3e 78 44 65 76 69 63 65 43 68 61 72  ods->xDeviceChar
8610: 61 63 74 65 72 69 73 74 69 63 73 28 70 53 75 62  acteristics(pSub
8620: 4f 70 65 6e 29 3b 0a 20 20 7d 0a 20 20 72 65 74  Open);.  }.  ret
8630: 75 72 6e 20 30 3b 0a 7d 0a 0a 2f 2a 20 50 61 73  urn 0;.}../* Pas
8640: 73 20 78 53 68 6d 4d 61 70 20 72 65 71 75 65 73  s xShmMap reques
8650: 74 73 20 74 68 72 6f 75 67 68 20 74 6f 20 74 68  ts through to th
8660: 65 20 6f 72 69 67 69 6e 61 6c 20 56 46 53 20 75  e original VFS u
8670: 6e 63 68 61 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61  nchanged..*/.sta
8680: 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65  tic int multiple
8690: 78 53 68 6d 4d 61 70 28 0a 20 20 73 71 6c 69 74  xShmMap(.  sqlit
86a0: 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c 20  e3_file *pConn, 
86b0: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 48 61             /* Ha
86c0: 6e 64 6c 65 20 6f 70 65 6e 20 6f 6e 20 64 61 74  ndle open on dat
86d0: 61 62 61 73 65 20 66 69 6c 65 20 2a 2f 0a 20 20  abase file */.  
86e0: 69 6e 74 20 69 52 65 67 69 6f 6e 2c 20 20 20 20  int iRegion,    
86f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8700: 2f 2a 20 52 65 67 69 6f 6e 20 74 6f 20 72 65 74  /* Region to ret
8710: 72 69 65 76 65 20 2a 2f 0a 20 20 69 6e 74 20 73  rieve */.  int s
8720: 7a 52 65 67 69 6f 6e 2c 20 20 20 20 20 20 20 20  zRegion,        
8730: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 53 69             /* Si
8740: 7a 65 20 6f 66 20 72 65 67 69 6f 6e 73 20 2a 2f  ze of regions */
8750: 0a 20 20 69 6e 74 20 62 45 78 74 65 6e 64 2c 20  .  int bExtend, 
8760: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8770: 20 20 20 2f 2a 20 54 72 75 65 20 74 6f 20 65 78     /* True to ex
8780: 74 65 6e 64 20 66 69 6c 65 20 69 66 20 6e 65 63  tend file if nec
8790: 65 73 73 61 72 79 20 2a 2f 0a 20 20 76 6f 69 64  essary */.  void
87a0: 20 76 6f 6c 61 74 69 6c 65 20 2a 2a 70 70 20 20   volatile **pp  
87b0: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4f              /* O
87c0: 55 54 3a 20 4d 61 70 70 65 64 20 6d 65 6d 6f 72  UT: Mapped memor
87d0: 79 20 2a 2f 0a 29 7b 0a 20 20 6d 75 6c 74 69 70  y */.){.  multip
87e0: 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75  lexConn *p = (mu
87f0: 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f  ltiplexConn*)pCo
8800: 6e 6e 3b 0a 20 20 69 6e 74 20 72 63 3b 0a 20 20  nn;.  int rc;.  
8810: 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53  sqlite3_file *pS
8820: 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c  ubOpen = multipl
8830: 65 78 53 75 62 4f 70 65 6e 28 70 2d 3e 70 47 72  exSubOpen(p->pGr
8840: 6f 75 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c  oup, 0, &rc, NUL
8850: 4c 2c 20 30 29 3b 0a 20 20 69 66 28 20 70 53 75  L, 0);.  if( pSu
8860: 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20 72 65 74  bOpen ){.    ret
8870: 75 72 6e 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d  urn pSubOpen->pM
8880: 65 74 68 6f 64 73 2d 3e 78 53 68 6d 4d 61 70 28  ethods->xShmMap(
8890: 70 53 75 62 4f 70 65 6e 2c 20 69 52 65 67 69 6f  pSubOpen, iRegio
88a0: 6e 2c 20 73 7a 52 65 67 69 6f 6e 2c 20 62 45 78  n, szRegion, bEx
88b0: 74 65 6e 64 2c 70 70 29 3b 0a 20 20 7d 0a 20 20  tend,pp);.  }.  
88c0: 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 49 4f  return SQLITE_IO
88d0: 45 52 52 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20  ERR;.}../* Pass 
88e0: 78 53 68 6d 4c 6f 63 6b 20 72 65 71 75 65 73 74  xShmLock request
88f0: 73 20 74 68 72 6f 75 67 68 20 74 6f 20 74 68 65  s through to the
8900: 20 6f 72 69 67 69 6e 61 6c 20 56 46 53 20 75 6e   original VFS un
8910: 63 68 61 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61 74  changed..*/.stat
8920: 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78  ic int multiplex
8930: 53 68 6d 4c 6f 63 6b 28 0a 20 20 73 71 6c 69 74  ShmLock(.  sqlit
8940: 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c 20  e3_file *pConn, 
8950: 20 20 20 20 20 20 2f 2a 20 44 61 74 61 62 61 73        /* Databas
8960: 65 20 66 69 6c 65 20 68 6f 6c 64 69 6e 67 20 74  e file holding t
8970: 68 65 20 73 68 61 72 65 64 20 6d 65 6d 6f 72 79  he shared memory
8980: 20 2a 2f 0a 20 20 69 6e 74 20 6f 66 73 74 2c 20   */.  int ofst, 
8990: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
89a0: 20 2f 2a 20 46 69 72 73 74 20 6c 6f 63 6b 20 74   /* First lock t
89b0: 6f 20 61 63 71 75 69 72 65 20 6f 72 20 72 65 6c  o acquire or rel
89c0: 65 61 73 65 20 2a 2f 0a 20 20 69 6e 74 20 6e 2c  ease */.  int n,
89d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
89e0: 20 20 20 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f       /* Number o
89f0: 66 20 6c 6f 63 6b 73 20 74 6f 20 61 63 71 75 69  f locks to acqui
8a00: 72 65 20 6f 72 20 72 65 6c 65 61 73 65 20 2a 2f  re or release */
8a10: 0a 20 20 69 6e 74 20 66 6c 61 67 73 20 20 20 20  .  int flags    
8a20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
8a30: 20 57 68 61 74 20 74 6f 20 64 6f 20 77 69 74 68   What to do with
8a40: 20 74 68 65 20 6c 6f 63 6b 20 2a 2f 0a 29 7b 0a   the lock */.){.
8a50: 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20    multiplexConn 
8a60: 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43  *p = (multiplexC
8a70: 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 69 6e  onn*)pConn;.  in
8a80: 74 20 72 63 3b 0a 20 20 73 71 6c 69 74 65 33 5f  t rc;.  sqlite3_
8a90: 66 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d  file *pSubOpen =
8aa0: 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65   multiplexSubOpe
8ab0: 6e 28 70 2d 3e 70 47 72 6f 75 70 2c 20 30 2c 20  n(p->pGroup, 0, 
8ac0: 26 72 63 2c 20 4e 55 4c 4c 2c 20 30 29 3b 0a 20  &rc, NULL, 0);. 
8ad0: 20 69 66 28 20 70 53 75 62 4f 70 65 6e 20 29 7b   if( pSubOpen ){
8ae0: 0a 20 20 20 20 72 65 74 75 72 6e 20 70 53 75 62  .    return pSub
8af0: 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e  Open->pMethods->
8b00: 78 53 68 6d 4c 6f 63 6b 28 70 53 75 62 4f 70 65  xShmLock(pSubOpe
8b10: 6e 2c 20 6f 66 73 74 2c 20 6e 2c 20 66 6c 61 67  n, ofst, n, flag
8b20: 73 29 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e  s);.  }.  return
8b30: 20 53 51 4c 49 54 45 5f 42 55 53 59 3b 0a 7d 0a   SQLITE_BUSY;.}.
8b40: 0a 2f 2a 20 50 61 73 73 20 78 53 68 6d 42 61 72  ./* Pass xShmBar
8b50: 72 69 65 72 20 72 65 71 75 65 73 74 73 20 74 68  rier requests th
8b60: 72 6f 75 67 68 20 74 6f 20 74 68 65 20 6f 72 69  rough to the ori
8b70: 67 69 6e 61 6c 20 56 46 53 20 75 6e 63 68 61 6e  ginal VFS unchan
8b80: 67 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 76  ged..*/.static v
8b90: 6f 69 64 20 6d 75 6c 74 69 70 6c 65 78 53 68 6d  oid multiplexShm
8ba0: 42 61 72 72 69 65 72 28 73 71 6c 69 74 65 33 5f  Barrier(sqlite3_
8bb0: 66 69 6c 65 20 2a 70 43 6f 6e 6e 29 7b 0a 20 20  file *pConn){.  
8bc0: 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70  multiplexConn *p
8bd0: 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e   = (multiplexCon
8be0: 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 69 6e 74 20  n*)pConn;.  int 
8bf0: 72 63 3b 0a 20 20 73 71 6c 69 74 65 33 5f 66 69  rc;.  sqlite3_fi
8c00: 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20 6d  le *pSubOpen = m
8c10: 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28  ultiplexSubOpen(
8c20: 70 2d 3e 70 47 72 6f 75 70 2c 20 30 2c 20 26 72  p->pGroup, 0, &r
8c30: 63 2c 20 4e 55 4c 4c 2c 20 30 29 3b 0a 20 20 69  c, NULL, 0);.  i
8c40: 66 28 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20  f( pSubOpen ){. 
8c50: 20 20 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65     pSubOpen->pMe
8c60: 74 68 6f 64 73 2d 3e 78 53 68 6d 42 61 72 72 69  thods->xShmBarri
8c70: 65 72 28 70 53 75 62 4f 70 65 6e 29 3b 0a 20 20  er(pSubOpen);.  
8c80: 7d 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 53 68  }.}../* Pass xSh
8c90: 6d 55 6e 6d 61 70 20 72 65 71 75 65 73 74 73 20  mUnmap requests 
8ca0: 74 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20 6f  through to the o
8cb0: 72 69 67 69 6e 61 6c 20 56 46 53 20 75 6e 63 68  riginal VFS unch
8cc0: 61 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63  anged..*/.static
8cd0: 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 53 68   int multiplexSh
8ce0: 6d 55 6e 6d 61 70 28 73 71 6c 69 74 65 33 5f 66  mUnmap(sqlite3_f
8cf0: 69 6c 65 20 2a 70 43 6f 6e 6e 2c 20 69 6e 74 20  ile *pConn, int 
8d00: 64 65 6c 65 74 65 46 6c 61 67 29 7b 0a 20 20 6d  deleteFlag){.  m
8d10: 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70 20  ultiplexConn *p 
8d20: 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e  = (multiplexConn
8d30: 2a 29 70 43 6f 6e 6e 3b 0a 20 20 69 6e 74 20 72  *)pConn;.  int r
8d40: 63 3b 0a 20 20 73 71 6c 69 74 65 33 5f 66 69 6c  c;.  sqlite3_fil
8d50: 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20 6d 75  e *pSubOpen = mu
8d60: 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28 70  ltiplexSubOpen(p
8d70: 2d 3e 70 47 72 6f 75 70 2c 20 30 2c 20 26 72 63  ->pGroup, 0, &rc
8d80: 2c 20 4e 55 4c 4c 2c 20 30 29 3b 0a 20 20 69 66  , NULL, 0);.  if
8d90: 28 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20  ( pSubOpen ){.  
8da0: 20 20 72 65 74 75 72 6e 20 70 53 75 62 4f 70 65    return pSubOpe
8db0: 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e 78 53 68  n->pMethods->xSh
8dc0: 6d 55 6e 6d 61 70 28 70 53 75 62 4f 70 65 6e 2c  mUnmap(pSubOpen,
8dd0: 20 64 65 6c 65 74 65 46 6c 61 67 29 3b 0a 20 20   deleteFlag);.  
8de0: 7d 0a 20 20 72 65 74 75 72 6e 20 53 51 4c 49 54  }.  return SQLIT
8df0: 45 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a 2a 2a 2a 2a 2a  E_OK;.}../******
8e00: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
8e10: 2a 2a 2a 2a 20 50 75 62 6c 69 63 20 49 6e 74 65  **** Public Inte
8e20: 72 66 61 63 65 73 20 2a 2a 2a 2a 2a 2a 2a 2a 2a  rfaces *********
8e30: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
8e40: 2a 2a 2a 2a 2f 0a 2f 2a 0a 2a 2a 20 43 41 50 49  ****/./*.** CAPI
8e50: 3a 20 49 6e 69 74 69 61 6c 69 7a 65 20 74 68 65  : Initialize the
8e60: 20 6d 75 6c 74 69 70 6c 65 78 20 56 46 53 20 73   multiplex VFS s
8e70: 68 69 6d 20 2d 20 73 71 6c 69 74 65 33 5f 6d 75  him - sqlite3_mu
8e80: 6c 74 69 70 6c 65 78 5f 69 6e 69 74 69 61 6c 69  ltiplex_initiali
8e90: 7a 65 28 29 0a 2a 2a 0a 2a 2a 20 55 73 65 20 74  ze().**.** Use t
8ea0: 68 65 20 56 46 53 20 6e 61 6d 65 64 20 7a 4f 72  he VFS named zOr
8eb0: 69 67 56 66 73 4e 61 6d 65 20 61 73 20 74 68 65  igVfsName as the
8ec0: 20 56 46 53 20 74 68 61 74 20 64 6f 65 73 20 74   VFS that does t
8ed0: 68 65 20 61 63 74 75 61 6c 20 77 6f 72 6b 2e 20  he actual work. 
8ee0: 20 0a 2a 2a 20 55 73 65 20 74 68 65 20 64 65 66   .** Use the def
8ef0: 61 75 6c 74 20 69 66 20 7a 4f 72 69 67 56 66 73  ault if zOrigVfs
8f00: 4e 61 6d 65 3d 3d 4e 55 4c 4c 2e 20 20 0a 2a 2a  Name==NULL.  .**
8f10: 0a 2a 2a 20 54 68 65 20 6d 75 6c 74 69 70 6c 65  .** The multiple
8f20: 78 20 56 46 53 20 73 68 69 6d 20 69 73 20 6e 61  x VFS shim is na
8f30: 6d 65 64 20 22 6d 75 6c 74 69 70 6c 65 78 22 2e  med "multiplex".
8f40: 20 20 49 74 20 77 69 6c 6c 20 62 65 63 6f 6d 65    It will become
8f50: 20 74 68 65 20 64 65 66 61 75 6c 74 0a 2a 2a 20   the default.** 
8f60: 56 46 53 20 69 66 20 6d 61 6b 65 44 65 66 61 75  VFS if makeDefau
8f70: 6c 74 20 69 73 20 6e 6f 6e 2d 7a 65 72 6f 2e 0a  lt is non-zero..
8f80: 2a 2a 0a 2a 2a 20 54 48 49 53 20 52 4f 55 54 49  **.** THIS ROUTI
8f90: 4e 45 20 49 53 20 4e 4f 54 20 54 48 52 45 41 44  NE IS NOT THREAD
8fa0: 53 41 46 45 2e 20 20 43 61 6c 6c 20 74 68 69 73  SAFE.  Call this
8fb0: 20 72 6f 75 74 69 6e 65 20 65 78 61 63 74 6c 79   routine exactly
8fc0: 20 6f 6e 63 65 0a 2a 2a 20 64 75 72 69 6e 67 20   once.** during 
8fd0: 73 74 61 72 74 2d 75 70 2e 0a 2a 2f 0a 69 6e 74  start-up..*/.int
8fe0: 20 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c   sqlite3_multipl
8ff0: 65 78 5f 69 6e 69 74 69 61 6c 69 7a 65 28 63 6f  ex_initialize(co
9000: 6e 73 74 20 63 68 61 72 20 2a 7a 4f 72 69 67 56  nst char *zOrigV
9010: 66 73 4e 61 6d 65 2c 20 69 6e 74 20 6d 61 6b 65  fsName, int make
9020: 44 65 66 61 75 6c 74 29 7b 0a 20 20 73 71 6c 69  Default){.  sqli
9030: 74 65 33 5f 76 66 73 20 2a 70 4f 72 69 67 56 66  te3_vfs *pOrigVf
9040: 73 3b 0a 20 20 69 66 28 20 67 4d 75 6c 74 69 70  s;.  if( gMultip
9050: 6c 65 78 2e 69 73 49 6e 69 74 69 61 6c 69 7a 65  lex.isInitialize
9060: 64 20 29 20 72 65 74 75 72 6e 20 53 51 4c 49 54  d ) return SQLIT
9070: 45 5f 4d 49 53 55 53 45 3b 0a 20 20 70 4f 72 69  E_MISUSE;.  pOri
9080: 67 56 66 73 20 3d 20 73 71 6c 69 74 65 33 5f 76  gVfs = sqlite3_v
9090: 66 73 5f 66 69 6e 64 28 7a 4f 72 69 67 56 66 73  fs_find(zOrigVfs
90a0: 4e 61 6d 65 29 3b 0a 20 20 69 66 28 20 70 4f 72  Name);.  if( pOr
90b0: 69 67 56 66 73 3d 3d 30 20 29 20 72 65 74 75 72  igVfs==0 ) retur
90c0: 6e 20 53 51 4c 49 54 45 5f 45 52 52 4f 52 3b 0a  n SQLITE_ERROR;.
90d0: 20 20 61 73 73 65 72 74 28 20 70 4f 72 69 67 56    assert( pOrigV
90e0: 66 73 21 3d 26 67 4d 75 6c 74 69 70 6c 65 78 2e  fs!=&gMultiplex.
90f0: 73 54 68 69 73 56 66 73 20 29 3b 0a 20 20 67 4d  sThisVfs );.  gM
9100: 75 6c 74 69 70 6c 65 78 2e 70 4d 75 74 65 78 20  ultiplex.pMutex 
9110: 3d 20 73 71 6c 69 74 65 33 5f 6d 75 74 65 78 5f  = sqlite3_mutex_
9120: 61 6c 6c 6f 63 28 53 51 4c 49 54 45 5f 4d 55 54  alloc(SQLITE_MUT
9130: 45 58 5f 46 41 53 54 29 3b 0a 20 20 69 66 28 20  EX_FAST);.  if( 
9140: 21 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4d 75 74  !gMultiplex.pMut
9150: 65 78 20 29 7b 0a 20 20 20 20 72 65 74 75 72 6e  ex ){.    return
9160: 20 53 51 4c 49 54 45 5f 4e 4f 4d 45 4d 3b 0a 20   SQLITE_NOMEM;. 
9170: 20 7d 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e   }.  gMultiplex.
9180: 70 47 72 6f 75 70 73 20 3d 20 4e 55 4c 4c 3b 0a  pGroups = NULL;.
9190: 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 69 73 49    gMultiplex.isI
91a0: 6e 69 74 69 61 6c 69 7a 65 64 20 3d 20 31 3b 0a  nitialized = 1;.
91b0: 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72    gMultiplex.pOr
91c0: 69 67 56 66 73 20 3d 20 70 4f 72 69 67 56 66 73  igVfs = pOrigVfs
91d0: 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73  ;.  gMultiplex.s
91e0: 54 68 69 73 56 66 73 20 3d 20 2a 70 4f 72 69 67  ThisVfs = *pOrig
91f0: 56 66 73 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65  Vfs;.  gMultiple
9200: 78 2e 73 54 68 69 73 56 66 73 2e 73 7a 4f 73 46  x.sThisVfs.szOsF
9210: 69 6c 65 20 2b 3d 20 73 69 7a 65 6f 66 28 6d 75  ile += sizeof(mu
9220: 6c 74 69 70 6c 65 78 43 6f 6e 6e 29 3b 0a 20 20  ltiplexConn);.  
9230: 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54 68 69 73  gMultiplex.sThis
9240: 56 66 73 2e 7a 4e 61 6d 65 20 3d 20 53 51 4c 49  Vfs.zName = SQLI
9250: 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 56 46 53  TE_MULTIPLEX_VFS
9260: 5f 4e 41 4d 45 3b 0a 20 20 67 4d 75 6c 74 69 70  _NAME;.  gMultip
9270: 6c 65 78 2e 73 54 68 69 73 56 66 73 2e 78 4f 70  lex.sThisVfs.xOp
9280: 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 4f 70  en = multiplexOp
9290: 65 6e 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78  en;.  gMultiplex
92a0: 2e 73 54 68 69 73 56 66 73 2e 78 44 65 6c 65 74  .sThisVfs.xDelet
92b0: 65 20 3d 20 6d 75 6c 74 69 70 6c 65 78 44 65 6c  e = multiplexDel
92c0: 65 74 65 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65  ete;.  gMultiple
92d0: 78 2e 73 54 68 69 73 56 66 73 2e 78 41 63 63 65  x.sThisVfs.xAcce
92e0: 73 73 20 3d 20 6d 75 6c 74 69 70 6c 65 78 41 63  ss = multiplexAc
92f0: 63 65 73 73 3b 0a 20 20 67 4d 75 6c 74 69 70 6c  cess;.  gMultipl
9300: 65 78 2e 73 54 68 69 73 56 66 73 2e 78 46 75 6c  ex.sThisVfs.xFul
9310: 6c 50 61 74 68 6e 61 6d 65 20 3d 20 6d 75 6c 74  lPathname = mult
9320: 69 70 6c 65 78 46 75 6c 6c 50 61 74 68 6e 61 6d  iplexFullPathnam
9330: 65 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e  e;.  gMultiplex.
9340: 73 54 68 69 73 56 66 73 2e 78 44 6c 4f 70 65 6e  sThisVfs.xDlOpen
9350: 20 3d 20 6d 75 6c 74 69 70 6c 65 78 44 6c 4f 70   = multiplexDlOp
9360: 65 6e 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78  en;.  gMultiplex
9370: 2e 73 54 68 69 73 56 66 73 2e 78 44 6c 45 72 72  .sThisVfs.xDlErr
9380: 6f 72 20 3d 20 6d 75 6c 74 69 70 6c 65 78 44 6c  or = multiplexDl
9390: 45 72 72 6f 72 3b 0a 20 20 67 4d 75 6c 74 69 70  Error;.  gMultip
93a0: 6c 65 78 2e 73 54 68 69 73 56 66 73 2e 78 44 6c  lex.sThisVfs.xDl
93b0: 53 79 6d 20 3d 20 6d 75 6c 74 69 70 6c 65 78 44  Sym = multiplexD
93c0: 6c 53 79 6d 3b 0a 20 20 67 4d 75 6c 74 69 70 6c  lSym;.  gMultipl
93d0: 65 78 2e 73 54 68 69 73 56 66 73 2e 78 44 6c 43  ex.sThisVfs.xDlC
93e0: 6c 6f 73 65 20 3d 20 6d 75 6c 74 69 70 6c 65 78  lose = multiplex
93f0: 44 6c 43 6c 6f 73 65 3b 0a 20 20 67 4d 75 6c 74  DlClose;.  gMult
9400: 69 70 6c 65 78 2e 73 54 68 69 73 56 66 73 2e 78  iplex.sThisVfs.x
9410: 52 61 6e 64 6f 6d 6e 65 73 73 20 3d 20 6d 75 6c  Randomness = mul
9420: 74 69 70 6c 65 78 52 61 6e 64 6f 6d 6e 65 73 73  tiplexRandomness
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 53 6c 65 65 70 20 3d  ThisVfs.xSleep =
9450: 20 6d 75 6c 74 69 70 6c 65 78 53 6c 65 65 70 3b   multiplexSleep;
9460: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54  .  gMultiplex.sT
9470: 68 69 73 56 66 73 2e 78 43 75 72 72 65 6e 74 54  hisVfs.xCurrentT
9480: 69 6d 65 20 3d 20 6d 75 6c 74 69 70 6c 65 78 43  ime = multiplexC
9490: 75 72 72 65 6e 74 54 69 6d 65 3b 0a 20 20 67 4d  urrentTime;.  gM
94a0: 75 6c 74 69 70 6c 65 78 2e 73 54 68 69 73 56 66  ultiplex.sThisVf
94b0: 73 2e 78 47 65 74 4c 61 73 74 45 72 72 6f 72 20  s.xGetLastError 
94c0: 3d 20 6d 75 6c 74 69 70 6c 65 78 47 65 74 4c 61  = multiplexGetLa
94d0: 73 74 45 72 72 6f 72 3b 0a 20 20 67 4d 75 6c 74  stError;.  gMult
94e0: 69 70 6c 65 78 2e 73 54 68 69 73 56 66 73 2e 78  iplex.sThisVfs.x
94f0: 43 75 72 72 65 6e 74 54 69 6d 65 49 6e 74 36 34  CurrentTimeInt64
9500: 20 3d 20 6d 75 6c 74 69 70 6c 65 78 43 75 72 72   = multiplexCurr
9510: 65 6e 74 54 69 6d 65 49 6e 74 36 34 3b 0a 0a 20  entTimeInt64;.. 
9520: 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d   gMultiplex.sIoM
9530: 65 74 68 6f 64 73 56 31 2e 69 56 65 72 73 69 6f  ethodsV1.iVersio
9540: 6e 20 3d 20 31 3b 0a 20 20 67 4d 75 6c 74 69 70  n = 1;.  gMultip
9550: 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31  lex.sIoMethodsV1
9560: 2e 78 43 6c 6f 73 65 20 3d 20 6d 75 6c 74 69 70  .xClose = multip
9570: 6c 65 78 43 6c 6f 73 65 3b 0a 20 20 67 4d 75 6c  lexClose;.  gMul
9580: 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64  tiplex.sIoMethod
9590: 73 56 31 2e 78 52 65 61 64 20 3d 20 6d 75 6c 74  sV1.xRead = mult
95a0: 69 70 6c 65 78 52 65 61 64 3b 0a 20 20 67 4d 75  iplexRead;.  gMu
95b0: 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f  ltiplex.sIoMetho
95c0: 64 73 56 31 2e 78 57 72 69 74 65 20 3d 20 6d 75  dsV1.xWrite = mu
95d0: 6c 74 69 70 6c 65 78 57 72 69 74 65 3b 0a 20 20  ltiplexWrite;.  
95e0: 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65  gMultiplex.sIoMe
95f0: 74 68 6f 64 73 56 31 2e 78 54 72 75 6e 63 61 74  thodsV1.xTruncat
9600: 65 20 3d 20 6d 75 6c 74 69 70 6c 65 78 54 72 75  e = multiplexTru
9610: 6e 63 61 74 65 3b 0a 20 20 67 4d 75 6c 74 69 70  ncate;.  gMultip
9620: 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31  lex.sIoMethodsV1
9630: 2e 78 53 79 6e 63 20 3d 20 6d 75 6c 74 69 70 6c  .xSync = multipl
9640: 65 78 53 79 6e 63 3b 0a 20 20 67 4d 75 6c 74 69  exSync;.  gMulti
9650: 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56  plex.sIoMethodsV
9660: 31 2e 78 46 69 6c 65 53 69 7a 65 20 3d 20 6d 75  1.xFileSize = mu
9670: 6c 74 69 70 6c 65 78 46 69 6c 65 53 69 7a 65 3b  ltiplexFileSize;
9680: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49  .  gMultiplex.sI
9690: 6f 4d 65 74 68 6f 64 73 56 31 2e 78 4c 6f 63 6b  oMethodsV1.xLock
96a0: 20 3d 20 6d 75 6c 74 69 70 6c 65 78 4c 6f 63 6b   = multiplexLock
96b0: 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73  ;.  gMultiplex.s
96c0: 49 6f 4d 65 74 68 6f 64 73 56 31 2e 78 55 6e 6c  IoMethodsV1.xUnl
96d0: 6f 63 6b 20 3d 20 6d 75 6c 74 69 70 6c 65 78 55  ock = multiplexU
96e0: 6e 6c 6f 63 6b 3b 0a 20 20 67 4d 75 6c 74 69 70  nlock;.  gMultip
96f0: 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31  lex.sIoMethodsV1
9700: 2e 78 43 68 65 63 6b 52 65 73 65 72 76 65 64 4c  .xCheckReservedL
9710: 6f 63 6b 20 3d 20 6d 75 6c 74 69 70 6c 65 78 43  ock = multiplexC
9720: 68 65 63 6b 52 65 73 65 72 76 65 64 4c 6f 63 6b  heckReservedLock
9730: 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73  ;.  gMultiplex.s
9740: 49 6f 4d 65 74 68 6f 64 73 56 31 2e 78 46 69 6c  IoMethodsV1.xFil
9750: 65 43 6f 6e 74 72 6f 6c 20 3d 20 6d 75 6c 74 69  eControl = multi
9760: 70 6c 65 78 46 69 6c 65 43 6f 6e 74 72 6f 6c 3b  plexFileControl;
9770: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49  .  gMultiplex.sI
9780: 6f 4d 65 74 68 6f 64 73 56 31 2e 78 53 65 63 74  oMethodsV1.xSect
9790: 6f 72 53 69 7a 65 20 3d 20 6d 75 6c 74 69 70 6c  orSize = multipl
97a0: 65 78 53 65 63 74 6f 72 53 69 7a 65 3b 0a 20 20  exSectorSize;.  
97b0: 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65  gMultiplex.sIoMe
97c0: 74 68 6f 64 73 56 31 2e 78 44 65 76 69 63 65 43  thodsV1.xDeviceC
97d0: 68 61 72 61 63 74 65 72 69 73 74 69 63 73 20 3d  haracteristics =
97e0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
97f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9800: 20 20 20 20 20 20 20 20 20 20 20 20 20 6d 75 6c               mul
9810: 74 69 70 6c 65 78 44 65 76 69 63 65 43 68 61 72  tiplexDeviceChar
9820: 61 63 74 65 72 69 73 74 69 63 73 3b 0a 20 20 67  acteristics;.  g
9830: 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74  Multiplex.sIoMet
9840: 68 6f 64 73 56 32 20 3d 20 67 4d 75 6c 74 69 70  hodsV2 = gMultip
9850: 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31  lex.sIoMethodsV1
9860: 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73  ;.  gMultiplex.s
9870: 49 6f 4d 65 74 68 6f 64 73 56 32 2e 69 56 65 72  IoMethodsV2.iVer
9880: 73 69 6f 6e 20 3d 20 32 3b 0a 20 20 67 4d 75 6c  sion = 2;.  gMul
9890: 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64  tiplex.sIoMethod
98a0: 73 56 32 2e 78 53 68 6d 4d 61 70 20 3d 20 6d 75  sV2.xShmMap = mu
98b0: 6c 74 69 70 6c 65 78 53 68 6d 4d 61 70 3b 0a 20  ltiplexShmMap;. 
98c0: 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d   gMultiplex.sIoM
98d0: 65 74 68 6f 64 73 56 32 2e 78 53 68 6d 4c 6f 63  ethodsV2.xShmLoc
98e0: 6b 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 68 6d  k = multiplexShm
98f0: 4c 6f 63 6b 3b 0a 20 20 67 4d 75 6c 74 69 70 6c  Lock;.  gMultipl
9900: 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 32 2e  ex.sIoMethodsV2.
9910: 78 53 68 6d 42 61 72 72 69 65 72 20 3d 20 6d 75  xShmBarrier = mu
9920: 6c 74 69 70 6c 65 78 53 68 6d 42 61 72 72 69 65  ltiplexShmBarrie
9930: 72 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e  r;.  gMultiplex.
9940: 73 49 6f 4d 65 74 68 6f 64 73 56 32 2e 78 53 68  sIoMethodsV2.xSh
9950: 6d 55 6e 6d 61 70 20 3d 20 6d 75 6c 74 69 70 6c  mUnmap = multipl
9960: 65 78 53 68 6d 55 6e 6d 61 70 3b 0a 20 20 73 71  exShmUnmap;.  sq
9970: 6c 69 74 65 33 5f 76 66 73 5f 72 65 67 69 73 74  lite3_vfs_regist
9980: 65 72 28 26 67 4d 75 6c 74 69 70 6c 65 78 2e 73  er(&gMultiplex.s
9990: 54 68 69 73 56 66 73 2c 20 6d 61 6b 65 44 65 66  ThisVfs, makeDef
99a0: 61 75 6c 74 29 3b 0a 0a 20 20 73 71 6c 69 74 65  ault);..  sqlite
99b0: 33 5f 61 75 74 6f 5f 65 78 74 65 6e 73 69 6f 6e  3_auto_extension
99c0: 28 28 76 6f 69 64 2a 29 6d 75 6c 74 69 70 6c 65  ((void*)multiple
99d0: 78 46 75 6e 63 49 6e 69 74 29 3b 0a 0a 20 20 72  xFuncInit);..  r
99e0: 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4f 4b 3b  eturn SQLITE_OK;
99f0: 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 43 41 50 49 3a 20  .}../*.** CAPI: 
9a00: 53 68 75 74 64 6f 77 6e 20 74 68 65 20 6d 75 6c  Shutdown the mul
9a10: 74 69 70 6c 65 78 20 73 79 73 74 65 6d 20 2d 20  tiplex system - 
9a20: 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65  sqlite3_multiple
9a30: 78 5f 73 68 75 74 64 6f 77 6e 28 29 0a 2a 2a 0a  x_shutdown().**.
9a40: 2a 2a 20 41 6c 6c 20 53 51 4c 69 74 65 20 64 61  ** All SQLite da
9a50: 74 61 62 61 73 65 20 63 6f 6e 6e 65 63 74 69 6f  tabase connectio
9a60: 6e 73 20 6d 75 73 74 20 62 65 20 63 6c 6f 73 65  ns must be close
9a70: 64 20 62 65 66 6f 72 65 20 63 61 6c 6c 69 6e 67  d before calling
9a80: 20 74 68 69 73 0a 2a 2a 20 72 6f 75 74 69 6e 65   this.** routine
9a90: 2e 0a 2a 2a 0a 2a 2a 20 54 48 49 53 20 52 4f 55  ..**.** THIS ROU
9aa0: 54 49 4e 45 20 49 53 20 4e 4f 54 20 54 48 52 45  TINE IS NOT THRE
9ab0: 41 44 53 41 46 45 2e 20 20 43 61 6c 6c 20 74 68  ADSAFE.  Call th
9ac0: 69 73 20 72 6f 75 74 69 6e 65 20 65 78 61 63 74  is routine exact
9ad0: 6c 79 20 6f 6e 63 65 20 77 68 69 6c 65 0a 2a 2a  ly once while.**
9ae0: 20 73 68 75 74 74 69 6e 67 20 64 6f 77 6e 20 69   shutting down i
9af0: 6e 20 6f 72 64 65 72 20 74 6f 20 66 72 65 65 20  n order to free 
9b00: 61 6c 6c 20 72 65 6d 61 69 6e 69 6e 67 20 6d 75  all remaining mu
9b10: 6c 74 69 70 6c 65 78 20 67 72 6f 75 70 73 2e 0a  ltiplex groups..
9b20: 2a 2f 0a 69 6e 74 20 73 71 6c 69 74 65 33 5f 6d  */.int sqlite3_m
9b30: 75 6c 74 69 70 6c 65 78 5f 73 68 75 74 64 6f 77  ultiplex_shutdow
9b40: 6e 28 76 6f 69 64 29 7b 0a 20 20 69 66 28 20 67  n(void){.  if( g
9b50: 4d 75 6c 74 69 70 6c 65 78 2e 69 73 49 6e 69 74  Multiplex.isInit
9b60: 69 61 6c 69 7a 65 64 3d 3d 30 20 29 20 72 65 74  ialized==0 ) ret
9b70: 75 72 6e 20 53 51 4c 49 54 45 5f 4d 49 53 55 53  urn SQLITE_MISUS
9b80: 45 3b 0a 20 20 69 66 28 20 67 4d 75 6c 74 69 70  E;.  if( gMultip
9b90: 6c 65 78 2e 70 47 72 6f 75 70 73 20 29 20 72 65  lex.pGroups ) re
9ba0: 74 75 72 6e 20 53 51 4c 49 54 45 5f 4d 49 53 55  turn SQLITE_MISU
9bb0: 53 45 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78  SE;.  gMultiplex
9bc0: 2e 69 73 49 6e 69 74 69 61 6c 69 7a 65 64 20 3d  .isInitialized =
9bd0: 20 30 3b 0a 20 20 73 71 6c 69 74 65 33 5f 6d 75   0;.  sqlite3_mu
9be0: 74 65 78 5f 66 72 65 65 28 67 4d 75 6c 74 69 70  tex_free(gMultip
9bf0: 6c 65 78 2e 70 4d 75 74 65 78 29 3b 0a 20 20 73  lex.pMutex);.  s
9c00: 71 6c 69 74 65 33 5f 76 66 73 5f 75 6e 72 65 67  qlite3_vfs_unreg
9c10: 69 73 74 65 72 28 26 67 4d 75 6c 74 69 70 6c 65  ister(&gMultiple
9c20: 78 2e 73 54 68 69 73 56 66 73 29 3b 0a 20 20 6d  x.sThisVfs);.  m
9c30: 65 6d 73 65 74 28 26 67 4d 75 6c 74 69 70 6c 65  emset(&gMultiple
9c40: 78 2c 20 30 2c 20 73 69 7a 65 6f 66 28 67 4d 75  x, 0, sizeof(gMu
9c50: 6c 74 69 70 6c 65 78 29 29 3b 0a 20 20 72 65 74  ltiplex));.  ret
9c60: 75 72 6e 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 7d  urn SQLITE_OK;.}
9c70: 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ../*************
9c80: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
9c90: 20 54 65 73 74 20 43 6f 64 65 20 2a 2a 2a 2a 2a   Test Code *****
9ca0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
9cb0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2f 0a  **************/.
9cc0: 23 69 66 64 65 66 20 53 51 4c 49 54 45 5f 54 45  #ifdef SQLITE_TE
9cd0: 53 54 0a 23 69 6e 63 6c 75 64 65 20 3c 74 63 6c  ST.#include <tcl
9ce0: 2e 68 3e 0a 65 78 74 65 72 6e 20 63 6f 6e 73 74  .h>.extern const
9cf0: 20 63 68 61 72 20 2a 73 71 6c 69 74 65 33 54 65   char *sqlite3Te
9d00: 73 74 45 72 72 6f 72 4e 61 6d 65 28 69 6e 74 29  stErrorName(int)
9d10: 3b 0a 0a 0a 2f 2a 0a 2a 2a 20 74 63 6c 63 6d 64  ;.../*.** tclcmd
9d20: 3a 20 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70  : sqlite3_multip
9d30: 6c 65 78 5f 69 6e 69 74 69 61 6c 69 7a 65 20 4e  lex_initialize N
9d40: 41 4d 45 20 4d 41 4b 45 44 45 46 41 55 4c 54 0a  AME MAKEDEFAULT.
9d50: 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 74 65  */.static int te
9d60: 73 74 5f 6d 75 6c 74 69 70 6c 65 78 5f 69 6e 69  st_multiplex_ini
9d70: 74 69 61 6c 69 7a 65 28 0a 20 20 76 6f 69 64 20  tialize(.  void 
9d80: 2a 20 63 6c 69 65 6e 74 44 61 74 61 2c 0a 20 20  * clientData,.  
9d90: 54 63 6c 5f 49 6e 74 65 72 70 20 2a 69 6e 74 65  Tcl_Interp *inte
9da0: 72 70 2c 0a 20 20 69 6e 74 20 6f 62 6a 63 2c 0a  rp,.  int objc,.
9db0: 20 20 54 63 6c 5f 4f 62 6a 20 2a 43 4f 4e 53 54    Tcl_Obj *CONST
9dc0: 20 6f 62 6a 76 5b 5d 0a 29 7b 0a 20 20 63 6f 6e   objv[].){.  con
9dd0: 73 74 20 63 68 61 72 20 2a 7a 4e 61 6d 65 3b 20  st char *zName; 
9de0: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
9df0: 4e 61 6d 65 20 6f 66 20 6e 65 77 20 6d 75 6c 74  Name of new mult
9e00: 69 70 6c 65 78 20 56 46 53 20 2a 2f 0a 20 20 69  iplex VFS */.  i
9e10: 6e 74 20 6d 61 6b 65 44 65 66 61 75 6c 74 3b 20  nt makeDefault; 
9e20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
9e30: 2a 20 54 72 75 65 20 74 6f 20 6d 61 6b 65 20 74  * True to make t
9e40: 68 65 20 6e 65 77 20 56 46 53 20 74 68 65 20 64  he new VFS the d
9e50: 65 66 61 75 6c 74 20 2a 2f 0a 20 20 69 6e 74 20  efault */.  int 
9e60: 72 63 3b 20 20 20 20 20 20 20 20 20 20 20 20 20  rc;             
9e70: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 56              /* V
9e80: 61 6c 75 65 20 72 65 74 75 72 6e 65 64 20 62 79  alue returned by
9e90: 20 6d 75 6c 74 69 70 6c 65 78 5f 69 6e 69 74 69   multiplex_initi
9ea0: 61 6c 69 7a 65 28 29 20 2a 2f 0a 0a 20 20 55 4e  alize() */..  UN
9eb0: 55 53 45 44 5f 50 41 52 41 4d 45 54 45 52 28 63  USED_PARAMETER(c
9ec0: 6c 69 65 6e 74 44 61 74 61 29 3b 0a 0a 20 20 2f  lientData);..  /
9ed0: 2a 20 50 72 6f 63 65 73 73 20 61 72 67 75 6d 65  * Process argume
9ee0: 6e 74 73 20 2a 2f 0a 20 20 69 66 28 20 6f 62 6a  nts */.  if( obj
9ef0: 63 21 3d 33 20 29 7b 0a 20 20 20 20 54 63 6c 5f  c!=3 ){.    Tcl_
9f00: 57 72 6f 6e 67 4e 75 6d 41 72 67 73 28 69 6e 74  WrongNumArgs(int
9f10: 65 72 70 2c 20 31 2c 20 6f 62 6a 76 2c 20 22 4e  erp, 1, objv, "N
9f20: 41 4d 45 20 4d 41 4b 45 44 45 46 41 55 4c 54 22  AME MAKEDEFAULT"
9f30: 29 3b 0a 20 20 20 20 72 65 74 75 72 6e 20 54 43  );.    return TC
9f40: 4c 5f 45 52 52 4f 52 3b 0a 20 20 7d 0a 20 20 7a  L_ERROR;.  }.  z
9f50: 4e 61 6d 65 20 3d 20 54 63 6c 5f 47 65 74 53 74  Name = Tcl_GetSt
9f60: 72 69 6e 67 28 6f 62 6a 76 5b 31 5d 29 3b 0a 20  ring(objv[1]);. 
9f70: 20 69 66 28 20 54 63 6c 5f 47 65 74 42 6f 6f 6c   if( Tcl_GetBool
9f80: 65 61 6e 46 72 6f 6d 4f 62 6a 28 69 6e 74 65 72  eanFromObj(inter
9f90: 70 2c 20 6f 62 6a 76 5b 32 5d 2c 20 26 6d 61 6b  p, objv[2], &mak
9fa0: 65 44 65 66 61 75 6c 74 29 20 29 20 72 65 74 75  eDefault) ) retu
9fb0: 72 6e 20 54 43 4c 5f 45 52 52 4f 52 3b 0a 20 20  rn TCL_ERROR;.  
9fc0: 69 66 28 20 7a 4e 61 6d 65 5b 30 5d 3d 3d 27 5c  if( zName[0]=='\
9fd0: 30 27 20 29 20 7a 4e 61 6d 65 20 3d 20 30 3b 0a  0' ) zName = 0;.
9fe0: 0a 20 20 2f 2a 20 43 61 6c 6c 20 73 71 6c 69 74  .  /* Call sqlit
9ff0: 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 69 6e 69  e3_multiplex_ini
a000: 74 69 61 6c 69 7a 65 28 29 20 2a 2f 0a 20 20 72  tialize() */.  r
a010: 63 20 3d 20 73 71 6c 69 74 65 33 5f 6d 75 6c 74  c = sqlite3_mult
a020: 69 70 6c 65 78 5f 69 6e 69 74 69 61 6c 69 7a 65  iplex_initialize
a030: 28 7a 4e 61 6d 65 2c 20 6d 61 6b 65 44 65 66 61  (zName, makeDefa
a040: 75 6c 74 29 3b 0a 20 20 54 63 6c 5f 53 65 74 52  ult);.  Tcl_SetR
a050: 65 73 75 6c 74 28 69 6e 74 65 72 70 2c 20 28 63  esult(interp, (c
a060: 68 61 72 20 2a 29 73 71 6c 69 74 65 33 54 65 73  har *)sqlite3Tes
a070: 74 45 72 72 6f 72 4e 61 6d 65 28 72 63 29 2c 20  tErrorName(rc), 
a080: 54 43 4c 5f 53 54 41 54 49 43 29 3b 0a 0a 20 20  TCL_STATIC);..  
a090: 72 65 74 75 72 6e 20 54 43 4c 5f 4f 4b 3b 0a 7d  return TCL_OK;.}
a0a0: 0a 0a 2f 2a 0a 2a 2a 20 74 63 6c 63 6d 64 3a 20  ../*.** tclcmd: 
a0b0: 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65  sqlite3_multiple
a0c0: 78 5f 73 68 75 74 64 6f 77 6e 0a 2a 2f 0a 73 74  x_shutdown.*/.st
a0d0: 61 74 69 63 20 69 6e 74 20 74 65 73 74 5f 6d 75  atic int test_mu
a0e0: 6c 74 69 70 6c 65 78 5f 73 68 75 74 64 6f 77 6e  ltiplex_shutdown
a0f0: 28 0a 20 20 76 6f 69 64 20 2a 20 63 6c 69 65 6e  (.  void * clien
a100: 74 44 61 74 61 2c 0a 20 20 54 63 6c 5f 49 6e 74  tData,.  Tcl_Int
a110: 65 72 70 20 2a 69 6e 74 65 72 70 2c 0a 20 20 69  erp *interp,.  i
a120: 6e 74 20 6f 62 6a 63 2c 0a 20 20 54 63 6c 5f 4f  nt objc,.  Tcl_O
a130: 62 6a 20 2a 43 4f 4e 53 54 20 6f 62 6a 76 5b 5d  bj *CONST objv[]
a140: 0a 29 7b 0a 20 20 69 6e 74 20 72 63 3b 20 20 20  .){.  int rc;   
a150: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a160: 20 20 20 20 20 20 2f 2a 20 56 61 6c 75 65 20 72        /* Value r
a170: 65 74 75 72 6e 65 64 20 62 79 20 6d 75 6c 74 69  eturned by multi
a180: 70 6c 65 78 5f 73 68 75 74 64 6f 77 6e 28 29 20  plex_shutdown() 
a190: 2a 2f 0a 0a 20 20 55 4e 55 53 45 44 5f 50 41 52  */..  UNUSED_PAR
a1a0: 41 4d 45 54 45 52 28 63 6c 69 65 6e 74 44 61 74  AMETER(clientDat
a1b0: 61 29 3b 0a 0a 20 20 69 66 28 20 6f 62 6a 63 21  a);..  if( objc!
a1c0: 3d 31 20 29 7b 0a 20 20 20 20 54 63 6c 5f 57 72  =1 ){.    Tcl_Wr
a1d0: 6f 6e 67 4e 75 6d 41 72 67 73 28 69 6e 74 65 72  ongNumArgs(inter
a1e0: 70 2c 20 31 2c 20 6f 62 6a 76 2c 20 22 22 29 3b  p, 1, objv, "");
a1f0: 0a 20 20 20 20 72 65 74 75 72 6e 20 54 43 4c 5f  .    return TCL_
a200: 45 52 52 4f 52 3b 0a 20 20 7d 0a 0a 20 20 2f 2a  ERROR;.  }..  /*
a210: 20 43 61 6c 6c 20 73 71 6c 69 74 65 33 5f 6d 75   Call sqlite3_mu
a220: 6c 74 69 70 6c 65 78 5f 73 68 75 74 64 6f 77 6e  ltiplex_shutdown
a230: 28 29 20 2a 2f 0a 20 20 72 63 20 3d 20 73 71 6c  () */.  rc = sql
a240: 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 73  ite3_multiplex_s
a250: 68 75 74 64 6f 77 6e 28 29 3b 0a 20 20 54 63 6c  hutdown();.  Tcl
a260: 5f 53 65 74 52 65 73 75 6c 74 28 69 6e 74 65 72  _SetResult(inter
a270: 70 2c 20 28 63 68 61 72 20 2a 29 73 71 6c 69 74  p, (char *)sqlit
a280: 65 33 54 65 73 74 45 72 72 6f 72 4e 61 6d 65 28  e3TestErrorName(
a290: 72 63 29 2c 20 54 43 4c 5f 53 54 41 54 49 43 29  rc), TCL_STATIC)
a2a0: 3b 0a 0a 20 20 72 65 74 75 72 6e 20 54 43 4c 5f  ;..  return TCL_
a2b0: 4f 4b 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 74 63 6c  OK;.}../*.** tcl
a2c0: 63 6d 64 3a 20 20 73 71 6c 69 74 65 33 5f 6d 75  cmd:  sqlite3_mu
a2d0: 6c 74 69 70 6c 65 78 5f 64 75 6d 70 0a 2a 2f 0a  ltiplex_dump.*/.
a2e0: 73 74 61 74 69 63 20 69 6e 74 20 74 65 73 74 5f  static int test_
a2f0: 6d 75 6c 74 69 70 6c 65 78 5f 64 75 6d 70 28 0a  multiplex_dump(.
a300: 20 20 76 6f 69 64 20 2a 20 63 6c 69 65 6e 74 44    void * clientD
a310: 61 74 61 2c 0a 20 20 54 63 6c 5f 49 6e 74 65 72  ata,.  Tcl_Inter
a320: 70 20 2a 69 6e 74 65 72 70 2c 0a 20 20 69 6e 74  p *interp,.  int
a330: 20 6f 62 6a 63 2c 0a 20 20 54 63 6c 5f 4f 62 6a   objc,.  Tcl_Obj
a340: 20 2a 43 4f 4e 53 54 20 6f 62 6a 76 5b 5d 0a 29   *CONST objv[].)
a350: 7b 0a 20 20 54 63 6c 5f 4f 62 6a 20 2a 70 52 65  {.  Tcl_Obj *pRe
a360: 73 75 6c 74 3b 0a 20 20 54 63 6c 5f 4f 62 6a 20  sult;.  Tcl_Obj 
a370: 2a 70 47 72 6f 75 70 54 65 72 6d 3b 0a 20 20 6d  *pGroupTerm;.  m
a380: 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 2a 70  ultiplexGroup *p
a390: 47 72 6f 75 70 3b 0a 20 20 69 6e 74 20 69 3b 0a  Group;.  int i;.
a3a0: 20 20 69 6e 74 20 6e 43 68 75 6e 6b 73 20 3d 20    int nChunks = 
a3b0: 30 3b 0a 0a 20 20 55 4e 55 53 45 44 5f 50 41 52  0;..  UNUSED_PAR
a3c0: 41 4d 45 54 45 52 28 63 6c 69 65 6e 74 44 61 74  AMETER(clientDat
a3d0: 61 29 3b 0a 20 20 55 4e 55 53 45 44 5f 50 41 52  a);.  UNUSED_PAR
a3e0: 41 4d 45 54 45 52 28 6f 62 6a 63 29 3b 0a 20 20  AMETER(objc);.  
a3f0: 55 4e 55 53 45 44 5f 50 41 52 41 4d 45 54 45 52  UNUSED_PARAMETER
a400: 28 6f 62 6a 76 29 3b 0a 0a 20 20 70 52 65 73 75  (objv);..  pResu
a410: 6c 74 20 3d 20 54 63 6c 5f 4e 65 77 4f 62 6a 28  lt = Tcl_NewObj(
a420: 29 3b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 45 6e  );.  multiplexEn
a430: 74 65 72 28 29 3b 0a 20 20 66 6f 72 28 70 47 72  ter();.  for(pGr
a440: 6f 75 70 3d 67 4d 75 6c 74 69 70 6c 65 78 2e 70  oup=gMultiplex.p
a450: 47 72 6f 75 70 73 3b 20 70 47 72 6f 75 70 3b 20  Groups; pGroup; 
a460: 70 47 72 6f 75 70 3d 70 47 72 6f 75 70 2d 3e 70  pGroup=pGroup->p
a470: 4e 65 78 74 29 7b 0a 20 20 20 20 70 47 72 6f 75  Next){.    pGrou
a480: 70 54 65 72 6d 20 3d 20 54 63 6c 5f 4e 65 77 4f  pTerm = Tcl_NewO
a490: 62 6a 28 29 3b 0a 0a 20 20 20 20 69 66 28 20 70  bj();..    if( p
a4a0: 47 72 6f 75 70 2d 3e 7a 4e 61 6d 65 20 29 7b 0a  Group->zName ){.
a4b0: 20 20 20 20 20 20 70 47 72 6f 75 70 2d 3e 7a 4e        pGroup->zN
a4c0: 61 6d 65 5b 70 47 72 6f 75 70 2d 3e 6e 4e 61 6d  ame[pGroup->nNam
a4d0: 65 5d 20 3d 20 27 5c 30 27 3b 0a 20 20 20 20 20  e] = '\0';.     
a4e0: 20 54 63 6c 5f 4c 69 73 74 4f 62 6a 41 70 70 65   Tcl_ListObjAppe
a4f0: 6e 64 45 6c 65 6d 65 6e 74 28 69 6e 74 65 72 70  ndElement(interp
a500: 2c 20 70 47 72 6f 75 70 54 65 72 6d 2c 0a 20 20  , pGroupTerm,.  
a510: 20 20 20 20 20 20 20 20 54 63 6c 5f 4e 65 77 53          Tcl_NewS
a520: 74 72 69 6e 67 4f 62 6a 28 70 47 72 6f 75 70 2d  tringObj(pGroup-
a530: 3e 7a 4e 61 6d 65 2c 20 2d 31 29 29 3b 0a 20 20  >zName, -1));.  
a540: 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 54    }else{.      T
a550: 63 6c 5f 4c 69 73 74 4f 62 6a 41 70 70 65 6e 64  cl_ListObjAppend
a560: 45 6c 65 6d 65 6e 74 28 69 6e 74 65 72 70 2c 20  Element(interp, 
a570: 70 47 72 6f 75 70 54 65 72 6d 2c 20 54 63 6c 5f  pGroupTerm, Tcl_
a580: 4e 65 77 4f 62 6a 28 29 29 3b 0a 20 20 20 20 7d  NewObj());.    }
a590: 0a 20 20 20 20 54 63 6c 5f 4c 69 73 74 4f 62 6a  .    Tcl_ListObj
a5a0: 41 70 70 65 6e 64 45 6c 65 6d 65 6e 74 28 69 6e  AppendElement(in
a5b0: 74 65 72 70 2c 20 70 47 72 6f 75 70 54 65 72 6d  terp, pGroupTerm
a5c0: 2c 0a 20 20 20 20 20 20 20 20 20 20 54 63 6c 5f  ,.          Tcl_
a5d0: 4e 65 77 49 6e 74 4f 62 6a 28 70 47 72 6f 75 70  NewIntObj(pGroup
a5e0: 2d 3e 6e 4e 61 6d 65 29 29 3b 0a 20 20 20 20 54  ->nName));.    T
a5f0: 63 6c 5f 4c 69 73 74 4f 62 6a 41 70 70 65 6e 64  cl_ListObjAppend
a600: 45 6c 65 6d 65 6e 74 28 69 6e 74 65 72 70 2c 20  Element(interp, 
a610: 70 47 72 6f 75 70 54 65 72 6d 2c 0a 20 20 20 20  pGroupTerm,.    
a620: 20 20 20 20 20 20 54 63 6c 5f 4e 65 77 49 6e 74        Tcl_NewInt
a630: 4f 62 6a 28 70 47 72 6f 75 70 2d 3e 66 6c 61 67  Obj(pGroup->flag
a640: 73 29 29 3b 0a 0a 20 20 20 20 2f 2a 20 63 6f 75  s));..    /* cou
a650: 6e 74 20 6e 75 6d 62 65 72 20 6f 66 20 63 68 75  nt number of chu
a660: 6e 6b 73 20 77 69 74 68 20 6f 70 65 6e 20 68 61  nks with open ha
a670: 6e 64 6c 65 73 20 2a 2f 0a 20 20 20 20 66 6f 72  ndles */.    for
a680: 28 69 3d 30 3b 20 69 3c 70 47 72 6f 75 70 2d 3e  (i=0; i<pGroup->
a690: 6e 52 65 61 6c 3b 20 69 2b 2b 29 7b 0a 20 20 20  nReal; i++){.   
a6a0: 20 20 20 69 66 28 20 70 47 72 6f 75 70 2d 3e 61     if( pGroup->a
a6b0: 52 65 61 6c 5b 69 5d 2e 70 21 3d 30 20 29 20 6e  Real[i].p!=0 ) n
a6c0: 43 68 75 6e 6b 73 2b 2b 3b 0a 20 20 20 20 7d 0a  Chunks++;.    }.
a6d0: 20 20 20 20 54 63 6c 5f 4c 69 73 74 4f 62 6a 41      Tcl_ListObjA
a6e0: 70 70 65 6e 64 45 6c 65 6d 65 6e 74 28 69 6e 74  ppendElement(int
a6f0: 65 72 70 2c 20 70 47 72 6f 75 70 54 65 72 6d 2c  erp, pGroupTerm,
a700: 0a 20 20 20 20 20 20 20 20 20 20 54 63 6c 5f 4e  .          Tcl_N
a710: 65 77 49 6e 74 4f 62 6a 28 6e 43 68 75 6e 6b 73  ewIntObj(nChunks
a720: 29 29 3b 0a 0a 20 20 20 20 54 63 6c 5f 4c 69 73  ));..    Tcl_Lis
a730: 74 4f 62 6a 41 70 70 65 6e 64 45 6c 65 6d 65 6e  tObjAppendElemen
a740: 74 28 69 6e 74 65 72 70 2c 20 70 47 72 6f 75 70  t(interp, pGroup
a750: 54 65 72 6d 2c 0a 20 20 20 20 20 20 20 20 20 20  Term,.          
a760: 54 63 6c 5f 4e 65 77 49 6e 74 4f 62 6a 28 70 47  Tcl_NewIntObj(pG
a770: 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 29 29 3b  roup->szChunk));
a780: 0a 20 20 20 20 54 63 6c 5f 4c 69 73 74 4f 62 6a  .    Tcl_ListObj
a790: 41 70 70 65 6e 64 45 6c 65 6d 65 6e 74 28 69 6e  AppendElement(in
a7a0: 74 65 72 70 2c 20 70 47 72 6f 75 70 54 65 72 6d  terp, pGroupTerm
a7b0: 2c 0a 20 20 20 20 20 20 20 20 20 20 54 63 6c 5f  ,.          Tcl_
a7c0: 4e 65 77 49 6e 74 4f 62 6a 28 70 47 72 6f 75 70  NewIntObj(pGroup
a7d0: 2d 3e 6e 52 65 61 6c 29 29 3b 0a 0a 20 20 20 20  ->nReal));..    
a7e0: 54 63 6c 5f 4c 69 73 74 4f 62 6a 41 70 70 65 6e  Tcl_ListObjAppen
a7f0: 64 45 6c 65 6d 65 6e 74 28 69 6e 74 65 72 70 2c  dElement(interp,
a800: 20 70 52 65 73 75 6c 74 2c 20 70 47 72 6f 75 70   pResult, pGroup
a810: 54 65 72 6d 29 3b 0a 20 20 7d 0a 20 20 6d 75 6c  Term);.  }.  mul
a820: 74 69 70 6c 65 78 4c 65 61 76 65 28 29 3b 0a 20  tiplexLeave();. 
a830: 20 54 63 6c 5f 53 65 74 4f 62 6a 52 65 73 75 6c   Tcl_SetObjResul
a840: 74 28 69 6e 74 65 72 70 2c 20 70 52 65 73 75 6c  t(interp, pResul
a850: 74 29 3b 0a 20 20 72 65 74 75 72 6e 20 54 43 4c  t);.  return TCL
a860: 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54 63  _OK;.}../*.** Tc
a870: 6c 63 6d 64 3a 20 74 65 73 74 5f 6d 75 6c 74 69  lcmd: test_multi
a880: 70 6c 65 78 5f 63 6f 6e 74 72 6f 6c 20 48 41 4e  plex_control HAN
a890: 44 4c 45 20 44 42 4e 41 4d 45 20 53 55 42 2d 43  DLE DBNAME SUB-C
a8a0: 4f 4d 4d 41 4e 44 20 3f 49 4e 54 2d 56 41 4c 55  OMMAND ?INT-VALU
a8b0: 45 3f 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74  E?.*/.static int
a8c0: 20 74 65 73 74 5f 6d 75 6c 74 69 70 6c 65 78 5f   test_multiplex_
a8d0: 63 6f 6e 74 72 6f 6c 28 0a 20 20 43 6c 69 65 6e  control(.  Clien
a8e0: 74 44 61 74 61 20 63 64 2c 0a 20 20 54 63 6c 5f  tData cd,.  Tcl_
a8f0: 49 6e 74 65 72 70 20 2a 69 6e 74 65 72 70 2c 0a  Interp *interp,.
a900: 20 20 69 6e 74 20 6f 62 6a 63 2c 0a 20 20 54 63    int objc,.  Tc
a910: 6c 5f 4f 62 6a 20 2a 43 4f 4e 53 54 20 6f 62 6a  l_Obj *CONST obj
a920: 76 5b 5d 0a 29 7b 0a 20 20 69 6e 74 20 72 63 3b  v[].){.  int rc;
a930: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a940: 20 20 20 20 20 20 20 20 20 2f 2a 20 52 65 74 75           /* Retu
a950: 72 6e 20 63 6f 64 65 20 66 72 6f 6d 20 66 69 6c  rn code from fil
a960: 65 5f 63 6f 6e 74 72 6f 6c 28 29 20 2a 2f 0a 20  e_control() */. 
a970: 20 69 6e 74 20 69 64 78 3b 20 20 20 20 20 20 20   int idx;       
a980: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a990: 20 2f 2a 20 49 6e 64 65 78 20 69 6e 20 61 53 75   /* Index in aSu
a9a0: 62 5b 5d 20 2a 2f 0a 20 20 54 63 6c 5f 43 6d 64  b[] */.  Tcl_Cmd
a9b0: 49 6e 66 6f 20 63 6d 64 49 6e 66 6f 3b 20 20 20  Info cmdInfo;   
a9c0: 20 20 20 20 20 20 20 20 20 2f 2a 20 43 6f 6d 6d           /* Comm
a9d0: 61 6e 64 20 69 6e 66 6f 20 73 74 72 75 63 74 75  and info structu
a9e0: 72 65 20 66 6f 72 20 48 41 4e 44 4c 45 20 2a 2f  re for HANDLE */
a9f0: 0a 20 20 73 71 6c 69 74 65 33 20 2a 64 62 3b 20  .  sqlite3 *db; 
aa00: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
aa10: 20 20 20 2f 2a 20 55 6e 64 65 72 6c 79 69 6e 67     /* Underlying
aa20: 20 64 62 20 68 61 6e 64 6c 65 20 66 6f 72 20 48   db handle for H
aa30: 41 4e 44 4c 45 20 2a 2f 0a 20 20 69 6e 74 20 69  ANDLE */.  int i
aa40: 56 61 6c 75 65 20 3d 20 30 3b 0a 20 20 76 6f 69  Value = 0;.  voi
aa50: 64 20 2a 70 41 72 67 20 3d 20 30 3b 0a 0a 20 20  d *pArg = 0;..  
aa60: 73 74 72 75 63 74 20 53 75 62 43 6f 6d 6d 61 6e  struct SubComman
aa70: 64 20 7b 0a 20 20 20 20 63 6f 6e 73 74 20 63 68  d {.    const ch
aa80: 61 72 20 2a 7a 4e 61 6d 65 3b 0a 20 20 20 20 69  ar *zName;.    i
aa90: 6e 74 20 6f 70 3b 0a 20 20 20 20 69 6e 74 20 61  nt op;.    int a
aaa0: 72 67 74 79 70 65 3b 0a 20 20 7d 20 61 53 75 62  rgtype;.  } aSub
aab0: 5b 5d 20 3d 20 7b 0a 20 20 20 20 7b 20 22 65 6e  [] = {.    { "en
aac0: 61 62 6c 65 22 2c 20 20 20 20 20 20 20 4d 55 4c  able",       MUL
aad0: 54 49 50 4c 45 58 5f 43 54 52 4c 5f 45 4e 41 42  TIPLEX_CTRL_ENAB
aae0: 4c 45 2c 20 20 20 20 20 20 20 20 20 20 20 31 20  LE,           1 
aaf0: 7d 2c 0a 20 20 20 20 7b 20 22 63 68 75 6e 6b 5f  },.    { "chunk_
ab00: 73 69 7a 65 22 2c 20 20 20 4d 55 4c 54 49 50 4c  size",   MULTIPL
ab10: 45 58 5f 43 54 52 4c 5f 53 45 54 5f 43 48 55 4e  EX_CTRL_SET_CHUN
ab20: 4b 5f 53 49 5a 45 2c 20 20 20 31 20 7d 2c 0a 20  K_SIZE,   1 },. 
ab30: 20 20 20 7b 20 22 6d 61 78 5f 63 68 75 6e 6b 73     { "max_chunks
ab40: 22 2c 20 20 20 4d 55 4c 54 49 50 4c 45 58 5f 43  ",   MULTIPLEX_C
ab50: 54 52 4c 5f 53 45 54 5f 4d 41 58 5f 43 48 55 4e  TRL_SET_MAX_CHUN
ab60: 4b 53 2c 20 20 20 31 20 7d 2c 0a 20 20 20 20 7b  KS,   1 },.    {
ab70: 20 30 2c 20 30 2c 20 30 20 7d 0a 20 20 7d 3b 0a   0, 0, 0 }.  };.
ab80: 0a 20 20 69 66 28 20 6f 62 6a 63 21 3d 35 20 29  .  if( objc!=5 )
ab90: 7b 0a 20 20 20 20 54 63 6c 5f 57 72 6f 6e 67 4e  {.    Tcl_WrongN
aba0: 75 6d 41 72 67 73 28 69 6e 74 65 72 70 2c 20 31  umArgs(interp, 1
abb0: 2c 20 6f 62 6a 76 2c 20 22 48 41 4e 44 4c 45 20  , objv, "HANDLE 
abc0: 44 42 4e 41 4d 45 20 53 55 42 2d 43 4f 4d 4d 41  DBNAME SUB-COMMA
abd0: 4e 44 20 49 4e 54 2d 56 41 4c 55 45 22 29 3b 0a  ND INT-VALUE");.
abe0: 20 20 20 20 72 65 74 75 72 6e 20 54 43 4c 5f 45      return TCL_E
abf0: 52 52 4f 52 3b 0a 20 20 7d 0a 0a 20 20 69 66 28  RROR;.  }..  if(
ac00: 20 30 3d 3d 54 63 6c 5f 47 65 74 43 6f 6d 6d 61   0==Tcl_GetComma
ac10: 6e 64 49 6e 66 6f 28 69 6e 74 65 72 70 2c 20 54  ndInfo(interp, T
ac20: 63 6c 5f 47 65 74 53 74 72 69 6e 67 28 6f 62 6a  cl_GetString(obj
ac30: 76 5b 31 5d 29 2c 20 26 63 6d 64 49 6e 66 6f 29  v[1]), &cmdInfo)
ac40: 20 29 7b 0a 20 20 20 20 54 63 6c 5f 41 70 70 65   ){.    Tcl_Appe
ac50: 6e 64 52 65 73 75 6c 74 28 69 6e 74 65 72 70 2c  ndResult(interp,
ac60: 20 22 65 78 70 65 63 74 65 64 20 64 61 74 61 62   "expected datab
ac70: 61 73 65 20 68 61 6e 64 6c 65 2c 20 67 6f 74 20  ase handle, got 
ac80: 5c 22 22 2c 20 30 29 3b 0a 20 20 20 20 54 63 6c  \"", 0);.    Tcl
ac90: 5f 41 70 70 65 6e 64 52 65 73 75 6c 74 28 69 6e  _AppendResult(in
aca0: 74 65 72 70 2c 20 54 63 6c 5f 47 65 74 53 74 72  terp, Tcl_GetStr
acb0: 69 6e 67 28 6f 62 6a 76 5b 31 5d 29 2c 20 22 5c  ing(objv[1]), "\
acc0: 22 22 2c 20 30 29 3b 0a 20 20 20 20 72 65 74 75  "", 0);.    retu
acd0: 72 6e 20 54 43 4c 5f 45 52 52 4f 52 3b 0a 20 20  rn TCL_ERROR;.  
ace0: 7d 65 6c 73 65 7b 0a 20 20 20 20 64 62 20 3d 20  }else{.    db = 
acf0: 2a 28 73 71 6c 69 74 65 33 20 2a 2a 29 63 6d 64  *(sqlite3 **)cmd
ad00: 49 6e 66 6f 2e 6f 62 6a 43 6c 69 65 6e 74 44 61  Info.objClientDa
ad10: 74 61 3b 0a 20 20 7d 0a 0a 20 20 72 63 20 3d 20  ta;.  }..  rc = 
ad20: 54 63 6c 5f 47 65 74 49 6e 64 65 78 46 72 6f 6d  Tcl_GetIndexFrom
ad30: 4f 62 6a 53 74 72 75 63 74 28 0a 20 20 20 20 20  ObjStruct(.     
ad40: 20 69 6e 74 65 72 70 2c 20 6f 62 6a 76 5b 33 5d   interp, objv[3]
ad50: 2c 20 61 53 75 62 2c 20 73 69 7a 65 6f 66 28 61  , aSub, sizeof(a
ad60: 53 75 62 5b 30 5d 29 2c 20 22 73 75 62 2d 63 6f  Sub[0]), "sub-co
ad70: 6d 6d 61 6e 64 22 2c 20 30 2c 20 26 69 64 78 0a  mmand", 0, &idx.
ad80: 20 20 29 3b 0a 20 20 69 66 28 20 72 63 21 3d 54    );.  if( rc!=T
ad90: 43 4c 5f 4f 4b 20 29 20 72 65 74 75 72 6e 20 72  CL_OK ) return r
ada0: 63 3b 0a 0a 20 20 73 77 69 74 63 68 28 20 61 53  c;..  switch( aS
adb0: 75 62 5b 69 64 78 5d 2e 61 72 67 74 79 70 65 20  ub[idx].argtype 
adc0: 29 7b 0a 20 20 20 20 63 61 73 65 20 31 3a 0a 20  ){.    case 1:. 
add0: 20 20 20 20 20 69 66 28 20 54 63 6c 5f 47 65 74       if( Tcl_Get
ade0: 49 6e 74 46 72 6f 6d 4f 62 6a 28 69 6e 74 65 72  IntFromObj(inter
adf0: 70 2c 20 6f 62 6a 76 5b 34 5d 2c 20 26 69 56 61  p, objv[4], &iVa
ae00: 6c 75 65 29 20 29 7b 0a 20 20 20 20 20 20 20 20  lue) ){.        
ae10: 72 65 74 75 72 6e 20 54 43 4c 5f 45 52 52 4f 52  return TCL_ERROR
ae20: 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20  ;.      }.      
ae30: 70 41 72 67 20 3d 20 28 76 6f 69 64 20 2a 29 26  pArg = (void *)&
ae40: 69 56 61 6c 75 65 3b 0a 20 20 20 20 20 20 62 72  iValue;.      br
ae50: 65 61 6b 3b 0a 20 20 20 20 64 65 66 61 75 6c 74  eak;.    default
ae60: 3a 0a 20 20 20 20 20 20 54 63 6c 5f 57 72 6f 6e  :.      Tcl_Wron
ae70: 67 4e 75 6d 41 72 67 73 28 69 6e 74 65 72 70 2c  gNumArgs(interp,
ae80: 20 34 2c 20 6f 62 6a 76 2c 20 22 53 55 42 2d 43   4, objv, "SUB-C
ae90: 4f 4d 4d 41 4e 44 22 29 3b 0a 20 20 20 20 20 20  OMMAND");.      
aea0: 72 65 74 75 72 6e 20 54 43 4c 5f 45 52 52 4f 52  return TCL_ERROR
aeb0: 3b 0a 20 20 7d 0a 0a 20 20 72 63 20 3d 20 73 71  ;.  }..  rc = sq
aec0: 6c 69 74 65 33 5f 66 69 6c 65 5f 63 6f 6e 74 72  lite3_file_contr
aed0: 6f 6c 28 64 62 2c 20 54 63 6c 5f 47 65 74 53 74  ol(db, Tcl_GetSt
aee0: 72 69 6e 67 28 6f 62 6a 76 5b 32 5d 29 2c 20 61  ring(objv[2]), a
aef0: 53 75 62 5b 69 64 78 5d 2e 6f 70 2c 20 70 41 72  Sub[idx].op, pAr
af00: 67 29 3b 0a 20 20 54 63 6c 5f 53 65 74 52 65 73  g);.  Tcl_SetRes
af10: 75 6c 74 28 69 6e 74 65 72 70 2c 20 28 63 68 61  ult(interp, (cha
af20: 72 20 2a 29 73 71 6c 69 74 65 33 54 65 73 74 45  r *)sqlite3TestE
af30: 72 72 6f 72 4e 61 6d 65 28 72 63 29 2c 20 54 43  rrorName(rc), TC
af40: 4c 5f 53 54 41 54 49 43 29 3b 0a 20 20 72 65 74  L_STATIC);.  ret
af50: 75 72 6e 20 28 72 63 3d 3d 53 51 4c 49 54 45 5f  urn (rc==SQLITE_
af60: 4f 4b 29 20 3f 20 54 43 4c 5f 4f 4b 20 3a 20 54  OK) ? TCL_OK : T
af70: 43 4c 5f 45 52 52 4f 52 3b 0a 7d 0a 0a 2f 2a 0a  CL_ERROR;.}../*.
af80: 2a 2a 20 54 68 69 73 20 72 6f 75 74 69 6e 65 20  ** This routine 
af90: 72 65 67 69 73 74 65 72 73 20 74 68 65 20 63 75  registers the cu
afa0: 73 74 6f 6d 20 54 43 4c 20 63 6f 6d 6d 61 6e 64  stom TCL command
afb0: 73 20 64 65 66 69 6e 65 64 20 69 6e 20 74 68 69  s defined in thi
afc0: 73 0a 2a 2a 20 6d 6f 64 75 6c 65 2e 20 20 54 68  s.** module.  Th
afd0: 69 73 20 73 68 6f 75 6c 64 20 62 65 20 74 68 65  is should be the
afe0: 20 6f 6e 6c 79 20 70 72 6f 63 65 64 75 72 65 20   only procedure 
aff0: 76 69 73 69 62 6c 65 20 66 72 6f 6d 20 6f 75 74  visible from out
b000: 73 69 64 65 0a 2a 2a 20 6f 66 20 74 68 69 73 20  side.** of this 
b010: 6d 6f 64 75 6c 65 2e 0a 2a 2f 0a 69 6e 74 20 53  module..*/.int S
b020: 71 6c 69 74 65 6d 75 6c 74 69 70 6c 65 78 5f 49  qlitemultiplex_I
b030: 6e 69 74 28 54 63 6c 5f 49 6e 74 65 72 70 20 2a  nit(Tcl_Interp *
b040: 69 6e 74 65 72 70 29 7b 0a 20 20 73 74 61 74 69  interp){.  stati
b050: 63 20 73 74 72 75 63 74 20 7b 0a 20 20 20 20 20  c struct {.     
b060: 63 68 61 72 20 2a 7a 4e 61 6d 65 3b 0a 20 20 20  char *zName;.   
b070: 20 20 54 63 6c 5f 4f 62 6a 43 6d 64 50 72 6f 63    Tcl_ObjCmdProc
b080: 20 2a 78 50 72 6f 63 3b 0a 20 20 7d 20 61 43 6d   *xProc;.  } aCm
b090: 64 5b 5d 20 3d 20 7b 0a 20 20 20 20 7b 20 22 73  d[] = {.    { "s
b0a0: 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78  qlite3_multiplex
b0b0: 5f 69 6e 69 74 69 61 6c 69 7a 65 22 2c 20 74 65  _initialize", te
b0c0: 73 74 5f 6d 75 6c 74 69 70 6c 65 78 5f 69 6e 69  st_multiplex_ini
b0d0: 74 69 61 6c 69 7a 65 20 7d 2c 0a 20 20 20 20 7b  tialize },.    {
b0e0: 20 22 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70   "sqlite3_multip
b0f0: 6c 65 78 5f 73 68 75 74 64 6f 77 6e 22 2c 20 74  lex_shutdown", t
b100: 65 73 74 5f 6d 75 6c 74 69 70 6c 65 78 5f 73 68  est_multiplex_sh
b110: 75 74 64 6f 77 6e 20 7d 2c 0a 20 20 20 20 7b 20  utdown },.    { 
b120: 22 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c  "sqlite3_multipl
b130: 65 78 5f 64 75 6d 70 22 2c 20 74 65 73 74 5f 6d  ex_dump", test_m
b140: 75 6c 74 69 70 6c 65 78 5f 64 75 6d 70 20 7d 2c  ultiplex_dump },
b150: 0a 20 20 20 20 7b 20 22 73 71 6c 69 74 65 33 5f  .    { "sqlite3_
b160: 6d 75 6c 74 69 70 6c 65 78 5f 63 6f 6e 74 72 6f  multiplex_contro
b170: 6c 22 2c 20 74 65 73 74 5f 6d 75 6c 74 69 70 6c  l", test_multipl
b180: 65 78 5f 63 6f 6e 74 72 6f 6c 20 7d 2c 0a 20 20  ex_control },.  
b190: 7d 3b 0a 20 20 69 6e 74 20 69 3b 0a 0a 20 20 66  };.  int i;..  f
b1a0: 6f 72 28 69 3d 30 3b 20 69 3c 73 69 7a 65 6f 66  or(i=0; i<sizeof
b1b0: 28 61 43 6d 64 29 2f 73 69 7a 65 6f 66 28 61 43  (aCmd)/sizeof(aC
b1c0: 6d 64 5b 30 5d 29 3b 20 69 2b 2b 29 7b 0a 20 20  md[0]); i++){.  
b1d0: 20 20 54 63 6c 5f 43 72 65 61 74 65 4f 62 6a 43    Tcl_CreateObjC
b1e0: 6f 6d 6d 61 6e 64 28 69 6e 74 65 72 70 2c 20 61  ommand(interp, a
b1f0: 43 6d 64 5b 69 5d 2e 7a 4e 61 6d 65 2c 20 61 43  Cmd[i].zName, aC
b200: 6d 64 5b 69 5d 2e 78 50 72 6f 63 2c 20 30 2c 20  md[i].xProc, 0, 
b210: 30 29 3b 0a 20 20 7d 0a 0a 20 20 72 65 74 75 72  0);.  }..  retur
b220: 6e 20 54 43 4c 5f 4f 4b 3b 0a 7d 0a 23 65 6e 64  n TCL_OK;.}.#end
b230: 69 66 0a                                         if.