/ Hex Artifact Content
Login

Artifact 9f304bf04170c91c0318238d512df2da039eb1c8:


0000: 2f 2a 0a 2a 2a 20 32 30 31 30 20 4f 63 74 6f 62  /*.** 2010 Octob
0010: 65 72 20 32 38 0a 2a 2a 0a 2a 2a 20 54 68 65 20  er 28.**.** The 
0020: 61 75 74 68 6f 72 20 64 69 73 63 6c 61 69 6d 73  author disclaims
0030: 20 63 6f 70 79 72 69 67 68 74 20 74 6f 20 74 68   copyright to th
0040: 69 73 20 73 6f 75 72 63 65 20 63 6f 64 65 2e 20  is source code. 
0050: 20 49 6e 20 70 6c 61 63 65 20 6f 66 0a 2a 2a 20   In place of.** 
0060: 61 20 6c 65 67 61 6c 20 6e 6f 74 69 63 65 2c 20  a legal notice, 
0070: 68 65 72 65 20 69 73 20 61 20 62 6c 65 73 73 69  here is a blessi
0080: 6e 67 3a 0a 2a 2a 0a 2a 2a 20 20 20 20 4d 61 79  ng:.**.**    May
0090: 20 79 6f 75 20 64 6f 20 67 6f 6f 64 20 61 6e 64   you do good and
00a0: 20 6e 6f 74 20 65 76 69 6c 2e 0a 2a 2a 20 20 20   not evil..**   
00b0: 20 4d 61 79 20 79 6f 75 20 66 69 6e 64 20 66 6f   May you find fo
00c0: 72 67 69 76 65 6e 65 73 73 20 66 6f 72 20 79 6f  rgiveness for yo
00d0: 75 72 73 65 6c 66 20 61 6e 64 20 66 6f 72 67 69  urself and forgi
00e0: 76 65 20 6f 74 68 65 72 73 2e 0a 2a 2a 20 20 20  ve others..**   
00f0: 20 4d 61 79 20 79 6f 75 20 73 68 61 72 65 20 66   May you share f
0100: 72 65 65 6c 79 2c 20 6e 65 76 65 72 20 74 61 6b  reely, never tak
0110: 69 6e 67 20 6d 6f 72 65 20 74 68 61 6e 20 79 6f  ing more than yo
0120: 75 20 67 69 76 65 2e 0a 2a 2a 0a 2a 2a 2a 2a 2a  u give..**.*****
0130: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0140: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0150: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0160: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0170: 2a 2a 2a 2a 0a 2a 2a 0a 2a 2a 20 54 68 69 73 20  ****.**.** This 
0180: 66 69 6c 65 20 63 6f 6e 74 61 69 6e 73 20 61 20  file contains a 
0190: 56 46 53 20 22 73 68 69 6d 22 20 2d 20 61 20 6c  VFS "shim" - a l
01a0: 61 79 65 72 20 74 68 61 74 20 73 69 74 73 20 69  ayer that sits i
01b0: 6e 20 62 65 74 77 65 65 6e 20 74 68 65 0a 2a 2a  n between the.**
01c0: 20 70 61 67 65 72 20 61 6e 64 20 74 68 65 20 72   pager and the r
01d0: 65 61 6c 20 56 46 53 20 2d 20 74 68 61 74 20 62  eal VFS - that b
01e0: 72 65 61 6b 73 20 75 70 20 61 20 76 65 72 79 20  reaks up a very 
01f0: 6c 61 72 67 65 20 64 61 74 61 62 61 73 65 20 66  large database f
0200: 69 6c 65 0a 2a 2a 20 69 6e 74 6f 20 74 77 6f 20  ile.** into two 
0210: 6f 72 20 6d 6f 72 65 20 73 6d 61 6c 6c 65 72 20  or more smaller 
0220: 66 69 6c 65 73 20 6f 6e 20 64 69 73 6b 2e 20 20  files on disk.  
0230: 54 68 69 73 20 69 73 20 75 73 65 66 75 6c 2c 20  This is useful, 
0240: 66 6f 72 20 65 78 61 6d 70 6c 65 2c 0a 2a 2a 20  for example,.** 
0250: 69 6e 20 6f 72 64 65 72 20 74 6f 20 73 75 70 70  in order to supp
0260: 6f 72 74 20 6c 61 72 67 65 2c 20 6d 75 6c 74 69  ort large, multi
0270: 2d 67 69 67 61 62 79 74 65 20 64 61 74 61 62 61  -gigabyte databa
0280: 73 65 73 20 6f 6e 20 6f 6c 64 65 72 20 66 69 6c  ses on older fil
0290: 65 73 79 73 74 65 6d 73 0a 2a 2a 20 74 68 61 74  esystems.** that
02a0: 20 6c 69 6d 69 74 20 74 68 65 20 6d 61 78 69 6d   limit the maxim
02b0: 75 6d 20 66 69 6c 65 20 73 69 7a 65 20 74 6f 20  um file size to 
02c0: 32 20 47 69 42 2e 0a 2a 2a 0a 2a 2a 20 55 53 41  2 GiB..**.** USA
02d0: 47 45 3a 0a 2a 2a 0a 2a 2a 20 43 6f 6d 70 69 6c  GE:.**.** Compil
02e0: 65 20 74 68 69 73 20 73 6f 75 72 63 65 20 66 69  e this source fi
02f0: 6c 65 20 61 6e 64 20 6c 69 6e 6b 20 69 74 20 77  le and link it w
0300: 69 74 68 20 79 6f 75 72 20 61 70 70 6c 69 63 61  ith your applica
0310: 74 69 6f 6e 2e 20 20 54 68 65 6e 0a 2a 2a 20 61  tion.  Then.** a
0320: 74 20 73 74 61 72 74 2d 74 69 6d 65 2c 20 69 6e  t start-time, in
0330: 76 6f 6b 65 20 74 68 65 20 66 6f 6c 6c 6f 77 69  voke the followi
0340: 6e 67 20 70 72 6f 63 65 64 75 72 65 3a 0a 2a 2a  ng procedure:.**
0350: 0a 2a 2a 20 20 20 69 6e 74 20 73 71 6c 69 74 65  .**   int sqlite
0360: 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 69 6e 69 74  3_multiplex_init
0370: 69 61 6c 69 7a 65 28 0a 2a 2a 20 20 20 20 20 20  ialize(.**      
0380: 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 4f 72 69  const char *zOri
0390: 67 56 66 73 4e 61 6d 65 2c 20 20 20 20 2f 2f 20  gVfsName,    // 
03a0: 54 68 65 20 75 6e 64 65 72 6c 79 69 6e 67 20 72  The underlying r
03b0: 65 61 6c 20 56 46 53 0a 2a 2a 20 20 20 20 20 20  eal VFS.**      
03c0: 69 6e 74 20 6d 61 6b 65 44 65 66 61 75 6c 74 20  int makeDefault 
03d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2f 20               // 
03e0: 54 72 75 65 20 74 6f 20 6d 61 6b 65 20 6d 75 6c  True to make mul
03f0: 74 69 70 6c 65 78 20 74 68 65 20 64 65 66 61 75  tiplex the defau
0400: 6c 74 20 56 46 53 0a 2a 2a 20 20 20 29 3b 0a 2a  lt VFS.**   );.*
0410: 2a 0a 2a 2a 20 54 68 65 20 70 72 6f 63 65 64 75  *.** The procedu
0420: 72 65 20 63 61 6c 6c 20 61 62 6f 76 65 20 77 69  re call above wi
0430: 6c 6c 20 63 72 65 61 74 65 20 61 6e 64 20 72 65  ll create and re
0440: 67 69 73 74 65 72 20 61 20 6e 65 77 20 56 46 53  gister a new VFS
0450: 20 73 68 69 6d 20 6e 61 6d 65 64 0a 2a 2a 20 22   shim named.** "
0460: 6d 75 6c 74 69 70 6c 65 78 22 2e 20 20 54 68 65  multiplex".  The
0470: 20 6d 75 6c 74 69 70 6c 65 78 20 56 46 53 20 77   multiplex VFS w
0480: 69 6c 6c 20 75 73 65 20 74 68 65 20 56 46 53 20  ill use the VFS 
0490: 6e 61 6d 65 64 20 62 79 20 7a 4f 72 69 67 56 66  named by zOrigVf
04a0: 73 4e 61 6d 65 20 74 6f 0a 2a 2a 20 64 6f 20 74  sName to.** do t
04b0: 68 65 20 61 63 74 75 61 6c 20 64 69 73 6b 20 49  he actual disk I
04c0: 2f 4f 2e 20 20 28 54 68 65 20 7a 4f 72 69 67 56  /O.  (The zOrigV
04d0: 66 73 4e 61 6d 65 20 70 61 72 61 6d 65 74 65 72  fsName parameter
04e0: 20 6d 61 79 20 62 65 20 4e 55 4c 4c 2c 20 69 6e   may be NULL, in
04f0: 20 0a 2a 2a 20 77 68 69 63 68 20 63 61 73 65 20   .** which case 
0500: 74 68 65 20 64 65 66 61 75 6c 74 20 56 46 53 20  the default VFS 
0510: 61 74 20 74 68 65 20 6d 6f 6d 65 6e 74 20 73 71  at the moment sq
0520: 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f  lite3_multiplex_
0530: 69 6e 69 74 69 61 6c 69 7a 65 28 29 0a 2a 2a 20  initialize().** 
0540: 69 73 20 63 61 6c 6c 65 64 20 77 69 6c 6c 20 62  is called will b
0550: 65 20 75 73 65 64 20 61 73 20 74 68 65 20 75 6e  e used as the un
0560: 64 65 72 6c 79 69 6e 67 20 72 65 61 6c 20 56 46  derlying real VF
0570: 53 2e 29 20 20 0a 2a 2a 0a 2a 2a 20 49 66 20 74  S.)  .**.** If t
0580: 68 65 20 6d 61 6b 65 44 65 66 61 75 6c 74 20 70  he makeDefault p
0590: 61 72 61 6d 65 74 65 72 20 69 73 20 54 52 55 45  arameter is TRUE
05a0: 20 74 68 65 6e 20 6d 75 6c 74 69 70 6c 65 78 20   then multiplex 
05b0: 62 65 63 6f 6d 65 73 20 74 68 65 20 6e 65 77 0a  becomes the new.
05c0: 2a 2a 20 64 65 66 61 75 6c 74 20 56 46 53 2e 20  ** default VFS. 
05d0: 20 4f 74 68 65 72 77 69 73 65 2c 20 79 6f 75 20   Otherwise, you 
05e0: 63 61 6e 20 75 73 65 20 74 68 65 20 6d 75 6c 74  can use the mult
05f0: 69 70 6c 65 78 20 56 46 53 20 62 79 20 73 70 65  iplex VFS by spe
0600: 63 69 66 79 69 6e 67 0a 2a 2a 20 22 6d 75 6c 74  cifying.** "mult
0610: 69 70 6c 65 78 22 20 61 73 20 74 68 65 20 34 74  iplex" as the 4t
0620: 68 20 70 61 72 61 6d 65 74 65 72 20 74 6f 20 73  h parameter to s
0630: 71 6c 69 74 65 33 5f 6f 70 65 6e 5f 76 32 28 29  qlite3_open_v2()
0640: 20 6f 72 20 62 79 20 65 6d 70 6c 6f 79 69 6e 67   or by employing
0650: 0a 2a 2a 20 55 52 49 20 66 69 6c 65 6e 61 6d 65  .** URI filename
0660: 73 20 61 6e 64 20 61 64 64 69 6e 67 20 22 76 66  s and adding "vf
0670: 73 3d 6d 75 6c 74 69 70 6c 65 78 22 20 61 73 20  s=multiplex" as 
0680: 61 20 70 61 72 61 6d 65 74 65 72 20 74 6f 20 74  a parameter to t
0690: 68 65 20 66 69 6c 65 6e 61 6d 65 0a 2a 2a 20 55  he filename.** U
06a0: 52 49 2e 0a 2a 2a 0a 2a 2a 20 54 68 65 20 6d 75  RI..**.** The mu
06b0: 6c 74 69 70 6c 65 78 20 56 46 53 20 61 6c 6c 6f  ltiplex VFS allo
06c0: 77 73 20 64 61 74 61 62 61 73 65 73 20 75 70 20  ws databases up 
06d0: 74 6f 20 33 32 20 47 69 42 20 69 6e 20 73 69 7a  to 32 GiB in siz
06e0: 65 2e 20 20 42 75 74 20 69 74 20 73 70 6c 69 74  e.  But it split
06f0: 73 0a 2a 2a 20 74 68 65 20 66 69 6c 65 73 20 75  s.** the files u
0700: 70 20 69 6e 74 6f 20 73 6d 61 6c 6c 65 72 20 70  p into smaller p
0710: 69 65 63 65 73 2c 20 73 6f 20 74 68 61 74 20 74  ieces, so that t
0720: 68 65 79 20 77 69 6c 6c 20 77 6f 72 6b 20 65 76  hey will work ev
0730: 65 6e 20 6f 6e 20 0a 2a 2a 20 66 69 6c 65 73 79  en on .** filesy
0740: 73 74 65 6d 73 20 74 68 61 74 20 64 6f 20 6e 6f  stems that do no
0750: 74 20 73 75 70 70 6f 72 74 20 6c 61 72 67 65 20  t support large 
0760: 66 69 6c 65 73 2e 20 20 54 68 65 20 64 65 66 61  files.  The defa
0770: 75 6c 74 20 63 68 75 6e 6b 20 73 69 7a 65 0a 2a  ult chunk size.*
0780: 2a 20 69 73 20 32 31 34 37 34 31 38 31 31 32 20  * is 2147418112 
0790: 62 79 74 65 73 20 28 77 68 69 63 68 20 69 73 20  bytes (which is 
07a0: 36 34 4b 69 42 20 6c 65 73 73 20 74 68 61 6e 20  64KiB less than 
07b0: 32 47 69 42 29 20 62 75 74 20 74 68 69 73 20 63  2GiB) but this c
07c0: 61 6e 20 62 65 0a 2a 2a 20 63 68 61 6e 67 65 64  an be.** changed
07d0: 20 61 74 20 63 6f 6d 70 69 6c 65 2d 74 69 6d 65   at compile-time
07e0: 20 62 79 20 64 65 66 69 6e 69 6e 67 20 74 68 65   by defining the
07f0: 20 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45   SQLITE_MULTIPLE
0800: 58 5f 43 48 55 4e 4b 5f 53 49 5a 45 0a 2a 2a 20  X_CHUNK_SIZE.** 
0810: 6d 61 63 72 6f 2e 20 20 55 73 65 20 74 68 65 20  macro.  Use the 
0820: 22 63 68 75 6e 6b 73 69 7a 65 3d 4e 4e 4e 4e 22  "chunksize=NNNN"
0830: 20 71 75 65 72 79 20 70 61 72 61 6d 65 74 65 72   query parameter
0840: 20 77 69 74 68 20 61 20 55 52 49 20 66 69 6c 65   with a URI file
0850: 6e 61 6d 65 0a 2a 2a 20 69 6e 20 6f 72 64 65 72  name.** in order
0860: 20 74 6f 20 73 65 6c 65 63 74 20 61 6e 20 61 6c   to select an al
0870: 74 65 72 6e 61 74 69 76 65 20 63 68 75 6e 6b 20  ternative chunk 
0880: 73 69 7a 65 20 66 6f 72 20 69 6e 64 69 76 69 64  size for individ
0890: 75 61 6c 20 63 6f 6e 6e 65 63 74 69 6f 6e 73 0a  ual connections.
08a0: 2a 2a 20 61 74 20 72 75 6e 2d 74 69 6d 65 2e 0a  ** at run-time..
08b0: 2a 2f 0a 23 69 6e 63 6c 75 64 65 20 22 73 71 6c  */.#include "sql
08c0: 69 74 65 33 2e 68 22 0a 23 69 6e 63 6c 75 64 65  ite3.h".#include
08d0: 20 3c 73 74 72 69 6e 67 2e 68 3e 0a 23 69 6e 63   <string.h>.#inc
08e0: 6c 75 64 65 20 3c 61 73 73 65 72 74 2e 68 3e 0a  lude <assert.h>.
08f0: 23 69 6e 63 6c 75 64 65 20 3c 73 74 64 6c 69 62  #include <stdlib
0900: 2e 68 3e 0a 23 69 6e 63 6c 75 64 65 20 22 74 65  .h>.#include "te
0910: 73 74 5f 6d 75 6c 74 69 70 6c 65 78 2e 68 22 0a  st_multiplex.h".
0920: 0a 23 69 66 6e 64 65 66 20 53 51 4c 49 54 45 5f  .#ifndef SQLITE_
0930: 43 4f 52 45 0a 20 20 23 64 65 66 69 6e 65 20 53  CORE.  #define S
0940: 51 4c 49 54 45 5f 43 4f 52 45 20 31 20 20 2f 2a  QLITE_CORE 1  /*
0950: 20 44 69 73 61 62 6c 65 20 74 68 65 20 41 50 49   Disable the API
0960: 20 72 65 64 65 66 69 6e 69 74 69 6f 6e 20 69 6e   redefinition in
0970: 20 73 71 6c 69 74 65 33 65 78 74 2e 68 20 2a 2f   sqlite3ext.h */
0980: 0a 23 65 6e 64 69 66 0a 23 69 6e 63 6c 75 64 65  .#endif.#include
0990: 20 22 73 71 6c 69 74 65 33 65 78 74 2e 68 22 0a   "sqlite3ext.h".
09a0: 0a 2f 2a 20 0a 2a 2a 20 54 68 65 73 65 20 73 68  ./* .** These sh
09b0: 6f 75 6c 64 20 62 65 20 64 65 66 69 6e 65 64 20  ould be defined 
09c0: 74 6f 20 62 65 20 74 68 65 20 73 61 6d 65 20 61  to be the same a
09d0: 73 20 74 68 65 20 76 61 6c 75 65 73 20 69 6e 20  s the values in 
09e0: 0a 2a 2a 20 73 71 6c 69 74 65 49 6e 74 2e 68 2e  .** sqliteInt.h.
09f0: 20 20 54 68 65 79 20 61 72 65 20 64 65 66 69 6e    They are defin
0a00: 65 64 20 73 65 70 61 72 61 74 65 6c 79 20 68 65  ed separately he
0a10: 72 65 20 73 6f 20 74 68 61 74 0a 2a 2a 20 74 68  re so that.** th
0a20: 65 20 6d 75 6c 74 69 70 6c 65 78 20 56 46 53 20  e multiplex VFS 
0a30: 73 68 69 6d 20 63 61 6e 20 62 65 20 62 75 69 6c  shim can be buil
0a40: 74 20 61 73 20 61 20 6c 6f 61 64 61 62 6c 65 20  t as a loadable 
0a50: 0a 2a 2a 20 6d 6f 64 75 6c 65 2e 0a 2a 2f 0a 23  .** module..*/.#
0a60: 64 65 66 69 6e 65 20 55 4e 55 53 45 44 5f 50 41  define UNUSED_PA
0a70: 52 41 4d 45 54 45 52 28 78 29 20 28 76 6f 69 64  RAMETER(x) (void
0a80: 29 28 78 29 0a 23 64 65 66 69 6e 65 20 4d 41 58  )(x).#define MAX
0a90: 5f 50 41 47 45 5f 53 49 5a 45 20 20 20 20 20 20  _PAGE_SIZE      
0aa0: 20 30 78 31 30 30 30 30 0a 23 64 65 66 69 6e 65   0x10000.#define
0ab0: 20 44 45 46 41 55 4c 54 5f 53 45 43 54 4f 52 5f   DEFAULT_SECTOR_
0ac0: 53 49 5a 45 20 30 78 31 30 30 30 0a 0a 2f 2a 0a  SIZE 0x1000../*.
0ad0: 2a 2a 20 46 6f 72 20 61 20 62 75 69 6c 64 20 77  ** For a build w
0ae0: 69 74 68 6f 75 74 20 6d 75 74 65 78 65 73 2c 20  ithout mutexes, 
0af0: 6e 6f 2d 6f 70 20 74 68 65 20 6d 75 74 65 78 20  no-op the mutex 
0b00: 63 61 6c 6c 73 2e 0a 2a 2f 0a 23 69 66 20 64 65  calls..*/.#if de
0b10: 66 69 6e 65 64 28 53 51 4c 49 54 45 5f 54 48 52  fined(SQLITE_THR
0b20: 45 41 44 53 41 46 45 29 20 26 26 20 53 51 4c 49  EADSAFE) && SQLI
0b30: 54 45 5f 54 48 52 45 41 44 53 41 46 45 3d 3d 30  TE_THREADSAFE==0
0b40: 0a 23 64 65 66 69 6e 65 20 73 71 6c 69 74 65 33  .#define sqlite3
0b50: 5f 6d 75 74 65 78 5f 61 6c 6c 6f 63 28 58 29 20  _mutex_alloc(X) 
0b60: 20 20 20 28 28 73 71 6c 69 74 65 33 5f 6d 75 74     ((sqlite3_mut
0b70: 65 78 2a 29 38 29 0a 23 64 65 66 69 6e 65 20 73  ex*)8).#define s
0b80: 71 6c 69 74 65 33 5f 6d 75 74 65 78 5f 66 72 65  qlite3_mutex_fre
0b90: 65 28 58 29 0a 23 64 65 66 69 6e 65 20 73 71 6c  e(X).#define sql
0ba0: 69 74 65 33 5f 6d 75 74 65 78 5f 65 6e 74 65 72  ite3_mutex_enter
0bb0: 28 58 29 0a 23 64 65 66 69 6e 65 20 73 71 6c 69  (X).#define sqli
0bc0: 74 65 33 5f 6d 75 74 65 78 5f 74 72 79 28 58 29  te3_mutex_try(X)
0bd0: 20 20 20 20 20 20 53 51 4c 49 54 45 5f 4f 4b 0a        SQLITE_OK.
0be0: 23 64 65 66 69 6e 65 20 73 71 6c 69 74 65 33 5f  #define sqlite3_
0bf0: 6d 75 74 65 78 5f 6c 65 61 76 65 28 58 29 0a 23  mutex_leave(X).#
0c00: 64 65 66 69 6e 65 20 73 71 6c 69 74 65 33 5f 6d  define sqlite3_m
0c10: 75 74 65 78 5f 68 65 6c 64 28 58 29 20 20 20 20  utex_held(X)    
0c20: 20 28 28 76 6f 69 64 29 28 58 29 2c 31 29 0a 23   ((void)(X),1).#
0c30: 64 65 66 69 6e 65 20 73 71 6c 69 74 65 33 5f 6d  define sqlite3_m
0c40: 75 74 65 78 5f 6e 6f 74 68 65 6c 64 28 58 29 20  utex_notheld(X) 
0c50: 20 28 28 76 6f 69 64 29 28 58 29 2c 31 29 0a 23   ((void)(X),1).#
0c60: 65 6e 64 69 66 20 2f 2a 20 53 51 4c 49 54 45 5f  endif /* SQLITE_
0c70: 54 48 52 45 41 44 53 41 46 45 3d 3d 30 20 2a 2f  THREADSAFE==0 */
0c80: 0a 0a 2f 2a 20 4d 61 78 69 6d 75 6d 20 63 68 75  ../* Maximum chu
0c90: 6e 6b 20 6e 75 6d 62 65 72 20 2a 2f 0a 23 64 65  nk number */.#de
0ca0: 66 69 6e 65 20 4d 58 5f 43 48 55 4e 4b 5f 4e 55  fine MX_CHUNK_NU
0cb0: 4d 42 45 52 20 32 39 39 0a 0a 2f 2a 20 46 69 72  MBER 299../* Fir
0cc0: 73 74 20 63 68 75 6e 6b 20 66 6f 72 20 72 6f 6c  st chunk for rol
0cd0: 6c 62 61 63 6b 20 6a 6f 75 72 6e 61 6c 20 66 69  lback journal fi
0ce0: 6c 65 73 20 2a 2f 0a 23 64 65 66 69 6e 65 20 53  les */.#define S
0cf0: 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f  QLITE_MULTIPLEX_
0d00: 4a 4f 55 52 4e 41 4c 5f 38 5f 33 5f 4f 46 46 53  JOURNAL_8_3_OFFS
0d10: 45 54 20 34 30 30 0a 23 64 65 66 69 6e 65 20 53  ET 400.#define S
0d20: 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f  QLITE_MULTIPLEX_
0d30: 57 41 4c 5f 38 5f 33 5f 4f 46 46 53 45 54 20 37  WAL_8_3_OFFSET 7
0d40: 30 30 0a 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  00.../**********
0d50: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20 53  ************** S
0d60: 68 69 6d 20 44 65 66 69 6e 69 74 69 6f 6e 73 20  him Definitions 
0d70: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0d80: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2f 0a  **************/.
0d90: 0a 23 69 66 6e 64 65 66 20 53 51 4c 49 54 45 5f  .#ifndef SQLITE_
0da0: 4d 55 4c 54 49 50 4c 45 58 5f 56 46 53 5f 4e 41  MULTIPLEX_VFS_NA
0db0: 4d 45 0a 23 20 64 65 66 69 6e 65 20 53 51 4c 49  ME.# define SQLI
0dc0: 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 56 46 53  TE_MULTIPLEX_VFS
0dd0: 5f 4e 41 4d 45 20 22 6d 75 6c 74 69 70 6c 65 78  _NAME "multiplex
0de0: 22 0a 23 65 6e 64 69 66 0a 0a 2f 2a 20 54 68 69  ".#endif../* Thi
0df0: 73 20 69 73 20 74 68 65 20 6c 69 6d 69 74 20 6f  s is the limit o
0e00: 6e 20 74 68 65 20 63 68 75 6e 6b 20 73 69 7a 65  n the chunk size
0e10: 2e 20 20 49 74 20 6d 61 79 20 62 65 20 63 68 61  .  It may be cha
0e20: 6e 67 65 64 20 62 79 20 63 61 6c 6c 69 6e 67 0a  nged by calling.
0e30: 2a 2a 20 74 68 65 20 78 46 69 6c 65 43 6f 6e 74  ** the xFileCont
0e40: 72 6f 6c 28 29 20 69 6e 74 65 72 66 61 63 65 2e  rol() interface.
0e50: 20 20 49 74 20 77 69 6c 6c 20 62 65 20 72 6f 75    It will be rou
0e60: 6e 64 65 64 20 75 70 20 74 6f 20 61 20 0a 2a 2a  nded up to a .**
0e70: 20 6d 75 6c 74 69 70 6c 65 20 6f 66 20 4d 41 58   multiple of MAX
0e80: 5f 50 41 47 45 5f 53 49 5a 45 2e 20 20 57 65 20  _PAGE_SIZE.  We 
0e90: 64 65 66 61 75 6c 74 20 69 74 20 68 65 72 65 20  default it here 
0ea0: 74 6f 20 32 47 69 42 20 6c 65 73 73 20 36 34 4b  to 2GiB less 64K
0eb0: 69 42 2e 0a 2a 2f 0a 23 69 66 6e 64 65 66 20 53  iB..*/.#ifndef S
0ec0: 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f  QLITE_MULTIPLEX_
0ed0: 43 48 55 4e 4b 5f 53 49 5a 45 0a 23 20 64 65 66  CHUNK_SIZE.# def
0ee0: 69 6e 65 20 53 51 4c 49 54 45 5f 4d 55 4c 54 49  ine SQLITE_MULTI
0ef0: 50 4c 45 58 5f 43 48 55 4e 4b 5f 53 49 5a 45 20  PLEX_CHUNK_SIZE 
0f00: 32 31 34 37 34 31 38 31 31 32 0a 23 65 6e 64 69  2147418112.#endi
0f10: 66 0a 0a 2f 2a 20 54 68 69 73 20 75 73 65 64 20  f../* This used 
0f20: 74 6f 20 62 65 20 74 68 65 20 64 65 66 61 75 6c  to be the defaul
0f30: 74 20 6c 69 6d 69 74 20 6f 6e 20 6e 75 6d 62 65  t limit on numbe
0f40: 72 20 6f 66 20 63 68 75 6e 6b 73 2c 20 62 75 74  r of chunks, but
0f50: 0a 2a 2a 20 69 74 20 69 73 20 6e 6f 20 6c 6f 6e  .** it is no lon
0f60: 67 65 72 20 65 6e 66 6f 72 63 65 64 2e 20 54 68  ger enforced. Th
0f70: 65 72 65 20 69 73 20 63 75 72 72 65 6e 74 6c 79  ere is currently
0f80: 20 6e 6f 20 6c 69 6d 69 74 20 74 6f 20 74 68 65   no limit to the
0f90: 0a 2a 2a 20 6e 75 6d 62 65 72 20 6f 66 20 63 68  .** number of ch
0fa0: 75 6e 6b 73 2e 0a 2a 2a 0a 2a 2a 20 4d 61 79 20  unks..**.** May 
0fb0: 62 65 20 63 68 61 6e 67 65 64 20 62 79 20 63 61  be changed by ca
0fc0: 6c 6c 69 6e 67 20 74 68 65 20 78 46 69 6c 65 43  lling the xFileC
0fd0: 6f 6e 74 72 6f 6c 28 29 20 69 6e 74 65 72 66 61  ontrol() interfa
0fe0: 63 65 2e 0a 2a 2f 0a 23 69 66 6e 64 65 66 20 53  ce..*/.#ifndef S
0ff0: 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f  QLITE_MULTIPLEX_
1000: 4d 41 58 5f 43 48 55 4e 4b 53 0a 23 20 64 65 66  MAX_CHUNKS.# def
1010: 69 6e 65 20 53 51 4c 49 54 45 5f 4d 55 4c 54 49  ine SQLITE_MULTI
1020: 50 4c 45 58 5f 4d 41 58 5f 43 48 55 4e 4b 53 20  PLEX_MAX_CHUNKS 
1030: 31 32 0a 23 65 6e 64 69 66 0a 0a 2f 2a 2a 2a 2a  12.#endif../****
1040: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1050: 2a 2a 2a 2a 20 4f 62 6a 65 63 74 20 44 65 66 69  **** Object Defi
1060: 6e 69 74 69 6f 6e 73 20 2a 2a 2a 2a 2a 2a 2a 2a  nitions ********
1070: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1080: 2a 2a 2a 2a 2a 2a 2f 0a 0a 2f 2a 20 46 6f 72 77  ******/../* Forw
1090: 61 72 64 20 64 65 63 6c 61 72 61 74 69 6f 6e 20  ard declaration 
10a0: 6f 66 20 61 6c 6c 20 6f 62 6a 65 63 74 20 74 79  of all object ty
10b0: 70 65 73 20 2a 2f 0a 74 79 70 65 64 65 66 20 73  pes */.typedef s
10c0: 74 72 75 63 74 20 6d 75 6c 74 69 70 6c 65 78 47  truct multiplexG
10d0: 72 6f 75 70 20 6d 75 6c 74 69 70 6c 65 78 47 72  roup multiplexGr
10e0: 6f 75 70 3b 0a 74 79 70 65 64 65 66 20 73 74 72  oup;.typedef str
10f0: 75 63 74 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e  uct multiplexCon
1100: 6e 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 3b  n multiplexConn;
1110: 0a 0a 2f 2a 0a 2a 2a 20 41 20 22 6d 75 6c 74 69  ../*.** A "multi
1120: 70 6c 65 78 20 67 72 6f 75 70 22 20 69 73 20 61  plex group" is a
1130: 20 63 6f 6c 6c 65 63 74 69 6f 6e 20 6f 66 20 66   collection of f
1140: 69 6c 65 73 20 74 68 61 74 20 63 6f 6c 6c 65 63  iles that collec
1150: 74 69 76 65 6c 79 0a 2a 2a 20 6d 61 6b 65 75 70  tively.** makeup
1160: 20 61 20 73 69 6e 67 6c 65 20 53 51 4c 69 74 65   a single SQLite
1170: 20 44 42 20 66 69 6c 65 2e 20 20 54 68 69 73 20   DB file.  This 
1180: 61 6c 6c 6f 77 73 20 74 68 65 20 73 69 7a 65 20  allows the size 
1190: 6f 66 20 74 68 65 20 44 42 0a 2a 2a 20 74 6f 20  of the DB.** to 
11a0: 65 78 63 65 65 64 20 74 68 65 20 6c 69 6d 69 74  exceed the limit
11b0: 73 20 69 6d 70 6f 73 65 64 20 62 79 20 74 68 65  s imposed by the
11c0: 20 66 69 6c 65 20 73 79 73 74 65 6d 2e 0a 2a 2a   file system..**
11d0: 0a 2a 2a 20 54 68 65 72 65 20 69 73 20 61 6e 20  .** There is an 
11e0: 69 6e 73 74 61 6e 63 65 20 6f 66 20 74 68 65 20  instance of the 
11f0: 66 6f 6c 6c 6f 77 69 6e 67 20 6f 62 6a 65 63 74  following object
1200: 20 66 6f 72 20 65 61 63 68 20 64 65 66 69 6e 65   for each define
1210: 64 20 6d 75 6c 74 69 70 6c 65 78 0a 2a 2a 20 67  d multiplex.** g
1220: 72 6f 75 70 2e 0a 2a 2f 0a 73 74 72 75 63 74 20  roup..*/.struct 
1230: 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 7b  multiplexGroup {
1240: 0a 20 20 73 74 72 75 63 74 20 6d 75 6c 74 69 70  .  struct multip
1250: 6c 65 78 52 65 61 6c 20 7b 20 20 20 20 20 20 20  lexReal {       
1260: 20 20 20 20 2f 2a 20 46 6f 72 20 65 61 63 68 20      /* For each 
1270: 63 68 75 6e 6b 20 2a 2f 0a 20 20 20 20 73 71 6c  chunk */.    sql
1280: 69 74 65 33 5f 66 69 6c 65 20 2a 70 3b 20 20 20  ite3_file *p;   
1290: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
12a0: 2a 20 48 61 6e 64 6c 65 20 66 6f 72 20 74 68 65  * Handle for the
12b0: 20 63 68 75 6e 6b 20 2a 2f 0a 20 20 20 20 63 68   chunk */.    ch
12c0: 61 72 20 2a 7a 3b 20 20 20 20 20 20 20 20 20 20  ar *z;          
12d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
12e0: 2f 2a 20 4e 61 6d 65 20 6f 66 20 74 68 69 73 20  /* Name of this 
12f0: 63 68 75 6e 6b 20 2a 2f 0a 20 20 7d 20 2a 61 52  chunk */.  } *aR
1300: 65 61 6c 3b 20 20 20 20 20 20 20 20 20 20 20 20  eal;            
1310: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 6c              /* l
1320: 69 73 74 20 6f 66 20 61 6c 6c 20 63 68 75 6e 6b  ist of all chunk
1330: 73 20 2a 2f 0a 20 20 69 6e 74 20 6e 52 65 61 6c  s */.  int nReal
1340: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ;               
1350: 20 20 20 20 20 20 20 20 2f 2a 20 4e 75 6d 62 65          /* Numbe
1360: 72 20 6f 66 20 63 68 75 6e 6b 73 20 2a 2f 0a 20  r of chunks */. 
1370: 20 63 68 61 72 20 2a 7a 4e 61 6d 65 3b 20 20 20   char *zName;   
1380: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1390: 20 20 2f 2a 20 42 61 73 65 20 66 69 6c 65 6e 61    /* Base filena
13a0: 6d 65 20 6f 66 20 74 68 69 73 20 67 72 6f 75 70  me of this group
13b0: 20 2a 2f 0a 20 20 69 6e 74 20 6e 4e 61 6d 65 3b   */.  int nName;
13c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
13d0: 20 20 20 20 20 20 20 2f 2a 20 4c 65 6e 67 74 68         /* Length
13e0: 20 6f 66 20 62 61 73 65 20 66 69 6c 65 6e 61 6d   of base filenam
13f0: 65 20 2a 2f 0a 20 20 69 6e 74 20 66 6c 61 67 73  e */.  int flags
1400: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ;               
1410: 20 20 20 20 20 20 20 20 2f 2a 20 46 6c 61 67 73          /* Flags
1420: 20 75 73 65 64 20 66 6f 72 20 6f 72 69 67 69 6e   used for origin
1430: 61 6c 20 6f 70 65 6e 69 6e 67 20 2a 2f 0a 20 20  al opening */.  
1440: 75 6e 73 69 67 6e 65 64 20 69 6e 74 20 73 7a 43  unsigned int szC
1450: 68 75 6e 6b 3b 20 20 20 20 20 20 20 20 20 20 20  hunk;           
1460: 20 2f 2a 20 43 68 75 6e 6b 20 73 69 7a 65 20 75   /* Chunk size u
1470: 73 65 64 20 66 6f 72 20 74 68 69 73 20 67 72 6f  sed for this gro
1480: 75 70 20 2a 2f 0a 20 20 75 6e 73 69 67 6e 65 64  up */.  unsigned
1490: 20 63 68 61 72 20 62 45 6e 61 62 6c 65 64 3b 20   char bEnabled; 
14a0: 20 20 20 20 20 20 20 20 20 2f 2a 20 54 52 55 45           /* TRUE
14b0: 20 74 6f 20 75 73 65 20 4d 75 6c 74 69 70 6c 65   to use Multiple
14c0: 78 20 56 46 53 20 66 6f 72 20 74 68 69 73 20 66  x VFS for this f
14d0: 69 6c 65 20 2a 2f 0a 20 20 75 6e 73 69 67 6e 65  ile */.  unsigne
14e0: 64 20 63 68 61 72 20 62 54 72 75 6e 63 61 74 65  d char bTruncate
14f0: 3b 20 20 20 20 20 20 20 20 20 2f 2a 20 54 52 55  ;         /* TRU
1500: 45 20 74 6f 20 65 6e 61 62 6c 65 20 74 72 75 6e  E to enable trun
1510: 63 61 74 69 6f 6e 20 6f 66 20 64 61 74 61 62 61  cation of databa
1520: 73 65 73 20 2a 2f 0a 20 20 6d 75 6c 74 69 70 6c  ses */.  multipl
1530: 65 78 47 72 6f 75 70 20 2a 70 4e 65 78 74 2c 20  exGroup *pNext, 
1540: 2a 70 50 72 65 76 3b 20 20 20 2f 2a 20 44 6f 75  *pPrev;   /* Dou
1550: 62 6c 79 20 6c 69 6e 6b 65 64 20 6c 69 73 74 20  bly linked list 
1560: 6f 66 20 61 6c 6c 20 67 72 6f 75 70 20 6f 62 6a  of all group obj
1570: 65 63 74 73 20 2a 2f 0a 7d 3b 0a 0a 2f 2a 0a 2a  ects */.};../*.*
1580: 2a 20 41 6e 20 69 6e 73 74 61 6e 63 65 20 6f 66  * An instance of
1590: 20 74 68 65 20 66 6f 6c 6c 6f 77 69 6e 67 20 6f   the following o
15a0: 62 6a 65 63 74 20 72 65 70 72 65 73 65 6e 74 73  bject represents
15b0: 20 65 61 63 68 20 6f 70 65 6e 20 63 6f 6e 6e 65   each open conne
15c0: 63 74 69 6f 6e 0a 2a 2a 20 74 6f 20 61 20 66 69  ction.** to a fi
15d0: 6c 65 20 74 68 61 74 20 69 73 20 6d 75 6c 74 69  le that is multi
15e0: 70 6c 65 78 27 65 64 2e 20 20 54 68 69 73 20 6f  plex'ed.  This o
15f0: 62 6a 65 63 74 20 69 73 20 61 20 0a 2a 2a 20 73  bject is a .** s
1600: 75 62 63 6c 61 73 73 20 6f 66 20 73 71 6c 69 74  ubclass of sqlit
1610: 65 33 5f 66 69 6c 65 2e 20 20 54 68 65 20 73 71  e3_file.  The sq
1620: 6c 69 74 65 33 5f 66 69 6c 65 20 6f 62 6a 65 63  lite3_file objec
1630: 74 20 66 6f 72 20 74 68 65 20 75 6e 64 65 72 6c  t for the underl
1640: 79 69 6e 67 0a 2a 2a 20 56 46 53 20 69 73 20 61  ying.** VFS is a
1650: 70 70 65 6e 64 65 64 20 74 6f 20 74 68 69 73 20  ppended to this 
1660: 73 74 72 75 63 74 75 72 65 2e 0a 2a 2f 0a 73 74  structure..*/.st
1670: 72 75 63 74 20 6d 75 6c 74 69 70 6c 65 78 43 6f  ruct multiplexCo
1680: 6e 6e 20 7b 0a 20 20 73 71 6c 69 74 65 33 5f 66  nn {.  sqlite3_f
1690: 69 6c 65 20 62 61 73 65 3b 20 20 20 20 20 20 20  ile base;       
16a0: 20 20 20 20 20 20 20 2f 2a 20 42 61 73 65 20 63         /* Base c
16b0: 6c 61 73 73 20 2d 20 6d 75 73 74 20 62 65 20 66  lass - must be f
16c0: 69 72 73 74 20 2a 2f 0a 20 20 6d 75 6c 74 69 70  irst */.  multip
16d0: 6c 65 78 47 72 6f 75 70 20 2a 70 47 72 6f 75 70  lexGroup *pGroup
16e0: 3b 20 20 20 20 20 20 20 20 20 2f 2a 20 54 68 65  ;         /* The
16f0: 20 75 6e 64 65 72 6c 79 69 6e 67 20 67 72 6f 75   underlying grou
1700: 70 20 6f 66 20 66 69 6c 65 73 20 2a 2f 0a 7d 3b  p of files */.};
1710: 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ../*************
1720: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20 47 6c 6f  ************ Glo
1730: 62 61 6c 20 56 61 72 69 61 62 6c 65 73 20 2a 2a  bal Variables **
1740: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1750: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1760: 2f 0a 2f 2a 0a 2a 2a 20 41 6c 6c 20 67 6c 6f 62  /./*.** All glob
1770: 61 6c 20 76 61 72 69 61 62 6c 65 73 20 75 73 65  al variables use
1780: 64 20 62 79 20 74 68 69 73 20 66 69 6c 65 20 61  d by this file a
1790: 72 65 20 63 6f 6e 74 61 69 6e 69 6e 67 20 77 69  re containing wi
17a0: 74 68 69 6e 20 74 68 65 20 66 6f 6c 6c 6f 77 69  thin the followi
17b0: 6e 67 0a 2a 2a 20 67 4d 75 6c 74 69 70 6c 65 78  ng.** gMultiplex
17c0: 20 73 74 72 75 63 74 75 72 65 2e 0a 2a 2f 0a 73   structure..*/.s
17d0: 74 61 74 69 63 20 73 74 72 75 63 74 20 7b 0a 20  tatic struct {. 
17e0: 20 2f 2a 20 54 68 65 20 70 4f 72 69 67 56 66 73   /* The pOrigVfs
17f0: 20 69 73 20 74 68 65 20 72 65 61 6c 2c 20 6f 72   is the real, or
1800: 69 67 69 6e 61 6c 20 75 6e 64 65 72 6c 79 69 6e  iginal underlyin
1810: 67 20 56 46 53 20 69 6d 70 6c 65 6d 65 6e 74 61  g VFS implementa
1820: 74 69 6f 6e 2e 0a 20 20 2a 2a 20 4d 6f 73 74 20  tion..  ** Most 
1830: 6f 70 65 72 61 74 69 6f 6e 73 20 70 61 73 73 2d  operations pass-
1840: 74 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20 72  through to the r
1850: 65 61 6c 20 56 46 53 2e 20 20 54 68 69 73 20 76  eal VFS.  This v
1860: 61 6c 75 65 20 69 73 20 72 65 61 64 2d 6f 6e 6c  alue is read-onl
1870: 79 0a 20 20 2a 2a 20 64 75 72 69 6e 67 20 6f 70  y.  ** during op
1880: 65 72 61 74 69 6f 6e 2e 20 20 49 74 20 69 73 20  eration.  It is 
1890: 6f 6e 6c 79 20 6d 6f 64 69 66 69 65 64 20 61 74  only modified at
18a0: 20 73 74 61 72 74 2d 74 69 6d 65 20 61 6e 64 20   start-time and 
18b0: 74 68 75 73 20 64 6f 65 73 20 6e 6f 74 0a 20 20  thus does not.  
18c0: 2a 2a 20 72 65 71 75 69 72 65 20 61 20 6d 75 74  ** require a mut
18d0: 65 78 2e 0a 20 20 2a 2f 0a 20 20 73 71 6c 69 74  ex..  */.  sqlit
18e0: 65 33 5f 76 66 73 20 2a 70 4f 72 69 67 56 66 73  e3_vfs *pOrigVfs
18f0: 3b 0a 0a 20 20 2f 2a 20 54 68 65 20 73 54 68 69  ;..  /* The sThi
1900: 73 56 66 73 20 69 73 20 74 68 65 20 56 46 53 20  sVfs is the VFS 
1910: 73 74 72 75 63 74 75 72 65 20 75 73 65 64 20 62  structure used b
1920: 79 20 74 68 69 73 20 73 68 69 6d 2e 20 20 49 74  y this shim.  It
1930: 20 69 73 20 69 6e 69 74 69 61 6c 69 7a 65 64 0a   is initialized.
1940: 20 20 2a 2a 20 61 74 20 73 74 61 72 74 2d 74 69    ** at start-ti
1950: 6d 65 20 61 6e 64 20 74 68 75 73 20 64 6f 65 73  me and thus does
1960: 20 6e 6f 74 20 72 65 71 75 69 72 65 20 61 20 6d   not require a m
1970: 75 74 65 78 0a 20 20 2a 2f 0a 20 20 73 71 6c 69  utex.  */.  sqli
1980: 74 65 33 5f 76 66 73 20 73 54 68 69 73 56 66 73  te3_vfs sThisVfs
1990: 3b 0a 0a 20 20 2f 2a 20 54 68 65 20 73 49 6f 4d  ;..  /* The sIoM
19a0: 65 74 68 6f 64 73 20 64 65 66 69 6e 65 73 20 74  ethods defines t
19b0: 68 65 20 6d 65 74 68 6f 64 73 20 75 73 65 64 20  he methods used 
19c0: 62 79 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20  by sqlite3_file 
19d0: 6f 62 6a 65 63 74 73 20 0a 20 20 2a 2a 20 61 73  objects .  ** as
19e0: 73 6f 63 69 61 74 65 64 20 77 69 74 68 20 74 68  sociated with th
19f0: 69 73 20 73 68 69 6d 2e 20 20 49 74 20 69 73 20  is shim.  It is 
1a00: 69 6e 69 74 69 61 6c 69 7a 65 64 20 61 74 20 73  initialized at s
1a10: 74 61 72 74 2d 74 69 6d 65 20 61 6e 64 20 64 6f  tart-time and do
1a20: 65 73 0a 20 20 2a 2a 20 6e 6f 74 20 72 65 71 75  es.  ** not requ
1a30: 69 72 65 20 61 20 6d 75 74 65 78 2e 0a 20 20 2a  ire a mutex..  *
1a40: 2a 0a 20 20 2a 2a 20 57 68 65 6e 20 74 68 65 20  *.  ** When the 
1a50: 75 6e 64 65 72 6c 79 69 6e 67 20 56 46 53 20 69  underlying VFS i
1a60: 73 20 63 61 6c 6c 65 64 20 74 6f 20 6f 70 65 6e  s called to open
1a70: 20 61 20 66 69 6c 65 2c 20 69 74 20 6d 69 67 68   a file, it migh
1a80: 74 20 72 65 74 75 72 6e 20 0a 20 20 2a 2a 20 65  t return .  ** e
1a90: 69 74 68 65 72 20 61 20 76 65 72 73 69 6f 6e 20  ither a version 
1aa0: 31 20 6f 72 20 61 20 76 65 72 73 69 6f 6e 20 32  1 or a version 2
1ab0: 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 6f 62   sqlite3_file ob
1ac0: 6a 65 63 74 2e 20 20 54 68 69 73 20 73 68 69 6d  ject.  This shim
1ad0: 0a 20 20 2a 2a 20 68 61 73 20 74 6f 20 63 72 65  .  ** has to cre
1ae0: 61 74 65 20 61 20 77 72 61 70 70 65 72 20 73 71  ate a wrapper sq
1af0: 6c 69 74 65 33 5f 66 69 6c 65 20 6f 66 20 74 68  lite3_file of th
1b00: 65 20 73 61 6d 65 20 76 65 72 73 69 6f 6e 2e 20  e same version. 
1b10: 20 48 65 6e 63 65 0a 20 20 2a 2a 20 74 68 65 72   Hence.  ** ther
1b20: 65 20 61 72 65 20 74 77 6f 20 49 2f 4f 20 6d 65  e are two I/O me
1b30: 74 68 6f 64 20 73 74 72 75 63 74 75 72 65 73 2c  thod structures,
1b40: 20 6f 6e 65 20 66 6f 72 20 76 65 72 73 69 6f 6e   one for version
1b50: 20 31 20 61 6e 64 20 74 68 65 20 6f 74 68 65 72   1 and the other
1b60: 0a 20 20 2a 2a 20 66 6f 72 20 76 65 72 73 69 6f  .  ** for versio
1b70: 6e 20 32 2e 0a 20 20 2a 2f 0a 20 20 73 71 6c 69  n 2..  */.  sqli
1b80: 74 65 33 5f 69 6f 5f 6d 65 74 68 6f 64 73 20 73  te3_io_methods s
1b90: 49 6f 4d 65 74 68 6f 64 73 56 31 3b 0a 20 20 73  IoMethodsV1;.  s
1ba0: 71 6c 69 74 65 33 5f 69 6f 5f 6d 65 74 68 6f 64  qlite3_io_method
1bb0: 73 20 73 49 6f 4d 65 74 68 6f 64 73 56 32 3b 0a  s sIoMethodsV2;.
1bc0: 0a 20 20 2f 2a 20 54 72 75 65 20 77 68 65 6e 20  .  /* True when 
1bd0: 74 68 69 73 20 73 68 69 6d 20 68 61 73 20 62 65  this shim has be
1be0: 65 6e 20 69 6e 69 74 69 61 6c 69 7a 65 64 2e 0a  en initialized..
1bf0: 20 20 2a 2f 0a 20 20 69 6e 74 20 69 73 49 6e 69    */.  int isIni
1c00: 74 69 61 6c 69 7a 65 64 3b 0a 0a 20 20 2f 2a 20  tialized;..  /* 
1c10: 46 6f 72 20 72 75 6e 2d 74 69 6d 65 20 61 63 63  For run-time acc
1c20: 65 73 73 20 61 6e 79 20 6f 66 20 74 68 65 20 6f  ess any of the o
1c30: 74 68 65 72 20 67 6c 6f 62 61 6c 20 64 61 74 61  ther global data
1c40: 20 73 74 72 75 63 74 75 72 65 73 20 69 6e 20 74   structures in t
1c50: 68 69 73 0a 20 20 2a 2a 20 73 68 69 6d 2c 20 74  his.  ** shim, t
1c60: 68 65 20 66 6f 6c 6c 6f 77 69 6e 67 20 6d 75 74  he following mut
1c70: 65 78 20 6d 75 73 74 20 62 65 20 68 65 6c 64 2e  ex must be held.
1c80: 0a 20 20 2a 2f 0a 20 20 73 71 6c 69 74 65 33 5f  .  */.  sqlite3_
1c90: 6d 75 74 65 78 20 2a 70 4d 75 74 65 78 3b 0a 0a  mutex *pMutex;..
1ca0: 20 20 2f 2a 20 4c 69 73 74 20 6f 66 20 6d 75 6c    /* List of mul
1cb0: 74 69 70 6c 65 78 47 72 6f 75 70 20 6f 62 6a 65  tiplexGroup obje
1cc0: 63 74 73 2e 0a 20 20 2a 2f 0a 20 20 6d 75 6c 74  cts..  */.  mult
1cd0: 69 70 6c 65 78 47 72 6f 75 70 20 2a 70 47 72 6f  iplexGroup *pGro
1ce0: 75 70 73 3b 0a 7d 20 67 4d 75 6c 74 69 70 6c 65  ups;.} gMultiple
1cf0: 78 3b 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  x;../***********
1d00: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20 55  ************** U
1d10: 74 69 6c 69 74 79 20 52 6f 75 74 69 6e 65 73 20  tility Routines 
1d20: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1d30: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1d40: 2a 2f 0a 2f 2a 0a 2a 2a 20 41 63 71 75 69 72 65  */./*.** Acquire
1d50: 20 61 6e 64 20 72 65 6c 65 61 73 65 20 74 68 65   and release the
1d60: 20 6d 75 74 65 78 20 75 73 65 64 20 74 6f 20 73   mutex used to s
1d70: 65 72 69 61 6c 69 7a 65 20 61 63 63 65 73 73 20  erialize access 
1d80: 74 6f 20 74 68 65 0a 2a 2a 20 6c 69 73 74 20 6f  to the.** list o
1d90: 66 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70  f multiplexGroup
1da0: 73 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 76 6f 69  s..*/.static voi
1db0: 64 20 6d 75 6c 74 69 70 6c 65 78 45 6e 74 65 72  d multiplexEnter
1dc0: 28 76 6f 69 64 29 7b 20 73 71 6c 69 74 65 33 5f  (void){ sqlite3_
1dd0: 6d 75 74 65 78 5f 65 6e 74 65 72 28 67 4d 75 6c  mutex_enter(gMul
1de0: 74 69 70 6c 65 78 2e 70 4d 75 74 65 78 29 3b 20  tiplex.pMutex); 
1df0: 7d 0a 73 74 61 74 69 63 20 76 6f 69 64 20 6d 75  }.static void mu
1e00: 6c 74 69 70 6c 65 78 4c 65 61 76 65 28 76 6f 69  ltiplexLeave(voi
1e10: 64 29 7b 20 73 71 6c 69 74 65 33 5f 6d 75 74 65  d){ sqlite3_mute
1e20: 78 5f 6c 65 61 76 65 28 67 4d 75 6c 74 69 70 6c  x_leave(gMultipl
1e30: 65 78 2e 70 4d 75 74 65 78 29 3b 20 7d 0a 0a 2f  ex.pMutex); }../
1e40: 2a 0a 2a 2a 20 43 6f 6d 70 75 74 65 20 61 20 73  *.** Compute a s
1e50: 74 72 69 6e 67 20 6c 65 6e 67 74 68 20 74 68 61  tring length tha
1e60: 74 20 69 73 20 6c 69 6d 69 74 65 64 20 74 6f 20  t is limited to 
1e70: 77 68 61 74 20 63 61 6e 20 62 65 20 73 74 6f 72  what can be stor
1e80: 65 64 20 69 6e 0a 2a 2a 20 6c 6f 77 65 72 20 33  ed in.** lower 3
1e90: 30 20 62 69 74 73 20 6f 66 20 61 20 33 32 2d 62  0 bits of a 32-b
1ea0: 69 74 20 73 69 67 6e 65 64 20 69 6e 74 65 67 65  it signed intege
1eb0: 72 2e 0a 2a 2a 0a 2a 2a 20 54 68 65 20 76 61 6c  r..**.** The val
1ec0: 75 65 20 72 65 74 75 72 6e 65 64 20 77 69 6c 6c  ue returned will
1ed0: 20 6e 65 76 65 72 20 62 65 20 6e 65 67 61 74 69   never be negati
1ee0: 76 65 2e 20 20 4e 6f 72 20 77 69 6c 6c 20 69 74  ve.  Nor will it
1ef0: 20 65 76 65 72 20 62 65 20 67 72 65 61 74 65 72   ever be greater
1f00: 0a 2a 2a 20 74 68 61 6e 20 74 68 65 20 61 63 74  .** than the act
1f10: 75 61 6c 20 6c 65 6e 67 74 68 20 6f 66 20 74 68  ual length of th
1f20: 65 20 73 74 72 69 6e 67 2e 20 20 46 6f 72 20 76  e string.  For v
1f30: 65 72 79 20 6c 6f 6e 67 20 73 74 72 69 6e 67 73  ery long strings
1f40: 20 28 67 72 65 61 74 65 72 0a 2a 2a 20 74 68 61   (greater.** tha
1f50: 6e 20 31 47 69 42 29 20 74 68 65 20 76 61 6c 75  n 1GiB) the valu
1f60: 65 20 72 65 74 75 72 6e 65 64 20 6d 69 67 68 74  e returned might
1f70: 20 62 65 20 6c 65 73 73 20 74 68 61 6e 20 74 68   be less than th
1f80: 65 20 74 72 75 65 20 73 74 72 69 6e 67 20 6c 65  e true string le
1f90: 6e 67 74 68 2e 0a 2a 2f 0a 73 74 61 74 69 63 20  ngth..*/.static 
1fa0: 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 53 74 72  int multiplexStr
1fb0: 6c 65 6e 33 30 28 63 6f 6e 73 74 20 63 68 61 72  len30(const char
1fc0: 20 2a 7a 29 7b 0a 20 20 63 6f 6e 73 74 20 63 68   *z){.  const ch
1fd0: 61 72 20 2a 7a 32 20 3d 20 7a 3b 0a 20 20 69 66  ar *z2 = z;.  if
1fe0: 28 20 7a 3d 3d 30 20 29 20 72 65 74 75 72 6e 20  ( z==0 ) return 
1ff0: 30 3b 0a 20 20 77 68 69 6c 65 28 20 2a 7a 32 20  0;.  while( *z2 
2000: 29 7b 20 7a 32 2b 2b 3b 20 7d 0a 20 20 72 65 74  ){ z2++; }.  ret
2010: 75 72 6e 20 30 78 33 66 66 66 66 66 66 66 20 26  urn 0x3fffffff &
2020: 20 28 69 6e 74 29 28 7a 32 20 2d 20 7a 29 3b 0a   (int)(z2 - z);.
2030: 7d 0a 0a 2f 2a 0a 2a 2a 20 47 65 6e 65 72 61 74  }../*.** Generat
2040: 65 20 74 68 65 20 66 69 6c 65 2d 6e 61 6d 65 20  e the file-name 
2050: 66 6f 72 20 63 68 75 6e 6b 20 69 43 68 75 6e 6b  for chunk iChunk
2060: 20 6f 66 20 74 68 65 20 67 72 6f 75 70 20 77 69   of the group wi
2070: 74 68 20 62 61 73 65 20 6e 61 6d 65 0a 2a 2a 20  th base name.** 
2080: 7a 42 61 73 65 2e 20 54 68 65 20 66 69 6c 65 2d  zBase. The file-
2090: 6e 61 6d 65 20 69 73 20 77 72 69 74 74 65 6e 20  name is written 
20a0: 74 6f 20 62 75 66 66 65 72 20 7a 4f 75 74 20 62  to buffer zOut b
20b0: 65 66 6f 72 65 20 72 65 74 75 72 6e 69 6e 67 2e  efore returning.
20c0: 20 42 75 66 66 65 72 0a 2a 2a 20 7a 4f 75 74 20   Buffer.** zOut 
20d0: 6d 75 73 74 20 62 65 20 61 6c 6c 6f 63 61 74 65  must be allocate
20e0: 64 20 62 79 20 74 68 65 20 63 61 6c 6c 65 72 20  d by the caller 
20f0: 73 6f 20 74 68 61 74 20 69 74 20 69 73 20 61 74  so that it is at
2100: 20 6c 65 61 73 74 20 28 6e 42 61 73 65 2b 35 29   least (nBase+5)
2110: 0a 2a 2a 20 62 79 74 65 73 20 69 6e 20 73 69 7a  .** bytes in siz
2120: 65 2c 20 77 68 65 72 65 20 6e 42 61 73 65 20 69  e, where nBase i
2130: 73 20 74 68 65 20 6c 65 6e 67 74 68 20 6f 66 20  s the length of 
2140: 7a 42 61 73 65 2c 20 6e 6f 74 20 69 6e 63 6c 75  zBase, not inclu
2150: 64 69 6e 67 20 74 68 65 0a 2a 2a 20 6e 75 6c 2d  ding the.** nul-
2160: 74 65 72 6d 69 6e 61 74 6f 72 2e 0a 2a 2a 0a 2a  terminator..**.*
2170: 2a 20 49 66 20 69 43 68 75 6e 6b 20 69 73 20 30  * If iChunk is 0
2180: 20 28 6f 72 20 34 30 30 20 2d 20 74 68 65 20 6e   (or 400 - the n
2190: 75 6d 62 65 72 20 66 6f 72 20 74 68 65 20 66 69  umber for the fi
21a0: 72 73 74 20 6a 6f 75 72 6e 61 6c 20 66 69 6c 65  rst journal file
21b0: 20 63 68 75 6e 6b 29 2c 0a 2a 2a 20 74 68 65 20   chunk),.** the 
21c0: 6f 75 74 70 75 74 20 69 73 20 61 20 63 6f 70 79  output is a copy
21d0: 20 6f 66 20 74 68 65 20 69 6e 70 75 74 20 73 74   of the input st
21e0: 72 69 6e 67 2e 20 4f 74 68 65 72 77 69 73 65 2c  ring. Otherwise,
21f0: 20 69 66 20 0a 2a 2a 20 53 51 4c 49 54 45 5f 45   if .** SQLITE_E
2200: 4e 41 42 4c 45 5f 38 5f 33 5f 4e 41 4d 45 53 20  NABLE_8_3_NAMES 
2210: 69 73 20 6e 6f 74 20 64 65 66 69 6e 65 64 20 6f  is not defined o
2220: 72 20 74 68 65 20 69 6e 70 75 74 20 62 75 66 66  r the input buff
2230: 65 72 20 64 6f 65 73 20 6e 6f 74 20 63 6f 6e 74  er does not cont
2240: 61 69 6e 0a 2a 2a 20 61 20 22 2e 22 20 63 68 61  ain.** a "." cha
2250: 72 61 63 74 65 72 2c 20 74 68 65 6e 20 74 68 65  racter, then the
2260: 20 6f 75 74 70 75 74 20 69 73 20 61 20 63 6f 70   output is a cop
2270: 79 20 6f 66 20 74 68 65 20 69 6e 70 75 74 20 73  y of the input s
2280: 74 72 69 6e 67 20 77 69 74 68 20 74 68 65 20 0a  tring with the .
2290: 2a 2a 20 74 68 72 65 65 2d 64 69 67 69 74 20 7a  ** three-digit z
22a0: 65 72 6f 2d 70 61 64 64 65 64 20 64 65 63 69 6d  ero-padded decim
22b0: 61 6c 20 72 65 70 72 65 73 65 6e 74 61 74 69 6f  al representatio
22c0: 6e 20 69 66 20 69 43 68 75 6e 6b 20 61 70 70 65  n if iChunk appe
22d0: 6e 64 65 64 20 74 6f 20 69 74 2e 20 0a 2a 2a 20  nded to it. .** 
22e0: 46 6f 72 20 65 78 61 6d 70 6c 65 3a 0a 2a 2a 0a  For example:.**.
22f0: 2a 2a 20 20 20 7a 42 61 73 65 3d 22 74 65 73 74  **   zBase="test
2300: 2e 64 62 22 2c 20 69 43 68 75 6e 6b 3d 34 20 20  .db", iChunk=4  
2310: 2d 3e 20 20 7a 4f 75 74 3d 22 74 65 73 74 2e 64  ->  zOut="test.d
2320: 62 30 30 34 22 0a 2a 2a 0a 2a 2a 20 4f 72 2c 20  b004".**.** Or, 
2330: 69 66 20 53 51 4c 49 54 45 5f 45 4e 41 42 4c 45  if SQLITE_ENABLE
2340: 5f 38 5f 33 5f 4e 41 4d 45 53 20 69 73 20 64 65  _8_3_NAMES is de
2350: 66 69 6e 65 64 20 61 6e 64 20 74 68 65 20 69 6e  fined and the in
2360: 70 75 74 20 62 75 66 66 65 72 20 63 6f 6e 74 61  put buffer conta
2370: 69 6e 73 0a 2a 2a 20 61 20 22 2e 22 20 63 68 61  ins.** a "." cha
2380: 72 61 63 74 65 72 2c 20 74 68 65 6e 20 65 76 65  racter, then eve
2390: 72 79 74 68 69 6e 67 20 61 66 74 65 72 20 74 68  rything after th
23a0: 65 20 22 2e 22 20 69 73 20 72 65 70 6c 61 63 65  e "." is replace
23b0: 64 20 62 79 20 74 68 65 20 0a 2a 2a 20 74 68 72  d by the .** thr
23c0: 65 65 2d 64 69 67 69 74 20 72 65 70 72 65 73 65  ee-digit represe
23d0: 6e 74 61 74 69 6f 6e 20 6f 66 20 69 43 68 75 6e  ntation of iChun
23e0: 6b 2e 0a 2a 2a 0a 2a 2a 20 20 20 7a 42 61 73 65  k..**.**   zBase
23f0: 3d 22 74 65 73 74 2e 64 62 22 2c 20 69 43 68 75  ="test.db", iChu
2400: 6e 6b 3d 34 20 20 2d 3e 20 20 7a 4f 75 74 3d 22  nk=4  ->  zOut="
2410: 74 65 73 74 2e 30 30 34 22 0a 2a 2a 0a 2a 2a 20  test.004".**.** 
2420: 54 68 65 20 6f 75 74 70 75 74 20 62 75 66 66 65  The output buffe
2430: 72 20 73 74 72 69 6e 67 20 69 73 20 74 65 72 6d  r string is term
2440: 69 6e 61 74 65 64 20 62 79 20 32 20 30 78 30 30  inated by 2 0x00
2450: 20 62 79 74 65 73 2e 20 54 68 69 73 20 6d 61 6b   bytes. This mak
2460: 65 73 20 69 74 20 73 61 66 65 0a 2a 2a 20 74 6f  es it safe.** to
2470: 20 70 61 73 73 20 74 6f 20 73 71 6c 69 74 65 33   pass to sqlite3
2480: 5f 75 72 69 5f 70 61 72 61 6d 65 74 65 72 28 29  _uri_parameter()
2490: 20 61 6e 64 20 73 69 6d 69 6c 61 72 2e 0a 2a 2f   and similar..*/
24a0: 0a 73 74 61 74 69 63 20 76 6f 69 64 20 6d 75 6c  .static void mul
24b0: 74 69 70 6c 65 78 46 69 6c 65 6e 61 6d 65 28 0a  tiplexFilename(.
24c0: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 42    const char *zB
24d0: 61 73 65 2c 20 20 20 20 20 20 20 20 20 20 20 20  ase,            
24e0: 20 20 2f 2a 20 46 69 6c 65 6e 61 6d 65 20 66 6f    /* Filename fo
24f0: 72 20 63 68 75 6e 6b 20 30 20 2a 2f 0a 20 20 69  r chunk 0 */.  i
2500: 6e 74 20 6e 42 61 73 65 2c 20 20 20 20 20 20 20  nt nBase,       
2510: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
2520: 2a 20 53 69 7a 65 20 6f 66 20 7a 42 61 73 65 20  * Size of zBase 
2530: 69 6e 20 62 79 74 65 73 20 28 77 69 74 68 6f 75  in bytes (withou
2540: 74 20 5c 30 29 20 2a 2f 0a 20 20 69 6e 74 20 66  t \0) */.  int f
2550: 6c 61 67 73 2c 20 20 20 20 20 20 20 20 20 20 20  lags,           
2560: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 46 6c             /* Fl
2570: 61 67 73 20 75 73 65 64 20 74 6f 20 6f 70 65 6e  ags used to open
2580: 20 66 69 6c 65 20 2a 2f 0a 20 20 69 6e 74 20 69   file */.  int i
2590: 43 68 75 6e 6b 2c 20 20 20 20 20 20 20 20 20 20  Chunk,          
25a0: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 43 68             /* Ch
25b0: 75 6e 6b 20 74 6f 20 67 65 6e 65 72 61 74 65 20  unk to generate 
25c0: 66 69 6c 65 6e 61 6d 65 20 66 6f 72 20 2a 2f 0a  filename for */.
25d0: 20 20 63 68 61 72 20 2a 7a 4f 75 74 20 20 20 20    char *zOut    
25e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
25f0: 20 20 2f 2a 20 42 75 66 66 65 72 20 74 6f 20 77    /* Buffer to w
2600: 72 69 74 65 20 67 65 6e 65 72 61 74 65 64 20 6e  rite generated n
2610: 61 6d 65 20 74 6f 20 2a 2f 0a 29 7b 0a 20 20 69  ame to */.){.  i
2620: 6e 74 20 6e 20 3d 20 6e 42 61 73 65 3b 0a 20 20  nt n = nBase;.  
2630: 6d 65 6d 63 70 79 28 7a 4f 75 74 2c 20 7a 42 61  memcpy(zOut, zBa
2640: 73 65 2c 20 6e 2b 31 29 3b 0a 20 20 69 66 28 20  se, n+1);.  if( 
2650: 69 43 68 75 6e 6b 21 3d 30 20 26 26 20 69 43 68  iChunk!=0 && iCh
2660: 75 6e 6b 3c 3d 4d 58 5f 43 48 55 4e 4b 5f 4e 55  unk<=MX_CHUNK_NU
2670: 4d 42 45 52 20 29 7b 0a 23 69 66 64 65 66 20 53  MBER ){.#ifdef S
2680: 51 4c 49 54 45 5f 45 4e 41 42 4c 45 5f 38 5f 33  QLITE_ENABLE_8_3
2690: 5f 4e 41 4d 45 53 0a 20 20 20 20 69 6e 74 20 69  _NAMES.    int i
26a0: 3b 0a 20 20 20 20 66 6f 72 28 69 3d 6e 2d 31 3b  ;.    for(i=n-1;
26b0: 20 69 3e 30 20 26 26 20 69 3e 3d 6e 2d 34 20 26   i>0 && i>=n-4 &
26c0: 26 20 7a 4f 75 74 5b 69 5d 21 3d 27 2e 27 3b 20  & zOut[i]!='.'; 
26d0: 69 2d 2d 29 7b 7d 0a 20 20 20 20 69 66 28 20 69  i--){}.    if( i
26e0: 3e 3d 6e 2d 34 20 29 20 6e 20 3d 20 69 2b 31 3b  >=n-4 ) n = i+1;
26f0: 0a 20 20 20 20 69 66 28 20 66 6c 61 67 73 20 26  .    if( flags &
2700: 20 53 51 4c 49 54 45 5f 4f 50 45 4e 5f 4d 41 49   SQLITE_OPEN_MAI
2710: 4e 5f 4a 4f 55 52 4e 41 4c 20 29 7b 0a 20 20 20  N_JOURNAL ){.   
2720: 20 20 20 2f 2a 20 54 68 65 20 65 78 74 65 6e 73     /* The extens
2730: 69 6f 6e 73 20 6f 6e 20 6f 76 65 72 66 6c 6f 77  ions on overflow
2740: 20 66 69 6c 65 73 20 66 6f 72 20 6d 61 69 6e 20   files for main 
2750: 64 61 74 61 62 61 73 65 73 20 61 72 65 20 30 30  databases are 00
2760: 31 2c 20 30 30 32 2c 0a 20 20 20 20 20 20 2a 2a  1, 002,.      **
2770: 20 30 30 33 20 61 6e 64 20 73 6f 20 66 6f 72 74   003 and so fort
2780: 68 2e 20 20 54 6f 20 61 76 6f 69 64 20 6e 61 6d  h.  To avoid nam
2790: 65 20 63 6f 6c 6c 69 73 69 6f 6e 73 2c 20 61 64  e collisions, ad
27a0: 64 20 34 30 30 20 74 6f 20 74 68 65 20 0a 20 20  d 400 to the .  
27b0: 20 20 20 20 2a 2a 20 65 78 74 65 6e 73 69 6f 6e      ** extension
27c0: 73 20 6f 66 20 6a 6f 75 72 6e 61 6c 20 66 69 6c  s of journal fil
27d0: 65 73 20 73 6f 20 74 68 61 74 20 74 68 65 79 20  es so that they 
27e0: 61 72 65 20 34 30 31 2c 20 34 30 32 2c 20 34 30  are 401, 402, 40
27f0: 33 2c 20 2e 2e 2e 2e 0a 20 20 20 20 20 20 2a 2f  3, .....      */
2800: 0a 20 20 20 20 20 20 69 43 68 75 6e 6b 20 2b 3d  .      iChunk +=
2810: 20 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45   SQLITE_MULTIPLE
2820: 58 5f 4a 4f 55 52 4e 41 4c 5f 38 5f 33 5f 4f 46  X_JOURNAL_8_3_OF
2830: 46 53 45 54 3b 0a 20 20 20 20 7d 65 6c 73 65 20  FSET;.    }else 
2840: 69 66 28 20 66 6c 61 67 73 20 26 20 53 51 4c 49  if( flags & SQLI
2850: 54 45 5f 4f 50 45 4e 5f 57 41 4c 20 29 7b 0a 20  TE_OPEN_WAL ){. 
2860: 20 20 20 20 20 2f 2a 20 54 6f 20 61 76 6f 69 64       /* To avoid
2870: 20 6e 61 6d 65 20 63 6f 6c 6c 69 73 69 6f 6e 73   name collisions
2880: 2c 20 61 64 64 20 37 30 30 20 74 6f 20 74 68 65  , add 700 to the
2890: 20 0a 20 20 20 20 20 20 2a 2a 20 65 78 74 65 6e   .      ** exten
28a0: 73 69 6f 6e 73 20 6f 66 20 57 41 4c 20 66 69 6c  sions of WAL fil
28b0: 65 73 20 73 6f 20 74 68 61 74 20 74 68 65 79 20  es so that they 
28c0: 61 72 65 20 37 30 31 2c 20 37 30 32 2c 20 37 30  are 701, 702, 70
28d0: 33 2c 20 2e 2e 2e 2e 0a 20 20 20 20 20 20 2a 2f  3, .....      */
28e0: 0a 20 20 20 20 20 20 69 43 68 75 6e 6b 20 2b 3d  .      iChunk +=
28f0: 20 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45   SQLITE_MULTIPLE
2900: 58 5f 57 41 4c 5f 38 5f 33 5f 4f 46 46 53 45 54  X_WAL_8_3_OFFSET
2910: 3b 0a 20 20 20 20 7d 0a 23 65 6e 64 69 66 0a 20  ;.    }.#endif. 
2920: 20 20 20 73 71 6c 69 74 65 33 5f 73 6e 70 72 69     sqlite3_snpri
2930: 6e 74 66 28 34 2c 26 7a 4f 75 74 5b 6e 5d 2c 22  ntf(4,&zOut[n],"
2940: 25 30 33 64 22 2c 69 43 68 75 6e 6b 29 3b 0a 20  %03d",iChunk);. 
2950: 20 20 20 6e 20 2b 3d 20 33 3b 0a 20 20 7d 0a 0a     n += 3;.  }..
2960: 20 20 61 73 73 65 72 74 28 20 7a 4f 75 74 5b 6e    assert( zOut[n
2970: 5d 3d 3d 27 5c 30 27 20 29 3b 0a 20 20 7a 4f 75  ]=='\0' );.  zOu
2980: 74 5b 6e 2b 31 5d 20 3d 20 27 5c 30 27 3b 0a 7d  t[n+1] = '\0';.}
2990: 0a 0a 2f 2a 20 43 6f 6d 70 75 74 65 20 74 68 65  ../* Compute the
29a0: 20 66 69 6c 65 6e 61 6d 65 20 66 6f 72 20 74 68   filename for th
29b0: 65 20 69 43 68 75 6e 6b 2d 74 68 20 63 68 75 6e  e iChunk-th chun
29c0: 6b 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20  k.*/.static int 
29d0: 6d 75 6c 74 69 70 6c 65 78 53 75 62 46 69 6c 65  multiplexSubFile
29e0: 6e 61 6d 65 28 6d 75 6c 74 69 70 6c 65 78 47 72  name(multiplexGr
29f0: 6f 75 70 20 2a 70 47 72 6f 75 70 2c 20 69 6e 74  oup *pGroup, int
2a00: 20 69 43 68 75 6e 6b 29 7b 0a 20 20 69 66 28 20   iChunk){.  if( 
2a10: 69 43 68 75 6e 6b 3e 3d 70 47 72 6f 75 70 2d 3e  iChunk>=pGroup->
2a20: 6e 52 65 61 6c 20 29 7b 0a 20 20 20 20 73 74 72  nReal ){.    str
2a30: 75 63 74 20 6d 75 6c 74 69 70 6c 65 78 52 65 61  uct multiplexRea
2a40: 6c 20 2a 70 3b 0a 20 20 20 20 70 20 3d 20 73 71  l *p;.    p = sq
2a50: 6c 69 74 65 33 5f 72 65 61 6c 6c 6f 63 28 70 47  lite3_realloc(pG
2a60: 72 6f 75 70 2d 3e 61 52 65 61 6c 2c 20 28 69 43  roup->aReal, (iC
2a70: 68 75 6e 6b 2b 31 29 2a 73 69 7a 65 6f 66 28 2a  hunk+1)*sizeof(*
2a80: 70 29 29 3b 0a 20 20 20 20 69 66 28 20 70 3d 3d  p));.    if( p==
2a90: 30 20 29 7b 0a 20 20 20 20 20 20 72 65 74 75 72  0 ){.      retur
2aa0: 6e 20 53 51 4c 49 54 45 5f 4e 4f 4d 45 4d 3b 0a  n SQLITE_NOMEM;.
2ab0: 20 20 20 20 7d 0a 20 20 20 20 6d 65 6d 73 65 74      }.    memset
2ac0: 28 26 70 5b 70 47 72 6f 75 70 2d 3e 6e 52 65 61  (&p[pGroup->nRea
2ad0: 6c 5d 2c 20 30 2c 20 73 69 7a 65 6f 66 28 70 5b  l], 0, sizeof(p[
2ae0: 30 5d 29 2a 28 69 43 68 75 6e 6b 2b 31 2d 70 47  0])*(iChunk+1-pG
2af0: 72 6f 75 70 2d 3e 6e 52 65 61 6c 29 29 3b 0a 20  roup->nReal));. 
2b00: 20 20 20 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c     pGroup->aReal
2b10: 20 3d 20 70 3b 0a 20 20 20 20 70 47 72 6f 75 70   = p;.    pGroup
2b20: 2d 3e 6e 52 65 61 6c 20 3d 20 69 43 68 75 6e 6b  ->nReal = iChunk
2b30: 2b 31 3b 0a 20 20 7d 0a 20 20 69 66 28 20 70 47  +1;.  }.  if( pG
2b40: 72 6f 75 70 2d 3e 7a 4e 61 6d 65 20 26 26 20 70  roup->zName && p
2b50: 47 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68  Group->aReal[iCh
2b60: 75 6e 6b 5d 2e 7a 3d 3d 30 20 29 7b 0a 20 20 20  unk].z==0 ){.   
2b70: 20 63 68 61 72 20 2a 7a 3b 0a 20 20 20 20 69 6e   char *z;.    in
2b80: 74 20 6e 20 3d 20 70 47 72 6f 75 70 2d 3e 6e 4e  t n = pGroup->nN
2b90: 61 6d 65 3b 0a 20 20 20 20 70 47 72 6f 75 70 2d  ame;.    pGroup-
2ba0: 3e 61 52 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e 7a  >aReal[iChunk].z
2bb0: 20 3d 20 7a 20 3d 20 73 71 6c 69 74 65 33 5f 6d   = z = sqlite3_m
2bc0: 61 6c 6c 6f 63 28 20 6e 2b 35 20 29 3b 0a 20 20  alloc( n+5 );.  
2bd0: 20 20 69 66 28 20 7a 3d 3d 30 20 29 7b 0a 20 20    if( z==0 ){.  
2be0: 20 20 20 20 72 65 74 75 72 6e 20 53 51 4c 49 54      return SQLIT
2bf0: 45 5f 4e 4f 4d 45 4d 3b 0a 20 20 20 20 7d 0a 20  E_NOMEM;.    }. 
2c00: 20 20 20 6d 75 6c 74 69 70 6c 65 78 46 69 6c 65     multiplexFile
2c10: 6e 61 6d 65 28 70 47 72 6f 75 70 2d 3e 7a 4e 61  name(pGroup->zNa
2c20: 6d 65 2c 20 70 47 72 6f 75 70 2d 3e 6e 4e 61 6d  me, pGroup->nNam
2c30: 65 2c 20 70 47 72 6f 75 70 2d 3e 66 6c 61 67 73  e, pGroup->flags
2c40: 2c 20 69 43 68 75 6e 6b 2c 20 7a 29 3b 0a 20 20  , iChunk, z);.  
2c50: 7d 0a 20 20 72 65 74 75 72 6e 20 53 51 4c 49 54  }.  return SQLIT
2c60: 45 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a 20 54 72 61 6e  E_OK;.}../* Tran
2c70: 73 6c 61 74 65 20 61 6e 20 73 71 6c 69 74 65 33  slate an sqlite3
2c80: 5f 66 69 6c 65 2a 20 74 68 61 74 20 69 73 20 72  _file* that is r
2c90: 65 61 6c 6c 79 20 61 20 6d 75 6c 74 69 70 6c 65  eally a multiple
2ca0: 78 47 72 6f 75 70 2a 20 69 6e 74 6f 0a 2a 2a 20  xGroup* into.** 
2cb0: 74 68 65 20 73 71 6c 69 74 65 33 5f 66 69 6c 65  the sqlite3_file
2cc0: 2a 20 66 6f 72 20 74 68 65 20 75 6e 64 65 72 6c  * for the underl
2cd0: 79 69 6e 67 20 6f 72 69 67 69 6e 61 6c 20 56 46  ying original VF
2ce0: 53 2e 0a 2a 2a 0a 2a 2a 20 46 6f 72 20 63 68 75  S..**.** For chu
2cf0: 6e 6b 20 30 2c 20 74 68 65 20 70 47 72 6f 75 70  nk 0, the pGroup
2d00: 2d 3e 66 6c 61 67 73 20 64 65 74 65 72 6d 69 6e  ->flags determin
2d10: 65 73 20 77 68 65 74 68 65 72 20 6f 72 20 6e 6f  es whether or no
2d20: 74 20 61 20 6e 65 77 20 66 69 6c 65 0a 2a 2a 20  t a new file.** 
2d30: 69 73 20 63 72 65 61 74 65 64 20 69 66 20 69 74  is created if it
2d40: 20 64 6f 65 73 20 6e 6f 74 20 61 6c 72 65 61 64   does not alread
2d50: 79 20 65 78 69 73 74 2e 20 20 46 6f 72 20 63 68  y exist.  For ch
2d60: 75 6e 6b 73 20 31 20 61 6e 64 20 68 69 67 68 65  unks 1 and highe
2d70: 72 2c 20 74 68 65 0a 2a 2a 20 66 69 6c 65 20 69  r, the.** file i
2d80: 73 20 63 72 65 61 74 65 64 20 6f 6e 6c 79 20 69  s created only i
2d90: 66 20 63 72 65 61 74 65 46 6c 61 67 20 69 73 20  f createFlag is 
2da0: 31 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 73 71 6c  1..*/.static sql
2db0: 69 74 65 33 5f 66 69 6c 65 20 2a 6d 75 6c 74 69  ite3_file *multi
2dc0: 70 6c 65 78 53 75 62 4f 70 65 6e 28 0a 20 20 6d  plexSubOpen(.  m
2dd0: 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 2a 70  ultiplexGroup *p
2de0: 47 72 6f 75 70 2c 20 20 20 20 2f 2a 20 54 68 65  Group,    /* The
2df0: 20 6d 75 6c 74 69 70 6c 65 78 6f 72 20 67 72 6f   multiplexor gro
2e00: 75 70 20 2a 2f 0a 20 20 69 6e 74 20 69 43 68 75  up */.  int iChu
2e10: 6e 6b 2c 20 20 20 20 20 20 20 20 20 20 20 20 20  nk,             
2e20: 20 20 20 2f 2a 20 57 68 69 63 68 20 63 68 75 6e     /* Which chun
2e30: 6b 20 74 6f 20 6f 70 65 6e 2e 20 20 30 3d 3d 6f  k to open.  0==o
2e40: 72 69 67 69 6e 61 6c 20 66 69 6c 65 20 2a 2f 0a  riginal file */.
2e50: 20 20 69 6e 74 20 2a 72 63 2c 20 20 20 20 20 20    int *rc,      
2e60: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
2e70: 52 65 73 75 6c 74 20 63 6f 64 65 20 69 6e 20 61  Result code in a
2e80: 6e 64 20 6f 75 74 20 2a 2f 0a 20 20 69 6e 74 20  nd out */.  int 
2e90: 2a 70 4f 75 74 46 6c 61 67 73 2c 20 20 20 20 20  *pOutFlags,     
2ea0: 20 20 20 20 20 20 20 2f 2a 20 4f 75 74 70 75 74         /* Output
2eb0: 20 66 6c 61 67 73 20 2a 2f 0a 20 20 69 6e 74 20   flags */.  int 
2ec0: 63 72 65 61 74 65 46 6c 61 67 20 20 20 20 20 20  createFlag      
2ed0: 20 20 20 20 20 20 20 2f 2a 20 54 72 75 65 20 74         /* True t
2ee0: 6f 20 63 72 65 61 74 65 20 69 66 20 69 43 68 75  o create if iChu
2ef0: 6e 6b 3e 30 20 2a 2f 0a 29 7b 0a 20 20 73 71 6c  nk>0 */.){.  sql
2f00: 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f  ite3_file *pSubO
2f10: 70 65 6e 20 3d 20 30 3b 0a 20 20 73 71 6c 69 74  pen = 0;.  sqlit
2f20: 65 33 5f 76 66 73 20 2a 70 4f 72 69 67 56 66 73  e3_vfs *pOrigVfs
2f30: 20 3d 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f   = gMultiplex.pO
2f40: 72 69 67 56 66 73 3b 20 20 20 20 20 20 20 20 2f  rigVfs;        /
2f50: 2a 20 52 65 61 6c 20 56 46 53 20 2a 2f 0a 0a 23  * Real VFS */..#
2f60: 69 66 64 65 66 20 53 51 4c 49 54 45 5f 45 4e 41  ifdef SQLITE_ENA
2f70: 42 4c 45 5f 38 5f 33 5f 4e 41 4d 45 53 0a 20 20  BLE_8_3_NAMES.  
2f80: 2f 2a 20 49 66 20 4a 4f 55 52 4e 41 4c 5f 38 5f  /* If JOURNAL_8_
2f90: 33 5f 4f 46 46 53 45 54 20 69 73 20 73 65 74 20  3_OFFSET is set 
2fa0: 74 6f 20 28 73 61 79 29 20 34 30 30 2c 20 74 68  to (say) 400, th
2fb0: 65 6e 20 61 6e 79 20 6f 76 65 72 66 6c 6f 77 20  en any overflow 
2fc0: 66 69 6c 65 73 20 61 72 65 20 0a 20 20 2a 2a 20  files are .  ** 
2fd0: 70 61 72 74 20 6f 66 20 61 20 64 61 74 61 62 61  part of a databa
2fe0: 73 65 20 6a 6f 75 72 6e 61 6c 20 61 72 65 20 6e  se journal are n
2ff0: 61 6d 65 64 20 64 62 2e 34 30 31 2c 20 64 62 2e  amed db.401, db.
3000: 34 30 32 2c 20 61 6e 64 20 73 6f 20 6f 6e 2e 20  402, and so on. 
3010: 41 20 0a 20 20 2a 2a 20 64 61 74 61 62 61 73 65  A .  ** database
3020: 20 6d 61 79 20 74 68 65 72 65 66 6f 72 65 20 6e   may therefore n
3030: 6f 74 20 67 72 6f 77 20 74 6f 20 6c 61 72 67 65  ot grow to large
3040: 72 20 74 68 61 6e 20 34 30 30 20 63 68 75 6e 6b  r than 400 chunk
3050: 73 2e 20 41 74 74 65 6d 70 74 69 6e 67 0a 20 20  s. Attempting.  
3060: 2a 2a 20 74 6f 20 6f 70 65 6e 20 63 68 75 6e 6b  ** to open chunk
3070: 20 34 30 31 20 69 6e 64 69 63 61 74 65 73 20 74   401 indicates t
3080: 68 65 20 64 61 74 61 62 61 73 65 20 69 73 20 66  he database is f
3090: 75 6c 6c 2e 20 2a 2f 0a 20 20 69 66 28 20 69 43  ull. */.  if( iC
30a0: 68 75 6e 6b 3e 3d 53 51 4c 49 54 45 5f 4d 55 4c  hunk>=SQLITE_MUL
30b0: 54 49 50 4c 45 58 5f 4a 4f 55 52 4e 41 4c 5f 38  TIPLEX_JOURNAL_8
30c0: 5f 33 5f 4f 46 46 53 45 54 20 29 7b 0a 20 20 20  _3_OFFSET ){.   
30d0: 20 73 71 6c 69 74 65 33 5f 6c 6f 67 28 53 51 4c   sqlite3_log(SQL
30e0: 49 54 45 5f 46 55 4c 4c 2c 20 22 6d 75 6c 74 69  ITE_FULL, "multi
30f0: 70 6c 65 78 65 64 20 63 68 75 6e 6b 20 6f 76 65  plexed chunk ove
3100: 72 66 6c 6f 77 3a 20 25 73 22 2c 20 70 47 72 6f  rflow: %s", pGro
3110: 75 70 2d 3e 7a 4e 61 6d 65 29 3b 0a 20 20 20 20  up->zName);.    
3120: 2a 72 63 20 3d 20 53 51 4c 49 54 45 5f 46 55 4c  *rc = SQLITE_FUL
3130: 4c 3b 0a 20 20 20 20 72 65 74 75 72 6e 20 30 3b  L;.    return 0;
3140: 0a 20 20 7d 0a 23 65 6e 64 69 66 0a 0a 20 20 2a  .  }.#endif..  *
3150: 72 63 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75  rc = multiplexSu
3160: 62 46 69 6c 65 6e 61 6d 65 28 70 47 72 6f 75 70  bFilename(pGroup
3170: 2c 20 69 43 68 75 6e 6b 29 3b 0a 20 20 69 66 28  , iChunk);.  if(
3180: 20 28 2a 72 63 29 3d 3d 53 51 4c 49 54 45 5f 4f   (*rc)==SQLITE_O
3190: 4b 20 26 26 20 28 70 53 75 62 4f 70 65 6e 20 3d  K && (pSubOpen =
31a0: 20 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69   pGroup->aReal[i
31b0: 43 68 75 6e 6b 5d 2e 70 29 3d 3d 30 20 29 7b 0a  Chunk].p)==0 ){.
31c0: 20 20 20 20 69 6e 74 20 66 6c 61 67 73 2c 20 62      int flags, b
31d0: 45 78 69 73 74 73 3b 0a 20 20 20 20 66 6c 61 67  Exists;.    flag
31e0: 73 20 3d 20 70 47 72 6f 75 70 2d 3e 66 6c 61 67  s = pGroup->flag
31f0: 73 3b 0a 20 20 20 20 69 66 28 20 63 72 65 61 74  s;.    if( creat
3200: 65 46 6c 61 67 20 29 7b 0a 20 20 20 20 20 20 66  eFlag ){.      f
3210: 6c 61 67 73 20 7c 3d 20 53 51 4c 49 54 45 5f 4f  lags |= SQLITE_O
3220: 50 45 4e 5f 43 52 45 41 54 45 3b 0a 20 20 20 20  PEN_CREATE;.    
3230: 7d 65 6c 73 65 20 69 66 28 20 69 43 68 75 6e 6b  }else if( iChunk
3240: 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 2f 2a 20  ==0 ){.      /* 
3250: 46 61 6c 6c 20 74 68 72 6f 75 67 68 20 2a 2f 0a  Fall through */.
3260: 20 20 20 20 7d 65 6c 73 65 20 69 66 28 20 70 47      }else if( pG
3270: 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68 75  roup->aReal[iChu
3280: 6e 6b 5d 2e 7a 3d 3d 30 20 29 7b 0a 20 20 20 20  nk].z==0 ){.    
3290: 20 20 72 65 74 75 72 6e 20 30 3b 0a 20 20 20 20    return 0;.    
32a0: 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 2a 72 63  }else{.      *rc
32b0: 20 3d 20 70 4f 72 69 67 56 66 73 2d 3e 78 41 63   = pOrigVfs->xAc
32c0: 63 65 73 73 28 70 4f 72 69 67 56 66 73 2c 20 70  cess(pOrigVfs, p
32d0: 47 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68  Group->aReal[iCh
32e0: 75 6e 6b 5d 2e 7a 2c 0a 20 20 20 20 20 20 20 20  unk].z,.        
32f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3300: 20 20 20 20 20 20 53 51 4c 49 54 45 5f 41 43 43        SQLITE_ACC
3310: 45 53 53 5f 45 58 49 53 54 53 2c 20 26 62 45 78  ESS_EXISTS, &bEx
3320: 69 73 74 73 29 3b 0a 20 20 20 20 20 69 66 28 20  ists);.     if( 
3330: 2a 72 63 20 7c 7c 20 21 62 45 78 69 73 74 73 20  *rc || !bExists 
3340: 29 7b 0a 20 20 20 20 20 20 20 20 69 66 28 20 2a  ){.        if( *
3350: 72 63 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20  rc ){.          
3360: 73 71 6c 69 74 65 33 5f 6c 6f 67 28 2a 72 63 2c  sqlite3_log(*rc,
3370: 20 22 6d 75 6c 74 69 70 6c 65 78 6f 72 2e 78 41   "multiplexor.xA
3380: 63 63 65 73 73 20 66 61 69 6c 75 72 65 20 6f 6e  ccess failure on
3390: 20 25 73 22 2c 0a 20 20 20 20 20 20 20 20 20 20   %s",.          
33a0: 20 20 20 20 20 20 20 20 20 20 20 20 70 47 72 6f              pGro
33b0: 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68 75 6e 6b  up->aReal[iChunk
33c0: 5d 2e 7a 29 3b 0a 20 20 20 20 20 20 20 20 7d 0a  ].z);.        }.
33d0: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 30          return 0
33e0: 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20  ;.      }.      
33f0: 66 6c 61 67 73 20 26 3d 20 7e 53 51 4c 49 54 45  flags &= ~SQLITE
3400: 5f 4f 50 45 4e 5f 43 52 45 41 54 45 3b 0a 20 20  _OPEN_CREATE;.  
3410: 20 20 7d 0a 20 20 20 20 70 53 75 62 4f 70 65 6e    }.    pSubOpen
3420: 20 3d 20 73 71 6c 69 74 65 33 5f 6d 61 6c 6c 6f   = sqlite3_mallo
3430: 63 28 20 70 4f 72 69 67 56 66 73 2d 3e 73 7a 4f  c( pOrigVfs->szO
3440: 73 46 69 6c 65 20 29 3b 0a 20 20 20 20 69 66 28  sFile );.    if(
3450: 20 70 53 75 62 4f 70 65 6e 3d 3d 30 20 29 7b 0a   pSubOpen==0 ){.
3460: 20 20 20 20 20 20 2a 72 63 20 3d 20 53 51 4c 49        *rc = SQLI
3470: 54 45 5f 49 4f 45 52 52 5f 4e 4f 4d 45 4d 3b 0a  TE_IOERR_NOMEM;.
3480: 20 20 20 20 20 20 72 65 74 75 72 6e 20 30 3b 0a        return 0;.
3490: 20 20 20 20 7d 0a 20 20 20 20 70 47 72 6f 75 70      }.    pGroup
34a0: 2d 3e 61 52 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e  ->aReal[iChunk].
34b0: 70 20 3d 20 70 53 75 62 4f 70 65 6e 3b 0a 20 20  p = pSubOpen;.  
34c0: 20 20 2a 72 63 20 3d 20 70 4f 72 69 67 56 66 73    *rc = pOrigVfs
34d0: 2d 3e 78 4f 70 65 6e 28 70 4f 72 69 67 56 66 73  ->xOpen(pOrigVfs
34e0: 2c 20 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c 5b  , pGroup->aReal[
34f0: 69 43 68 75 6e 6b 5d 2e 7a 2c 20 70 53 75 62 4f  iChunk].z, pSubO
3500: 70 65 6e 2c 0a 20 20 20 20 20 20 20 20 20 20 20  pen,.           
3510: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 66                 f
3520: 6c 61 67 73 2c 20 70 4f 75 74 46 6c 61 67 73 29  lags, pOutFlags)
3530: 3b 0a 20 20 20 20 69 66 28 20 28 2a 72 63 29 21  ;.    if( (*rc)!
3540: 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20  =SQLITE_OK ){.  
3550: 20 20 20 20 73 71 6c 69 74 65 33 5f 6c 6f 67 28      sqlite3_log(
3560: 2a 72 63 2c 20 22 6d 75 6c 74 69 70 6c 65 78 6f  *rc, "multiplexo
3570: 72 2e 78 4f 70 65 6e 20 66 61 69 6c 75 72 65 20  r.xOpen failure 
3580: 6f 6e 20 25 73 22 2c 0a 20 20 20 20 20 20 20 20  on %s",.        
3590: 20 20 20 20 20 20 20 20 20 20 70 47 72 6f 75 70            pGroup
35a0: 2d 3e 61 52 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e  ->aReal[iChunk].
35b0: 7a 29 3b 0a 20 20 20 20 20 20 73 71 6c 69 74 65  z);.      sqlite
35c0: 33 5f 66 72 65 65 28 70 53 75 62 4f 70 65 6e 29  3_free(pSubOpen)
35d0: 3b 0a 20 20 20 20 20 20 70 47 72 6f 75 70 2d 3e  ;.      pGroup->
35e0: 61 52 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e 70 20  aReal[iChunk].p 
35f0: 3d 20 30 3b 0a 20 20 20 20 20 20 72 65 74 75 72  = 0;.      retur
3600: 6e 20 30 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 20  n 0;.    }.  }. 
3610: 20 72 65 74 75 72 6e 20 70 53 75 62 4f 70 65 6e   return pSubOpen
3620: 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 52 65 74 75 72  ;.}../*.** Retur
3630: 6e 20 74 68 65 20 73 69 7a 65 2c 20 69 6e 20 62  n the size, in b
3640: 79 74 65 73 2c 20 6f 66 20 63 68 75 6e 6b 20 6e  ytes, of chunk n
3650: 75 6d 62 65 72 20 69 43 68 75 6e 6b 2e 20 20 49  umber iChunk.  I
3660: 66 20 74 68 61 74 20 63 68 75 6e 6b 0a 2a 2a 20  f that chunk.** 
3670: 64 6f 65 73 20 6e 6f 74 20 65 78 69 73 74 2c 20  does not exist, 
3680: 74 68 65 6e 20 72 65 74 75 72 6e 20 30 2e 20 20  then return 0.  
3690: 54 68 69 73 20 66 75 6e 63 74 69 6f 6e 20 64 6f  This function do
36a0: 65 73 20 6e 6f 74 20 64 69 73 74 69 6e 67 69 73  es not distingis
36b0: 68 20 62 65 74 77 65 65 6e 0a 2a 2a 20 6e 6f 6e  h between.** non
36c0: 2d 65 78 69 73 74 61 6e 74 20 66 69 6c 65 73 20  -existant files 
36d0: 61 6e 64 20 7a 65 72 6f 2d 6c 65 6e 67 74 68 20  and zero-length 
36e0: 66 69 6c 65 73 2e 0a 2a 2f 0a 73 74 61 74 69 63  files..*/.static
36f0: 20 73 71 6c 69 74 65 33 5f 69 6e 74 36 34 20 6d   sqlite3_int64 m
3700: 75 6c 74 69 70 6c 65 78 53 75 62 53 69 7a 65 28  ultiplexSubSize(
3710: 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75  .  multiplexGrou
3720: 70 20 2a 70 47 72 6f 75 70 2c 20 20 20 20 2f 2a  p *pGroup,    /*
3730: 20 54 68 65 20 6d 75 6c 74 69 70 6c 65 78 6f 72   The multiplexor
3740: 20 67 72 6f 75 70 20 2a 2f 0a 20 20 69 6e 74 20   group */.  int 
3750: 69 43 68 75 6e 6b 2c 20 20 20 20 20 20 20 20 20  iChunk,         
3760: 20 20 20 20 20 20 20 2f 2a 20 57 68 69 63 68 20         /* Which 
3770: 63 68 75 6e 6b 20 74 6f 20 6f 70 65 6e 2e 20 20  chunk to open.  
3780: 30 3d 3d 6f 72 69 67 69 6e 61 6c 20 66 69 6c 65  0==original file
3790: 20 2a 2f 0a 20 20 69 6e 74 20 2a 72 63 20 20 20   */.  int *rc   
37a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
37b0: 20 2f 2a 20 52 65 73 75 6c 74 20 63 6f 64 65 20   /* Result code 
37c0: 69 6e 20 61 6e 64 20 6f 75 74 20 2a 2f 0a 29 7b  in and out */.){
37d0: 0a 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20  .  sqlite3_file 
37e0: 2a 70 53 75 62 3b 0a 20 20 73 71 6c 69 74 65 33  *pSub;.  sqlite3
37f0: 5f 69 6e 74 36 34 20 73 7a 20 3d 20 30 3b 0a 0a  _int64 sz = 0;..
3800: 20 20 69 66 28 20 2a 72 63 20 29 20 72 65 74 75    if( *rc ) retu
3810: 72 6e 20 30 3b 0a 20 20 70 53 75 62 20 3d 20 6d  rn 0;.  pSub = m
3820: 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28  ultiplexSubOpen(
3830: 70 47 72 6f 75 70 2c 20 69 43 68 75 6e 6b 2c 20  pGroup, iChunk, 
3840: 72 63 2c 20 4e 55 4c 4c 2c 20 30 29 3b 0a 20 20  rc, NULL, 0);.  
3850: 69 66 28 20 70 53 75 62 3d 3d 30 20 29 20 72 65  if( pSub==0 ) re
3860: 74 75 72 6e 20 30 3b 0a 20 20 2a 72 63 20 3d 20  turn 0;.  *rc = 
3870: 70 53 75 62 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e  pSub->pMethods->
3880: 78 46 69 6c 65 53 69 7a 65 28 70 53 75 62 2c 20  xFileSize(pSub, 
3890: 26 73 7a 29 3b 0a 20 20 72 65 74 75 72 6e 20 73  &sz);.  return s
38a0: 7a 3b 0a 7d 20 20 20 20 0a 0a 2f 2a 0a 2a 2a 20  z;.}    ../*.** 
38b0: 54 68 69 73 20 69 73 20 74 68 65 20 69 6d 70 6c  This is the impl
38c0: 65 6d 65 6e 74 61 74 69 6f 6e 20 6f 66 20 74 68  ementation of th
38d0: 65 20 6d 75 6c 74 69 70 6c 65 78 5f 63 6f 6e 74  e multiplex_cont
38e0: 72 6f 6c 28 29 20 53 51 4c 20 66 75 6e 63 74 69  rol() SQL functi
38f0: 6f 6e 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 76 6f  on..*/.static vo
3900: 69 64 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 74  id multiplexCont
3910: 72 6f 6c 46 75 6e 63 28 0a 20 20 73 71 6c 69 74  rolFunc(.  sqlit
3920: 65 33 5f 63 6f 6e 74 65 78 74 20 2a 63 6f 6e 74  e3_context *cont
3930: 65 78 74 2c 0a 20 20 69 6e 74 20 61 72 67 63 2c  ext,.  int argc,
3940: 0a 20 20 73 71 6c 69 74 65 33 5f 76 61 6c 75 65  .  sqlite3_value
3950: 20 2a 2a 61 72 67 76 0a 29 7b 0a 20 20 69 6e 74   **argv.){.  int
3960: 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b   rc = SQLITE_OK;
3970: 0a 20 20 73 71 6c 69 74 65 33 20 2a 64 62 20 3d  .  sqlite3 *db =
3980: 20 73 71 6c 69 74 65 33 5f 63 6f 6e 74 65 78 74   sqlite3_context
3990: 5f 64 62 5f 68 61 6e 64 6c 65 28 63 6f 6e 74 65  _db_handle(conte
39a0: 78 74 29 3b 0a 20 20 69 6e 74 20 6f 70 3b 0a 20  xt);.  int op;. 
39b0: 20 69 6e 74 20 69 56 61 6c 3b 0a 0a 20 20 69 66   int iVal;..  if
39c0: 28 20 21 64 62 20 7c 7c 20 61 72 67 63 21 3d 32  ( !db || argc!=2
39d0: 20 29 7b 20 0a 20 20 20 20 72 63 20 3d 20 53 51   ){ .    rc = SQ
39e0: 4c 49 54 45 5f 45 52 52 4f 52 3b 20 0a 20 20 7d  LITE_ERROR; .  }
39f0: 65 6c 73 65 7b 0a 20 20 20 20 2f 2a 20 65 78 74  else{.    /* ext
3a00: 72 61 63 74 20 70 61 72 61 6d 73 20 2a 2f 0a 20  ract params */. 
3a10: 20 20 20 6f 70 20 3d 20 73 71 6c 69 74 65 33 5f     op = sqlite3_
3a20: 76 61 6c 75 65 5f 69 6e 74 28 61 72 67 76 5b 30  value_int(argv[0
3a30: 5d 29 3b 0a 20 20 20 20 69 56 61 6c 20 3d 20 73  ]);.    iVal = s
3a40: 71 6c 69 74 65 33 5f 76 61 6c 75 65 5f 69 6e 74  qlite3_value_int
3a50: 28 61 72 67 76 5b 31 5d 29 3b 0a 20 20 20 20 2f  (argv[1]);.    /
3a60: 2a 20 6d 61 70 20 66 75 6e 63 74 69 6f 6e 20 6f  * map function o
3a70: 70 20 74 6f 20 66 69 6c 65 5f 63 6f 6e 74 72 6f  p to file_contro
3a80: 6c 20 6f 70 20 2a 2f 0a 20 20 20 20 73 77 69 74  l op */.    swit
3a90: 63 68 28 20 6f 70 20 29 7b 0a 20 20 20 20 20 20  ch( op ){.      
3aa0: 63 61 73 65 20 31 3a 20 0a 20 20 20 20 20 20 20  case 1: .       
3ab0: 20 6f 70 20 3d 20 4d 55 4c 54 49 50 4c 45 58 5f   op = MULTIPLEX_
3ac0: 43 54 52 4c 5f 45 4e 41 42 4c 45 3b 20 0a 20 20  CTRL_ENABLE; .  
3ad0: 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20        break;.   
3ae0: 20 20 20 63 61 73 65 20 32 3a 20 0a 20 20 20 20     case 2: .    
3af0: 20 20 20 20 6f 70 20 3d 20 4d 55 4c 54 49 50 4c      op = MULTIPL
3b00: 45 58 5f 43 54 52 4c 5f 53 45 54 5f 43 48 55 4e  EX_CTRL_SET_CHUN
3b10: 4b 5f 53 49 5a 45 3b 20 0a 20 20 20 20 20 20 20  K_SIZE; .       
3b20: 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 63 61   break;.      ca
3b30: 73 65 20 33 3a 20 0a 20 20 20 20 20 20 20 20 6f  se 3: .        o
3b40: 70 20 3d 20 4d 55 4c 54 49 50 4c 45 58 5f 43 54  p = MULTIPLEX_CT
3b50: 52 4c 5f 53 45 54 5f 4d 41 58 5f 43 48 55 4e 4b  RL_SET_MAX_CHUNK
3b60: 53 3b 20 0a 20 20 20 20 20 20 20 20 62 72 65 61  S; .        brea
3b70: 6b 3b 0a 20 20 20 20 20 20 64 65 66 61 75 6c 74  k;.      default
3b80: 3a 0a 20 20 20 20 20 20 20 20 72 63 20 3d 20 53  :.        rc = S
3b90: 51 4c 49 54 45 5f 4e 4f 54 46 4f 55 4e 44 3b 0a  QLITE_NOTFOUND;.
3ba0: 20 20 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20          break;. 
3bb0: 20 20 20 7d 0a 20 20 7d 0a 20 20 69 66 28 20 72     }.  }.  if( r
3bc0: 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a  c==SQLITE_OK ){.
3bd0: 20 20 20 20 72 63 20 3d 20 73 71 6c 69 74 65 33      rc = sqlite3
3be0: 5f 66 69 6c 65 5f 63 6f 6e 74 72 6f 6c 28 64 62  _file_control(db
3bf0: 2c 20 30 2c 20 6f 70 2c 20 26 69 56 61 6c 29 3b  , 0, op, &iVal);
3c00: 0a 20 20 7d 0a 20 20 73 71 6c 69 74 65 33 5f 72  .  }.  sqlite3_r
3c10: 65 73 75 6c 74 5f 65 72 72 6f 72 5f 63 6f 64 65  esult_error_code
3c20: 28 63 6f 6e 74 65 78 74 2c 20 72 63 29 3b 0a 7d  (context, rc);.}
3c30: 0a 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20 69 73 20  ../*.** This is 
3c40: 74 68 65 20 65 6e 74 72 79 20 70 6f 69 6e 74 20  the entry point 
3c50: 74 6f 20 72 65 67 69 73 74 65 72 20 74 68 65 20  to register the 
3c60: 61 75 74 6f 2d 65 78 74 65 6e 73 69 6f 6e 20 66  auto-extension f
3c70: 6f 72 20 74 68 65 20 0a 2a 2a 20 6d 75 6c 74 69  or the .** multi
3c80: 70 6c 65 78 5f 63 6f 6e 74 72 6f 6c 28 29 20 66  plex_control() f
3c90: 75 6e 63 74 69 6f 6e 2e 0a 2a 2f 0a 73 74 61 74  unction..*/.stat
3ca0: 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78  ic int multiplex
3cb0: 46 75 6e 63 49 6e 69 74 28 0a 20 20 73 71 6c 69  FuncInit(.  sqli
3cc0: 74 65 33 20 2a 64 62 2c 20 0a 20 20 63 68 61 72  te3 *db, .  char
3cd0: 20 2a 2a 70 7a 45 72 72 4d 73 67 2c 20 0a 20 20   **pzErrMsg, .  
3ce0: 63 6f 6e 73 74 20 73 71 6c 69 74 65 33 5f 61 70  const sqlite3_ap
3cf0: 69 5f 72 6f 75 74 69 6e 65 73 20 2a 70 41 70 69  i_routines *pApi
3d00: 0a 29 7b 0a 20 20 69 6e 74 20 72 63 3b 0a 20 20  .){.  int rc;.  
3d10: 72 63 20 3d 20 73 71 6c 69 74 65 33 5f 63 72 65  rc = sqlite3_cre
3d20: 61 74 65 5f 66 75 6e 63 74 69 6f 6e 28 64 62 2c  ate_function(db,
3d30: 20 22 6d 75 6c 74 69 70 6c 65 78 5f 63 6f 6e 74   "multiplex_cont
3d40: 72 6f 6c 22 2c 20 32 2c 20 53 51 4c 49 54 45 5f  rol", 2, SQLITE_
3d50: 41 4e 59 2c 20 0a 20 20 20 20 20 20 30 2c 20 6d  ANY, .      0, m
3d60: 75 6c 74 69 70 6c 65 78 43 6f 6e 74 72 6f 6c 46  ultiplexControlF
3d70: 75 6e 63 2c 20 30 2c 20 30 29 3b 0a 20 20 72 65  unc, 0, 0);.  re
3d80: 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 0a 2a  turn rc;.}../*.*
3d90: 2a 20 43 6c 6f 73 65 20 61 20 73 69 6e 67 6c 65  * Close a single
3da0: 20 73 75 62 2d 66 69 6c 65 20 69 6e 20 74 68 65   sub-file in the
3db0: 20 63 6f 6e 6e 65 63 74 69 6f 6e 20 67 72 6f 75   connection grou
3dc0: 70 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 76 6f 69  p..*/.static voi
3dd0: 64 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 43 6c  d multiplexSubCl
3de0: 6f 73 65 28 0a 20 20 6d 75 6c 74 69 70 6c 65 78  ose(.  multiplex
3df0: 47 72 6f 75 70 20 2a 70 47 72 6f 75 70 2c 0a 20  Group *pGroup,. 
3e00: 20 69 6e 74 20 69 43 68 75 6e 6b 2c 0a 20 20 73   int iChunk,.  s
3e10: 71 6c 69 74 65 33 5f 76 66 73 20 2a 70 4f 72 69  qlite3_vfs *pOri
3e20: 67 56 66 73 0a 29 7b 0a 20 20 73 71 6c 69 74 65  gVfs.){.  sqlite
3e30: 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e  3_file *pSubOpen
3e40: 20 3d 20 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c   = pGroup->aReal
3e50: 5b 69 43 68 75 6e 6b 5d 2e 70 3b 0a 20 20 69 66  [iChunk].p;.  if
3e60: 28 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20  ( pSubOpen ){.  
3e70: 20 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74    pSubOpen->pMet
3e80: 68 6f 64 73 2d 3e 78 43 6c 6f 73 65 28 70 53 75  hods->xClose(pSu
3e90: 62 4f 70 65 6e 29 3b 0a 20 20 20 20 69 66 28 20  bOpen);.    if( 
3ea0: 70 4f 72 69 67 56 66 73 20 26 26 20 70 47 72 6f  pOrigVfs && pGro
3eb0: 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68 75 6e 6b  up->aReal[iChunk
3ec0: 5d 2e 7a 20 29 7b 0a 20 20 20 20 20 20 70 4f 72  ].z ){.      pOr
3ed0: 69 67 56 66 73 2d 3e 78 44 65 6c 65 74 65 28 70  igVfs->xDelete(p
3ee0: 4f 72 69 67 56 66 73 2c 20 70 47 72 6f 75 70 2d  OrigVfs, pGroup-
3ef0: 3e 61 52 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e 7a  >aReal[iChunk].z
3f00: 2c 20 30 29 3b 0a 20 20 20 20 7d 0a 20 20 20 20  , 0);.    }.    
3f10: 73 71 6c 69 74 65 33 5f 66 72 65 65 28 70 47 72  sqlite3_free(pGr
3f20: 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68 75 6e  oup->aReal[iChun
3f30: 6b 5d 2e 70 29 3b 0a 20 20 7d 0a 20 20 73 71 6c  k].p);.  }.  sql
3f40: 69 74 65 33 5f 66 72 65 65 28 70 47 72 6f 75 70  ite3_free(pGroup
3f50: 2d 3e 61 52 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e  ->aReal[iChunk].
3f60: 7a 29 3b 0a 20 20 6d 65 6d 73 65 74 28 26 70 47  z);.  memset(&pG
3f70: 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68 75  roup->aReal[iChu
3f80: 6e 6b 5d 2c 20 30 2c 20 73 69 7a 65 6f 66 28 70  nk], 0, sizeof(p
3f90: 47 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68  Group->aReal[iCh
3fa0: 75 6e 6b 5d 29 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a  unk]));.}../*.**
3fb0: 20 44 65 61 6c 6c 6f 63 61 74 65 20 6d 65 6d 6f   Deallocate memo
3fc0: 72 79 20 68 65 6c 64 20 62 79 20 61 20 6d 75 6c  ry held by a mul
3fd0: 74 69 70 6c 65 78 47 72 6f 75 70 0a 2a 2f 0a 73  tiplexGroup.*/.s
3fe0: 74 61 74 69 63 20 76 6f 69 64 20 6d 75 6c 74 69  tatic void multi
3ff0: 70 6c 65 78 46 72 65 65 43 6f 6d 70 6f 6e 65 6e  plexFreeComponen
4000: 74 73 28 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75  ts(multiplexGrou
4010: 70 20 2a 70 47 72 6f 75 70 29 7b 0a 20 20 69 6e  p *pGroup){.  in
4020: 74 20 69 3b 0a 20 20 66 6f 72 28 69 3d 30 3b 20  t i;.  for(i=0; 
4030: 69 3c 70 47 72 6f 75 70 2d 3e 6e 52 65 61 6c 3b  i<pGroup->nReal;
4040: 20 69 2b 2b 29 7b 20 6d 75 6c 74 69 70 6c 65 78   i++){ multiplex
4050: 53 75 62 43 6c 6f 73 65 28 70 47 72 6f 75 70 2c  SubClose(pGroup,
4060: 20 69 2c 20 30 29 3b 20 7d 0a 20 20 73 71 6c 69   i, 0); }.  sqli
4070: 74 65 33 5f 66 72 65 65 28 70 47 72 6f 75 70 2d  te3_free(pGroup-
4080: 3e 61 52 65 61 6c 29 3b 0a 20 20 70 47 72 6f 75  >aReal);.  pGrou
4090: 70 2d 3e 61 52 65 61 6c 20 3d 20 30 3b 0a 20 20  p->aReal = 0;.  
40a0: 70 47 72 6f 75 70 2d 3e 6e 52 65 61 6c 20 3d 20  pGroup->nReal = 
40b0: 30 3b 0a 7d 0a 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a  0;.}.../********
40c0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
40d0: 2a 20 56 46 53 20 4d 65 74 68 6f 64 20 57 72 61  * VFS Method Wra
40e0: 70 70 65 72 73 20 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ppers **********
40f0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
4100: 2a 2a 2a 2f 0a 0a 2f 2a 0a 2a 2a 20 54 68 69 73  ***/../*.** This
4110: 20 69 73 20 74 68 65 20 78 4f 70 65 6e 20 6d 65   is the xOpen me
4120: 74 68 6f 64 20 75 73 65 64 20 66 6f 72 20 74 68  thod used for th
4130: 65 20 22 6d 75 6c 74 69 70 6c 65 78 22 20 56 46  e "multiplex" VF
4140: 53 2e 0a 2a 2a 0a 2a 2a 20 4d 6f 73 74 20 6f 66  S..**.** Most of
4150: 20 74 68 65 20 77 6f 72 6b 20 69 73 20 64 6f 6e   the work is don
4160: 65 20 62 79 20 74 68 65 20 75 6e 64 65 72 6c 79  e by the underly
4170: 69 6e 67 20 6f 72 69 67 69 6e 61 6c 20 56 46 53  ing original VFS
4180: 2e 20 20 54 68 69 73 20 6d 65 74 68 6f 64 0a 2a  .  This method.*
4190: 2a 20 73 69 6d 70 6c 79 20 6c 69 6e 6b 73 20 74  * simply links t
41a0: 68 65 20 6e 65 77 20 66 69 6c 65 20 69 6e 74 6f  he new file into
41b0: 20 74 68 65 20 61 70 70 72 6f 70 72 69 61 74 65   the appropriate
41c0: 20 6d 75 6c 74 69 70 6c 65 78 20 67 72 6f 75 70   multiplex group
41d0: 20 69 66 20 69 74 20 69 73 20 61 0a 2a 2a 20 66   if it is a.** f
41e0: 69 6c 65 20 74 68 61 74 20 6e 65 65 64 73 20 74  ile that needs t
41f0: 6f 20 62 65 20 74 72 61 63 6b 65 64 2e 0a 2a 2f  o be tracked..*/
4200: 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74  .static int mult
4210: 69 70 6c 65 78 4f 70 65 6e 28 0a 20 20 73 71 6c  iplexOpen(.  sql
4220: 69 74 65 33 5f 76 66 73 20 2a 70 56 66 73 2c 20  ite3_vfs *pVfs, 
4230: 20 20 20 20 20 20 20 20 2f 2a 20 54 68 65 20 6d          /* The m
4240: 75 6c 74 69 70 6c 65 78 20 56 46 53 20 2a 2f 0a  ultiplex VFS */.
4250: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 4e    const char *zN
4260: 61 6d 65 2c 20 20 20 20 20 20 20 20 20 2f 2a 20  ame,         /* 
4270: 4e 61 6d 65 20 6f 66 20 66 69 6c 65 20 74 6f 20  Name of file to 
4280: 62 65 20 6f 70 65 6e 65 64 20 2a 2f 0a 20 20 73  be opened */.  s
4290: 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f  qlite3_file *pCo
42a0: 6e 6e 2c 20 20 20 20 20 20 20 2f 2a 20 46 69 6c  nn,       /* Fil
42b0: 6c 20 69 6e 20 74 68 69 73 20 66 69 6c 65 20 64  l in this file d
42c0: 65 73 63 72 69 70 74 6f 72 20 2a 2f 0a 20 20 69  escriptor */.  i
42d0: 6e 74 20 66 6c 61 67 73 2c 20 20 20 20 20 20 20  nt flags,       
42e0: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 46 6c 61            /* Fla
42f0: 67 73 20 74 6f 20 63 6f 6e 74 72 6f 6c 20 74 68  gs to control th
4300: 65 20 6f 70 65 6e 69 6e 67 20 2a 2f 0a 20 20 69  e opening */.  i
4310: 6e 74 20 2a 70 4f 75 74 46 6c 61 67 73 20 20 20  nt *pOutFlags   
4320: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 46 6c 61            /* Fla
4330: 67 73 20 73 68 6f 77 69 6e 67 20 72 65 73 75 6c  gs showing resul
4340: 74 73 20 6f 66 20 6f 70 65 6e 69 6e 67 20 2a 2f  ts of opening */
4350: 0a 29 7b 0a 20 20 69 6e 74 20 72 63 20 3d 20 53  .){.  int rc = S
4360: 51 4c 49 54 45 5f 4f 4b 3b 20 20 20 20 20 20 20  QLITE_OK;       
4370: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 52 65             /* Re
4380: 73 75 6c 74 20 63 6f 64 65 20 2a 2f 0a 20 20 6d  sult code */.  m
4390: 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70 4d  ultiplexConn *pM
43a0: 75 6c 74 69 70 6c 65 78 4f 70 65 6e 3b 20 20 20  ultiplexOpen;   
43b0: 20 20 20 20 2f 2a 20 54 68 65 20 6e 65 77 20 6d      /* The new m
43c0: 75 6c 74 69 70 6c 65 78 20 66 69 6c 65 20 64 65  ultiplex file de
43d0: 73 63 72 69 70 74 6f 72 20 2a 2f 0a 20 20 6d 75  scriptor */.  mu
43e0: 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 2a 70 47  ltiplexGroup *pG
43f0: 72 6f 75 70 20 3d 20 30 3b 20 20 20 20 20 20 20  roup = 0;       
4400: 20 20 20 2f 2a 20 43 6f 72 72 65 73 70 6f 6e 64     /* Correspond
4410: 69 6e 67 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f  ing multiplexGro
4420: 75 70 20 6f 62 6a 65 63 74 20 2a 2f 0a 20 20 73  up object */.  s
4430: 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75  qlite3_file *pSu
4440: 62 4f 70 65 6e 20 3d 20 30 3b 20 20 20 20 20 20  bOpen = 0;      
4450: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
4460: 20 52 65 61 6c 20 66 69 6c 65 20 64 65 73 63 72   Real file descr
4470: 69 70 74 6f 72 20 2a 2f 0a 20 20 73 71 6c 69 74  iptor */.  sqlit
4480: 65 33 5f 76 66 73 20 2a 70 4f 72 69 67 56 66 73  e3_vfs *pOrigVfs
4490: 20 3d 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f   = gMultiplex.pO
44a0: 72 69 67 56 66 73 3b 20 20 20 2f 2a 20 52 65 61  rigVfs;   /* Rea
44b0: 6c 20 56 46 53 20 2a 2f 0a 20 20 69 6e 74 20 6e  l VFS */.  int n
44c0: 4e 61 6d 65 20 3d 20 30 3b 0a 20 20 69 6e 74 20  Name = 0;.  int 
44d0: 73 7a 20 3d 20 30 3b 0a 20 20 63 68 61 72 20 2a  sz = 0;.  char *
44e0: 7a 54 6f 46 72 65 65 20 3d 20 30 3b 0a 0a 20 20  zToFree = 0;..  
44f0: 55 4e 55 53 45 44 5f 50 41 52 41 4d 45 54 45 52  UNUSED_PARAMETER
4500: 28 70 56 66 73 29 3b 0a 20 20 6d 65 6d 73 65 74  (pVfs);.  memset
4510: 28 70 43 6f 6e 6e 2c 20 30 2c 20 70 56 66 73 2d  (pConn, 0, pVfs-
4520: 3e 73 7a 4f 73 46 69 6c 65 29 3b 0a 20 20 61 73  >szOsFile);.  as
4530: 73 65 72 74 28 20 7a 4e 61 6d 65 20 7c 7c 20 28  sert( zName || (
4540: 66 6c 61 67 73 20 26 20 53 51 4c 49 54 45 5f 4f  flags & SQLITE_O
4550: 50 45 4e 5f 44 45 4c 45 54 45 4f 4e 43 4c 4f 53  PEN_DELETEONCLOS
4560: 45 29 20 29 3b 0a 0a 20 20 2f 2a 20 57 65 20 6e  E) );..  /* We n
4570: 65 65 64 20 74 6f 20 63 72 65 61 74 65 20 61 20  eed to create a 
4580: 67 72 6f 75 70 20 73 74 72 75 63 74 75 72 65 20  group structure 
4590: 61 6e 64 20 6d 61 6e 61 67 65 0a 20 20 2a 2a 20  and manage.  ** 
45a0: 61 63 63 65 73 73 20 74 6f 20 74 68 69 73 20 67  access to this g
45b0: 72 6f 75 70 20 6f 66 20 66 69 6c 65 73 2e 0a 20  roup of files.. 
45c0: 20 2a 2f 0a 20 20 6d 75 6c 74 69 70 6c 65 78 45   */.  multiplexE
45d0: 6e 74 65 72 28 29 3b 0a 20 20 70 4d 75 6c 74 69  nter();.  pMulti
45e0: 70 6c 65 78 4f 70 65 6e 20 3d 20 28 6d 75 6c 74  plexOpen = (mult
45f0: 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e  iplexConn*)pConn
4600: 3b 0a 0a 20 20 69 66 28 20 72 63 3d 3d 53 51 4c  ;..  if( rc==SQL
4610: 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 2f 2a  ITE_OK ){.    /*
4620: 20 61 6c 6c 6f 63 61 74 65 20 73 70 61 63 65 20   allocate space 
4630: 66 6f 72 20 67 72 6f 75 70 20 2a 2f 0a 20 20 20  for group */.   
4640: 20 6e 4e 61 6d 65 20 3d 20 7a 4e 61 6d 65 20 3f   nName = zName ?
4650: 20 6d 75 6c 74 69 70 6c 65 78 53 74 72 6c 65 6e   multiplexStrlen
4660: 33 30 28 7a 4e 61 6d 65 29 20 3a 20 30 3b 0a 20  30(zName) : 0;. 
4670: 20 20 20 73 7a 20 3d 20 73 69 7a 65 6f 66 28 6d     sz = sizeof(m
4680: 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 29 20 20  ultiplexGroup)  
4690: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
46a0: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 6d 75             /* mu
46b0: 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 2a 2f 0a  ltiplexGroup */.
46c0: 20 20 20 20 20 20 20 2b 20 6e 4e 61 6d 65 20 2b         + nName +
46d0: 20 31 3b 20 20 20 20 20 20 20 20 20 20 20 20 20   1;             
46e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
46f0: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 7a              /* z
4700: 4e 61 6d 65 20 2a 2f 0a 20 20 20 20 70 47 72 6f  Name */.    pGro
4710: 75 70 20 3d 20 73 71 6c 69 74 65 33 5f 6d 61 6c  up = sqlite3_mal
4720: 6c 6f 63 28 20 73 7a 20 29 3b 0a 20 20 20 20 69  loc( sz );.    i
4730: 66 28 20 70 47 72 6f 75 70 3d 3d 30 20 29 7b 0a  f( pGroup==0 ){.
4740: 20 20 20 20 20 20 72 63 20 3d 20 53 51 4c 49 54        rc = SQLIT
4750: 45 5f 4e 4f 4d 45 4d 3b 0a 20 20 20 20 7d 0a 20  E_NOMEM;.    }. 
4760: 20 7d 0a 0a 20 20 69 66 28 20 72 63 3d 3d 53 51   }..  if( rc==SQ
4770: 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 63  LITE_OK ){.    c
4780: 6f 6e 73 74 20 63 68 61 72 20 2a 7a 55 72 69 20  onst char *zUri 
4790: 3d 20 28 66 6c 61 67 73 20 26 20 53 51 4c 49 54  = (flags & SQLIT
47a0: 45 5f 4f 50 45 4e 5f 55 52 49 29 20 3f 20 7a 4e  E_OPEN_URI) ? zN
47b0: 61 6d 65 20 3a 20 30 3b 0a 20 20 20 20 2f 2a 20  ame : 0;.    /* 
47c0: 61 73 73 69 67 6e 20 70 6f 69 6e 74 65 72 73 20  assign pointers 
47d0: 74 6f 20 65 78 74 72 61 20 73 70 61 63 65 20 61  to extra space a
47e0: 6c 6c 6f 63 61 74 65 64 20 2a 2f 0a 20 20 20 20  llocated */.    
47f0: 6d 65 6d 73 65 74 28 70 47 72 6f 75 70 2c 20 30  memset(pGroup, 0
4800: 2c 20 73 7a 29 3b 0a 20 20 20 20 70 4d 75 6c 74  , sz);.    pMult
4810: 69 70 6c 65 78 4f 70 65 6e 2d 3e 70 47 72 6f 75  iplexOpen->pGrou
4820: 70 20 3d 20 70 47 72 6f 75 70 3b 0a 20 20 20 20  p = pGroup;.    
4830: 70 47 72 6f 75 70 2d 3e 62 45 6e 61 62 6c 65 64  pGroup->bEnabled
4840: 20 3d 20 2d 31 3b 0a 20 20 20 20 70 47 72 6f 75   = -1;.    pGrou
4850: 70 2d 3e 62 54 72 75 6e 63 61 74 65 20 3d 20 73  p->bTruncate = s
4860: 71 6c 69 74 65 33 5f 75 72 69 5f 62 6f 6f 6c 65  qlite3_uri_boole
4870: 61 6e 28 7a 55 72 69 2c 20 22 74 72 75 6e 63 61  an(zUri, "trunca
4880: 74 65 22 2c 20 0a 20 20 20 20 20 20 20 20 20 20  te", .          
4890: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
48a0: 20 20 20 20 20 20 20 20 20 28 66 6c 61 67 73 20           (flags 
48b0: 26 20 53 51 4c 49 54 45 5f 4f 50 45 4e 5f 4d 41  & SQLITE_OPEN_MA
48c0: 49 4e 5f 44 42 29 3d 3d 30 29 3b 0a 20 20 20 20  IN_DB)==0);.    
48d0: 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 20  pGroup->szChunk 
48e0: 3d 20 28 69 6e 74 29 73 71 6c 69 74 65 33 5f 75  = (int)sqlite3_u
48f0: 72 69 5f 69 6e 74 36 34 28 7a 55 72 69 2c 20 22  ri_int64(zUri, "
4900: 63 68 75 6e 6b 73 69 7a 65 22 2c 0a 20 20 20 20  chunksize",.    
4910: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4920: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4930: 20 20 20 20 53 51 4c 49 54 45 5f 4d 55 4c 54 49      SQLITE_MULTI
4940: 50 4c 45 58 5f 43 48 55 4e 4b 5f 53 49 5a 45 29  PLEX_CHUNK_SIZE)
4950: 3b 0a 20 20 20 20 70 47 72 6f 75 70 2d 3e 73 7a  ;.    pGroup->sz
4960: 43 68 75 6e 6b 20 3d 20 28 70 47 72 6f 75 70 2d  Chunk = (pGroup-
4970: 3e 73 7a 43 68 75 6e 6b 2b 30 78 66 66 66 66 29  >szChunk+0xffff)
4980: 26 7e 30 78 66 66 66 66 3b 0a 20 20 20 20 69 66  &~0xffff;.    if
4990: 28 20 7a 4e 61 6d 65 20 29 7b 0a 20 20 20 20 20  ( zName ){.     
49a0: 20 63 68 61 72 20 2a 70 20 3d 20 28 63 68 61 72   char *p = (char
49b0: 20 2a 29 26 70 47 72 6f 75 70 5b 31 5d 3b 0a 20   *)&pGroup[1];. 
49c0: 20 20 20 20 20 70 47 72 6f 75 70 2d 3e 7a 4e 61       pGroup->zNa
49d0: 6d 65 20 3d 20 70 3b 0a 20 20 20 20 20 20 6d 65  me = p;.      me
49e0: 6d 63 70 79 28 70 47 72 6f 75 70 2d 3e 7a 4e 61  mcpy(pGroup->zNa
49f0: 6d 65 2c 20 7a 4e 61 6d 65 2c 20 6e 4e 61 6d 65  me, zName, nName
4a00: 2b 31 29 3b 0a 20 20 20 20 20 20 70 47 72 6f 75  +1);.      pGrou
4a10: 70 2d 3e 6e 4e 61 6d 65 20 3d 20 6e 4e 61 6d 65  p->nName = nName
4a20: 3b 0a 20 20 20 20 7d 0a 20 20 20 20 69 66 28 20  ;.    }.    if( 
4a30: 70 47 72 6f 75 70 2d 3e 62 45 6e 61 62 6c 65 64  pGroup->bEnabled
4a40: 20 29 7b 0a 20 20 20 20 20 20 2f 2a 20 4d 61 6b   ){.      /* Mak
4a50: 65 20 73 75 72 65 20 74 68 61 74 20 74 68 65 20  e sure that the 
4a60: 63 68 75 6e 6b 73 69 7a 65 20 69 73 20 73 75 63  chunksize is suc
4a70: 68 20 74 68 61 74 20 74 68 65 20 70 65 6e 64 69  h that the pendi
4a80: 6e 67 20 62 79 74 65 20 64 6f 65 73 20 6e 6f 74  ng byte does not
4a90: 0a 20 20 20 20 20 20 2a 2a 20 66 61 6c 6c 73 20  .      ** falls 
4aa0: 61 74 20 74 68 65 20 65 6e 64 20 6f 66 20 61 20  at the end of a 
4ab0: 63 68 75 6e 6b 2e 20 20 41 20 72 65 67 69 6f 6e  chunk.  A region
4ac0: 20 6f 66 20 75 70 20 74 6f 20 36 34 4b 20 66 6f   of up to 64K fo
4ad0: 6c 6c 6f 77 69 6e 67 0a 20 20 20 20 20 20 2a 2a  llowing.      **
4ae0: 20 74 68 65 20 70 65 6e 64 69 6e 67 20 62 79 74   the pending byt
4af0: 65 20 69 73 20 6e 65 76 65 72 20 77 72 69 74 74  e is never writt
4b00: 65 6e 2c 20 73 6f 20 69 66 20 74 68 65 20 70 65  en, so if the pe
4b10: 6e 64 69 6e 67 20 62 79 74 65 20 6f 63 63 75 72  nding byte occur
4b20: 73 0a 20 20 20 20 20 20 2a 2a 20 6e 65 61 72 20  s.      ** near 
4b30: 74 68 65 20 65 6e 64 20 6f 66 20 61 20 63 68 75  the end of a chu
4b40: 6e 6b 2c 20 74 68 61 74 20 63 68 75 6e 6b 20 77  nk, that chunk w
4b50: 69 6c 6c 20 62 65 20 74 6f 6f 20 73 6d 61 6c 6c  ill be too small
4b60: 2e 20 2a 2f 0a 23 69 66 6e 64 65 66 20 53 51 4c  . */.#ifndef SQL
4b70: 49 54 45 5f 4f 4d 49 54 5f 57 53 44 0a 20 20 20  ITE_OMIT_WSD.   
4b80: 20 20 20 65 78 74 65 72 6e 20 69 6e 74 20 73 71     extern int sq
4b90: 6c 69 74 65 33 50 65 6e 64 69 6e 67 42 79 74 65  lite3PendingByte
4ba0: 3b 0a 23 65 6c 73 65 0a 20 20 20 20 20 20 69 6e  ;.#else.      in
4bb0: 74 20 73 71 6c 69 74 65 33 50 65 6e 64 69 6e 67  t sqlite3Pending
4bc0: 42 79 74 65 20 3d 20 30 78 34 30 30 30 30 30 30  Byte = 0x4000000
4bd0: 30 3b 0a 23 65 6e 64 69 66 0a 20 20 20 20 20 20  0;.#endif.      
4be0: 77 68 69 6c 65 28 20 28 73 71 6c 69 74 65 33 50  while( (sqlite3P
4bf0: 65 6e 64 69 6e 67 42 79 74 65 20 25 20 70 47 72  endingByte % pGr
4c00: 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 29 3e 3d 28  oup->szChunk)>=(
4c10: 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 2d  pGroup->szChunk-
4c20: 36 35 35 33 36 29 20 29 7b 0a 20 20 20 20 20 20  65536) ){.      
4c30: 20 20 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e    pGroup->szChun
4c40: 6b 20 2b 3d 20 36 35 35 33 36 3b 0a 20 20 20 20  k += 65536;.    
4c50: 20 20 7d 0a 20 20 20 20 7d 0a 20 20 20 20 70 47    }.    }.    pG
4c60: 72 6f 75 70 2d 3e 66 6c 61 67 73 20 3d 20 66 6c  roup->flags = fl
4c70: 61 67 73 3b 0a 20 20 20 20 72 63 20 3d 20 6d 75  ags;.    rc = mu
4c80: 6c 74 69 70 6c 65 78 53 75 62 46 69 6c 65 6e 61  ltiplexSubFilena
4c90: 6d 65 28 70 47 72 6f 75 70 2c 20 31 29 3b 0a 20  me(pGroup, 1);. 
4ca0: 20 20 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54     if( rc==SQLIT
4cb0: 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 70 53  E_OK ){.      pS
4cc0: 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c  ubOpen = multipl
4cd0: 65 78 53 75 62 4f 70 65 6e 28 70 47 72 6f 75 70  exSubOpen(pGroup
4ce0: 2c 20 30 2c 20 26 72 63 2c 20 70 4f 75 74 46 6c  , 0, &rc, pOutFl
4cf0: 61 67 73 2c 20 30 29 3b 0a 20 20 20 20 20 20 69  ags, 0);.      i
4d00: 66 28 20 70 53 75 62 4f 70 65 6e 3d 3d 30 20 26  f( pSubOpen==0 &
4d10: 26 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20  & rc==SQLITE_OK 
4d20: 29 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 43 41  ) rc = SQLITE_CA
4d30: 4e 54 4f 50 45 4e 3b 0a 20 20 20 20 7d 0a 20 20  NTOPEN;.    }.  
4d40: 20 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54 45    if( rc==SQLITE
4d50: 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 73 71 6c  _OK ){.      sql
4d60: 69 74 65 33 5f 69 6e 74 36 34 20 73 7a 3b 0a 0a  ite3_int64 sz;..
4d70: 20 20 20 20 20 20 72 63 20 3d 20 70 53 75 62 4f        rc = pSubO
4d80: 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e 78  pen->pMethods->x
4d90: 46 69 6c 65 53 69 7a 65 28 70 53 75 62 4f 70 65  FileSize(pSubOpe
4da0: 6e 2c 20 26 73 7a 29 3b 0a 20 20 20 20 20 20 69  n, &sz);.      i
4db0: 66 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b  f( rc==SQLITE_OK
4dc0: 20 26 26 20 7a 4e 61 6d 65 20 29 7b 0a 20 20 20   && zName ){.   
4dd0: 20 20 20 20 20 69 6e 74 20 62 45 78 69 73 74 73       int bExists
4de0: 3b 0a 20 20 20 20 20 20 20 20 69 66 28 20 73 7a  ;.        if( sz
4df0: 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 20 20 20  ==0 ){.         
4e00: 20 69 66 28 20 66 6c 61 67 73 20 26 20 53 51 4c   if( flags & SQL
4e10: 49 54 45 5f 4f 50 45 4e 5f 4d 41 49 4e 5f 4a 4f  ITE_OPEN_MAIN_JO
4e20: 55 52 4e 41 4c 20 29 7b 0a 20 20 20 20 20 20 20  URNAL ){.       
4e30: 20 20 20 20 20 2f 2a 20 49 66 20 6f 70 65 6e 69       /* If openi
4e40: 6e 67 20 61 20 6d 61 69 6e 20 6a 6f 75 72 6e 61  ng a main journa
4e50: 6c 20 66 69 6c 65 20 61 6e 64 20 74 68 65 20 66  l file and the f
4e60: 69 72 73 74 20 63 68 75 6e 6b 20 69 73 20 7a 65  irst chunk is ze
4e70: 72 6f 0a 20 20 20 20 20 20 20 20 20 20 20 20 2a  ro.            *
4e80: 2a 20 62 79 74 65 73 20 69 6e 20 73 69 7a 65 2c  * bytes in size,
4e90: 20 64 65 6c 65 74 65 20 61 6e 79 20 73 75 62 73   delete any subs
4ea0: 65 71 75 65 6e 74 20 63 68 75 6e 6b 73 20 66 72  equent chunks fr
4eb0: 6f 6d 20 74 68 65 20 0a 20 20 20 20 20 20 20 20  om the .        
4ec0: 20 20 20 20 2a 2a 20 66 69 6c 65 2d 73 79 73 74      ** file-syst
4ed0: 65 6d 2e 20 2a 2f 0a 20 20 20 20 20 20 20 20 20  em. */.         
4ee0: 20 20 20 69 6e 74 20 69 43 68 75 6e 6b 20 3d 20     int iChunk = 
4ef0: 31 3b 0a 20 20 20 20 20 20 20 20 20 20 20 20 64  1;.            d
4f00: 6f 20 7b 0a 20 20 20 20 20 20 20 20 20 20 20 20  o {.            
4f10: 20 20 72 63 20 3d 20 70 4f 72 69 67 56 66 73 2d    rc = pOrigVfs-
4f20: 3e 78 41 63 63 65 73 73 28 70 4f 72 69 67 56 66  >xAccess(pOrigVf
4f30: 73 2c 20 0a 20 20 20 20 20 20 20 20 20 20 20 20  s, .            
4f40: 20 20 20 20 20 20 70 47 72 6f 75 70 2d 3e 61 52        pGroup->aR
4f50: 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e 7a 2c 20 53  eal[iChunk].z, S
4f60: 51 4c 49 54 45 5f 41 43 43 45 53 53 5f 45 58 49  QLITE_ACCESS_EXI
4f70: 53 54 53 2c 20 26 62 45 78 69 73 74 73 0a 20 20  STS, &bExists.  
4f80: 20 20 20 20 20 20 20 20 20 20 20 20 29 3b 0a 20              );. 
4f90: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66 28               if(
4fa0: 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 26   rc==SQLITE_OK &
4fb0: 26 20 62 45 78 69 73 74 73 20 29 7b 0a 20 20 20  & bExists ){.   
4fc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 72 63 20               rc 
4fd0: 3d 20 70 4f 72 69 67 56 66 73 2d 3e 78 44 65 6c  = pOrigVfs->xDel
4fe0: 65 74 65 28 70 4f 72 69 67 56 66 73 2c 20 70 47  ete(pOrigVfs, pG
4ff0: 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68 75  roup->aReal[iChu
5000: 6e 6b 5d 2e 7a 2c 20 30 29 3b 0a 20 20 20 20 20  nk].z, 0);.     
5010: 20 20 20 20 20 20 20 20 20 20 20 69 66 28 20 72             if( r
5020: 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a  c==SQLITE_OK ){.
5030: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5040: 20 20 72 63 20 3d 20 6d 75 6c 74 69 70 6c 65 78    rc = multiplex
5050: 53 75 62 46 69 6c 65 6e 61 6d 65 28 70 47 72 6f  SubFilename(pGro
5060: 75 70 2c 20 2b 2b 69 43 68 75 6e 6b 29 3b 0a 20  up, ++iChunk);. 
5070: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 7d                 }
5080: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 7d  .              }
5090: 0a 20 20 20 20 20 20 20 20 20 20 20 20 7d 77 68  .            }wh
50a0: 69 6c 65 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f  ile( rc==SQLITE_
50b0: 4f 4b 20 26 26 20 62 45 78 69 73 74 73 20 29 3b  OK && bExists );
50c0: 0a 20 20 20 20 20 20 20 20 20 20 7d 0a 20 20 20  .          }.   
50d0: 20 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20       }else{.    
50e0: 20 20 20 20 20 20 2f 2a 20 49 66 20 74 68 65 20        /* If the 
50f0: 66 69 72 73 74 20 6f 76 65 72 66 6c 6f 77 20 66  first overflow f
5100: 69 6c 65 20 65 78 69 73 74 73 20 61 6e 64 20 69  ile exists and i
5110: 66 20 74 68 65 20 73 69 7a 65 20 6f 66 20 74 68  f the size of th
5120: 65 20 6d 61 69 6e 20 66 69 6c 65 0a 20 20 20 20  e main file.    
5130: 20 20 20 20 20 20 2a 2a 20 69 73 20 64 69 66 66        ** is diff
5140: 65 72 65 6e 74 20 66 72 6f 6d 20 74 68 65 20 63  erent from the c
5150: 68 75 6e 6b 20 73 69 7a 65 2c 20 74 68 61 74 20  hunk size, that 
5160: 6d 65 61 6e 73 20 74 68 65 20 63 68 75 6e 6b 20  means the chunk 
5170: 73 69 7a 65 20 69 73 20 73 65 74 0a 20 20 20 20  size is set.    
5180: 20 20 20 20 20 20 2a 2a 20 73 65 74 20 69 6e 63        ** set inc
5190: 6f 72 72 65 63 74 6c 79 2e 20 20 53 6f 20 66 69  orrectly.  So fi
51a0: 78 20 69 74 2e 0a 20 20 20 20 20 20 20 20 20 20  x it..          
51b0: 2a 2a 0a 20 20 20 20 20 20 20 20 20 20 2a 2a 20  **.          ** 
51c0: 4f 72 2c 20 69 66 20 74 68 65 20 66 69 72 73 74  Or, if the first
51d0: 20 6f 76 65 72 66 6c 6f 77 20 66 69 6c 65 20 64   overflow file d
51e0: 6f 65 73 20 6e 6f 74 20 65 78 69 73 74 20 61 6e  oes not exist an
51f0: 64 20 74 68 65 20 6d 61 69 6e 20 66 69 6c 65 20  d the main file 
5200: 69 73 0a 20 20 20 20 20 20 20 20 20 20 2a 2a 20  is.          ** 
5210: 6c 61 72 67 65 72 20 74 68 61 6e 20 74 68 65 20  larger than the 
5220: 63 68 75 6e 6b 20 73 69 7a 65 2c 20 74 68 61 74  chunk size, that
5230: 20 6d 65 61 6e 73 20 74 68 65 20 63 68 75 6e 6b   means the chunk
5240: 20 73 69 7a 65 20 69 73 20 74 6f 6f 20 73 6d 61   size is too sma
5250: 6c 6c 2e 0a 20 20 20 20 20 20 20 20 20 20 2a 2a  ll..          **
5260: 20 42 75 74 20 77 65 20 68 61 76 65 20 6e 6f 20   But we have no 
5270: 77 61 79 20 6f 66 20 64 65 74 65 72 6d 69 6e 69  way of determini
5280: 6e 67 20 74 68 65 20 69 6e 74 65 6e 64 65 64 20  ng the intended 
5290: 63 68 75 6e 6b 20 73 69 7a 65 2c 20 73 6f 20 0a  chunk size, so .
52a0: 20 20 20 20 20 20 20 20 20 20 2a 2a 20 6a 75 73            ** jus
52b0: 74 20 64 69 73 61 62 6c 65 20 74 68 65 20 6d 75  t disable the mu
52c0: 6c 74 69 70 6c 65 78 6f 72 20 61 6c 6c 20 74 6f  ltiplexor all to
52d0: 67 65 74 68 72 65 2e 0a 20 20 20 20 20 20 20 20  gethre..        
52e0: 20 20 2a 2f 0a 20 20 20 20 20 20 20 20 20 20 72    */.          r
52f0: 63 20 3d 20 70 4f 72 69 67 56 66 73 2d 3e 78 41  c = pOrigVfs->xA
5300: 63 63 65 73 73 28 70 4f 72 69 67 56 66 73 2c 20  ccess(pOrigVfs, 
5310: 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 31 5d  pGroup->aReal[1]
5320: 2e 7a 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20  .z,.            
5330: 20 20 53 51 4c 49 54 45 5f 41 43 43 45 53 53 5f    SQLITE_ACCESS_
5340: 45 58 49 53 54 53 2c 20 26 62 45 78 69 73 74 73  EXISTS, &bExists
5350: 29 3b 0a 20 20 20 20 20 20 20 20 20 20 62 45 78  );.          bEx
5360: 69 73 74 73 20 3d 20 6d 75 6c 74 69 70 6c 65 78  ists = multiplex
5370: 53 75 62 53 69 7a 65 28 70 47 72 6f 75 70 2c 20  SubSize(pGroup, 
5380: 31 2c 20 26 72 63 29 3e 30 3b 0a 20 20 20 20 20  1, &rc)>0;.     
5390: 20 20 20 20 20 69 66 28 20 72 63 3d 3d 53 51 4c       if( rc==SQL
53a0: 49 54 45 5f 4f 4b 20 26 26 20 62 45 78 69 73 74  ITE_OK && bExist
53b0: 73 20 20 26 26 20 73 7a 3d 3d 28 73 7a 26 30 78  s  && sz==(sz&0x
53c0: 66 66 66 66 30 30 30 30 29 20 26 26 20 73 7a 3e  ffff0000) && sz>
53d0: 30 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  0.              
53e0: 26 26 20 73 7a 21 3d 70 47 72 6f 75 70 2d 3e 73  && sz!=pGroup->s
53f0: 7a 43 68 75 6e 6b 20 29 7b 0a 20 20 20 20 20 20  zChunk ){.      
5400: 20 20 20 20 20 20 70 47 72 6f 75 70 2d 3e 73 7a        pGroup->sz
5410: 43 68 75 6e 6b 20 3d 20 28 69 6e 74 29 73 7a 3b  Chunk = (int)sz;
5420: 0a 20 20 20 20 20 20 20 20 20 20 7d 65 6c 73 65  .          }else
5430: 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f   if( rc==SQLITE_
5440: 4f 4b 20 26 26 20 21 62 45 78 69 73 74 73 20 26  OK && !bExists &
5450: 26 20 73 7a 3e 70 47 72 6f 75 70 2d 3e 73 7a 43  & sz>pGroup->szC
5460: 68 75 6e 6b 20 29 7b 0a 20 20 20 20 20 20 20 20  hunk ){.        
5470: 20 20 20 20 70 47 72 6f 75 70 2d 3e 62 45 6e 61      pGroup->bEna
5480: 62 6c 65 64 20 3d 20 30 3b 0a 20 20 20 20 20 20  bled = 0;.      
5490: 20 20 20 20 7d 0a 20 20 20 20 20 20 20 20 7d 0a      }.        }.
54a0: 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a 0a 20        }.    }.. 
54b0: 20 20 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54     if( rc==SQLIT
54c0: 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 69 66  E_OK ){.      if
54d0: 28 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74  ( pSubOpen->pMet
54e0: 68 6f 64 73 2d 3e 69 56 65 72 73 69 6f 6e 3d 3d  hods->iVersion==
54f0: 31 20 29 7b 0a 20 20 20 20 20 20 20 20 70 4d 75  1 ){.        pMu
5500: 6c 74 69 70 6c 65 78 4f 70 65 6e 2d 3e 62 61 73  ltiplexOpen->bas
5510: 65 2e 70 4d 65 74 68 6f 64 73 20 3d 20 26 67 4d  e.pMethods = &gM
5520: 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68  ultiplex.sIoMeth
5530: 6f 64 73 56 31 3b 0a 20 20 20 20 20 20 7d 65 6c  odsV1;.      }el
5540: 73 65 7b 0a 20 20 20 20 20 20 20 20 70 4d 75 6c  se{.        pMul
5550: 74 69 70 6c 65 78 4f 70 65 6e 2d 3e 62 61 73 65  tiplexOpen->base
5560: 2e 70 4d 65 74 68 6f 64 73 20 3d 20 26 67 4d 75  .pMethods = &gMu
5570: 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f  ltiplex.sIoMetho
5580: 64 73 56 32 3b 0a 20 20 20 20 20 20 7d 0a 20 20  dsV2;.      }.  
5590: 20 20 20 20 2f 2a 20 70 6c 61 63 65 20 74 68 69      /* place thi
55a0: 73 20 67 72 6f 75 70 20 61 74 20 74 68 65 20 68  s group at the h
55b0: 65 61 64 20 6f 66 20 6f 75 72 20 6c 69 73 74 20  ead of our list 
55c0: 2a 2f 0a 20 20 20 20 20 20 70 47 72 6f 75 70 2d  */.      pGroup-
55d0: 3e 70 4e 65 78 74 20 3d 20 67 4d 75 6c 74 69 70  >pNext = gMultip
55e0: 6c 65 78 2e 70 47 72 6f 75 70 73 3b 0a 20 20 20  lex.pGroups;.   
55f0: 20 20 20 69 66 28 20 67 4d 75 6c 74 69 70 6c 65     if( gMultiple
5600: 78 2e 70 47 72 6f 75 70 73 20 29 20 67 4d 75 6c  x.pGroups ) gMul
5610: 74 69 70 6c 65 78 2e 70 47 72 6f 75 70 73 2d 3e  tiplex.pGroups->
5620: 70 50 72 65 76 20 3d 20 70 47 72 6f 75 70 3b 0a  pPrev = pGroup;.
5630: 20 20 20 20 20 20 67 4d 75 6c 74 69 70 6c 65 78        gMultiplex
5640: 2e 70 47 72 6f 75 70 73 20 3d 20 70 47 72 6f 75  .pGroups = pGrou
5650: 70 3b 0a 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20  p;.    }else{.  
5660: 20 20 20 20 6d 75 6c 74 69 70 6c 65 78 46 72 65      multiplexFre
5670: 65 43 6f 6d 70 6f 6e 65 6e 74 73 28 70 47 72 6f  eComponents(pGro
5680: 75 70 29 3b 0a 20 20 20 20 20 20 73 71 6c 69 74  up);.      sqlit
5690: 65 33 5f 66 72 65 65 28 70 47 72 6f 75 70 29 3b  e3_free(pGroup);
56a0: 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20 6d 75 6c  .    }.  }.  mul
56b0: 74 69 70 6c 65 78 4c 65 61 76 65 28 29 3b 0a 20  tiplexLeave();. 
56c0: 20 73 71 6c 69 74 65 33 5f 66 72 65 65 28 7a 54   sqlite3_free(zT
56d0: 6f 46 72 65 65 29 3b 0a 20 20 72 65 74 75 72 6e  oFree);.  return
56e0: 20 72 63 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54 68   rc;.}../*.** Th
56f0: 69 73 20 69 73 20 74 68 65 20 78 44 65 6c 65 74  is is the xDelet
5700: 65 20 6d 65 74 68 6f 64 20 75 73 65 64 20 66 6f  e method used fo
5710: 72 20 74 68 65 20 22 6d 75 6c 74 69 70 6c 65 78  r the "multiplex
5720: 22 20 56 46 53 2e 0a 2a 2a 20 49 74 20 61 74 74  " VFS..** It att
5730: 65 6d 70 74 73 20 74 6f 20 64 65 6c 65 74 65 20  empts to delete 
5740: 74 68 65 20 66 69 6c 65 6e 61 6d 65 20 73 70 65  the filename spe
5750: 63 69 66 69 65 64 2e 0a 2a 2f 0a 73 74 61 74 69  cified..*/.stati
5760: 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 44  c int multiplexD
5770: 65 6c 65 74 65 28 0a 20 20 73 71 6c 69 74 65 33  elete(.  sqlite3
5780: 5f 76 66 73 20 2a 70 56 66 73 2c 20 20 20 20 20  _vfs *pVfs,     
5790: 20 20 20 20 2f 2a 20 54 68 65 20 6d 75 6c 74 69      /* The multi
57a0: 70 6c 65 78 20 56 46 53 20 2a 2f 0a 20 20 63 6f  plex VFS */.  co
57b0: 6e 73 74 20 63 68 61 72 20 2a 7a 4e 61 6d 65 2c  nst char *zName,
57c0: 20 20 20 20 20 20 20 20 20 2f 2a 20 4e 61 6d 65           /* Name
57d0: 20 6f 66 20 66 69 6c 65 20 74 6f 20 64 65 6c 65   of file to dele
57e0: 74 65 20 2a 2f 0a 20 20 69 6e 74 20 73 79 6e 63  te */.  int sync
57f0: 44 69 72 0a 29 7b 0a 20 20 69 6e 74 20 72 63 3b  Dir.){.  int rc;
5800: 0a 20 20 73 71 6c 69 74 65 33 5f 76 66 73 20 2a  .  sqlite3_vfs *
5810: 70 4f 72 69 67 56 66 73 20 3d 20 67 4d 75 6c 74  pOrigVfs = gMult
5820: 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 3b 20  iplex.pOrigVfs; 
5830: 20 20 2f 2a 20 52 65 61 6c 20 56 46 53 20 2a 2f    /* Real VFS */
5840: 0a 20 20 72 63 20 3d 20 70 4f 72 69 67 56 66 73  .  rc = pOrigVfs
5850: 2d 3e 78 44 65 6c 65 74 65 28 70 4f 72 69 67 56  ->xDelete(pOrigV
5860: 66 73 2c 20 7a 4e 61 6d 65 2c 20 73 79 6e 63 44  fs, zName, syncD
5870: 69 72 29 3b 0a 20 20 69 66 28 20 72 63 3d 3d 53  ir);.  if( rc==S
5880: 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20  QLITE_OK ){.    
5890: 2f 2a 20 49 66 20 74 68 65 20 6d 61 69 6e 20 63  /* If the main c
58a0: 68 75 6e 6b 20 77 61 73 20 64 65 6c 65 74 65 64  hunk was deleted
58b0: 20 73 75 63 63 65 73 73 66 75 6c 6c 79 2c 20 61   successfully, a
58c0: 6c 73 6f 20 64 65 6c 65 74 65 20 61 6e 79 20 73  lso delete any s
58d0: 75 62 73 65 71 75 65 6e 74 0a 20 20 20 20 2a 2a  ubsequent.    **
58e0: 20 63 68 75 6e 6b 73 20 2d 20 73 74 61 72 74 69   chunks - starti
58f0: 6e 67 20 77 69 74 68 20 74 68 65 20 6c 61 73 74  ng with the last
5900: 20 28 68 69 67 68 65 73 74 20 6e 75 6d 62 65 72   (highest number
5910: 65 64 29 2e 20 0a 20 20 20 20 2a 2f 0a 20 20 20  ed). .    */.   
5920: 20 69 6e 74 20 6e 4e 61 6d 65 20 3d 20 28 69 6e   int nName = (in
5930: 74 29 73 74 72 6c 65 6e 28 7a 4e 61 6d 65 29 3b  t)strlen(zName);
5940: 0a 20 20 20 20 63 68 61 72 20 2a 7a 3b 0a 20 20  .    char *z;.  
5950: 20 20 7a 20 3d 20 73 71 6c 69 74 65 33 5f 6d 61    z = sqlite3_ma
5960: 6c 6c 6f 63 28 6e 4e 61 6d 65 20 2b 20 35 29 3b  lloc(nName + 5);
5970: 0a 20 20 20 20 69 66 28 20 7a 3d 3d 30 20 29 7b  .    if( z==0 ){
5980: 0a 20 20 20 20 20 20 72 63 20 3d 20 53 51 4c 49  .      rc = SQLI
5990: 54 45 5f 49 4f 45 52 52 5f 4e 4f 4d 45 4d 3b 0a  TE_IOERR_NOMEM;.
59a0: 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20      }else{.     
59b0: 20 69 6e 74 20 69 43 68 75 6e 6b 20 3d 20 30 3b   int iChunk = 0;
59c0: 0a 20 20 20 20 20 20 69 6e 74 20 62 45 78 69 73  .      int bExis
59d0: 74 73 3b 0a 20 20 20 20 20 20 64 6f 7b 0a 20 20  ts;.      do{.  
59e0: 20 20 20 20 20 20 6d 75 6c 74 69 70 6c 65 78 46        multiplexF
59f0: 69 6c 65 6e 61 6d 65 28 7a 4e 61 6d 65 2c 20 6e  ilename(zName, n
5a00: 4e 61 6d 65 2c 20 53 51 4c 49 54 45 5f 4f 50 45  Name, SQLITE_OPE
5a10: 4e 5f 4d 41 49 4e 5f 4a 4f 55 52 4e 41 4c 2c 20  N_MAIN_JOURNAL, 
5a20: 2b 2b 69 43 68 75 6e 6b 2c 20 7a 29 3b 0a 20 20  ++iChunk, z);.  
5a30: 20 20 20 20 20 20 72 63 20 3d 20 70 4f 72 69 67        rc = pOrig
5a40: 56 66 73 2d 3e 78 41 63 63 65 73 73 28 70 4f 72  Vfs->xAccess(pOr
5a50: 69 67 56 66 73 2c 20 7a 2c 20 53 51 4c 49 54 45  igVfs, z, SQLITE
5a60: 5f 41 43 43 45 53 53 5f 45 58 49 53 54 53 2c 20  _ACCESS_EXISTS, 
5a70: 26 62 45 78 69 73 74 73 29 3b 0a 20 20 20 20 20  &bExists);.     
5a80: 20 7d 77 68 69 6c 65 28 20 72 63 3d 3d 53 51 4c   }while( rc==SQL
5a90: 49 54 45 5f 4f 4b 20 26 26 20 62 45 78 69 73 74  ITE_OK && bExist
5aa0: 73 20 29 3b 0a 20 20 20 20 20 20 77 68 69 6c 65  s );.      while
5ab0: 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20  ( rc==SQLITE_OK 
5ac0: 26 26 20 69 43 68 75 6e 6b 3e 31 20 29 7b 0a 20  && iChunk>1 ){. 
5ad0: 20 20 20 20 20 20 20 6d 75 6c 74 69 70 6c 65 78         multiplex
5ae0: 46 69 6c 65 6e 61 6d 65 28 7a 4e 61 6d 65 2c 20  Filename(zName, 
5af0: 6e 4e 61 6d 65 2c 20 53 51 4c 49 54 45 5f 4f 50  nName, SQLITE_OP
5b00: 45 4e 5f 4d 41 49 4e 5f 4a 4f 55 52 4e 41 4c 2c  EN_MAIN_JOURNAL,
5b10: 20 2d 2d 69 43 68 75 6e 6b 2c 20 7a 29 3b 0a 20   --iChunk, z);. 
5b20: 20 20 20 20 20 20 20 72 63 20 3d 20 70 4f 72 69         rc = pOri
5b30: 67 56 66 73 2d 3e 78 44 65 6c 65 74 65 28 70 4f  gVfs->xDelete(pO
5b40: 72 69 67 56 66 73 2c 20 7a 2c 20 73 79 6e 63 44  rigVfs, z, syncD
5b50: 69 72 29 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20  ir);.      }.   
5b60: 20 20 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54     if( rc==SQLIT
5b70: 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 20 20  E_OK ){.        
5b80: 69 43 68 75 6e 6b 20 3d 20 30 3b 0a 20 20 20 20  iChunk = 0;.    
5b90: 20 20 20 20 64 6f 7b 0a 20 20 20 20 20 20 20 20      do{.        
5ba0: 20 20 6d 75 6c 74 69 70 6c 65 78 46 69 6c 65 6e    multiplexFilen
5bb0: 61 6d 65 28 7a 4e 61 6d 65 2c 20 6e 4e 61 6d 65  ame(zName, nName
5bc0: 2c 20 53 51 4c 49 54 45 5f 4f 50 45 4e 5f 57 41  , SQLITE_OPEN_WA
5bd0: 4c 2c 20 2b 2b 69 43 68 75 6e 6b 2c 20 7a 29 3b  L, ++iChunk, z);
5be0: 0a 20 20 20 20 20 20 20 20 20 20 72 63 20 3d 20  .          rc = 
5bf0: 70 4f 72 69 67 56 66 73 2d 3e 78 41 63 63 65 73  pOrigVfs->xAcces
5c00: 73 28 70 4f 72 69 67 56 66 73 2c 20 7a 2c 20 53  s(pOrigVfs, z, S
5c10: 51 4c 49 54 45 5f 41 43 43 45 53 53 5f 45 58 49  QLITE_ACCESS_EXI
5c20: 53 54 53 2c 20 26 62 45 78 69 73 74 73 29 3b 0a  STS, &bExists);.
5c30: 20 20 20 20 20 20 20 20 7d 77 68 69 6c 65 28 20          }while( 
5c40: 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 26 26  rc==SQLITE_OK &&
5c50: 20 62 45 78 69 73 74 73 20 29 3b 0a 20 20 20 20   bExists );.    
5c60: 20 20 20 20 77 68 69 6c 65 28 20 72 63 3d 3d 53      while( rc==S
5c70: 51 4c 49 54 45 5f 4f 4b 20 26 26 20 69 43 68 75  QLITE_OK && iChu
5c80: 6e 6b 3e 31 20 29 7b 0a 20 20 20 20 20 20 20 20  nk>1 ){.        
5c90: 20 20 6d 75 6c 74 69 70 6c 65 78 46 69 6c 65 6e    multiplexFilen
5ca0: 61 6d 65 28 7a 4e 61 6d 65 2c 20 6e 4e 61 6d 65  ame(zName, nName
5cb0: 2c 20 53 51 4c 49 54 45 5f 4f 50 45 4e 5f 57 41  , SQLITE_OPEN_WA
5cc0: 4c 2c 20 2d 2d 69 43 68 75 6e 6b 2c 20 7a 29 3b  L, --iChunk, z);
5cd0: 0a 20 20 20 20 20 20 20 20 20 20 72 63 20 3d 20  .          rc = 
5ce0: 70 4f 72 69 67 56 66 73 2d 3e 78 44 65 6c 65 74  pOrigVfs->xDelet
5cf0: 65 28 70 4f 72 69 67 56 66 73 2c 20 7a 2c 20 73  e(pOrigVfs, z, s
5d00: 79 6e 63 44 69 72 29 3b 0a 20 20 20 20 20 20 20  yncDir);.       
5d10: 20 7d 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 7d   }.      }.    }
5d20: 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 66 72 65  .    sqlite3_fre
5d30: 65 28 7a 29 3b 0a 20 20 7d 0a 20 20 72 65 74 75  e(z);.  }.  retu
5d40: 72 6e 20 72 63 3b 0a 7d 0a 0a 73 74 61 74 69 63  rn rc;.}..static
5d50: 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 41 63   int multiplexAc
5d60: 63 65 73 73 28 73 71 6c 69 74 65 33 5f 76 66 73  cess(sqlite3_vfs
5d70: 20 2a 61 2c 20 63 6f 6e 73 74 20 63 68 61 72 20   *a, const char 
5d80: 2a 62 2c 20 69 6e 74 20 63 2c 20 69 6e 74 20 2a  *b, int c, int *
5d90: 64 29 7b 0a 20 20 72 65 74 75 72 6e 20 67 4d 75  d){.  return gMu
5da0: 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73  ltiplex.pOrigVfs
5db0: 2d 3e 78 41 63 63 65 73 73 28 67 4d 75 6c 74 69  ->xAccess(gMulti
5dc0: 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2c 20 62  plex.pOrigVfs, b
5dd0: 2c 20 63 2c 20 64 29 3b 0a 7d 0a 73 74 61 74 69  , c, d);.}.stati
5de0: 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 46  c int multiplexF
5df0: 75 6c 6c 50 61 74 68 6e 61 6d 65 28 73 71 6c 69  ullPathname(sqli
5e00: 74 65 33 5f 76 66 73 20 2a 61 2c 20 63 6f 6e 73  te3_vfs *a, cons
5e10: 74 20 63 68 61 72 20 2a 62 2c 20 69 6e 74 20 63  t char *b, int c
5e20: 2c 20 63 68 61 72 20 2a 64 29 7b 0a 20 20 72 65  , char *d){.  re
5e30: 74 75 72 6e 20 67 4d 75 6c 74 69 70 6c 65 78 2e  turn gMultiplex.
5e40: 70 4f 72 69 67 56 66 73 2d 3e 78 46 75 6c 6c 50  pOrigVfs->xFullP
5e50: 61 74 68 6e 61 6d 65 28 67 4d 75 6c 74 69 70 6c  athname(gMultipl
5e60: 65 78 2e 70 4f 72 69 67 56 66 73 2c 20 62 2c 20  ex.pOrigVfs, b, 
5e70: 63 2c 20 64 29 3b 0a 7d 0a 73 74 61 74 69 63 20  c, d);.}.static 
5e80: 76 6f 69 64 20 2a 6d 75 6c 74 69 70 6c 65 78 44  void *multiplexD
5e90: 6c 4f 70 65 6e 28 73 71 6c 69 74 65 33 5f 76 66  lOpen(sqlite3_vf
5ea0: 73 20 2a 61 2c 20 63 6f 6e 73 74 20 63 68 61 72  s *a, const char
5eb0: 20 2a 62 29 7b 0a 20 20 72 65 74 75 72 6e 20 67   *b){.  return g
5ec0: 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56  Multiplex.pOrigV
5ed0: 66 73 2d 3e 78 44 6c 4f 70 65 6e 28 67 4d 75 6c  fs->xDlOpen(gMul
5ee0: 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2c  tiplex.pOrigVfs,
5ef0: 20 62 29 3b 0a 7d 0a 73 74 61 74 69 63 20 76 6f   b);.}.static vo
5f00: 69 64 20 6d 75 6c 74 69 70 6c 65 78 44 6c 45 72  id multiplexDlEr
5f10: 72 6f 72 28 73 71 6c 69 74 65 33 5f 76 66 73 20  ror(sqlite3_vfs 
5f20: 2a 61 2c 20 69 6e 74 20 62 2c 20 63 68 61 72 20  *a, int b, char 
5f30: 2a 63 29 7b 0a 20 20 67 4d 75 6c 74 69 70 6c 65  *c){.  gMultiple
5f40: 78 2e 70 4f 72 69 67 56 66 73 2d 3e 78 44 6c 45  x.pOrigVfs->xDlE
5f50: 72 72 6f 72 28 67 4d 75 6c 74 69 70 6c 65 78 2e  rror(gMultiplex.
5f60: 70 4f 72 69 67 56 66 73 2c 20 62 2c 20 63 29 3b  pOrigVfs, b, c);
5f70: 0a 7d 0a 73 74 61 74 69 63 20 76 6f 69 64 20 28  .}.static void (
5f80: 2a 6d 75 6c 74 69 70 6c 65 78 44 6c 53 79 6d 28  *multiplexDlSym(
5f90: 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 61 2c 20  sqlite3_vfs *a, 
5fa0: 76 6f 69 64 20 2a 62 2c 20 63 6f 6e 73 74 20 63  void *b, const c
5fb0: 68 61 72 20 2a 63 29 29 28 76 6f 69 64 29 7b 0a  har *c))(void){.
5fc0: 20 20 72 65 74 75 72 6e 20 67 4d 75 6c 74 69 70    return gMultip
5fd0: 6c 65 78 2e 70 4f 72 69 67 56 66 73 2d 3e 78 44  lex.pOrigVfs->xD
5fe0: 6c 53 79 6d 28 67 4d 75 6c 74 69 70 6c 65 78 2e  lSym(gMultiplex.
5ff0: 70 4f 72 69 67 56 66 73 2c 20 62 2c 20 63 29 3b  pOrigVfs, b, c);
6000: 0a 7d 0a 73 74 61 74 69 63 20 76 6f 69 64 20 6d  .}.static void m
6010: 75 6c 74 69 70 6c 65 78 44 6c 43 6c 6f 73 65 28  ultiplexDlClose(
6020: 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 61 2c 20  sqlite3_vfs *a, 
6030: 76 6f 69 64 20 2a 62 29 7b 0a 20 20 67 4d 75 6c  void *b){.  gMul
6040: 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2d  tiplex.pOrigVfs-
6050: 3e 78 44 6c 43 6c 6f 73 65 28 67 4d 75 6c 74 69  >xDlClose(gMulti
6060: 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2c 20 62  plex.pOrigVfs, b
6070: 29 3b 0a 7d 0a 73 74 61 74 69 63 20 69 6e 74 20  );.}.static int 
6080: 6d 75 6c 74 69 70 6c 65 78 52 61 6e 64 6f 6d 6e  multiplexRandomn
6090: 65 73 73 28 73 71 6c 69 74 65 33 5f 76 66 73 20  ess(sqlite3_vfs 
60a0: 2a 61 2c 20 69 6e 74 20 62 2c 20 63 68 61 72 20  *a, int b, char 
60b0: 2a 63 29 7b 0a 20 20 72 65 74 75 72 6e 20 67 4d  *c){.  return gM
60c0: 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66  ultiplex.pOrigVf
60d0: 73 2d 3e 78 52 61 6e 64 6f 6d 6e 65 73 73 28 67  s->xRandomness(g
60e0: 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56  Multiplex.pOrigV
60f0: 66 73 2c 20 62 2c 20 63 29 3b 0a 7d 0a 73 74 61  fs, b, c);.}.sta
6100: 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65  tic int multiple
6110: 78 53 6c 65 65 70 28 73 71 6c 69 74 65 33 5f 76  xSleep(sqlite3_v
6120: 66 73 20 2a 61 2c 20 69 6e 74 20 62 29 7b 0a 20  fs *a, int b){. 
6130: 20 72 65 74 75 72 6e 20 67 4d 75 6c 74 69 70 6c   return gMultipl
6140: 65 78 2e 70 4f 72 69 67 56 66 73 2d 3e 78 53 6c  ex.pOrigVfs->xSl
6150: 65 65 70 28 67 4d 75 6c 74 69 70 6c 65 78 2e 70  eep(gMultiplex.p
6160: 4f 72 69 67 56 66 73 2c 20 62 29 3b 0a 7d 0a 73  OrigVfs, b);.}.s
6170: 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70  tatic int multip
6180: 6c 65 78 43 75 72 72 65 6e 74 54 69 6d 65 28 73  lexCurrentTime(s
6190: 71 6c 69 74 65 33 5f 76 66 73 20 2a 61 2c 20 64  qlite3_vfs *a, d
61a0: 6f 75 62 6c 65 20 2a 62 29 7b 0a 20 20 72 65 74  ouble *b){.  ret
61b0: 75 72 6e 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70  urn gMultiplex.p
61c0: 4f 72 69 67 56 66 73 2d 3e 78 43 75 72 72 65 6e  OrigVfs->xCurren
61d0: 74 54 69 6d 65 28 67 4d 75 6c 74 69 70 6c 65 78  tTime(gMultiplex
61e0: 2e 70 4f 72 69 67 56 66 73 2c 20 62 29 3b 0a 7d  .pOrigVfs, b);.}
61f0: 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74  .static int mult
6200: 69 70 6c 65 78 47 65 74 4c 61 73 74 45 72 72 6f  iplexGetLastErro
6210: 72 28 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 61  r(sqlite3_vfs *a
6220: 2c 20 69 6e 74 20 62 2c 20 63 68 61 72 20 2a 63  , int b, char *c
6230: 29 7b 0a 20 20 72 65 74 75 72 6e 20 67 4d 75 6c  ){.  return gMul
6240: 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2d  tiplex.pOrigVfs-
6250: 3e 78 47 65 74 4c 61 73 74 45 72 72 6f 72 28 67  >xGetLastError(g
6260: 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56  Multiplex.pOrigV
6270: 66 73 2c 20 62 2c 20 63 29 3b 0a 7d 0a 73 74 61  fs, b, c);.}.sta
6280: 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65  tic int multiple
6290: 78 43 75 72 72 65 6e 74 54 69 6d 65 49 6e 74 36  xCurrentTimeInt6
62a0: 34 28 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 61  4(sqlite3_vfs *a
62b0: 2c 20 73 71 6c 69 74 65 33 5f 69 6e 74 36 34 20  , sqlite3_int64 
62c0: 2a 62 29 7b 0a 20 20 72 65 74 75 72 6e 20 67 4d  *b){.  return gM
62d0: 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66  ultiplex.pOrigVf
62e0: 73 2d 3e 78 43 75 72 72 65 6e 74 54 69 6d 65 49  s->xCurrentTimeI
62f0: 6e 74 36 34 28 67 4d 75 6c 74 69 70 6c 65 78 2e  nt64(gMultiplex.
6300: 70 4f 72 69 67 56 66 73 2c 20 62 29 3b 0a 7d 0a  pOrigVfs, b);.}.
6310: 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ./**************
6320: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20 49 2f 4f 20 4d  ********** I/O M
6330: 65 74 68 6f 64 20 57 72 61 70 70 65 72 73 20 2a  ethod Wrappers *
6340: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
6350: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2f 0a  **************/.
6360: 0a 2f 2a 20 78 43 6c 6f 73 65 20 72 65 71 75 65  ./* xClose reque
6370: 73 74 73 20 67 65 74 20 70 61 73 73 65 64 20 74  sts get passed t
6380: 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20 6f 72  hrough to the or
6390: 69 67 69 6e 61 6c 20 56 46 53 2e 0a 2a 2a 20 57  iginal VFS..** W
63a0: 65 20 6c 6f 6f 70 20 6f 76 65 72 20 61 6c 6c 20  e loop over all 
63b0: 6f 70 65 6e 20 63 68 75 6e 6b 20 68 61 6e 64 6c  open chunk handl
63c0: 65 73 20 61 6e 64 20 63 6c 6f 73 65 20 74 68 65  es and close the
63d0: 6d 2e 0a 2a 2a 20 54 68 65 20 67 72 6f 75 70 20  m..** The group 
63e0: 73 74 72 75 63 74 75 72 65 20 66 6f 72 20 74 68  structure for th
63f0: 69 73 20 66 69 6c 65 20 69 73 20 75 6e 6c 69 6e  is file is unlin
6400: 6b 65 64 20 66 72 6f 6d 20 0a 2a 2a 20 6f 75 72  ked from .** our
6410: 20 6c 69 73 74 20 6f 66 20 67 72 6f 75 70 73 20   list of groups 
6420: 61 6e 64 20 66 72 65 65 64 2e 0a 2a 2f 0a 73 74  and freed..*/.st
6430: 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c  atic int multipl
6440: 65 78 43 6c 6f 73 65 28 73 71 6c 69 74 65 33 5f  exClose(sqlite3_
6450: 66 69 6c 65 20 2a 70 43 6f 6e 6e 29 7b 0a 20 20  file *pConn){.  
6460: 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70  multiplexConn *p
6470: 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e   = (multiplexCon
6480: 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 6d 75 6c 74  n*)pConn;.  mult
6490: 69 70 6c 65 78 47 72 6f 75 70 20 2a 70 47 72 6f  iplexGroup *pGro
64a0: 75 70 20 3d 20 70 2d 3e 70 47 72 6f 75 70 3b 0a  up = p->pGroup;.
64b0: 20 20 69 6e 74 20 72 63 20 3d 20 53 51 4c 49 54    int rc = SQLIT
64c0: 45 5f 4f 4b 3b 0a 20 20 6d 75 6c 74 69 70 6c 65  E_OK;.  multiple
64d0: 78 45 6e 74 65 72 28 29 3b 0a 20 20 6d 75 6c 74  xEnter();.  mult
64e0: 69 70 6c 65 78 46 72 65 65 43 6f 6d 70 6f 6e 65  iplexFreeCompone
64f0: 6e 74 73 28 70 47 72 6f 75 70 29 3b 0a 20 20 2f  nts(pGroup);.  /
6500: 2a 20 72 65 6d 6f 76 65 20 66 72 6f 6d 20 6c 69  * remove from li
6510: 6e 6b 65 64 20 6c 69 73 74 20 2a 2f 0a 20 20 69  nked list */.  i
6520: 66 28 20 70 47 72 6f 75 70 2d 3e 70 4e 65 78 74  f( pGroup->pNext
6530: 20 29 20 70 47 72 6f 75 70 2d 3e 70 4e 65 78 74   ) pGroup->pNext
6540: 2d 3e 70 50 72 65 76 20 3d 20 70 47 72 6f 75 70  ->pPrev = pGroup
6550: 2d 3e 70 50 72 65 76 3b 0a 20 20 69 66 28 20 70  ->pPrev;.  if( p
6560: 47 72 6f 75 70 2d 3e 70 50 72 65 76 20 29 7b 0a  Group->pPrev ){.
6570: 20 20 20 20 70 47 72 6f 75 70 2d 3e 70 50 72 65      pGroup->pPre
6580: 76 2d 3e 70 4e 65 78 74 20 3d 20 70 47 72 6f 75  v->pNext = pGrou
6590: 70 2d 3e 70 4e 65 78 74 3b 0a 20 20 7d 65 6c 73  p->pNext;.  }els
65a0: 65 7b 0a 20 20 20 20 67 4d 75 6c 74 69 70 6c 65  e{.    gMultiple
65b0: 78 2e 70 47 72 6f 75 70 73 20 3d 20 70 47 72 6f  x.pGroups = pGro
65c0: 75 70 2d 3e 70 4e 65 78 74 3b 0a 20 20 7d 0a 20  up->pNext;.  }. 
65d0: 20 73 71 6c 69 74 65 33 5f 66 72 65 65 28 70 47   sqlite3_free(pG
65e0: 72 6f 75 70 29 3b 0a 20 20 6d 75 6c 74 69 70 6c  roup);.  multipl
65f0: 65 78 4c 65 61 76 65 28 29 3b 0a 20 20 72 65 74  exLeave();.  ret
6600: 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 20 50 61  urn rc;.}../* Pa
6610: 73 73 20 78 52 65 61 64 20 72 65 71 75 65 73 74  ss xRead request
6620: 73 20 74 68 72 75 20 74 6f 20 74 68 65 20 6f 72  s thru to the or
6630: 69 67 69 6e 61 6c 20 56 46 53 20 61 66 74 65 72  iginal VFS after
6640: 0a 2a 2a 20 64 65 74 65 72 6d 69 6e 69 6e 67 20  .** determining 
6650: 74 68 65 20 63 6f 72 72 65 63 74 20 63 68 75 6e  the correct chun
6660: 6b 20 74 6f 20 6f 70 65 72 61 74 65 20 6f 6e 2e  k to operate on.
6670: 0a 2a 2a 20 42 72 65 61 6b 20 75 70 20 72 65 61  .** Break up rea
6680: 64 73 20 61 63 72 6f 73 73 20 63 68 75 6e 6b 20  ds across chunk 
6690: 62 6f 75 6e 64 61 72 69 65 73 2e 0a 2a 2f 0a 73  boundaries..*/.s
66a0: 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70  tatic int multip
66b0: 6c 65 78 52 65 61 64 28 0a 20 20 73 71 6c 69 74  lexRead(.  sqlit
66c0: 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c 0a  e3_file *pConn,.
66d0: 20 20 76 6f 69 64 20 2a 70 42 75 66 2c 0a 20 20    void *pBuf,.  
66e0: 69 6e 74 20 69 41 6d 74 2c 0a 20 20 73 71 6c 69  int iAmt,.  sqli
66f0: 74 65 33 5f 69 6e 74 36 34 20 69 4f 66 73 74 0a  te3_int64 iOfst.
6700: 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f  ){.  multiplexCo
6710: 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c  nn *p = (multipl
6720: 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20  exConn*)pConn;. 
6730: 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 20   multiplexGroup 
6740: 2a 70 47 72 6f 75 70 20 3d 20 70 2d 3e 70 47 72  *pGroup = p->pGr
6750: 6f 75 70 3b 0a 20 20 69 6e 74 20 72 63 20 3d 20  oup;.  int rc = 
6760: 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 69 6e 74  SQLITE_OK;.  int
6770: 20 6e 4d 75 74 65 78 20 3d 20 30 3b 0a 20 20 6d   nMutex = 0;.  m
6780: 75 6c 74 69 70 6c 65 78 45 6e 74 65 72 28 29 3b  ultiplexEnter();
6790: 20 6e 4d 75 74 65 78 2b 2b 3b 0a 20 20 69 66 28   nMutex++;.  if(
67a0: 20 21 70 47 72 6f 75 70 2d 3e 62 45 6e 61 62 6c   !pGroup->bEnabl
67b0: 65 64 20 29 7b 0a 20 20 20 20 73 71 6c 69 74 65  ed ){.    sqlite
67c0: 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e  3_file *pSubOpen
67d0: 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f   = multiplexSubO
67e0: 70 65 6e 28 70 47 72 6f 75 70 2c 20 30 2c 20 26  pen(pGroup, 0, &
67f0: 72 63 2c 20 4e 55 4c 4c 2c 20 30 29 3b 0a 20 20  rc, NULL, 0);.  
6800: 20 20 6d 75 6c 74 69 70 6c 65 78 4c 65 61 76 65    multiplexLeave
6810: 28 29 3b 20 6e 4d 75 74 65 78 2d 2d 3b 0a 20 20  (); nMutex--;.  
6820: 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e 3d 3d    if( pSubOpen==
6830: 30 20 29 7b 0a 20 20 20 20 20 20 72 63 20 3d 20  0 ){.      rc = 
6840: 53 51 4c 49 54 45 5f 49 4f 45 52 52 5f 52 45 41  SQLITE_IOERR_REA
6850: 44 3b 0a 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20  D;.    }else{.  
6860: 20 20 20 20 72 63 20 3d 20 70 53 75 62 4f 70 65      rc = pSubOpe
6870: 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e 78 52 65  n->pMethods->xRe
6880: 61 64 28 70 53 75 62 4f 70 65 6e 2c 20 70 42 75  ad(pSubOpen, pBu
6890: 66 2c 20 69 41 6d 74 2c 20 69 4f 66 73 74 29 3b  f, iAmt, iOfst);
68a0: 0a 20 20 20 20 7d 0a 20 20 7d 65 6c 73 65 7b 0a  .    }.  }else{.
68b0: 20 20 20 20 77 68 69 6c 65 28 20 69 41 6d 74 20      while( iAmt 
68c0: 3e 20 30 20 29 7b 0a 20 20 20 20 20 20 69 6e 74  > 0 ){.      int
68d0: 20 69 20 3d 20 28 69 6e 74 29 28 69 4f 66 73 74   i = (int)(iOfst
68e0: 20 2f 20 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75   / pGroup->szChu
68f0: 6e 6b 29 3b 0a 20 20 20 20 20 20 73 71 6c 69 74  nk);.      sqlit
6900: 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70 65  e3_file *pSubOpe
6910: 6e 3b 0a 20 20 20 20 20 20 69 66 28 20 6e 4d 75  n;.      if( nMu
6920: 74 65 78 3d 3d 30 20 29 7b 20 6d 75 6c 74 69 70  tex==0 ){ multip
6930: 6c 65 78 45 6e 74 65 72 28 29 3b 20 6e 4d 75 74  lexEnter(); nMut
6940: 65 78 2b 2b 3b 20 7d 0a 20 20 20 20 20 20 70 53  ex++; }.      pS
6950: 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c  ubOpen = multipl
6960: 65 78 53 75 62 4f 70 65 6e 28 70 47 72 6f 75 70  exSubOpen(pGroup
6970: 2c 20 69 2c 20 26 72 63 2c 20 4e 55 4c 4c 2c 20  , i, &rc, NULL, 
6980: 31 29 3b 0a 20 20 20 20 20 20 6d 75 6c 74 69 70  1);.      multip
6990: 6c 65 78 4c 65 61 76 65 28 29 3b 20 6e 4d 75 74  lexLeave(); nMut
69a0: 65 78 2d 2d 3b 0a 20 20 20 20 20 20 69 66 28 20  ex--;.      if( 
69b0: 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20  pSubOpen ){.    
69c0: 20 20 20 20 69 6e 74 20 65 78 74 72 61 20 3d 20      int extra = 
69d0: 28 28 69 6e 74 29 28 69 4f 66 73 74 20 25 20 70  ((int)(iOfst % p
69e0: 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 29 20  Group->szChunk) 
69f0: 2b 20 69 41 6d 74 29 20 2d 20 70 47 72 6f 75 70  + iAmt) - pGroup
6a00: 2d 3e 73 7a 43 68 75 6e 6b 3b 0a 20 20 20 20 20  ->szChunk;.     
6a10: 20 20 20 69 66 28 20 65 78 74 72 61 3c 30 20 29     if( extra<0 )
6a20: 20 65 78 74 72 61 20 3d 20 30 3b 0a 20 20 20 20   extra = 0;.    
6a30: 20 20 20 20 69 41 6d 74 20 2d 3d 20 65 78 74 72      iAmt -= extr
6a40: 61 3b 0a 20 20 20 20 20 20 20 20 72 63 20 3d 20  a;.        rc = 
6a50: 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f  pSubOpen->pMetho
6a60: 64 73 2d 3e 78 52 65 61 64 28 70 53 75 62 4f 70  ds->xRead(pSubOp
6a70: 65 6e 2c 20 70 42 75 66 2c 20 69 41 6d 74 2c 0a  en, pBuf, iAmt,.
6a80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6a90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6aa0: 20 20 20 20 20 20 20 69 4f 66 73 74 20 25 20 70         iOfst % p
6ab0: 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 29 3b  Group->szChunk);
6ac0: 0a 20 20 20 20 20 20 20 20 69 66 28 20 72 63 21  .        if( rc!
6ad0: 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 20 62 72 65  =SQLITE_OK ) bre
6ae0: 61 6b 3b 0a 20 20 20 20 20 20 20 20 70 42 75 66  ak;.        pBuf
6af0: 20 3d 20 28 63 68 61 72 20 2a 29 70 42 75 66 20   = (char *)pBuf 
6b00: 2b 20 69 41 6d 74 3b 0a 20 20 20 20 20 20 20 20  + iAmt;.        
6b10: 69 4f 66 73 74 20 2b 3d 20 69 41 6d 74 3b 0a 20  iOfst += iAmt;. 
6b20: 20 20 20 20 20 20 20 69 41 6d 74 20 3d 20 65 78         iAmt = ex
6b30: 74 72 61 3b 0a 20 20 20 20 20 20 7d 65 6c 73 65  tra;.      }else
6b40: 7b 0a 20 20 20 20 20 20 20 20 72 63 20 3d 20 53  {.        rc = S
6b50: 51 4c 49 54 45 5f 49 4f 45 52 52 5f 52 45 41 44  QLITE_IOERR_READ
6b60: 3b 0a 20 20 20 20 20 20 20 20 62 72 65 61 6b 3b  ;.        break;
6b70: 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a 20  .      }.    }. 
6b80: 20 7d 0a 20 20 61 73 73 65 72 74 28 20 6e 4d 75   }.  assert( nMu
6b90: 74 65 78 3d 3d 30 20 7c 7c 20 6e 4d 75 74 65 78  tex==0 || nMutex
6ba0: 3d 3d 31 20 29 3b 0a 20 20 69 66 28 20 6e 4d 75  ==1 );.  if( nMu
6bb0: 74 65 78 20 29 20 6d 75 6c 74 69 70 6c 65 78 4c  tex ) multiplexL
6bc0: 65 61 76 65 28 29 3b 0a 20 20 72 65 74 75 72 6e  eave();.  return
6bd0: 20 72 63 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20   rc;.}../* Pass 
6be0: 78 57 72 69 74 65 20 72 65 71 75 65 73 74 73 20  xWrite requests 
6bf0: 74 68 72 75 20 74 6f 20 74 68 65 20 6f 72 69 67  thru to the orig
6c00: 69 6e 61 6c 20 56 46 53 20 61 66 74 65 72 0a 2a  inal VFS after.*
6c10: 2a 20 64 65 74 65 72 6d 69 6e 69 6e 67 20 74 68  * determining th
6c20: 65 20 63 6f 72 72 65 63 74 20 63 68 75 6e 6b 20  e correct chunk 
6c30: 74 6f 20 6f 70 65 72 61 74 65 20 6f 6e 2e 0a 2a  to operate on..*
6c40: 2a 20 42 72 65 61 6b 20 75 70 20 77 72 69 74 65  * Break up write
6c50: 73 20 61 63 72 6f 73 73 20 63 68 75 6e 6b 20 62  s across chunk b
6c60: 6f 75 6e 64 61 72 69 65 73 2e 0a 2a 2f 0a 73 74  oundaries..*/.st
6c70: 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c  atic int multipl
6c80: 65 78 57 72 69 74 65 28 0a 20 20 73 71 6c 69 74  exWrite(.  sqlit
6c90: 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c 0a  e3_file *pConn,.
6ca0: 20 20 63 6f 6e 73 74 20 76 6f 69 64 20 2a 70 42    const void *pB
6cb0: 75 66 2c 0a 20 20 69 6e 74 20 69 41 6d 74 2c 0a  uf,.  int iAmt,.
6cc0: 20 20 73 71 6c 69 74 65 33 5f 69 6e 74 36 34 20    sqlite3_int64 
6cd0: 69 4f 66 73 74 0a 29 7b 0a 20 20 6d 75 6c 74 69  iOfst.){.  multi
6ce0: 70 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d  plexConn *p = (m
6cf0: 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43  ultiplexConn*)pC
6d00: 6f 6e 6e 3b 0a 20 20 6d 75 6c 74 69 70 6c 65 78  onn;.  multiplex
6d10: 47 72 6f 75 70 20 2a 70 47 72 6f 75 70 20 3d 20  Group *pGroup = 
6d20: 70 2d 3e 70 47 72 6f 75 70 3b 0a 20 20 69 6e 74  p->pGroup;.  int
6d30: 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b   rc = SQLITE_OK;
6d40: 0a 20 20 6d 75 6c 74 69 70 6c 65 78 45 6e 74 65  .  multiplexEnte
6d50: 72 28 29 3b 0a 20 20 69 66 28 20 21 70 47 72 6f  r();.  if( !pGro
6d60: 75 70 2d 3e 62 45 6e 61 62 6c 65 64 20 29 7b 0a  up->bEnabled ){.
6d70: 20 20 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65      sqlite3_file
6d80: 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c   *pSubOpen = mul
6d90: 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28 70 47  tiplexSubOpen(pG
6da0: 72 6f 75 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55  roup, 0, &rc, NU
6db0: 4c 4c 2c 20 30 29 3b 0a 20 20 20 20 69 66 28 20  LL, 0);.    if( 
6dc0: 70 53 75 62 4f 70 65 6e 3d 3d 30 20 29 7b 0a 20  pSubOpen==0 ){. 
6dd0: 20 20 20 20 20 72 63 20 3d 20 53 51 4c 49 54 45       rc = SQLITE
6de0: 5f 49 4f 45 52 52 5f 57 52 49 54 45 3b 0a 20 20  _IOERR_WRITE;.  
6df0: 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 72    }else{.      r
6e00: 63 20 3d 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d  c = pSubOpen->pM
6e10: 65 74 68 6f 64 73 2d 3e 78 57 72 69 74 65 28 70  ethods->xWrite(p
6e20: 53 75 62 4f 70 65 6e 2c 20 70 42 75 66 2c 20 69  SubOpen, pBuf, i
6e30: 41 6d 74 2c 20 69 4f 66 73 74 29 3b 0a 20 20 20  Amt, iOfst);.   
6e40: 20 7d 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20   }.  }else{.    
6e50: 77 68 69 6c 65 28 20 72 63 3d 3d 53 51 4c 49 54  while( rc==SQLIT
6e60: 45 5f 4f 4b 20 26 26 20 69 41 6d 74 3e 30 20 29  E_OK && iAmt>0 )
6e70: 7b 0a 20 20 20 20 20 20 69 6e 74 20 69 20 3d 20  {.      int i = 
6e80: 28 69 6e 74 29 28 69 4f 66 73 74 20 2f 20 70 47  (int)(iOfst / pG
6e90: 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 29 3b 0a  roup->szChunk);.
6ea0: 20 20 20 20 20 20 73 71 6c 69 74 65 33 5f 66 69        sqlite3_fi
6eb0: 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20 6d  le *pSubOpen = m
6ec0: 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28  ultiplexSubOpen(
6ed0: 70 47 72 6f 75 70 2c 20 69 2c 20 26 72 63 2c 20  pGroup, i, &rc, 
6ee0: 4e 55 4c 4c 2c 20 31 29 3b 0a 20 20 20 20 20 20  NULL, 1);.      
6ef0: 69 66 28 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a  if( pSubOpen ){.
6f00: 20 20 20 20 20 20 20 20 69 6e 74 20 65 78 74 72          int extr
6f10: 61 20 3d 20 28 28 69 6e 74 29 28 69 4f 66 73 74  a = ((int)(iOfst
6f20: 20 25 20 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75   % pGroup->szChu
6f30: 6e 6b 29 20 2b 20 69 41 6d 74 29 20 2d 0a 20 20  nk) + iAmt) -.  
6f40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6f50: 20 20 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e    pGroup->szChun
6f60: 6b 3b 0a 20 20 20 20 20 20 20 20 69 66 28 20 65  k;.        if( e
6f70: 78 74 72 61 3c 30 20 29 20 65 78 74 72 61 20 3d  xtra<0 ) extra =
6f80: 20 30 3b 0a 20 20 20 20 20 20 20 20 69 41 6d 74   0;.        iAmt
6f90: 20 2d 3d 20 65 78 74 72 61 3b 0a 20 20 20 20 20   -= extra;.     
6fa0: 20 20 20 72 63 20 3d 20 70 53 75 62 4f 70 65 6e     rc = pSubOpen
6fb0: 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e 78 57 72 69  ->pMethods->xWri
6fc0: 74 65 28 70 53 75 62 4f 70 65 6e 2c 20 70 42 75  te(pSubOpen, pBu
6fd0: 66 2c 20 69 41 6d 74 2c 0a 20 20 20 20 20 20 20  f, iAmt,.       
6fe0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6ff0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7000: 20 69 4f 66 73 74 20 25 20 70 47 72 6f 75 70 2d   iOfst % pGroup-
7010: 3e 73 7a 43 68 75 6e 6b 29 3b 0a 20 20 20 20 20  >szChunk);.     
7020: 20 20 20 70 42 75 66 20 3d 20 28 63 68 61 72 20     pBuf = (char 
7030: 2a 29 70 42 75 66 20 2b 20 69 41 6d 74 3b 0a 20  *)pBuf + iAmt;. 
7040: 20 20 20 20 20 20 20 69 4f 66 73 74 20 2b 3d 20         iOfst += 
7050: 69 41 6d 74 3b 0a 20 20 20 20 20 20 20 20 69 41  iAmt;.        iA
7060: 6d 74 20 3d 20 65 78 74 72 61 3b 0a 20 20 20 20  mt = extra;.    
7070: 20 20 7d 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20    }.    }.  }.  
7080: 6d 75 6c 74 69 70 6c 65 78 4c 65 61 76 65 28 29  multiplexLeave()
7090: 3b 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d  ;.  return rc;.}
70a0: 0a 0a 2f 2a 20 50 61 73 73 20 78 54 72 75 6e 63  ../* Pass xTrunc
70b0: 61 74 65 20 72 65 71 75 65 73 74 73 20 74 68 72  ate requests thr
70c0: 75 20 74 6f 20 74 68 65 20 6f 72 69 67 69 6e 61  u to the origina
70d0: 6c 20 56 46 53 20 61 66 74 65 72 0a 2a 2a 20 64  l VFS after.** d
70e0: 65 74 65 72 6d 69 6e 69 6e 67 20 74 68 65 20 63  etermining the c
70f0: 6f 72 72 65 63 74 20 63 68 75 6e 6b 20 74 6f 20  orrect chunk to 
7100: 6f 70 65 72 61 74 65 20 6f 6e 2e 20 20 44 65 6c  operate on.  Del
7110: 65 74 65 20 61 6e 79 0a 2a 2a 20 63 68 75 6e 6b  ete any.** chunk
7120: 73 20 61 62 6f 76 65 20 74 68 65 20 74 72 75 6e  s above the trun
7130: 63 61 74 65 20 6d 61 72 6b 2e 0a 2a 2f 0a 73 74  cate mark..*/.st
7140: 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c  atic int multipl
7150: 65 78 54 72 75 6e 63 61 74 65 28 73 71 6c 69 74  exTruncate(sqlit
7160: 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c 20  e3_file *pConn, 
7170: 73 71 6c 69 74 65 33 5f 69 6e 74 36 34 20 73 69  sqlite3_int64 si
7180: 7a 65 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78  ze){.  multiplex
7190: 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69  Conn *p = (multi
71a0: 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b  plexConn*)pConn;
71b0: 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75  .  multiplexGrou
71c0: 70 20 2a 70 47 72 6f 75 70 20 3d 20 70 2d 3e 70  p *pGroup = p->p
71d0: 47 72 6f 75 70 3b 0a 20 20 69 6e 74 20 72 63 20  Group;.  int rc 
71e0: 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 6d  = SQLITE_OK;.  m
71f0: 75 6c 74 69 70 6c 65 78 45 6e 74 65 72 28 29 3b  ultiplexEnter();
7200: 0a 20 20 69 66 28 20 21 70 47 72 6f 75 70 2d 3e  .  if( !pGroup->
7210: 62 45 6e 61 62 6c 65 64 20 29 7b 0a 20 20 20 20  bEnabled ){.    
7220: 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53  sqlite3_file *pS
7230: 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c  ubOpen = multipl
7240: 65 78 53 75 62 4f 70 65 6e 28 70 47 72 6f 75 70  exSubOpen(pGroup
7250: 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 2c 20  , 0, &rc, NULL, 
7260: 30 29 3b 0a 20 20 20 20 69 66 28 20 70 53 75 62  0);.    if( pSub
7270: 4f 70 65 6e 3d 3d 30 20 29 7b 0a 20 20 20 20 20  Open==0 ){.     
7280: 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 49 4f 45   rc = SQLITE_IOE
7290: 52 52 5f 54 52 55 4e 43 41 54 45 3b 0a 20 20 20  RR_TRUNCATE;.   
72a0: 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 72 63   }else{.      rc
72b0: 20 3d 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65   = pSubOpen->pMe
72c0: 74 68 6f 64 73 2d 3e 78 54 72 75 6e 63 61 74 65  thods->xTruncate
72d0: 28 70 53 75 62 4f 70 65 6e 2c 20 73 69 7a 65 29  (pSubOpen, size)
72e0: 3b 0a 20 20 20 20 7d 0a 20 20 7d 65 6c 73 65 7b  ;.    }.  }else{
72f0: 0a 20 20 20 20 69 6e 74 20 69 3b 0a 20 20 20 20  .    int i;.    
7300: 69 6e 74 20 69 42 61 73 65 47 72 6f 75 70 20 3d  int iBaseGroup =
7310: 20 28 69 6e 74 29 28 73 69 7a 65 20 2f 20 70 47   (int)(size / pG
7320: 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 29 3b 0a  roup->szChunk);.
7330: 20 20 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65      sqlite3_file
7340: 20 2a 70 53 75 62 4f 70 65 6e 3b 0a 20 20 20 20   *pSubOpen;.    
7350: 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 70 4f 72  sqlite3_vfs *pOr
7360: 69 67 56 66 73 20 3d 20 67 4d 75 6c 74 69 70 6c  igVfs = gMultipl
7370: 65 78 2e 70 4f 72 69 67 56 66 73 3b 20 20 20 2f  ex.pOrigVfs;   /
7380: 2a 20 52 65 61 6c 20 56 46 53 20 2a 2f 0a 20 20  * Real VFS */.  
7390: 20 20 2f 2a 20 64 65 6c 65 74 65 20 74 68 65 20    /* delete the 
73a0: 63 68 75 6e 6b 73 20 61 62 6f 76 65 20 74 68 65  chunks above the
73b0: 20 74 72 75 6e 63 61 74 65 20 6c 69 6d 69 74 20   truncate limit 
73c0: 2a 2f 0a 20 20 20 20 66 6f 72 28 69 20 3d 20 70  */.    for(i = p
73d0: 47 72 6f 75 70 2d 3e 6e 52 65 61 6c 2d 31 3b 20  Group->nReal-1; 
73e0: 69 3e 69 42 61 73 65 47 72 6f 75 70 20 26 26 20  i>iBaseGroup && 
73f0: 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 3b 20 69  rc==SQLITE_OK; i
7400: 2d 2d 29 7b 0a 20 20 20 20 20 20 69 66 28 20 70  --){.      if( p
7410: 47 72 6f 75 70 2d 3e 62 54 72 75 6e 63 61 74 65  Group->bTruncate
7420: 20 29 7b 0a 20 20 20 20 20 20 20 20 6d 75 6c 74   ){.        mult
7430: 69 70 6c 65 78 53 75 62 43 6c 6f 73 65 28 70 47  iplexSubClose(pG
7440: 72 6f 75 70 2c 20 69 2c 20 70 4f 72 69 67 56 66  roup, i, pOrigVf
7450: 73 29 3b 0a 20 20 20 20 20 20 7d 65 6c 73 65 7b  s);.      }else{
7460: 0a 20 20 20 20 20 20 20 20 70 53 75 62 4f 70 65  .        pSubOpe
7470: 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75 62  n = multiplexSub
7480: 4f 70 65 6e 28 70 47 72 6f 75 70 2c 20 69 2c 20  Open(pGroup, i, 
7490: 26 72 63 2c 20 30 2c 20 30 29 3b 0a 20 20 20 20  &rc, 0, 0);.    
74a0: 20 20 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e      if( pSubOpen
74b0: 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20 72 63   ){.          rc
74c0: 20 3d 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65   = pSubOpen->pMe
74d0: 74 68 6f 64 73 2d 3e 78 54 72 75 6e 63 61 74 65  thods->xTruncate
74e0: 28 70 53 75 62 4f 70 65 6e 2c 20 30 29 3b 0a 20  (pSubOpen, 0);. 
74f0: 20 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 7d         }.      }
7500: 0a 20 20 20 20 7d 0a 20 20 20 20 69 66 28 20 72  .    }.    if( r
7510: 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a  c==SQLITE_OK ){.
7520: 20 20 20 20 20 20 70 53 75 62 4f 70 65 6e 20 3d        pSubOpen =
7530: 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65   multiplexSubOpe
7540: 6e 28 70 47 72 6f 75 70 2c 20 69 42 61 73 65 47  n(pGroup, iBaseG
7550: 72 6f 75 70 2c 20 26 72 63 2c 20 30 2c 20 30 29  roup, &rc, 0, 0)
7560: 3b 0a 20 20 20 20 20 20 69 66 28 20 70 53 75 62  ;.      if( pSub
7570: 4f 70 65 6e 20 29 7b 0a 20 20 20 20 20 20 20 20  Open ){.        
7580: 72 63 20 3d 20 70 53 75 62 4f 70 65 6e 2d 3e 70  rc = pSubOpen->p
7590: 4d 65 74 68 6f 64 73 2d 3e 78 54 72 75 6e 63 61  Methods->xTrunca
75a0: 74 65 28 70 53 75 62 4f 70 65 6e 2c 20 73 69 7a  te(pSubOpen, siz
75b0: 65 20 25 20 70 47 72 6f 75 70 2d 3e 73 7a 43 68  e % pGroup->szCh
75c0: 75 6e 6b 29 3b 0a 20 20 20 20 20 20 7d 0a 20 20  unk);.      }.  
75d0: 20 20 7d 0a 20 20 20 20 69 66 28 20 72 63 20 29    }.    if( rc )
75e0: 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 49 4f 45   rc = SQLITE_IOE
75f0: 52 52 5f 54 52 55 4e 43 41 54 45 3b 0a 20 20 7d  RR_TRUNCATE;.  }
7600: 0a 20 20 6d 75 6c 74 69 70 6c 65 78 4c 65 61 76  .  multiplexLeav
7610: 65 28 29 3b 0a 20 20 72 65 74 75 72 6e 20 72 63  e();.  return rc
7620: 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 53 79  ;.}../* Pass xSy
7630: 6e 63 20 72 65 71 75 65 73 74 73 20 74 68 72 6f  nc requests thro
7640: 75 67 68 20 74 6f 20 74 68 65 20 6f 72 69 67 69  ugh to the origi
7650: 6e 61 6c 20 56 46 53 20 77 69 74 68 6f 75 74 20  nal VFS without 
7660: 63 68 61 6e 67 65 0a 2a 2f 0a 73 74 61 74 69 63  change.*/.static
7670: 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 53 79   int multiplexSy
7680: 6e 63 28 73 71 6c 69 74 65 33 5f 66 69 6c 65 20  nc(sqlite3_file 
7690: 2a 70 43 6f 6e 6e 2c 20 69 6e 74 20 66 6c 61 67  *pConn, int flag
76a0: 73 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43  s){.  multiplexC
76b0: 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70  onn *p = (multip
76c0: 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a  lexConn*)pConn;.
76d0: 20 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70    multiplexGroup
76e0: 20 2a 70 47 72 6f 75 70 20 3d 20 70 2d 3e 70 47   *pGroup = p->pG
76f0: 72 6f 75 70 3b 0a 20 20 69 6e 74 20 72 63 20 3d  roup;.  int rc =
7700: 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 69 6e   SQLITE_OK;.  in
7710: 74 20 69 3b 0a 20 20 6d 75 6c 74 69 70 6c 65 78  t i;.  multiplex
7720: 45 6e 74 65 72 28 29 3b 0a 20 20 66 6f 72 28 69  Enter();.  for(i
7730: 3d 30 3b 20 69 3c 70 47 72 6f 75 70 2d 3e 6e 52  =0; i<pGroup->nR
7740: 65 61 6c 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 73  eal; i++){.    s
7750: 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75  qlite3_file *pSu
7760: 62 4f 70 65 6e 20 3d 20 70 47 72 6f 75 70 2d 3e  bOpen = pGroup->
7770: 61 52 65 61 6c 5b 69 5d 2e 70 3b 0a 20 20 20 20  aReal[i].p;.    
7780: 69 66 28 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a  if( pSubOpen ){.
7790: 20 20 20 20 20 20 69 6e 74 20 72 63 32 20 3d 20        int rc2 = 
77a0: 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f  pSubOpen->pMetho
77b0: 64 73 2d 3e 78 53 79 6e 63 28 70 53 75 62 4f 70  ds->xSync(pSubOp
77c0: 65 6e 2c 20 66 6c 61 67 73 29 3b 0a 20 20 20 20  en, flags);.    
77d0: 20 20 69 66 28 20 72 63 32 21 3d 53 51 4c 49 54    if( rc2!=SQLIT
77e0: 45 5f 4f 4b 20 29 20 72 63 20 3d 20 72 63 32 3b  E_OK ) rc = rc2;
77f0: 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20 6d 75 6c  .    }.  }.  mul
7800: 74 69 70 6c 65 78 4c 65 61 76 65 28 29 3b 0a 20  tiplexLeave();. 
7810: 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f   return rc;.}../
7820: 2a 20 50 61 73 73 20 78 46 69 6c 65 53 69 7a 65  * Pass xFileSize
7830: 20 72 65 71 75 65 73 74 73 20 74 68 72 6f 75 67   requests throug
7840: 68 20 74 6f 20 74 68 65 20 6f 72 69 67 69 6e 61  h to the origina
7850: 6c 20 56 46 53 2e 0a 2a 2a 20 41 67 67 72 65 67  l VFS..** Aggreg
7860: 61 74 65 20 74 68 65 20 73 69 7a 65 20 6f 66 20  ate the size of 
7870: 61 6c 6c 20 74 68 65 20 63 68 75 6e 6b 73 20 62  all the chunks b
7880: 65 66 6f 72 65 20 72 65 74 75 72 6e 69 6e 67 2e  efore returning.
7890: 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 6d  .*/.static int m
78a0: 75 6c 74 69 70 6c 65 78 46 69 6c 65 53 69 7a 65  ultiplexFileSize
78b0: 28 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70  (sqlite3_file *p
78c0: 43 6f 6e 6e 2c 20 73 71 6c 69 74 65 33 5f 69 6e  Conn, sqlite3_in
78d0: 74 36 34 20 2a 70 53 69 7a 65 29 7b 0a 20 20 6d  t64 *pSize){.  m
78e0: 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70 20  ultiplexConn *p 
78f0: 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e  = (multiplexConn
7900: 2a 29 70 43 6f 6e 6e 3b 0a 20 20 6d 75 6c 74 69  *)pConn;.  multi
7910: 70 6c 65 78 47 72 6f 75 70 20 2a 70 47 72 6f 75  plexGroup *pGrou
7920: 70 20 3d 20 70 2d 3e 70 47 72 6f 75 70 3b 0a 20  p = p->pGroup;. 
7930: 20 69 6e 74 20 72 63 20 3d 20 53 51 4c 49 54 45   int rc = SQLITE
7940: 5f 4f 4b 3b 0a 20 20 69 6e 74 20 69 3b 0a 20 20  _OK;.  int i;.  
7950: 6d 75 6c 74 69 70 6c 65 78 45 6e 74 65 72 28 29  multiplexEnter()
7960: 3b 0a 20 20 69 66 28 20 21 70 47 72 6f 75 70 2d  ;.  if( !pGroup-
7970: 3e 62 45 6e 61 62 6c 65 64 20 29 7b 0a 20 20 20  >bEnabled ){.   
7980: 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70   sqlite3_file *p
7990: 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70  SubOpen = multip
79a0: 6c 65 78 53 75 62 4f 70 65 6e 28 70 47 72 6f 75  lexSubOpen(pGrou
79b0: 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 2c  p, 0, &rc, NULL,
79c0: 20 30 29 3b 0a 20 20 20 20 69 66 28 20 70 53 75   0);.    if( pSu
79d0: 62 4f 70 65 6e 3d 3d 30 20 29 7b 0a 20 20 20 20  bOpen==0 ){.    
79e0: 20 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 49 4f    rc = SQLITE_IO
79f0: 45 52 52 5f 46 53 54 41 54 3b 0a 20 20 20 20 7d  ERR_FSTAT;.    }
7a00: 65 6c 73 65 7b 0a 20 20 20 20 20 20 72 63 20 3d  else{.      rc =
7a10: 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68   pSubOpen->pMeth
7a20: 6f 64 73 2d 3e 78 46 69 6c 65 53 69 7a 65 28 70  ods->xFileSize(p
7a30: 53 75 62 4f 70 65 6e 2c 20 70 53 69 7a 65 29 3b  SubOpen, pSize);
7a40: 0a 20 20 20 20 7d 0a 20 20 7d 65 6c 73 65 7b 0a  .    }.  }else{.
7a50: 20 20 20 20 2a 70 53 69 7a 65 20 3d 20 30 3b 0a      *pSize = 0;.
7a60: 20 20 20 20 66 6f 72 28 69 3d 30 3b 20 72 63 3d      for(i=0; rc=
7a70: 3d 53 51 4c 49 54 45 5f 4f 4b 3b 20 69 2b 2b 29  =SQLITE_OK; i++)
7a80: 7b 0a 20 20 20 20 20 20 73 71 6c 69 74 65 33 5f  {.      sqlite3_
7a90: 69 6e 74 36 34 20 73 7a 20 3d 20 6d 75 6c 74 69  int64 sz = multi
7aa0: 70 6c 65 78 53 75 62 53 69 7a 65 28 70 47 72 6f  plexSubSize(pGro
7ab0: 75 70 2c 20 69 2c 20 26 72 63 29 3b 0a 20 20 20  up, i, &rc);.   
7ac0: 20 20 20 69 66 28 20 73 7a 3d 3d 30 20 29 20 62     if( sz==0 ) b
7ad0: 72 65 61 6b 3b 0a 20 20 20 20 20 20 2a 70 53 69  reak;.      *pSi
7ae0: 7a 65 20 3d 20 69 2a 28 73 71 6c 69 74 65 33 5f  ze = i*(sqlite3_
7af0: 69 6e 74 36 34 29 70 47 72 6f 75 70 2d 3e 73 7a  int64)pGroup->sz
7b00: 43 68 75 6e 6b 20 2b 20 73 7a 3b 0a 20 20 20 20  Chunk + sz;.    
7b10: 7d 0a 20 20 7d 0a 20 20 6d 75 6c 74 69 70 6c 65  }.  }.  multiple
7b20: 78 4c 65 61 76 65 28 29 3b 0a 20 20 72 65 74 75  xLeave();.  retu
7b30: 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 20 50 61 73  rn rc;.}../* Pas
7b40: 73 20 78 4c 6f 63 6b 20 72 65 71 75 65 73 74 73  s xLock requests
7b50: 20 74 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20   through to the 
7b60: 6f 72 69 67 69 6e 61 6c 20 56 46 53 20 75 6e 63  original VFS unc
7b70: 68 61 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61 74 69  hanged..*/.stati
7b80: 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 4c  c int multiplexL
7b90: 6f 63 6b 28 73 71 6c 69 74 65 33 5f 66 69 6c 65  ock(sqlite3_file
7ba0: 20 2a 70 43 6f 6e 6e 2c 20 69 6e 74 20 6c 6f 63   *pConn, int loc
7bb0: 6b 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43  k){.  multiplexC
7bc0: 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70  onn *p = (multip
7bd0: 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a  lexConn*)pConn;.
7be0: 20 20 69 6e 74 20 72 63 3b 0a 20 20 73 71 6c 69    int rc;.  sqli
7bf0: 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70  te3_file *pSubOp
7c00: 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75  en = multiplexSu
7c10: 62 4f 70 65 6e 28 70 2d 3e 70 47 72 6f 75 70 2c  bOpen(p->pGroup,
7c20: 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 2c 20 30   0, &rc, NULL, 0
7c30: 29 3b 0a 20 20 69 66 28 20 70 53 75 62 4f 70 65  );.  if( pSubOpe
7c40: 6e 20 29 7b 0a 20 20 20 20 72 65 74 75 72 6e 20  n ){.    return 
7c50: 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f  pSubOpen->pMetho
7c60: 64 73 2d 3e 78 4c 6f 63 6b 28 70 53 75 62 4f 70  ds->xLock(pSubOp
7c70: 65 6e 2c 20 6c 6f 63 6b 29 3b 0a 20 20 7d 0a 20  en, lock);.  }. 
7c80: 20 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 42   return SQLITE_B
7c90: 55 53 59 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20  USY;.}../* Pass 
7ca0: 78 55 6e 6c 6f 63 6b 20 72 65 71 75 65 73 74 73  xUnlock requests
7cb0: 20 74 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20   through to the 
7cc0: 6f 72 69 67 69 6e 61 6c 20 56 46 53 20 75 6e 63  original VFS unc
7cd0: 68 61 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61 74 69  hanged..*/.stati
7ce0: 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 55  c int multiplexU
7cf0: 6e 6c 6f 63 6b 28 73 71 6c 69 74 65 33 5f 66 69  nlock(sqlite3_fi
7d00: 6c 65 20 2a 70 43 6f 6e 6e 2c 20 69 6e 74 20 6c  le *pConn, int l
7d10: 6f 63 6b 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65  ock){.  multiple
7d20: 78 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74  xConn *p = (mult
7d30: 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e  iplexConn*)pConn
7d40: 3b 0a 20 20 69 6e 74 20 72 63 3b 0a 20 20 73 71  ;.  int rc;.  sq
7d50: 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62  lite3_file *pSub
7d60: 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78  Open = multiplex
7d70: 53 75 62 4f 70 65 6e 28 70 2d 3e 70 47 72 6f 75  SubOpen(p->pGrou
7d80: 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 2c  p, 0, &rc, NULL,
7d90: 20 30 29 3b 0a 20 20 69 66 28 20 70 53 75 62 4f   0);.  if( pSubO
7da0: 70 65 6e 20 29 7b 0a 20 20 20 20 72 65 74 75 72  pen ){.    retur
7db0: 6e 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74  n pSubOpen->pMet
7dc0: 68 6f 64 73 2d 3e 78 55 6e 6c 6f 63 6b 28 70 53  hods->xUnlock(pS
7dd0: 75 62 4f 70 65 6e 2c 20 6c 6f 63 6b 29 3b 0a 20  ubOpen, lock);. 
7de0: 20 7d 0a 20 20 72 65 74 75 72 6e 20 53 51 4c 49   }.  return SQLI
7df0: 54 45 5f 49 4f 45 52 52 5f 55 4e 4c 4f 43 4b 3b  TE_IOERR_UNLOCK;
7e00: 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 43 68 65  .}../* Pass xChe
7e10: 63 6b 52 65 73 65 72 76 65 64 4c 6f 63 6b 20 72  ckReservedLock r
7e20: 65 71 75 65 73 74 73 20 74 68 72 6f 75 67 68 20  equests through 
7e30: 74 6f 20 74 68 65 20 6f 72 69 67 69 6e 61 6c 20  to the original 
7e40: 56 46 53 20 75 6e 63 68 61 6e 67 65 64 2e 0a 2a  VFS unchanged..*
7e50: 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c  /.static int mul
7e60: 74 69 70 6c 65 78 43 68 65 63 6b 52 65 73 65 72  tiplexCheckReser
7e70: 76 65 64 4c 6f 63 6b 28 73 71 6c 69 74 65 33 5f  vedLock(sqlite3_
7e80: 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c 20 69 6e 74  file *pConn, int
7e90: 20 2a 70 52 65 73 4f 75 74 29 7b 0a 20 20 6d 75   *pResOut){.  mu
7ea0: 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d  ltiplexConn *p =
7eb0: 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a   (multiplexConn*
7ec0: 29 70 43 6f 6e 6e 3b 0a 20 20 69 6e 74 20 72 63  )pConn;.  int rc
7ed0: 3b 0a 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65  ;.  sqlite3_file
7ee0: 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c   *pSubOpen = mul
7ef0: 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28 70 2d  tiplexSubOpen(p-
7f00: 3e 70 47 72 6f 75 70 2c 20 30 2c 20 26 72 63 2c  >pGroup, 0, &rc,
7f10: 20 4e 55 4c 4c 2c 20 30 29 3b 0a 20 20 69 66 28   NULL, 0);.  if(
7f20: 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20   pSubOpen ){.   
7f30: 20 72 65 74 75 72 6e 20 70 53 75 62 4f 70 65 6e   return pSubOpen
7f40: 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e 78 43 68 65  ->pMethods->xChe
7f50: 63 6b 52 65 73 65 72 76 65 64 4c 6f 63 6b 28 70  ckReservedLock(p
7f60: 53 75 62 4f 70 65 6e 2c 20 70 52 65 73 4f 75 74  SubOpen, pResOut
7f70: 29 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20  );.  }.  return 
7f80: 53 51 4c 49 54 45 5f 49 4f 45 52 52 5f 43 48 45  SQLITE_IOERR_CHE
7f90: 43 4b 52 45 53 45 52 56 45 44 4c 4f 43 4b 3b 0a  CKRESERVEDLOCK;.
7fa0: 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 46 69 6c 65  }../* Pass xFile
7fb0: 43 6f 6e 74 72 6f 6c 20 72 65 71 75 65 73 74 73  Control requests
7fc0: 20 74 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20   through to the 
7fd0: 6f 72 69 67 69 6e 61 6c 20 56 46 53 20 75 6e 63  original VFS unc
7fe0: 68 61 6e 67 65 64 2c 0a 2a 2a 20 65 78 63 65 70  hanged,.** excep
7ff0: 74 20 66 6f 72 20 61 6e 79 20 4d 55 4c 54 49 50  t for any MULTIP
8000: 4c 45 58 5f 43 54 52 4c 5f 2a 20 72 65 71 75 65  LEX_CTRL_* reque
8010: 73 74 73 20 68 65 72 65 2e 0a 2a 2f 0a 73 74 61  sts here..*/.sta
8020: 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65  tic int multiple
8030: 78 46 69 6c 65 43 6f 6e 74 72 6f 6c 28 73 71 6c  xFileControl(sql
8040: 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e  ite3_file *pConn
8050: 2c 20 69 6e 74 20 6f 70 2c 20 76 6f 69 64 20 2a  , int op, void *
8060: 70 41 72 67 29 7b 0a 20 20 6d 75 6c 74 69 70 6c  pArg){.  multipl
8070: 65 78 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c  exConn *p = (mul
8080: 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e  tiplexConn*)pCon
8090: 6e 3b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47 72  n;.  multiplexGr
80a0: 6f 75 70 20 2a 70 47 72 6f 75 70 20 3d 20 70 2d  oup *pGroup = p-
80b0: 3e 70 47 72 6f 75 70 3b 0a 20 20 69 6e 74 20 72  >pGroup;.  int r
80c0: 63 20 3d 20 53 51 4c 49 54 45 5f 45 52 52 4f 52  c = SQLITE_ERROR
80d0: 3b 0a 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65  ;.  sqlite3_file
80e0: 20 2a 70 53 75 62 4f 70 65 6e 3b 0a 0a 20 20 69   *pSubOpen;..  i
80f0: 66 28 20 21 67 4d 75 6c 74 69 70 6c 65 78 2e 69  f( !gMultiplex.i
8100: 73 49 6e 69 74 69 61 6c 69 7a 65 64 20 29 20 72  sInitialized ) r
8110: 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4d 49 53  eturn SQLITE_MIS
8120: 55 53 45 3b 0a 20 20 73 77 69 74 63 68 28 20 6f  USE;.  switch( o
8130: 70 20 29 7b 0a 20 20 20 20 63 61 73 65 20 4d 55  p ){.    case MU
8140: 4c 54 49 50 4c 45 58 5f 43 54 52 4c 5f 45 4e 41  LTIPLEX_CTRL_ENA
8150: 42 4c 45 3a 0a 20 20 20 20 20 20 69 66 28 20 70  BLE:.      if( p
8160: 41 72 67 20 29 20 7b 0a 20 20 20 20 20 20 20 20  Arg ) {.        
8170: 69 6e 74 20 62 45 6e 61 62 6c 65 64 20 3d 20 2a  int bEnabled = *
8180: 28 69 6e 74 20 2a 29 70 41 72 67 3b 0a 20 20 20  (int *)pArg;.   
8190: 20 20 20 20 20 70 47 72 6f 75 70 2d 3e 62 45 6e       pGroup->bEn
81a0: 61 62 6c 65 64 20 3d 20 62 45 6e 61 62 6c 65 64  abled = bEnabled
81b0: 3b 0a 20 20 20 20 20 20 20 20 72 63 20 3d 20 53  ;.        rc = S
81c0: 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 20 20 20 20  QLITE_OK;.      
81d0: 7d 0a 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20  }.      break;. 
81e0: 20 20 20 63 61 73 65 20 4d 55 4c 54 49 50 4c 45     case MULTIPLE
81f0: 58 5f 43 54 52 4c 5f 53 45 54 5f 43 48 55 4e 4b  X_CTRL_SET_CHUNK
8200: 5f 53 49 5a 45 3a 0a 20 20 20 20 20 20 69 66 28  _SIZE:.      if(
8210: 20 70 41 72 67 20 29 20 7b 0a 20 20 20 20 20 20   pArg ) {.      
8220: 20 20 75 6e 73 69 67 6e 65 64 20 69 6e 74 20 73    unsigned int s
8230: 7a 43 68 75 6e 6b 20 3d 20 2a 28 75 6e 73 69 67  zChunk = *(unsig
8240: 6e 65 64 2a 29 70 41 72 67 3b 0a 20 20 20 20 20  ned*)pArg;.     
8250: 20 20 20 69 66 28 20 73 7a 43 68 75 6e 6b 3c 31     if( szChunk<1
8260: 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20 72 63   ){.          rc
8270: 20 3d 20 53 51 4c 49 54 45 5f 4d 49 53 55 53 45   = SQLITE_MISUSE
8280: 3b 0a 20 20 20 20 20 20 20 20 7d 65 6c 73 65 7b  ;.        }else{
8290: 0a 20 20 20 20 20 20 20 20 20 20 2f 2a 20 52 6f  .          /* Ro
82a0: 75 6e 64 20 75 70 20 74 6f 20 6e 65 61 72 65 73  und up to neares
82b0: 74 20 6d 75 6c 74 69 70 6c 65 20 6f 66 20 4d 41  t multiple of MA
82c0: 58 5f 50 41 47 45 5f 53 49 5a 45 2e 20 2a 2f 0a  X_PAGE_SIZE. */.
82d0: 20 20 20 20 20 20 20 20 20 20 73 7a 43 68 75 6e            szChun
82e0: 6b 20 3d 20 28 73 7a 43 68 75 6e 6b 20 2b 20 28  k = (szChunk + (
82f0: 4d 41 58 5f 50 41 47 45 5f 53 49 5a 45 2d 31 29  MAX_PAGE_SIZE-1)
8300: 29 3b 0a 20 20 20 20 20 20 20 20 20 20 73 7a 43  );.          szC
8310: 68 75 6e 6b 20 26 3d 20 7e 28 4d 41 58 5f 50 41  hunk &= ~(MAX_PA
8320: 47 45 5f 53 49 5a 45 2d 31 29 3b 0a 20 20 20 20  GE_SIZE-1);.    
8330: 20 20 20 20 20 20 70 47 72 6f 75 70 2d 3e 73 7a        pGroup->sz
8340: 43 68 75 6e 6b 20 3d 20 73 7a 43 68 75 6e 6b 3b  Chunk = szChunk;
8350: 0a 20 20 20 20 20 20 20 20 20 20 72 63 20 3d 20  .          rc = 
8360: 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 20 20 20  SQLITE_OK;.     
8370: 20 20 20 7d 0a 20 20 20 20 20 20 7d 0a 20 20 20     }.      }.   
8380: 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 63 61     break;.    ca
8390: 73 65 20 4d 55 4c 54 49 50 4c 45 58 5f 43 54 52  se MULTIPLEX_CTR
83a0: 4c 5f 53 45 54 5f 4d 41 58 5f 43 48 55 4e 4b 53  L_SET_MAX_CHUNKS
83b0: 3a 0a 20 20 20 20 20 20 72 63 20 3d 20 53 51 4c  :.      rc = SQL
83c0: 49 54 45 5f 4f 4b 3b 0a 20 20 20 20 20 20 62 72  ITE_OK;.      br
83d0: 65 61 6b 3b 0a 20 20 20 20 63 61 73 65 20 53 51  eak;.    case SQ
83e0: 4c 49 54 45 5f 46 43 4e 54 4c 5f 53 49 5a 45 5f  LITE_FCNTL_SIZE_
83f0: 48 49 4e 54 3a 0a 20 20 20 20 63 61 73 65 20 53  HINT:.    case S
8400: 51 4c 49 54 45 5f 46 43 4e 54 4c 5f 43 48 55 4e  QLITE_FCNTL_CHUN
8410: 4b 5f 53 49 5a 45 3a 0a 20 20 20 20 20 20 2f 2a  K_SIZE:.      /*
8420: 20 6e 6f 2d 6f 70 20 74 68 65 73 65 20 2a 2f 0a   no-op these */.
8430: 20 20 20 20 20 20 72 63 20 3d 20 53 51 4c 49 54        rc = SQLIT
8440: 45 5f 4f 4b 3b 0a 20 20 20 20 20 20 62 72 65 61  E_OK;.      brea
8450: 6b 3b 0a 20 20 20 20 64 65 66 61 75 6c 74 3a 0a  k;.    default:.
8460: 20 20 20 20 20 20 70 53 75 62 4f 70 65 6e 20 3d        pSubOpen =
8470: 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65   multiplexSubOpe
8480: 6e 28 70 47 72 6f 75 70 2c 20 30 2c 20 26 72 63  n(pGroup, 0, &rc
8490: 2c 20 4e 55 4c 4c 2c 20 30 29 3b 0a 20 20 20 20  , NULL, 0);.    
84a0: 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e 20 29    if( pSubOpen )
84b0: 7b 0a 20 20 20 20 20 20 20 20 72 63 20 3d 20 70  {.        rc = p
84c0: 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64  SubOpen->pMethod
84d0: 73 2d 3e 78 46 69 6c 65 43 6f 6e 74 72 6f 6c 28  s->xFileControl(
84e0: 70 53 75 62 4f 70 65 6e 2c 20 6f 70 2c 20 70 41  pSubOpen, op, pA
84f0: 72 67 29 3b 0a 20 20 20 20 20 20 20 20 69 66 28  rg);.        if(
8500: 20 6f 70 3d 3d 53 51 4c 49 54 45 5f 46 43 4e 54   op==SQLITE_FCNT
8510: 4c 5f 56 46 53 4e 41 4d 45 20 26 26 20 72 63 3d  L_VFSNAME && rc=
8520: 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20  =SQLITE_OK ){.  
8530: 20 20 20 20 20 20 20 2a 28 63 68 61 72 2a 2a 29         *(char**)
8540: 70 41 72 67 20 3d 20 73 71 6c 69 74 65 33 5f 6d  pArg = sqlite3_m
8550: 70 72 69 6e 74 66 28 22 6d 75 6c 74 69 70 6c 65  printf("multiple
8560: 78 2f 25 7a 22 2c 20 2a 28 63 68 61 72 2a 2a 29  x/%z", *(char**)
8570: 70 41 72 67 29 3b 0a 20 20 20 20 20 20 20 20 7d  pArg);.        }
8580: 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 62  .      }.      b
8590: 72 65 61 6b 3b 0a 20 20 7d 0a 20 20 72 65 74 75  reak;.  }.  retu
85a0: 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 20 50 61 73  rn rc;.}../* Pas
85b0: 73 20 78 53 65 63 74 6f 72 53 69 7a 65 20 72 65  s xSectorSize re
85c0: 71 75 65 73 74 73 20 74 68 72 6f 75 67 68 20 74  quests through t
85d0: 6f 20 74 68 65 20 6f 72 69 67 69 6e 61 6c 20 56  o the original V
85e0: 46 53 20 75 6e 63 68 61 6e 67 65 64 2e 0a 2a 2f  FS unchanged..*/
85f0: 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74  .static int mult
8600: 69 70 6c 65 78 53 65 63 74 6f 72 53 69 7a 65 28  iplexSectorSize(
8610: 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 43  sqlite3_file *pC
8620: 6f 6e 6e 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65  onn){.  multiple
8630: 78 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74  xConn *p = (mult
8640: 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e  iplexConn*)pConn
8650: 3b 0a 20 20 69 6e 74 20 72 63 3b 0a 20 20 73 71  ;.  int rc;.  sq
8660: 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62  lite3_file *pSub
8670: 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78  Open = multiplex
8680: 53 75 62 4f 70 65 6e 28 70 2d 3e 70 47 72 6f 75  SubOpen(p->pGrou
8690: 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 2c  p, 0, &rc, NULL,
86a0: 20 30 29 3b 0a 20 20 69 66 28 20 70 53 75 62 4f   0);.  if( pSubO
86b0: 70 65 6e 20 26 26 20 70 53 75 62 4f 70 65 6e 2d  pen && pSubOpen-
86c0: 3e 70 4d 65 74 68 6f 64 73 2d 3e 78 53 65 63 74  >pMethods->xSect
86d0: 6f 72 53 69 7a 65 20 29 7b 0a 20 20 20 20 72 65  orSize ){.    re
86e0: 74 75 72 6e 20 70 53 75 62 4f 70 65 6e 2d 3e 70  turn pSubOpen->p
86f0: 4d 65 74 68 6f 64 73 2d 3e 78 53 65 63 74 6f 72  Methods->xSector
8700: 53 69 7a 65 28 70 53 75 62 4f 70 65 6e 29 3b 0a  Size(pSubOpen);.
8710: 20 20 7d 0a 20 20 72 65 74 75 72 6e 20 44 45 46    }.  return DEF
8720: 41 55 4c 54 5f 53 45 43 54 4f 52 5f 53 49 5a 45  AULT_SECTOR_SIZE
8730: 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 44 65  ;.}../* Pass xDe
8740: 76 69 63 65 43 68 61 72 61 63 74 65 72 69 73 74  viceCharacterist
8750: 69 63 73 20 72 65 71 75 65 73 74 73 20 74 68 72  ics requests thr
8760: 6f 75 67 68 20 74 6f 20 74 68 65 20 6f 72 69 67  ough to the orig
8770: 69 6e 61 6c 20 56 46 53 20 75 6e 63 68 61 6e 67  inal VFS unchang
8780: 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e  ed..*/.static in
8790: 74 20 6d 75 6c 74 69 70 6c 65 78 44 65 76 69 63  t multiplexDevic
87a0: 65 43 68 61 72 61 63 74 65 72 69 73 74 69 63 73  eCharacteristics
87b0: 28 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70  (sqlite3_file *p
87c0: 43 6f 6e 6e 29 7b 0a 20 20 6d 75 6c 74 69 70 6c  Conn){.  multipl
87d0: 65 78 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c  exConn *p = (mul
87e0: 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e  tiplexConn*)pCon
87f0: 6e 3b 0a 20 20 69 6e 74 20 72 63 3b 0a 20 20 73  n;.  int rc;.  s
8800: 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75  qlite3_file *pSu
8810: 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65  bOpen = multiple
8820: 78 53 75 62 4f 70 65 6e 28 70 2d 3e 70 47 72 6f  xSubOpen(p->pGro
8830: 75 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c  up, 0, &rc, NULL
8840: 2c 20 30 29 3b 0a 20 20 69 66 28 20 70 53 75 62  , 0);.  if( pSub
8850: 4f 70 65 6e 20 29 7b 0a 20 20 20 20 72 65 74 75  Open ){.    retu
8860: 72 6e 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65  rn pSubOpen->pMe
8870: 74 68 6f 64 73 2d 3e 78 44 65 76 69 63 65 43 68  thods->xDeviceCh
8880: 61 72 61 63 74 65 72 69 73 74 69 63 73 28 70 53  aracteristics(pS
8890: 75 62 4f 70 65 6e 29 3b 0a 20 20 7d 0a 20 20 72  ubOpen);.  }.  r
88a0: 65 74 75 72 6e 20 30 3b 0a 7d 0a 0a 2f 2a 20 50  eturn 0;.}../* P
88b0: 61 73 73 20 78 53 68 6d 4d 61 70 20 72 65 71 75  ass xShmMap requ
88c0: 65 73 74 73 20 74 68 72 6f 75 67 68 20 74 6f 20  ests through to 
88d0: 74 68 65 20 6f 72 69 67 69 6e 61 6c 20 56 46 53  the original VFS
88e0: 20 75 6e 63 68 61 6e 67 65 64 2e 0a 2a 2f 0a 73   unchanged..*/.s
88f0: 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70  tatic int multip
8900: 6c 65 78 53 68 6d 4d 61 70 28 0a 20 20 73 71 6c  lexShmMap(.  sql
8910: 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e  ite3_file *pConn
8920: 2c 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20  ,            /* 
8930: 48 61 6e 64 6c 65 20 6f 70 65 6e 20 6f 6e 20 64  Handle open on d
8940: 61 74 61 62 61 73 65 20 66 69 6c 65 20 2a 2f 0a  atabase file */.
8950: 20 20 69 6e 74 20 69 52 65 67 69 6f 6e 2c 20 20    int iRegion,  
8960: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8970: 20 20 2f 2a 20 52 65 67 69 6f 6e 20 74 6f 20 72    /* Region to r
8980: 65 74 72 69 65 76 65 20 2a 2f 0a 20 20 69 6e 74  etrieve */.  int
8990: 20 73 7a 52 65 67 69 6f 6e 2c 20 20 20 20 20 20   szRegion,      
89a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
89b0: 53 69 7a 65 20 6f 66 20 72 65 67 69 6f 6e 73 20  Size of regions 
89c0: 2a 2f 0a 20 20 69 6e 74 20 62 45 78 74 65 6e 64  */.  int bExtend
89d0: 2c 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,               
89e0: 20 20 20 20 20 2f 2a 20 54 72 75 65 20 74 6f 20       /* True to 
89f0: 65 78 74 65 6e 64 20 66 69 6c 65 20 69 66 20 6e  extend file if n
8a00: 65 63 65 73 73 61 72 79 20 2a 2f 0a 20 20 76 6f  ecessary */.  vo
8a10: 69 64 20 76 6f 6c 61 74 69 6c 65 20 2a 2a 70 70  id volatile **pp
8a20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
8a30: 20 4f 55 54 3a 20 4d 61 70 70 65 64 20 6d 65 6d   OUT: Mapped mem
8a40: 6f 72 79 20 2a 2f 0a 29 7b 0a 20 20 6d 75 6c 74  ory */.){.  mult
8a50: 69 70 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d 20 28  iplexConn *p = (
8a60: 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70  multiplexConn*)p
8a70: 43 6f 6e 6e 3b 0a 20 20 69 6e 74 20 72 63 3b 0a  Conn;.  int rc;.
8a80: 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a    sqlite3_file *
8a90: 70 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69  pSubOpen = multi
8aa0: 70 6c 65 78 53 75 62 4f 70 65 6e 28 70 2d 3e 70  plexSubOpen(p->p
8ab0: 47 72 6f 75 70 2c 20 30 2c 20 26 72 63 2c 20 4e  Group, 0, &rc, N
8ac0: 55 4c 4c 2c 20 30 29 3b 0a 20 20 69 66 28 20 70  ULL, 0);.  if( p
8ad0: 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20 72  SubOpen ){.    r
8ae0: 65 74 75 72 6e 20 70 53 75 62 4f 70 65 6e 2d 3e  eturn pSubOpen->
8af0: 70 4d 65 74 68 6f 64 73 2d 3e 78 53 68 6d 4d 61  pMethods->xShmMa
8b00: 70 28 70 53 75 62 4f 70 65 6e 2c 20 69 52 65 67  p(pSubOpen, iReg
8b10: 69 6f 6e 2c 20 73 7a 52 65 67 69 6f 6e 2c 20 62  ion, szRegion, b
8b20: 45 78 74 65 6e 64 2c 70 70 29 3b 0a 20 20 7d 0a  Extend,pp);.  }.
8b30: 20 20 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f    return SQLITE_
8b40: 49 4f 45 52 52 3b 0a 7d 0a 0a 2f 2a 20 50 61 73  IOERR;.}../* Pas
8b50: 73 20 78 53 68 6d 4c 6f 63 6b 20 72 65 71 75 65  s xShmLock reque
8b60: 73 74 73 20 74 68 72 6f 75 67 68 20 74 6f 20 74  sts through to t
8b70: 68 65 20 6f 72 69 67 69 6e 61 6c 20 56 46 53 20  he original VFS 
8b80: 75 6e 63 68 61 6e 67 65 64 2e 0a 2a 2f 0a 73 74  unchanged..*/.st
8b90: 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c  atic int multipl
8ba0: 65 78 53 68 6d 4c 6f 63 6b 28 0a 20 20 73 71 6c  exShmLock(.  sql
8bb0: 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e  ite3_file *pConn
8bc0: 2c 20 20 20 20 20 20 20 2f 2a 20 44 61 74 61 62  ,       /* Datab
8bd0: 61 73 65 20 66 69 6c 65 20 68 6f 6c 64 69 6e 67  ase file holding
8be0: 20 74 68 65 20 73 68 61 72 65 64 20 6d 65 6d 6f   the shared memo
8bf0: 72 79 20 2a 2f 0a 20 20 69 6e 74 20 6f 66 73 74  ry */.  int ofst
8c00: 2c 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,               
8c10: 20 20 20 2f 2a 20 46 69 72 73 74 20 6c 6f 63 6b     /* First lock
8c20: 20 74 6f 20 61 63 71 75 69 72 65 20 6f 72 20 72   to acquire or r
8c30: 65 6c 65 61 73 65 20 2a 2f 0a 20 20 69 6e 74 20  elease */.  int 
8c40: 6e 2c 20 20 20 20 20 20 20 20 20 20 20 20 20 20  n,              
8c50: 20 20 20 20 20 20 20 2f 2a 20 4e 75 6d 62 65 72         /* Number
8c60: 20 6f 66 20 6c 6f 63 6b 73 20 74 6f 20 61 63 71   of locks to acq
8c70: 75 69 72 65 20 6f 72 20 72 65 6c 65 61 73 65 20  uire or release 
8c80: 2a 2f 0a 20 20 69 6e 74 20 66 6c 61 67 73 20 20  */.  int flags  
8c90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8ca0: 2f 2a 20 57 68 61 74 20 74 6f 20 64 6f 20 77 69  /* What to do wi
8cb0: 74 68 20 74 68 65 20 6c 6f 63 6b 20 2a 2f 0a 29  th the lock */.)
8cc0: 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e  {.  multiplexCon
8cd0: 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65  n *p = (multiple
8ce0: 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20  xConn*)pConn;.  
8cf0: 69 6e 74 20 72 63 3b 0a 20 20 73 71 6c 69 74 65  int rc;.  sqlite
8d00: 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e  3_file *pSubOpen
8d10: 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f   = multiplexSubO
8d20: 70 65 6e 28 70 2d 3e 70 47 72 6f 75 70 2c 20 30  pen(p->pGroup, 0
8d30: 2c 20 26 72 63 2c 20 4e 55 4c 4c 2c 20 30 29 3b  , &rc, NULL, 0);
8d40: 0a 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e 20  .  if( pSubOpen 
8d50: 29 7b 0a 20 20 20 20 72 65 74 75 72 6e 20 70 53  ){.    return pS
8d60: 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73  ubOpen->pMethods
8d70: 2d 3e 78 53 68 6d 4c 6f 63 6b 28 70 53 75 62 4f  ->xShmLock(pSubO
8d80: 70 65 6e 2c 20 6f 66 73 74 2c 20 6e 2c 20 66 6c  pen, ofst, n, fl
8d90: 61 67 73 29 3b 0a 20 20 7d 0a 20 20 72 65 74 75  ags);.  }.  retu
8da0: 72 6e 20 53 51 4c 49 54 45 5f 42 55 53 59 3b 0a  rn SQLITE_BUSY;.
8db0: 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 53 68 6d 42  }../* Pass xShmB
8dc0: 61 72 72 69 65 72 20 72 65 71 75 65 73 74 73 20  arrier requests 
8dd0: 74 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20 6f  through to the o
8de0: 72 69 67 69 6e 61 6c 20 56 46 53 20 75 6e 63 68  riginal VFS unch
8df0: 61 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63  anged..*/.static
8e00: 20 76 6f 69 64 20 6d 75 6c 74 69 70 6c 65 78 53   void multiplexS
8e10: 68 6d 42 61 72 72 69 65 72 28 73 71 6c 69 74 65  hmBarrier(sqlite
8e20: 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 29 7b 0a  3_file *pConn){.
8e30: 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20    multiplexConn 
8e40: 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43  *p = (multiplexC
8e50: 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 69 6e  onn*)pConn;.  in
8e60: 74 20 72 63 3b 0a 20 20 73 71 6c 69 74 65 33 5f  t rc;.  sqlite3_
8e70: 66 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d  file *pSubOpen =
8e80: 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65   multiplexSubOpe
8e90: 6e 28 70 2d 3e 70 47 72 6f 75 70 2c 20 30 2c 20  n(p->pGroup, 0, 
8ea0: 26 72 63 2c 20 4e 55 4c 4c 2c 20 30 29 3b 0a 20  &rc, NULL, 0);. 
8eb0: 20 69 66 28 20 70 53 75 62 4f 70 65 6e 20 29 7b   if( pSubOpen ){
8ec0: 0a 20 20 20 20 70 53 75 62 4f 70 65 6e 2d 3e 70  .    pSubOpen->p
8ed0: 4d 65 74 68 6f 64 73 2d 3e 78 53 68 6d 42 61 72  Methods->xShmBar
8ee0: 72 69 65 72 28 70 53 75 62 4f 70 65 6e 29 3b 0a  rier(pSubOpen);.
8ef0: 20 20 7d 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78    }.}../* Pass x
8f00: 53 68 6d 55 6e 6d 61 70 20 72 65 71 75 65 73 74  ShmUnmap request
8f10: 73 20 74 68 72 6f 75 67 68 20 74 6f 20 74 68 65  s through to the
8f20: 20 6f 72 69 67 69 6e 61 6c 20 56 46 53 20 75 6e   original VFS un
8f30: 63 68 61 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61 74  changed..*/.stat
8f40: 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78  ic int multiplex
8f50: 53 68 6d 55 6e 6d 61 70 28 73 71 6c 69 74 65 33  ShmUnmap(sqlite3
8f60: 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c 20 69 6e  _file *pConn, in
8f70: 74 20 64 65 6c 65 74 65 46 6c 61 67 29 7b 0a 20  t deleteFlag){. 
8f80: 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a   multiplexConn *
8f90: 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f  p = (multiplexCo
8fa0: 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 69 6e 74  nn*)pConn;.  int
8fb0: 20 72 63 3b 0a 20 20 73 71 6c 69 74 65 33 5f 66   rc;.  sqlite3_f
8fc0: 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20  ile *pSubOpen = 
8fd0: 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e  multiplexSubOpen
8fe0: 28 70 2d 3e 70 47 72 6f 75 70 2c 20 30 2c 20 26  (p->pGroup, 0, &
8ff0: 72 63 2c 20 4e 55 4c 4c 2c 20 30 29 3b 0a 20 20  rc, NULL, 0);.  
9000: 69 66 28 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a  if( pSubOpen ){.
9010: 20 20 20 20 72 65 74 75 72 6e 20 70 53 75 62 4f      return pSubO
9020: 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e 78  pen->pMethods->x
9030: 53 68 6d 55 6e 6d 61 70 28 70 53 75 62 4f 70 65  ShmUnmap(pSubOpe
9040: 6e 2c 20 64 65 6c 65 74 65 46 6c 61 67 29 3b 0a  n, deleteFlag);.
9050: 20 20 7d 0a 20 20 72 65 74 75 72 6e 20 53 51 4c    }.  return SQL
9060: 49 54 45 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a 2a 2a 2a  ITE_OK;.}../****
9070: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
9080: 2a 2a 2a 2a 2a 2a 20 50 75 62 6c 69 63 20 49 6e  ****** Public In
9090: 74 65 72 66 61 63 65 73 20 2a 2a 2a 2a 2a 2a 2a  terfaces *******
90a0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
90b0: 2a 2a 2a 2a 2a 2a 2f 0a 2f 2a 0a 2a 2a 20 43 41  ******/./*.** CA
90c0: 50 49 3a 20 49 6e 69 74 69 61 6c 69 7a 65 20 74  PI: Initialize t
90d0: 68 65 20 6d 75 6c 74 69 70 6c 65 78 20 56 46 53  he multiplex VFS
90e0: 20 73 68 69 6d 20 2d 20 73 71 6c 69 74 65 33 5f   shim - sqlite3_
90f0: 6d 75 6c 74 69 70 6c 65 78 5f 69 6e 69 74 69 61  multiplex_initia
9100: 6c 69 7a 65 28 29 0a 2a 2a 0a 2a 2a 20 55 73 65  lize().**.** Use
9110: 20 74 68 65 20 56 46 53 20 6e 61 6d 65 64 20 7a   the VFS named z
9120: 4f 72 69 67 56 66 73 4e 61 6d 65 20 61 73 20 74  OrigVfsName as t
9130: 68 65 20 56 46 53 20 74 68 61 74 20 64 6f 65 73  he VFS that does
9140: 20 74 68 65 20 61 63 74 75 61 6c 20 77 6f 72 6b   the actual work
9150: 2e 20 20 0a 2a 2a 20 55 73 65 20 74 68 65 20 64  .  .** Use the d
9160: 65 66 61 75 6c 74 20 69 66 20 7a 4f 72 69 67 56  efault if zOrigV
9170: 66 73 4e 61 6d 65 3d 3d 4e 55 4c 4c 2e 20 20 0a  fsName==NULL.  .
9180: 2a 2a 0a 2a 2a 20 54 68 65 20 6d 75 6c 74 69 70  **.** The multip
9190: 6c 65 78 20 56 46 53 20 73 68 69 6d 20 69 73 20  lex VFS shim is 
91a0: 6e 61 6d 65 64 20 22 6d 75 6c 74 69 70 6c 65 78  named "multiplex
91b0: 22 2e 20 20 49 74 20 77 69 6c 6c 20 62 65 63 6f  ".  It will beco
91c0: 6d 65 20 74 68 65 20 64 65 66 61 75 6c 74 0a 2a  me the default.*
91d0: 2a 20 56 46 53 20 69 66 20 6d 61 6b 65 44 65 66  * VFS if makeDef
91e0: 61 75 6c 74 20 69 73 20 6e 6f 6e 2d 7a 65 72 6f  ault is non-zero
91f0: 2e 0a 2a 2a 0a 2a 2a 20 54 48 49 53 20 52 4f 55  ..**.** THIS ROU
9200: 54 49 4e 45 20 49 53 20 4e 4f 54 20 54 48 52 45  TINE IS NOT THRE
9210: 41 44 53 41 46 45 2e 20 20 43 61 6c 6c 20 74 68  ADSAFE.  Call th
9220: 69 73 20 72 6f 75 74 69 6e 65 20 65 78 61 63 74  is routine exact
9230: 6c 79 20 6f 6e 63 65 0a 2a 2a 20 64 75 72 69 6e  ly once.** durin
9240: 67 20 73 74 61 72 74 2d 75 70 2e 0a 2a 2f 0a 69  g start-up..*/.i
9250: 6e 74 20 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69  nt sqlite3_multi
9260: 70 6c 65 78 5f 69 6e 69 74 69 61 6c 69 7a 65 28  plex_initialize(
9270: 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 4f 72 69  const char *zOri
9280: 67 56 66 73 4e 61 6d 65 2c 20 69 6e 74 20 6d 61  gVfsName, int ma
9290: 6b 65 44 65 66 61 75 6c 74 29 7b 0a 20 20 73 71  keDefault){.  sq
92a0: 6c 69 74 65 33 5f 76 66 73 20 2a 70 4f 72 69 67  lite3_vfs *pOrig
92b0: 56 66 73 3b 0a 20 20 69 66 28 20 67 4d 75 6c 74  Vfs;.  if( gMult
92c0: 69 70 6c 65 78 2e 69 73 49 6e 69 74 69 61 6c 69  iplex.isInitiali
92d0: 7a 65 64 20 29 20 72 65 74 75 72 6e 20 53 51 4c  zed ) return SQL
92e0: 49 54 45 5f 4d 49 53 55 53 45 3b 0a 20 20 70 4f  ITE_MISUSE;.  pO
92f0: 72 69 67 56 66 73 20 3d 20 73 71 6c 69 74 65 33  rigVfs = sqlite3
9300: 5f 76 66 73 5f 66 69 6e 64 28 7a 4f 72 69 67 56  _vfs_find(zOrigV
9310: 66 73 4e 61 6d 65 29 3b 0a 20 20 69 66 28 20 70  fsName);.  if( p
9320: 4f 72 69 67 56 66 73 3d 3d 30 20 29 20 72 65 74  OrigVfs==0 ) ret
9330: 75 72 6e 20 53 51 4c 49 54 45 5f 45 52 52 4f 52  urn SQLITE_ERROR
9340: 3b 0a 20 20 61 73 73 65 72 74 28 20 70 4f 72 69  ;.  assert( pOri
9350: 67 56 66 73 21 3d 26 67 4d 75 6c 74 69 70 6c 65  gVfs!=&gMultiple
9360: 78 2e 73 54 68 69 73 56 66 73 20 29 3b 0a 20 20  x.sThisVfs );.  
9370: 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4d 75 74 65  gMultiplex.pMute
9380: 78 20 3d 20 73 71 6c 69 74 65 33 5f 6d 75 74 65  x = sqlite3_mute
9390: 78 5f 61 6c 6c 6f 63 28 53 51 4c 49 54 45 5f 4d  x_alloc(SQLITE_M
93a0: 55 54 45 58 5f 46 41 53 54 29 3b 0a 20 20 69 66  UTEX_FAST);.  if
93b0: 28 20 21 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4d  ( !gMultiplex.pM
93c0: 75 74 65 78 20 29 7b 0a 20 20 20 20 72 65 74 75  utex ){.    retu
93d0: 72 6e 20 53 51 4c 49 54 45 5f 4e 4f 4d 45 4d 3b  rn SQLITE_NOMEM;
93e0: 0a 20 20 7d 0a 20 20 67 4d 75 6c 74 69 70 6c 65  .  }.  gMultiple
93f0: 78 2e 70 47 72 6f 75 70 73 20 3d 20 4e 55 4c 4c  x.pGroups = NULL
9400: 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 69  ;.  gMultiplex.i
9410: 73 49 6e 69 74 69 61 6c 69 7a 65 64 20 3d 20 31  sInitialized = 1
9420: 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70  ;.  gMultiplex.p
9430: 4f 72 69 67 56 66 73 20 3d 20 70 4f 72 69 67 56  OrigVfs = pOrigV
9440: 66 73 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78  fs;.  gMultiplex
9450: 2e 73 54 68 69 73 56 66 73 20 3d 20 2a 70 4f 72  .sThisVfs = *pOr
9460: 69 67 56 66 73 3b 0a 20 20 67 4d 75 6c 74 69 70  igVfs;.  gMultip
9470: 6c 65 78 2e 73 54 68 69 73 56 66 73 2e 73 7a 4f  lex.sThisVfs.szO
9480: 73 46 69 6c 65 20 2b 3d 20 73 69 7a 65 6f 66 28  sFile += sizeof(
9490: 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 29 3b 0a  multiplexConn);.
94a0: 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54 68    gMultiplex.sTh
94b0: 69 73 56 66 73 2e 7a 4e 61 6d 65 20 3d 20 53 51  isVfs.zName = SQ
94c0: 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 56  LITE_MULTIPLEX_V
94d0: 46 53 5f 4e 41 4d 45 3b 0a 20 20 67 4d 75 6c 74  FS_NAME;.  gMult
94e0: 69 70 6c 65 78 2e 73 54 68 69 73 56 66 73 2e 78  iplex.sThisVfs.x
94f0: 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78  Open = multiplex
9500: 4f 70 65 6e 3b 0a 20 20 67 4d 75 6c 74 69 70 6c  Open;.  gMultipl
9510: 65 78 2e 73 54 68 69 73 56 66 73 2e 78 44 65 6c  ex.sThisVfs.xDel
9520: 65 74 65 20 3d 20 6d 75 6c 74 69 70 6c 65 78 44  ete = multiplexD
9530: 65 6c 65 74 65 3b 0a 20 20 67 4d 75 6c 74 69 70  elete;.  gMultip
9540: 6c 65 78 2e 73 54 68 69 73 56 66 73 2e 78 41 63  lex.sThisVfs.xAc
9550: 63 65 73 73 20 3d 20 6d 75 6c 74 69 70 6c 65 78  cess = multiplex
9560: 41 63 63 65 73 73 3b 0a 20 20 67 4d 75 6c 74 69  Access;.  gMulti
9570: 70 6c 65 78 2e 73 54 68 69 73 56 66 73 2e 78 46  plex.sThisVfs.xF
9580: 75 6c 6c 50 61 74 68 6e 61 6d 65 20 3d 20 6d 75  ullPathname = mu
9590: 6c 74 69 70 6c 65 78 46 75 6c 6c 50 61 74 68 6e  ltiplexFullPathn
95a0: 61 6d 65 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65  ame;.  gMultiple
95b0: 78 2e 73 54 68 69 73 56 66 73 2e 78 44 6c 4f 70  x.sThisVfs.xDlOp
95c0: 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 44 6c  en = multiplexDl
95d0: 4f 70 65 6e 3b 0a 20 20 67 4d 75 6c 74 69 70 6c  Open;.  gMultipl
95e0: 65 78 2e 73 54 68 69 73 56 66 73 2e 78 44 6c 45  ex.sThisVfs.xDlE
95f0: 72 72 6f 72 20 3d 20 6d 75 6c 74 69 70 6c 65 78  rror = multiplex
9600: 44 6c 45 72 72 6f 72 3b 0a 20 20 67 4d 75 6c 74  DlError;.  gMult
9610: 69 70 6c 65 78 2e 73 54 68 69 73 56 66 73 2e 78  iplex.sThisVfs.x
9620: 44 6c 53 79 6d 20 3d 20 6d 75 6c 74 69 70 6c 65  DlSym = multiple
9630: 78 44 6c 53 79 6d 3b 0a 20 20 67 4d 75 6c 74 69  xDlSym;.  gMulti
9640: 70 6c 65 78 2e 73 54 68 69 73 56 66 73 2e 78 44  plex.sThisVfs.xD
9650: 6c 43 6c 6f 73 65 20 3d 20 6d 75 6c 74 69 70 6c  lClose = multipl
9660: 65 78 44 6c 43 6c 6f 73 65 3b 0a 20 20 67 4d 75  exDlClose;.  gMu
9670: 6c 74 69 70 6c 65 78 2e 73 54 68 69 73 56 66 73  ltiplex.sThisVfs
9680: 2e 78 52 61 6e 64 6f 6d 6e 65 73 73 20 3d 20 6d  .xRandomness = m
9690: 75 6c 74 69 70 6c 65 78 52 61 6e 64 6f 6d 6e 65  ultiplexRandomne
96a0: 73 73 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78  ss;.  gMultiplex
96b0: 2e 73 54 68 69 73 56 66 73 2e 78 53 6c 65 65 70  .sThisVfs.xSleep
96c0: 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 6c 65 65   = multiplexSlee
96d0: 70 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e  p;.  gMultiplex.
96e0: 73 54 68 69 73 56 66 73 2e 78 43 75 72 72 65 6e  sThisVfs.xCurren
96f0: 74 54 69 6d 65 20 3d 20 6d 75 6c 74 69 70 6c 65  tTime = multiple
9700: 78 43 75 72 72 65 6e 74 54 69 6d 65 3b 0a 20 20  xCurrentTime;.  
9710: 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54 68 69 73  gMultiplex.sThis
9720: 56 66 73 2e 78 47 65 74 4c 61 73 74 45 72 72 6f  Vfs.xGetLastErro
9730: 72 20 3d 20 6d 75 6c 74 69 70 6c 65 78 47 65 74  r = multiplexGet
9740: 4c 61 73 74 45 72 72 6f 72 3b 0a 20 20 67 4d 75  LastError;.  gMu
9750: 6c 74 69 70 6c 65 78 2e 73 54 68 69 73 56 66 73  ltiplex.sThisVfs
9760: 2e 78 43 75 72 72 65 6e 74 54 69 6d 65 49 6e 74  .xCurrentTimeInt
9770: 36 34 20 3d 20 6d 75 6c 74 69 70 6c 65 78 43 75  64 = multiplexCu
9780: 72 72 65 6e 74 54 69 6d 65 49 6e 74 36 34 3b 0a  rrentTimeInt64;.
9790: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49  .  gMultiplex.sI
97a0: 6f 4d 65 74 68 6f 64 73 56 31 2e 69 56 65 72 73  oMethodsV1.iVers
97b0: 69 6f 6e 20 3d 20 31 3b 0a 20 20 67 4d 75 6c 74  ion = 1;.  gMult
97c0: 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73  iplex.sIoMethods
97d0: 56 31 2e 78 43 6c 6f 73 65 20 3d 20 6d 75 6c 74  V1.xClose = mult
97e0: 69 70 6c 65 78 43 6c 6f 73 65 3b 0a 20 20 67 4d  iplexClose;.  gM
97f0: 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68  ultiplex.sIoMeth
9800: 6f 64 73 56 31 2e 78 52 65 61 64 20 3d 20 6d 75  odsV1.xRead = mu
9810: 6c 74 69 70 6c 65 78 52 65 61 64 3b 0a 20 20 67  ltiplexRead;.  g
9820: 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74  Multiplex.sIoMet
9830: 68 6f 64 73 56 31 2e 78 57 72 69 74 65 20 3d 20  hodsV1.xWrite = 
9840: 6d 75 6c 74 69 70 6c 65 78 57 72 69 74 65 3b 0a  multiplexWrite;.
9850: 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f    gMultiplex.sIo
9860: 4d 65 74 68 6f 64 73 56 31 2e 78 54 72 75 6e 63  MethodsV1.xTrunc
9870: 61 74 65 20 3d 20 6d 75 6c 74 69 70 6c 65 78 54  ate = multiplexT
9880: 72 75 6e 63 61 74 65 3b 0a 20 20 67 4d 75 6c 74  runcate;.  gMult
9890: 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73  iplex.sIoMethods
98a0: 56 31 2e 78 53 79 6e 63 20 3d 20 6d 75 6c 74 69  V1.xSync = multi
98b0: 70 6c 65 78 53 79 6e 63 3b 0a 20 20 67 4d 75 6c  plexSync;.  gMul
98c0: 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64  tiplex.sIoMethod
98d0: 73 56 31 2e 78 46 69 6c 65 53 69 7a 65 20 3d 20  sV1.xFileSize = 
98e0: 6d 75 6c 74 69 70 6c 65 78 46 69 6c 65 53 69 7a  multiplexFileSiz
98f0: 65 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e  e;.  gMultiplex.
9900: 73 49 6f 4d 65 74 68 6f 64 73 56 31 2e 78 4c 6f  sIoMethodsV1.xLo
9910: 63 6b 20 3d 20 6d 75 6c 74 69 70 6c 65 78 4c 6f  ck = multiplexLo
9920: 63 6b 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78  ck;.  gMultiplex
9930: 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31 2e 78 55  .sIoMethodsV1.xU
9940: 6e 6c 6f 63 6b 20 3d 20 6d 75 6c 74 69 70 6c 65  nlock = multiple
9950: 78 55 6e 6c 6f 63 6b 3b 0a 20 20 67 4d 75 6c 74  xUnlock;.  gMult
9960: 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73  iplex.sIoMethods
9970: 56 31 2e 78 43 68 65 63 6b 52 65 73 65 72 76 65  V1.xCheckReserve
9980: 64 4c 6f 63 6b 20 3d 20 6d 75 6c 74 69 70 6c 65  dLock = multiple
9990: 78 43 68 65 63 6b 52 65 73 65 72 76 65 64 4c 6f  xCheckReservedLo
99a0: 63 6b 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78  ck;.  gMultiplex
99b0: 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31 2e 78 46  .sIoMethodsV1.xF
99c0: 69 6c 65 43 6f 6e 74 72 6f 6c 20 3d 20 6d 75 6c  ileControl = mul
99d0: 74 69 70 6c 65 78 46 69 6c 65 43 6f 6e 74 72 6f  tiplexFileContro
99e0: 6c 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e  l;.  gMultiplex.
99f0: 73 49 6f 4d 65 74 68 6f 64 73 56 31 2e 78 53 65  sIoMethodsV1.xSe
9a00: 63 74 6f 72 53 69 7a 65 20 3d 20 6d 75 6c 74 69  ctorSize = multi
9a10: 70 6c 65 78 53 65 63 74 6f 72 53 69 7a 65 3b 0a  plexSectorSize;.
9a20: 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f    gMultiplex.sIo
9a30: 4d 65 74 68 6f 64 73 56 31 2e 78 44 65 76 69 63  MethodsV1.xDevic
9a40: 65 43 68 61 72 61 63 74 65 72 69 73 74 69 63 73  eCharacteristics
9a50: 20 3d 0a 20 20 20 20 20 20 20 20 20 20 20 20 20   =.             
9a60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9a70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 6d                 m
9a80: 75 6c 74 69 70 6c 65 78 44 65 76 69 63 65 43 68  ultiplexDeviceCh
9a90: 61 72 61 63 74 65 72 69 73 74 69 63 73 3b 0a 20  aracteristics;. 
9aa0: 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d   gMultiplex.sIoM
9ab0: 65 74 68 6f 64 73 56 32 20 3d 20 67 4d 75 6c 74  ethodsV2 = gMult
9ac0: 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73  iplex.sIoMethods
9ad0: 56 31 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78  V1;.  gMultiplex
9ae0: 2e 73 49 6f 4d 65 74 68 6f 64 73 56 32 2e 69 56  .sIoMethodsV2.iV
9af0: 65 72 73 69 6f 6e 20 3d 20 32 3b 0a 20 20 67 4d  ersion = 2;.  gM
9b00: 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68  ultiplex.sIoMeth
9b10: 6f 64 73 56 32 2e 78 53 68 6d 4d 61 70 20 3d 20  odsV2.xShmMap = 
9b20: 6d 75 6c 74 69 70 6c 65 78 53 68 6d 4d 61 70 3b  multiplexShmMap;
9b30: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49  .  gMultiplex.sI
9b40: 6f 4d 65 74 68 6f 64 73 56 32 2e 78 53 68 6d 4c  oMethodsV2.xShmL
9b50: 6f 63 6b 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53  ock = multiplexS
9b60: 68 6d 4c 6f 63 6b 3b 0a 20 20 67 4d 75 6c 74 69  hmLock;.  gMulti
9b70: 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56  plex.sIoMethodsV
9b80: 32 2e 78 53 68 6d 42 61 72 72 69 65 72 20 3d 20  2.xShmBarrier = 
9b90: 6d 75 6c 74 69 70 6c 65 78 53 68 6d 42 61 72 72  multiplexShmBarr
9ba0: 69 65 72 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65  ier;.  gMultiple
9bb0: 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 32 2e 78  x.sIoMethodsV2.x
9bc0: 53 68 6d 55 6e 6d 61 70 20 3d 20 6d 75 6c 74 69  ShmUnmap = multi
9bd0: 70 6c 65 78 53 68 6d 55 6e 6d 61 70 3b 0a 20 20  plexShmUnmap;.  
9be0: 73 71 6c 69 74 65 33 5f 76 66 73 5f 72 65 67 69  sqlite3_vfs_regi
9bf0: 73 74 65 72 28 26 67 4d 75 6c 74 69 70 6c 65 78  ster(&gMultiplex
9c00: 2e 73 54 68 69 73 56 66 73 2c 20 6d 61 6b 65 44  .sThisVfs, makeD
9c10: 65 66 61 75 6c 74 29 3b 0a 0a 20 20 73 71 6c 69  efault);..  sqli
9c20: 74 65 33 5f 61 75 74 6f 5f 65 78 74 65 6e 73 69  te3_auto_extensi
9c30: 6f 6e 28 28 76 6f 69 64 2a 29 6d 75 6c 74 69 70  on((void*)multip
9c40: 6c 65 78 46 75 6e 63 49 6e 69 74 29 3b 0a 0a 20  lexFuncInit);.. 
9c50: 20 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4f   return SQLITE_O
9c60: 4b 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 43 41 50 49  K;.}../*.** CAPI
9c70: 3a 20 53 68 75 74 64 6f 77 6e 20 74 68 65 20 6d  : Shutdown the m
9c80: 75 6c 74 69 70 6c 65 78 20 73 79 73 74 65 6d 20  ultiplex system 
9c90: 2d 20 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70  - sqlite3_multip
9ca0: 6c 65 78 5f 73 68 75 74 64 6f 77 6e 28 29 0a 2a  lex_shutdown().*
9cb0: 2a 0a 2a 2a 20 41 6c 6c 20 53 51 4c 69 74 65 20  *.** All SQLite 
9cc0: 64 61 74 61 62 61 73 65 20 63 6f 6e 6e 65 63 74  database connect
9cd0: 69 6f 6e 73 20 6d 75 73 74 20 62 65 20 63 6c 6f  ions must be clo
9ce0: 73 65 64 20 62 65 66 6f 72 65 20 63 61 6c 6c 69  sed before calli
9cf0: 6e 67 20 74 68 69 73 0a 2a 2a 20 72 6f 75 74 69  ng this.** routi
9d00: 6e 65 2e 0a 2a 2a 0a 2a 2a 20 54 48 49 53 20 52  ne..**.** THIS R
9d10: 4f 55 54 49 4e 45 20 49 53 20 4e 4f 54 20 54 48  OUTINE IS NOT TH
9d20: 52 45 41 44 53 41 46 45 2e 20 20 43 61 6c 6c 20  READSAFE.  Call 
9d30: 74 68 69 73 20 72 6f 75 74 69 6e 65 20 65 78 61  this routine exa
9d40: 63 74 6c 79 20 6f 6e 63 65 20 77 68 69 6c 65 0a  ctly once while.
9d50: 2a 2a 20 73 68 75 74 74 69 6e 67 20 64 6f 77 6e  ** shutting down
9d60: 20 69 6e 20 6f 72 64 65 72 20 74 6f 20 66 72 65   in order to fre
9d70: 65 20 61 6c 6c 20 72 65 6d 61 69 6e 69 6e 67 20  e all remaining 
9d80: 6d 75 6c 74 69 70 6c 65 78 20 67 72 6f 75 70 73  multiplex groups
9d90: 2e 0a 2a 2f 0a 69 6e 74 20 73 71 6c 69 74 65 33  ..*/.int sqlite3
9da0: 5f 6d 75 6c 74 69 70 6c 65 78 5f 73 68 75 74 64  _multiplex_shutd
9db0: 6f 77 6e 28 76 6f 69 64 29 7b 0a 20 20 69 66 28  own(void){.  if(
9dc0: 20 67 4d 75 6c 74 69 70 6c 65 78 2e 69 73 49 6e   gMultiplex.isIn
9dd0: 69 74 69 61 6c 69 7a 65 64 3d 3d 30 20 29 20 72  itialized==0 ) r
9de0: 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4d 49 53  eturn SQLITE_MIS
9df0: 55 53 45 3b 0a 20 20 69 66 28 20 67 4d 75 6c 74  USE;.  if( gMult
9e00: 69 70 6c 65 78 2e 70 47 72 6f 75 70 73 20 29 20  iplex.pGroups ) 
9e10: 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4d 49  return SQLITE_MI
9e20: 53 55 53 45 3b 0a 20 20 67 4d 75 6c 74 69 70 6c  SUSE;.  gMultipl
9e30: 65 78 2e 69 73 49 6e 69 74 69 61 6c 69 7a 65 64  ex.isInitialized
9e40: 20 3d 20 30 3b 0a 20 20 73 71 6c 69 74 65 33 5f   = 0;.  sqlite3_
9e50: 6d 75 74 65 78 5f 66 72 65 65 28 67 4d 75 6c 74  mutex_free(gMult
9e60: 69 70 6c 65 78 2e 70 4d 75 74 65 78 29 3b 0a 20  iplex.pMutex);. 
9e70: 20 73 71 6c 69 74 65 33 5f 76 66 73 5f 75 6e 72   sqlite3_vfs_unr
9e80: 65 67 69 73 74 65 72 28 26 67 4d 75 6c 74 69 70  egister(&gMultip
9e90: 6c 65 78 2e 73 54 68 69 73 56 66 73 29 3b 0a 20  lex.sThisVfs);. 
9ea0: 20 6d 65 6d 73 65 74 28 26 67 4d 75 6c 74 69 70   memset(&gMultip
9eb0: 6c 65 78 2c 20 30 2c 20 73 69 7a 65 6f 66 28 67  lex, 0, sizeof(g
9ec0: 4d 75 6c 74 69 70 6c 65 78 29 29 3b 0a 20 20 72  Multiplex));.  r
9ed0: 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4f 4b 3b  eturn SQLITE_OK;
9ee0: 0a 7d 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  .}../***********
9ef0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
9f00: 2a 2a 20 54 65 73 74 20 43 6f 64 65 20 2a 2a 2a  ** Test Code ***
9f10: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
9f20: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
9f30: 2f 0a 23 69 66 64 65 66 20 53 51 4c 49 54 45 5f  /.#ifdef SQLITE_
9f40: 54 45 53 54 0a 23 69 6e 63 6c 75 64 65 20 3c 74  TEST.#include <t
9f50: 63 6c 2e 68 3e 0a 65 78 74 65 72 6e 20 63 6f 6e  cl.h>.extern con
9f60: 73 74 20 63 68 61 72 20 2a 73 71 6c 69 74 65 33  st char *sqlite3
9f70: 45 72 72 4e 61 6d 65 28 69 6e 74 29 3b 0a 0a 0a  ErrName(int);...
9f80: 2f 2a 0a 2a 2a 20 74 63 6c 63 6d 64 3a 20 73 71  /*.** tclcmd: sq
9f90: 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f  lite3_multiplex_
9fa0: 69 6e 69 74 69 61 6c 69 7a 65 20 4e 41 4d 45 20  initialize NAME 
9fb0: 4d 41 4b 45 44 45 46 41 55 4c 54 0a 2a 2f 0a 73  MAKEDEFAULT.*/.s
9fc0: 74 61 74 69 63 20 69 6e 74 20 74 65 73 74 5f 6d  tatic int test_m
9fd0: 75 6c 74 69 70 6c 65 78 5f 69 6e 69 74 69 61 6c  ultiplex_initial
9fe0: 69 7a 65 28 0a 20 20 76 6f 69 64 20 2a 20 63 6c  ize(.  void * cl
9ff0: 69 65 6e 74 44 61 74 61 2c 0a 20 20 54 63 6c 5f  ientData,.  Tcl_
a000: 49 6e 74 65 72 70 20 2a 69 6e 74 65 72 70 2c 0a  Interp *interp,.
a010: 20 20 69 6e 74 20 6f 62 6a 63 2c 0a 20 20 54 63    int objc,.  Tc
a020: 6c 5f 4f 62 6a 20 2a 43 4f 4e 53 54 20 6f 62 6a  l_Obj *CONST obj
a030: 76 5b 5d 0a 29 7b 0a 20 20 63 6f 6e 73 74 20 63  v[].){.  const c
a040: 68 61 72 20 2a 7a 4e 61 6d 65 3b 20 20 20 20 20  har *zName;     
a050: 20 20 20 20 20 20 20 20 20 2f 2a 20 4e 61 6d 65           /* Name
a060: 20 6f 66 20 6e 65 77 20 6d 75 6c 74 69 70 6c 65   of new multiple
a070: 78 20 56 46 53 20 2a 2f 0a 20 20 69 6e 74 20 6d  x VFS */.  int m
a080: 61 6b 65 44 65 66 61 75 6c 74 3b 20 20 20 20 20  akeDefault;     
a090: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 54 72             /* Tr
a0a0: 75 65 20 74 6f 20 6d 61 6b 65 20 74 68 65 20 6e  ue to make the n
a0b0: 65 77 20 56 46 53 20 74 68 65 20 64 65 66 61 75  ew VFS the defau
a0c0: 6c 74 20 2a 2f 0a 20 20 69 6e 74 20 72 63 3b 20  lt */.  int rc; 
a0d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a0e0: 20 20 20 20 20 20 20 20 2f 2a 20 56 61 6c 75 65          /* Value
a0f0: 20 72 65 74 75 72 6e 65 64 20 62 79 20 6d 75 6c   returned by mul
a100: 74 69 70 6c 65 78 5f 69 6e 69 74 69 61 6c 69 7a  tiplex_initializ
a110: 65 28 29 20 2a 2f 0a 0a 20 20 55 4e 55 53 45 44  e() */..  UNUSED
a120: 5f 50 41 52 41 4d 45 54 45 52 28 63 6c 69 65 6e  _PARAMETER(clien
a130: 74 44 61 74 61 29 3b 0a 0a 20 20 2f 2a 20 50 72  tData);..  /* Pr
a140: 6f 63 65 73 73 20 61 72 67 75 6d 65 6e 74 73 20  ocess arguments 
a150: 2a 2f 0a 20 20 69 66 28 20 6f 62 6a 63 21 3d 33  */.  if( objc!=3
a160: 20 29 7b 0a 20 20 20 20 54 63 6c 5f 57 72 6f 6e   ){.    Tcl_Wron
a170: 67 4e 75 6d 41 72 67 73 28 69 6e 74 65 72 70 2c  gNumArgs(interp,
a180: 20 31 2c 20 6f 62 6a 76 2c 20 22 4e 41 4d 45 20   1, objv, "NAME 
a190: 4d 41 4b 45 44 45 46 41 55 4c 54 22 29 3b 0a 20  MAKEDEFAULT");. 
a1a0: 20 20 20 72 65 74 75 72 6e 20 54 43 4c 5f 45 52     return TCL_ER
a1b0: 52 4f 52 3b 0a 20 20 7d 0a 20 20 7a 4e 61 6d 65  ROR;.  }.  zName
a1c0: 20 3d 20 54 63 6c 5f 47 65 74 53 74 72 69 6e 67   = Tcl_GetString
a1d0: 28 6f 62 6a 76 5b 31 5d 29 3b 0a 20 20 69 66 28  (objv[1]);.  if(
a1e0: 20 54 63 6c 5f 47 65 74 42 6f 6f 6c 65 61 6e 46   Tcl_GetBooleanF
a1f0: 72 6f 6d 4f 62 6a 28 69 6e 74 65 72 70 2c 20 6f  romObj(interp, o
a200: 62 6a 76 5b 32 5d 2c 20 26 6d 61 6b 65 44 65 66  bjv[2], &makeDef
a210: 61 75 6c 74 29 20 29 20 72 65 74 75 72 6e 20 54  ault) ) return T
a220: 43 4c 5f 45 52 52 4f 52 3b 0a 20 20 69 66 28 20  CL_ERROR;.  if( 
a230: 7a 4e 61 6d 65 5b 30 5d 3d 3d 27 5c 30 27 20 29  zName[0]=='\0' )
a240: 20 7a 4e 61 6d 65 20 3d 20 30 3b 0a 0a 20 20 2f   zName = 0;..  /
a250: 2a 20 43 61 6c 6c 20 73 71 6c 69 74 65 33 5f 6d  * Call sqlite3_m
a260: 75 6c 74 69 70 6c 65 78 5f 69 6e 69 74 69 61 6c  ultiplex_initial
a270: 69 7a 65 28 29 20 2a 2f 0a 20 20 72 63 20 3d 20  ize() */.  rc = 
a280: 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65  sqlite3_multiple
a290: 78 5f 69 6e 69 74 69 61 6c 69 7a 65 28 7a 4e 61  x_initialize(zNa
a2a0: 6d 65 2c 20 6d 61 6b 65 44 65 66 61 75 6c 74 29  me, makeDefault)
a2b0: 3b 0a 20 20 54 63 6c 5f 53 65 74 52 65 73 75 6c  ;.  Tcl_SetResul
a2c0: 74 28 69 6e 74 65 72 70 2c 20 28 63 68 61 72 20  t(interp, (char 
a2d0: 2a 29 73 71 6c 69 74 65 33 45 72 72 4e 61 6d 65  *)sqlite3ErrName
a2e0: 28 72 63 29 2c 20 54 43 4c 5f 53 54 41 54 49 43  (rc), TCL_STATIC
a2f0: 29 3b 0a 0a 20 20 72 65 74 75 72 6e 20 54 43 4c  );..  return TCL
a300: 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 74 63  _OK;.}../*.** tc
a310: 6c 63 6d 64 3a 20 73 71 6c 69 74 65 33 5f 6d 75  lcmd: sqlite3_mu
a320: 6c 74 69 70 6c 65 78 5f 73 68 75 74 64 6f 77 6e  ltiplex_shutdown
a330: 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 74  .*/.static int t
a340: 65 73 74 5f 6d 75 6c 74 69 70 6c 65 78 5f 73 68  est_multiplex_sh
a350: 75 74 64 6f 77 6e 28 0a 20 20 76 6f 69 64 20 2a  utdown(.  void *
a360: 20 63 6c 69 65 6e 74 44 61 74 61 2c 0a 20 20 54   clientData,.  T
a370: 63 6c 5f 49 6e 74 65 72 70 20 2a 69 6e 74 65 72  cl_Interp *inter
a380: 70 2c 0a 20 20 69 6e 74 20 6f 62 6a 63 2c 0a 20  p,.  int objc,. 
a390: 20 54 63 6c 5f 4f 62 6a 20 2a 43 4f 4e 53 54 20   Tcl_Obj *CONST 
a3a0: 6f 62 6a 76 5b 5d 0a 29 7b 0a 20 20 69 6e 74 20  objv[].){.  int 
a3b0: 72 63 3b 20 20 20 20 20 20 20 20 20 20 20 20 20  rc;             
a3c0: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 56              /* V
a3d0: 61 6c 75 65 20 72 65 74 75 72 6e 65 64 20 62 79  alue returned by
a3e0: 20 6d 75 6c 74 69 70 6c 65 78 5f 73 68 75 74 64   multiplex_shutd
a3f0: 6f 77 6e 28 29 20 2a 2f 0a 0a 20 20 55 4e 55 53  own() */..  UNUS
a400: 45 44 5f 50 41 52 41 4d 45 54 45 52 28 63 6c 69  ED_PARAMETER(cli
a410: 65 6e 74 44 61 74 61 29 3b 0a 0a 20 20 69 66 28  entData);..  if(
a420: 20 6f 62 6a 63 21 3d 31 20 29 7b 0a 20 20 20 20   objc!=1 ){.    
a430: 54 63 6c 5f 57 72 6f 6e 67 4e 75 6d 41 72 67 73  Tcl_WrongNumArgs
a440: 28 69 6e 74 65 72 70 2c 20 31 2c 20 6f 62 6a 76  (interp, 1, objv
a450: 2c 20 22 22 29 3b 0a 20 20 20 20 72 65 74 75 72  , "");.    retur
a460: 6e 20 54 43 4c 5f 45 52 52 4f 52 3b 0a 20 20 7d  n TCL_ERROR;.  }
a470: 0a 0a 20 20 2f 2a 20 43 61 6c 6c 20 73 71 6c 69  ..  /* Call sqli
a480: 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 73 68  te3_multiplex_sh
a490: 75 74 64 6f 77 6e 28 29 20 2a 2f 0a 20 20 72 63  utdown() */.  rc
a4a0: 20 3d 20 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69   = sqlite3_multi
a4b0: 70 6c 65 78 5f 73 68 75 74 64 6f 77 6e 28 29 3b  plex_shutdown();
a4c0: 0a 20 20 54 63 6c 5f 53 65 74 52 65 73 75 6c 74  .  Tcl_SetResult
a4d0: 28 69 6e 74 65 72 70 2c 20 28 63 68 61 72 20 2a  (interp, (char *
a4e0: 29 73 71 6c 69 74 65 33 45 72 72 4e 61 6d 65 28  )sqlite3ErrName(
a4f0: 72 63 29 2c 20 54 43 4c 5f 53 54 41 54 49 43 29  rc), TCL_STATIC)
a500: 3b 0a 0a 20 20 72 65 74 75 72 6e 20 54 43 4c 5f  ;..  return TCL_
a510: 4f 4b 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 74 63 6c  OK;.}../*.** tcl
a520: 63 6d 64 3a 20 20 73 71 6c 69 74 65 33 5f 6d 75  cmd:  sqlite3_mu
a530: 6c 74 69 70 6c 65 78 5f 64 75 6d 70 0a 2a 2f 0a  ltiplex_dump.*/.
a540: 73 74 61 74 69 63 20 69 6e 74 20 74 65 73 74 5f  static int test_
a550: 6d 75 6c 74 69 70 6c 65 78 5f 64 75 6d 70 28 0a  multiplex_dump(.
a560: 20 20 76 6f 69 64 20 2a 20 63 6c 69 65 6e 74 44    void * clientD
a570: 61 74 61 2c 0a 20 20 54 63 6c 5f 49 6e 74 65 72  ata,.  Tcl_Inter
a580: 70 20 2a 69 6e 74 65 72 70 2c 0a 20 20 69 6e 74  p *interp,.  int
a590: 20 6f 62 6a 63 2c 0a 20 20 54 63 6c 5f 4f 62 6a   objc,.  Tcl_Obj
a5a0: 20 2a 43 4f 4e 53 54 20 6f 62 6a 76 5b 5d 0a 29   *CONST objv[].)
a5b0: 7b 0a 20 20 54 63 6c 5f 4f 62 6a 20 2a 70 52 65  {.  Tcl_Obj *pRe
a5c0: 73 75 6c 74 3b 0a 20 20 54 63 6c 5f 4f 62 6a 20  sult;.  Tcl_Obj 
a5d0: 2a 70 47 72 6f 75 70 54 65 72 6d 3b 0a 20 20 6d  *pGroupTerm;.  m
a5e0: 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 2a 70  ultiplexGroup *p
a5f0: 47 72 6f 75 70 3b 0a 20 20 69 6e 74 20 69 3b 0a  Group;.  int i;.
a600: 20 20 69 6e 74 20 6e 43 68 75 6e 6b 73 20 3d 20    int nChunks = 
a610: 30 3b 0a 0a 20 20 55 4e 55 53 45 44 5f 50 41 52  0;..  UNUSED_PAR
a620: 41 4d 45 54 45 52 28 63 6c 69 65 6e 74 44 61 74  AMETER(clientDat
a630: 61 29 3b 0a 20 20 55 4e 55 53 45 44 5f 50 41 52  a);.  UNUSED_PAR
a640: 41 4d 45 54 45 52 28 6f 62 6a 63 29 3b 0a 20 20  AMETER(objc);.  
a650: 55 4e 55 53 45 44 5f 50 41 52 41 4d 45 54 45 52  UNUSED_PARAMETER
a660: 28 6f 62 6a 76 29 3b 0a 0a 20 20 70 52 65 73 75  (objv);..  pResu
a670: 6c 74 20 3d 20 54 63 6c 5f 4e 65 77 4f 62 6a 28  lt = Tcl_NewObj(
a680: 29 3b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 45 6e  );.  multiplexEn
a690: 74 65 72 28 29 3b 0a 20 20 66 6f 72 28 70 47 72  ter();.  for(pGr
a6a0: 6f 75 70 3d 67 4d 75 6c 74 69 70 6c 65 78 2e 70  oup=gMultiplex.p
a6b0: 47 72 6f 75 70 73 3b 20 70 47 72 6f 75 70 3b 20  Groups; pGroup; 
a6c0: 70 47 72 6f 75 70 3d 70 47 72 6f 75 70 2d 3e 70  pGroup=pGroup->p
a6d0: 4e 65 78 74 29 7b 0a 20 20 20 20 70 47 72 6f 75  Next){.    pGrou
a6e0: 70 54 65 72 6d 20 3d 20 54 63 6c 5f 4e 65 77 4f  pTerm = Tcl_NewO
a6f0: 62 6a 28 29 3b 0a 0a 20 20 20 20 69 66 28 20 70  bj();..    if( p
a700: 47 72 6f 75 70 2d 3e 7a 4e 61 6d 65 20 29 7b 0a  Group->zName ){.
a710: 20 20 20 20 20 20 70 47 72 6f 75 70 2d 3e 7a 4e        pGroup->zN
a720: 61 6d 65 5b 70 47 72 6f 75 70 2d 3e 6e 4e 61 6d  ame[pGroup->nNam
a730: 65 5d 20 3d 20 27 5c 30 27 3b 0a 20 20 20 20 20  e] = '\0';.     
a740: 20 54 63 6c 5f 4c 69 73 74 4f 62 6a 41 70 70 65   Tcl_ListObjAppe
a750: 6e 64 45 6c 65 6d 65 6e 74 28 69 6e 74 65 72 70  ndElement(interp
a760: 2c 20 70 47 72 6f 75 70 54 65 72 6d 2c 0a 20 20  , pGroupTerm,.  
a770: 20 20 20 20 20 20 20 20 54 63 6c 5f 4e 65 77 53          Tcl_NewS
a780: 74 72 69 6e 67 4f 62 6a 28 70 47 72 6f 75 70 2d  tringObj(pGroup-
a790: 3e 7a 4e 61 6d 65 2c 20 2d 31 29 29 3b 0a 20 20  >zName, -1));.  
a7a0: 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 54    }else{.      T
a7b0: 63 6c 5f 4c 69 73 74 4f 62 6a 41 70 70 65 6e 64  cl_ListObjAppend
a7c0: 45 6c 65 6d 65 6e 74 28 69 6e 74 65 72 70 2c 20  Element(interp, 
a7d0: 70 47 72 6f 75 70 54 65 72 6d 2c 20 54 63 6c 5f  pGroupTerm, Tcl_
a7e0: 4e 65 77 4f 62 6a 28 29 29 3b 0a 20 20 20 20 7d  NewObj());.    }
a7f0: 0a 20 20 20 20 54 63 6c 5f 4c 69 73 74 4f 62 6a  .    Tcl_ListObj
a800: 41 70 70 65 6e 64 45 6c 65 6d 65 6e 74 28 69 6e  AppendElement(in
a810: 74 65 72 70 2c 20 70 47 72 6f 75 70 54 65 72 6d  terp, pGroupTerm
a820: 2c 0a 20 20 20 20 20 20 20 20 20 20 54 63 6c 5f  ,.          Tcl_
a830: 4e 65 77 49 6e 74 4f 62 6a 28 70 47 72 6f 75 70  NewIntObj(pGroup
a840: 2d 3e 6e 4e 61 6d 65 29 29 3b 0a 20 20 20 20 54  ->nName));.    T
a850: 63 6c 5f 4c 69 73 74 4f 62 6a 41 70 70 65 6e 64  cl_ListObjAppend
a860: 45 6c 65 6d 65 6e 74 28 69 6e 74 65 72 70 2c 20  Element(interp, 
a870: 70 47 72 6f 75 70 54 65 72 6d 2c 0a 20 20 20 20  pGroupTerm,.    
a880: 20 20 20 20 20 20 54 63 6c 5f 4e 65 77 49 6e 74        Tcl_NewInt
a890: 4f 62 6a 28 70 47 72 6f 75 70 2d 3e 66 6c 61 67  Obj(pGroup->flag
a8a0: 73 29 29 3b 0a 0a 20 20 20 20 2f 2a 20 63 6f 75  s));..    /* cou
a8b0: 6e 74 20 6e 75 6d 62 65 72 20 6f 66 20 63 68 75  nt number of chu
a8c0: 6e 6b 73 20 77 69 74 68 20 6f 70 65 6e 20 68 61  nks with open ha
a8d0: 6e 64 6c 65 73 20 2a 2f 0a 20 20 20 20 66 6f 72  ndles */.    for
a8e0: 28 69 3d 30 3b 20 69 3c 70 47 72 6f 75 70 2d 3e  (i=0; i<pGroup->
a8f0: 6e 52 65 61 6c 3b 20 69 2b 2b 29 7b 0a 20 20 20  nReal; i++){.   
a900: 20 20 20 69 66 28 20 70 47 72 6f 75 70 2d 3e 61     if( pGroup->a
a910: 52 65 61 6c 5b 69 5d 2e 70 21 3d 30 20 29 20 6e  Real[i].p!=0 ) n
a920: 43 68 75 6e 6b 73 2b 2b 3b 0a 20 20 20 20 7d 0a  Chunks++;.    }.
a930: 20 20 20 20 54 63 6c 5f 4c 69 73 74 4f 62 6a 41      Tcl_ListObjA
a940: 70 70 65 6e 64 45 6c 65 6d 65 6e 74 28 69 6e 74  ppendElement(int
a950: 65 72 70 2c 20 70 47 72 6f 75 70 54 65 72 6d 2c  erp, pGroupTerm,
a960: 0a 20 20 20 20 20 20 20 20 20 20 54 63 6c 5f 4e  .          Tcl_N
a970: 65 77 49 6e 74 4f 62 6a 28 6e 43 68 75 6e 6b 73  ewIntObj(nChunks
a980: 29 29 3b 0a 0a 20 20 20 20 54 63 6c 5f 4c 69 73  ));..    Tcl_Lis
a990: 74 4f 62 6a 41 70 70 65 6e 64 45 6c 65 6d 65 6e  tObjAppendElemen
a9a0: 74 28 69 6e 74 65 72 70 2c 20 70 47 72 6f 75 70  t(interp, pGroup
a9b0: 54 65 72 6d 2c 0a 20 20 20 20 20 20 20 20 20 20  Term,.          
a9c0: 54 63 6c 5f 4e 65 77 49 6e 74 4f 62 6a 28 70 47  Tcl_NewIntObj(pG
a9d0: 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 29 29 3b  roup->szChunk));
a9e0: 0a 20 20 20 20 54 63 6c 5f 4c 69 73 74 4f 62 6a  .    Tcl_ListObj
a9f0: 41 70 70 65 6e 64 45 6c 65 6d 65 6e 74 28 69 6e  AppendElement(in
aa00: 74 65 72 70 2c 20 70 47 72 6f 75 70 54 65 72 6d  terp, pGroupTerm
aa10: 2c 0a 20 20 20 20 20 20 20 20 20 20 54 63 6c 5f  ,.          Tcl_
aa20: 4e 65 77 49 6e 74 4f 62 6a 28 70 47 72 6f 75 70  NewIntObj(pGroup
aa30: 2d 3e 6e 52 65 61 6c 29 29 3b 0a 0a 20 20 20 20  ->nReal));..    
aa40: 54 63 6c 5f 4c 69 73 74 4f 62 6a 41 70 70 65 6e  Tcl_ListObjAppen
aa50: 64 45 6c 65 6d 65 6e 74 28 69 6e 74 65 72 70 2c  dElement(interp,
aa60: 20 70 52 65 73 75 6c 74 2c 20 70 47 72 6f 75 70   pResult, pGroup
aa70: 54 65 72 6d 29 3b 0a 20 20 7d 0a 20 20 6d 75 6c  Term);.  }.  mul
aa80: 74 69 70 6c 65 78 4c 65 61 76 65 28 29 3b 0a 20  tiplexLeave();. 
aa90: 20 54 63 6c 5f 53 65 74 4f 62 6a 52 65 73 75 6c   Tcl_SetObjResul
aaa0: 74 28 69 6e 74 65 72 70 2c 20 70 52 65 73 75 6c  t(interp, pResul
aab0: 74 29 3b 0a 20 20 72 65 74 75 72 6e 20 54 43 4c  t);.  return TCL
aac0: 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54 63  _OK;.}../*.** Tc
aad0: 6c 63 6d 64 3a 20 74 65 73 74 5f 6d 75 6c 74 69  lcmd: test_multi
aae0: 70 6c 65 78 5f 63 6f 6e 74 72 6f 6c 20 48 41 4e  plex_control HAN
aaf0: 44 4c 45 20 44 42 4e 41 4d 45 20 53 55 42 2d 43  DLE DBNAME SUB-C
ab00: 4f 4d 4d 41 4e 44 20 3f 49 4e 54 2d 56 41 4c 55  OMMAND ?INT-VALU
ab10: 45 3f 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74  E?.*/.static int
ab20: 20 74 65 73 74 5f 6d 75 6c 74 69 70 6c 65 78 5f   test_multiplex_
ab30: 63 6f 6e 74 72 6f 6c 28 0a 20 20 43 6c 69 65 6e  control(.  Clien
ab40: 74 44 61 74 61 20 63 64 2c 0a 20 20 54 63 6c 5f  tData cd,.  Tcl_
ab50: 49 6e 74 65 72 70 20 2a 69 6e 74 65 72 70 2c 0a  Interp *interp,.
ab60: 20 20 69 6e 74 20 6f 62 6a 63 2c 0a 20 20 54 63    int objc,.  Tc
ab70: 6c 5f 4f 62 6a 20 2a 43 4f 4e 53 54 20 6f 62 6a  l_Obj *CONST obj
ab80: 76 5b 5d 0a 29 7b 0a 20 20 69 6e 74 20 72 63 3b  v[].){.  int rc;
ab90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
aba0: 20 20 20 20 20 20 20 20 20 2f 2a 20 52 65 74 75           /* Retu
abb0: 72 6e 20 63 6f 64 65 20 66 72 6f 6d 20 66 69 6c  rn code from fil
abc0: 65 5f 63 6f 6e 74 72 6f 6c 28 29 20 2a 2f 0a 20  e_control() */. 
abd0: 20 69 6e 74 20 69 64 78 3b 20 20 20 20 20 20 20   int idx;       
abe0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
abf0: 20 2f 2a 20 49 6e 64 65 78 20 69 6e 20 61 53 75   /* Index in aSu
ac00: 62 5b 5d 20 2a 2f 0a 20 20 54 63 6c 5f 43 6d 64  b[] */.  Tcl_Cmd
ac10: 49 6e 66 6f 20 63 6d 64 49 6e 66 6f 3b 20 20 20  Info cmdInfo;   
ac20: 20 20 20 20 20 20 20 20 20 2f 2a 20 43 6f 6d 6d           /* Comm
ac30: 61 6e 64 20 69 6e 66 6f 20 73 74 72 75 63 74 75  and info structu
ac40: 72 65 20 66 6f 72 20 48 41 4e 44 4c 45 20 2a 2f  re for HANDLE */
ac50: 0a 20 20 73 71 6c 69 74 65 33 20 2a 64 62 3b 20  .  sqlite3 *db; 
ac60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
ac70: 20 20 20 2f 2a 20 55 6e 64 65 72 6c 79 69 6e 67     /* Underlying
ac80: 20 64 62 20 68 61 6e 64 6c 65 20 66 6f 72 20 48   db handle for H
ac90: 41 4e 44 4c 45 20 2a 2f 0a 20 20 69 6e 74 20 69  ANDLE */.  int i
aca0: 56 61 6c 75 65 20 3d 20 30 3b 0a 20 20 76 6f 69  Value = 0;.  voi
acb0: 64 20 2a 70 41 72 67 20 3d 20 30 3b 0a 0a 20 20  d *pArg = 0;..  
acc0: 73 74 72 75 63 74 20 53 75 62 43 6f 6d 6d 61 6e  struct SubComman
acd0: 64 20 7b 0a 20 20 20 20 63 6f 6e 73 74 20 63 68  d {.    const ch
ace0: 61 72 20 2a 7a 4e 61 6d 65 3b 0a 20 20 20 20 69  ar *zName;.    i
acf0: 6e 74 20 6f 70 3b 0a 20 20 20 20 69 6e 74 20 61  nt op;.    int a
ad00: 72 67 74 79 70 65 3b 0a 20 20 7d 20 61 53 75 62  rgtype;.  } aSub
ad10: 5b 5d 20 3d 20 7b 0a 20 20 20 20 7b 20 22 65 6e  [] = {.    { "en
ad20: 61 62 6c 65 22 2c 20 20 20 20 20 20 20 4d 55 4c  able",       MUL
ad30: 54 49 50 4c 45 58 5f 43 54 52 4c 5f 45 4e 41 42  TIPLEX_CTRL_ENAB
ad40: 4c 45 2c 20 20 20 20 20 20 20 20 20 20 20 31 20  LE,           1 
ad50: 7d 2c 0a 20 20 20 20 7b 20 22 63 68 75 6e 6b 5f  },.    { "chunk_
ad60: 73 69 7a 65 22 2c 20 20 20 4d 55 4c 54 49 50 4c  size",   MULTIPL
ad70: 45 58 5f 43 54 52 4c 5f 53 45 54 5f 43 48 55 4e  EX_CTRL_SET_CHUN
ad80: 4b 5f 53 49 5a 45 2c 20 20 20 31 20 7d 2c 0a 20  K_SIZE,   1 },. 
ad90: 20 20 20 7b 20 22 6d 61 78 5f 63 68 75 6e 6b 73     { "max_chunks
ada0: 22 2c 20 20 20 4d 55 4c 54 49 50 4c 45 58 5f 43  ",   MULTIPLEX_C
adb0: 54 52 4c 5f 53 45 54 5f 4d 41 58 5f 43 48 55 4e  TRL_SET_MAX_CHUN
adc0: 4b 53 2c 20 20 20 31 20 7d 2c 0a 20 20 20 20 7b  KS,   1 },.    {
add0: 20 30 2c 20 30 2c 20 30 20 7d 0a 20 20 7d 3b 0a   0, 0, 0 }.  };.
ade0: 0a 20 20 69 66 28 20 6f 62 6a 63 21 3d 35 20 29  .  if( objc!=5 )
adf0: 7b 0a 20 20 20 20 54 63 6c 5f 57 72 6f 6e 67 4e  {.    Tcl_WrongN
ae00: 75 6d 41 72 67 73 28 69 6e 74 65 72 70 2c 20 31  umArgs(interp, 1
ae10: 2c 20 6f 62 6a 76 2c 20 22 48 41 4e 44 4c 45 20  , objv, "HANDLE 
ae20: 44 42 4e 41 4d 45 20 53 55 42 2d 43 4f 4d 4d 41  DBNAME SUB-COMMA
ae30: 4e 44 20 49 4e 54 2d 56 41 4c 55 45 22 29 3b 0a  ND INT-VALUE");.
ae40: 20 20 20 20 72 65 74 75 72 6e 20 54 43 4c 5f 45      return TCL_E
ae50: 52 52 4f 52 3b 0a 20 20 7d 0a 0a 20 20 69 66 28  RROR;.  }..  if(
ae60: 20 30 3d 3d 54 63 6c 5f 47 65 74 43 6f 6d 6d 61   0==Tcl_GetComma
ae70: 6e 64 49 6e 66 6f 28 69 6e 74 65 72 70 2c 20 54  ndInfo(interp, T
ae80: 63 6c 5f 47 65 74 53 74 72 69 6e 67 28 6f 62 6a  cl_GetString(obj
ae90: 76 5b 31 5d 29 2c 20 26 63 6d 64 49 6e 66 6f 29  v[1]), &cmdInfo)
aea0: 20 29 7b 0a 20 20 20 20 54 63 6c 5f 41 70 70 65   ){.    Tcl_Appe
aeb0: 6e 64 52 65 73 75 6c 74 28 69 6e 74 65 72 70 2c  ndResult(interp,
aec0: 20 22 65 78 70 65 63 74 65 64 20 64 61 74 61 62   "expected datab
aed0: 61 73 65 20 68 61 6e 64 6c 65 2c 20 67 6f 74 20  ase handle, got 
aee0: 5c 22 22 2c 20 30 29 3b 0a 20 20 20 20 54 63 6c  \"", 0);.    Tcl
aef0: 5f 41 70 70 65 6e 64 52 65 73 75 6c 74 28 69 6e  _AppendResult(in
af00: 74 65 72 70 2c 20 54 63 6c 5f 47 65 74 53 74 72  terp, Tcl_GetStr
af10: 69 6e 67 28 6f 62 6a 76 5b 31 5d 29 2c 20 22 5c  ing(objv[1]), "\
af20: 22 22 2c 20 30 29 3b 0a 20 20 20 20 72 65 74 75  "", 0);.    retu
af30: 72 6e 20 54 43 4c 5f 45 52 52 4f 52 3b 0a 20 20  rn TCL_ERROR;.  
af40: 7d 65 6c 73 65 7b 0a 20 20 20 20 64 62 20 3d 20  }else{.    db = 
af50: 2a 28 73 71 6c 69 74 65 33 20 2a 2a 29 63 6d 64  *(sqlite3 **)cmd
af60: 49 6e 66 6f 2e 6f 62 6a 43 6c 69 65 6e 74 44 61  Info.objClientDa
af70: 74 61 3b 0a 20 20 7d 0a 0a 20 20 72 63 20 3d 20  ta;.  }..  rc = 
af80: 54 63 6c 5f 47 65 74 49 6e 64 65 78 46 72 6f 6d  Tcl_GetIndexFrom
af90: 4f 62 6a 53 74 72 75 63 74 28 0a 20 20 20 20 20  ObjStruct(.     
afa0: 20 69 6e 74 65 72 70 2c 20 6f 62 6a 76 5b 33 5d   interp, objv[3]
afb0: 2c 20 61 53 75 62 2c 20 73 69 7a 65 6f 66 28 61  , aSub, sizeof(a
afc0: 53 75 62 5b 30 5d 29 2c 20 22 73 75 62 2d 63 6f  Sub[0]), "sub-co
afd0: 6d 6d 61 6e 64 22 2c 20 30 2c 20 26 69 64 78 0a  mmand", 0, &idx.
afe0: 20 20 29 3b 0a 20 20 69 66 28 20 72 63 21 3d 54    );.  if( rc!=T
aff0: 43 4c 5f 4f 4b 20 29 20 72 65 74 75 72 6e 20 72  CL_OK ) return r
b000: 63 3b 0a 0a 20 20 73 77 69 74 63 68 28 20 61 53  c;..  switch( aS
b010: 75 62 5b 69 64 78 5d 2e 61 72 67 74 79 70 65 20  ub[idx].argtype 
b020: 29 7b 0a 20 20 20 20 63 61 73 65 20 31 3a 0a 20  ){.    case 1:. 
b030: 20 20 20 20 20 69 66 28 20 54 63 6c 5f 47 65 74       if( Tcl_Get
b040: 49 6e 74 46 72 6f 6d 4f 62 6a 28 69 6e 74 65 72  IntFromObj(inter
b050: 70 2c 20 6f 62 6a 76 5b 34 5d 2c 20 26 69 56 61  p, objv[4], &iVa
b060: 6c 75 65 29 20 29 7b 0a 20 20 20 20 20 20 20 20  lue) ){.        
b070: 72 65 74 75 72 6e 20 54 43 4c 5f 45 52 52 4f 52  return TCL_ERROR
b080: 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20  ;.      }.      
b090: 70 41 72 67 20 3d 20 28 76 6f 69 64 20 2a 29 26  pArg = (void *)&
b0a0: 69 56 61 6c 75 65 3b 0a 20 20 20 20 20 20 62 72  iValue;.      br
b0b0: 65 61 6b 3b 0a 20 20 20 20 64 65 66 61 75 6c 74  eak;.    default
b0c0: 3a 0a 20 20 20 20 20 20 54 63 6c 5f 57 72 6f 6e  :.      Tcl_Wron
b0d0: 67 4e 75 6d 41 72 67 73 28 69 6e 74 65 72 70 2c  gNumArgs(interp,
b0e0: 20 34 2c 20 6f 62 6a 76 2c 20 22 53 55 42 2d 43   4, objv, "SUB-C
b0f0: 4f 4d 4d 41 4e 44 22 29 3b 0a 20 20 20 20 20 20  OMMAND");.      
b100: 72 65 74 75 72 6e 20 54 43 4c 5f 45 52 52 4f 52  return TCL_ERROR
b110: 3b 0a 20 20 7d 0a 0a 20 20 72 63 20 3d 20 73 71  ;.  }..  rc = sq
b120: 6c 69 74 65 33 5f 66 69 6c 65 5f 63 6f 6e 74 72  lite3_file_contr
b130: 6f 6c 28 64 62 2c 20 54 63 6c 5f 47 65 74 53 74  ol(db, Tcl_GetSt
b140: 72 69 6e 67 28 6f 62 6a 76 5b 32 5d 29 2c 20 61  ring(objv[2]), a
b150: 53 75 62 5b 69 64 78 5d 2e 6f 70 2c 20 70 41 72  Sub[idx].op, pAr
b160: 67 29 3b 0a 20 20 54 63 6c 5f 53 65 74 52 65 73  g);.  Tcl_SetRes
b170: 75 6c 74 28 69 6e 74 65 72 70 2c 20 28 63 68 61  ult(interp, (cha
b180: 72 20 2a 29 73 71 6c 69 74 65 33 45 72 72 4e 61  r *)sqlite3ErrNa
b190: 6d 65 28 72 63 29 2c 20 54 43 4c 5f 53 54 41 54  me(rc), TCL_STAT
b1a0: 49 43 29 3b 0a 20 20 72 65 74 75 72 6e 20 28 72  IC);.  return (r
b1b0: 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 29 20 3f 20  c==SQLITE_OK) ? 
b1c0: 54 43 4c 5f 4f 4b 20 3a 20 54 43 4c 5f 45 52 52  TCL_OK : TCL_ERR
b1d0: 4f 52 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54 68 69  OR;.}../*.** Thi
b1e0: 73 20 72 6f 75 74 69 6e 65 20 72 65 67 69 73 74  s routine regist
b1f0: 65 72 73 20 74 68 65 20 63 75 73 74 6f 6d 20 54  ers the custom T
b200: 43 4c 20 63 6f 6d 6d 61 6e 64 73 20 64 65 66 69  CL commands defi
b210: 6e 65 64 20 69 6e 20 74 68 69 73 0a 2a 2a 20 6d  ned in this.** m
b220: 6f 64 75 6c 65 2e 20 20 54 68 69 73 20 73 68 6f  odule.  This sho
b230: 75 6c 64 20 62 65 20 74 68 65 20 6f 6e 6c 79 20  uld be the only 
b240: 70 72 6f 63 65 64 75 72 65 20 76 69 73 69 62 6c  procedure visibl
b250: 65 20 66 72 6f 6d 20 6f 75 74 73 69 64 65 0a 2a  e from outside.*
b260: 2a 20 6f 66 20 74 68 69 73 20 6d 6f 64 75 6c 65  * of this module
b270: 2e 0a 2a 2f 0a 69 6e 74 20 53 71 6c 69 74 65 6d  ..*/.int Sqlitem
b280: 75 6c 74 69 70 6c 65 78 5f 49 6e 69 74 28 54 63  ultiplex_Init(Tc
b290: 6c 5f 49 6e 74 65 72 70 20 2a 69 6e 74 65 72 70  l_Interp *interp
b2a0: 29 7b 0a 20 20 73 74 61 74 69 63 20 73 74 72 75  ){.  static stru
b2b0: 63 74 20 7b 0a 20 20 20 20 20 63 68 61 72 20 2a  ct {.     char *
b2c0: 7a 4e 61 6d 65 3b 0a 20 20 20 20 20 54 63 6c 5f  zName;.     Tcl_
b2d0: 4f 62 6a 43 6d 64 50 72 6f 63 20 2a 78 50 72 6f  ObjCmdProc *xPro
b2e0: 63 3b 0a 20 20 7d 20 61 43 6d 64 5b 5d 20 3d 20  c;.  } aCmd[] = 
b2f0: 7b 0a 20 20 20 20 7b 20 22 73 71 6c 69 74 65 33  {.    { "sqlite3
b300: 5f 6d 75 6c 74 69 70 6c 65 78 5f 69 6e 69 74 69  _multiplex_initi
b310: 61 6c 69 7a 65 22 2c 20 74 65 73 74 5f 6d 75 6c  alize", test_mul
b320: 74 69 70 6c 65 78 5f 69 6e 69 74 69 61 6c 69 7a  tiplex_initializ
b330: 65 20 7d 2c 0a 20 20 20 20 7b 20 22 73 71 6c 69  e },.    { "sqli
b340: 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 73 68  te3_multiplex_sh
b350: 75 74 64 6f 77 6e 22 2c 20 74 65 73 74 5f 6d 75  utdown", test_mu
b360: 6c 74 69 70 6c 65 78 5f 73 68 75 74 64 6f 77 6e  ltiplex_shutdown
b370: 20 7d 2c 0a 20 20 20 20 7b 20 22 73 71 6c 69 74   },.    { "sqlit
b380: 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 64 75 6d  e3_multiplex_dum
b390: 70 22 2c 20 74 65 73 74 5f 6d 75 6c 74 69 70 6c  p", test_multipl
b3a0: 65 78 5f 64 75 6d 70 20 7d 2c 0a 20 20 20 20 7b  ex_dump },.    {
b3b0: 20 22 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70   "sqlite3_multip
b3c0: 6c 65 78 5f 63 6f 6e 74 72 6f 6c 22 2c 20 74 65  lex_control", te
b3d0: 73 74 5f 6d 75 6c 74 69 70 6c 65 78 5f 63 6f 6e  st_multiplex_con
b3e0: 74 72 6f 6c 20 7d 2c 0a 20 20 7d 3b 0a 20 20 69  trol },.  };.  i
b3f0: 6e 74 20 69 3b 0a 0a 20 20 66 6f 72 28 69 3d 30  nt i;..  for(i=0
b400: 3b 20 69 3c 73 69 7a 65 6f 66 28 61 43 6d 64 29  ; i<sizeof(aCmd)
b410: 2f 73 69 7a 65 6f 66 28 61 43 6d 64 5b 30 5d 29  /sizeof(aCmd[0])
b420: 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 54 63 6c 5f  ; i++){.    Tcl_
b430: 43 72 65 61 74 65 4f 62 6a 43 6f 6d 6d 61 6e 64  CreateObjCommand
b440: 28 69 6e 74 65 72 70 2c 20 61 43 6d 64 5b 69 5d  (interp, aCmd[i]
b450: 2e 7a 4e 61 6d 65 2c 20 61 43 6d 64 5b 69 5d 2e  .zName, aCmd[i].
b460: 78 50 72 6f 63 2c 20 30 2c 20 30 29 3b 0a 20 20  xProc, 0, 0);.  
b470: 7d 0a 0a 20 20 72 65 74 75 72 6e 20 54 43 4c 5f  }..  return TCL_
b480: 4f 4b 3b 0a 7d 0a 23 65 6e 64 69 66 0a           OK;.}.#endif.