/ Hex Artifact Content
Login

Artifact 6a65dd5006117d26718110a8e00b0118aa5c98a1:


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 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  .../************
0c90: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20 53 68 69  ************ Shi
0ca0: 6d 20 44 65 66 69 6e 69 74 69 6f 6e 73 20 2a 2a  m Definitions **
0cb0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0cc0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2f 0a 0a 23  ************/..#
0cd0: 69 66 6e 64 65 66 20 53 51 4c 49 54 45 5f 4d 55  ifndef SQLITE_MU
0ce0: 4c 54 49 50 4c 45 58 5f 56 46 53 5f 4e 41 4d 45  LTIPLEX_VFS_NAME
0cf0: 0a 23 20 64 65 66 69 6e 65 20 53 51 4c 49 54 45  .# define SQLITE
0d00: 5f 4d 55 4c 54 49 50 4c 45 58 5f 56 46 53 5f 4e  _MULTIPLEX_VFS_N
0d10: 41 4d 45 20 22 6d 75 6c 74 69 70 6c 65 78 22 0a  AME "multiplex".
0d20: 23 65 6e 64 69 66 0a 0a 2f 2a 20 54 68 69 73 20  #endif../* This 
0d30: 69 73 20 74 68 65 20 6c 69 6d 69 74 20 6f 6e 20  is the limit on 
0d40: 74 68 65 20 63 68 75 6e 6b 20 73 69 7a 65 2e 20  the chunk size. 
0d50: 20 49 74 20 6d 61 79 20 62 65 20 63 68 61 6e 67   It may be chang
0d60: 65 64 20 62 79 20 63 61 6c 6c 69 6e 67 0a 2a 2a  ed by calling.**
0d70: 20 74 68 65 20 78 46 69 6c 65 43 6f 6e 74 72 6f   the xFileContro
0d80: 6c 28 29 20 69 6e 74 65 72 66 61 63 65 2e 20 20  l() interface.  
0d90: 49 74 20 77 69 6c 6c 20 62 65 20 72 6f 75 6e 64  It will be round
0da0: 65 64 20 75 70 20 74 6f 20 61 20 0a 2a 2a 20 6d  ed up to a .** m
0db0: 75 6c 74 69 70 6c 65 20 6f 66 20 4d 41 58 5f 50  ultiple of MAX_P
0dc0: 41 47 45 5f 53 49 5a 45 2e 20 20 57 65 20 64 65  AGE_SIZE.  We de
0dd0: 66 61 75 6c 74 20 69 74 20 68 65 72 65 20 74 6f  fault it here to
0de0: 20 32 47 69 42 20 6c 65 73 73 20 36 34 4b 69 42   2GiB less 64KiB
0df0: 2e 0a 2a 2f 0a 23 69 66 6e 64 65 66 20 53 51 4c  ..*/.#ifndef SQL
0e00: 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 43 48  ITE_MULTIPLEX_CH
0e10: 55 4e 4b 5f 53 49 5a 45 0a 23 20 64 65 66 69 6e  UNK_SIZE.# defin
0e20: 65 20 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c  e SQLITE_MULTIPL
0e30: 45 58 5f 43 48 55 4e 4b 5f 53 49 5a 45 20 32 31  EX_CHUNK_SIZE 21
0e40: 34 37 34 31 38 31 31 32 0a 23 65 6e 64 69 66 0a  47418112.#endif.
0e50: 0a 2f 2a 20 44 65 66 61 75 6c 74 20 6c 69 6d 69  ./* Default limi
0e60: 74 20 6f 6e 20 6e 75 6d 62 65 72 20 6f 66 20 63  t on number of c
0e70: 68 75 6e 6b 73 2e 0a 2a 2a 20 4d 61 79 20 62 65  hunks..** May be
0e80: 20 63 68 61 6e 67 65 64 20 62 79 20 63 61 6c 6c   changed by call
0e90: 69 6e 67 0a 2a 2a 20 74 68 65 20 78 46 69 6c 65  ing.** the xFile
0ea0: 43 6f 6e 74 72 6f 6c 28 29 20 69 6e 74 65 72 66  Control() interf
0eb0: 61 63 65 2e 0a 2a 2f 0a 23 69 66 6e 64 65 66 20  ace..*/.#ifndef 
0ec0: 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58  SQLITE_MULTIPLEX
0ed0: 5f 4d 41 58 5f 43 48 55 4e 4b 53 0a 23 20 64 65  _MAX_CHUNKS.# de
0ee0: 66 69 6e 65 20 53 51 4c 49 54 45 5f 4d 55 4c 54  fine SQLITE_MULT
0ef0: 49 50 4c 45 58 5f 4d 41 58 5f 43 48 55 4e 4b 53  IPLEX_MAX_CHUNKS
0f00: 20 33 32 0a 23 65 6e 64 69 66 0a 0a 2f 2a 2a 2a   32.#endif../***
0f10: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0f20: 2a 2a 2a 2a 2a 20 4f 62 6a 65 63 74 20 44 65 66  ***** Object Def
0f30: 69 6e 69 74 69 6f 6e 73 20 2a 2a 2a 2a 2a 2a 2a  initions *******
0f40: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0f50: 2a 2a 2a 2a 2a 2a 2a 2f 0a 0a 2f 2a 20 46 6f 72  *******/../* For
0f60: 77 61 72 64 20 64 65 63 6c 61 72 61 74 69 6f 6e  ward declaration
0f70: 20 6f 66 20 61 6c 6c 20 6f 62 6a 65 63 74 20 74   of all object t
0f80: 79 70 65 73 20 2a 2f 0a 74 79 70 65 64 65 66 20  ypes */.typedef 
0f90: 73 74 72 75 63 74 20 6d 75 6c 74 69 70 6c 65 78  struct multiplex
0fa0: 47 72 6f 75 70 20 6d 75 6c 74 69 70 6c 65 78 47  Group multiplexG
0fb0: 72 6f 75 70 3b 0a 74 79 70 65 64 65 66 20 73 74  roup;.typedef st
0fc0: 72 75 63 74 20 6d 75 6c 74 69 70 6c 65 78 43 6f  ruct multiplexCo
0fd0: 6e 6e 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e  nn multiplexConn
0fe0: 3b 0a 0a 2f 2a 0a 2a 2a 20 41 20 22 6d 75 6c 74  ;../*.** A "mult
0ff0: 69 70 6c 65 78 20 67 72 6f 75 70 22 20 69 73 20  iplex group" is 
1000: 61 20 63 6f 6c 6c 65 63 74 69 6f 6e 20 6f 66 20  a collection of 
1010: 66 69 6c 65 73 20 74 68 61 74 20 63 6f 6c 6c 65  files that colle
1020: 63 74 69 76 65 6c 79 0a 2a 2a 20 6d 61 6b 65 75  ctively.** makeu
1030: 70 20 61 20 73 69 6e 67 6c 65 20 53 51 4c 69 74  p a single SQLit
1040: 65 20 44 42 20 66 69 6c 65 2e 20 20 54 68 69 73  e DB file.  This
1050: 20 61 6c 6c 6f 77 73 20 74 68 65 20 73 69 7a 65   allows the size
1060: 20 6f 66 20 74 68 65 20 44 42 0a 2a 2a 20 74 6f   of the DB.** to
1070: 20 65 78 63 65 65 64 20 74 68 65 20 6c 69 6d 69   exceed the limi
1080: 74 73 20 69 6d 70 6f 73 65 64 20 62 79 20 74 68  ts imposed by th
1090: 65 20 66 69 6c 65 20 73 79 73 74 65 6d 2e 0a 2a  e file system..*
10a0: 2a 0a 2a 2a 20 54 68 65 72 65 20 69 73 20 61 6e  *.** There is an
10b0: 20 69 6e 73 74 61 6e 63 65 20 6f 66 20 74 68 65   instance of the
10c0: 20 66 6f 6c 6c 6f 77 69 6e 67 20 6f 62 6a 65 63   following objec
10d0: 74 20 66 6f 72 20 65 61 63 68 20 64 65 66 69 6e  t for each defin
10e0: 65 64 20 6d 75 6c 74 69 70 6c 65 78 0a 2a 2a 20  ed multiplex.** 
10f0: 67 72 6f 75 70 2e 0a 2a 2f 0a 73 74 72 75 63 74  group..*/.struct
1100: 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 20   multiplexGroup 
1110: 7b 0a 20 20 73 74 72 75 63 74 20 6d 75 6c 74 69  {.  struct multi
1120: 70 6c 65 78 52 65 61 6c 20 7b 20 20 20 20 20 20  plexReal {      
1130: 20 20 20 20 20 2f 2a 20 46 6f 72 20 65 61 63 68       /* For each
1140: 20 63 68 75 6e 6b 20 2a 2f 0a 20 20 20 20 73 71   chunk */.    sq
1150: 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 3b 20 20  lite3_file *p;  
1160: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1170: 2f 2a 20 48 61 6e 64 6c 65 20 66 6f 72 20 74 68  /* Handle for th
1180: 65 20 63 68 75 6e 6b 20 2a 2f 0a 20 20 20 20 63  e chunk */.    c
1190: 68 61 72 20 2a 7a 3b 20 20 20 20 20 20 20 20 20  har *z;         
11a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
11b0: 20 2f 2a 20 4e 61 6d 65 20 6f 66 20 74 68 69 73   /* Name of this
11c0: 20 63 68 75 6e 6b 20 2a 2f 0a 20 20 7d 20 2a 61   chunk */.  } *a
11d0: 52 65 61 6c 3b 20 20 20 20 20 20 20 20 20 20 20  Real;           
11e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
11f0: 6c 69 73 74 20 6f 66 20 61 6c 6c 20 63 68 75 6e  list of all chun
1200: 6b 73 20 2a 2f 0a 20 20 69 6e 74 20 6e 52 65 61  ks */.  int nRea
1210: 6c 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  l;              
1220: 20 20 20 20 20 20 20 20 20 2f 2a 20 4e 75 6d 62           /* Numb
1230: 65 72 20 6f 66 20 63 68 75 6e 6b 73 20 2a 2f 0a  er of chunks */.
1240: 20 20 63 68 61 72 20 2a 7a 4e 61 6d 65 3b 20 20    char *zName;  
1250: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1260: 20 20 20 2f 2a 20 42 61 73 65 20 66 69 6c 65 6e     /* Base filen
1270: 61 6d 65 20 6f 66 20 74 68 69 73 20 67 72 6f 75  ame of this grou
1280: 70 20 2a 2f 0a 20 20 69 6e 74 20 6e 4e 61 6d 65  p */.  int nName
1290: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ;               
12a0: 20 20 20 20 20 20 20 20 2f 2a 20 4c 65 6e 67 74          /* Lengt
12b0: 68 20 6f 66 20 62 61 73 65 20 66 69 6c 65 6e 61  h of base filena
12c0: 6d 65 20 2a 2f 0a 20 20 69 6e 74 20 66 6c 61 67  me */.  int flag
12d0: 73 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  s;              
12e0: 20 20 20 20 20 20 20 20 20 2f 2a 20 46 6c 61 67           /* Flag
12f0: 73 20 75 73 65 64 20 66 6f 72 20 6f 72 69 67 69  s used for origi
1300: 6e 61 6c 20 6f 70 65 6e 69 6e 67 20 2a 2f 0a 20  nal opening */. 
1310: 20 75 6e 73 69 67 6e 65 64 20 69 6e 74 20 73 7a   unsigned int sz
1320: 43 68 75 6e 6b 3b 20 20 20 20 20 20 20 20 20 20  Chunk;          
1330: 20 20 2f 2a 20 43 68 75 6e 6b 20 73 69 7a 65 20    /* Chunk size 
1340: 75 73 65 64 20 66 6f 72 20 74 68 69 73 20 67 72  used for this gr
1350: 6f 75 70 20 2a 2f 0a 20 20 69 6e 74 20 62 45 6e  oup */.  int bEn
1360: 61 62 6c 65 64 3b 20 20 20 20 20 20 20 20 20 20  abled;          
1370: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 54 52 55            /* TRU
1380: 45 20 74 6f 20 75 73 65 20 4d 75 6c 74 69 70 6c  E to use Multipl
1390: 65 78 20 56 46 53 20 66 6f 72 20 74 68 69 73 20  ex VFS for this 
13a0: 66 69 6c 65 20 2a 2f 0a 20 20 6d 75 6c 74 69 70  file */.  multip
13b0: 6c 65 78 47 72 6f 75 70 20 2a 70 4e 65 78 74 2c  lexGroup *pNext,
13c0: 20 2a 70 50 72 65 76 3b 20 20 20 2f 2a 20 44 6f   *pPrev;   /* Do
13d0: 75 62 6c 79 20 6c 69 6e 6b 65 64 20 6c 69 73 74  ubly linked list
13e0: 20 6f 66 20 61 6c 6c 20 67 72 6f 75 70 20 6f 62   of all group ob
13f0: 6a 65 63 74 73 20 2a 2f 0a 7d 3b 0a 0a 2f 2a 0a  jects */.};../*.
1400: 2a 2a 20 41 6e 20 69 6e 73 74 61 6e 63 65 20 6f  ** An instance o
1410: 66 20 74 68 65 20 66 6f 6c 6c 6f 77 69 6e 67 20  f the following 
1420: 6f 62 6a 65 63 74 20 72 65 70 72 65 73 65 6e 74  object represent
1430: 73 20 65 61 63 68 20 6f 70 65 6e 20 63 6f 6e 6e  s each open conn
1440: 65 63 74 69 6f 6e 0a 2a 2a 20 74 6f 20 61 20 66  ection.** to a f
1450: 69 6c 65 20 74 68 61 74 20 69 73 20 6d 75 6c 74  ile that is mult
1460: 69 70 6c 65 78 27 65 64 2e 20 20 54 68 69 73 20  iplex'ed.  This 
1470: 6f 62 6a 65 63 74 20 69 73 20 61 20 0a 2a 2a 20  object is a .** 
1480: 73 75 62 63 6c 61 73 73 20 6f 66 20 73 71 6c 69  subclass of sqli
1490: 74 65 33 5f 66 69 6c 65 2e 20 20 54 68 65 20 73  te3_file.  The s
14a0: 71 6c 69 74 65 33 5f 66 69 6c 65 20 6f 62 6a 65  qlite3_file obje
14b0: 63 74 20 66 6f 72 20 74 68 65 20 75 6e 64 65 72  ct for the under
14c0: 6c 79 69 6e 67 0a 2a 2a 20 56 46 53 20 69 73 20  lying.** VFS is 
14d0: 61 70 70 65 6e 64 65 64 20 74 6f 20 74 68 69 73  appended to this
14e0: 20 73 74 72 75 63 74 75 72 65 2e 0a 2a 2f 0a 73   structure..*/.s
14f0: 74 72 75 63 74 20 6d 75 6c 74 69 70 6c 65 78 43  truct multiplexC
1500: 6f 6e 6e 20 7b 0a 20 20 73 71 6c 69 74 65 33 5f  onn {.  sqlite3_
1510: 66 69 6c 65 20 62 61 73 65 3b 20 20 20 20 20 20  file base;      
1520: 20 20 20 20 20 20 20 20 2f 2a 20 42 61 73 65 20          /* Base 
1530: 63 6c 61 73 73 20 2d 20 6d 75 73 74 20 62 65 20  class - must be 
1540: 66 69 72 73 74 20 2a 2f 0a 20 20 6d 75 6c 74 69  first */.  multi
1550: 70 6c 65 78 47 72 6f 75 70 20 2a 70 47 72 6f 75  plexGroup *pGrou
1560: 70 3b 20 20 20 20 20 20 20 20 20 2f 2a 20 54 68  p;         /* Th
1570: 65 20 75 6e 64 65 72 6c 79 69 6e 67 20 67 72 6f  e underlying gro
1580: 75 70 20 6f 66 20 66 69 6c 65 73 20 2a 2f 0a 7d  up of files */.}
1590: 3b 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ;../************
15a0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20 47 6c  ************* Gl
15b0: 6f 62 61 6c 20 56 61 72 69 61 62 6c 65 73 20 2a  obal Variables *
15c0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
15d0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
15e0: 2a 2f 0a 2f 2a 0a 2a 2a 20 41 6c 6c 20 67 6c 6f  */./*.** All glo
15f0: 62 61 6c 20 76 61 72 69 61 62 6c 65 73 20 75 73  bal variables us
1600: 65 64 20 62 79 20 74 68 69 73 20 66 69 6c 65 20  ed by this file 
1610: 61 72 65 20 63 6f 6e 74 61 69 6e 69 6e 67 20 77  are containing w
1620: 69 74 68 69 6e 20 74 68 65 20 66 6f 6c 6c 6f 77  ithin the follow
1630: 69 6e 67 0a 2a 2a 20 67 4d 75 6c 74 69 70 6c 65  ing.** gMultiple
1640: 78 20 73 74 72 75 63 74 75 72 65 2e 0a 2a 2f 0a  x structure..*/.
1650: 73 74 61 74 69 63 20 73 74 72 75 63 74 20 7b 0a  static struct {.
1660: 20 20 2f 2a 20 54 68 65 20 70 4f 72 69 67 56 66    /* The pOrigVf
1670: 73 20 69 73 20 74 68 65 20 72 65 61 6c 2c 20 6f  s is the real, o
1680: 72 69 67 69 6e 61 6c 20 75 6e 64 65 72 6c 79 69  riginal underlyi
1690: 6e 67 20 56 46 53 20 69 6d 70 6c 65 6d 65 6e 74  ng VFS implement
16a0: 61 74 69 6f 6e 2e 0a 20 20 2a 2a 20 4d 6f 73 74  ation..  ** Most
16b0: 20 6f 70 65 72 61 74 69 6f 6e 73 20 70 61 73 73   operations pass
16c0: 2d 74 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20  -through to the 
16d0: 72 65 61 6c 20 56 46 53 2e 20 20 54 68 69 73 20  real VFS.  This 
16e0: 76 61 6c 75 65 20 69 73 20 72 65 61 64 2d 6f 6e  value is read-on
16f0: 6c 79 0a 20 20 2a 2a 20 64 75 72 69 6e 67 20 6f  ly.  ** during o
1700: 70 65 72 61 74 69 6f 6e 2e 20 20 49 74 20 69 73  peration.  It is
1710: 20 6f 6e 6c 79 20 6d 6f 64 69 66 69 65 64 20 61   only modified a
1720: 74 20 73 74 61 72 74 2d 74 69 6d 65 20 61 6e 64  t start-time and
1730: 20 74 68 75 73 20 64 6f 65 73 20 6e 6f 74 0a 20   thus does not. 
1740: 20 2a 2a 20 72 65 71 75 69 72 65 20 61 20 6d 75   ** require a mu
1750: 74 65 78 2e 0a 20 20 2a 2f 0a 20 20 73 71 6c 69  tex..  */.  sqli
1760: 74 65 33 5f 76 66 73 20 2a 70 4f 72 69 67 56 66  te3_vfs *pOrigVf
1770: 73 3b 0a 0a 20 20 2f 2a 20 54 68 65 20 73 54 68  s;..  /* The sTh
1780: 69 73 56 66 73 20 69 73 20 74 68 65 20 56 46 53  isVfs is the VFS
1790: 20 73 74 72 75 63 74 75 72 65 20 75 73 65 64 20   structure used 
17a0: 62 79 20 74 68 69 73 20 73 68 69 6d 2e 20 20 49  by this shim.  I
17b0: 74 20 69 73 20 69 6e 69 74 69 61 6c 69 7a 65 64  t is initialized
17c0: 0a 20 20 2a 2a 20 61 74 20 73 74 61 72 74 2d 74  .  ** at start-t
17d0: 69 6d 65 20 61 6e 64 20 74 68 75 73 20 64 6f 65  ime and thus doe
17e0: 73 20 6e 6f 74 20 72 65 71 75 69 72 65 20 61 20  s not require a 
17f0: 6d 75 74 65 78 0a 20 20 2a 2f 0a 20 20 73 71 6c  mutex.  */.  sql
1800: 69 74 65 33 5f 76 66 73 20 73 54 68 69 73 56 66  ite3_vfs sThisVf
1810: 73 3b 0a 0a 20 20 2f 2a 20 54 68 65 20 73 49 6f  s;..  /* The sIo
1820: 4d 65 74 68 6f 64 73 20 64 65 66 69 6e 65 73 20  Methods defines 
1830: 74 68 65 20 6d 65 74 68 6f 64 73 20 75 73 65 64  the methods used
1840: 20 62 79 20 73 71 6c 69 74 65 33 5f 66 69 6c 65   by sqlite3_file
1850: 20 6f 62 6a 65 63 74 73 20 0a 20 20 2a 2a 20 61   objects .  ** a
1860: 73 73 6f 63 69 61 74 65 64 20 77 69 74 68 20 74  ssociated with t
1870: 68 69 73 20 73 68 69 6d 2e 20 20 49 74 20 69 73  his shim.  It is
1880: 20 69 6e 69 74 69 61 6c 69 7a 65 64 20 61 74 20   initialized at 
1890: 73 74 61 72 74 2d 74 69 6d 65 20 61 6e 64 20 64  start-time and d
18a0: 6f 65 73 0a 20 20 2a 2a 20 6e 6f 74 20 72 65 71  oes.  ** not req
18b0: 75 69 72 65 20 61 20 6d 75 74 65 78 2e 0a 20 20  uire a mutex..  
18c0: 2a 2a 0a 20 20 2a 2a 20 57 68 65 6e 20 74 68 65  **.  ** When the
18d0: 20 75 6e 64 65 72 6c 79 69 6e 67 20 56 46 53 20   underlying VFS 
18e0: 69 73 20 63 61 6c 6c 65 64 20 74 6f 20 6f 70 65  is called to ope
18f0: 6e 20 61 20 66 69 6c 65 2c 20 69 74 20 6d 69 67  n a file, it mig
1900: 68 74 20 72 65 74 75 72 6e 20 0a 20 20 2a 2a 20  ht return .  ** 
1910: 65 69 74 68 65 72 20 61 20 76 65 72 73 69 6f 6e  either a version
1920: 20 31 20 6f 72 20 61 20 76 65 72 73 69 6f 6e 20   1 or a version 
1930: 32 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 6f  2 sqlite3_file o
1940: 62 6a 65 63 74 2e 20 20 54 68 69 73 20 73 68 69  bject.  This shi
1950: 6d 0a 20 20 2a 2a 20 68 61 73 20 74 6f 20 63 72  m.  ** has to cr
1960: 65 61 74 65 20 61 20 77 72 61 70 70 65 72 20 73  eate a wrapper s
1970: 71 6c 69 74 65 33 5f 66 69 6c 65 20 6f 66 20 74  qlite3_file of t
1980: 68 65 20 73 61 6d 65 20 76 65 72 73 69 6f 6e 2e  he same version.
1990: 20 20 48 65 6e 63 65 0a 20 20 2a 2a 20 74 68 65    Hence.  ** the
19a0: 72 65 20 61 72 65 20 74 77 6f 20 49 2f 4f 20 6d  re are two I/O m
19b0: 65 74 68 6f 64 20 73 74 72 75 63 74 75 72 65 73  ethod structures
19c0: 2c 20 6f 6e 65 20 66 6f 72 20 76 65 72 73 69 6f  , one for versio
19d0: 6e 20 31 20 61 6e 64 20 74 68 65 20 6f 74 68 65  n 1 and the othe
19e0: 72 0a 20 20 2a 2a 20 66 6f 72 20 76 65 72 73 69  r.  ** for versi
19f0: 6f 6e 20 32 2e 0a 20 20 2a 2f 0a 20 20 73 71 6c  on 2..  */.  sql
1a00: 69 74 65 33 5f 69 6f 5f 6d 65 74 68 6f 64 73 20  ite3_io_methods 
1a10: 73 49 6f 4d 65 74 68 6f 64 73 56 31 3b 0a 20 20  sIoMethodsV1;.  
1a20: 73 71 6c 69 74 65 33 5f 69 6f 5f 6d 65 74 68 6f  sqlite3_io_metho
1a30: 64 73 20 73 49 6f 4d 65 74 68 6f 64 73 56 32 3b  ds sIoMethodsV2;
1a40: 0a 0a 20 20 2f 2a 20 54 72 75 65 20 77 68 65 6e  ..  /* True when
1a50: 20 74 68 69 73 20 73 68 69 6d 20 68 61 73 20 62   this shim has b
1a60: 65 65 6e 20 69 6e 69 74 69 61 6c 69 7a 65 64 2e  een initialized.
1a70: 0a 20 20 2a 2f 0a 20 20 69 6e 74 20 69 73 49 6e  .  */.  int isIn
1a80: 69 74 69 61 6c 69 7a 65 64 3b 0a 0a 20 20 2f 2a  itialized;..  /*
1a90: 20 46 6f 72 20 72 75 6e 2d 74 69 6d 65 20 61 63   For run-time ac
1aa0: 63 65 73 73 20 61 6e 79 20 6f 66 20 74 68 65 20  cess any of the 
1ab0: 6f 74 68 65 72 20 67 6c 6f 62 61 6c 20 64 61 74  other global dat
1ac0: 61 20 73 74 72 75 63 74 75 72 65 73 20 69 6e 20  a structures in 
1ad0: 74 68 69 73 0a 20 20 2a 2a 20 73 68 69 6d 2c 20  this.  ** shim, 
1ae0: 74 68 65 20 66 6f 6c 6c 6f 77 69 6e 67 20 6d 75  the following mu
1af0: 74 65 78 20 6d 75 73 74 20 62 65 20 68 65 6c 64  tex must be held
1b00: 2e 0a 20 20 2a 2f 0a 20 20 73 71 6c 69 74 65 33  ..  */.  sqlite3
1b10: 5f 6d 75 74 65 78 20 2a 70 4d 75 74 65 78 3b 0a  _mutex *pMutex;.
1b20: 0a 20 20 2f 2a 20 4c 69 73 74 20 6f 66 20 6d 75  .  /* List of mu
1b30: 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 6f 62 6a  ltiplexGroup obj
1b40: 65 63 74 73 2e 0a 20 20 2a 2f 0a 20 20 6d 75 6c  ects..  */.  mul
1b50: 74 69 70 6c 65 78 47 72 6f 75 70 20 2a 70 47 72  tiplexGroup *pGr
1b60: 6f 75 70 73 3b 0a 7d 20 67 4d 75 6c 74 69 70 6c  oups;.} gMultipl
1b70: 65 78 3b 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ex;../**********
1b80: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20  *************** 
1b90: 55 74 69 6c 69 74 79 20 52 6f 75 74 69 6e 65 73  Utility Routines
1ba0: 20 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a   ***************
1bb0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1bc0: 2a 2a 2f 0a 2f 2a 0a 2a 2a 20 41 63 71 75 69 72  **/./*.** Acquir
1bd0: 65 20 61 6e 64 20 72 65 6c 65 61 73 65 20 74 68  e and release th
1be0: 65 20 6d 75 74 65 78 20 75 73 65 64 20 74 6f 20  e mutex used to 
1bf0: 73 65 72 69 61 6c 69 7a 65 20 61 63 63 65 73 73  serialize access
1c00: 20 74 6f 20 74 68 65 0a 2a 2a 20 6c 69 73 74 20   to the.** list 
1c10: 6f 66 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75  of multiplexGrou
1c20: 70 73 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 76 6f  ps..*/.static vo
1c30: 69 64 20 6d 75 6c 74 69 70 6c 65 78 45 6e 74 65  id multiplexEnte
1c40: 72 28 76 6f 69 64 29 7b 20 73 71 6c 69 74 65 33  r(void){ sqlite3
1c50: 5f 6d 75 74 65 78 5f 65 6e 74 65 72 28 67 4d 75  _mutex_enter(gMu
1c60: 6c 74 69 70 6c 65 78 2e 70 4d 75 74 65 78 29 3b  ltiplex.pMutex);
1c70: 20 7d 0a 73 74 61 74 69 63 20 76 6f 69 64 20 6d   }.static void m
1c80: 75 6c 74 69 70 6c 65 78 4c 65 61 76 65 28 76 6f  ultiplexLeave(vo
1c90: 69 64 29 7b 20 73 71 6c 69 74 65 33 5f 6d 75 74  id){ sqlite3_mut
1ca0: 65 78 5f 6c 65 61 76 65 28 67 4d 75 6c 74 69 70  ex_leave(gMultip
1cb0: 6c 65 78 2e 70 4d 75 74 65 78 29 3b 20 7d 0a 0a  lex.pMutex); }..
1cc0: 2f 2a 0a 2a 2a 20 43 6f 6d 70 75 74 65 20 61 20  /*.** Compute a 
1cd0: 73 74 72 69 6e 67 20 6c 65 6e 67 74 68 20 74 68  string length th
1ce0: 61 74 20 69 73 20 6c 69 6d 69 74 65 64 20 74 6f  at is limited to
1cf0: 20 77 68 61 74 20 63 61 6e 20 62 65 20 73 74 6f   what can be sto
1d00: 72 65 64 20 69 6e 0a 2a 2a 20 6c 6f 77 65 72 20  red in.** lower 
1d10: 33 30 20 62 69 74 73 20 6f 66 20 61 20 33 32 2d  30 bits of a 32-
1d20: 62 69 74 20 73 69 67 6e 65 64 20 69 6e 74 65 67  bit signed integ
1d30: 65 72 2e 0a 2a 2a 0a 2a 2a 20 54 68 65 20 76 61  er..**.** The va
1d40: 6c 75 65 20 72 65 74 75 72 6e 65 64 20 77 69 6c  lue returned wil
1d50: 6c 20 6e 65 76 65 72 20 62 65 20 6e 65 67 61 74  l never be negat
1d60: 69 76 65 2e 20 20 4e 6f 72 20 77 69 6c 6c 20 69  ive.  Nor will i
1d70: 74 20 65 76 65 72 20 62 65 20 67 72 65 61 74 65  t ever be greate
1d80: 72 0a 2a 2a 20 74 68 61 6e 20 74 68 65 20 61 63  r.** than the ac
1d90: 74 75 61 6c 20 6c 65 6e 67 74 68 20 6f 66 20 74  tual length of t
1da0: 68 65 20 73 74 72 69 6e 67 2e 20 20 46 6f 72 20  he string.  For 
1db0: 76 65 72 79 20 6c 6f 6e 67 20 73 74 72 69 6e 67  very long string
1dc0: 73 20 28 67 72 65 61 74 65 72 0a 2a 2a 20 74 68  s (greater.** th
1dd0: 61 6e 20 31 47 69 42 29 20 74 68 65 20 76 61 6c  an 1GiB) the val
1de0: 75 65 20 72 65 74 75 72 6e 65 64 20 6d 69 67 68  ue returned migh
1df0: 74 20 62 65 20 6c 65 73 73 20 74 68 61 6e 20 74  t be less than t
1e00: 68 65 20 74 72 75 65 20 73 74 72 69 6e 67 20 6c  he true string l
1e10: 65 6e 67 74 68 2e 0a 2a 2f 0a 73 74 61 74 69 63  ength..*/.static
1e20: 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 53 74   int multiplexSt
1e30: 72 6c 65 6e 33 30 28 63 6f 6e 73 74 20 63 68 61  rlen30(const cha
1e40: 72 20 2a 7a 29 7b 0a 20 20 63 6f 6e 73 74 20 63  r *z){.  const c
1e50: 68 61 72 20 2a 7a 32 20 3d 20 7a 3b 0a 20 20 69  har *z2 = z;.  i
1e60: 66 28 20 7a 3d 3d 30 20 29 20 72 65 74 75 72 6e  f( z==0 ) return
1e70: 20 30 3b 0a 20 20 77 68 69 6c 65 28 20 2a 7a 32   0;.  while( *z2
1e80: 20 29 7b 20 7a 32 2b 2b 3b 20 7d 0a 20 20 72 65   ){ z2++; }.  re
1e90: 74 75 72 6e 20 30 78 33 66 66 66 66 66 66 66 20  turn 0x3fffffff 
1ea0: 26 20 28 69 6e 74 29 28 7a 32 20 2d 20 7a 29 3b  & (int)(z2 - z);
1eb0: 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 43 72 65 61 74 65  .}../*.** Create
1ec0: 20 61 20 74 65 6d 70 6f 72 61 72 79 20 66 69 6c   a temporary fil
1ed0: 65 20 6e 61 6d 65 20 69 6e 20 7a 42 75 66 2e 20  e name in zBuf. 
1ee0: 20 7a 42 75 66 20 6d 75 73 74 20 62 65 20 62 69   zBuf must be bi
1ef0: 67 20 65 6e 6f 75 67 68 20 74 6f 0a 2a 2a 20 68  g enough to.** h
1f00: 6f 6c 64 20 61 74 20 70 4f 72 69 67 56 66 73 2d  old at pOrigVfs-
1f10: 3e 6d 78 50 61 74 68 6e 61 6d 65 20 63 68 61 72  >mxPathname char
1f20: 61 63 74 65 72 73 2e 20 20 54 68 69 73 20 66 75  acters.  This fu
1f30: 6e 63 74 69 6f 6e 20 64 65 70 61 72 74 73 0a 2a  nction departs.*
1f40: 2a 20 66 72 6f 6d 20 74 68 65 20 74 72 61 64 69  * from the tradi
1f50: 74 69 6f 6e 61 6c 20 74 65 6d 70 6f 72 61 72 79  tional temporary
1f60: 20 6e 61 6d 65 20 67 65 6e 65 72 61 74 69 6f 6e   name generation
1f70: 20 69 6e 20 74 68 65 20 6f 73 5f 77 69 6e 0a 2a   in the os_win.*
1f80: 2a 20 61 6e 64 20 6f 73 5f 75 6e 69 78 20 56 46  * and os_unix VF
1f90: 53 20 69 6e 20 73 65 76 65 72 61 6c 20 77 61 79  S in several way
1fa0: 73 2c 20 62 75 74 20 69 73 20 6e 65 63 65 73 73  s, but is necess
1fb0: 61 72 79 20 73 6f 20 74 68 61 74 20 0a 2a 2a 20  ary so that .** 
1fc0: 74 68 65 20 66 69 6c 65 20 6e 61 6d 65 20 69 73  the file name is
1fd0: 20 6b 6e 6f 77 6e 20 66 6f 72 20 74 65 6d 70 6f   known for tempo
1fe0: 72 61 72 79 20 66 69 6c 65 73 20 28 6c 69 6b 65  rary files (like
1ff0: 20 74 68 6f 73 65 20 75 73 65 64 20 0a 2a 2a 20   those used .** 
2000: 64 75 72 69 6e 67 20 76 61 63 75 75 6d 2e 29 0a  during vacuum.).
2010: 2a 2a 0a 2a 2a 20 4e 2e 42 2e 20 54 68 69 73 20  **.** N.B. This 
2020: 72 6f 75 74 69 6e 65 20 61 73 73 75 6d 65 73 20  routine assumes 
2030: 79 6f 75 72 20 75 6e 64 65 72 6c 79 69 6e 67 20  your underlying 
2040: 56 46 53 20 69 73 20 6f 6b 20 77 69 74 68 20 75  VFS is ok with u
2050: 73 69 6e 67 0a 2a 2a 20 22 2f 22 20 61 73 20 61  sing.** "/" as a
2060: 20 64 69 72 65 63 74 6f 72 79 20 73 65 70 65 72   directory seper
2070: 61 74 6f 72 2e 20 20 54 68 69 73 20 69 73 20 74  ator.  This is t
2080: 68 65 20 64 65 66 61 75 6c 74 20 66 6f 72 20 55  he default for U
2090: 4e 49 58 73 0a 2a 2a 20 61 6e 64 20 69 73 20 61  NIXs.** and is a
20a0: 6c 6c 6f 77 65 64 20 28 65 76 65 6e 20 6d 69 78  llowed (even mix
20b0: 65 64 29 20 66 6f 72 20 6d 6f 73 74 20 76 65 72  ed) for most ver
20c0: 73 69 6f 6e 73 20 6f 66 20 57 69 6e 64 6f 77 73  sions of Windows
20d0: 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20  ..*/.static int 
20e0: 6d 75 6c 74 69 70 6c 65 78 47 65 74 54 65 6d 70  multiplexGetTemp
20f0: 6e 61 6d 65 28 73 71 6c 69 74 65 33 5f 76 66 73  name(sqlite3_vfs
2100: 20 2a 70 4f 72 69 67 56 66 73 2c 20 69 6e 74 20   *pOrigVfs, int 
2110: 6e 42 75 66 2c 20 63 68 61 72 20 2a 7a 42 75 66  nBuf, char *zBuf
2120: 29 7b 0a 20 20 73 74 61 74 69 63 20 63 68 61 72  ){.  static char
2130: 20 7a 43 68 61 72 73 5b 5d 20 3d 0a 20 20 20 20   zChars[] =.    
2140: 22 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f  "abcdefghijklmno
2150: 70 71 72 73 74 75 76 77 78 79 7a 22 0a 20 20 20  pqrstuvwxyz".   
2160: 20 22 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e   "ABCDEFGHIJKLMN
2170: 4f 50 51 52 53 54 55 56 57 58 59 5a 22 0a 20 20  OPQRSTUVWXYZ".  
2180: 20 20 22 30 31 32 33 34 35 36 37 38 39 22 3b 0a    "0123456789";.
2190: 20 20 69 6e 74 20 69 2c 6a 3b 0a 20 20 69 6e 74    int i,j;.  int
21a0: 20 61 74 74 65 6d 70 74 73 20 3d 20 30 3b 0a 20   attempts = 0;. 
21b0: 20 69 6e 74 20 65 78 69 73 74 73 20 3d 20 30 3b   int exists = 0;
21c0: 0a 20 20 69 6e 74 20 72 63 20 3d 20 53 51 4c 49  .  int rc = SQLI
21d0: 54 45 5f 45 52 52 4f 52 3b 0a 0a 20 20 2f 2a 20  TE_ERROR;..  /* 
21e0: 43 68 65 63 6b 20 74 68 61 74 20 74 68 65 20 6f  Check that the o
21f0: 75 74 70 75 74 20 62 75 66 66 65 72 20 69 73 20  utput buffer is 
2200: 6c 61 72 67 65 20 65 6e 6f 75 67 68 20 66 6f 72  large enough for
2210: 20 0a 20 20 2a 2a 20 70 56 66 73 2d 3e 6d 78 50   .  ** pVfs->mxP
2220: 61 74 68 6e 61 6d 65 20 63 68 61 72 61 63 74 65  athname characte
2230: 72 73 2e 0a 20 20 2a 2f 0a 20 20 69 66 28 20 70  rs..  */.  if( p
2240: 4f 72 69 67 56 66 73 2d 3e 6d 78 50 61 74 68 6e  OrigVfs->mxPathn
2250: 61 6d 65 20 3c 3d 20 6e 42 75 66 20 29 7b 0a 20  ame <= nBuf ){. 
2260: 20 20 20 63 68 61 72 20 2a 7a 54 6d 70 20 3d 20     char *zTmp = 
2270: 73 71 6c 69 74 65 33 5f 6d 61 6c 6c 6f 63 28 70  sqlite3_malloc(p
2280: 4f 72 69 67 56 66 73 2d 3e 6d 78 50 61 74 68 6e  OrigVfs->mxPathn
2290: 61 6d 65 29 3b 0a 20 20 20 20 69 66 28 20 7a 54  ame);.    if( zT
22a0: 6d 70 3d 3d 30 20 29 20 72 65 74 75 72 6e 20 53  mp==0 ) return S
22b0: 51 4c 49 54 45 5f 4e 4f 4d 45 4d 3b 0a 0a 20 20  QLITE_NOMEM;..  
22c0: 20 20 2f 2a 20 73 71 6c 69 74 65 33 5f 74 65 6d    /* sqlite3_tem
22d0: 70 5f 64 69 72 65 63 74 6f 72 79 20 73 68 6f 75  p_directory shou
22e0: 6c 64 20 61 6c 77 61 79 73 20 62 65 20 6c 65 73  ld always be les
22f0: 73 20 74 68 61 6e 0a 20 20 20 20 2a 2a 20 70 56  s than.    ** pV
2300: 66 73 2d 3e 6d 78 50 61 74 68 6e 61 6d 65 20 63  fs->mxPathname c
2310: 68 61 72 61 63 74 65 72 73 2e 0a 20 20 20 20 2a  haracters..    *
2320: 2f 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 73 6e  /.    sqlite3_sn
2330: 70 72 69 6e 74 66 28 70 4f 72 69 67 56 66 73 2d  printf(pOrigVfs-
2340: 3e 6d 78 50 61 74 68 6e 61 6d 65 2c 0a 20 20 20  >mxPathname,.   
2350: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2360: 20 20 7a 54 6d 70 2c 0a 20 20 20 20 20 20 20 20    zTmp,.        
2370: 20 20 20 20 20 20 20 20 20 20 20 20 20 22 25 73               "%s
2380: 2f 22 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20  /",.            
2390: 20 20 20 20 20 20 20 20 20 73 71 6c 69 74 65 33           sqlite3
23a0: 5f 74 65 6d 70 5f 64 69 72 65 63 74 6f 72 79 20  _temp_directory 
23b0: 3f 20 73 71 6c 69 74 65 33 5f 74 65 6d 70 5f 64  ? sqlite3_temp_d
23c0: 69 72 65 63 74 6f 72 79 20 3a 20 22 2e 22 29 3b  irectory : ".");
23d0: 0a 20 20 20 20 72 63 20 3d 20 70 4f 72 69 67 56  .    rc = pOrigV
23e0: 66 73 2d 3e 78 46 75 6c 6c 50 61 74 68 6e 61 6d  fs->xFullPathnam
23f0: 65 28 70 4f 72 69 67 56 66 73 2c 20 7a 54 6d 70  e(pOrigVfs, zTmp
2400: 2c 20 6e 42 75 66 2c 20 7a 42 75 66 29 3b 0a 20  , nBuf, zBuf);. 
2410: 20 20 20 73 71 6c 69 74 65 33 5f 66 72 65 65 28     sqlite3_free(
2420: 7a 54 6d 70 29 3b 0a 20 20 20 20 69 66 28 20 72  zTmp);.    if( r
2430: 63 20 29 20 72 65 74 75 72 6e 20 72 63 3b 0a 0a  c ) return rc;..
2440: 20 20 20 20 2f 2a 20 43 68 65 63 6b 20 74 68 61      /* Check tha
2450: 74 20 74 68 65 20 6f 75 74 70 75 74 20 62 75 66  t the output buf
2460: 66 65 72 20 69 73 20 6c 61 72 67 65 20 65 6e 6f  fer is large eno
2470: 75 67 68 20 66 6f 72 20 74 68 65 20 74 65 6d 70  ugh for the temp
2480: 6f 72 61 72 79 20 66 69 6c 65 20 0a 20 20 20 20  orary file .    
2490: 2a 2a 20 6e 61 6d 65 2e 0a 20 20 20 20 2a 2f 0a  ** name..    */.
24a0: 20 20 20 20 6a 20 3d 20 6d 75 6c 74 69 70 6c 65      j = multiple
24b0: 78 53 74 72 6c 65 6e 33 30 28 7a 42 75 66 29 3b  xStrlen30(zBuf);
24c0: 0a 20 20 20 20 69 66 28 20 28 6a 20 2b 20 38 20  .    if( (j + 8 
24d0: 2b 20 31 20 2b 20 33 20 2b 20 31 29 20 3c 3d 20  + 1 + 3 + 1) <= 
24e0: 6e 42 75 66 20 29 7b 0a 20 20 20 20 20 20 2f 2a  nBuf ){.      /*
24f0: 20 4d 61 6b 65 20 33 20 61 74 74 65 6d 70 74 73   Make 3 attempts
2500: 20 74 6f 20 67 65 6e 65 72 61 74 65 20 61 20 75   to generate a u
2510: 6e 69 71 75 65 20 6e 61 6d 65 2e 20 2a 2f 0a 20  nique name. */. 
2520: 20 20 20 20 20 64 6f 20 7b 0a 20 20 20 20 20 20       do {.      
2530: 20 20 61 74 74 65 6d 70 74 73 2b 2b 3b 0a 20 20    attempts++;.  
2540: 20 20 20 20 20 20 73 71 6c 69 74 65 33 5f 72 61        sqlite3_ra
2550: 6e 64 6f 6d 6e 65 73 73 28 38 2c 20 26 7a 42 75  ndomness(8, &zBu
2560: 66 5b 6a 5d 29 3b 0a 20 20 20 20 20 20 20 20 66  f[j]);.        f
2570: 6f 72 28 69 3d 30 3b 20 69 3c 38 3b 20 69 2b 2b  or(i=0; i<8; i++
2580: 29 7b 0a 20 20 20 20 20 20 20 20 20 20 75 6e 73  ){.          uns
2590: 69 67 6e 65 64 20 63 68 61 72 20 75 63 20 3d 20  igned char uc = 
25a0: 28 75 6e 73 69 67 6e 65 64 20 63 68 61 72 29 7a  (unsigned char)z
25b0: 42 75 66 5b 6a 2b 69 5d 3b 0a 20 20 20 20 20 20  Buf[j+i];.      
25c0: 20 20 20 20 7a 42 75 66 5b 6a 2b 69 5d 20 3d 20      zBuf[j+i] = 
25d0: 28 63 68 61 72 29 7a 43 68 61 72 73 5b 75 63 25  (char)zChars[uc%
25e0: 28 73 69 7a 65 6f 66 28 7a 43 68 61 72 73 29 2d  (sizeof(zChars)-
25f0: 31 29 5d 3b 0a 20 20 20 20 20 20 20 20 7d 0a 20  1)];.        }. 
2600: 20 20 20 20 20 20 20 6d 65 6d 63 70 79 28 26 7a         memcpy(&z
2610: 42 75 66 5b 6a 2b 69 5d 2c 20 22 2e 74 6d 70 22  Buf[j+i], ".tmp"
2620: 2c 20 35 29 3b 0a 20 20 20 20 20 20 20 20 72 63  , 5);.        rc
2630: 20 3d 20 70 4f 72 69 67 56 66 73 2d 3e 78 41 63   = pOrigVfs->xAc
2640: 63 65 73 73 28 70 4f 72 69 67 56 66 73 2c 20 7a  cess(pOrigVfs, z
2650: 42 75 66 2c 20 53 51 4c 49 54 45 5f 41 43 43 45  Buf, SQLITE_ACCE
2660: 53 53 5f 45 58 49 53 54 53 2c 20 26 65 78 69 73  SS_EXISTS, &exis
2670: 74 73 29 3b 0a 20 20 20 20 20 20 7d 20 77 68 69  ts);.      } whi
2680: 6c 65 20 28 20 28 72 63 3d 3d 53 51 4c 49 54 45  le ( (rc==SQLITE
2690: 5f 4f 4b 29 20 26 26 20 65 78 69 73 74 73 20 26  _OK) && exists &
26a0: 26 20 28 61 74 74 65 6d 70 74 73 3c 33 29 20 29  & (attempts<3) )
26b0: 3b 0a 20 20 20 20 20 20 69 66 28 20 72 63 3d 3d  ;.      if( rc==
26c0: 53 51 4c 49 54 45 5f 4f 4b 20 26 26 20 65 78 69  SQLITE_OK && exi
26d0: 73 74 73 20 29 7b 0a 20 20 20 20 20 20 20 20 72  sts ){.        r
26e0: 63 20 3d 20 53 51 4c 49 54 45 5f 45 52 52 4f 52  c = SQLITE_ERROR
26f0: 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a  ;.      }.    }.
2700: 20 20 7d 0a 0a 20 20 72 65 74 75 72 6e 20 72 63    }..  return rc
2710: 3b 0a 7d 0a 0a 2f 2a 20 43 6f 6d 70 75 74 65 20  ;.}../* Compute 
2720: 74 68 65 20 66 69 6c 65 6e 61 6d 65 20 66 6f 72  the filename for
2730: 20 74 68 65 20 69 43 68 75 6e 6b 2d 74 68 20 63   the iChunk-th c
2740: 68 75 6e 6b 0a 2a 2f 0a 73 74 61 74 69 63 20 69  hunk.*/.static i
2750: 6e 74 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 46  nt multiplexSubF
2760: 69 6c 65 6e 61 6d 65 28 6d 75 6c 74 69 70 6c 65  ilename(multiple
2770: 78 47 72 6f 75 70 20 2a 70 47 72 6f 75 70 2c 20  xGroup *pGroup, 
2780: 69 6e 74 20 69 43 68 75 6e 6b 29 7b 0a 20 20 69  int iChunk){.  i
2790: 66 28 20 69 43 68 75 6e 6b 3e 3d 70 47 72 6f 75  f( iChunk>=pGrou
27a0: 70 2d 3e 6e 52 65 61 6c 20 29 7b 0a 20 20 20 20  p->nReal ){.    
27b0: 73 74 72 75 63 74 20 6d 75 6c 74 69 70 6c 65 78  struct multiplex
27c0: 52 65 61 6c 20 2a 70 3b 0a 20 20 20 20 70 20 3d  Real *p;.    p =
27d0: 20 73 71 6c 69 74 65 33 5f 72 65 61 6c 6c 6f 63   sqlite3_realloc
27e0: 28 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c 2c 20  (pGroup->aReal, 
27f0: 28 69 43 68 75 6e 6b 2b 31 29 2a 73 69 7a 65 6f  (iChunk+1)*sizeo
2800: 66 28 2a 70 29 29 3b 0a 20 20 20 20 69 66 28 20  f(*p));.    if( 
2810: 70 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 72 65  p==0 ){.      re
2820: 74 75 72 6e 20 53 51 4c 49 54 45 5f 4e 4f 4d 45  turn SQLITE_NOME
2830: 4d 3b 0a 20 20 20 20 7d 0a 20 20 20 20 6d 65 6d  M;.    }.    mem
2840: 73 65 74 28 26 70 5b 70 47 72 6f 75 70 2d 3e 6e  set(&p[pGroup->n
2850: 52 65 61 6c 5d 2c 20 30 2c 20 73 69 7a 65 6f 66  Real], 0, sizeof
2860: 28 70 5b 30 5d 29 2a 28 69 43 68 75 6e 6b 2b 31  (p[0])*(iChunk+1
2870: 2d 70 47 72 6f 75 70 2d 3e 6e 52 65 61 6c 29 29  -pGroup->nReal))
2880: 3b 0a 20 20 20 20 70 47 72 6f 75 70 2d 3e 61 52  ;.    pGroup->aR
2890: 65 61 6c 20 3d 20 70 3b 0a 20 20 20 20 70 47 72  eal = p;.    pGr
28a0: 6f 75 70 2d 3e 6e 52 65 61 6c 20 3d 20 69 43 68  oup->nReal = iCh
28b0: 75 6e 6b 2b 31 3b 0a 20 20 7d 0a 20 20 69 66 28  unk+1;.  }.  if(
28c0: 20 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69   pGroup->aReal[i
28d0: 43 68 75 6e 6b 5d 2e 7a 3d 3d 30 20 29 7b 0a 20  Chunk].z==0 ){. 
28e0: 20 20 20 63 68 61 72 20 2a 7a 3b 0a 20 20 20 20     char *z;.    
28f0: 69 6e 74 20 6e 20 3d 20 70 47 72 6f 75 70 2d 3e  int n = pGroup->
2900: 6e 4e 61 6d 65 3b 0a 20 20 20 20 70 47 72 6f 75  nName;.    pGrou
2910: 70 2d 3e 61 52 65 61 6c 5b 69 43 68 75 6e 6b 5d  p->aReal[iChunk]
2920: 2e 7a 20 3d 20 7a 20 3d 20 73 71 6c 69 74 65 33  .z = z = sqlite3
2930: 5f 6d 61 6c 6c 6f 63 28 20 6e 2b 34 20 29 3b 0a  _malloc( n+4 );.
2940: 20 20 20 20 69 66 28 20 7a 3d 3d 30 20 29 7b 0a      if( z==0 ){.
2950: 20 20 20 20 20 20 72 65 74 75 72 6e 20 53 51 4c        return SQL
2960: 49 54 45 5f 4e 4f 4d 45 4d 3b 0a 20 20 20 20 7d  ITE_NOMEM;.    }
2970: 0a 20 20 20 20 6d 65 6d 63 70 79 28 7a 2c 20 70  .    memcpy(z, p
2980: 47 72 6f 75 70 2d 3e 7a 4e 61 6d 65 2c 20 6e 2b  Group->zName, n+
2990: 31 29 3b 0a 20 20 20 20 69 66 28 20 69 43 68 75  1);.    if( iChu
29a0: 6e 6b 3e 30 20 29 7b 0a 23 69 66 64 65 66 20 53  nk>0 ){.#ifdef S
29b0: 51 4c 49 54 45 5f 45 4e 41 42 4c 45 5f 38 5f 33  QLITE_ENABLE_8_3
29c0: 5f 4e 41 4d 45 53 0a 20 20 20 20 20 20 69 6e 74  _NAMES.      int
29d0: 20 69 3b 0a 20 20 20 20 20 20 66 6f 72 28 69 3d   i;.      for(i=
29e0: 6e 2d 31 3b 20 69 3e 30 20 26 26 20 69 3e 3d 6e  n-1; i>0 && i>=n
29f0: 2d 34 20 26 26 20 7a 5b 69 5d 21 3d 27 2e 27 3b  -4 && z[i]!='.';
2a00: 20 69 2d 2d 29 7b 7d 0a 20 20 20 20 20 20 69 66   i--){}.      if
2a10: 28 20 69 3e 3d 6e 2d 34 20 29 20 6e 20 3d 20 69  ( i>=n-4 ) n = i
2a20: 2b 31 3b 0a 23 65 6e 64 69 66 0a 20 20 20 20 20  +1;.#endif.     
2a30: 20 73 71 6c 69 74 65 33 5f 73 6e 70 72 69 6e 74   sqlite3_snprint
2a40: 66 28 34 2c 26 7a 5b 6e 5d 2c 22 25 30 33 64 22  f(4,&z[n],"%03d"
2a50: 2c 69 43 68 75 6e 6b 29 3b 0a 20 20 20 20 7d 0a  ,iChunk);.    }.
2a60: 20 20 7d 0a 20 20 72 65 74 75 72 6e 20 53 51 4c    }.  return SQL
2a70: 49 54 45 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a 20 54 72  ITE_OK;.}../* Tr
2a80: 61 6e 73 6c 61 74 65 20 61 6e 20 73 71 6c 69 74  anslate an sqlit
2a90: 65 33 5f 66 69 6c 65 2a 20 74 68 61 74 20 69 73  e3_file* that is
2aa0: 20 72 65 61 6c 6c 79 20 61 20 6d 75 6c 74 69 70   really a multip
2ab0: 6c 65 78 47 72 6f 75 70 2a 20 69 6e 74 6f 0a 2a  lexGroup* into.*
2ac0: 2a 20 74 68 65 20 73 71 6c 69 74 65 33 5f 66 69  * the sqlite3_fi
2ad0: 6c 65 2a 20 66 6f 72 20 74 68 65 20 75 6e 64 65  le* for the unde
2ae0: 72 6c 79 69 6e 67 20 6f 72 69 67 69 6e 61 6c 20  rlying original 
2af0: 56 46 53 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 73  VFS..*/.static s
2b00: 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 6d 75 6c  qlite3_file *mul
2b10: 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28 0a 20  tiplexSubOpen(. 
2b20: 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 20   multiplexGroup 
2b30: 2a 70 47 72 6f 75 70 2c 0a 20 20 69 6e 74 20 69  *pGroup,.  int i
2b40: 43 68 75 6e 6b 2c 0a 20 20 69 6e 74 20 2a 72 63  Chunk,.  int *rc
2b50: 2c 0a 20 20 69 6e 74 20 2a 70 4f 75 74 46 6c 61  ,.  int *pOutFla
2b60: 67 73 0a 29 7b 0a 20 20 73 71 6c 69 74 65 33 5f  gs.){.  sqlite3_
2b70: 66 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d  file *pSubOpen =
2b80: 20 30 3b 0a 20 20 73 71 6c 69 74 65 33 5f 76 66   0;.  sqlite3_vf
2b90: 73 20 2a 70 4f 72 69 67 56 66 73 20 3d 20 67 4d  s *pOrigVfs = gM
2ba0: 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66  ultiplex.pOrigVf
2bb0: 73 3b 20 20 20 20 20 20 20 20 2f 2a 20 52 65 61  s;        /* Rea
2bc0: 6c 20 56 46 53 20 2a 2f 0a 20 20 2a 72 63 20 3d  l VFS */.  *rc =
2bd0: 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 46 69 6c   multiplexSubFil
2be0: 65 6e 61 6d 65 28 70 47 72 6f 75 70 2c 20 69 43  ename(pGroup, iC
2bf0: 68 75 6e 6b 29 3b 0a 20 20 69 66 28 20 28 2a 72  hunk);.  if( (*r
2c00: 63 29 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 26 26  c)==SQLITE_OK &&
2c10: 20 28 70 53 75 62 4f 70 65 6e 20 3d 20 70 47 72   (pSubOpen = pGr
2c20: 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68 75 6e  oup->aReal[iChun
2c30: 6b 5d 2e 70 29 3d 3d 30 20 29 7b 0a 20 20 20 20  k].p)==0 ){.    
2c40: 70 53 75 62 4f 70 65 6e 20 3d 20 73 71 6c 69 74  pSubOpen = sqlit
2c50: 65 33 5f 6d 61 6c 6c 6f 63 28 20 70 4f 72 69 67  e3_malloc( pOrig
2c60: 56 66 73 2d 3e 73 7a 4f 73 46 69 6c 65 20 29 3b  Vfs->szOsFile );
2c70: 0a 20 20 20 20 69 66 28 20 70 53 75 62 4f 70 65  .    if( pSubOpe
2c80: 6e 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 2a 72  n==0 ){.      *r
2c90: 63 20 3d 20 53 51 4c 49 54 45 5f 4e 4f 4d 45 4d  c = SQLITE_NOMEM
2ca0: 3b 0a 20 20 20 20 20 20 72 65 74 75 72 6e 20 30  ;.      return 0
2cb0: 3b 0a 20 20 20 20 7d 0a 20 20 20 20 70 47 72 6f  ;.    }.    pGro
2cc0: 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68 75 6e 6b  up->aReal[iChunk
2cd0: 5d 2e 70 20 3d 20 70 53 75 62 4f 70 65 6e 3b 0a  ].p = pSubOpen;.
2ce0: 20 20 20 20 2a 72 63 20 3d 20 70 4f 72 69 67 56      *rc = pOrigV
2cf0: 66 73 2d 3e 78 4f 70 65 6e 28 70 4f 72 69 67 56  fs->xOpen(pOrigV
2d00: 66 73 2c 20 70 47 72 6f 75 70 2d 3e 61 52 65 61  fs, pGroup->aRea
2d10: 6c 5b 69 43 68 75 6e 6b 5d 2e 7a 2c 20 70 53 75  l[iChunk].z, pSu
2d20: 62 4f 70 65 6e 2c 0a 20 20 20 20 20 20 20 20 20  bOpen,.         
2d30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2d40: 20 70 47 72 6f 75 70 2d 3e 66 6c 61 67 73 2c 20   pGroup->flags, 
2d50: 70 4f 75 74 46 6c 61 67 73 29 3b 0a 20 20 20 20  pOutFlags);.    
2d60: 69 66 28 20 2a 72 63 21 3d 53 51 4c 49 54 45 5f  if( *rc!=SQLITE_
2d70: 4f 4b 20 29 7b 0a 20 20 20 20 20 20 73 71 6c 69  OK ){.      sqli
2d80: 74 65 33 5f 66 72 65 65 28 70 53 75 62 4f 70 65  te3_free(pSubOpe
2d90: 6e 29 3b 0a 20 20 20 20 20 20 70 47 72 6f 75 70  n);.      pGroup
2da0: 2d 3e 61 52 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e  ->aReal[iChunk].
2db0: 70 20 3d 20 30 3b 0a 20 20 20 20 20 20 72 65 74  p = 0;.      ret
2dc0: 75 72 6e 20 30 3b 0a 20 20 20 20 7d 0a 20 20 7d  urn 0;.    }.  }
2dd0: 0a 20 20 72 65 74 75 72 6e 20 70 53 75 62 4f 70  .  return pSubOp
2de0: 65 6e 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54 68 69  en;.}../*.** Thi
2df0: 73 20 69 73 20 74 68 65 20 69 6d 70 6c 65 6d 65  s is the impleme
2e00: 6e 74 61 74 69 6f 6e 20 6f 66 20 74 68 65 20 6d  ntation of the m
2e10: 75 6c 74 69 70 6c 65 78 5f 63 6f 6e 74 72 6f 6c  ultiplex_control
2e20: 28 29 20 53 51 4c 20 66 75 6e 63 74 69 6f 6e 2e  () SQL function.
2e30: 0a 2a 2f 0a 73 74 61 74 69 63 20 76 6f 69 64 20  .*/.static void 
2e40: 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 74 72 6f 6c  multiplexControl
2e50: 46 75 6e 63 28 0a 20 20 73 71 6c 69 74 65 33 5f  Func(.  sqlite3_
2e60: 63 6f 6e 74 65 78 74 20 2a 63 6f 6e 74 65 78 74  context *context
2e70: 2c 0a 20 20 69 6e 74 20 61 72 67 63 2c 0a 20 20  ,.  int argc,.  
2e80: 73 71 6c 69 74 65 33 5f 76 61 6c 75 65 20 2a 2a  sqlite3_value **
2e90: 61 72 67 76 0a 29 7b 0a 20 20 69 6e 74 20 72 63  argv.){.  int rc
2ea0: 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20   = SQLITE_OK;.  
2eb0: 73 71 6c 69 74 65 33 20 2a 64 62 20 3d 20 73 71  sqlite3 *db = sq
2ec0: 6c 69 74 65 33 5f 63 6f 6e 74 65 78 74 5f 64 62  lite3_context_db
2ed0: 5f 68 61 6e 64 6c 65 28 63 6f 6e 74 65 78 74 29  _handle(context)
2ee0: 3b 0a 20 20 69 6e 74 20 6f 70 3b 0a 20 20 69 6e  ;.  int op;.  in
2ef0: 74 20 69 56 61 6c 3b 0a 0a 20 20 69 66 28 20 21  t iVal;..  if( !
2f00: 64 62 20 7c 7c 20 61 72 67 63 21 3d 32 20 29 7b  db || argc!=2 ){
2f10: 20 0a 20 20 20 20 72 63 20 3d 20 53 51 4c 49 54   .    rc = SQLIT
2f20: 45 5f 45 52 52 4f 52 3b 20 0a 20 20 7d 65 6c 73  E_ERROR; .  }els
2f30: 65 7b 0a 20 20 20 20 2f 2a 20 65 78 74 72 61 63  e{.    /* extrac
2f40: 74 20 70 61 72 61 6d 73 20 2a 2f 0a 20 20 20 20  t params */.    
2f50: 6f 70 20 3d 20 73 71 6c 69 74 65 33 5f 76 61 6c  op = sqlite3_val
2f60: 75 65 5f 69 6e 74 28 61 72 67 76 5b 30 5d 29 3b  ue_int(argv[0]);
2f70: 0a 20 20 20 20 69 56 61 6c 20 3d 20 73 71 6c 69  .    iVal = sqli
2f80: 74 65 33 5f 76 61 6c 75 65 5f 69 6e 74 28 61 72  te3_value_int(ar
2f90: 67 76 5b 31 5d 29 3b 0a 20 20 20 20 2f 2a 20 6d  gv[1]);.    /* m
2fa0: 61 70 20 66 75 6e 63 74 69 6f 6e 20 6f 70 20 74  ap function op t
2fb0: 6f 20 66 69 6c 65 5f 63 6f 6e 74 72 6f 6c 20 6f  o file_control o
2fc0: 70 20 2a 2f 0a 20 20 20 20 73 77 69 74 63 68 28  p */.    switch(
2fd0: 20 6f 70 20 29 7b 0a 20 20 20 20 20 20 63 61 73   op ){.      cas
2fe0: 65 20 31 3a 20 0a 20 20 20 20 20 20 20 20 6f 70  e 1: .        op
2ff0: 20 3d 20 4d 55 4c 54 49 50 4c 45 58 5f 43 54 52   = MULTIPLEX_CTR
3000: 4c 5f 45 4e 41 42 4c 45 3b 20 0a 20 20 20 20 20  L_ENABLE; .     
3010: 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20     break;.      
3020: 63 61 73 65 20 32 3a 20 0a 20 20 20 20 20 20 20  case 2: .       
3030: 20 6f 70 20 3d 20 4d 55 4c 54 49 50 4c 45 58 5f   op = MULTIPLEX_
3040: 43 54 52 4c 5f 53 45 54 5f 43 48 55 4e 4b 5f 53  CTRL_SET_CHUNK_S
3050: 49 5a 45 3b 20 0a 20 20 20 20 20 20 20 20 62 72  IZE; .        br
3060: 65 61 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20  eak;.      case 
3070: 33 3a 20 0a 20 20 20 20 20 20 20 20 6f 70 20 3d  3: .        op =
3080: 20 4d 55 4c 54 49 50 4c 45 58 5f 43 54 52 4c 5f   MULTIPLEX_CTRL_
3090: 53 45 54 5f 4d 41 58 5f 43 48 55 4e 4b 53 3b 20  SET_MAX_CHUNKS; 
30a0: 0a 20 20 20 20 20 20 20 20 62 72 65 61 6b 3b 0a  .        break;.
30b0: 20 20 20 20 20 20 64 65 66 61 75 6c 74 3a 0a 20        default:. 
30c0: 20 20 20 20 20 20 20 72 63 20 3d 20 53 51 4c 49         rc = SQLI
30d0: 54 45 5f 4e 4f 54 46 4f 55 4e 44 3b 0a 20 20 20  TE_NOTFOUND;.   
30e0: 20 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20       break;.    
30f0: 7d 0a 20 20 7d 0a 20 20 69 66 28 20 72 63 3d 3d  }.  }.  if( rc==
3100: 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20  SQLITE_OK ){.   
3110: 20 72 63 20 3d 20 73 71 6c 69 74 65 33 5f 66 69   rc = sqlite3_fi
3120: 6c 65 5f 63 6f 6e 74 72 6f 6c 28 64 62 2c 20 30  le_control(db, 0
3130: 2c 20 6f 70 2c 20 26 69 56 61 6c 29 3b 0a 20 20  , op, &iVal);.  
3140: 7d 0a 20 20 73 71 6c 69 74 65 33 5f 72 65 73 75  }.  sqlite3_resu
3150: 6c 74 5f 65 72 72 6f 72 5f 63 6f 64 65 28 63 6f  lt_error_code(co
3160: 6e 74 65 78 74 2c 20 72 63 29 3b 0a 7d 0a 0a 2f  ntext, rc);.}../
3170: 2a 0a 2a 2a 20 54 68 69 73 20 69 73 20 74 68 65  *.** This is the
3180: 20 65 6e 74 72 79 20 70 6f 69 6e 74 20 74 6f 20   entry point to 
3190: 72 65 67 69 73 74 65 72 20 74 68 65 20 61 75 74  register the aut
31a0: 6f 2d 65 78 74 65 6e 73 69 6f 6e 20 66 6f 72 20  o-extension for 
31b0: 74 68 65 20 0a 2a 2a 20 6d 75 6c 74 69 70 6c 65  the .** multiple
31c0: 78 5f 63 6f 6e 74 72 6f 6c 28 29 20 66 75 6e 63  x_control() func
31d0: 74 69 6f 6e 2e 0a 2a 2f 0a 73 74 61 74 69 63 20  tion..*/.static 
31e0: 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 46 75 6e  int multiplexFun
31f0: 63 49 6e 69 74 28 0a 20 20 73 71 6c 69 74 65 33  cInit(.  sqlite3
3200: 20 2a 64 62 2c 20 0a 20 20 63 68 61 72 20 2a 2a   *db, .  char **
3210: 70 7a 45 72 72 4d 73 67 2c 20 0a 20 20 63 6f 6e  pzErrMsg, .  con
3220: 73 74 20 73 71 6c 69 74 65 33 5f 61 70 69 5f 72  st sqlite3_api_r
3230: 6f 75 74 69 6e 65 73 20 2a 70 41 70 69 0a 29 7b  outines *pApi.){
3240: 0a 20 20 69 6e 74 20 72 63 3b 0a 20 20 72 63 20  .  int rc;.  rc 
3250: 3d 20 73 71 6c 69 74 65 33 5f 63 72 65 61 74 65  = sqlite3_create
3260: 5f 66 75 6e 63 74 69 6f 6e 28 64 62 2c 20 22 6d  _function(db, "m
3270: 75 6c 74 69 70 6c 65 78 5f 63 6f 6e 74 72 6f 6c  ultiplex_control
3280: 22 2c 20 32 2c 20 53 51 4c 49 54 45 5f 41 4e 59  ", 2, SQLITE_ANY
3290: 2c 20 0a 20 20 20 20 20 20 30 2c 20 6d 75 6c 74  , .      0, mult
32a0: 69 70 6c 65 78 43 6f 6e 74 72 6f 6c 46 75 6e 63  iplexControlFunc
32b0: 2c 20 30 2c 20 30 29 3b 0a 20 20 72 65 74 75 72  , 0, 0);.  retur
32c0: 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 43  n rc;.}../*.** C
32d0: 6c 6f 73 65 20 61 20 73 69 6e 67 6c 65 20 73 75  lose a single su
32e0: 62 2d 66 69 6c 65 20 69 6e 20 74 68 65 20 63 6f  b-file in the co
32f0: 6e 6e 65 63 74 69 6f 6e 20 67 72 6f 75 70 2e 0a  nnection group..
3300: 2a 2f 0a 73 74 61 74 69 63 20 76 6f 69 64 20 6d  */.static void m
3310: 75 6c 74 69 70 6c 65 78 53 75 62 43 6c 6f 73 65  ultiplexSubClose
3320: 28 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f  (.  multiplexGro
3330: 75 70 20 2a 70 47 72 6f 75 70 2c 0a 20 20 69 6e  up *pGroup,.  in
3340: 74 20 69 43 68 75 6e 6b 2c 0a 20 20 73 71 6c 69  t iChunk,.  sqli
3350: 74 65 33 5f 76 66 73 20 2a 70 4f 72 69 67 56 66  te3_vfs *pOrigVf
3360: 73 0a 29 7b 0a 20 20 73 71 6c 69 74 65 33 5f 66  s.){.  sqlite3_f
3370: 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20  ile *pSubOpen = 
3380: 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43  pGroup->aReal[iC
3390: 68 75 6e 6b 5d 2e 70 3b 0a 20 20 69 66 28 20 70  hunk].p;.  if( p
33a0: 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20 70  SubOpen ){.    p
33b0: 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64  SubOpen->pMethod
33c0: 73 2d 3e 78 43 6c 6f 73 65 28 70 53 75 62 4f 70  s->xClose(pSubOp
33d0: 65 6e 29 3b 0a 20 20 20 20 69 66 28 20 70 4f 72  en);.    if( pOr
33e0: 69 67 56 66 73 20 29 20 70 4f 72 69 67 56 66 73  igVfs ) pOrigVfs
33f0: 2d 3e 78 44 65 6c 65 74 65 28 70 4f 72 69 67 56  ->xDelete(pOrigV
3400: 66 73 2c 20 70 47 72 6f 75 70 2d 3e 61 52 65 61  fs, pGroup->aRea
3410: 6c 5b 69 43 68 75 6e 6b 5d 2e 7a 2c 20 30 29 3b  l[iChunk].z, 0);
3420: 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 66 72 65  .    sqlite3_fre
3430: 65 28 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c 5b  e(pGroup->aReal[
3440: 69 43 68 75 6e 6b 5d 2e 70 29 3b 0a 20 20 7d 0a  iChunk].p);.  }.
3450: 20 20 73 71 6c 69 74 65 33 5f 66 72 65 65 28 70    sqlite3_free(p
3460: 47 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68  Group->aReal[iCh
3470: 75 6e 6b 5d 2e 7a 29 3b 0a 20 20 6d 65 6d 73 65  unk].z);.  memse
3480: 74 28 26 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c  t(&pGroup->aReal
3490: 5b 69 43 68 75 6e 6b 5d 2c 20 30 2c 20 73 69 7a  [iChunk], 0, siz
34a0: 65 6f 66 28 70 47 72 6f 75 70 2d 3e 61 52 65 61  eof(pGroup->aRea
34b0: 6c 5b 69 43 68 75 6e 6b 5d 29 29 3b 0a 7d 0a 0a  l[iChunk]));.}..
34c0: 2f 2a 0a 2a 2a 20 44 65 61 6c 6c 6f 63 61 74 65  /*.** Deallocate
34d0: 20 6d 65 6d 6f 72 79 20 68 65 6c 64 20 62 79 20   memory held by 
34e0: 61 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70  a multiplexGroup
34f0: 0a 2a 2f 0a 73 74 61 74 69 63 20 76 6f 69 64 20  .*/.static void 
3500: 6d 75 6c 74 69 70 6c 65 78 46 72 65 65 43 6f 6d  multiplexFreeCom
3510: 70 6f 6e 65 6e 74 73 28 6d 75 6c 74 69 70 6c 65  ponents(multiple
3520: 78 47 72 6f 75 70 20 2a 70 47 72 6f 75 70 29 7b  xGroup *pGroup){
3530: 0a 20 20 69 6e 74 20 69 3b 0a 20 20 66 6f 72 28  .  int i;.  for(
3540: 69 3d 30 3b 20 69 3c 70 47 72 6f 75 70 2d 3e 6e  i=0; i<pGroup->n
3550: 52 65 61 6c 3b 20 69 2b 2b 29 7b 20 6d 75 6c 74  Real; i++){ mult
3560: 69 70 6c 65 78 53 75 62 43 6c 6f 73 65 28 70 47  iplexSubClose(pG
3570: 72 6f 75 70 2c 20 69 2c 20 30 29 3b 20 7d 0a 20  roup, i, 0); }. 
3580: 20 73 71 6c 69 74 65 33 5f 66 72 65 65 28 70 47   sqlite3_free(pG
3590: 72 6f 75 70 2d 3e 61 52 65 61 6c 29 3b 0a 20 20  roup->aReal);.  
35a0: 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c 20 3d 20  pGroup->aReal = 
35b0: 30 3b 0a 20 20 70 47 72 6f 75 70 2d 3e 6e 52 65  0;.  pGroup->nRe
35c0: 61 6c 20 3d 20 30 3b 0a 7d 0a 0a 0a 2f 2a 2a 2a  al = 0;.}.../***
35d0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
35e0: 2a 2a 2a 2a 2a 2a 20 56 46 53 20 4d 65 74 68 6f  ****** VFS Metho
35f0: 64 20 57 72 61 70 70 65 72 73 20 2a 2a 2a 2a 2a  d Wrappers *****
3600: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
3610: 2a 2a 2a 2a 2a 2a 2a 2a 2f 0a 0a 2f 2a 0a 2a 2a  ********/../*.**
3620: 20 54 68 69 73 20 69 73 20 74 68 65 20 78 4f 70   This is the xOp
3630: 65 6e 20 6d 65 74 68 6f 64 20 75 73 65 64 20 66  en method used f
3640: 6f 72 20 74 68 65 20 22 6d 75 6c 74 69 70 6c 65  or the "multiple
3650: 78 22 20 56 46 53 2e 0a 2a 2a 0a 2a 2a 20 4d 6f  x" VFS..**.** Mo
3660: 73 74 20 6f 66 20 74 68 65 20 77 6f 72 6b 20 69  st of the work i
3670: 73 20 64 6f 6e 65 20 62 79 20 74 68 65 20 75 6e  s done by the un
3680: 64 65 72 6c 79 69 6e 67 20 6f 72 69 67 69 6e 61  derlying origina
3690: 6c 20 56 46 53 2e 20 20 54 68 69 73 20 6d 65 74  l VFS.  This met
36a0: 68 6f 64 0a 2a 2a 20 73 69 6d 70 6c 79 20 6c 69  hod.** simply li
36b0: 6e 6b 73 20 74 68 65 20 6e 65 77 20 66 69 6c 65  nks the new file
36c0: 20 69 6e 74 6f 20 74 68 65 20 61 70 70 72 6f 70   into the approp
36d0: 72 69 61 74 65 20 6d 75 6c 74 69 70 6c 65 78 20  riate multiplex 
36e0: 67 72 6f 75 70 20 69 66 20 69 74 20 69 73 20 61  group if it is a
36f0: 0a 2a 2a 20 66 69 6c 65 20 74 68 61 74 20 6e 65  .** file that ne
3700: 65 64 73 20 74 6f 20 62 65 20 74 72 61 63 6b 65  eds to be tracke
3710: 64 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74  d..*/.static int
3720: 20 6d 75 6c 74 69 70 6c 65 78 4f 70 65 6e 28 0a   multiplexOpen(.
3730: 20 20 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 70    sqlite3_vfs *p
3740: 56 66 73 2c 20 20 20 20 20 20 20 20 20 2f 2a 20  Vfs,         /* 
3750: 54 68 65 20 6d 75 6c 74 69 70 6c 65 78 20 56 46  The multiplex VF
3760: 53 20 2a 2f 0a 20 20 63 6f 6e 73 74 20 63 68 61  S */.  const cha
3770: 72 20 2a 7a 4e 61 6d 65 2c 20 20 20 20 20 20 20  r *zName,       
3780: 20 20 2f 2a 20 4e 61 6d 65 20 6f 66 20 66 69 6c    /* Name of fil
3790: 65 20 74 6f 20 62 65 20 6f 70 65 6e 65 64 20 2a  e to be opened *
37a0: 2f 0a 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65  /.  sqlite3_file
37b0: 20 2a 70 43 6f 6e 6e 2c 20 20 20 20 20 20 20 2f   *pConn,       /
37c0: 2a 20 46 69 6c 6c 20 69 6e 20 74 68 69 73 20 66  * Fill in this f
37d0: 69 6c 65 20 64 65 73 63 72 69 70 74 6f 72 20 2a  ile descriptor *
37e0: 2f 0a 20 20 69 6e 74 20 66 6c 61 67 73 2c 20 20  /.  int flags,  
37f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
3800: 2a 20 46 6c 61 67 73 20 74 6f 20 63 6f 6e 74 72  * Flags to contr
3810: 6f 6c 20 74 68 65 20 6f 70 65 6e 69 6e 67 20 2a  ol the opening *
3820: 2f 0a 20 20 69 6e 74 20 2a 70 4f 75 74 46 6c 61  /.  int *pOutFla
3830: 67 73 20 20 20 20 20 20 20 20 20 20 20 20 20 2f  gs             /
3840: 2a 20 46 6c 61 67 73 20 73 68 6f 77 69 6e 67 20  * Flags showing 
3850: 72 65 73 75 6c 74 73 20 6f 66 20 6f 70 65 6e 69  results of openi
3860: 6e 67 20 2a 2f 0a 29 7b 0a 20 20 69 6e 74 20 72  ng */.){.  int r
3870: 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b 20 20  c = SQLITE_OK;  
3880: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3890: 2f 2a 20 52 65 73 75 6c 74 20 63 6f 64 65 20 2a  /* Result code *
38a0: 2f 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e  /.  multiplexCon
38b0: 6e 20 2a 70 4d 75 6c 74 69 70 6c 65 78 4f 70 65  n *pMultiplexOpe
38c0: 6e 3b 20 20 20 20 20 20 20 2f 2a 20 54 68 65 20  n;       /* The 
38d0: 6e 65 77 20 6d 75 6c 74 69 70 6c 65 78 20 66 69  new multiplex fi
38e0: 6c 65 20 64 65 73 63 72 69 70 74 6f 72 20 2a 2f  le descriptor */
38f0: 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75  .  multiplexGrou
3900: 70 20 2a 70 47 72 6f 75 70 3b 20 20 20 20 20 20  p *pGroup;      
3910: 20 20 20 20 20 20 20 20 2f 2a 20 43 6f 72 72 65          /* Corre
3920: 73 70 6f 6e 64 69 6e 67 20 6d 75 6c 74 69 70 6c  sponding multipl
3930: 65 78 47 72 6f 75 70 20 6f 62 6a 65 63 74 20 2a  exGroup object *
3940: 2f 0a 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65  /.  sqlite3_file
3950: 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20 30 3b 20   *pSubOpen = 0; 
3960: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3970: 20 20 20 2f 2a 20 52 65 61 6c 20 66 69 6c 65 20     /* Real file 
3980: 64 65 73 63 72 69 70 74 6f 72 20 2a 2f 0a 20 20  descriptor */.  
3990: 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 70 4f 72  sqlite3_vfs *pOr
39a0: 69 67 56 66 73 20 3d 20 67 4d 75 6c 74 69 70 6c  igVfs = gMultipl
39b0: 65 78 2e 70 4f 72 69 67 56 66 73 3b 20 20 20 2f  ex.pOrigVfs;   /
39c0: 2a 20 52 65 61 6c 20 56 46 53 20 2a 2f 0a 20 20  * Real VFS */.  
39d0: 69 6e 74 20 6e 4e 61 6d 65 3b 0a 20 20 69 6e 74  int nName;.  int
39e0: 20 73 7a 3b 0a 20 20 63 68 61 72 20 2a 7a 54 6f   sz;.  char *zTo
39f0: 46 72 65 65 20 3d 20 30 3b 0a 0a 20 20 55 4e 55  Free = 0;..  UNU
3a00: 53 45 44 5f 50 41 52 41 4d 45 54 45 52 28 70 56  SED_PARAMETER(pV
3a10: 66 73 29 3b 0a 20 20 6d 65 6d 73 65 74 28 70 43  fs);.  memset(pC
3a20: 6f 6e 6e 2c 20 30 2c 20 70 56 66 73 2d 3e 73 7a  onn, 0, pVfs->sz
3a30: 4f 73 46 69 6c 65 29 3b 0a 0a 20 20 2f 2a 20 57  OsFile);..  /* W
3a40: 65 20 6e 65 65 64 20 74 6f 20 63 72 65 61 74 65  e need to create
3a50: 20 61 20 67 72 6f 75 70 20 73 74 72 75 63 74 75   a group structu
3a60: 72 65 20 61 6e 64 20 6d 61 6e 61 67 65 0a 20 20  re and manage.  
3a70: 2a 2a 20 61 63 63 65 73 73 20 74 6f 20 74 68 69  ** access to thi
3a80: 73 20 67 72 6f 75 70 20 6f 66 20 66 69 6c 65 73  s group of files
3a90: 2e 0a 20 20 2a 2f 0a 20 20 6d 75 6c 74 69 70 6c  ..  */.  multipl
3aa0: 65 78 45 6e 74 65 72 28 29 3b 0a 20 20 70 4d 75  exEnter();.  pMu
3ab0: 6c 74 69 70 6c 65 78 4f 70 65 6e 20 3d 20 28 6d  ltiplexOpen = (m
3ac0: 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43  ultiplexConn*)pC
3ad0: 6f 6e 6e 3b 0a 0a 20 20 2f 2a 20 49 66 20 74 68  onn;..  /* If th
3ae0: 65 20 73 65 63 6f 6e 64 20 61 72 67 75 6d 65 6e  e second argumen
3af0: 74 20 74 6f 20 74 68 69 73 20 66 75 6e 63 74 69  t to this functi
3b00: 6f 6e 20 69 73 20 4e 55 4c 4c 2c 20 67 65 6e 65  on is NULL, gene
3b10: 72 61 74 65 20 61 20 0a 20 20 2a 2a 20 74 65 6d  rate a .  ** tem
3b20: 70 6f 72 61 72 79 20 66 69 6c 65 20 6e 61 6d 65  porary file name
3b30: 20 74 6f 20 75 73 65 2e 20 20 54 68 69 73 20 77   to use.  This w
3b40: 69 6c 6c 20 62 65 20 68 61 6e 64 6c 65 64 20 62  ill be handled b
3b50: 79 20 74 68 65 0a 20 20 2a 2a 20 6f 72 69 67 69  y the.  ** origi
3b60: 6e 61 6c 20 78 4f 70 65 6e 20 6d 65 74 68 6f 64  nal xOpen method
3b70: 2e 20 20 57 65 20 6a 75 73 74 20 6e 65 65 64 20  .  We just need 
3b80: 74 6f 20 61 6c 6c 6f 63 61 74 65 20 73 70 61 63  to allocate spac
3b90: 65 20 66 6f 72 0a 20 20 2a 2a 20 69 74 2e 0a 20  e for.  ** it.. 
3ba0: 20 2a 2f 0a 20 20 69 66 28 20 21 7a 4e 61 6d 65   */.  if( !zName
3bb0: 20 29 7b 0a 20 20 20 20 7a 4e 61 6d 65 20 3d 20   ){.    zName = 
3bc0: 7a 54 6f 46 72 65 65 20 3d 20 73 71 6c 69 74 65  zToFree = sqlite
3bd0: 33 5f 6d 61 6c 6c 6f 63 28 20 70 4f 72 69 67 56  3_malloc( pOrigV
3be0: 66 73 2d 3e 6d 78 50 61 74 68 6e 61 6d 65 20 2b  fs->mxPathname +
3bf0: 20 31 30 20 29 3b 0a 20 20 20 20 69 66 28 20 7a   10 );.    if( z
3c00: 4e 61 6d 65 3d 3d 30 20 29 7b 0a 20 20 20 20 20  Name==0 ){.     
3c10: 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4e 4f 4d   rc = SQLITE_NOM
3c20: 45 4d 3b 0a 20 20 20 20 7d 65 6c 73 65 7b 0a 20  EM;.    }else{. 
3c30: 20 20 20 20 20 72 63 20 3d 20 6d 75 6c 74 69 70       rc = multip
3c40: 6c 65 78 47 65 74 54 65 6d 70 6e 61 6d 65 28 70  lexGetTempname(p
3c50: 4f 72 69 67 56 66 73 2c 20 70 4f 72 69 67 56 66  OrigVfs, pOrigVf
3c60: 73 2d 3e 6d 78 50 61 74 68 6e 61 6d 65 2c 20 7a  s->mxPathname, z
3c70: 54 6f 46 72 65 65 29 3b 0a 20 20 20 20 7d 0a 20  ToFree);.    }. 
3c80: 20 7d 0a 0a 20 20 69 66 28 20 72 63 3d 3d 53 51   }..  if( rc==SQ
3c90: 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 2f  LITE_OK ){.    /
3ca0: 2a 20 61 6c 6c 6f 63 61 74 65 20 73 70 61 63 65  * allocate space
3cb0: 20 66 6f 72 20 67 72 6f 75 70 20 2a 2f 0a 20 20   for group */.  
3cc0: 20 20 6e 4e 61 6d 65 20 3d 20 6d 75 6c 74 69 70    nName = multip
3cd0: 6c 65 78 53 74 72 6c 65 6e 33 30 28 7a 4e 61 6d  lexStrlen30(zNam
3ce0: 65 29 3b 0a 20 20 20 20 73 7a 20 3d 20 73 69 7a  e);.    sz = siz
3cf0: 65 6f 66 28 6d 75 6c 74 69 70 6c 65 78 47 72 6f  eof(multiplexGro
3d00: 75 70 29 20 20 20 20 20 20 20 20 20 20 20 20 20  up)             
3d10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3d20: 2f 2a 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75  /* multiplexGrou
3d30: 70 20 2a 2f 0a 20 20 20 20 20 20 20 2b 20 6e 4e  p */.       + nN
3d40: 61 6d 65 20 2b 20 31 3b 20 20 20 20 20 20 20 20  ame + 1;        
3d50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3d60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3d70: 20 2f 2a 20 7a 4e 61 6d 65 20 2a 2f 0a 20 20 20   /* zName */.   
3d80: 20 70 47 72 6f 75 70 20 3d 20 73 71 6c 69 74 65   pGroup = sqlite
3d90: 33 5f 6d 61 6c 6c 6f 63 28 20 73 7a 20 29 3b 0a  3_malloc( sz );.
3da0: 20 20 20 20 69 66 28 20 70 47 72 6f 75 70 3d 3d      if( pGroup==
3db0: 30 20 29 7b 0a 20 20 20 20 20 20 72 63 20 3d 20  0 ){.      rc = 
3dc0: 53 51 4c 49 54 45 5f 4e 4f 4d 45 4d 3b 0a 20 20  SQLITE_NOMEM;.  
3dd0: 20 20 7d 0a 20 20 7d 0a 0a 20 20 69 66 28 20 72    }.  }..  if( r
3de0: 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a  c==SQLITE_OK ){.
3df0: 20 20 20 20 2f 2a 20 61 73 73 69 67 6e 20 70 6f      /* assign po
3e00: 69 6e 74 65 72 73 20 74 6f 20 65 78 74 72 61 20  inters to extra 
3e10: 73 70 61 63 65 20 61 6c 6c 6f 63 61 74 65 64 20  space allocated 
3e20: 2a 2f 0a 20 20 20 20 63 68 61 72 20 2a 70 20 3d  */.    char *p =
3e30: 20 28 63 68 61 72 20 2a 29 26 70 47 72 6f 75 70   (char *)&pGroup
3e40: 5b 31 5d 3b 0a 20 20 20 20 70 4d 75 6c 74 69 70  [1];.    pMultip
3e50: 6c 65 78 4f 70 65 6e 2d 3e 70 47 72 6f 75 70 20  lexOpen->pGroup 
3e60: 3d 20 70 47 72 6f 75 70 3b 0a 20 20 20 20 6d 65  = pGroup;.    me
3e70: 6d 73 65 74 28 70 47 72 6f 75 70 2c 20 30 2c 20  mset(pGroup, 0, 
3e80: 73 7a 29 3b 0a 20 20 20 20 70 47 72 6f 75 70 2d  sz);.    pGroup-
3e90: 3e 62 45 6e 61 62 6c 65 64 20 3d 20 2d 31 3b 0a  >bEnabled = -1;.
3ea0: 20 20 20 20 70 47 72 6f 75 70 2d 3e 73 7a 43 68      pGroup->szCh
3eb0: 75 6e 6b 20 3d 20 53 51 4c 49 54 45 5f 4d 55 4c  unk = SQLITE_MUL
3ec0: 54 49 50 4c 45 58 5f 43 48 55 4e 4b 5f 53 49 5a  TIPLEX_CHUNK_SIZ
3ed0: 45 3b 0a 20 20 20 20 69 66 28 20 66 6c 61 67 73  E;.    if( flags
3ee0: 20 26 20 53 51 4c 49 54 45 5f 4f 50 45 4e 5f 55   & SQLITE_OPEN_U
3ef0: 52 49 20 29 7b 0a 20 20 20 20 20 20 63 6f 6e 73  RI ){.      cons
3f00: 74 20 63 68 61 72 20 2a 7a 43 68 75 6e 6b 53 69  t char *zChunkSi
3f10: 7a 65 3b 0a 20 20 20 20 20 20 7a 43 68 75 6e 6b  ze;.      zChunk
3f20: 53 69 7a 65 20 3d 20 73 71 6c 69 74 65 33 5f 75  Size = sqlite3_u
3f30: 72 69 5f 70 61 72 61 6d 65 74 65 72 28 7a 4e 61  ri_parameter(zNa
3f40: 6d 65 2c 20 22 63 68 75 6e 6b 73 69 7a 65 22 29  me, "chunksize")
3f50: 3b 0a 20 20 20 20 20 20 69 66 28 20 7a 43 68 75  ;.      if( zChu
3f60: 6e 6b 53 69 7a 65 20 29 7b 0a 20 20 20 20 20 20  nkSize ){.      
3f70: 20 20 75 6e 73 69 67 6e 65 64 20 69 6e 74 20 6e    unsigned int n
3f80: 20 3d 20 30 3b 0a 20 20 20 20 20 20 20 20 69 6e   = 0;.        in
3f90: 74 20 69 3b 0a 20 20 20 20 20 20 20 20 66 6f 72  t i;.        for
3fa0: 28 69 3d 30 3b 20 7a 43 68 75 6e 6b 53 69 7a 65  (i=0; zChunkSize
3fb0: 5b 69 5d 3e 3d 27 30 27 20 26 26 20 7a 43 68 75  [i]>='0' && zChu
3fc0: 6e 6b 53 69 7a 65 5b 69 5d 3c 3d 27 39 27 3b 20  nkSize[i]<='9'; 
3fd0: 69 2b 2b 29 7b 0a 20 20 20 20 20 20 20 20 20 20  i++){.          
3fe0: 6e 20 3d 20 6e 2a 31 30 20 2b 20 7a 43 68 75 6e  n = n*10 + zChun
3ff0: 6b 53 69 7a 65 5b 69 5d 20 2d 20 27 30 27 3b 0a  kSize[i] - '0';.
4000: 20 20 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20          }.      
4010: 20 20 69 66 28 20 6e 3e 30 20 29 7b 0a 20 20 20    if( n>0 ){.   
4020: 20 20 20 20 20 20 20 70 47 72 6f 75 70 2d 3e 73         pGroup->s
4030: 7a 43 68 75 6e 6b 20 3d 20 28 6e 2b 30 78 66 66  zChunk = (n+0xff
4040: 66 66 29 26 7e 30 78 66 66 66 66 3b 0a 20 20 20  ff)&~0xffff;.   
4050: 20 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20       }else{.    
4060: 20 20 20 20 20 20 2f 2a 20 41 20 7a 65 72 6f 20        /* A zero 
4070: 6f 72 20 6e 65 67 61 74 69 76 65 20 63 68 75 6e  or negative chun
4080: 6b 73 69 7a 65 20 64 69 73 61 62 6c 65 64 20 74  ksize disabled t
4090: 68 65 20 6d 75 6c 74 69 70 6c 65 78 6f 72 20 2a  he multiplexor *
40a0: 2f 0a 20 20 20 20 20 20 20 20 20 20 70 47 72 6f  /.          pGro
40b0: 75 70 2d 3e 62 45 6e 61 62 6c 65 64 20 3d 20 30  up->bEnabled = 0
40c0: 3b 0a 20 20 20 20 20 20 20 20 7d 0a 20 20 20 20  ;.        }.    
40d0: 20 20 7d 0a 20 20 20 20 7d 0a 20 20 20 20 70 47    }.    }.    pG
40e0: 72 6f 75 70 2d 3e 7a 4e 61 6d 65 20 3d 20 70 3b  roup->zName = p;
40f0: 0a 20 20 20 20 2f 2a 20 73 61 76 65 20 6f 66 66  .    /* save off
4100: 20 62 61 73 65 20 66 69 6c 65 6e 61 6d 65 2c 20   base filename, 
4110: 6e 61 6d 65 20 6c 65 6e 67 74 68 2c 20 61 6e 64  name length, and
4120: 20 6f 72 69 67 69 6e 61 6c 20 6f 70 65 6e 20 66   original open f
4130: 6c 61 67 73 20 20 2a 2f 0a 20 20 20 20 6d 65 6d  lags  */.    mem
4140: 63 70 79 28 70 47 72 6f 75 70 2d 3e 7a 4e 61 6d  cpy(pGroup->zNam
4150: 65 2c 20 7a 4e 61 6d 65 2c 20 6e 4e 61 6d 65 2b  e, zName, nName+
4160: 31 29 3b 0a 20 20 20 20 70 47 72 6f 75 70 2d 3e  1);.    pGroup->
4170: 6e 4e 61 6d 65 20 3d 20 6e 4e 61 6d 65 3b 0a 20  nName = nName;. 
4180: 20 20 20 70 47 72 6f 75 70 2d 3e 66 6c 61 67 73     pGroup->flags
4190: 20 3d 20 66 6c 61 67 73 3b 0a 20 20 20 20 72 63   = flags;.    rc
41a0: 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 46   = multiplexSubF
41b0: 69 6c 65 6e 61 6d 65 28 70 47 72 6f 75 70 2c 20  ilename(pGroup, 
41c0: 31 29 3b 0a 20 20 20 20 69 66 28 20 72 63 3d 3d  1);.    if( rc==
41d0: 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20  SQLITE_OK ){.   
41e0: 20 20 20 70 53 75 62 4f 70 65 6e 20 3d 20 6d 75     pSubOpen = mu
41f0: 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28 70  ltiplexSubOpen(p
4200: 47 72 6f 75 70 2c 20 30 2c 20 26 72 63 2c 20 70  Group, 0, &rc, p
4210: 4f 75 74 46 6c 61 67 73 29 3b 0a 20 20 20 20 7d  OutFlags);.    }
4220: 0a 20 20 20 20 69 66 28 20 70 53 75 62 4f 70 65  .    if( pSubOpe
4230: 6e 20 29 7b 0a 20 20 20 20 20 20 69 6e 74 20 65  n ){.      int e
4240: 78 69 73 74 73 2c 20 72 63 32 2c 20 72 63 33 3b  xists, rc2, rc3;
4250: 0a 20 20 20 20 20 20 73 71 6c 69 74 65 33 5f 69  .      sqlite3_i
4260: 6e 74 36 34 20 73 7a 3b 0a 0a 20 20 20 20 20 20  nt64 sz;..      
4270: 72 63 32 20 3d 20 70 53 75 62 4f 70 65 6e 2d 3e  rc2 = pSubOpen->
4280: 70 4d 65 74 68 6f 64 73 2d 3e 78 46 69 6c 65 53  pMethods->xFileS
4290: 69 7a 65 28 70 53 75 62 4f 70 65 6e 2c 20 26 73  ize(pSubOpen, &s
42a0: 7a 29 3b 0a 20 20 20 20 20 20 69 66 28 20 72 63  z);.      if( rc
42b0: 32 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a  2==SQLITE_OK ){.
42c0: 20 20 20 20 20 20 20 20 2f 2a 20 49 66 20 74 68          /* If th
42d0: 65 20 66 69 72 73 74 20 6f 76 65 72 66 6c 6f 77  e first overflow
42e0: 20 66 69 6c 65 20 65 78 69 73 74 73 20 61 6e 64   file exists and
42f0: 20 69 66 20 74 68 65 20 73 69 7a 65 20 6f 66 20   if the size of 
4300: 74 68 65 20 6d 61 69 6e 20 66 69 6c 65 0a 20 20  the main file.  
4310: 20 20 20 20 20 20 2a 2a 20 69 73 20 64 69 66 66        ** is diff
4320: 65 72 65 6e 74 20 66 72 6f 6d 20 74 68 65 20 63  erent from the c
4330: 68 75 6e 6b 20 73 69 7a 65 2c 20 74 68 61 74 20  hunk size, that 
4340: 6d 65 61 6e 73 20 74 68 65 20 63 68 75 6e 6b 20  means the chunk 
4350: 73 69 7a 65 20 69 73 20 73 65 74 0a 20 20 20 20  size is set.    
4360: 20 20 20 20 2a 2a 20 73 65 74 20 69 6e 63 6f 72      ** set incor
4370: 72 65 63 74 6c 79 2e 20 20 53 6f 20 66 69 78 20  rectly.  So fix 
4380: 69 74 2e 0a 20 20 20 20 20 20 20 20 2a 2a 0a 20  it..        **. 
4390: 20 20 20 20 20 20 20 2a 2a 20 4f 72 2c 20 69 66         ** Or, if
43a0: 20 74 68 65 20 66 69 72 73 74 20 6f 76 65 72 66   the first overf
43b0: 6c 6f 77 20 66 69 6c 65 20 64 6f 65 73 20 6e 6f  low file does no
43c0: 74 20 65 78 69 73 74 20 61 6e 64 20 74 68 65 20  t exist and the 
43d0: 6d 61 69 6e 20 66 69 6c 65 20 69 73 0a 20 20 20  main file is.   
43e0: 20 20 20 20 20 2a 2a 20 6c 61 72 67 65 72 20 74       ** larger t
43f0: 68 61 6e 20 74 68 65 20 63 68 75 6e 6b 20 73 69  han the chunk si
4400: 7a 65 2c 20 74 68 61 74 20 6d 65 61 6e 73 20 74  ze, that means t
4410: 68 65 20 63 68 75 6e 6b 20 73 69 7a 65 20 69 73  he chunk size is
4420: 20 74 6f 6f 20 73 6d 61 6c 6c 2e 0a 20 20 20 20   too small..    
4430: 20 20 20 20 2a 2a 20 42 75 74 20 77 65 20 68 61      ** But we ha
4440: 76 65 20 6e 6f 20 77 61 79 20 6f 66 20 64 65 74  ve no way of det
4450: 65 72 6d 69 6e 69 6e 67 20 74 68 65 20 69 6e 74  ermining the int
4460: 65 6e 64 65 64 20 63 68 75 6e 6b 20 73 69 7a 65  ended chunk size
4470: 2c 20 73 6f 20 0a 20 20 20 20 20 20 20 20 2a 2a  , so .        **
4480: 20 6a 75 73 74 20 64 69 73 61 62 6c 65 20 74 68   just disable th
4490: 65 20 6d 75 6c 74 69 70 6c 65 78 6f 72 20 61 6c  e multiplexor al
44a0: 6c 20 74 6f 67 65 74 68 72 65 2e 0a 20 20 20 20  l togethre..    
44b0: 20 20 20 20 2a 2f 0a 20 20 20 20 20 20 20 20 72      */.        r
44c0: 63 33 20 3d 20 70 4f 72 69 67 56 66 73 2d 3e 78  c3 = pOrigVfs->x
44d0: 41 63 63 65 73 73 28 70 4f 72 69 67 56 66 73 2c  Access(pOrigVfs,
44e0: 20 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 31   pGroup->aReal[1
44f0: 5d 2e 7a 2c 0a 20 20 20 20 20 20 20 20 20 20 20  ].z,.           
4500: 20 53 51 4c 49 54 45 5f 41 43 43 45 53 53 5f 45   SQLITE_ACCESS_E
4510: 58 49 53 54 53 2c 20 26 65 78 69 73 74 73 29 3b  XISTS, &exists);
4520: 0a 20 20 20 20 20 20 20 20 69 66 28 20 72 63 33  .        if( rc3
4530: 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 26 26 20 65  ==SQLITE_OK && e
4540: 78 69 73 74 73 20 26 26 20 73 7a 3d 3d 28 73 7a  xists && sz==(sz
4550: 26 30 78 66 66 66 66 30 30 30 30 29 20 26 26 20  &0xffff0000) && 
4560: 73 7a 3e 30 0a 20 20 20 20 20 20 20 20 20 20 20  sz>0.           
4570: 20 26 26 20 73 7a 21 3d 70 47 72 6f 75 70 2d 3e   && sz!=pGroup->
4580: 73 7a 43 68 75 6e 6b 20 29 7b 0a 20 20 20 20 20  szChunk ){.     
4590: 20 20 20 20 20 70 47 72 6f 75 70 2d 3e 73 7a 43       pGroup->szC
45a0: 68 75 6e 6b 20 3d 20 73 7a 3b 0a 20 20 20 20 20  hunk = sz;.     
45b0: 20 20 20 7d 65 6c 73 65 20 69 66 28 20 72 63 33     }else if( rc3
45c0: 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 26 26 20 21  ==SQLITE_OK && !
45d0: 65 78 69 73 74 73 20 26 26 20 73 7a 3e 70 47 72  exists && sz>pGr
45e0: 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 20 29 7b 0a  oup->szChunk ){.
45f0: 20 20 20 20 20 20 20 20 20 20 70 47 72 6f 75 70            pGroup
4600: 2d 3e 62 45 6e 61 62 6c 65 64 20 3d 20 30 3b 0a  ->bEnabled = 0;.
4610: 20 20 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20          }.      
4620: 7d 0a 0a 20 20 20 20 20 20 69 66 28 20 70 53 75  }..      if( pSu
4630: 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d  bOpen->pMethods-
4640: 3e 69 56 65 72 73 69 6f 6e 3d 3d 31 20 29 7b 0a  >iVersion==1 ){.
4650: 20 20 20 20 20 20 20 20 70 4d 75 6c 74 69 70 6c          pMultipl
4660: 65 78 4f 70 65 6e 2d 3e 62 61 73 65 2e 70 4d 65  exOpen->base.pMe
4670: 74 68 6f 64 73 20 3d 20 26 67 4d 75 6c 74 69 70  thods = &gMultip
4680: 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31  lex.sIoMethodsV1
4690: 3b 0a 20 20 20 20 20 20 7d 65 6c 73 65 7b 0a 20  ;.      }else{. 
46a0: 20 20 20 20 20 20 20 70 4d 75 6c 74 69 70 6c 65         pMultiple
46b0: 78 4f 70 65 6e 2d 3e 62 61 73 65 2e 70 4d 65 74  xOpen->base.pMet
46c0: 68 6f 64 73 20 3d 20 26 67 4d 75 6c 74 69 70 6c  hods = &gMultipl
46d0: 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 32 3b  ex.sIoMethodsV2;
46e0: 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 2f  .      }.      /
46f0: 2a 20 70 6c 61 63 65 20 74 68 69 73 20 67 72 6f  * place this gro
4700: 75 70 20 61 74 20 74 68 65 20 68 65 61 64 20 6f  up at the head o
4710: 66 20 6f 75 72 20 6c 69 73 74 20 2a 2f 0a 20 20  f our list */.  
4720: 20 20 20 20 70 47 72 6f 75 70 2d 3e 70 4e 65 78      pGroup->pNex
4730: 74 20 3d 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70  t = gMultiplex.p
4740: 47 72 6f 75 70 73 3b 0a 20 20 20 20 20 20 69 66  Groups;.      if
4750: 28 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 47 72  ( gMultiplex.pGr
4760: 6f 75 70 73 20 29 20 67 4d 75 6c 74 69 70 6c 65  oups ) gMultiple
4770: 78 2e 70 47 72 6f 75 70 73 2d 3e 70 50 72 65 76  x.pGroups->pPrev
4780: 20 3d 20 70 47 72 6f 75 70 3b 0a 20 20 20 20 20   = pGroup;.     
4790: 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 47 72 6f   gMultiplex.pGro
47a0: 75 70 73 20 3d 20 70 47 72 6f 75 70 3b 0a 20 20  ups = pGroup;.  
47b0: 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 6d    }else{.      m
47c0: 75 6c 74 69 70 6c 65 78 46 72 65 65 43 6f 6d 70  ultiplexFreeComp
47d0: 6f 6e 65 6e 74 73 28 70 47 72 6f 75 70 29 3b 0a  onents(pGroup);.
47e0: 20 20 20 20 20 20 73 71 6c 69 74 65 33 5f 66 72        sqlite3_fr
47f0: 65 65 28 70 47 72 6f 75 70 29 3b 0a 20 20 20 20  ee(pGroup);.    
4800: 7d 0a 20 20 7d 0a 20 20 6d 75 6c 74 69 70 6c 65  }.  }.  multiple
4810: 78 4c 65 61 76 65 28 29 3b 0a 20 20 73 71 6c 69  xLeave();.  sqli
4820: 74 65 33 5f 66 72 65 65 28 7a 54 6f 46 72 65 65  te3_free(zToFree
4830: 29 3b 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a  );.  return rc;.
4840: 7d 0a 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20 69 73  }../*.** This is
4850: 20 74 68 65 20 78 44 65 6c 65 74 65 20 6d 65 74   the xDelete met
4860: 68 6f 64 20 75 73 65 64 20 66 6f 72 20 74 68 65  hod used for the
4870: 20 22 6d 75 6c 74 69 70 6c 65 78 22 20 56 46 53   "multiplex" VFS
4880: 2e 0a 2a 2a 20 49 74 20 61 74 74 65 6d 70 74 73  ..** It attempts
4890: 20 74 6f 20 64 65 6c 65 74 65 20 74 68 65 20 66   to delete the f
48a0: 69 6c 65 6e 61 6d 65 20 73 70 65 63 69 66 69 65  ilename specifie
48b0: 64 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74  d..*/.static int
48c0: 20 6d 75 6c 74 69 70 6c 65 78 44 65 6c 65 74 65   multiplexDelete
48d0: 28 0a 20 20 73 71 6c 69 74 65 33 5f 76 66 73 20  (.  sqlite3_vfs 
48e0: 2a 70 56 66 73 2c 20 20 20 20 20 20 20 20 20 2f  *pVfs,         /
48f0: 2a 20 54 68 65 20 6d 75 6c 74 69 70 6c 65 78 20  * The multiplex 
4900: 56 46 53 20 2a 2f 0a 20 20 63 6f 6e 73 74 20 63  VFS */.  const c
4910: 68 61 72 20 2a 7a 4e 61 6d 65 2c 20 20 20 20 20  har *zName,     
4920: 20 20 20 20 2f 2a 20 4e 61 6d 65 20 6f 66 20 66      /* Name of f
4930: 69 6c 65 20 74 6f 20 64 65 6c 65 74 65 20 2a 2f  ile to delete */
4940: 0a 20 20 69 6e 74 20 73 79 6e 63 44 69 72 0a 29  .  int syncDir.)
4950: 7b 0a 20 20 73 71 6c 69 74 65 33 5f 76 66 73 20  {.  sqlite3_vfs 
4960: 2a 70 4f 72 69 67 56 66 73 20 3d 20 67 4d 75 6c  *pOrigVfs = gMul
4970: 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 3b  tiplex.pOrigVfs;
4980: 20 20 20 2f 2a 20 52 65 61 6c 20 56 46 53 20 2a     /* Real VFS *
4990: 2f 0a 20 20 72 65 74 75 72 6e 20 70 4f 72 69 67  /.  return pOrig
49a0: 56 66 73 2d 3e 78 44 65 6c 65 74 65 28 70 4f 72  Vfs->xDelete(pOr
49b0: 69 67 56 66 73 2c 20 7a 4e 61 6d 65 2c 20 73 79  igVfs, zName, sy
49c0: 6e 63 44 69 72 29 3b 0a 7d 0a 0a 73 74 61 74 69  ncDir);.}..stati
49d0: 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 41  c int multiplexA
49e0: 63 63 65 73 73 28 73 71 6c 69 74 65 33 5f 76 66  ccess(sqlite3_vf
49f0: 73 20 2a 61 2c 20 63 6f 6e 73 74 20 63 68 61 72  s *a, const char
4a00: 20 2a 62 2c 20 69 6e 74 20 63 2c 20 69 6e 74 20   *b, int c, int 
4a10: 2a 64 29 7b 0a 20 20 72 65 74 75 72 6e 20 67 4d  *d){.  return gM
4a20: 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66  ultiplex.pOrigVf
4a30: 73 2d 3e 78 41 63 63 65 73 73 28 67 4d 75 6c 74  s->xAccess(gMult
4a40: 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2c 20  iplex.pOrigVfs, 
4a50: 62 2c 20 63 2c 20 64 29 3b 0a 7d 0a 73 74 61 74  b, c, d);.}.stat
4a60: 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78  ic int multiplex
4a70: 46 75 6c 6c 50 61 74 68 6e 61 6d 65 28 73 71 6c  FullPathname(sql
4a80: 69 74 65 33 5f 76 66 73 20 2a 61 2c 20 63 6f 6e  ite3_vfs *a, con
4a90: 73 74 20 63 68 61 72 20 2a 62 2c 20 69 6e 74 20  st char *b, int 
4aa0: 63 2c 20 63 68 61 72 20 2a 64 29 7b 0a 20 20 72  c, char *d){.  r
4ab0: 65 74 75 72 6e 20 67 4d 75 6c 74 69 70 6c 65 78  eturn gMultiplex
4ac0: 2e 70 4f 72 69 67 56 66 73 2d 3e 78 46 75 6c 6c  .pOrigVfs->xFull
4ad0: 50 61 74 68 6e 61 6d 65 28 67 4d 75 6c 74 69 70  Pathname(gMultip
4ae0: 6c 65 78 2e 70 4f 72 69 67 56 66 73 2c 20 62 2c  lex.pOrigVfs, b,
4af0: 20 63 2c 20 64 29 3b 0a 7d 0a 73 74 61 74 69 63   c, d);.}.static
4b00: 20 76 6f 69 64 20 2a 6d 75 6c 74 69 70 6c 65 78   void *multiplex
4b10: 44 6c 4f 70 65 6e 28 73 71 6c 69 74 65 33 5f 76  DlOpen(sqlite3_v
4b20: 66 73 20 2a 61 2c 20 63 6f 6e 73 74 20 63 68 61  fs *a, const cha
4b30: 72 20 2a 62 29 7b 0a 20 20 72 65 74 75 72 6e 20  r *b){.  return 
4b40: 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67  gMultiplex.pOrig
4b50: 56 66 73 2d 3e 78 44 6c 4f 70 65 6e 28 67 4d 75  Vfs->xDlOpen(gMu
4b60: 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73  ltiplex.pOrigVfs
4b70: 2c 20 62 29 3b 0a 7d 0a 73 74 61 74 69 63 20 76  , b);.}.static v
4b80: 6f 69 64 20 6d 75 6c 74 69 70 6c 65 78 44 6c 45  oid multiplexDlE
4b90: 72 72 6f 72 28 73 71 6c 69 74 65 33 5f 76 66 73  rror(sqlite3_vfs
4ba0: 20 2a 61 2c 20 69 6e 74 20 62 2c 20 63 68 61 72   *a, int b, char
4bb0: 20 2a 63 29 7b 0a 20 20 67 4d 75 6c 74 69 70 6c   *c){.  gMultipl
4bc0: 65 78 2e 70 4f 72 69 67 56 66 73 2d 3e 78 44 6c  ex.pOrigVfs->xDl
4bd0: 45 72 72 6f 72 28 67 4d 75 6c 74 69 70 6c 65 78  Error(gMultiplex
4be0: 2e 70 4f 72 69 67 56 66 73 2c 20 62 2c 20 63 29  .pOrigVfs, b, c)
4bf0: 3b 0a 7d 0a 73 74 61 74 69 63 20 76 6f 69 64 20  ;.}.static void 
4c00: 28 2a 6d 75 6c 74 69 70 6c 65 78 44 6c 53 79 6d  (*multiplexDlSym
4c10: 28 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 61 2c  (sqlite3_vfs *a,
4c20: 20 76 6f 69 64 20 2a 62 2c 20 63 6f 6e 73 74 20   void *b, const 
4c30: 63 68 61 72 20 2a 63 29 29 28 76 6f 69 64 29 7b  char *c))(void){
4c40: 0a 20 20 72 65 74 75 72 6e 20 67 4d 75 6c 74 69  .  return gMulti
4c50: 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2d 3e 78  plex.pOrigVfs->x
4c60: 44 6c 53 79 6d 28 67 4d 75 6c 74 69 70 6c 65 78  DlSym(gMultiplex
4c70: 2e 70 4f 72 69 67 56 66 73 2c 20 62 2c 20 63 29  .pOrigVfs, b, c)
4c80: 3b 0a 7d 0a 73 74 61 74 69 63 20 76 6f 69 64 20  ;.}.static void 
4c90: 6d 75 6c 74 69 70 6c 65 78 44 6c 43 6c 6f 73 65  multiplexDlClose
4ca0: 28 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 61 2c  (sqlite3_vfs *a,
4cb0: 20 76 6f 69 64 20 2a 62 29 7b 0a 20 20 67 4d 75   void *b){.  gMu
4cc0: 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73  ltiplex.pOrigVfs
4cd0: 2d 3e 78 44 6c 43 6c 6f 73 65 28 67 4d 75 6c 74  ->xDlClose(gMult
4ce0: 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2c 20  iplex.pOrigVfs, 
4cf0: 62 29 3b 0a 7d 0a 73 74 61 74 69 63 20 69 6e 74  b);.}.static int
4d00: 20 6d 75 6c 74 69 70 6c 65 78 52 61 6e 64 6f 6d   multiplexRandom
4d10: 6e 65 73 73 28 73 71 6c 69 74 65 33 5f 76 66 73  ness(sqlite3_vfs
4d20: 20 2a 61 2c 20 69 6e 74 20 62 2c 20 63 68 61 72   *a, int b, char
4d30: 20 2a 63 29 7b 0a 20 20 72 65 74 75 72 6e 20 67   *c){.  return g
4d40: 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56  Multiplex.pOrigV
4d50: 66 73 2d 3e 78 52 61 6e 64 6f 6d 6e 65 73 73 28  fs->xRandomness(
4d60: 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67  gMultiplex.pOrig
4d70: 56 66 73 2c 20 62 2c 20 63 29 3b 0a 7d 0a 73 74  Vfs, b, c);.}.st
4d80: 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c  atic int multipl
4d90: 65 78 53 6c 65 65 70 28 73 71 6c 69 74 65 33 5f  exSleep(sqlite3_
4da0: 76 66 73 20 2a 61 2c 20 69 6e 74 20 62 29 7b 0a  vfs *a, int b){.
4db0: 20 20 72 65 74 75 72 6e 20 67 4d 75 6c 74 69 70    return gMultip
4dc0: 6c 65 78 2e 70 4f 72 69 67 56 66 73 2d 3e 78 53  lex.pOrigVfs->xS
4dd0: 6c 65 65 70 28 67 4d 75 6c 74 69 70 6c 65 78 2e  leep(gMultiplex.
4de0: 70 4f 72 69 67 56 66 73 2c 20 62 29 3b 0a 7d 0a  pOrigVfs, b);.}.
4df0: 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69  static int multi
4e00: 70 6c 65 78 43 75 72 72 65 6e 74 54 69 6d 65 28  plexCurrentTime(
4e10: 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 61 2c 20  sqlite3_vfs *a, 
4e20: 64 6f 75 62 6c 65 20 2a 62 29 7b 0a 20 20 72 65  double *b){.  re
4e30: 74 75 72 6e 20 67 4d 75 6c 74 69 70 6c 65 78 2e  turn gMultiplex.
4e40: 70 4f 72 69 67 56 66 73 2d 3e 78 43 75 72 72 65  pOrigVfs->xCurre
4e50: 6e 74 54 69 6d 65 28 67 4d 75 6c 74 69 70 6c 65  ntTime(gMultiple
4e60: 78 2e 70 4f 72 69 67 56 66 73 2c 20 62 29 3b 0a  x.pOrigVfs, b);.
4e70: 7d 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c  }.static int mul
4e80: 74 69 70 6c 65 78 47 65 74 4c 61 73 74 45 72 72  tiplexGetLastErr
4e90: 6f 72 28 73 71 6c 69 74 65 33 5f 76 66 73 20 2a  or(sqlite3_vfs *
4ea0: 61 2c 20 69 6e 74 20 62 2c 20 63 68 61 72 20 2a  a, int b, char *
4eb0: 63 29 7b 0a 20 20 72 65 74 75 72 6e 20 67 4d 75  c){.  return gMu
4ec0: 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73  ltiplex.pOrigVfs
4ed0: 2d 3e 78 47 65 74 4c 61 73 74 45 72 72 6f 72 28  ->xGetLastError(
4ee0: 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67  gMultiplex.pOrig
4ef0: 56 66 73 2c 20 62 2c 20 63 29 3b 0a 7d 0a 73 74  Vfs, b, c);.}.st
4f00: 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c  atic int multipl
4f10: 65 78 43 75 72 72 65 6e 74 54 69 6d 65 49 6e 74  exCurrentTimeInt
4f20: 36 34 28 73 71 6c 69 74 65 33 5f 76 66 73 20 2a  64(sqlite3_vfs *
4f30: 61 2c 20 73 71 6c 69 74 65 33 5f 69 6e 74 36 34  a, sqlite3_int64
4f40: 20 2a 62 29 7b 0a 20 20 72 65 74 75 72 6e 20 67   *b){.  return g
4f50: 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56  Multiplex.pOrigV
4f60: 66 73 2d 3e 78 43 75 72 72 65 6e 74 54 69 6d 65  fs->xCurrentTime
4f70: 49 6e 74 36 34 28 67 4d 75 6c 74 69 70 6c 65 78  Int64(gMultiplex
4f80: 2e 70 4f 72 69 67 56 66 73 2c 20 62 29 3b 0a 7d  .pOrigVfs, b);.}
4f90: 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ../*************
4fa0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20 49 2f 4f 20  *********** I/O 
4fb0: 4d 65 74 68 6f 64 20 57 72 61 70 70 65 72 73 20  Method Wrappers 
4fc0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
4fd0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2f  ***************/
4fe0: 0a 0a 2f 2a 20 78 43 6c 6f 73 65 20 72 65 71 75  ../* xClose requ
4ff0: 65 73 74 73 20 67 65 74 20 70 61 73 73 65 64 20  ests get passed 
5000: 74 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20 6f  through to the o
5010: 72 69 67 69 6e 61 6c 20 56 46 53 2e 0a 2a 2a 20  riginal VFS..** 
5020: 57 65 20 6c 6f 6f 70 20 6f 76 65 72 20 61 6c 6c  We loop over all
5030: 20 6f 70 65 6e 20 63 68 75 6e 6b 20 68 61 6e 64   open chunk hand
5040: 6c 65 73 20 61 6e 64 20 63 6c 6f 73 65 20 74 68  les and close th
5050: 65 6d 2e 0a 2a 2a 20 54 68 65 20 67 72 6f 75 70  em..** The group
5060: 20 73 74 72 75 63 74 75 72 65 20 66 6f 72 20 74   structure for t
5070: 68 69 73 20 66 69 6c 65 20 69 73 20 75 6e 6c 69  his file is unli
5080: 6e 6b 65 64 20 66 72 6f 6d 20 0a 2a 2a 20 6f 75  nked from .** ou
5090: 72 20 6c 69 73 74 20 6f 66 20 67 72 6f 75 70 73  r list of groups
50a0: 20 61 6e 64 20 66 72 65 65 64 2e 0a 2a 2f 0a 73   and freed..*/.s
50b0: 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70  tatic int multip
50c0: 6c 65 78 43 6c 6f 73 65 28 73 71 6c 69 74 65 33  lexClose(sqlite3
50d0: 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 29 7b 0a 20  _file *pConn){. 
50e0: 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a   multiplexConn *
50f0: 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f  p = (multiplexCo
5100: 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 6d 75 6c  nn*)pConn;.  mul
5110: 74 69 70 6c 65 78 47 72 6f 75 70 20 2a 70 47 72  tiplexGroup *pGr
5120: 6f 75 70 20 3d 20 70 2d 3e 70 47 72 6f 75 70 3b  oup = p->pGroup;
5130: 0a 20 20 69 6e 74 20 72 63 20 3d 20 53 51 4c 49  .  int rc = SQLI
5140: 54 45 5f 4f 4b 3b 0a 20 20 6d 75 6c 74 69 70 6c  TE_OK;.  multipl
5150: 65 78 45 6e 74 65 72 28 29 3b 0a 20 20 6d 75 6c  exEnter();.  mul
5160: 74 69 70 6c 65 78 46 72 65 65 43 6f 6d 70 6f 6e  tiplexFreeCompon
5170: 65 6e 74 73 28 70 47 72 6f 75 70 29 3b 0a 20 20  ents(pGroup);.  
5180: 2f 2a 20 72 65 6d 6f 76 65 20 66 72 6f 6d 20 6c  /* remove from l
5190: 69 6e 6b 65 64 20 6c 69 73 74 20 2a 2f 0a 20 20  inked list */.  
51a0: 69 66 28 20 70 47 72 6f 75 70 2d 3e 70 4e 65 78  if( pGroup->pNex
51b0: 74 20 29 20 70 47 72 6f 75 70 2d 3e 70 4e 65 78  t ) pGroup->pNex
51c0: 74 2d 3e 70 50 72 65 76 20 3d 20 70 47 72 6f 75  t->pPrev = pGrou
51d0: 70 2d 3e 70 50 72 65 76 3b 0a 20 20 69 66 28 20  p->pPrev;.  if( 
51e0: 70 47 72 6f 75 70 2d 3e 70 50 72 65 76 20 29 7b  pGroup->pPrev ){
51f0: 0a 20 20 20 20 70 47 72 6f 75 70 2d 3e 70 50 72  .    pGroup->pPr
5200: 65 76 2d 3e 70 4e 65 78 74 20 3d 20 70 47 72 6f  ev->pNext = pGro
5210: 75 70 2d 3e 70 4e 65 78 74 3b 0a 20 20 7d 65 6c  up->pNext;.  }el
5220: 73 65 7b 0a 20 20 20 20 67 4d 75 6c 74 69 70 6c  se{.    gMultipl
5230: 65 78 2e 70 47 72 6f 75 70 73 20 3d 20 70 47 72  ex.pGroups = pGr
5240: 6f 75 70 2d 3e 70 4e 65 78 74 3b 0a 20 20 7d 0a  oup->pNext;.  }.
5250: 20 20 73 71 6c 69 74 65 33 5f 66 72 65 65 28 70    sqlite3_free(p
5260: 47 72 6f 75 70 29 3b 0a 20 20 6d 75 6c 74 69 70  Group);.  multip
5270: 6c 65 78 4c 65 61 76 65 28 29 3b 0a 20 20 72 65  lexLeave();.  re
5280: 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 20 50  turn rc;.}../* P
5290: 61 73 73 20 78 52 65 61 64 20 72 65 71 75 65 73  ass xRead reques
52a0: 74 73 20 74 68 72 75 20 74 6f 20 74 68 65 20 6f  ts thru to the o
52b0: 72 69 67 69 6e 61 6c 20 56 46 53 20 61 66 74 65  riginal VFS afte
52c0: 72 0a 2a 2a 20 64 65 74 65 72 6d 69 6e 69 6e 67  r.** determining
52d0: 20 74 68 65 20 63 6f 72 72 65 63 74 20 63 68 75   the correct chu
52e0: 6e 6b 20 74 6f 20 6f 70 65 72 61 74 65 20 6f 6e  nk to operate on
52f0: 2e 0a 2a 2a 20 42 72 65 61 6b 20 75 70 20 72 65  ..** Break up re
5300: 61 64 73 20 61 63 72 6f 73 73 20 63 68 75 6e 6b  ads across chunk
5310: 20 62 6f 75 6e 64 61 72 69 65 73 2e 0a 2a 2f 0a   boundaries..*/.
5320: 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69  static int multi
5330: 70 6c 65 78 52 65 61 64 28 0a 20 20 73 71 6c 69  plexRead(.  sqli
5340: 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c  te3_file *pConn,
5350: 0a 20 20 76 6f 69 64 20 2a 70 42 75 66 2c 0a 20  .  void *pBuf,. 
5360: 20 69 6e 74 20 69 41 6d 74 2c 0a 20 20 73 71 6c   int iAmt,.  sql
5370: 69 74 65 33 5f 69 6e 74 36 34 20 69 4f 66 73 74  ite3_int64 iOfst
5380: 0a 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43  .){.  multiplexC
5390: 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70  onn *p = (multip
53a0: 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a  lexConn*)pConn;.
53b0: 20 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70    multiplexGroup
53c0: 20 2a 70 47 72 6f 75 70 20 3d 20 70 2d 3e 70 47   *pGroup = p->pG
53d0: 72 6f 75 70 3b 0a 20 20 69 6e 74 20 72 63 20 3d  roup;.  int rc =
53e0: 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 6d 75   SQLITE_OK;.  mu
53f0: 6c 74 69 70 6c 65 78 45 6e 74 65 72 28 29 3b 0a  ltiplexEnter();.
5400: 20 20 69 66 28 20 21 70 47 72 6f 75 70 2d 3e 62    if( !pGroup->b
5410: 45 6e 61 62 6c 65 64 20 29 7b 0a 20 20 20 20 73  Enabled ){.    s
5420: 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75  qlite3_file *pSu
5430: 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65  bOpen = multiple
5440: 78 53 75 62 4f 70 65 6e 28 70 47 72 6f 75 70 2c  xSubOpen(pGroup,
5450: 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 29 3b 0a   0, &rc, NULL);.
5460: 20 20 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e      if( pSubOpen
5470: 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 72 63 20  ==0 ){.      rc 
5480: 3d 20 53 51 4c 49 54 45 5f 49 4f 45 52 52 5f 52  = SQLITE_IOERR_R
5490: 45 41 44 3b 0a 20 20 20 20 7d 65 6c 73 65 7b 0a  EAD;.    }else{.
54a0: 20 20 20 20 20 20 72 63 20 3d 20 70 53 75 62 4f        rc = pSubO
54b0: 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e 78  pen->pMethods->x
54c0: 52 65 61 64 28 70 53 75 62 4f 70 65 6e 2c 20 70  Read(pSubOpen, p
54d0: 42 75 66 2c 20 69 41 6d 74 2c 20 69 4f 66 73 74  Buf, iAmt, iOfst
54e0: 29 3b 0a 20 20 20 20 7d 0a 20 20 7d 65 6c 73 65  );.    }.  }else
54f0: 7b 0a 20 20 20 20 77 68 69 6c 65 28 20 69 41 6d  {.    while( iAm
5500: 74 20 3e 20 30 20 29 7b 0a 20 20 20 20 20 20 69  t > 0 ){.      i
5510: 6e 74 20 69 20 3d 20 28 69 6e 74 29 28 69 4f 66  nt i = (int)(iOf
5520: 73 74 20 2f 20 70 47 72 6f 75 70 2d 3e 73 7a 43  st / pGroup->szC
5530: 68 75 6e 6b 29 3b 0a 20 20 20 20 20 20 73 71 6c  hunk);.      sql
5540: 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f  ite3_file *pSubO
5550: 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53  pen = multiplexS
5560: 75 62 4f 70 65 6e 28 70 47 72 6f 75 70 2c 20 69  ubOpen(pGroup, i
5570: 2c 20 26 72 63 2c 20 4e 55 4c 4c 29 3b 0a 20 20  , &rc, NULL);.  
5580: 20 20 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e      if( pSubOpen
5590: 20 29 7b 0a 20 20 20 20 20 20 20 20 69 6e 74 20   ){.        int 
55a0: 65 78 74 72 61 20 3d 20 28 28 69 6e 74 29 28 69  extra = ((int)(i
55b0: 4f 66 73 74 20 25 20 70 47 72 6f 75 70 2d 3e 73  Ofst % pGroup->s
55c0: 7a 43 68 75 6e 6b 29 20 2b 20 69 41 6d 74 29 20  zChunk) + iAmt) 
55d0: 2d 20 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e  - pGroup->szChun
55e0: 6b 3b 0a 20 20 20 20 20 20 20 20 69 66 28 20 65  k;.        if( e
55f0: 78 74 72 61 3c 30 20 29 20 65 78 74 72 61 20 3d  xtra<0 ) extra =
5600: 20 30 3b 0a 20 20 20 20 20 20 20 20 69 41 6d 74   0;.        iAmt
5610: 20 2d 3d 20 65 78 74 72 61 3b 0a 20 20 20 20 20   -= extra;.     
5620: 20 20 20 72 63 20 3d 20 70 53 75 62 4f 70 65 6e     rc = pSubOpen
5630: 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e 78 52 65 61  ->pMethods->xRea
5640: 64 28 70 53 75 62 4f 70 65 6e 2c 20 70 42 75 66  d(pSubOpen, pBuf
5650: 2c 20 69 41 6d 74 2c 0a 20 20 20 20 20 20 20 20  , iAmt,.        
5660: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5670: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69                 i
5680: 4f 66 73 74 20 25 20 70 47 72 6f 75 70 2d 3e 73  Ofst % pGroup->s
5690: 7a 43 68 75 6e 6b 29 3b 0a 20 20 20 20 20 20 20  zChunk);.       
56a0: 20 69 66 28 20 72 63 21 3d 53 51 4c 49 54 45 5f   if( rc!=SQLITE_
56b0: 4f 4b 20 29 20 62 72 65 61 6b 3b 0a 20 20 20 20  OK ) break;.    
56c0: 20 20 20 20 70 42 75 66 20 3d 20 28 63 68 61 72      pBuf = (char
56d0: 20 2a 29 70 42 75 66 20 2b 20 69 41 6d 74 3b 0a   *)pBuf + iAmt;.
56e0: 20 20 20 20 20 20 20 20 69 4f 66 73 74 20 2b 3d          iOfst +=
56f0: 20 69 41 6d 74 3b 0a 20 20 20 20 20 20 20 20 69   iAmt;.        i
5700: 41 6d 74 20 3d 20 65 78 74 72 61 3b 0a 20 20 20  Amt = extra;.   
5710: 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20     }else{.      
5720: 20 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 49 4f    rc = SQLITE_IO
5730: 45 52 52 5f 52 45 41 44 3b 0a 20 20 20 20 20 20  ERR_READ;.      
5740: 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 7d    break;.      }
5750: 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20 6d 75 6c  .    }.  }.  mul
5760: 74 69 70 6c 65 78 4c 65 61 76 65 28 29 3b 0a 20  tiplexLeave();. 
5770: 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f   return rc;.}../
5780: 2a 20 50 61 73 73 20 78 57 72 69 74 65 20 72 65  * Pass xWrite re
5790: 71 75 65 73 74 73 20 74 68 72 75 20 74 6f 20 74  quests thru to t
57a0: 68 65 20 6f 72 69 67 69 6e 61 6c 20 56 46 53 20  he original VFS 
57b0: 61 66 74 65 72 0a 2a 2a 20 64 65 74 65 72 6d 69  after.** determi
57c0: 6e 69 6e 67 20 74 68 65 20 63 6f 72 72 65 63 74  ning the correct
57d0: 20 63 68 75 6e 6b 20 74 6f 20 6f 70 65 72 61 74   chunk to operat
57e0: 65 20 6f 6e 2e 0a 2a 2a 20 42 72 65 61 6b 20 75  e on..** Break u
57f0: 70 20 77 72 69 74 65 73 20 61 63 72 6f 73 73 20  p writes across 
5800: 63 68 75 6e 6b 20 62 6f 75 6e 64 61 72 69 65 73  chunk boundaries
5810: 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20  ..*/.static int 
5820: 6d 75 6c 74 69 70 6c 65 78 57 72 69 74 65 28 0a  multiplexWrite(.
5830: 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a    sqlite3_file *
5840: 70 43 6f 6e 6e 2c 0a 20 20 63 6f 6e 73 74 20 76  pConn,.  const v
5850: 6f 69 64 20 2a 70 42 75 66 2c 0a 20 20 69 6e 74  oid *pBuf,.  int
5860: 20 69 41 6d 74 2c 0a 20 20 73 71 6c 69 74 65 33   iAmt,.  sqlite3
5870: 5f 69 6e 74 36 34 20 69 4f 66 73 74 0a 29 7b 0a  _int64 iOfst.){.
5880: 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20    multiplexConn 
5890: 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43  *p = (multiplexC
58a0: 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 6d 75  onn*)pConn;.  mu
58b0: 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 2a 70 47  ltiplexGroup *pG
58c0: 72 6f 75 70 20 3d 20 70 2d 3e 70 47 72 6f 75 70  roup = p->pGroup
58d0: 3b 0a 20 20 69 6e 74 20 72 63 20 3d 20 53 51 4c  ;.  int rc = SQL
58e0: 49 54 45 5f 4f 4b 3b 0a 20 20 6d 75 6c 74 69 70  ITE_OK;.  multip
58f0: 6c 65 78 45 6e 74 65 72 28 29 3b 0a 20 20 69 66  lexEnter();.  if
5900: 28 20 21 70 47 72 6f 75 70 2d 3e 62 45 6e 61 62  ( !pGroup->bEnab
5910: 6c 65 64 20 29 7b 0a 20 20 20 20 73 71 6c 69 74  led ){.    sqlit
5920: 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70 65  e3_file *pSubOpe
5930: 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75 62  n = multiplexSub
5940: 4f 70 65 6e 28 70 47 72 6f 75 70 2c 20 30 2c 20  Open(pGroup, 0, 
5950: 26 72 63 2c 20 4e 55 4c 4c 29 3b 0a 20 20 20 20  &rc, NULL);.    
5960: 69 66 28 20 70 53 75 62 4f 70 65 6e 3d 3d 30 20  if( pSubOpen==0 
5970: 29 7b 0a 20 20 20 20 20 20 72 63 20 3d 20 53 51  ){.      rc = SQ
5980: 4c 49 54 45 5f 49 4f 45 52 52 5f 57 52 49 54 45  LITE_IOERR_WRITE
5990: 3b 0a 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20  ;.    }else{.   
59a0: 20 20 20 72 63 20 3d 20 70 53 75 62 4f 70 65 6e     rc = pSubOpen
59b0: 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e 78 57 72 69  ->pMethods->xWri
59c0: 74 65 28 70 53 75 62 4f 70 65 6e 2c 20 70 42 75  te(pSubOpen, pBu
59d0: 66 2c 20 69 41 6d 74 2c 20 69 4f 66 73 74 29 3b  f, iAmt, iOfst);
59e0: 0a 20 20 20 20 7d 0a 20 20 7d 65 6c 73 65 7b 0a  .    }.  }else{.
59f0: 20 20 20 20 77 68 69 6c 65 28 20 69 41 6d 74 20      while( iAmt 
5a00: 3e 20 30 20 29 7b 0a 20 20 20 20 20 20 69 6e 74  > 0 ){.      int
5a10: 20 69 20 3d 20 28 69 6e 74 29 28 69 4f 66 73 74   i = (int)(iOfst
5a20: 20 2f 20 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75   / pGroup->szChu
5a30: 6e 6b 29 3b 0a 20 20 20 20 20 20 73 71 6c 69 74  nk);.      sqlit
5a40: 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70 65  e3_file *pSubOpe
5a50: 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75 62  n = multiplexSub
5a60: 4f 70 65 6e 28 70 47 72 6f 75 70 2c 20 69 2c 20  Open(pGroup, i, 
5a70: 26 72 63 2c 20 4e 55 4c 4c 29 3b 0a 20 20 20 20  &rc, NULL);.    
5a80: 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e 20 29    if( pSubOpen )
5a90: 7b 0a 20 20 20 20 20 20 20 20 69 6e 74 20 65 78  {.        int ex
5aa0: 74 72 61 20 3d 20 28 28 69 6e 74 29 28 69 4f 66  tra = ((int)(iOf
5ab0: 73 74 20 25 20 70 47 72 6f 75 70 2d 3e 73 7a 43  st % pGroup->szC
5ac0: 68 75 6e 6b 29 20 2b 20 69 41 6d 74 29 20 2d 0a  hunk) + iAmt) -.
5ad0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5ae0: 20 20 20 20 70 47 72 6f 75 70 2d 3e 73 7a 43 68      pGroup->szCh
5af0: 75 6e 6b 3b 0a 20 20 20 20 20 20 20 20 69 66 28  unk;.        if(
5b00: 20 65 78 74 72 61 3c 30 20 29 20 65 78 74 72 61   extra<0 ) extra
5b10: 20 3d 20 30 3b 0a 20 20 20 20 20 20 20 20 69 41   = 0;.        iA
5b20: 6d 74 20 2d 3d 20 65 78 74 72 61 3b 0a 20 20 20  mt -= extra;.   
5b30: 20 20 20 20 20 72 63 20 3d 20 70 53 75 62 4f 70       rc = pSubOp
5b40: 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e 78 57  en->pMethods->xW
5b50: 72 69 74 65 28 70 53 75 62 4f 70 65 6e 2c 20 70  rite(pSubOpen, p
5b60: 42 75 66 2c 20 69 41 6d 74 2c 0a 20 20 20 20 20  Buf, iAmt,.     
5b70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5b80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5b90: 20 20 20 69 4f 66 73 74 20 25 20 70 47 72 6f 75     iOfst % pGrou
5ba0: 70 2d 3e 73 7a 43 68 75 6e 6b 29 3b 0a 20 20 20  p->szChunk);.   
5bb0: 20 20 20 20 20 69 66 28 20 72 63 21 3d 53 51 4c       if( rc!=SQL
5bc0: 49 54 45 5f 4f 4b 20 29 20 62 72 65 61 6b 3b 0a  ITE_OK ) break;.
5bd0: 20 20 20 20 20 20 20 20 70 42 75 66 20 3d 20 28          pBuf = (
5be0: 63 68 61 72 20 2a 29 70 42 75 66 20 2b 20 69 41  char *)pBuf + iA
5bf0: 6d 74 3b 0a 20 20 20 20 20 20 20 20 69 4f 66 73  mt;.        iOfs
5c00: 74 20 2b 3d 20 69 41 6d 74 3b 0a 20 20 20 20 20  t += iAmt;.     
5c10: 20 20 20 69 41 6d 74 20 3d 20 65 78 74 72 61 3b     iAmt = extra;
5c20: 0a 20 20 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20  .      }else{.  
5c30: 20 20 20 20 20 20 72 63 20 3d 20 53 51 4c 49 54        rc = SQLIT
5c40: 45 5f 49 4f 45 52 52 5f 57 52 49 54 45 3b 0a 20  E_IOERR_WRITE;. 
5c50: 20 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20 20         break;.  
5c60: 20 20 20 20 7d 0a 20 20 20 20 7d 0a 20 20 7d 0a      }.    }.  }.
5c70: 20 20 6d 75 6c 74 69 70 6c 65 78 4c 65 61 76 65    multiplexLeave
5c80: 28 29 3b 0a 20 20 72 65 74 75 72 6e 20 72 63 3b  ();.  return rc;
5c90: 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 54 72 75  .}../* Pass xTru
5ca0: 6e 63 61 74 65 20 72 65 71 75 65 73 74 73 20 74  ncate requests t
5cb0: 68 72 75 20 74 6f 20 74 68 65 20 6f 72 69 67 69  hru to the origi
5cc0: 6e 61 6c 20 56 46 53 20 61 66 74 65 72 0a 2a 2a  nal VFS after.**
5cd0: 20 64 65 74 65 72 6d 69 6e 69 6e 67 20 74 68 65   determining the
5ce0: 20 63 6f 72 72 65 63 74 20 63 68 75 6e 6b 20 74   correct chunk t
5cf0: 6f 20 6f 70 65 72 61 74 65 20 6f 6e 2e 20 20 44  o operate on.  D
5d00: 65 6c 65 74 65 20 61 6e 79 0a 2a 2a 20 63 68 75  elete any.** chu
5d10: 6e 6b 73 20 61 62 6f 76 65 20 74 68 65 20 74 72  nks above the tr
5d20: 75 6e 63 61 74 65 20 6d 61 72 6b 2e 0a 2a 2f 0a  uncate mark..*/.
5d30: 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69  static int multi
5d40: 70 6c 65 78 54 72 75 6e 63 61 74 65 28 73 71 6c  plexTruncate(sql
5d50: 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e  ite3_file *pConn
5d60: 2c 20 73 71 6c 69 74 65 33 5f 69 6e 74 36 34 20  , sqlite3_int64 
5d70: 73 69 7a 65 29 7b 0a 20 20 6d 75 6c 74 69 70 6c  size){.  multipl
5d80: 65 78 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c  exConn *p = (mul
5d90: 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e  tiplexConn*)pCon
5da0: 6e 3b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47 72  n;.  multiplexGr
5db0: 6f 75 70 20 2a 70 47 72 6f 75 70 20 3d 20 70 2d  oup *pGroup = p-
5dc0: 3e 70 47 72 6f 75 70 3b 0a 20 20 69 6e 74 20 72  >pGroup;.  int r
5dd0: 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20  c = SQLITE_OK;. 
5de0: 20 6d 75 6c 74 69 70 6c 65 78 45 6e 74 65 72 28   multiplexEnter(
5df0: 29 3b 0a 20 20 69 66 28 20 21 70 47 72 6f 75 70  );.  if( !pGroup
5e00: 2d 3e 62 45 6e 61 62 6c 65 64 20 29 7b 0a 20 20  ->bEnabled ){.  
5e10: 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a    sqlite3_file *
5e20: 70 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69  pSubOpen = multi
5e30: 70 6c 65 78 53 75 62 4f 70 65 6e 28 70 47 72 6f  plexSubOpen(pGro
5e40: 75 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c  up, 0, &rc, NULL
5e50: 29 3b 0a 20 20 20 20 69 66 28 20 70 53 75 62 4f  );.    if( pSubO
5e60: 70 65 6e 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20  pen==0 ){.      
5e70: 72 63 20 3d 20 53 51 4c 49 54 45 5f 49 4f 45 52  rc = SQLITE_IOER
5e80: 52 5f 54 52 55 4e 43 41 54 45 3b 0a 20 20 20 20  R_TRUNCATE;.    
5e90: 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 72 63 20  }else{.      rc 
5ea0: 3d 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74  = pSubOpen->pMet
5eb0: 68 6f 64 73 2d 3e 78 54 72 75 6e 63 61 74 65 28  hods->xTruncate(
5ec0: 70 53 75 62 4f 70 65 6e 2c 20 73 69 7a 65 29 3b  pSubOpen, size);
5ed0: 0a 20 20 20 20 7d 0a 20 20 7d 65 6c 73 65 7b 0a  .    }.  }else{.
5ee0: 20 20 20 20 69 6e 74 20 72 63 32 3b 0a 20 20 20      int rc2;.   
5ef0: 20 69 6e 74 20 69 3b 0a 20 20 20 20 73 71 6c 69   int i;.    sqli
5f00: 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70  te3_file *pSubOp
5f10: 65 6e 3b 0a 20 20 20 20 73 71 6c 69 74 65 33 5f  en;.    sqlite3_
5f20: 76 66 73 20 2a 70 4f 72 69 67 56 66 73 20 3d 20  vfs *pOrigVfs = 
5f30: 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67  gMultiplex.pOrig
5f40: 56 66 73 3b 20 20 20 2f 2a 20 52 65 61 6c 20 56  Vfs;   /* Real V
5f50: 46 53 20 2a 2f 0a 20 20 20 20 2f 2a 20 64 65 6c  FS */.    /* del
5f60: 65 74 65 20 74 68 65 20 63 68 75 6e 6b 73 20 61  ete the chunks a
5f70: 62 6f 76 65 20 74 68 65 20 74 72 75 6e 63 61 74  bove the truncat
5f80: 65 20 6c 69 6d 69 74 20 2a 2f 0a 20 20 20 20 66  e limit */.    f
5f90: 6f 72 28 69 3d 28 69 6e 74 29 28 73 69 7a 65 20  or(i=(int)(size 
5fa0: 2f 20 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e  / pGroup->szChun
5fb0: 6b 29 2b 31 3b 20 69 3c 70 47 72 6f 75 70 2d 3e  k)+1; i<pGroup->
5fc0: 6e 52 65 61 6c 3b 20 69 2b 2b 29 7b 0a 20 20 20  nReal; i++){.   
5fd0: 20 20 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 43     multiplexSubC
5fe0: 6c 6f 73 65 28 70 47 72 6f 75 70 2c 20 69 2c 20  lose(pGroup, i, 
5ff0: 70 4f 72 69 67 56 66 73 29 3b 0a 20 20 20 20 7d  pOrigVfs);.    }
6000: 0a 20 20 20 20 70 53 75 62 4f 70 65 6e 20 3d 20  .    pSubOpen = 
6010: 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e  multiplexSubOpen
6020: 28 70 47 72 6f 75 70 2c 20 28 69 6e 74 29 28 73  (pGroup, (int)(s
6030: 69 7a 65 2f 70 47 72 6f 75 70 2d 3e 73 7a 43 68  ize/pGroup->szCh
6040: 75 6e 6b 29 2c 20 26 72 63 32 2c 30 29 3b 0a 20  unk), &rc2,0);. 
6050: 20 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e 20     if( pSubOpen 
6060: 29 7b 0a 20 20 20 20 20 20 72 63 32 20 3d 20 70  ){.      rc2 = p
6070: 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64  SubOpen->pMethod
6080: 73 2d 3e 78 54 72 75 6e 63 61 74 65 28 70 53 75  s->xTruncate(pSu
6090: 62 4f 70 65 6e 2c 20 73 69 7a 65 20 25 20 70 47  bOpen, size % pG
60a0: 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 29 3b 0a  roup->szChunk);.
60b0: 20 20 20 20 20 20 69 66 28 20 72 63 32 21 3d 53        if( rc2!=S
60c0: 51 4c 49 54 45 5f 4f 4b 20 29 20 72 63 20 3d 20  QLITE_OK ) rc = 
60d0: 72 63 32 3b 0a 20 20 20 20 7d 65 6c 73 65 7b 0a  rc2;.    }else{.
60e0: 20 20 20 20 20 20 72 63 20 3d 20 53 51 4c 49 54        rc = SQLIT
60f0: 45 5f 49 4f 45 52 52 5f 54 52 55 4e 43 41 54 45  E_IOERR_TRUNCATE
6100: 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20 6d 75  ;.    }.  }.  mu
6110: 6c 74 69 70 6c 65 78 4c 65 61 76 65 28 29 3b 0a  ltiplexLeave();.
6120: 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a    return rc;.}..
6130: 2f 2a 20 50 61 73 73 20 78 53 79 6e 63 20 72 65  /* Pass xSync re
6140: 71 75 65 73 74 73 20 74 68 72 6f 75 67 68 20 74  quests through t
6150: 6f 20 74 68 65 20 6f 72 69 67 69 6e 61 6c 20 56  o the original V
6160: 46 53 20 77 69 74 68 6f 75 74 20 63 68 61 6e 67  FS without chang
6170: 65 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20  e.*/.static int 
6180: 6d 75 6c 74 69 70 6c 65 78 53 79 6e 63 28 73 71  multiplexSync(sq
6190: 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e  lite3_file *pCon
61a0: 6e 2c 20 69 6e 74 20 66 6c 61 67 73 29 7b 0a 20  n, int flags){. 
61b0: 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a   multiplexConn *
61c0: 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f  p = (multiplexCo
61d0: 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 6d 75 6c  nn*)pConn;.  mul
61e0: 74 69 70 6c 65 78 47 72 6f 75 70 20 2a 70 47 72  tiplexGroup *pGr
61f0: 6f 75 70 20 3d 20 70 2d 3e 70 47 72 6f 75 70 3b  oup = p->pGroup;
6200: 0a 20 20 69 6e 74 20 72 63 20 3d 20 53 51 4c 49  .  int rc = SQLI
6210: 54 45 5f 4f 4b 3b 0a 20 20 69 6e 74 20 69 3b 0a  TE_OK;.  int i;.
6220: 20 20 6d 75 6c 74 69 70 6c 65 78 45 6e 74 65 72    multiplexEnter
6230: 28 29 3b 0a 20 20 66 6f 72 28 69 3d 30 3b 20 69  ();.  for(i=0; i
6240: 3c 70 47 72 6f 75 70 2d 3e 6e 52 65 61 6c 3b 20  <pGroup->nReal; 
6250: 69 2b 2b 29 7b 0a 20 20 20 20 73 71 6c 69 74 65  i++){.    sqlite
6260: 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e  3_file *pSubOpen
6270: 20 3d 20 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c   = pGroup->aReal
6280: 5b 69 5d 2e 70 3b 0a 20 20 20 20 69 66 28 20 70  [i].p;.    if( p
6290: 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20 20  SubOpen ){.     
62a0: 20 69 6e 74 20 72 63 32 20 3d 20 70 53 75 62 4f   int rc2 = pSubO
62b0: 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e 78  pen->pMethods->x
62c0: 53 79 6e 63 28 70 53 75 62 4f 70 65 6e 2c 20 66  Sync(pSubOpen, f
62d0: 6c 61 67 73 29 3b 0a 20 20 20 20 20 20 69 66 28  lags);.      if(
62e0: 20 72 63 32 21 3d 53 51 4c 49 54 45 5f 4f 4b 20   rc2!=SQLITE_OK 
62f0: 29 20 72 63 20 3d 20 72 63 32 3b 0a 20 20 20 20  ) rc = rc2;.    
6300: 7d 0a 20 20 7d 0a 20 20 6d 75 6c 74 69 70 6c 65  }.  }.  multiple
6310: 78 4c 65 61 76 65 28 29 3b 0a 20 20 72 65 74 75  xLeave();.  retu
6320: 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 20 50 61 73  rn rc;.}../* Pas
6330: 73 20 78 46 69 6c 65 53 69 7a 65 20 72 65 71 75  s xFileSize requ
6340: 65 73 74 73 20 74 68 72 6f 75 67 68 20 74 6f 20  ests through to 
6350: 74 68 65 20 6f 72 69 67 69 6e 61 6c 20 56 46 53  the original VFS
6360: 2e 0a 2a 2a 20 41 67 67 72 65 67 61 74 65 20 74  ..** Aggregate t
6370: 68 65 20 73 69 7a 65 20 6f 66 20 61 6c 6c 20 74  he size of all t
6380: 68 65 20 63 68 75 6e 6b 73 20 62 65 66 6f 72 65  he chunks before
6390: 20 72 65 74 75 72 6e 69 6e 67 2e 0a 2a 2f 0a 73   returning..*/.s
63a0: 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70  tatic int multip
63b0: 6c 65 78 46 69 6c 65 53 69 7a 65 28 73 71 6c 69  lexFileSize(sqli
63c0: 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c  te3_file *pConn,
63d0: 20 73 71 6c 69 74 65 33 5f 69 6e 74 36 34 20 2a   sqlite3_int64 *
63e0: 70 53 69 7a 65 29 7b 0a 20 20 6d 75 6c 74 69 70  pSize){.  multip
63f0: 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75  lexConn *p = (mu
6400: 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f  ltiplexConn*)pCo
6410: 6e 6e 3b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47  nn;.  multiplexG
6420: 72 6f 75 70 20 2a 70 47 72 6f 75 70 20 3d 20 70  roup *pGroup = p
6430: 2d 3e 70 47 72 6f 75 70 3b 0a 20 20 69 6e 74 20  ->pGroup;.  int 
6440: 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a  rc = SQLITE_OK;.
6450: 20 20 69 6e 74 20 72 63 32 3b 0a 20 20 69 6e 74    int rc2;.  int
6460: 20 69 3b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 45   i;.  multiplexE
6470: 6e 74 65 72 28 29 3b 0a 20 20 69 66 28 20 21 70  nter();.  if( !p
6480: 47 72 6f 75 70 2d 3e 62 45 6e 61 62 6c 65 64 20  Group->bEnabled 
6490: 29 7b 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 66  ){.    sqlite3_f
64a0: 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20  ile *pSubOpen = 
64b0: 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e  multiplexSubOpen
64c0: 28 70 47 72 6f 75 70 2c 20 30 2c 20 26 72 63 2c  (pGroup, 0, &rc,
64d0: 20 4e 55 4c 4c 29 3b 0a 20 20 20 20 69 66 28 20   NULL);.    if( 
64e0: 70 53 75 62 4f 70 65 6e 3d 3d 30 20 29 7b 0a 20  pSubOpen==0 ){. 
64f0: 20 20 20 20 20 72 63 20 3d 20 53 51 4c 49 54 45       rc = SQLITE
6500: 5f 49 4f 45 52 52 5f 46 53 54 41 54 3b 0a 20 20  _IOERR_FSTAT;.  
6510: 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 72    }else{.      r
6520: 63 20 3d 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d  c = pSubOpen->pM
6530: 65 74 68 6f 64 73 2d 3e 78 46 69 6c 65 53 69 7a  ethods->xFileSiz
6540: 65 28 70 53 75 62 4f 70 65 6e 2c 20 70 53 69 7a  e(pSubOpen, pSiz
6550: 65 29 3b 0a 20 20 20 20 7d 0a 20 20 7d 65 6c 73  e);.    }.  }els
6560: 65 7b 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 76  e{.    sqlite3_v
6570: 66 73 20 2a 70 4f 72 69 67 56 66 73 20 3d 20 67  fs *pOrigVfs = g
6580: 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56  Multiplex.pOrigV
6590: 66 73 3b 0a 20 20 20 20 2a 70 53 69 7a 65 20 3d  fs;.    *pSize =
65a0: 20 30 3b 0a 20 20 20 20 66 6f 72 28 69 3d 30 3b   0;.    for(i=0;
65b0: 20 31 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 20 20   1; i++){.      
65c0: 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53  sqlite3_file *pS
65d0: 75 62 4f 70 65 6e 20 3d 20 30 3b 0a 20 20 20 20  ubOpen = 0;.    
65e0: 20 20 69 6e 74 20 65 78 69 73 74 73 20 3d 20 30    int exists = 0
65f0: 3b 0a 20 20 20 20 20 20 72 63 20 3d 20 6d 75 6c  ;.      rc = mul
6600: 74 69 70 6c 65 78 53 75 62 46 69 6c 65 6e 61 6d  tiplexSubFilenam
6610: 65 28 70 47 72 6f 75 70 2c 20 69 29 3b 0a 20 20  e(pGroup, i);.  
6620: 20 20 20 20 69 66 28 20 72 63 20 29 20 62 72 65      if( rc ) bre
6630: 61 6b 3b 0a 20 20 20 20 20 20 72 63 32 20 3d 20  ak;.      rc2 = 
6640: 70 4f 72 69 67 56 66 73 2d 3e 78 41 63 63 65 73  pOrigVfs->xAcces
6650: 73 28 70 4f 72 69 67 56 66 73 2c 20 70 47 72 6f  s(pOrigVfs, pGro
6660: 75 70 2d 3e 61 52 65 61 6c 5b 69 5d 2e 7a 2c 0a  up->aReal[i].z,.
6670: 20 20 20 20 20 20 20 20 20 20 53 51 4c 49 54 45            SQLITE
6680: 5f 41 43 43 45 53 53 5f 45 58 49 53 54 53 2c 20  _ACCESS_EXISTS, 
6690: 26 65 78 69 73 74 73 29 3b 0a 20 20 20 20 20 20  &exists);.      
66a0: 69 66 28 20 72 63 32 3d 3d 53 51 4c 49 54 45 5f  if( rc2==SQLITE_
66b0: 4f 4b 20 26 26 20 65 78 69 73 74 73 29 7b 0a 20  OK && exists){. 
66c0: 20 20 20 20 20 20 20 2f 2a 20 69 66 20 69 74 20         /* if it 
66d0: 65 78 69 73 74 73 2c 20 6f 70 65 6e 20 69 74 20  exists, open it 
66e0: 2a 2f 0a 20 20 20 20 20 20 20 20 70 53 75 62 4f  */.        pSubO
66f0: 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53  pen = multiplexS
6700: 75 62 4f 70 65 6e 28 70 47 72 6f 75 70 2c 20 69  ubOpen(pGroup, i
6710: 2c 20 26 72 63 2c 20 4e 55 4c 4c 29 3b 0a 20 20  , &rc, NULL);.  
6720: 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20      }else{.     
6730: 20 20 20 2f 2a 20 73 74 6f 70 20 61 74 20 66 69     /* stop at fi
6740: 72 73 74 20 22 67 61 70 22 20 2a 2f 0a 20 20 20  rst "gap" */.   
6750: 20 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20       break;.    
6760: 20 20 7d 0a 20 20 20 20 20 20 69 66 28 20 70 53    }.      if( pS
6770: 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20 20 20  ubOpen ){.      
6780: 20 20 73 71 6c 69 74 65 33 5f 69 6e 74 36 34 20    sqlite3_int64 
6790: 73 7a 3b 0a 20 20 20 20 20 20 20 20 72 63 32 20  sz;.        rc2 
67a0: 3d 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74  = pSubOpen->pMet
67b0: 68 6f 64 73 2d 3e 78 46 69 6c 65 53 69 7a 65 28  hods->xFileSize(
67c0: 70 53 75 62 4f 70 65 6e 2c 20 26 73 7a 29 3b 0a  pSubOpen, &sz);.
67d0: 20 20 20 20 20 20 20 20 69 66 28 20 72 63 32 21          if( rc2!
67e0: 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20  =SQLITE_OK ){.  
67f0: 20 20 20 20 20 20 20 20 72 63 20 3d 20 72 63 32          rc = rc2
6800: 3b 0a 20 20 20 20 20 20 20 20 7d 65 6c 73 65 7b  ;.        }else{
6810: 0a 20 20 20 20 20 20 20 20 20 20 69 66 28 20 73  .          if( s
6820: 7a 3e 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e  z>pGroup->szChun
6830: 6b 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20 20  k ){.           
6840: 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 49 4f 45   rc = SQLITE_IOE
6850: 52 52 5f 46 53 54 41 54 3b 0a 20 20 20 20 20 20  RR_FSTAT;.      
6860: 20 20 20 20 7d 0a 20 20 20 20 20 20 20 20 20 20      }.          
6870: 2a 70 53 69 7a 65 20 2b 3d 20 73 7a 3b 0a 20 20  *pSize += sz;.  
6880: 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 7d 65        }.      }e
6890: 6c 73 65 7b 0a 20 20 20 20 20 20 20 20 62 72 65  lse{.        bre
68a0: 61 6b 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20 20  ak;.      }.    
68b0: 7d 0a 20 20 7d 0a 20 20 6d 75 6c 74 69 70 6c 65  }.  }.  multiple
68c0: 78 4c 65 61 76 65 28 29 3b 0a 20 20 72 65 74 75  xLeave();.  retu
68d0: 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 20 50 61 73  rn rc;.}../* Pas
68e0: 73 20 78 4c 6f 63 6b 20 72 65 71 75 65 73 74 73  s xLock requests
68f0: 20 74 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20   through to the 
6900: 6f 72 69 67 69 6e 61 6c 20 56 46 53 20 75 6e 63  original VFS unc
6910: 68 61 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61 74 69  hanged..*/.stati
6920: 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 4c  c int multiplexL
6930: 6f 63 6b 28 73 71 6c 69 74 65 33 5f 66 69 6c 65  ock(sqlite3_file
6940: 20 2a 70 43 6f 6e 6e 2c 20 69 6e 74 20 6c 6f 63   *pConn, int loc
6950: 6b 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43  k){.  multiplexC
6960: 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70  onn *p = (multip
6970: 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a  lexConn*)pConn;.
6980: 20 20 69 6e 74 20 72 63 3b 0a 20 20 73 71 6c 69    int rc;.  sqli
6990: 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70  te3_file *pSubOp
69a0: 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75  en = multiplexSu
69b0: 62 4f 70 65 6e 28 70 2d 3e 70 47 72 6f 75 70 2c  bOpen(p->pGroup,
69c0: 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 29 3b 0a   0, &rc, NULL);.
69d0: 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e 20 29    if( pSubOpen )
69e0: 7b 0a 20 20 20 20 72 65 74 75 72 6e 20 70 53 75  {.    return pSu
69f0: 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d  bOpen->pMethods-
6a00: 3e 78 4c 6f 63 6b 28 70 53 75 62 4f 70 65 6e 2c  >xLock(pSubOpen,
6a10: 20 6c 6f 63 6b 29 3b 0a 20 20 7d 0a 20 20 72 65   lock);.  }.  re
6a20: 74 75 72 6e 20 53 51 4c 49 54 45 5f 42 55 53 59  turn SQLITE_BUSY
6a30: 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 55 6e  ;.}../* Pass xUn
6a40: 6c 6f 63 6b 20 72 65 71 75 65 73 74 73 20 74 68  lock requests th
6a50: 72 6f 75 67 68 20 74 6f 20 74 68 65 20 6f 72 69  rough to the ori
6a60: 67 69 6e 61 6c 20 56 46 53 20 75 6e 63 68 61 6e  ginal VFS unchan
6a70: 67 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69  ged..*/.static i
6a80: 6e 74 20 6d 75 6c 74 69 70 6c 65 78 55 6e 6c 6f  nt multiplexUnlo
6a90: 63 6b 28 73 71 6c 69 74 65 33 5f 66 69 6c 65 20  ck(sqlite3_file 
6aa0: 2a 70 43 6f 6e 6e 2c 20 69 6e 74 20 6c 6f 63 6b  *pConn, int lock
6ab0: 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f  ){.  multiplexCo
6ac0: 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c  nn *p = (multipl
6ad0: 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20  exConn*)pConn;. 
6ae0: 20 69 6e 74 20 72 63 3b 0a 20 20 73 71 6c 69 74   int rc;.  sqlit
6af0: 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70 65  e3_file *pSubOpe
6b00: 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75 62  n = multiplexSub
6b10: 4f 70 65 6e 28 70 2d 3e 70 47 72 6f 75 70 2c 20  Open(p->pGroup, 
6b20: 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 29 3b 0a 20  0, &rc, NULL);. 
6b30: 20 69 66 28 20 70 53 75 62 4f 70 65 6e 20 29 7b   if( pSubOpen ){
6b40: 0a 20 20 20 20 72 65 74 75 72 6e 20 70 53 75 62  .    return pSub
6b50: 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e  Open->pMethods->
6b60: 78 55 6e 6c 6f 63 6b 28 70 53 75 62 4f 70 65 6e  xUnlock(pSubOpen
6b70: 2c 20 6c 6f 63 6b 29 3b 0a 20 20 7d 0a 20 20 72  , lock);.  }.  r
6b80: 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 49 4f 45  eturn SQLITE_IOE
6b90: 52 52 5f 55 4e 4c 4f 43 4b 3b 0a 7d 0a 0a 2f 2a  RR_UNLOCK;.}../*
6ba0: 20 50 61 73 73 20 78 43 68 65 63 6b 52 65 73 65   Pass xCheckRese
6bb0: 72 76 65 64 4c 6f 63 6b 20 72 65 71 75 65 73 74  rvedLock request
6bc0: 73 20 74 68 72 6f 75 67 68 20 74 6f 20 74 68 65  s through to the
6bd0: 20 6f 72 69 67 69 6e 61 6c 20 56 46 53 20 75 6e   original VFS un
6be0: 63 68 61 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61 74  changed..*/.stat
6bf0: 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78  ic int multiplex
6c00: 43 68 65 63 6b 52 65 73 65 72 76 65 64 4c 6f 63  CheckReservedLoc
6c10: 6b 28 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a  k(sqlite3_file *
6c20: 70 43 6f 6e 6e 2c 20 69 6e 74 20 2a 70 52 65 73  pConn, int *pRes
6c30: 4f 75 74 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65  Out){.  multiple
6c40: 78 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74  xConn *p = (mult
6c50: 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e  iplexConn*)pConn
6c60: 3b 0a 20 20 69 6e 74 20 72 63 3b 0a 20 20 73 71  ;.  int rc;.  sq
6c70: 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62  lite3_file *pSub
6c80: 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78  Open = multiplex
6c90: 53 75 62 4f 70 65 6e 28 70 2d 3e 70 47 72 6f 75  SubOpen(p->pGrou
6ca0: 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 29  p, 0, &rc, NULL)
6cb0: 3b 0a 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e  ;.  if( pSubOpen
6cc0: 20 29 7b 0a 20 20 20 20 72 65 74 75 72 6e 20 70   ){.    return p
6cd0: 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64  SubOpen->pMethod
6ce0: 73 2d 3e 78 43 68 65 63 6b 52 65 73 65 72 76 65  s->xCheckReserve
6cf0: 64 4c 6f 63 6b 28 70 53 75 62 4f 70 65 6e 2c 20  dLock(pSubOpen, 
6d00: 70 52 65 73 4f 75 74 29 3b 0a 20 20 7d 0a 20 20  pResOut);.  }.  
6d10: 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 49 4f  return SQLITE_IO
6d20: 45 52 52 5f 43 48 45 43 4b 52 45 53 45 52 56 45  ERR_CHECKRESERVE
6d30: 44 4c 4f 43 4b 3b 0a 7d 0a 0a 2f 2a 20 50 61 73  DLOCK;.}../* Pas
6d40: 73 20 78 46 69 6c 65 43 6f 6e 74 72 6f 6c 20 72  s xFileControl r
6d50: 65 71 75 65 73 74 73 20 74 68 72 6f 75 67 68 20  equests through 
6d60: 74 6f 20 74 68 65 20 6f 72 69 67 69 6e 61 6c 20  to the original 
6d70: 56 46 53 20 75 6e 63 68 61 6e 67 65 64 2c 0a 2a  VFS unchanged,.*
6d80: 2a 20 65 78 63 65 70 74 20 66 6f 72 20 61 6e 79  * except for any
6d90: 20 4d 55 4c 54 49 50 4c 45 58 5f 43 54 52 4c 5f   MULTIPLEX_CTRL_
6da0: 2a 20 72 65 71 75 65 73 74 73 20 68 65 72 65 2e  * requests here.
6db0: 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 6d  .*/.static int m
6dc0: 75 6c 74 69 70 6c 65 78 46 69 6c 65 43 6f 6e 74  ultiplexFileCont
6dd0: 72 6f 6c 28 73 71 6c 69 74 65 33 5f 66 69 6c 65  rol(sqlite3_file
6de0: 20 2a 70 43 6f 6e 6e 2c 20 69 6e 74 20 6f 70 2c   *pConn, int op,
6df0: 20 76 6f 69 64 20 2a 70 41 72 67 29 7b 0a 20 20   void *pArg){.  
6e00: 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70  multiplexConn *p
6e10: 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e   = (multiplexCon
6e20: 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 6d 75 6c 74  n*)pConn;.  mult
6e30: 69 70 6c 65 78 47 72 6f 75 70 20 2a 70 47 72 6f  iplexGroup *pGro
6e40: 75 70 20 3d 20 70 2d 3e 70 47 72 6f 75 70 3b 0a  up = p->pGroup;.
6e50: 20 20 69 6e 74 20 72 63 20 3d 20 53 51 4c 49 54    int rc = SQLIT
6e60: 45 5f 45 52 52 4f 52 3b 0a 20 20 73 71 6c 69 74  E_ERROR;.  sqlit
6e70: 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70 65  e3_file *pSubOpe
6e80: 6e 3b 0a 0a 20 20 69 66 28 20 21 67 4d 75 6c 74  n;..  if( !gMult
6e90: 69 70 6c 65 78 2e 69 73 49 6e 69 74 69 61 6c 69  iplex.isInitiali
6ea0: 7a 65 64 20 29 20 72 65 74 75 72 6e 20 53 51 4c  zed ) return SQL
6eb0: 49 54 45 5f 4d 49 53 55 53 45 3b 0a 20 20 73 77  ITE_MISUSE;.  sw
6ec0: 69 74 63 68 28 20 6f 70 20 29 7b 0a 20 20 20 20  itch( op ){.    
6ed0: 63 61 73 65 20 4d 55 4c 54 49 50 4c 45 58 5f 43  case MULTIPLEX_C
6ee0: 54 52 4c 5f 45 4e 41 42 4c 45 3a 0a 20 20 20 20  TRL_ENABLE:.    
6ef0: 20 20 69 66 28 20 70 41 72 67 20 29 20 7b 0a 20    if( pArg ) {. 
6f00: 20 20 20 20 20 20 20 69 6e 74 20 62 45 6e 61 62         int bEnab
6f10: 6c 65 64 20 3d 20 2a 28 69 6e 74 20 2a 29 70 41  led = *(int *)pA
6f20: 72 67 3b 0a 20 20 20 20 20 20 20 20 70 47 72 6f  rg;.        pGro
6f30: 75 70 2d 3e 62 45 6e 61 62 6c 65 64 20 3d 20 62  up->bEnabled = b
6f40: 45 6e 61 62 6c 65 64 3b 0a 20 20 20 20 20 20 20  Enabled;.       
6f50: 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b   rc = SQLITE_OK;
6f60: 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 62  .      }.      b
6f70: 72 65 61 6b 3b 0a 20 20 20 20 63 61 73 65 20 4d  reak;.    case M
6f80: 55 4c 54 49 50 4c 45 58 5f 43 54 52 4c 5f 53 45  ULTIPLEX_CTRL_SE
6f90: 54 5f 43 48 55 4e 4b 5f 53 49 5a 45 3a 0a 20 20  T_CHUNK_SIZE:.  
6fa0: 20 20 20 20 69 66 28 20 70 41 72 67 20 29 20 7b      if( pArg ) {
6fb0: 0a 20 20 20 20 20 20 20 20 75 6e 73 69 67 6e 65  .        unsigne
6fc0: 64 20 69 6e 74 20 73 7a 43 68 75 6e 6b 20 3d 20  d int szChunk = 
6fd0: 2a 28 75 6e 73 69 67 6e 65 64 2a 29 70 41 72 67  *(unsigned*)pArg
6fe0: 3b 0a 20 20 20 20 20 20 20 20 69 66 28 20 73 7a  ;.        if( sz
6ff0: 43 68 75 6e 6b 3c 31 20 29 7b 0a 20 20 20 20 20  Chunk<1 ){.     
7000: 20 20 20 20 20 72 63 20 3d 20 53 51 4c 49 54 45       rc = SQLITE
7010: 5f 4d 49 53 55 53 45 3b 0a 20 20 20 20 20 20 20  _MISUSE;.       
7020: 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 20 20   }else{.        
7030: 20 20 2f 2a 20 52 6f 75 6e 64 20 75 70 20 74 6f    /* Round up to
7040: 20 6e 65 61 72 65 73 74 20 6d 75 6c 74 69 70 6c   nearest multipl
7050: 65 20 6f 66 20 4d 41 58 5f 50 41 47 45 5f 53 49  e of MAX_PAGE_SI
7060: 5a 45 2e 20 2a 2f 0a 20 20 20 20 20 20 20 20 20  ZE. */.         
7070: 20 73 7a 43 68 75 6e 6b 20 3d 20 28 73 7a 43 68   szChunk = (szCh
7080: 75 6e 6b 20 2b 20 28 4d 41 58 5f 50 41 47 45 5f  unk + (MAX_PAGE_
7090: 53 49 5a 45 2d 31 29 29 3b 0a 20 20 20 20 20 20  SIZE-1));.      
70a0: 20 20 20 20 73 7a 43 68 75 6e 6b 20 26 3d 20 7e      szChunk &= ~
70b0: 28 4d 41 58 5f 50 41 47 45 5f 53 49 5a 45 2d 31  (MAX_PAGE_SIZE-1
70c0: 29 3b 0a 20 20 20 20 20 20 20 20 20 20 70 47 72  );.          pGr
70d0: 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 20 3d 20 73  oup->szChunk = s
70e0: 7a 43 68 75 6e 6b 3b 0a 20 20 20 20 20 20 20 20  zChunk;.        
70f0: 20 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b    rc = SQLITE_OK
7100: 3b 0a 20 20 20 20 20 20 20 20 7d 0a 20 20 20 20  ;.        }.    
7110: 20 20 7d 0a 20 20 20 20 20 20 62 72 65 61 6b 3b    }.      break;
7120: 0a 20 20 20 20 63 61 73 65 20 4d 55 4c 54 49 50  .    case MULTIP
7130: 4c 45 58 5f 43 54 52 4c 5f 53 45 54 5f 4d 41 58  LEX_CTRL_SET_MAX
7140: 5f 43 48 55 4e 4b 53 3a 0a 20 20 20 20 20 20 72  _CHUNKS:.      r
7150: 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20  c = SQLITE_OK;. 
7160: 20 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20       break;.    
7170: 63 61 73 65 20 53 51 4c 49 54 45 5f 46 43 4e 54  case SQLITE_FCNT
7180: 4c 5f 53 49 5a 45 5f 48 49 4e 54 3a 0a 20 20 20  L_SIZE_HINT:.   
7190: 20 63 61 73 65 20 53 51 4c 49 54 45 5f 46 43 4e   case SQLITE_FCN
71a0: 54 4c 5f 43 48 55 4e 4b 5f 53 49 5a 45 3a 0a 20  TL_CHUNK_SIZE:. 
71b0: 20 20 20 20 20 2f 2a 20 6e 6f 2d 6f 70 20 74 68       /* no-op th
71c0: 65 73 65 20 2a 2f 0a 20 20 20 20 20 20 72 63 20  ese */.      rc 
71d0: 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 20  = SQLITE_OK;.   
71e0: 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 64 65     break;.    de
71f0: 66 61 75 6c 74 3a 0a 20 20 20 20 20 20 70 53 75  fault:.      pSu
7200: 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65  bOpen = multiple
7210: 78 53 75 62 4f 70 65 6e 28 70 47 72 6f 75 70 2c  xSubOpen(pGroup,
7220: 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 29 3b 0a   0, &rc, NULL);.
7230: 20 20 20 20 20 20 69 66 28 20 70 53 75 62 4f 70        if( pSubOp
7240: 65 6e 20 29 7b 0a 20 20 20 20 20 20 20 20 72 63  en ){.        rc
7250: 20 3d 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65   = pSubOpen->pMe
7260: 74 68 6f 64 73 2d 3e 78 46 69 6c 65 43 6f 6e 74  thods->xFileCont
7270: 72 6f 6c 28 70 53 75 62 4f 70 65 6e 2c 20 6f 70  rol(pSubOpen, op
7280: 2c 20 70 41 72 67 29 3b 0a 20 20 20 20 20 20 7d  , pArg);.      }
7290: 0a 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20 20  .      break;.  
72a0: 7d 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d  }.  return rc;.}
72b0: 0a 0a 2f 2a 20 50 61 73 73 20 78 53 65 63 74 6f  ../* Pass xSecto
72c0: 72 53 69 7a 65 20 72 65 71 75 65 73 74 73 20 74  rSize requests t
72d0: 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20 6f 72  hrough to the or
72e0: 69 67 69 6e 61 6c 20 56 46 53 20 75 6e 63 68 61  iginal VFS uncha
72f0: 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63 20  nged..*/.static 
7300: 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 53 65 63  int multiplexSec
7310: 74 6f 72 53 69 7a 65 28 73 71 6c 69 74 65 33 5f  torSize(sqlite3_
7320: 66 69 6c 65 20 2a 70 43 6f 6e 6e 29 7b 0a 20 20  file *pConn){.  
7330: 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70  multiplexConn *p
7340: 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e   = (multiplexCon
7350: 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 69 6e 74 20  n*)pConn;.  int 
7360: 72 63 3b 0a 20 20 73 71 6c 69 74 65 33 5f 66 69  rc;.  sqlite3_fi
7370: 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20 6d  le *pSubOpen = m
7380: 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28  ultiplexSubOpen(
7390: 70 2d 3e 70 47 72 6f 75 70 2c 20 30 2c 20 26 72  p->pGroup, 0, &r
73a0: 63 2c 20 4e 55 4c 4c 29 3b 0a 20 20 69 66 28 20  c, NULL);.  if( 
73b0: 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20  pSubOpen ){.    
73c0: 72 65 74 75 72 6e 20 70 53 75 62 4f 70 65 6e 2d  return pSubOpen-
73d0: 3e 70 4d 65 74 68 6f 64 73 2d 3e 78 53 65 63 74  >pMethods->xSect
73e0: 6f 72 53 69 7a 65 28 70 53 75 62 4f 70 65 6e 29  orSize(pSubOpen)
73f0: 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20 44  ;.  }.  return D
7400: 45 46 41 55 4c 54 5f 53 45 43 54 4f 52 5f 53 49  EFAULT_SECTOR_SI
7410: 5a 45 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78  ZE;.}../* Pass x
7420: 44 65 76 69 63 65 43 68 61 72 61 63 74 65 72 69  DeviceCharacteri
7430: 73 74 69 63 73 20 72 65 71 75 65 73 74 73 20 74  stics requests t
7440: 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20 6f 72  hrough to the or
7450: 69 67 69 6e 61 6c 20 56 46 53 20 75 6e 63 68 61  iginal VFS uncha
7460: 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63 20  nged..*/.static 
7470: 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 44 65 76  int multiplexDev
7480: 69 63 65 43 68 61 72 61 63 74 65 72 69 73 74 69  iceCharacteristi
7490: 63 73 28 73 71 6c 69 74 65 33 5f 66 69 6c 65 20  cs(sqlite3_file 
74a0: 2a 70 43 6f 6e 6e 29 7b 0a 20 20 6d 75 6c 74 69  *pConn){.  multi
74b0: 70 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d  plexConn *p = (m
74c0: 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43  ultiplexConn*)pC
74d0: 6f 6e 6e 3b 0a 20 20 69 6e 74 20 72 63 3b 0a 20  onn;.  int rc;. 
74e0: 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70   sqlite3_file *p
74f0: 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70  SubOpen = multip
7500: 6c 65 78 53 75 62 4f 70 65 6e 28 70 2d 3e 70 47  lexSubOpen(p->pG
7510: 72 6f 75 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55  roup, 0, &rc, NU
7520: 4c 4c 29 3b 0a 20 20 69 66 28 20 70 53 75 62 4f  LL);.  if( pSubO
7530: 70 65 6e 20 29 7b 0a 20 20 20 20 72 65 74 75 72  pen ){.    retur
7540: 6e 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74  n pSubOpen->pMet
7550: 68 6f 64 73 2d 3e 78 44 65 76 69 63 65 43 68 61  hods->xDeviceCha
7560: 72 61 63 74 65 72 69 73 74 69 63 73 28 70 53 75  racteristics(pSu
7570: 62 4f 70 65 6e 29 3b 0a 20 20 7d 0a 20 20 72 65  bOpen);.  }.  re
7580: 74 75 72 6e 20 30 3b 0a 7d 0a 0a 2f 2a 20 50 61  turn 0;.}../* Pa
7590: 73 73 20 78 53 68 6d 4d 61 70 20 72 65 71 75 65  ss xShmMap reque
75a0: 73 74 73 20 74 68 72 6f 75 67 68 20 74 6f 20 74  sts through to t
75b0: 68 65 20 6f 72 69 67 69 6e 61 6c 20 56 46 53 20  he original VFS 
75c0: 75 6e 63 68 61 6e 67 65 64 2e 0a 2a 2f 0a 73 74  unchanged..*/.st
75d0: 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c  atic int multipl
75e0: 65 78 53 68 6d 4d 61 70 28 0a 20 20 73 71 6c 69  exShmMap(.  sqli
75f0: 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c  te3_file *pConn,
7600: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 48              /* H
7610: 61 6e 64 6c 65 20 6f 70 65 6e 20 6f 6e 20 64 61  andle open on da
7620: 74 61 62 61 73 65 20 66 69 6c 65 20 2a 2f 0a 20  tabase file */. 
7630: 20 69 6e 74 20 69 52 65 67 69 6f 6e 2c 20 20 20   int iRegion,   
7640: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7650: 20 2f 2a 20 52 65 67 69 6f 6e 20 74 6f 20 72 65   /* Region to re
7660: 74 72 69 65 76 65 20 2a 2f 0a 20 20 69 6e 74 20  trieve */.  int 
7670: 73 7a 52 65 67 69 6f 6e 2c 20 20 20 20 20 20 20  szRegion,       
7680: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 53              /* S
7690: 69 7a 65 20 6f 66 20 72 65 67 69 6f 6e 73 20 2a  ize of regions *
76a0: 2f 0a 20 20 69 6e 74 20 62 45 78 74 65 6e 64 2c  /.  int bExtend,
76b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
76c0: 20 20 20 20 2f 2a 20 54 72 75 65 20 74 6f 20 65      /* True to e
76d0: 78 74 65 6e 64 20 66 69 6c 65 20 69 66 20 6e 65  xtend file if ne
76e0: 63 65 73 73 61 72 79 20 2a 2f 0a 20 20 76 6f 69  cessary */.  voi
76f0: 64 20 76 6f 6c 61 74 69 6c 65 20 2a 2a 70 70 20  d volatile **pp 
7700: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
7710: 4f 55 54 3a 20 4d 61 70 70 65 64 20 6d 65 6d 6f  OUT: Mapped memo
7720: 72 79 20 2a 2f 0a 29 7b 0a 20 20 6d 75 6c 74 69  ry */.){.  multi
7730: 70 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d  plexConn *p = (m
7740: 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43  ultiplexConn*)pC
7750: 6f 6e 6e 3b 0a 20 20 69 6e 74 20 72 63 3b 0a 20  onn;.  int rc;. 
7760: 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70   sqlite3_file *p
7770: 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70  SubOpen = multip
7780: 6c 65 78 53 75 62 4f 70 65 6e 28 70 2d 3e 70 47  lexSubOpen(p->pG
7790: 72 6f 75 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55  roup, 0, &rc, NU
77a0: 4c 4c 29 3b 0a 20 20 69 66 28 20 70 53 75 62 4f  LL);.  if( pSubO
77b0: 70 65 6e 20 29 7b 0a 20 20 20 20 72 65 74 75 72  pen ){.    retur
77c0: 6e 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74  n pSubOpen->pMet
77d0: 68 6f 64 73 2d 3e 78 53 68 6d 4d 61 70 28 70 53  hods->xShmMap(pS
77e0: 75 62 4f 70 65 6e 2c 20 69 52 65 67 69 6f 6e 2c  ubOpen, iRegion,
77f0: 20 73 7a 52 65 67 69 6f 6e 2c 20 62 45 78 74 65   szRegion, bExte
7800: 6e 64 2c 70 70 29 3b 0a 20 20 7d 0a 20 20 72 65  nd,pp);.  }.  re
7810: 74 75 72 6e 20 53 51 4c 49 54 45 5f 49 4f 45 52  turn SQLITE_IOER
7820: 52 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 53  R;.}../* Pass xS
7830: 68 6d 4c 6f 63 6b 20 72 65 71 75 65 73 74 73 20  hmLock requests 
7840: 74 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20 6f  through to the o
7850: 72 69 67 69 6e 61 6c 20 56 46 53 20 75 6e 63 68  riginal VFS unch
7860: 61 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63  anged..*/.static
7870: 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 53 68   int multiplexSh
7880: 6d 4c 6f 63 6b 28 0a 20 20 73 71 6c 69 74 65 33  mLock(.  sqlite3
7890: 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c 20 20 20  _file *pConn,   
78a0: 20 20 20 20 2f 2a 20 44 61 74 61 62 61 73 65 20      /* Database 
78b0: 66 69 6c 65 20 68 6f 6c 64 69 6e 67 20 74 68 65  file holding the
78c0: 20 73 68 61 72 65 64 20 6d 65 6d 6f 72 79 20 2a   shared memory *
78d0: 2f 0a 20 20 69 6e 74 20 6f 66 73 74 2c 20 20 20  /.  int ofst,   
78e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
78f0: 2a 20 46 69 72 73 74 20 6c 6f 63 6b 20 74 6f 20  * First lock to 
7900: 61 63 71 75 69 72 65 20 6f 72 20 72 65 6c 65 61  acquire or relea
7910: 73 65 20 2a 2f 0a 20 20 69 6e 74 20 6e 2c 20 20  se */.  int n,  
7920: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7930: 20 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f 66 20     /* Number of 
7940: 6c 6f 63 6b 73 20 74 6f 20 61 63 71 75 69 72 65  locks to acquire
7950: 20 6f 72 20 72 65 6c 65 61 73 65 20 2a 2f 0a 20   or release */. 
7960: 20 69 6e 74 20 66 6c 61 67 73 20 20 20 20 20 20   int flags      
7970: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 57              /* W
7980: 68 61 74 20 74 6f 20 64 6f 20 77 69 74 68 20 74  hat to do with t
7990: 68 65 20 6c 6f 63 6b 20 2a 2f 0a 29 7b 0a 20 20  he lock */.){.  
79a0: 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70  multiplexConn *p
79b0: 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e   = (multiplexCon
79c0: 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 69 6e 74 20  n*)pConn;.  int 
79d0: 72 63 3b 0a 20 20 73 71 6c 69 74 65 33 5f 66 69  rc;.  sqlite3_fi
79e0: 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20 6d  le *pSubOpen = m
79f0: 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28  ultiplexSubOpen(
7a00: 70 2d 3e 70 47 72 6f 75 70 2c 20 30 2c 20 26 72  p->pGroup, 0, &r
7a10: 63 2c 20 4e 55 4c 4c 29 3b 0a 20 20 69 66 28 20  c, NULL);.  if( 
7a20: 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20  pSubOpen ){.    
7a30: 72 65 74 75 72 6e 20 70 53 75 62 4f 70 65 6e 2d  return pSubOpen-
7a40: 3e 70 4d 65 74 68 6f 64 73 2d 3e 78 53 68 6d 4c  >pMethods->xShmL
7a50: 6f 63 6b 28 70 53 75 62 4f 70 65 6e 2c 20 6f 66  ock(pSubOpen, of
7a60: 73 74 2c 20 6e 2c 20 66 6c 61 67 73 29 3b 0a 20  st, n, flags);. 
7a70: 20 7d 0a 20 20 72 65 74 75 72 6e 20 53 51 4c 49   }.  return SQLI
7a80: 54 45 5f 42 55 53 59 3b 0a 7d 0a 0a 2f 2a 20 50  TE_BUSY;.}../* P
7a90: 61 73 73 20 78 53 68 6d 42 61 72 72 69 65 72 20  ass xShmBarrier 
7aa0: 72 65 71 75 65 73 74 73 20 74 68 72 6f 75 67 68  requests through
7ab0: 20 74 6f 20 74 68 65 20 6f 72 69 67 69 6e 61 6c   to the original
7ac0: 20 56 46 53 20 75 6e 63 68 61 6e 67 65 64 2e 0a   VFS unchanged..
7ad0: 2a 2f 0a 73 74 61 74 69 63 20 76 6f 69 64 20 6d  */.static void m
7ae0: 75 6c 74 69 70 6c 65 78 53 68 6d 42 61 72 72 69  ultiplexShmBarri
7af0: 65 72 28 73 71 6c 69 74 65 33 5f 66 69 6c 65 20  er(sqlite3_file 
7b00: 2a 70 43 6f 6e 6e 29 7b 0a 20 20 6d 75 6c 74 69  *pConn){.  multi
7b10: 70 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d  plexConn *p = (m
7b20: 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43  ultiplexConn*)pC
7b30: 6f 6e 6e 3b 0a 20 20 69 6e 74 20 72 63 3b 0a 20  onn;.  int rc;. 
7b40: 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70   sqlite3_file *p
7b50: 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70  SubOpen = multip
7b60: 6c 65 78 53 75 62 4f 70 65 6e 28 70 2d 3e 70 47  lexSubOpen(p->pG
7b70: 72 6f 75 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55  roup, 0, &rc, NU
7b80: 4c 4c 29 3b 0a 20 20 69 66 28 20 70 53 75 62 4f  LL);.  if( pSubO
7b90: 70 65 6e 20 29 7b 0a 20 20 20 20 70 53 75 62 4f  pen ){.    pSubO
7ba0: 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e 78  pen->pMethods->x
7bb0: 53 68 6d 42 61 72 72 69 65 72 28 70 53 75 62 4f  ShmBarrier(pSubO
7bc0: 70 65 6e 29 3b 0a 20 20 7d 0a 7d 0a 0a 2f 2a 20  pen);.  }.}../* 
7bd0: 50 61 73 73 20 78 53 68 6d 55 6e 6d 61 70 20 72  Pass xShmUnmap r
7be0: 65 71 75 65 73 74 73 20 74 68 72 6f 75 67 68 20  equests through 
7bf0: 74 6f 20 74 68 65 20 6f 72 69 67 69 6e 61 6c 20  to the original 
7c00: 56 46 53 20 75 6e 63 68 61 6e 67 65 64 2e 0a 2a  VFS unchanged..*
7c10: 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c  /.static int mul
7c20: 74 69 70 6c 65 78 53 68 6d 55 6e 6d 61 70 28 73  tiplexShmUnmap(s
7c30: 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f  qlite3_file *pCo
7c40: 6e 6e 2c 20 69 6e 74 20 64 65 6c 65 74 65 46 6c  nn, int deleteFl
7c50: 61 67 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78  ag){.  multiplex
7c60: 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69  Conn *p = (multi
7c70: 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b  plexConn*)pConn;
7c80: 0a 20 20 69 6e 74 20 72 63 3b 0a 20 20 73 71 6c  .  int rc;.  sql
7c90: 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f  ite3_file *pSubO
7ca0: 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53  pen = multiplexS
7cb0: 75 62 4f 70 65 6e 28 70 2d 3e 70 47 72 6f 75 70  ubOpen(p->pGroup
7cc0: 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 29 3b  , 0, &rc, NULL);
7cd0: 0a 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e 20  .  if( pSubOpen 
7ce0: 29 7b 0a 20 20 20 20 72 65 74 75 72 6e 20 70 53  ){.    return pS
7cf0: 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73  ubOpen->pMethods
7d00: 2d 3e 78 53 68 6d 55 6e 6d 61 70 28 70 53 75 62  ->xShmUnmap(pSub
7d10: 4f 70 65 6e 2c 20 64 65 6c 65 74 65 46 6c 61 67  Open, deleteFlag
7d20: 29 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20  );.  }.  return 
7d30: 53 51 4c 49 54 45 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a  SQLITE_OK;.}../*
7d40: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
7d50: 2a 2a 2a 2a 2a 2a 2a 2a 2a 20 50 75 62 6c 69 63  ********* Public
7d60: 20 49 6e 74 65 72 66 61 63 65 73 20 2a 2a 2a 2a   Interfaces ****
7d70: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
7d80: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2f 0a 2f 2a 0a 2a 2a  *********/./*.**
7d90: 20 43 41 50 49 3a 20 49 6e 69 74 69 61 6c 69 7a   CAPI: Initializ
7da0: 65 20 74 68 65 20 6d 75 6c 74 69 70 6c 65 78 20  e the multiplex 
7db0: 56 46 53 20 73 68 69 6d 20 2d 20 73 71 6c 69 74  VFS shim - sqlit
7dc0: 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 69 6e 69  e3_multiplex_ini
7dd0: 74 69 61 6c 69 7a 65 28 29 0a 2a 2a 0a 2a 2a 20  tialize().**.** 
7de0: 55 73 65 20 74 68 65 20 56 46 53 20 6e 61 6d 65  Use the VFS name
7df0: 64 20 7a 4f 72 69 67 56 66 73 4e 61 6d 65 20 61  d zOrigVfsName a
7e00: 73 20 74 68 65 20 56 46 53 20 74 68 61 74 20 64  s the VFS that d
7e10: 6f 65 73 20 74 68 65 20 61 63 74 75 61 6c 20 77  oes the actual w
7e20: 6f 72 6b 2e 20 20 0a 2a 2a 20 55 73 65 20 74 68  ork.  .** Use th
7e30: 65 20 64 65 66 61 75 6c 74 20 69 66 20 7a 4f 72  e default if zOr
7e40: 69 67 56 66 73 4e 61 6d 65 3d 3d 4e 55 4c 4c 2e  igVfsName==NULL.
7e50: 20 20 0a 2a 2a 0a 2a 2a 20 54 68 65 20 6d 75 6c    .**.** The mul
7e60: 74 69 70 6c 65 78 20 56 46 53 20 73 68 69 6d 20  tiplex VFS shim 
7e70: 69 73 20 6e 61 6d 65 64 20 22 6d 75 6c 74 69 70  is named "multip
7e80: 6c 65 78 22 2e 20 20 49 74 20 77 69 6c 6c 20 62  lex".  It will b
7e90: 65 63 6f 6d 65 20 74 68 65 20 64 65 66 61 75 6c  ecome the defaul
7ea0: 74 0a 2a 2a 20 56 46 53 20 69 66 20 6d 61 6b 65  t.** VFS if make
7eb0: 44 65 66 61 75 6c 74 20 69 73 20 6e 6f 6e 2d 7a  Default is non-z
7ec0: 65 72 6f 2e 0a 2a 2a 0a 2a 2a 20 54 48 49 53 20  ero..**.** THIS 
7ed0: 52 4f 55 54 49 4e 45 20 49 53 20 4e 4f 54 20 54  ROUTINE IS NOT T
7ee0: 48 52 45 41 44 53 41 46 45 2e 20 20 43 61 6c 6c  HREADSAFE.  Call
7ef0: 20 74 68 69 73 20 72 6f 75 74 69 6e 65 20 65 78   this routine ex
7f00: 61 63 74 6c 79 20 6f 6e 63 65 0a 2a 2a 20 64 75  actly once.** du
7f10: 72 69 6e 67 20 73 74 61 72 74 2d 75 70 2e 0a 2a  ring start-up..*
7f20: 2f 0a 69 6e 74 20 73 71 6c 69 74 65 33 5f 6d 75  /.int sqlite3_mu
7f30: 6c 74 69 70 6c 65 78 5f 69 6e 69 74 69 61 6c 69  ltiplex_initiali
7f40: 7a 65 28 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a  ze(const char *z
7f50: 4f 72 69 67 56 66 73 4e 61 6d 65 2c 20 69 6e 74  OrigVfsName, int
7f60: 20 6d 61 6b 65 44 65 66 61 75 6c 74 29 7b 0a 20   makeDefault){. 
7f70: 20 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 70 4f   sqlite3_vfs *pO
7f80: 72 69 67 56 66 73 3b 0a 20 20 69 66 28 20 67 4d  rigVfs;.  if( gM
7f90: 75 6c 74 69 70 6c 65 78 2e 69 73 49 6e 69 74 69  ultiplex.isIniti
7fa0: 61 6c 69 7a 65 64 20 29 20 72 65 74 75 72 6e 20  alized ) return 
7fb0: 53 51 4c 49 54 45 5f 4d 49 53 55 53 45 3b 0a 20  SQLITE_MISUSE;. 
7fc0: 20 70 4f 72 69 67 56 66 73 20 3d 20 73 71 6c 69   pOrigVfs = sqli
7fd0: 74 65 33 5f 76 66 73 5f 66 69 6e 64 28 7a 4f 72  te3_vfs_find(zOr
7fe0: 69 67 56 66 73 4e 61 6d 65 29 3b 0a 20 20 69 66  igVfsName);.  if
7ff0: 28 20 70 4f 72 69 67 56 66 73 3d 3d 30 20 29 20  ( pOrigVfs==0 ) 
8000: 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 45 52  return SQLITE_ER
8010: 52 4f 52 3b 0a 20 20 61 73 73 65 72 74 28 20 70  ROR;.  assert( p
8020: 4f 72 69 67 56 66 73 21 3d 26 67 4d 75 6c 74 69  OrigVfs!=&gMulti
8030: 70 6c 65 78 2e 73 54 68 69 73 56 66 73 20 29 3b  plex.sThisVfs );
8040: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4d  .  gMultiplex.pM
8050: 75 74 65 78 20 3d 20 73 71 6c 69 74 65 33 5f 6d  utex = sqlite3_m
8060: 75 74 65 78 5f 61 6c 6c 6f 63 28 53 51 4c 49 54  utex_alloc(SQLIT
8070: 45 5f 4d 55 54 45 58 5f 46 41 53 54 29 3b 0a 20  E_MUTEX_FAST);. 
8080: 20 69 66 28 20 21 67 4d 75 6c 74 69 70 6c 65 78   if( !gMultiplex
8090: 2e 70 4d 75 74 65 78 20 29 7b 0a 20 20 20 20 72  .pMutex ){.    r
80a0: 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4e 4f 4d  eturn SQLITE_NOM
80b0: 45 4d 3b 0a 20 20 7d 0a 20 20 67 4d 75 6c 74 69  EM;.  }.  gMulti
80c0: 70 6c 65 78 2e 70 47 72 6f 75 70 73 20 3d 20 4e  plex.pGroups = N
80d0: 55 4c 4c 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65  ULL;.  gMultiple
80e0: 78 2e 69 73 49 6e 69 74 69 61 6c 69 7a 65 64 20  x.isInitialized 
80f0: 3d 20 31 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65  = 1;.  gMultiple
8100: 78 2e 70 4f 72 69 67 56 66 73 20 3d 20 70 4f 72  x.pOrigVfs = pOr
8110: 69 67 56 66 73 3b 0a 20 20 67 4d 75 6c 74 69 70  igVfs;.  gMultip
8120: 6c 65 78 2e 73 54 68 69 73 56 66 73 20 3d 20 2a  lex.sThisVfs = *
8130: 70 4f 72 69 67 56 66 73 3b 0a 20 20 67 4d 75 6c  pOrigVfs;.  gMul
8140: 74 69 70 6c 65 78 2e 73 54 68 69 73 56 66 73 2e  tiplex.sThisVfs.
8150: 73 7a 4f 73 46 69 6c 65 20 2b 3d 20 73 69 7a 65  szOsFile += size
8160: 6f 66 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e  of(multiplexConn
8170: 29 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e  );.  gMultiplex.
8180: 73 54 68 69 73 56 66 73 2e 7a 4e 61 6d 65 20 3d  sThisVfs.zName =
8190: 20 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45   SQLITE_MULTIPLE
81a0: 58 5f 56 46 53 5f 4e 41 4d 45 3b 0a 20 20 67 4d  X_VFS_NAME;.  gM
81b0: 75 6c 74 69 70 6c 65 78 2e 73 54 68 69 73 56 66  ultiplex.sThisVf
81c0: 73 2e 78 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70  s.xOpen = multip
81d0: 6c 65 78 4f 70 65 6e 3b 0a 20 20 67 4d 75 6c 74  lexOpen;.  gMult
81e0: 69 70 6c 65 78 2e 73 54 68 69 73 56 66 73 2e 78  iplex.sThisVfs.x
81f0: 44 65 6c 65 74 65 20 3d 20 6d 75 6c 74 69 70 6c  Delete = multipl
8200: 65 78 44 65 6c 65 74 65 3b 0a 20 20 67 4d 75 6c  exDelete;.  gMul
8210: 74 69 70 6c 65 78 2e 73 54 68 69 73 56 66 73 2e  tiplex.sThisVfs.
8220: 78 41 63 63 65 73 73 20 3d 20 6d 75 6c 74 69 70  xAccess = multip
8230: 6c 65 78 41 63 63 65 73 73 3b 0a 20 20 67 4d 75  lexAccess;.  gMu
8240: 6c 74 69 70 6c 65 78 2e 73 54 68 69 73 56 66 73  ltiplex.sThisVfs
8250: 2e 78 46 75 6c 6c 50 61 74 68 6e 61 6d 65 20 3d  .xFullPathname =
8260: 20 6d 75 6c 74 69 70 6c 65 78 46 75 6c 6c 50 61   multiplexFullPa
8270: 74 68 6e 61 6d 65 3b 0a 20 20 67 4d 75 6c 74 69  thname;.  gMulti
8280: 70 6c 65 78 2e 73 54 68 69 73 56 66 73 2e 78 44  plex.sThisVfs.xD
8290: 6c 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65  lOpen = multiple
82a0: 78 44 6c 4f 70 65 6e 3b 0a 20 20 67 4d 75 6c 74  xDlOpen;.  gMult
82b0: 69 70 6c 65 78 2e 73 54 68 69 73 56 66 73 2e 78  iplex.sThisVfs.x
82c0: 44 6c 45 72 72 6f 72 20 3d 20 6d 75 6c 74 69 70  DlError = multip
82d0: 6c 65 78 44 6c 45 72 72 6f 72 3b 0a 20 20 67 4d  lexDlError;.  gM
82e0: 75 6c 74 69 70 6c 65 78 2e 73 54 68 69 73 56 66  ultiplex.sThisVf
82f0: 73 2e 78 44 6c 53 79 6d 20 3d 20 6d 75 6c 74 69  s.xDlSym = multi
8300: 70 6c 65 78 44 6c 53 79 6d 3b 0a 20 20 67 4d 75  plexDlSym;.  gMu
8310: 6c 74 69 70 6c 65 78 2e 73 54 68 69 73 56 66 73  ltiplex.sThisVfs
8320: 2e 78 44 6c 43 6c 6f 73 65 20 3d 20 6d 75 6c 74  .xDlClose = mult
8330: 69 70 6c 65 78 44 6c 43 6c 6f 73 65 3b 0a 20 20  iplexDlClose;.  
8340: 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54 68 69 73  gMultiplex.sThis
8350: 56 66 73 2e 78 52 61 6e 64 6f 6d 6e 65 73 73 20  Vfs.xRandomness 
8360: 3d 20 6d 75 6c 74 69 70 6c 65 78 52 61 6e 64 6f  = multiplexRando
8370: 6d 6e 65 73 73 3b 0a 20 20 67 4d 75 6c 74 69 70  mness;.  gMultip
8380: 6c 65 78 2e 73 54 68 69 73 56 66 73 2e 78 53 6c  lex.sThisVfs.xSl
8390: 65 65 70 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53  eep = multiplexS
83a0: 6c 65 65 70 3b 0a 20 20 67 4d 75 6c 74 69 70 6c  leep;.  gMultipl
83b0: 65 78 2e 73 54 68 69 73 56 66 73 2e 78 43 75 72  ex.sThisVfs.xCur
83c0: 72 65 6e 74 54 69 6d 65 20 3d 20 6d 75 6c 74 69  rentTime = multi
83d0: 70 6c 65 78 43 75 72 72 65 6e 74 54 69 6d 65 3b  plexCurrentTime;
83e0: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54  .  gMultiplex.sT
83f0: 68 69 73 56 66 73 2e 78 47 65 74 4c 61 73 74 45  hisVfs.xGetLastE
8400: 72 72 6f 72 20 3d 20 6d 75 6c 74 69 70 6c 65 78  rror = multiplex
8410: 47 65 74 4c 61 73 74 45 72 72 6f 72 3b 0a 20 20  GetLastError;.  
8420: 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54 68 69 73  gMultiplex.sThis
8430: 56 66 73 2e 78 43 75 72 72 65 6e 74 54 69 6d 65  Vfs.xCurrentTime
8440: 49 6e 74 36 34 20 3d 20 6d 75 6c 74 69 70 6c 65  Int64 = multiple
8450: 78 43 75 72 72 65 6e 74 54 69 6d 65 49 6e 74 36  xCurrentTimeInt6
8460: 34 3b 0a 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78  4;..  gMultiplex
8470: 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31 2e 69 56  .sIoMethodsV1.iV
8480: 65 72 73 69 6f 6e 20 3d 20 31 3b 0a 20 20 67 4d  ersion = 1;.  gM
8490: 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68  ultiplex.sIoMeth
84a0: 6f 64 73 56 31 2e 78 43 6c 6f 73 65 20 3d 20 6d  odsV1.xClose = m
84b0: 75 6c 74 69 70 6c 65 78 43 6c 6f 73 65 3b 0a 20  ultiplexClose;. 
84c0: 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d   gMultiplex.sIoM
84d0: 65 74 68 6f 64 73 56 31 2e 78 52 65 61 64 20 3d  ethodsV1.xRead =
84e0: 20 6d 75 6c 74 69 70 6c 65 78 52 65 61 64 3b 0a   multiplexRead;.
84f0: 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f    gMultiplex.sIo
8500: 4d 65 74 68 6f 64 73 56 31 2e 78 57 72 69 74 65  MethodsV1.xWrite
8510: 20 3d 20 6d 75 6c 74 69 70 6c 65 78 57 72 69 74   = multiplexWrit
8520: 65 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e  e;.  gMultiplex.
8530: 73 49 6f 4d 65 74 68 6f 64 73 56 31 2e 78 54 72  sIoMethodsV1.xTr
8540: 75 6e 63 61 74 65 20 3d 20 6d 75 6c 74 69 70 6c  uncate = multipl
8550: 65 78 54 72 75 6e 63 61 74 65 3b 0a 20 20 67 4d  exTruncate;.  gM
8560: 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68  ultiplex.sIoMeth
8570: 6f 64 73 56 31 2e 78 53 79 6e 63 20 3d 20 6d 75  odsV1.xSync = mu
8580: 6c 74 69 70 6c 65 78 53 79 6e 63 3b 0a 20 20 67  ltiplexSync;.  g
8590: 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74  Multiplex.sIoMet
85a0: 68 6f 64 73 56 31 2e 78 46 69 6c 65 53 69 7a 65  hodsV1.xFileSize
85b0: 20 3d 20 6d 75 6c 74 69 70 6c 65 78 46 69 6c 65   = multiplexFile
85c0: 53 69 7a 65 3b 0a 20 20 67 4d 75 6c 74 69 70 6c  Size;.  gMultipl
85d0: 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31 2e  ex.sIoMethodsV1.
85e0: 78 4c 6f 63 6b 20 3d 20 6d 75 6c 74 69 70 6c 65  xLock = multiple
85f0: 78 4c 6f 63 6b 3b 0a 20 20 67 4d 75 6c 74 69 70  xLock;.  gMultip
8600: 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31  lex.sIoMethodsV1
8610: 2e 78 55 6e 6c 6f 63 6b 20 3d 20 6d 75 6c 74 69  .xUnlock = multi
8620: 70 6c 65 78 55 6e 6c 6f 63 6b 3b 0a 20 20 67 4d  plexUnlock;.  gM
8630: 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68  ultiplex.sIoMeth
8640: 6f 64 73 56 31 2e 78 43 68 65 63 6b 52 65 73 65  odsV1.xCheckRese
8650: 72 76 65 64 4c 6f 63 6b 20 3d 20 6d 75 6c 74 69  rvedLock = multi
8660: 70 6c 65 78 43 68 65 63 6b 52 65 73 65 72 76 65  plexCheckReserve
8670: 64 4c 6f 63 6b 3b 0a 20 20 67 4d 75 6c 74 69 70  dLock;.  gMultip
8680: 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31  lex.sIoMethodsV1
8690: 2e 78 46 69 6c 65 43 6f 6e 74 72 6f 6c 20 3d 20  .xFileControl = 
86a0: 6d 75 6c 74 69 70 6c 65 78 46 69 6c 65 43 6f 6e  multiplexFileCon
86b0: 74 72 6f 6c 3b 0a 20 20 67 4d 75 6c 74 69 70 6c  trol;.  gMultipl
86c0: 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31 2e  ex.sIoMethodsV1.
86d0: 78 53 65 63 74 6f 72 53 69 7a 65 20 3d 20 6d 75  xSectorSize = mu
86e0: 6c 74 69 70 6c 65 78 53 65 63 74 6f 72 53 69 7a  ltiplexSectorSiz
86f0: 65 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e  e;.  gMultiplex.
8700: 73 49 6f 4d 65 74 68 6f 64 73 56 31 2e 78 44 65  sIoMethodsV1.xDe
8710: 76 69 63 65 43 68 61 72 61 63 74 65 72 69 73 74  viceCharacterist
8720: 69 63 73 20 3d 0a 20 20 20 20 20 20 20 20 20 20  ics =.          
8730: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8740: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8750: 20 20 6d 75 6c 74 69 70 6c 65 78 44 65 76 69 63    multiplexDevic
8760: 65 43 68 61 72 61 63 74 65 72 69 73 74 69 63 73  eCharacteristics
8770: 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73  ;.  gMultiplex.s
8780: 49 6f 4d 65 74 68 6f 64 73 56 32 20 3d 20 67 4d  IoMethodsV2 = gM
8790: 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68  ultiplex.sIoMeth
87a0: 6f 64 73 56 31 3b 0a 20 20 67 4d 75 6c 74 69 70  odsV1;.  gMultip
87b0: 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 32  lex.sIoMethodsV2
87c0: 2e 69 56 65 72 73 69 6f 6e 20 3d 20 32 3b 0a 20  .iVersion = 2;. 
87d0: 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d   gMultiplex.sIoM
87e0: 65 74 68 6f 64 73 56 32 2e 78 53 68 6d 4d 61 70  ethodsV2.xShmMap
87f0: 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 68 6d 4d   = multiplexShmM
8800: 61 70 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78  ap;.  gMultiplex
8810: 2e 73 49 6f 4d 65 74 68 6f 64 73 56 32 2e 78 53  .sIoMethodsV2.xS
8820: 68 6d 4c 6f 63 6b 20 3d 20 6d 75 6c 74 69 70 6c  hmLock = multipl
8830: 65 78 53 68 6d 4c 6f 63 6b 3b 0a 20 20 67 4d 75  exShmLock;.  gMu
8840: 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f  ltiplex.sIoMetho
8850: 64 73 56 32 2e 78 53 68 6d 42 61 72 72 69 65 72  dsV2.xShmBarrier
8860: 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 68 6d 42   = multiplexShmB
8870: 61 72 72 69 65 72 3b 0a 20 20 67 4d 75 6c 74 69  arrier;.  gMulti
8880: 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56  plex.sIoMethodsV
8890: 32 2e 78 53 68 6d 55 6e 6d 61 70 20 3d 20 6d 75  2.xShmUnmap = mu
88a0: 6c 74 69 70 6c 65 78 53 68 6d 55 6e 6d 61 70 3b  ltiplexShmUnmap;
88b0: 0a 20 20 73 71 6c 69 74 65 33 5f 76 66 73 5f 72  .  sqlite3_vfs_r
88c0: 65 67 69 73 74 65 72 28 26 67 4d 75 6c 74 69 70  egister(&gMultip
88d0: 6c 65 78 2e 73 54 68 69 73 56 66 73 2c 20 6d 61  lex.sThisVfs, ma
88e0: 6b 65 44 65 66 61 75 6c 74 29 3b 0a 0a 20 20 73  keDefault);..  s
88f0: 71 6c 69 74 65 33 5f 61 75 74 6f 5f 65 78 74 65  qlite3_auto_exte
8900: 6e 73 69 6f 6e 28 28 76 6f 69 64 2a 29 6d 75 6c  nsion((void*)mul
8910: 74 69 70 6c 65 78 46 75 6e 63 49 6e 69 74 29 3b  tiplexFuncInit);
8920: 0a 0a 20 20 72 65 74 75 72 6e 20 53 51 4c 49 54  ..  return SQLIT
8930: 45 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 43  E_OK;.}../*.** C
8940: 41 50 49 3a 20 53 68 75 74 64 6f 77 6e 20 74 68  API: Shutdown th
8950: 65 20 6d 75 6c 74 69 70 6c 65 78 20 73 79 73 74  e multiplex syst
8960: 65 6d 20 2d 20 73 71 6c 69 74 65 33 5f 6d 75 6c  em - sqlite3_mul
8970: 74 69 70 6c 65 78 5f 73 68 75 74 64 6f 77 6e 28  tiplex_shutdown(
8980: 29 0a 2a 2a 0a 2a 2a 20 41 6c 6c 20 53 51 4c 69  ).**.** All SQLi
8990: 74 65 20 64 61 74 61 62 61 73 65 20 63 6f 6e 6e  te database conn
89a0: 65 63 74 69 6f 6e 73 20 6d 75 73 74 20 62 65 20  ections must be 
89b0: 63 6c 6f 73 65 64 20 62 65 66 6f 72 65 20 63 61  closed before ca
89c0: 6c 6c 69 6e 67 20 74 68 69 73 0a 2a 2a 20 72 6f  lling this.** ro
89d0: 75 74 69 6e 65 2e 0a 2a 2a 0a 2a 2a 20 54 48 49  utine..**.** THI
89e0: 53 20 52 4f 55 54 49 4e 45 20 49 53 20 4e 4f 54  S ROUTINE IS NOT
89f0: 20 54 48 52 45 41 44 53 41 46 45 2e 20 20 43 61   THREADSAFE.  Ca
8a00: 6c 6c 20 74 68 69 73 20 72 6f 75 74 69 6e 65 20  ll this routine 
8a10: 65 78 61 63 74 6c 79 20 6f 6e 63 65 20 77 68 69  exactly once whi
8a20: 6c 65 0a 2a 2a 20 73 68 75 74 74 69 6e 67 20 64  le.** shutting d
8a30: 6f 77 6e 20 69 6e 20 6f 72 64 65 72 20 74 6f 20  own in order to 
8a40: 66 72 65 65 20 61 6c 6c 20 72 65 6d 61 69 6e 69  free all remaini
8a50: 6e 67 20 6d 75 6c 74 69 70 6c 65 78 20 67 72 6f  ng multiplex gro
8a60: 75 70 73 2e 0a 2a 2f 0a 69 6e 74 20 73 71 6c 69  ups..*/.int sqli
8a70: 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 73 68  te3_multiplex_sh
8a80: 75 74 64 6f 77 6e 28 76 6f 69 64 29 7b 0a 20 20  utdown(void){.  
8a90: 69 66 28 20 67 4d 75 6c 74 69 70 6c 65 78 2e 69  if( gMultiplex.i
8aa0: 73 49 6e 69 74 69 61 6c 69 7a 65 64 3d 3d 30 20  sInitialized==0 
8ab0: 29 20 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f  ) return SQLITE_
8ac0: 4d 49 53 55 53 45 3b 0a 20 20 69 66 28 20 67 4d  MISUSE;.  if( gM
8ad0: 75 6c 74 69 70 6c 65 78 2e 70 47 72 6f 75 70 73  ultiplex.pGroups
8ae0: 20 29 20 72 65 74 75 72 6e 20 53 51 4c 49 54 45   ) return SQLITE
8af0: 5f 4d 49 53 55 53 45 3b 0a 20 20 67 4d 75 6c 74  _MISUSE;.  gMult
8b00: 69 70 6c 65 78 2e 69 73 49 6e 69 74 69 61 6c 69  iplex.isInitiali
8b10: 7a 65 64 20 3d 20 30 3b 0a 20 20 73 71 6c 69 74  zed = 0;.  sqlit
8b20: 65 33 5f 6d 75 74 65 78 5f 66 72 65 65 28 67 4d  e3_mutex_free(gM
8b30: 75 6c 74 69 70 6c 65 78 2e 70 4d 75 74 65 78 29  ultiplex.pMutex)
8b40: 3b 0a 20 20 73 71 6c 69 74 65 33 5f 76 66 73 5f  ;.  sqlite3_vfs_
8b50: 75 6e 72 65 67 69 73 74 65 72 28 26 67 4d 75 6c  unregister(&gMul
8b60: 74 69 70 6c 65 78 2e 73 54 68 69 73 56 66 73 29  tiplex.sThisVfs)
8b70: 3b 0a 20 20 6d 65 6d 73 65 74 28 26 67 4d 75 6c  ;.  memset(&gMul
8b80: 74 69 70 6c 65 78 2c 20 30 2c 20 73 69 7a 65 6f  tiplex, 0, sizeo
8b90: 66 28 67 4d 75 6c 74 69 70 6c 65 78 29 29 3b 0a  f(gMultiplex));.
8ba0: 20 20 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f    return SQLITE_
8bb0: 4f 4b 3b 0a 7d 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a  OK;.}../********
8bc0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
8bd0: 2a 2a 2a 2a 2a 20 54 65 73 74 20 43 6f 64 65 20  ***** Test Code 
8be0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
8bf0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
8c00: 2a 2a 2a 2f 0a 23 69 66 64 65 66 20 53 51 4c 49  ***/.#ifdef SQLI
8c10: 54 45 5f 54 45 53 54 0a 23 69 6e 63 6c 75 64 65  TE_TEST.#include
8c20: 20 3c 74 63 6c 2e 68 3e 0a 65 78 74 65 72 6e 20   <tcl.h>.extern 
8c30: 63 6f 6e 73 74 20 63 68 61 72 20 2a 73 71 6c 69  const char *sqli
8c40: 74 65 33 54 65 73 74 45 72 72 6f 72 4e 61 6d 65  te3TestErrorName
8c50: 28 69 6e 74 29 3b 0a 0a 0a 2f 2a 0a 2a 2a 20 74  (int);.../*.** t
8c60: 63 6c 63 6d 64 3a 20 73 71 6c 69 74 65 33 5f 6d  clcmd: sqlite3_m
8c70: 75 6c 74 69 70 6c 65 78 5f 69 6e 69 74 69 61 6c  ultiplex_initial
8c80: 69 7a 65 20 4e 41 4d 45 20 4d 41 4b 45 44 45 46  ize NAME MAKEDEF
8c90: 41 55 4c 54 0a 2a 2f 0a 73 74 61 74 69 63 20 69  AULT.*/.static i
8ca0: 6e 74 20 74 65 73 74 5f 6d 75 6c 74 69 70 6c 65  nt test_multiple
8cb0: 78 5f 69 6e 69 74 69 61 6c 69 7a 65 28 0a 20 20  x_initialize(.  
8cc0: 76 6f 69 64 20 2a 20 63 6c 69 65 6e 74 44 61 74  void * clientDat
8cd0: 61 2c 0a 20 20 54 63 6c 5f 49 6e 74 65 72 70 20  a,.  Tcl_Interp 
8ce0: 2a 69 6e 74 65 72 70 2c 0a 20 20 69 6e 74 20 6f  *interp,.  int o
8cf0: 62 6a 63 2c 0a 20 20 54 63 6c 5f 4f 62 6a 20 2a  bjc,.  Tcl_Obj *
8d00: 43 4f 4e 53 54 20 6f 62 6a 76 5b 5d 0a 29 7b 0a  CONST objv[].){.
8d10: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 4e    const char *zN
8d20: 61 6d 65 3b 20 20 20 20 20 20 20 20 20 20 20 20  ame;            
8d30: 20 20 2f 2a 20 4e 61 6d 65 20 6f 66 20 6e 65 77    /* Name of new
8d40: 20 6d 75 6c 74 69 70 6c 65 78 20 56 46 53 20 2a   multiplex VFS *
8d50: 2f 0a 20 20 69 6e 74 20 6d 61 6b 65 44 65 66 61  /.  int makeDefa
8d60: 75 6c 74 3b 20 20 20 20 20 20 20 20 20 20 20 20  ult;            
8d70: 20 20 20 20 2f 2a 20 54 72 75 65 20 74 6f 20 6d      /* True to m
8d80: 61 6b 65 20 74 68 65 20 6e 65 77 20 56 46 53 20  ake the new VFS 
8d90: 74 68 65 20 64 65 66 61 75 6c 74 20 2a 2f 0a 20  the default */. 
8da0: 20 69 6e 74 20 72 63 3b 20 20 20 20 20 20 20 20   int rc;        
8db0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8dc0: 20 2f 2a 20 56 61 6c 75 65 20 72 65 74 75 72 6e   /* Value return
8dd0: 65 64 20 62 79 20 6d 75 6c 74 69 70 6c 65 78 5f  ed by multiplex_
8de0: 69 6e 69 74 69 61 6c 69 7a 65 28 29 20 2a 2f 0a  initialize() */.
8df0: 0a 20 20 55 4e 55 53 45 44 5f 50 41 52 41 4d 45  .  UNUSED_PARAME
8e00: 54 45 52 28 63 6c 69 65 6e 74 44 61 74 61 29 3b  TER(clientData);
8e10: 0a 0a 20 20 2f 2a 20 50 72 6f 63 65 73 73 20 61  ..  /* Process a
8e20: 72 67 75 6d 65 6e 74 73 20 2a 2f 0a 20 20 69 66  rguments */.  if
8e30: 28 20 6f 62 6a 63 21 3d 33 20 29 7b 0a 20 20 20  ( objc!=3 ){.   
8e40: 20 54 63 6c 5f 57 72 6f 6e 67 4e 75 6d 41 72 67   Tcl_WrongNumArg
8e50: 73 28 69 6e 74 65 72 70 2c 20 31 2c 20 6f 62 6a  s(interp, 1, obj
8e60: 76 2c 20 22 4e 41 4d 45 20 4d 41 4b 45 44 45 46  v, "NAME MAKEDEF
8e70: 41 55 4c 54 22 29 3b 0a 20 20 20 20 72 65 74 75  AULT");.    retu
8e80: 72 6e 20 54 43 4c 5f 45 52 52 4f 52 3b 0a 20 20  rn TCL_ERROR;.  
8e90: 7d 0a 20 20 7a 4e 61 6d 65 20 3d 20 54 63 6c 5f  }.  zName = Tcl_
8ea0: 47 65 74 53 74 72 69 6e 67 28 6f 62 6a 76 5b 31  GetString(objv[1
8eb0: 5d 29 3b 0a 20 20 69 66 28 20 54 63 6c 5f 47 65  ]);.  if( Tcl_Ge
8ec0: 74 42 6f 6f 6c 65 61 6e 46 72 6f 6d 4f 62 6a 28  tBooleanFromObj(
8ed0: 69 6e 74 65 72 70 2c 20 6f 62 6a 76 5b 32 5d 2c  interp, objv[2],
8ee0: 20 26 6d 61 6b 65 44 65 66 61 75 6c 74 29 20 29   &makeDefault) )
8ef0: 20 72 65 74 75 72 6e 20 54 43 4c 5f 45 52 52 4f   return TCL_ERRO
8f00: 52 3b 0a 20 20 69 66 28 20 7a 4e 61 6d 65 5b 30  R;.  if( zName[0
8f10: 5d 3d 3d 27 5c 30 27 20 29 20 7a 4e 61 6d 65 20  ]=='\0' ) zName 
8f20: 3d 20 30 3b 0a 0a 20 20 2f 2a 20 43 61 6c 6c 20  = 0;..  /* Call 
8f30: 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65  sqlite3_multiple
8f40: 78 5f 69 6e 69 74 69 61 6c 69 7a 65 28 29 20 2a  x_initialize() *
8f50: 2f 0a 20 20 72 63 20 3d 20 73 71 6c 69 74 65 33  /.  rc = sqlite3
8f60: 5f 6d 75 6c 74 69 70 6c 65 78 5f 69 6e 69 74 69  _multiplex_initi
8f70: 61 6c 69 7a 65 28 7a 4e 61 6d 65 2c 20 6d 61 6b  alize(zName, mak
8f80: 65 44 65 66 61 75 6c 74 29 3b 0a 20 20 54 63 6c  eDefault);.  Tcl
8f90: 5f 53 65 74 52 65 73 75 6c 74 28 69 6e 74 65 72  _SetResult(inter
8fa0: 70 2c 20 28 63 68 61 72 20 2a 29 73 71 6c 69 74  p, (char *)sqlit
8fb0: 65 33 54 65 73 74 45 72 72 6f 72 4e 61 6d 65 28  e3TestErrorName(
8fc0: 72 63 29 2c 20 54 43 4c 5f 53 54 41 54 49 43 29  rc), TCL_STATIC)
8fd0: 3b 0a 0a 20 20 72 65 74 75 72 6e 20 54 43 4c 5f  ;..  return TCL_
8fe0: 4f 4b 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 74 63 6c  OK;.}../*.** tcl
8ff0: 63 6d 64 3a 20 73 71 6c 69 74 65 33 5f 6d 75 6c  cmd: sqlite3_mul
9000: 74 69 70 6c 65 78 5f 73 68 75 74 64 6f 77 6e 0a  tiplex_shutdown.
9010: 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 74 65  */.static int te
9020: 73 74 5f 6d 75 6c 74 69 70 6c 65 78 5f 73 68 75  st_multiplex_shu
9030: 74 64 6f 77 6e 28 0a 20 20 76 6f 69 64 20 2a 20  tdown(.  void * 
9040: 63 6c 69 65 6e 74 44 61 74 61 2c 0a 20 20 54 63  clientData,.  Tc
9050: 6c 5f 49 6e 74 65 72 70 20 2a 69 6e 74 65 72 70  l_Interp *interp
9060: 2c 0a 20 20 69 6e 74 20 6f 62 6a 63 2c 0a 20 20  ,.  int objc,.  
9070: 54 63 6c 5f 4f 62 6a 20 2a 43 4f 4e 53 54 20 6f  Tcl_Obj *CONST o
9080: 62 6a 76 5b 5d 0a 29 7b 0a 20 20 69 6e 74 20 72  bjv[].){.  int r
9090: 63 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  c;              
90a0: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 56 61             /* Va
90b0: 6c 75 65 20 72 65 74 75 72 6e 65 64 20 62 79 20  lue returned by 
90c0: 6d 75 6c 74 69 70 6c 65 78 5f 73 68 75 74 64 6f  multiplex_shutdo
90d0: 77 6e 28 29 20 2a 2f 0a 0a 20 20 55 4e 55 53 45  wn() */..  UNUSE
90e0: 44 5f 50 41 52 41 4d 45 54 45 52 28 63 6c 69 65  D_PARAMETER(clie
90f0: 6e 74 44 61 74 61 29 3b 0a 0a 20 20 69 66 28 20  ntData);..  if( 
9100: 6f 62 6a 63 21 3d 31 20 29 7b 0a 20 20 20 20 54  objc!=1 ){.    T
9110: 63 6c 5f 57 72 6f 6e 67 4e 75 6d 41 72 67 73 28  cl_WrongNumArgs(
9120: 69 6e 74 65 72 70 2c 20 31 2c 20 6f 62 6a 76 2c  interp, 1, objv,
9130: 20 22 22 29 3b 0a 20 20 20 20 72 65 74 75 72 6e   "");.    return
9140: 20 54 43 4c 5f 45 52 52 4f 52 3b 0a 20 20 7d 0a   TCL_ERROR;.  }.
9150: 0a 20 20 2f 2a 20 43 61 6c 6c 20 73 71 6c 69 74  .  /* Call sqlit
9160: 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 73 68 75  e3_multiplex_shu
9170: 74 64 6f 77 6e 28 29 20 2a 2f 0a 20 20 72 63 20  tdown() */.  rc 
9180: 3d 20 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70  = sqlite3_multip
9190: 6c 65 78 5f 73 68 75 74 64 6f 77 6e 28 29 3b 0a  lex_shutdown();.
91a0: 20 20 54 63 6c 5f 53 65 74 52 65 73 75 6c 74 28    Tcl_SetResult(
91b0: 69 6e 74 65 72 70 2c 20 28 63 68 61 72 20 2a 29  interp, (char *)
91c0: 73 71 6c 69 74 65 33 54 65 73 74 45 72 72 6f 72  sqlite3TestError
91d0: 4e 61 6d 65 28 72 63 29 2c 20 54 43 4c 5f 53 54  Name(rc), TCL_ST
91e0: 41 54 49 43 29 3b 0a 0a 20 20 72 65 74 75 72 6e  ATIC);..  return
91f0: 20 54 43 4c 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a 0a 2a   TCL_OK;.}../*.*
9200: 2a 20 74 63 6c 63 6d 64 3a 20 20 73 71 6c 69 74  * tclcmd:  sqlit
9210: 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 64 75 6d  e3_multiplex_dum
9220: 70 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20  p.*/.static int 
9230: 74 65 73 74 5f 6d 75 6c 74 69 70 6c 65 78 5f 64  test_multiplex_d
9240: 75 6d 70 28 0a 20 20 76 6f 69 64 20 2a 20 63 6c  ump(.  void * cl
9250: 69 65 6e 74 44 61 74 61 2c 0a 20 20 54 63 6c 5f  ientData,.  Tcl_
9260: 49 6e 74 65 72 70 20 2a 69 6e 74 65 72 70 2c 0a  Interp *interp,.
9270: 20 20 69 6e 74 20 6f 62 6a 63 2c 0a 20 20 54 63    int objc,.  Tc
9280: 6c 5f 4f 62 6a 20 2a 43 4f 4e 53 54 20 6f 62 6a  l_Obj *CONST obj
9290: 76 5b 5d 0a 29 7b 0a 20 20 54 63 6c 5f 4f 62 6a  v[].){.  Tcl_Obj
92a0: 20 2a 70 52 65 73 75 6c 74 3b 0a 20 20 54 63 6c   *pResult;.  Tcl
92b0: 5f 4f 62 6a 20 2a 70 47 72 6f 75 70 54 65 72 6d  _Obj *pGroupTerm
92c0: 3b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f  ;.  multiplexGro
92d0: 75 70 20 2a 70 47 72 6f 75 70 3b 0a 20 20 69 6e  up *pGroup;.  in
92e0: 74 20 69 3b 0a 20 20 69 6e 74 20 6e 43 68 75 6e  t i;.  int nChun
92f0: 6b 73 20 3d 20 30 3b 0a 0a 20 20 55 4e 55 53 45  ks = 0;..  UNUSE
9300: 44 5f 50 41 52 41 4d 45 54 45 52 28 63 6c 69 65  D_PARAMETER(clie
9310: 6e 74 44 61 74 61 29 3b 0a 20 20 55 4e 55 53 45  ntData);.  UNUSE
9320: 44 5f 50 41 52 41 4d 45 54 45 52 28 6f 62 6a 63  D_PARAMETER(objc
9330: 29 3b 0a 20 20 55 4e 55 53 45 44 5f 50 41 52 41  );.  UNUSED_PARA
9340: 4d 45 54 45 52 28 6f 62 6a 76 29 3b 0a 0a 20 20  METER(objv);..  
9350: 70 52 65 73 75 6c 74 20 3d 20 54 63 6c 5f 4e 65  pResult = Tcl_Ne
9360: 77 4f 62 6a 28 29 3b 0a 20 20 6d 75 6c 74 69 70  wObj();.  multip
9370: 6c 65 78 45 6e 74 65 72 28 29 3b 0a 20 20 66 6f  lexEnter();.  fo
9380: 72 28 70 47 72 6f 75 70 3d 67 4d 75 6c 74 69 70  r(pGroup=gMultip
9390: 6c 65 78 2e 70 47 72 6f 75 70 73 3b 20 70 47 72  lex.pGroups; pGr
93a0: 6f 75 70 3b 20 70 47 72 6f 75 70 3d 70 47 72 6f  oup; pGroup=pGro
93b0: 75 70 2d 3e 70 4e 65 78 74 29 7b 0a 20 20 20 20  up->pNext){.    
93c0: 70 47 72 6f 75 70 54 65 72 6d 20 3d 20 54 63 6c  pGroupTerm = Tcl
93d0: 5f 4e 65 77 4f 62 6a 28 29 3b 0a 0a 20 20 20 20  _NewObj();..    
93e0: 70 47 72 6f 75 70 2d 3e 7a 4e 61 6d 65 5b 70 47  pGroup->zName[pG
93f0: 72 6f 75 70 2d 3e 6e 4e 61 6d 65 5d 20 3d 20 27  roup->nName] = '
9400: 5c 30 27 3b 0a 20 20 20 20 54 63 6c 5f 4c 69 73  \0';.    Tcl_Lis
9410: 74 4f 62 6a 41 70 70 65 6e 64 45 6c 65 6d 65 6e  tObjAppendElemen
9420: 74 28 69 6e 74 65 72 70 2c 20 70 47 72 6f 75 70  t(interp, pGroup
9430: 54 65 72 6d 2c 0a 20 20 20 20 20 20 20 20 20 20  Term,.          
9440: 54 63 6c 5f 4e 65 77 53 74 72 69 6e 67 4f 62 6a  Tcl_NewStringObj
9450: 28 70 47 72 6f 75 70 2d 3e 7a 4e 61 6d 65 2c 20  (pGroup->zName, 
9460: 2d 31 29 29 3b 0a 20 20 20 20 54 63 6c 5f 4c 69  -1));.    Tcl_Li
9470: 73 74 4f 62 6a 41 70 70 65 6e 64 45 6c 65 6d 65  stObjAppendEleme
9480: 6e 74 28 69 6e 74 65 72 70 2c 20 70 47 72 6f 75  nt(interp, pGrou
9490: 70 54 65 72 6d 2c 0a 20 20 20 20 20 20 20 20 20  pTerm,.         
94a0: 20 54 63 6c 5f 4e 65 77 49 6e 74 4f 62 6a 28 70   Tcl_NewIntObj(p
94b0: 47 72 6f 75 70 2d 3e 6e 4e 61 6d 65 29 29 3b 0a  Group->nName));.
94c0: 20 20 20 20 54 63 6c 5f 4c 69 73 74 4f 62 6a 41      Tcl_ListObjA
94d0: 70 70 65 6e 64 45 6c 65 6d 65 6e 74 28 69 6e 74  ppendElement(int
94e0: 65 72 70 2c 20 70 47 72 6f 75 70 54 65 72 6d 2c  erp, pGroupTerm,
94f0: 0a 20 20 20 20 20 20 20 20 20 20 54 63 6c 5f 4e  .          Tcl_N
9500: 65 77 49 6e 74 4f 62 6a 28 70 47 72 6f 75 70 2d  ewIntObj(pGroup-
9510: 3e 66 6c 61 67 73 29 29 3b 0a 0a 20 20 20 20 2f  >flags));..    /
9520: 2a 20 63 6f 75 6e 74 20 6e 75 6d 62 65 72 20 6f  * count number o
9530: 66 20 63 68 75 6e 6b 73 20 77 69 74 68 20 6f 70  f chunks with op
9540: 65 6e 20 68 61 6e 64 6c 65 73 20 2a 2f 0a 20 20  en handles */.  
9550: 20 20 66 6f 72 28 69 3d 30 3b 20 69 3c 70 47 72    for(i=0; i<pGr
9560: 6f 75 70 2d 3e 6e 52 65 61 6c 3b 20 69 2b 2b 29  oup->nReal; i++)
9570: 7b 0a 20 20 20 20 20 20 69 66 28 20 70 47 72 6f  {.      if( pGro
9580: 75 70 2d 3e 61 52 65 61 6c 5b 69 5d 2e 70 21 3d  up->aReal[i].p!=
9590: 30 20 29 20 6e 43 68 75 6e 6b 73 2b 2b 3b 0a 20  0 ) nChunks++;. 
95a0: 20 20 20 7d 0a 20 20 20 20 54 63 6c 5f 4c 69 73     }.    Tcl_Lis
95b0: 74 4f 62 6a 41 70 70 65 6e 64 45 6c 65 6d 65 6e  tObjAppendElemen
95c0: 74 28 69 6e 74 65 72 70 2c 20 70 47 72 6f 75 70  t(interp, pGroup
95d0: 54 65 72 6d 2c 0a 20 20 20 20 20 20 20 20 20 20  Term,.          
95e0: 54 63 6c 5f 4e 65 77 49 6e 74 4f 62 6a 28 6e 43  Tcl_NewIntObj(nC
95f0: 68 75 6e 6b 73 29 29 3b 0a 0a 20 20 20 20 54 63  hunks));..    Tc
9600: 6c 5f 4c 69 73 74 4f 62 6a 41 70 70 65 6e 64 45  l_ListObjAppendE
9610: 6c 65 6d 65 6e 74 28 69 6e 74 65 72 70 2c 20 70  lement(interp, p
9620: 47 72 6f 75 70 54 65 72 6d 2c 0a 20 20 20 20 20  GroupTerm,.     
9630: 20 20 20 20 20 54 63 6c 5f 4e 65 77 49 6e 74 4f       Tcl_NewIntO
9640: 62 6a 28 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75  bj(pGroup->szChu
9650: 6e 6b 29 29 3b 0a 20 20 20 20 54 63 6c 5f 4c 69  nk));.    Tcl_Li
9660: 73 74 4f 62 6a 41 70 70 65 6e 64 45 6c 65 6d 65  stObjAppendEleme
9670: 6e 74 28 69 6e 74 65 72 70 2c 20 70 47 72 6f 75  nt(interp, pGrou
9680: 70 54 65 72 6d 2c 0a 20 20 20 20 20 20 20 20 20  pTerm,.         
9690: 20 54 63 6c 5f 4e 65 77 49 6e 74 4f 62 6a 28 70   Tcl_NewIntObj(p
96a0: 47 72 6f 75 70 2d 3e 6e 52 65 61 6c 29 29 3b 0a  Group->nReal));.
96b0: 0a 20 20 20 20 54 63 6c 5f 4c 69 73 74 4f 62 6a  .    Tcl_ListObj
96c0: 41 70 70 65 6e 64 45 6c 65 6d 65 6e 74 28 69 6e  AppendElement(in
96d0: 74 65 72 70 2c 20 70 52 65 73 75 6c 74 2c 20 70  terp, pResult, p
96e0: 47 72 6f 75 70 54 65 72 6d 29 3b 0a 20 20 7d 0a  GroupTerm);.  }.
96f0: 20 20 6d 75 6c 74 69 70 6c 65 78 4c 65 61 76 65    multiplexLeave
9700: 28 29 3b 0a 20 20 54 63 6c 5f 53 65 74 4f 62 6a  ();.  Tcl_SetObj
9710: 52 65 73 75 6c 74 28 69 6e 74 65 72 70 2c 20 70  Result(interp, p
9720: 52 65 73 75 6c 74 29 3b 0a 20 20 72 65 74 75 72  Result);.  retur
9730: 6e 20 54 43 4c 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a 0a  n TCL_OK;.}../*.
9740: 2a 2a 20 54 63 6c 63 6d 64 3a 20 74 65 73 74 5f  ** Tclcmd: test_
9750: 6d 75 6c 74 69 70 6c 65 78 5f 63 6f 6e 74 72 6f  multiplex_contro
9760: 6c 20 48 41 4e 44 4c 45 20 44 42 4e 41 4d 45 20  l HANDLE DBNAME 
9770: 53 55 42 2d 43 4f 4d 4d 41 4e 44 20 3f 49 4e 54  SUB-COMMAND ?INT
9780: 2d 56 41 4c 55 45 3f 0a 2a 2f 0a 73 74 61 74 69  -VALUE?.*/.stati
9790: 63 20 69 6e 74 20 74 65 73 74 5f 6d 75 6c 74 69  c int test_multi
97a0: 70 6c 65 78 5f 63 6f 6e 74 72 6f 6c 28 0a 20 20  plex_control(.  
97b0: 43 6c 69 65 6e 74 44 61 74 61 20 63 64 2c 0a 20  ClientData cd,. 
97c0: 20 54 63 6c 5f 49 6e 74 65 72 70 20 2a 69 6e 74   Tcl_Interp *int
97d0: 65 72 70 2c 0a 20 20 69 6e 74 20 6f 62 6a 63 2c  erp,.  int objc,
97e0: 0a 20 20 54 63 6c 5f 4f 62 6a 20 2a 43 4f 4e 53  .  Tcl_Obj *CONS
97f0: 54 20 6f 62 6a 76 5b 5d 0a 29 7b 0a 20 20 69 6e  T objv[].){.  in
9800: 74 20 72 63 3b 20 20 20 20 20 20 20 20 20 20 20  t rc;           
9810: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
9820: 20 52 65 74 75 72 6e 20 63 6f 64 65 20 66 72 6f   Return code fro
9830: 6d 20 66 69 6c 65 5f 63 6f 6e 74 72 6f 6c 28 29  m file_control()
9840: 20 2a 2f 0a 20 20 69 6e 74 20 69 64 78 3b 20 20   */.  int idx;  
9850: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9860: 20 20 20 20 20 20 2f 2a 20 49 6e 64 65 78 20 69        /* Index i
9870: 6e 20 61 53 75 62 5b 5d 20 2a 2f 0a 20 20 54 63  n aSub[] */.  Tc
9880: 6c 5f 43 6d 64 49 6e 66 6f 20 63 6d 64 49 6e 66  l_CmdInfo cmdInf
9890: 6f 3b 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a  o;            /*
98a0: 20 43 6f 6d 6d 61 6e 64 20 69 6e 66 6f 20 73 74   Command info st
98b0: 72 75 63 74 75 72 65 20 66 6f 72 20 48 41 4e 44  ructure for HAND
98c0: 4c 45 20 2a 2f 0a 20 20 73 71 6c 69 74 65 33 20  LE */.  sqlite3 
98d0: 2a 64 62 3b 20 20 20 20 20 20 20 20 20 20 20 20  *db;            
98e0: 20 20 20 20 20 20 20 20 2f 2a 20 55 6e 64 65 72          /* Under
98f0: 6c 79 69 6e 67 20 64 62 20 68 61 6e 64 6c 65 20  lying db handle 
9900: 66 6f 72 20 48 41 4e 44 4c 45 20 2a 2f 0a 20 20  for HANDLE */.  
9910: 69 6e 74 20 69 56 61 6c 75 65 20 3d 20 30 3b 0a  int iValue = 0;.
9920: 20 20 76 6f 69 64 20 2a 70 41 72 67 20 3d 20 30    void *pArg = 0
9930: 3b 0a 0a 20 20 73 74 72 75 63 74 20 53 75 62 43  ;..  struct SubC
9940: 6f 6d 6d 61 6e 64 20 7b 0a 20 20 20 20 63 6f 6e  ommand {.    con
9950: 73 74 20 63 68 61 72 20 2a 7a 4e 61 6d 65 3b 0a  st char *zName;.
9960: 20 20 20 20 69 6e 74 20 6f 70 3b 0a 20 20 20 20      int op;.    
9970: 69 6e 74 20 61 72 67 74 79 70 65 3b 0a 20 20 7d  int argtype;.  }
9980: 20 61 53 75 62 5b 5d 20 3d 20 7b 0a 20 20 20 20   aSub[] = {.    
9990: 7b 20 22 65 6e 61 62 6c 65 22 2c 20 20 20 20 20  { "enable",     
99a0: 20 20 4d 55 4c 54 49 50 4c 45 58 5f 43 54 52 4c    MULTIPLEX_CTRL
99b0: 5f 45 4e 41 42 4c 45 2c 20 20 20 20 20 20 20 20  _ENABLE,        
99c0: 20 20 20 31 20 7d 2c 0a 20 20 20 20 7b 20 22 63     1 },.    { "c
99d0: 68 75 6e 6b 5f 73 69 7a 65 22 2c 20 20 20 4d 55  hunk_size",   MU
99e0: 4c 54 49 50 4c 45 58 5f 43 54 52 4c 5f 53 45 54  LTIPLEX_CTRL_SET
99f0: 5f 43 48 55 4e 4b 5f 53 49 5a 45 2c 20 20 20 31  _CHUNK_SIZE,   1
9a00: 20 7d 2c 0a 20 20 20 20 7b 20 22 6d 61 78 5f 63   },.    { "max_c
9a10: 68 75 6e 6b 73 22 2c 20 20 20 4d 55 4c 54 49 50  hunks",   MULTIP
9a20: 4c 45 58 5f 43 54 52 4c 5f 53 45 54 5f 4d 41 58  LEX_CTRL_SET_MAX
9a30: 5f 43 48 55 4e 4b 53 2c 20 20 20 31 20 7d 2c 0a  _CHUNKS,   1 },.
9a40: 20 20 20 20 7b 20 30 2c 20 30 2c 20 30 20 7d 0a      { 0, 0, 0 }.
9a50: 20 20 7d 3b 0a 0a 20 20 69 66 28 20 6f 62 6a 63    };..  if( objc
9a60: 21 3d 35 20 29 7b 0a 20 20 20 20 54 63 6c 5f 57  !=5 ){.    Tcl_W
9a70: 72 6f 6e 67 4e 75 6d 41 72 67 73 28 69 6e 74 65  rongNumArgs(inte
9a80: 72 70 2c 20 31 2c 20 6f 62 6a 76 2c 20 22 48 41  rp, 1, objv, "HA
9a90: 4e 44 4c 45 20 44 42 4e 41 4d 45 20 53 55 42 2d  NDLE DBNAME SUB-
9aa0: 43 4f 4d 4d 41 4e 44 20 49 4e 54 2d 56 41 4c 55  COMMAND INT-VALU
9ab0: 45 22 29 3b 0a 20 20 20 20 72 65 74 75 72 6e 20  E");.    return 
9ac0: 54 43 4c 5f 45 52 52 4f 52 3b 0a 20 20 7d 0a 0a  TCL_ERROR;.  }..
9ad0: 20 20 69 66 28 20 30 3d 3d 54 63 6c 5f 47 65 74    if( 0==Tcl_Get
9ae0: 43 6f 6d 6d 61 6e 64 49 6e 66 6f 28 69 6e 74 65  CommandInfo(inte
9af0: 72 70 2c 20 54 63 6c 5f 47 65 74 53 74 72 69 6e  rp, Tcl_GetStrin
9b00: 67 28 6f 62 6a 76 5b 31 5d 29 2c 20 26 63 6d 64  g(objv[1]), &cmd
9b10: 49 6e 66 6f 29 20 29 7b 0a 20 20 20 20 54 63 6c  Info) ){.    Tcl
9b20: 5f 41 70 70 65 6e 64 52 65 73 75 6c 74 28 69 6e  _AppendResult(in
9b30: 74 65 72 70 2c 20 22 65 78 70 65 63 74 65 64 20  terp, "expected 
9b40: 64 61 74 61 62 61 73 65 20 68 61 6e 64 6c 65 2c  database handle,
9b50: 20 67 6f 74 20 5c 22 22 2c 20 30 29 3b 0a 20 20   got \"", 0);.  
9b60: 20 20 54 63 6c 5f 41 70 70 65 6e 64 52 65 73 75    Tcl_AppendResu
9b70: 6c 74 28 69 6e 74 65 72 70 2c 20 54 63 6c 5f 47  lt(interp, Tcl_G
9b80: 65 74 53 74 72 69 6e 67 28 6f 62 6a 76 5b 31 5d  etString(objv[1]
9b90: 29 2c 20 22 5c 22 22 2c 20 30 29 3b 0a 20 20 20  ), "\"", 0);.   
9ba0: 20 72 65 74 75 72 6e 20 54 43 4c 5f 45 52 52 4f   return TCL_ERRO
9bb0: 52 3b 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20  R;.  }else{.    
9bc0: 64 62 20 3d 20 2a 28 73 71 6c 69 74 65 33 20 2a  db = *(sqlite3 *
9bd0: 2a 29 63 6d 64 49 6e 66 6f 2e 6f 62 6a 43 6c 69  *)cmdInfo.objCli
9be0: 65 6e 74 44 61 74 61 3b 0a 20 20 7d 0a 0a 20 20  entData;.  }..  
9bf0: 72 63 20 3d 20 54 63 6c 5f 47 65 74 49 6e 64 65  rc = Tcl_GetInde
9c00: 78 46 72 6f 6d 4f 62 6a 53 74 72 75 63 74 28 0a  xFromObjStruct(.
9c10: 20 20 20 20 20 20 69 6e 74 65 72 70 2c 20 6f 62        interp, ob
9c20: 6a 76 5b 33 5d 2c 20 61 53 75 62 2c 20 73 69 7a  jv[3], aSub, siz
9c30: 65 6f 66 28 61 53 75 62 5b 30 5d 29 2c 20 22 73  eof(aSub[0]), "s
9c40: 75 62 2d 63 6f 6d 6d 61 6e 64 22 2c 20 30 2c 20  ub-command", 0, 
9c50: 26 69 64 78 0a 20 20 29 3b 0a 20 20 69 66 28 20  &idx.  );.  if( 
9c60: 72 63 21 3d 54 43 4c 5f 4f 4b 20 29 20 72 65 74  rc!=TCL_OK ) ret
9c70: 75 72 6e 20 72 63 3b 0a 0a 20 20 73 77 69 74 63  urn rc;..  switc
9c80: 68 28 20 61 53 75 62 5b 69 64 78 5d 2e 61 72 67  h( aSub[idx].arg
9c90: 74 79 70 65 20 29 7b 0a 20 20 20 20 63 61 73 65  type ){.    case
9ca0: 20 31 3a 0a 20 20 20 20 20 20 69 66 28 20 54 63   1:.      if( Tc
9cb0: 6c 5f 47 65 74 49 6e 74 46 72 6f 6d 4f 62 6a 28  l_GetIntFromObj(
9cc0: 69 6e 74 65 72 70 2c 20 6f 62 6a 76 5b 34 5d 2c  interp, objv[4],
9cd0: 20 26 69 56 61 6c 75 65 29 20 29 7b 0a 20 20 20   &iValue) ){.   
9ce0: 20 20 20 20 20 72 65 74 75 72 6e 20 54 43 4c 5f       return TCL_
9cf0: 45 52 52 4f 52 3b 0a 20 20 20 20 20 20 7d 0a 20  ERROR;.      }. 
9d00: 20 20 20 20 20 70 41 72 67 20 3d 20 28 76 6f 69       pArg = (voi
9d10: 64 20 2a 29 26 69 56 61 6c 75 65 3b 0a 20 20 20  d *)&iValue;.   
9d20: 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 64 65     break;.    de
9d30: 66 61 75 6c 74 3a 0a 20 20 20 20 20 20 54 63 6c  fault:.      Tcl
9d40: 5f 57 72 6f 6e 67 4e 75 6d 41 72 67 73 28 69 6e  _WrongNumArgs(in
9d50: 74 65 72 70 2c 20 34 2c 20 6f 62 6a 76 2c 20 22  terp, 4, objv, "
9d60: 53 55 42 2d 43 4f 4d 4d 41 4e 44 22 29 3b 0a 20  SUB-COMMAND");. 
9d70: 20 20 20 20 20 72 65 74 75 72 6e 20 54 43 4c 5f       return TCL_
9d80: 45 52 52 4f 52 3b 0a 20 20 7d 0a 0a 20 20 72 63  ERROR;.  }..  rc
9d90: 20 3d 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 5f   = sqlite3_file_
9da0: 63 6f 6e 74 72 6f 6c 28 64 62 2c 20 54 63 6c 5f  control(db, Tcl_
9db0: 47 65 74 53 74 72 69 6e 67 28 6f 62 6a 76 5b 32  GetString(objv[2
9dc0: 5d 29 2c 20 61 53 75 62 5b 69 64 78 5d 2e 6f 70  ]), aSub[idx].op
9dd0: 2c 20 70 41 72 67 29 3b 0a 20 20 54 63 6c 5f 53  , pArg);.  Tcl_S
9de0: 65 74 52 65 73 75 6c 74 28 69 6e 74 65 72 70 2c  etResult(interp,
9df0: 20 28 63 68 61 72 20 2a 29 73 71 6c 69 74 65 33   (char *)sqlite3
9e00: 54 65 73 74 45 72 72 6f 72 4e 61 6d 65 28 72 63  TestErrorName(rc
9e10: 29 2c 20 54 43 4c 5f 53 54 41 54 49 43 29 3b 0a  ), TCL_STATIC);.
9e20: 20 20 72 65 74 75 72 6e 20 28 72 63 3d 3d 53 51    return (rc==SQ
9e30: 4c 49 54 45 5f 4f 4b 29 20 3f 20 54 43 4c 5f 4f  LITE_OK) ? TCL_O
9e40: 4b 20 3a 20 54 43 4c 5f 45 52 52 4f 52 3b 0a 7d  K : TCL_ERROR;.}
9e50: 0a 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20 72 6f 75  ../*.** This rou
9e60: 74 69 6e 65 20 72 65 67 69 73 74 65 72 73 20 74  tine registers t
9e70: 68 65 20 63 75 73 74 6f 6d 20 54 43 4c 20 63 6f  he custom TCL co
9e80: 6d 6d 61 6e 64 73 20 64 65 66 69 6e 65 64 20 69  mmands defined i
9e90: 6e 20 74 68 69 73 0a 2a 2a 20 6d 6f 64 75 6c 65  n this.** module
9ea0: 2e 20 20 54 68 69 73 20 73 68 6f 75 6c 64 20 62  .  This should b
9eb0: 65 20 74 68 65 20 6f 6e 6c 79 20 70 72 6f 63 65  e the only proce
9ec0: 64 75 72 65 20 76 69 73 69 62 6c 65 20 66 72 6f  dure visible fro
9ed0: 6d 20 6f 75 74 73 69 64 65 0a 2a 2a 20 6f 66 20  m outside.** of 
9ee0: 74 68 69 73 20 6d 6f 64 75 6c 65 2e 0a 2a 2f 0a  this module..*/.
9ef0: 69 6e 74 20 53 71 6c 69 74 65 6d 75 6c 74 69 70  int Sqlitemultip
9f00: 6c 65 78 5f 49 6e 69 74 28 54 63 6c 5f 49 6e 74  lex_Init(Tcl_Int
9f10: 65 72 70 20 2a 69 6e 74 65 72 70 29 7b 0a 20 20  erp *interp){.  
9f20: 73 74 61 74 69 63 20 73 74 72 75 63 74 20 7b 0a  static struct {.
9f30: 20 20 20 20 20 63 68 61 72 20 2a 7a 4e 61 6d 65       char *zName
9f40: 3b 0a 20 20 20 20 20 54 63 6c 5f 4f 62 6a 43 6d  ;.     Tcl_ObjCm
9f50: 64 50 72 6f 63 20 2a 78 50 72 6f 63 3b 0a 20 20  dProc *xProc;.  
9f60: 7d 20 61 43 6d 64 5b 5d 20 3d 20 7b 0a 20 20 20  } aCmd[] = {.   
9f70: 20 7b 20 22 73 71 6c 69 74 65 33 5f 6d 75 6c 74   { "sqlite3_mult
9f80: 69 70 6c 65 78 5f 69 6e 69 74 69 61 6c 69 7a 65  iplex_initialize
9f90: 22 2c 20 74 65 73 74 5f 6d 75 6c 74 69 70 6c 65  ", test_multiple
9fa0: 78 5f 69 6e 69 74 69 61 6c 69 7a 65 20 7d 2c 0a  x_initialize },.
9fb0: 20 20 20 20 7b 20 22 73 71 6c 69 74 65 33 5f 6d      { "sqlite3_m
9fc0: 75 6c 74 69 70 6c 65 78 5f 73 68 75 74 64 6f 77  ultiplex_shutdow
9fd0: 6e 22 2c 20 74 65 73 74 5f 6d 75 6c 74 69 70 6c  n", test_multipl
9fe0: 65 78 5f 73 68 75 74 64 6f 77 6e 20 7d 2c 0a 20  ex_shutdown },. 
9ff0: 20 20 20 7b 20 22 73 71 6c 69 74 65 33 5f 6d 75     { "sqlite3_mu
a000: 6c 74 69 70 6c 65 78 5f 64 75 6d 70 22 2c 20 74  ltiplex_dump", t
a010: 65 73 74 5f 6d 75 6c 74 69 70 6c 65 78 5f 64 75  est_multiplex_du
a020: 6d 70 20 7d 2c 0a 20 20 20 20 7b 20 22 73 71 6c  mp },.    { "sql
a030: 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 63  ite3_multiplex_c
a040: 6f 6e 74 72 6f 6c 22 2c 20 74 65 73 74 5f 6d 75  ontrol", test_mu
a050: 6c 74 69 70 6c 65 78 5f 63 6f 6e 74 72 6f 6c 20  ltiplex_control 
a060: 7d 2c 0a 20 20 7d 3b 0a 20 20 69 6e 74 20 69 3b  },.  };.  int i;
a070: 0a 0a 20 20 66 6f 72 28 69 3d 30 3b 20 69 3c 73  ..  for(i=0; i<s
a080: 69 7a 65 6f 66 28 61 43 6d 64 29 2f 73 69 7a 65  izeof(aCmd)/size
a090: 6f 66 28 61 43 6d 64 5b 30 5d 29 3b 20 69 2b 2b  of(aCmd[0]); i++
a0a0: 29 7b 0a 20 20 20 20 54 63 6c 5f 43 72 65 61 74  ){.    Tcl_Creat
a0b0: 65 4f 62 6a 43 6f 6d 6d 61 6e 64 28 69 6e 74 65  eObjCommand(inte
a0c0: 72 70 2c 20 61 43 6d 64 5b 69 5d 2e 7a 4e 61 6d  rp, aCmd[i].zNam
a0d0: 65 2c 20 61 43 6d 64 5b 69 5d 2e 78 50 72 6f 63  e, aCmd[i].xProc
a0e0: 2c 20 30 2c 20 30 29 3b 0a 20 20 7d 0a 0a 20 20  , 0, 0);.  }..  
a0f0: 72 65 74 75 72 6e 20 54 43 4c 5f 4f 4b 3b 0a 7d  return TCL_OK;.}
a100: 0a 23 65 6e 64 69 66 0a                          .#endif.