/ Hex Artifact Content
Login

Artifact 31fb992ab388a23813c0cb003dc3c0463aa149ac:


0000: 2f 2a 0a 2a 2a 20 32 30 31 30 20 4f 63 74 6f 62  /*.** 2010 Octob
0010: 65 72 20 32 38 0a 2a 2a 0a 2a 2a 20 54 68 65 20  er 28.**.** The 
0020: 61 75 74 68 6f 72 20 64 69 73 63 6c 61 69 6d 73  author disclaims
0030: 20 63 6f 70 79 72 69 67 68 74 20 74 6f 20 74 68   copyright to th
0040: 69 73 20 73 6f 75 72 63 65 20 63 6f 64 65 2e 20  is source code. 
0050: 20 49 6e 20 70 6c 61 63 65 20 6f 66 0a 2a 2a 20   In place of.** 
0060: 61 20 6c 65 67 61 6c 20 6e 6f 74 69 63 65 2c 20  a legal notice, 
0070: 68 65 72 65 20 69 73 20 61 20 62 6c 65 73 73 69  here is a blessi
0080: 6e 67 3a 0a 2a 2a 0a 2a 2a 20 20 20 20 4d 61 79  ng:.**.**    May
0090: 20 79 6f 75 20 64 6f 20 67 6f 6f 64 20 61 6e 64   you do good and
00a0: 20 6e 6f 74 20 65 76 69 6c 2e 0a 2a 2a 20 20 20   not evil..**   
00b0: 20 4d 61 79 20 79 6f 75 20 66 69 6e 64 20 66 6f   May you find fo
00c0: 72 67 69 76 65 6e 65 73 73 20 66 6f 72 20 79 6f  rgiveness for yo
00d0: 75 72 73 65 6c 66 20 61 6e 64 20 66 6f 72 67 69  urself and forgi
00e0: 76 65 20 6f 74 68 65 72 73 2e 0a 2a 2a 20 20 20  ve others..**   
00f0: 20 4d 61 79 20 79 6f 75 20 73 68 61 72 65 20 66   May you share f
0100: 72 65 65 6c 79 2c 20 6e 65 76 65 72 20 74 61 6b  reely, never tak
0110: 69 6e 67 20 6d 6f 72 65 20 74 68 61 6e 20 79 6f  ing more than yo
0120: 75 20 67 69 76 65 2e 0a 2a 2a 0a 2a 2a 2a 2a 2a  u give..**.*****
0130: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0140: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0150: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0160: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0170: 2a 2a 2a 2a 0a 2a 2a 0a 2a 2a 20 54 68 69 73 20  ****.**.** This 
0180: 66 69 6c 65 20 63 6f 6e 74 61 69 6e 73 20 61 20  file contains a 
0190: 56 46 53 20 22 73 68 69 6d 22 20 2d 20 61 20 6c  VFS "shim" - a l
01a0: 61 79 65 72 20 74 68 61 74 20 73 69 74 73 20 69  ayer that sits i
01b0: 6e 20 62 65 74 77 65 65 6e 20 74 68 65 0a 2a 2a  n between the.**
01c0: 20 70 61 67 65 72 20 61 6e 64 20 74 68 65 20 72   pager and the r
01d0: 65 61 6c 20 56 46 53 20 2d 20 74 68 61 74 20 62  eal VFS - that b
01e0: 72 65 61 6b 73 20 75 70 20 61 20 76 65 72 79 20  reaks up a very 
01f0: 6c 61 72 67 65 20 64 61 74 61 62 61 73 65 20 66  large database f
0200: 69 6c 65 0a 2a 2a 20 69 6e 74 6f 20 74 77 6f 20  ile.** into two 
0210: 6f 72 20 6d 6f 72 65 20 73 6d 61 6c 6c 65 72 20  or more smaller 
0220: 66 69 6c 65 73 20 6f 6e 20 64 69 73 6b 2e 20 20  files on disk.  
0230: 54 68 69 73 20 69 73 20 75 73 65 66 75 6c 2c 20  This is useful, 
0240: 66 6f 72 20 65 78 61 6d 70 6c 65 2c 0a 2a 2a 20  for example,.** 
0250: 69 6e 20 6f 72 64 65 72 20 74 6f 20 73 75 70 70  in order to supp
0260: 6f 72 74 20 6c 61 72 67 65 2c 20 6d 75 6c 74 69  ort large, multi
0270: 2d 67 69 67 61 62 79 74 65 20 64 61 74 61 62 61  -gigabyte databa
0280: 73 65 73 20 6f 6e 20 6f 6c 64 65 72 20 66 69 6c  ses on older fil
0290: 65 73 79 73 74 65 6d 73 0a 2a 2a 20 74 68 61 74  esystems.** that
02a0: 20 6c 69 6d 69 74 20 74 68 65 20 6d 61 78 69 6d   limit the maxim
02b0: 75 6d 20 66 69 6c 65 20 73 69 7a 65 20 74 6f 20  um file size to 
02c0: 32 20 47 69 42 2e 0a 2a 2a 0a 2a 2a 20 55 53 41  2 GiB..**.** USA
02d0: 47 45 3a 0a 2a 2a 0a 2a 2a 20 43 6f 6d 70 69 6c  GE:.**.** Compil
02e0: 65 20 74 68 69 73 20 73 6f 75 72 63 65 20 66 69  e this source fi
02f0: 6c 65 20 61 6e 64 20 6c 69 6e 6b 20 69 74 20 77  le and link it w
0300: 69 74 68 20 79 6f 75 72 20 61 70 70 6c 69 63 61  ith your applica
0310: 74 69 6f 6e 2e 20 20 54 68 65 6e 0a 2a 2a 20 61  tion.  Then.** a
0320: 74 20 73 74 61 72 74 2d 74 69 6d 65 2c 20 69 6e  t start-time, in
0330: 76 6f 6b 65 20 74 68 65 20 66 6f 6c 6c 6f 77 69  voke the followi
0340: 6e 67 20 70 72 6f 63 65 64 75 72 65 3a 0a 2a 2a  ng procedure:.**
0350: 0a 2a 2a 20 20 20 69 6e 74 20 73 71 6c 69 74 65  .**   int sqlite
0360: 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 69 6e 69 74  3_multiplex_init
0370: 69 61 6c 69 7a 65 28 0a 2a 2a 20 20 20 20 20 20  ialize(.**      
0380: 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 4f 72 69  const char *zOri
0390: 67 56 66 73 4e 61 6d 65 2c 20 20 20 20 2f 2f 20  gVfsName,    // 
03a0: 54 68 65 20 75 6e 64 65 72 6c 79 69 6e 67 20 72  The underlying r
03b0: 65 61 6c 20 56 46 53 0a 2a 2a 20 20 20 20 20 20  eal VFS.**      
03c0: 69 6e 74 20 6d 61 6b 65 44 65 66 61 75 6c 74 20  int makeDefault 
03d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2f 20               // 
03e0: 54 72 75 65 20 74 6f 20 6d 61 6b 65 20 6d 75 6c  True to make mul
03f0: 74 69 70 6c 65 78 20 74 68 65 20 64 65 66 61 75  tiplex the defau
0400: 6c 74 20 56 46 53 0a 2a 2a 20 20 20 29 3b 0a 2a  lt VFS.**   );.*
0410: 2a 0a 2a 2a 20 54 68 65 20 70 72 6f 63 65 64 75  *.** The procedu
0420: 72 65 20 63 61 6c 6c 20 61 62 6f 76 65 20 77 69  re call above wi
0430: 6c 6c 20 63 72 65 61 74 65 20 61 6e 64 20 72 65  ll create and re
0440: 67 69 73 74 65 72 20 61 20 6e 65 77 20 56 46 53  gister a new VFS
0450: 20 73 68 69 6d 20 6e 61 6d 65 64 0a 2a 2a 20 22   shim named.** "
0460: 6d 75 6c 74 69 70 6c 65 78 22 2e 20 20 54 68 65  multiplex".  The
0470: 20 6d 75 6c 74 69 70 6c 65 78 20 56 46 53 20 77   multiplex VFS w
0480: 69 6c 6c 20 75 73 65 20 74 68 65 20 56 46 53 20  ill use the VFS 
0490: 6e 61 6d 65 64 20 62 79 20 7a 4f 72 69 67 56 66  named by zOrigVf
04a0: 73 4e 61 6d 65 20 74 6f 0a 2a 2a 20 64 6f 20 74  sName to.** do t
04b0: 68 65 20 61 63 74 75 61 6c 20 64 69 73 6b 20 49  he actual disk I
04c0: 2f 4f 2e 20 20 28 54 68 65 20 7a 4f 72 69 67 56  /O.  (The zOrigV
04d0: 66 73 4e 61 6d 65 20 70 61 72 61 6d 65 74 65 72  fsName parameter
04e0: 20 6d 61 79 20 62 65 20 4e 55 4c 4c 2c 20 69 6e   may be NULL, in
04f0: 20 0a 2a 2a 20 77 68 69 63 68 20 63 61 73 65 20   .** which case 
0500: 74 68 65 20 64 65 66 61 75 6c 74 20 56 46 53 20  the default VFS 
0510: 61 74 20 74 68 65 20 6d 6f 6d 65 6e 74 20 73 71  at the moment sq
0520: 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f  lite3_multiplex_
0530: 69 6e 69 74 69 61 6c 69 7a 65 28 29 0a 2a 2a 20  initialize().** 
0540: 69 73 20 63 61 6c 6c 65 64 20 77 69 6c 6c 20 62  is called will b
0550: 65 20 75 73 65 64 20 61 73 20 74 68 65 20 75 6e  e used as the un
0560: 64 65 72 6c 79 69 6e 67 20 72 65 61 6c 20 56 46  derlying real VF
0570: 53 2e 29 20 20 0a 2a 2a 0a 2a 2a 20 49 66 20 74  S.)  .**.** If t
0580: 68 65 20 6d 61 6b 65 44 65 66 61 75 6c 74 20 70  he makeDefault p
0590: 61 72 61 6d 65 74 65 72 20 69 73 20 54 52 55 45  arameter is TRUE
05a0: 20 74 68 65 6e 20 6d 75 6c 74 69 70 6c 65 78 20   then multiplex 
05b0: 62 65 63 6f 6d 65 73 20 74 68 65 20 6e 65 77 0a  becomes the new.
05c0: 2a 2a 20 64 65 66 61 75 6c 74 20 56 46 53 2e 20  ** default VFS. 
05d0: 20 4f 74 68 65 72 77 69 73 65 2c 20 79 6f 75 20   Otherwise, you 
05e0: 63 61 6e 20 75 73 65 20 74 68 65 20 6d 75 6c 74  can use the mult
05f0: 69 70 6c 65 78 20 56 46 53 20 62 79 20 73 70 65  iplex VFS by spe
0600: 63 69 66 79 69 6e 67 0a 2a 2a 20 22 6d 75 6c 74  cifying.** "mult
0610: 69 70 6c 65 78 22 20 61 73 20 74 68 65 20 34 74  iplex" as the 4t
0620: 68 20 70 61 72 61 6d 65 74 65 72 20 74 6f 20 73  h parameter to s
0630: 71 6c 69 74 65 33 5f 6f 70 65 6e 5f 76 32 28 29  qlite3_open_v2()
0640: 20 6f 72 20 62 79 20 65 6d 70 6c 6f 79 69 6e 67   or by employing
0650: 0a 2a 2a 20 55 52 49 20 66 69 6c 65 6e 61 6d 65  .** URI filename
0660: 73 20 61 6e 64 20 61 64 64 69 6e 67 20 22 76 66  s and adding "vf
0670: 73 3d 6d 75 6c 74 69 70 6c 65 78 22 20 61 73 20  s=multiplex" as 
0680: 61 20 70 61 72 61 6d 65 74 65 72 20 74 6f 20 74  a parameter to t
0690: 68 65 20 66 69 6c 65 6e 61 6d 65 0a 2a 2a 20 55  he filename.** U
06a0: 52 49 2e 0a 2a 2a 0a 2a 2a 20 54 68 65 20 6d 75  RI..**.** The mu
06b0: 6c 74 69 70 6c 65 78 20 56 46 53 20 61 6c 6c 6f  ltiplex VFS allo
06c0: 77 73 20 64 61 74 61 62 61 73 65 73 20 75 70 20  ws databases up 
06d0: 74 6f 20 33 32 20 47 69 42 20 69 6e 20 73 69 7a  to 32 GiB in siz
06e0: 65 2e 20 20 42 75 74 20 69 74 20 73 70 6c 69 74  e.  But it split
06f0: 73 0a 2a 2a 20 74 68 65 20 66 69 6c 65 73 20 75  s.** the files u
0700: 70 20 69 6e 74 6f 20 73 6d 61 6c 6c 65 72 20 70  p into smaller p
0710: 69 65 63 65 73 2c 20 73 6f 20 74 68 61 74 20 74  ieces, so that t
0720: 68 65 79 20 77 69 6c 6c 20 77 6f 72 6b 20 65 76  hey will work ev
0730: 65 6e 20 6f 6e 20 0a 2a 2a 20 66 69 6c 65 73 79  en on .** filesy
0740: 73 74 65 6d 73 20 74 68 61 74 20 64 6f 20 6e 6f  stems that do no
0750: 74 20 73 75 70 70 6f 72 74 20 6c 61 72 67 65 20  t support large 
0760: 66 69 6c 65 73 2e 20 20 54 68 65 20 64 65 66 61  files.  The defa
0770: 75 6c 74 20 63 68 75 6e 6b 20 73 69 7a 65 0a 2a  ult chunk size.*
0780: 2a 20 69 73 20 32 31 34 37 34 31 38 31 31 32 20  * is 2147418112 
0790: 62 79 74 65 73 20 28 77 68 69 63 68 20 69 73 20  bytes (which is 
07a0: 36 34 4b 69 42 20 6c 65 73 73 20 74 68 61 6e 20  64KiB less than 
07b0: 32 47 69 42 29 20 62 75 74 20 74 68 69 73 20 63  2GiB) but this c
07c0: 61 6e 20 62 65 0a 2a 2a 20 63 68 61 6e 67 65 64  an be.** changed
07d0: 20 61 74 20 63 6f 6d 70 69 6c 65 2d 74 69 6d 65   at compile-time
07e0: 20 62 79 20 64 65 66 69 6e 69 6e 67 20 74 68 65   by defining the
07f0: 20 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45   SQLITE_MULTIPLE
0800: 58 5f 43 48 55 4e 4b 5f 53 49 5a 45 0a 2a 2a 20  X_CHUNK_SIZE.** 
0810: 6d 61 63 72 6f 2e 20 20 55 73 65 20 74 68 65 20  macro.  Use the 
0820: 22 63 68 75 6e 6b 73 69 7a 65 3d 4e 4e 4e 4e 22  "chunksize=NNNN"
0830: 20 71 75 65 72 79 20 70 61 72 61 6d 65 74 65 72   query parameter
0840: 20 77 69 74 68 20 61 20 55 52 49 20 66 69 6c 65   with a URI file
0850: 6e 61 6d 65 0a 2a 2a 20 69 6e 20 6f 72 64 65 72  name.** in order
0860: 20 74 6f 20 73 65 6c 65 63 74 20 61 6e 20 61 6c   to select an al
0870: 74 65 72 6e 61 74 69 76 65 20 63 68 75 6e 6b 20  ternative chunk 
0880: 73 69 7a 65 20 66 6f 72 20 69 6e 64 69 76 69 64  size for individ
0890: 75 61 6c 20 63 6f 6e 6e 65 63 74 69 6f 6e 73 0a  ual connections.
08a0: 2a 2a 20 61 74 20 72 75 6e 2d 74 69 6d 65 2e 0a  ** at run-time..
08b0: 2a 2f 0a 23 69 6e 63 6c 75 64 65 20 22 73 71 6c  */.#include "sql
08c0: 69 74 65 33 2e 68 22 0a 23 69 6e 63 6c 75 64 65  ite3.h".#include
08d0: 20 3c 73 74 72 69 6e 67 2e 68 3e 0a 23 69 6e 63   <string.h>.#inc
08e0: 6c 75 64 65 20 3c 61 73 73 65 72 74 2e 68 3e 0a  lude <assert.h>.
08f0: 23 69 6e 63 6c 75 64 65 20 3c 73 74 64 6c 69 62  #include <stdlib
0900: 2e 68 3e 0a 23 69 6e 63 6c 75 64 65 20 22 74 65  .h>.#include "te
0910: 73 74 5f 6d 75 6c 74 69 70 6c 65 78 2e 68 22 0a  st_multiplex.h".
0920: 0a 23 69 66 6e 64 65 66 20 53 51 4c 49 54 45 5f  .#ifndef SQLITE_
0930: 43 4f 52 45 0a 20 20 23 64 65 66 69 6e 65 20 53  CORE.  #define S
0940: 51 4c 49 54 45 5f 43 4f 52 45 20 31 20 20 2f 2a  QLITE_CORE 1  /*
0950: 20 44 69 73 61 62 6c 65 20 74 68 65 20 41 50 49   Disable the API
0960: 20 72 65 64 65 66 69 6e 69 74 69 6f 6e 20 69 6e   redefinition in
0970: 20 73 71 6c 69 74 65 33 65 78 74 2e 68 20 2a 2f   sqlite3ext.h */
0980: 0a 23 65 6e 64 69 66 0a 23 69 6e 63 6c 75 64 65  .#endif.#include
0990: 20 22 73 71 6c 69 74 65 33 65 78 74 2e 68 22 0a   "sqlite3ext.h".
09a0: 0a 2f 2a 20 0a 2a 2a 20 54 68 65 73 65 20 73 68  ./* .** These sh
09b0: 6f 75 6c 64 20 62 65 20 64 65 66 69 6e 65 64 20  ould be defined 
09c0: 74 6f 20 62 65 20 74 68 65 20 73 61 6d 65 20 61  to be the same a
09d0: 73 20 74 68 65 20 76 61 6c 75 65 73 20 69 6e 20  s the values in 
09e0: 0a 2a 2a 20 73 71 6c 69 74 65 49 6e 74 2e 68 2e  .** sqliteInt.h.
09f0: 20 20 54 68 65 79 20 61 72 65 20 64 65 66 69 6e    They are defin
0a00: 65 64 20 73 65 70 65 72 61 74 65 6c 79 20 68 65  ed seperately he
0a10: 72 65 20 73 6f 20 74 68 61 74 0a 2a 2a 20 74 68  re so that.** th
0a20: 65 20 6d 75 6c 74 69 70 6c 65 78 20 56 46 53 20  e multiplex VFS 
0a30: 73 68 69 6d 20 63 61 6e 20 62 65 20 62 75 69 6c  shim can be buil
0a40: 74 20 61 73 20 61 20 6c 6f 61 64 61 62 6c 65 20  t as a loadable 
0a50: 0a 2a 2a 20 6d 6f 64 75 6c 65 2e 0a 2a 2f 0a 23  .** module..*/.#
0a60: 64 65 66 69 6e 65 20 55 4e 55 53 45 44 5f 50 41  define UNUSED_PA
0a70: 52 41 4d 45 54 45 52 28 78 29 20 28 76 6f 69 64  RAMETER(x) (void
0a80: 29 28 78 29 0a 23 64 65 66 69 6e 65 20 4d 41 58  )(x).#define MAX
0a90: 5f 50 41 47 45 5f 53 49 5a 45 20 20 20 20 20 20  _PAGE_SIZE      
0aa0: 20 30 78 31 30 30 30 30 0a 23 64 65 66 69 6e 65   0x10000.#define
0ab0: 20 44 45 46 41 55 4c 54 5f 53 45 43 54 4f 52 5f   DEFAULT_SECTOR_
0ac0: 53 49 5a 45 20 30 78 31 30 30 30 0a 0a 2f 2a 0a  SIZE 0x1000../*.
0ad0: 2a 2a 20 46 6f 72 20 61 20 62 75 69 6c 64 20 77  ** For a build w
0ae0: 69 74 68 6f 75 74 20 6d 75 74 65 78 65 73 2c 20  ithout mutexes, 
0af0: 6e 6f 2d 6f 70 20 74 68 65 20 6d 75 74 65 78 20  no-op the mutex 
0b00: 63 61 6c 6c 73 2e 0a 2a 2f 0a 23 69 66 20 64 65  calls..*/.#if de
0b10: 66 69 6e 65 64 28 53 51 4c 49 54 45 5f 54 48 52  fined(SQLITE_THR
0b20: 45 41 44 53 41 46 45 29 20 26 26 20 53 51 4c 49  EADSAFE) && SQLI
0b30: 54 45 5f 54 48 52 45 41 44 53 41 46 45 3d 3d 30  TE_THREADSAFE==0
0b40: 0a 23 64 65 66 69 6e 65 20 73 71 6c 69 74 65 33  .#define sqlite3
0b50: 5f 6d 75 74 65 78 5f 61 6c 6c 6f 63 28 58 29 20  _mutex_alloc(X) 
0b60: 20 20 20 28 28 73 71 6c 69 74 65 33 5f 6d 75 74     ((sqlite3_mut
0b70: 65 78 2a 29 38 29 0a 23 64 65 66 69 6e 65 20 73  ex*)8).#define s
0b80: 71 6c 69 74 65 33 5f 6d 75 74 65 78 5f 66 72 65  qlite3_mutex_fre
0b90: 65 28 58 29 0a 23 64 65 66 69 6e 65 20 73 71 6c  e(X).#define sql
0ba0: 69 74 65 33 5f 6d 75 74 65 78 5f 65 6e 74 65 72  ite3_mutex_enter
0bb0: 28 58 29 0a 23 64 65 66 69 6e 65 20 73 71 6c 69  (X).#define sqli
0bc0: 74 65 33 5f 6d 75 74 65 78 5f 74 72 79 28 58 29  te3_mutex_try(X)
0bd0: 20 20 20 20 20 20 53 51 4c 49 54 45 5f 4f 4b 0a        SQLITE_OK.
0be0: 23 64 65 66 69 6e 65 20 73 71 6c 69 74 65 33 5f  #define sqlite3_
0bf0: 6d 75 74 65 78 5f 6c 65 61 76 65 28 58 29 0a 23  mutex_leave(X).#
0c00: 64 65 66 69 6e 65 20 73 71 6c 69 74 65 33 5f 6d  define sqlite3_m
0c10: 75 74 65 78 5f 68 65 6c 64 28 58 29 20 20 20 20  utex_held(X)    
0c20: 20 28 28 76 6f 69 64 29 28 58 29 2c 31 29 0a 23   ((void)(X),1).#
0c30: 64 65 66 69 6e 65 20 73 71 6c 69 74 65 33 5f 6d  define sqlite3_m
0c40: 75 74 65 78 5f 6e 6f 74 68 65 6c 64 28 58 29 20  utex_notheld(X) 
0c50: 20 28 28 76 6f 69 64 29 28 58 29 2c 31 29 0a 23   ((void)(X),1).#
0c60: 65 6e 64 69 66 20 2f 2a 20 53 51 4c 49 54 45 5f  endif /* SQLITE_
0c70: 54 48 52 45 41 44 53 41 46 45 3d 3d 30 20 2a 2f  THREADSAFE==0 */
0c80: 0a 0a 2f 2a 20 46 69 72 73 74 20 63 68 75 6e 6b  ../* First chunk
0c90: 20 66 6f 72 20 72 6f 6c 6c 62 61 63 6b 20 6a 6f   for rollback jo
0ca0: 75 72 6e 61 6c 20 66 69 6c 65 73 20 2a 2f 0a 23  urnal files */.#
0cb0: 64 65 66 69 6e 65 20 53 51 4c 49 54 45 5f 4d 55  define SQLITE_MU
0cc0: 4c 54 49 50 4c 45 58 5f 4a 4f 55 52 4e 41 4c 5f  LTIPLEX_JOURNAL_
0cd0: 38 5f 33 5f 4f 46 46 53 45 54 20 34 30 30 0a 0a  8_3_OFFSET 400..
0ce0: 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ./**************
0cf0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20 53 68 69 6d 20  ********** Shim 
0d00: 44 65 66 69 6e 69 74 69 6f 6e 73 20 2a 2a 2a 2a  Definitions ****
0d10: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0d20: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2f 0a 0a 23 69 66  **********/..#if
0d30: 6e 64 65 66 20 53 51 4c 49 54 45 5f 4d 55 4c 54  ndef SQLITE_MULT
0d40: 49 50 4c 45 58 5f 56 46 53 5f 4e 41 4d 45 0a 23  IPLEX_VFS_NAME.#
0d50: 20 64 65 66 69 6e 65 20 53 51 4c 49 54 45 5f 4d   define SQLITE_M
0d60: 55 4c 54 49 50 4c 45 58 5f 56 46 53 5f 4e 41 4d  ULTIPLEX_VFS_NAM
0d70: 45 20 22 6d 75 6c 74 69 70 6c 65 78 22 0a 23 65  E "multiplex".#e
0d80: 6e 64 69 66 0a 0a 2f 2a 20 54 68 69 73 20 69 73  ndif../* This is
0d90: 20 74 68 65 20 6c 69 6d 69 74 20 6f 6e 20 74 68   the limit on th
0da0: 65 20 63 68 75 6e 6b 20 73 69 7a 65 2e 20 20 49  e chunk size.  I
0db0: 74 20 6d 61 79 20 62 65 20 63 68 61 6e 67 65 64  t may be changed
0dc0: 20 62 79 20 63 61 6c 6c 69 6e 67 0a 2a 2a 20 74   by calling.** t
0dd0: 68 65 20 78 46 69 6c 65 43 6f 6e 74 72 6f 6c 28  he xFileControl(
0de0: 29 20 69 6e 74 65 72 66 61 63 65 2e 20 20 49 74  ) interface.  It
0df0: 20 77 69 6c 6c 20 62 65 20 72 6f 75 6e 64 65 64   will be rounded
0e00: 20 75 70 20 74 6f 20 61 20 0a 2a 2a 20 6d 75 6c   up to a .** mul
0e10: 74 69 70 6c 65 20 6f 66 20 4d 41 58 5f 50 41 47  tiple of MAX_PAG
0e20: 45 5f 53 49 5a 45 2e 20 20 57 65 20 64 65 66 61  E_SIZE.  We defa
0e30: 75 6c 74 20 69 74 20 68 65 72 65 20 74 6f 20 32  ult it here to 2
0e40: 47 69 42 20 6c 65 73 73 20 36 34 4b 69 42 2e 0a  GiB less 64KiB..
0e50: 2a 2f 0a 23 69 66 6e 64 65 66 20 53 51 4c 49 54  */.#ifndef SQLIT
0e60: 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 43 48 55 4e  E_MULTIPLEX_CHUN
0e70: 4b 5f 53 49 5a 45 0a 23 20 64 65 66 69 6e 65 20  K_SIZE.# define 
0e80: 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58  SQLITE_MULTIPLEX
0e90: 5f 43 48 55 4e 4b 5f 53 49 5a 45 20 32 31 34 37  _CHUNK_SIZE 2147
0ea0: 34 31 38 31 31 32 0a 23 65 6e 64 69 66 0a 0a 2f  418112.#endif../
0eb0: 2a 20 54 68 69 73 20 75 73 65 64 20 74 6f 20 62  * This used to b
0ec0: 65 20 74 68 65 20 64 65 66 61 75 6c 74 20 6c 69  e the default li
0ed0: 6d 69 74 20 6f 6e 20 6e 75 6d 62 65 72 20 6f 66  mit on number of
0ee0: 20 63 68 75 6e 6b 73 2c 20 62 75 74 0a 2a 2a 20   chunks, but.** 
0ef0: 69 74 20 69 73 20 6e 6f 20 6c 6f 6e 67 65 72 20  it is no longer 
0f00: 65 6e 66 6f 72 63 65 64 2e 20 54 68 65 72 65 20  enforced. There 
0f10: 69 73 20 63 75 72 72 65 6e 74 6c 79 20 6e 6f 20  is currently no 
0f20: 6c 69 6d 69 74 20 74 6f 20 74 68 65 0a 2a 2a 20  limit to the.** 
0f30: 6e 75 6d 62 65 72 20 6f 66 20 63 68 75 6e 6b 73  number of chunks
0f40: 2e 0a 2a 2a 0a 2a 2a 20 4d 61 79 20 62 65 20 63  ..**.** May be c
0f50: 68 61 6e 67 65 64 20 62 79 20 63 61 6c 6c 69 6e  hanged by callin
0f60: 67 20 74 68 65 20 78 46 69 6c 65 43 6f 6e 74 72  g the xFileContr
0f70: 6f 6c 28 29 20 69 6e 74 65 72 66 61 63 65 2e 0a  ol() interface..
0f80: 2a 2f 0a 23 69 66 6e 64 65 66 20 53 51 4c 49 54  */.#ifndef SQLIT
0f90: 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 4d 41 58 5f  E_MULTIPLEX_MAX_
0fa0: 43 48 55 4e 4b 53 0a 23 20 64 65 66 69 6e 65 20  CHUNKS.# define 
0fb0: 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58  SQLITE_MULTIPLEX
0fc0: 5f 4d 41 58 5f 43 48 55 4e 4b 53 20 31 32 0a 23  _MAX_CHUNKS 12.#
0fd0: 65 6e 64 69 66 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a  endif../********
0fe0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0ff0: 20 4f 62 6a 65 63 74 20 44 65 66 69 6e 69 74 69   Object Definiti
1000: 6f 6e 73 20 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ons ************
1010: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1020: 2a 2a 2f 0a 0a 2f 2a 20 46 6f 72 77 61 72 64 20  **/../* Forward 
1030: 64 65 63 6c 61 72 61 74 69 6f 6e 20 6f 66 20 61  declaration of a
1040: 6c 6c 20 6f 62 6a 65 63 74 20 74 79 70 65 73 20  ll object types 
1050: 2a 2f 0a 74 79 70 65 64 65 66 20 73 74 72 75 63  */.typedef struc
1060: 74 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70  t multiplexGroup
1070: 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 3b   multiplexGroup;
1080: 0a 74 79 70 65 64 65 66 20 73 74 72 75 63 74 20  .typedef struct 
1090: 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 6d 75  multiplexConn mu
10a0: 6c 74 69 70 6c 65 78 43 6f 6e 6e 3b 0a 0a 2f 2a  ltiplexConn;../*
10b0: 0a 2a 2a 20 41 20 22 6d 75 6c 74 69 70 6c 65 78  .** A "multiplex
10c0: 20 67 72 6f 75 70 22 20 69 73 20 61 20 63 6f 6c   group" is a col
10d0: 6c 65 63 74 69 6f 6e 20 6f 66 20 66 69 6c 65 73  lection of files
10e0: 20 74 68 61 74 20 63 6f 6c 6c 65 63 74 69 76 65   that collective
10f0: 6c 79 0a 2a 2a 20 6d 61 6b 65 75 70 20 61 20 73  ly.** makeup a s
1100: 69 6e 67 6c 65 20 53 51 4c 69 74 65 20 44 42 20  ingle SQLite DB 
1110: 66 69 6c 65 2e 20 20 54 68 69 73 20 61 6c 6c 6f  file.  This allo
1120: 77 73 20 74 68 65 20 73 69 7a 65 20 6f 66 20 74  ws the size of t
1130: 68 65 20 44 42 0a 2a 2a 20 74 6f 20 65 78 63 65  he DB.** to exce
1140: 65 64 20 74 68 65 20 6c 69 6d 69 74 73 20 69 6d  ed the limits im
1150: 70 6f 73 65 64 20 62 79 20 74 68 65 20 66 69 6c  posed by the fil
1160: 65 20 73 79 73 74 65 6d 2e 0a 2a 2a 0a 2a 2a 20  e system..**.** 
1170: 54 68 65 72 65 20 69 73 20 61 6e 20 69 6e 73 74  There is an inst
1180: 61 6e 63 65 20 6f 66 20 74 68 65 20 66 6f 6c 6c  ance of the foll
1190: 6f 77 69 6e 67 20 6f 62 6a 65 63 74 20 66 6f 72  owing object for
11a0: 20 65 61 63 68 20 64 65 66 69 6e 65 64 20 6d 75   each defined mu
11b0: 6c 74 69 70 6c 65 78 0a 2a 2a 20 67 72 6f 75 70  ltiplex.** group
11c0: 2e 0a 2a 2f 0a 73 74 72 75 63 74 20 6d 75 6c 74  ..*/.struct mult
11d0: 69 70 6c 65 78 47 72 6f 75 70 20 7b 0a 20 20 73  iplexGroup {.  s
11e0: 74 72 75 63 74 20 6d 75 6c 74 69 70 6c 65 78 52  truct multiplexR
11f0: 65 61 6c 20 7b 20 20 20 20 20 20 20 20 20 20 20  eal {           
1200: 2f 2a 20 46 6f 72 20 65 61 63 68 20 63 68 75 6e  /* For each chun
1210: 6b 20 2a 2f 0a 20 20 20 20 73 71 6c 69 74 65 33  k */.    sqlite3
1220: 5f 66 69 6c 65 20 2a 70 3b 20 20 20 20 20 20 20  _file *p;       
1230: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 48 61             /* Ha
1240: 6e 64 6c 65 20 66 6f 72 20 74 68 65 20 63 68 75  ndle for the chu
1250: 6e 6b 20 2a 2f 0a 20 20 20 20 63 68 61 72 20 2a  nk */.    char *
1260: 7a 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  z;              
1270: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4e              /* N
1280: 61 6d 65 20 6f 66 20 74 68 69 73 20 63 68 75 6e  ame of this chun
1290: 6b 20 2a 2f 0a 20 20 7d 20 2a 61 52 65 61 6c 3b  k */.  } *aReal;
12a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
12b0: 20 20 20 20 20 20 20 20 2f 2a 20 6c 69 73 74 20          /* list 
12c0: 6f 66 20 61 6c 6c 20 63 68 75 6e 6b 73 20 2a 2f  of all chunks */
12d0: 0a 20 20 69 6e 74 20 6e 52 65 61 6c 3b 20 20 20  .  int nReal;   
12e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
12f0: 20 20 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f 66      /* Number of
1300: 20 63 68 75 6e 6b 73 20 2a 2f 0a 20 20 63 68 61   chunks */.  cha
1310: 72 20 2a 7a 4e 61 6d 65 3b 20 20 20 20 20 20 20  r *zName;       
1320: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
1330: 20 42 61 73 65 20 66 69 6c 65 6e 61 6d 65 20 6f   Base filename o
1340: 66 20 74 68 69 73 20 67 72 6f 75 70 20 2a 2f 0a  f this group */.
1350: 20 20 69 6e 74 20 6e 4e 61 6d 65 3b 20 20 20 20    int nName;    
1360: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1370: 20 20 20 2f 2a 20 4c 65 6e 67 74 68 20 6f 66 20     /* Length of 
1380: 62 61 73 65 20 66 69 6c 65 6e 61 6d 65 20 2a 2f  base filename */
1390: 0a 20 20 69 6e 74 20 66 6c 61 67 73 3b 20 20 20  .  int flags;   
13a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
13b0: 20 20 20 20 2f 2a 20 46 6c 61 67 73 20 75 73 65      /* Flags use
13c0: 64 20 66 6f 72 20 6f 72 69 67 69 6e 61 6c 20 6f  d for original o
13d0: 70 65 6e 69 6e 67 20 2a 2f 0a 20 20 75 6e 73 69  pening */.  unsi
13e0: 67 6e 65 64 20 69 6e 74 20 73 7a 43 68 75 6e 6b  gned int szChunk
13f0: 3b 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20  ;            /* 
1400: 43 68 75 6e 6b 20 73 69 7a 65 20 75 73 65 64 20  Chunk size used 
1410: 66 6f 72 20 74 68 69 73 20 67 72 6f 75 70 20 2a  for this group *
1420: 2f 0a 20 20 75 6e 73 69 67 6e 65 64 20 63 68 61  /.  unsigned cha
1430: 72 20 62 45 6e 61 62 6c 65 64 3b 20 20 20 20 20  r bEnabled;     
1440: 20 20 20 20 20 2f 2a 20 54 52 55 45 20 74 6f 20       /* TRUE to 
1450: 75 73 65 20 4d 75 6c 74 69 70 6c 65 78 20 56 46  use Multiplex VF
1460: 53 20 66 6f 72 20 74 68 69 73 20 66 69 6c 65 20  S for this file 
1470: 2a 2f 0a 20 20 75 6e 73 69 67 6e 65 64 20 63 68  */.  unsigned ch
1480: 61 72 20 62 54 72 75 6e 63 61 74 65 3b 20 20 20  ar bTruncate;   
1490: 20 20 20 20 20 20 2f 2a 20 54 52 55 45 20 74 6f        /* TRUE to
14a0: 20 65 6e 61 62 6c 65 20 74 72 75 6e 63 61 74 69   enable truncati
14b0: 6f 6e 20 6f 66 20 64 61 74 61 62 61 73 65 73 20  on of databases 
14c0: 2a 2f 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47 72  */.  multiplexGr
14d0: 6f 75 70 20 2a 70 4e 65 78 74 2c 20 2a 70 50 72  oup *pNext, *pPr
14e0: 65 76 3b 20 20 20 2f 2a 20 44 6f 75 62 6c 79 20  ev;   /* Doubly 
14f0: 6c 69 6e 6b 65 64 20 6c 69 73 74 20 6f 66 20 61  linked list of a
1500: 6c 6c 20 67 72 6f 75 70 20 6f 62 6a 65 63 74 73  ll group objects
1510: 20 2a 2f 0a 7d 3b 0a 0a 2f 2a 0a 2a 2a 20 41 6e   */.};../*.** An
1520: 20 69 6e 73 74 61 6e 63 65 20 6f 66 20 74 68 65   instance of the
1530: 20 66 6f 6c 6c 6f 77 69 6e 67 20 6f 62 6a 65 63   following objec
1540: 74 20 72 65 70 72 65 73 65 6e 74 73 20 65 61 63  t represents eac
1550: 68 20 6f 70 65 6e 20 63 6f 6e 6e 65 63 74 69 6f  h open connectio
1560: 6e 0a 2a 2a 20 74 6f 20 61 20 66 69 6c 65 20 74  n.** to a file t
1570: 68 61 74 20 69 73 20 6d 75 6c 74 69 70 6c 65 78  hat is multiplex
1580: 27 65 64 2e 20 20 54 68 69 73 20 6f 62 6a 65 63  'ed.  This objec
1590: 74 20 69 73 20 61 20 0a 2a 2a 20 73 75 62 63 6c  t is a .** subcl
15a0: 61 73 73 20 6f 66 20 73 71 6c 69 74 65 33 5f 66  ass of sqlite3_f
15b0: 69 6c 65 2e 20 20 54 68 65 20 73 71 6c 69 74 65  ile.  The sqlite
15c0: 33 5f 66 69 6c 65 20 6f 62 6a 65 63 74 20 66 6f  3_file object fo
15d0: 72 20 74 68 65 20 75 6e 64 65 72 6c 79 69 6e 67  r the underlying
15e0: 0a 2a 2a 20 56 46 53 20 69 73 20 61 70 70 65 6e  .** VFS is appen
15f0: 64 65 64 20 74 6f 20 74 68 69 73 20 73 74 72 75  ded to this stru
1600: 63 74 75 72 65 2e 0a 2a 2f 0a 73 74 72 75 63 74  cture..*/.struct
1610: 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 7b   multiplexConn {
1620: 0a 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20  .  sqlite3_file 
1630: 62 61 73 65 3b 20 20 20 20 20 20 20 20 20 20 20  base;           
1640: 20 20 20 2f 2a 20 42 61 73 65 20 63 6c 61 73 73     /* Base class
1650: 20 2d 20 6d 75 73 74 20 62 65 20 66 69 72 73 74   - must be first
1660: 20 2a 2f 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47   */.  multiplexG
1670: 72 6f 75 70 20 2a 70 47 72 6f 75 70 3b 20 20 20  roup *pGroup;   
1680: 20 20 20 20 20 20 2f 2a 20 54 68 65 20 75 6e 64        /* The und
1690: 65 72 6c 79 69 6e 67 20 67 72 6f 75 70 20 6f 66  erlying group of
16a0: 20 66 69 6c 65 73 20 2a 2f 0a 7d 3b 0a 0a 2f 2a   files */.};../*
16b0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
16c0: 2a 2a 2a 2a 2a 2a 2a 2a 20 47 6c 6f 62 61 6c 20  ******** Global 
16d0: 56 61 72 69 61 62 6c 65 73 20 2a 2a 2a 2a 2a 2a  Variables ******
16e0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
16f0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2f 0a 2f 2a  ************/./*
1700: 0a 2a 2a 20 41 6c 6c 20 67 6c 6f 62 61 6c 20 76  .** All global v
1710: 61 72 69 61 62 6c 65 73 20 75 73 65 64 20 62 79  ariables used by
1720: 20 74 68 69 73 20 66 69 6c 65 20 61 72 65 20 63   this file are c
1730: 6f 6e 74 61 69 6e 69 6e 67 20 77 69 74 68 69 6e  ontaining within
1740: 20 74 68 65 20 66 6f 6c 6c 6f 77 69 6e 67 0a 2a   the following.*
1750: 2a 20 67 4d 75 6c 74 69 70 6c 65 78 20 73 74 72  * gMultiplex str
1760: 75 63 74 75 72 65 2e 0a 2a 2f 0a 73 74 61 74 69  ucture..*/.stati
1770: 63 20 73 74 72 75 63 74 20 7b 0a 20 20 2f 2a 20  c struct {.  /* 
1780: 54 68 65 20 70 4f 72 69 67 56 66 73 20 69 73 20  The pOrigVfs is 
1790: 74 68 65 20 72 65 61 6c 2c 20 6f 72 69 67 69 6e  the real, origin
17a0: 61 6c 20 75 6e 64 65 72 6c 79 69 6e 67 20 56 46  al underlying VF
17b0: 53 20 69 6d 70 6c 65 6d 65 6e 74 61 74 69 6f 6e  S implementation
17c0: 2e 0a 20 20 2a 2a 20 4d 6f 73 74 20 6f 70 65 72  ..  ** Most oper
17d0: 61 74 69 6f 6e 73 20 70 61 73 73 2d 74 68 72 6f  ations pass-thro
17e0: 75 67 68 20 74 6f 20 74 68 65 20 72 65 61 6c 20  ugh to the real 
17f0: 56 46 53 2e 20 20 54 68 69 73 20 76 61 6c 75 65  VFS.  This value
1800: 20 69 73 20 72 65 61 64 2d 6f 6e 6c 79 0a 20 20   is read-only.  
1810: 2a 2a 20 64 75 72 69 6e 67 20 6f 70 65 72 61 74  ** during operat
1820: 69 6f 6e 2e 20 20 49 74 20 69 73 20 6f 6e 6c 79  ion.  It is only
1830: 20 6d 6f 64 69 66 69 65 64 20 61 74 20 73 74 61   modified at sta
1840: 72 74 2d 74 69 6d 65 20 61 6e 64 20 74 68 75 73  rt-time and thus
1850: 20 64 6f 65 73 20 6e 6f 74 0a 20 20 2a 2a 20 72   does not.  ** r
1860: 65 71 75 69 72 65 20 61 20 6d 75 74 65 78 2e 0a  equire a mutex..
1870: 20 20 2a 2f 0a 20 20 73 71 6c 69 74 65 33 5f 76    */.  sqlite3_v
1880: 66 73 20 2a 70 4f 72 69 67 56 66 73 3b 0a 0a 20  fs *pOrigVfs;.. 
1890: 20 2f 2a 20 54 68 65 20 73 54 68 69 73 56 66 73   /* The sThisVfs
18a0: 20 69 73 20 74 68 65 20 56 46 53 20 73 74 72 75   is the VFS stru
18b0: 63 74 75 72 65 20 75 73 65 64 20 62 79 20 74 68  cture used by th
18c0: 69 73 20 73 68 69 6d 2e 20 20 49 74 20 69 73 20  is shim.  It is 
18d0: 69 6e 69 74 69 61 6c 69 7a 65 64 0a 20 20 2a 2a  initialized.  **
18e0: 20 61 74 20 73 74 61 72 74 2d 74 69 6d 65 20 61   at start-time a
18f0: 6e 64 20 74 68 75 73 20 64 6f 65 73 20 6e 6f 74  nd thus does not
1900: 20 72 65 71 75 69 72 65 20 61 20 6d 75 74 65 78   require a mutex
1910: 0a 20 20 2a 2f 0a 20 20 73 71 6c 69 74 65 33 5f  .  */.  sqlite3_
1920: 76 66 73 20 73 54 68 69 73 56 66 73 3b 0a 0a 20  vfs sThisVfs;.. 
1930: 20 2f 2a 20 54 68 65 20 73 49 6f 4d 65 74 68 6f   /* The sIoMetho
1940: 64 73 20 64 65 66 69 6e 65 73 20 74 68 65 20 6d  ds defines the m
1950: 65 74 68 6f 64 73 20 75 73 65 64 20 62 79 20 73  ethods used by s
1960: 71 6c 69 74 65 33 5f 66 69 6c 65 20 6f 62 6a 65  qlite3_file obje
1970: 63 74 73 20 0a 20 20 2a 2a 20 61 73 73 6f 63 69  cts .  ** associ
1980: 61 74 65 64 20 77 69 74 68 20 74 68 69 73 20 73  ated with this s
1990: 68 69 6d 2e 20 20 49 74 20 69 73 20 69 6e 69 74  him.  It is init
19a0: 69 61 6c 69 7a 65 64 20 61 74 20 73 74 61 72 74  ialized at start
19b0: 2d 74 69 6d 65 20 61 6e 64 20 64 6f 65 73 0a 20  -time and does. 
19c0: 20 2a 2a 20 6e 6f 74 20 72 65 71 75 69 72 65 20   ** not require 
19d0: 61 20 6d 75 74 65 78 2e 0a 20 20 2a 2a 0a 20 20  a mutex..  **.  
19e0: 2a 2a 20 57 68 65 6e 20 74 68 65 20 75 6e 64 65  ** When the unde
19f0: 72 6c 79 69 6e 67 20 56 46 53 20 69 73 20 63 61  rlying VFS is ca
1a00: 6c 6c 65 64 20 74 6f 20 6f 70 65 6e 20 61 20 66  lled to open a f
1a10: 69 6c 65 2c 20 69 74 20 6d 69 67 68 74 20 72 65  ile, it might re
1a20: 74 75 72 6e 20 0a 20 20 2a 2a 20 65 69 74 68 65  turn .  ** eithe
1a30: 72 20 61 20 76 65 72 73 69 6f 6e 20 31 20 6f 72  r a version 1 or
1a40: 20 61 20 76 65 72 73 69 6f 6e 20 32 20 73 71 6c   a version 2 sql
1a50: 69 74 65 33 5f 66 69 6c 65 20 6f 62 6a 65 63 74  ite3_file object
1a60: 2e 20 20 54 68 69 73 20 73 68 69 6d 0a 20 20 2a  .  This shim.  *
1a70: 2a 20 68 61 73 20 74 6f 20 63 72 65 61 74 65 20  * has to create 
1a80: 61 20 77 72 61 70 70 65 72 20 73 71 6c 69 74 65  a wrapper sqlite
1a90: 33 5f 66 69 6c 65 20 6f 66 20 74 68 65 20 73 61  3_file of the sa
1aa0: 6d 65 20 76 65 72 73 69 6f 6e 2e 20 20 48 65 6e  me version.  Hen
1ab0: 63 65 0a 20 20 2a 2a 20 74 68 65 72 65 20 61 72  ce.  ** there ar
1ac0: 65 20 74 77 6f 20 49 2f 4f 20 6d 65 74 68 6f 64  e two I/O method
1ad0: 20 73 74 72 75 63 74 75 72 65 73 2c 20 6f 6e 65   structures, one
1ae0: 20 66 6f 72 20 76 65 72 73 69 6f 6e 20 31 20 61   for version 1 a
1af0: 6e 64 20 74 68 65 20 6f 74 68 65 72 0a 20 20 2a  nd the other.  *
1b00: 2a 20 66 6f 72 20 76 65 72 73 69 6f 6e 20 32 2e  * for version 2.
1b10: 0a 20 20 2a 2f 0a 20 20 73 71 6c 69 74 65 33 5f  .  */.  sqlite3_
1b20: 69 6f 5f 6d 65 74 68 6f 64 73 20 73 49 6f 4d 65  io_methods sIoMe
1b30: 74 68 6f 64 73 56 31 3b 0a 20 20 73 71 6c 69 74  thodsV1;.  sqlit
1b40: 65 33 5f 69 6f 5f 6d 65 74 68 6f 64 73 20 73 49  e3_io_methods sI
1b50: 6f 4d 65 74 68 6f 64 73 56 32 3b 0a 0a 20 20 2f  oMethodsV2;..  /
1b60: 2a 20 54 72 75 65 20 77 68 65 6e 20 74 68 69 73  * True when this
1b70: 20 73 68 69 6d 20 68 61 73 20 62 65 65 6e 20 69   shim has been i
1b80: 6e 69 74 69 61 6c 69 7a 65 64 2e 0a 20 20 2a 2f  nitialized..  */
1b90: 0a 20 20 69 6e 74 20 69 73 49 6e 69 74 69 61 6c  .  int isInitial
1ba0: 69 7a 65 64 3b 0a 0a 20 20 2f 2a 20 46 6f 72 20  ized;..  /* For 
1bb0: 72 75 6e 2d 74 69 6d 65 20 61 63 63 65 73 73 20  run-time access 
1bc0: 61 6e 79 20 6f 66 20 74 68 65 20 6f 74 68 65 72  any of the other
1bd0: 20 67 6c 6f 62 61 6c 20 64 61 74 61 20 73 74 72   global data str
1be0: 75 63 74 75 72 65 73 20 69 6e 20 74 68 69 73 0a  uctures in this.
1bf0: 20 20 2a 2a 20 73 68 69 6d 2c 20 74 68 65 20 66    ** shim, the f
1c00: 6f 6c 6c 6f 77 69 6e 67 20 6d 75 74 65 78 20 6d  ollowing mutex m
1c10: 75 73 74 20 62 65 20 68 65 6c 64 2e 0a 20 20 2a  ust be held..  *
1c20: 2f 0a 20 20 73 71 6c 69 74 65 33 5f 6d 75 74 65  /.  sqlite3_mute
1c30: 78 20 2a 70 4d 75 74 65 78 3b 0a 0a 20 20 2f 2a  x *pMutex;..  /*
1c40: 20 4c 69 73 74 20 6f 66 20 6d 75 6c 74 69 70 6c   List of multipl
1c50: 65 78 47 72 6f 75 70 20 6f 62 6a 65 63 74 73 2e  exGroup objects.
1c60: 0a 20 20 2a 2f 0a 20 20 6d 75 6c 74 69 70 6c 65  .  */.  multiple
1c70: 78 47 72 6f 75 70 20 2a 70 47 72 6f 75 70 73 3b  xGroup *pGroups;
1c80: 0a 7d 20 67 4d 75 6c 74 69 70 6c 65 78 3b 0a 0a  .} gMultiplex;..
1c90: 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  /***************
1ca0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20 55 74 69 6c 69  ********** Utili
1cb0: 74 79 20 52 6f 75 74 69 6e 65 73 20 2a 2a 2a 2a  ty Routines ****
1cc0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
1cd0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2f 0a 2f  *************/./
1ce0: 2a 0a 2a 2a 20 41 63 71 75 69 72 65 20 61 6e 64  *.** Acquire and
1cf0: 20 72 65 6c 65 61 73 65 20 74 68 65 20 6d 75 74   release the mut
1d00: 65 78 20 75 73 65 64 20 74 6f 20 73 65 72 69 61  ex used to seria
1d10: 6c 69 7a 65 20 61 63 63 65 73 73 20 74 6f 20 74  lize access to t
1d20: 68 65 0a 2a 2a 20 6c 69 73 74 20 6f 66 20 6d 75  he.** list of mu
1d30: 6c 74 69 70 6c 65 78 47 72 6f 75 70 73 2e 0a 2a  ltiplexGroups..*
1d40: 2f 0a 73 74 61 74 69 63 20 76 6f 69 64 20 6d 75  /.static void mu
1d50: 6c 74 69 70 6c 65 78 45 6e 74 65 72 28 76 6f 69  ltiplexEnter(voi
1d60: 64 29 7b 20 73 71 6c 69 74 65 33 5f 6d 75 74 65  d){ sqlite3_mute
1d70: 78 5f 65 6e 74 65 72 28 67 4d 75 6c 74 69 70 6c  x_enter(gMultipl
1d80: 65 78 2e 70 4d 75 74 65 78 29 3b 20 7d 0a 73 74  ex.pMutex); }.st
1d90: 61 74 69 63 20 76 6f 69 64 20 6d 75 6c 74 69 70  atic void multip
1da0: 6c 65 78 4c 65 61 76 65 28 76 6f 69 64 29 7b 20  lexLeave(void){ 
1db0: 73 71 6c 69 74 65 33 5f 6d 75 74 65 78 5f 6c 65  sqlite3_mutex_le
1dc0: 61 76 65 28 67 4d 75 6c 74 69 70 6c 65 78 2e 70  ave(gMultiplex.p
1dd0: 4d 75 74 65 78 29 3b 20 7d 0a 0a 2f 2a 0a 2a 2a  Mutex); }../*.**
1de0: 20 43 6f 6d 70 75 74 65 20 61 20 73 74 72 69 6e   Compute a strin
1df0: 67 20 6c 65 6e 67 74 68 20 74 68 61 74 20 69 73  g length that is
1e00: 20 6c 69 6d 69 74 65 64 20 74 6f 20 77 68 61 74   limited to what
1e10: 20 63 61 6e 20 62 65 20 73 74 6f 72 65 64 20 69   can be stored i
1e20: 6e 0a 2a 2a 20 6c 6f 77 65 72 20 33 30 20 62 69  n.** lower 30 bi
1e30: 74 73 20 6f 66 20 61 20 33 32 2d 62 69 74 20 73  ts of a 32-bit s
1e40: 69 67 6e 65 64 20 69 6e 74 65 67 65 72 2e 0a 2a  igned integer..*
1e50: 2a 0a 2a 2a 20 54 68 65 20 76 61 6c 75 65 20 72  *.** The value r
1e60: 65 74 75 72 6e 65 64 20 77 69 6c 6c 20 6e 65 76  eturned will nev
1e70: 65 72 20 62 65 20 6e 65 67 61 74 69 76 65 2e 20  er be negative. 
1e80: 20 4e 6f 72 20 77 69 6c 6c 20 69 74 20 65 76 65   Nor will it eve
1e90: 72 20 62 65 20 67 72 65 61 74 65 72 0a 2a 2a 20  r be greater.** 
1ea0: 74 68 61 6e 20 74 68 65 20 61 63 74 75 61 6c 20  than the actual 
1eb0: 6c 65 6e 67 74 68 20 6f 66 20 74 68 65 20 73 74  length of the st
1ec0: 72 69 6e 67 2e 20 20 46 6f 72 20 76 65 72 79 20  ring.  For very 
1ed0: 6c 6f 6e 67 20 73 74 72 69 6e 67 73 20 28 67 72  long strings (gr
1ee0: 65 61 74 65 72 0a 2a 2a 20 74 68 61 6e 20 31 47  eater.** than 1G
1ef0: 69 42 29 20 74 68 65 20 76 61 6c 75 65 20 72 65  iB) the value re
1f00: 74 75 72 6e 65 64 20 6d 69 67 68 74 20 62 65 20  turned might be 
1f10: 6c 65 73 73 20 74 68 61 6e 20 74 68 65 20 74 72  less than the tr
1f20: 75 65 20 73 74 72 69 6e 67 20 6c 65 6e 67 74 68  ue string length
1f30: 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20  ..*/.static int 
1f40: 6d 75 6c 74 69 70 6c 65 78 53 74 72 6c 65 6e 33  multiplexStrlen3
1f50: 30 28 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 29  0(const char *z)
1f60: 7b 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a  {.  const char *
1f70: 7a 32 20 3d 20 7a 3b 0a 20 20 69 66 28 20 7a 3d  z2 = z;.  if( z=
1f80: 3d 30 20 29 20 72 65 74 75 72 6e 20 30 3b 0a 20  =0 ) return 0;. 
1f90: 20 77 68 69 6c 65 28 20 2a 7a 32 20 29 7b 20 7a   while( *z2 ){ z
1fa0: 32 2b 2b 3b 20 7d 0a 20 20 72 65 74 75 72 6e 20  2++; }.  return 
1fb0: 30 78 33 66 66 66 66 66 66 66 20 26 20 28 69 6e  0x3fffffff & (in
1fc0: 74 29 28 7a 32 20 2d 20 7a 29 3b 0a 7d 0a 0a 2f  t)(z2 - z);.}../
1fd0: 2a 0a 2a 2a 20 47 65 6e 65 72 61 74 65 20 74 68  *.** Generate th
1fe0: 65 20 66 69 6c 65 2d 6e 61 6d 65 20 66 6f 72 20  e file-name for 
1ff0: 63 68 75 6e 6b 20 69 43 68 75 6e 6b 20 6f 66 20  chunk iChunk of 
2000: 74 68 65 20 67 72 6f 75 70 20 77 69 74 68 20 62  the group with b
2010: 61 73 65 20 6e 61 6d 65 0a 2a 2a 20 7a 42 61 73  ase name.** zBas
2020: 65 2e 20 54 68 65 20 66 69 6c 65 2d 6e 61 6d 65  e. The file-name
2030: 20 69 73 20 77 72 69 74 74 65 6e 20 74 6f 20 62   is written to b
2040: 75 66 66 65 72 20 7a 4f 75 74 20 62 65 66 6f 72  uffer zOut befor
2050: 65 20 72 65 74 75 72 6e 69 6e 67 2e 20 42 75 66  e returning. Buf
2060: 66 65 72 0a 2a 2a 20 7a 4f 75 74 20 6d 75 73 74  fer.** zOut must
2070: 20 62 65 20 61 6c 6c 6f 63 61 74 65 64 20 62 79   be allocated by
2080: 20 74 68 65 20 63 61 6c 6c 65 72 20 73 6f 20 74   the caller so t
2090: 68 61 74 20 69 74 20 69 73 20 61 74 20 6c 65 61  hat it is at lea
20a0: 73 74 20 28 6e 42 61 73 65 2b 35 29 0a 2a 2a 20  st (nBase+5).** 
20b0: 62 79 74 65 73 20 69 6e 20 73 69 7a 65 2c 20 77  bytes in size, w
20c0: 68 65 72 65 20 6e 42 61 73 65 20 69 73 20 74 68  here nBase is th
20d0: 65 20 6c 65 6e 67 74 68 20 6f 66 20 7a 42 61 73  e length of zBas
20e0: 65 2c 20 6e 6f 74 20 69 6e 63 6c 75 64 69 6e 67  e, not including
20f0: 20 74 68 65 0a 2a 2a 20 6e 75 6c 2d 74 65 72 6d   the.** nul-term
2100: 69 6e 61 74 6f 72 2e 0a 2a 2a 0a 2a 2a 20 49 66  inator..**.** If
2110: 20 69 43 68 75 6e 6b 20 69 73 20 30 20 28 6f 72   iChunk is 0 (or
2120: 20 34 30 30 20 2d 20 74 68 65 20 6e 75 6d 62 65   400 - the numbe
2130: 72 20 66 6f 72 20 74 68 65 20 66 69 72 73 74 20  r for the first 
2140: 6a 6f 75 72 6e 61 6c 20 66 69 6c 65 20 63 68 75  journal file chu
2150: 6e 6b 29 2c 0a 2a 2a 20 74 68 65 20 6f 75 74 70  nk),.** the outp
2160: 75 74 20 69 73 20 61 20 63 6f 70 79 20 6f 66 20  ut is a copy of 
2170: 74 68 65 20 69 6e 70 75 74 20 73 74 72 69 6e 67  the input string
2180: 2e 20 4f 74 68 65 72 77 69 73 65 2c 20 69 66 20  . Otherwise, if 
2190: 0a 2a 2a 20 53 51 4c 49 54 45 5f 45 4e 41 42 4c  .** SQLITE_ENABL
21a0: 45 5f 38 5f 33 5f 4e 41 4d 45 53 20 69 73 20 6e  E_8_3_NAMES is n
21b0: 6f 74 20 64 65 66 69 6e 65 64 20 6f 72 20 74 68  ot defined or th
21c0: 65 20 69 6e 70 75 74 20 62 75 66 66 65 72 20 64  e input buffer d
21d0: 6f 65 73 20 6e 6f 74 20 63 6f 6e 74 61 69 6e 0a  oes not contain.
21e0: 2a 2a 20 61 20 22 2e 22 20 63 68 61 72 61 63 74  ** a "." charact
21f0: 65 72 2c 20 74 68 65 6e 20 74 68 65 20 6f 75 74  er, then the out
2200: 70 75 74 20 69 73 20 61 20 63 6f 70 79 20 6f 66  put is a copy of
2210: 20 74 68 65 20 69 6e 70 75 74 20 73 74 72 69 6e   the input strin
2220: 67 20 77 69 74 68 20 74 68 65 20 0a 2a 2a 20 74  g with the .** t
2230: 68 72 65 65 2d 64 69 67 69 74 20 7a 65 72 6f 2d  hree-digit zero-
2240: 70 61 64 64 65 64 20 64 65 63 69 6d 61 6c 20 72  padded decimal r
2250: 65 70 72 65 73 65 6e 74 61 74 69 6f 6e 20 69 66  epresentation if
2260: 20 69 43 68 75 6e 6b 20 61 70 70 65 6e 64 65 64   iChunk appended
2270: 20 74 6f 20 69 74 2e 20 0a 2a 2a 20 46 6f 72 20   to it. .** For 
2280: 65 78 61 6d 70 6c 65 3a 0a 2a 2a 0a 2a 2a 20 20  example:.**.**  
2290: 20 7a 42 61 73 65 3d 22 74 65 73 74 2e 64 62 22   zBase="test.db"
22a0: 2c 20 69 43 68 75 6e 6b 3d 34 20 20 2d 3e 20 20  , iChunk=4  ->  
22b0: 7a 4f 75 74 3d 22 74 65 73 74 2e 64 62 30 30 34  zOut="test.db004
22c0: 22 0a 2a 2a 0a 2a 2a 20 4f 72 2c 20 69 66 20 53  ".**.** Or, if S
22d0: 51 4c 49 54 45 5f 45 4e 41 42 4c 45 5f 38 5f 33  QLITE_ENABLE_8_3
22e0: 5f 4e 41 4d 45 53 20 69 73 20 64 65 66 69 6e 65  _NAMES is define
22f0: 64 20 61 6e 64 20 74 68 65 20 69 6e 70 75 74 20  d and the input 
2300: 62 75 66 66 65 72 20 63 6f 6e 74 61 69 6e 73 0a  buffer contains.
2310: 2a 2a 20 61 20 22 2e 22 20 63 68 61 72 61 63 74  ** a "." charact
2320: 65 72 2c 20 74 68 65 6e 20 65 76 65 72 79 74 68  er, then everyth
2330: 69 6e 67 20 61 66 74 65 72 20 74 68 65 20 22 2e  ing after the ".
2340: 22 20 69 73 20 72 65 70 6c 61 63 65 64 20 62 79  " is replaced by
2350: 20 74 68 65 20 0a 2a 2a 20 74 68 72 65 65 2d 64   the .** three-d
2360: 69 67 69 74 20 72 65 70 72 65 73 65 6e 74 61 74  igit representat
2370: 69 6f 6e 20 6f 66 20 69 43 68 75 6e 6b 2e 0a 2a  ion of iChunk..*
2380: 2a 0a 2a 2a 20 20 20 7a 42 61 73 65 3d 22 74 65  *.**   zBase="te
2390: 73 74 2e 64 62 22 2c 20 69 43 68 75 6e 6b 3d 34  st.db", iChunk=4
23a0: 20 20 2d 3e 20 20 7a 4f 75 74 3d 22 74 65 73 74    ->  zOut="test
23b0: 2e 30 30 34 22 0a 2a 2a 0a 2a 2a 20 54 68 65 20  .004".**.** The 
23c0: 6f 75 74 70 75 74 20 62 75 66 66 65 72 20 73 74  output buffer st
23d0: 72 69 6e 67 20 69 73 20 74 65 72 6d 69 6e 61 74  ring is terminat
23e0: 65 64 20 62 79 20 32 20 30 78 30 30 20 62 79 74  ed by 2 0x00 byt
23f0: 65 73 2e 20 54 68 69 73 20 6d 61 6b 65 73 20 69  es. This makes i
2400: 74 20 73 61 66 65 0a 2a 2a 20 74 6f 20 70 61 73  t safe.** to pas
2410: 73 20 74 6f 20 73 71 6c 69 74 65 33 5f 75 72 69  s to sqlite3_uri
2420: 5f 70 61 72 61 6d 65 74 65 72 28 29 20 61 6e 64  _parameter() and
2430: 20 73 69 6d 69 6c 61 72 2e 0a 2a 2f 0a 73 74 61   similar..*/.sta
2440: 74 69 63 20 76 6f 69 64 20 6d 75 6c 74 69 70 6c  tic void multipl
2450: 65 78 46 69 6c 65 6e 61 6d 65 28 0a 20 20 63 6f  exFilename(.  co
2460: 6e 73 74 20 63 68 61 72 20 2a 7a 42 61 73 65 2c  nst char *zBase,
2470: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
2480: 20 46 69 6c 65 6e 61 6d 65 20 66 6f 72 20 63 68   Filename for ch
2490: 75 6e 6b 20 30 20 2a 2f 0a 20 20 69 6e 74 20 6e  unk 0 */.  int n
24a0: 42 61 73 65 2c 20 20 20 20 20 20 20 20 20 20 20  Base,           
24b0: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 53 69             /* Si
24c0: 7a 65 20 6f 66 20 7a 42 61 73 65 20 69 6e 20 62  ze of zBase in b
24d0: 79 74 65 73 20 28 77 69 74 68 6f 75 74 20 5c 30  ytes (without \0
24e0: 29 20 2a 2f 0a 20 20 69 6e 74 20 66 6c 61 67 73  ) */.  int flags
24f0: 2c 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,               
2500: 20 20 20 20 20 20 20 2f 2a 20 46 6c 61 67 73 20         /* Flags 
2510: 75 73 65 64 20 74 6f 20 6f 70 65 6e 20 66 69 6c  used to open fil
2520: 65 20 2a 2f 0a 20 20 69 6e 74 20 69 43 68 75 6e  e */.  int iChun
2530: 6b 2c 20 20 20 20 20 20 20 20 20 20 20 20 20 20  k,              
2540: 20 20 20 20 20 20 20 2f 2a 20 43 68 75 6e 6b 20         /* Chunk 
2550: 74 6f 20 67 65 6e 65 72 61 74 65 20 66 69 6c 65  to generate file
2560: 6e 61 6d 65 20 66 6f 72 20 2a 2f 0a 20 20 63 68  name for */.  ch
2570: 61 72 20 2a 7a 4f 75 74 20 20 20 20 20 20 20 20  ar *zOut        
2580: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
2590: 20 42 75 66 66 65 72 20 74 6f 20 77 72 69 74 65   Buffer to write
25a0: 20 67 65 6e 65 72 61 74 65 64 20 6e 61 6d 65 20   generated name 
25b0: 74 6f 20 2a 2f 0a 29 7b 0a 20 20 69 6e 74 20 6e  to */.){.  int n
25c0: 20 3d 20 6e 42 61 73 65 3b 0a 20 20 6d 65 6d 63   = nBase;.  memc
25d0: 70 79 28 7a 4f 75 74 2c 20 7a 42 61 73 65 2c 20  py(zOut, zBase, 
25e0: 6e 2b 31 29 3b 0a 20 20 69 66 28 20 69 43 68 75  n+1);.  if( iChu
25f0: 6e 6b 21 3d 30 20 26 26 20 69 43 68 75 6e 6b 21  nk!=0 && iChunk!
2600: 3d 53 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45  =SQLITE_MULTIPLE
2610: 58 5f 4a 4f 55 52 4e 41 4c 5f 38 5f 33 5f 4f 46  X_JOURNAL_8_3_OF
2620: 46 53 45 54 20 29 7b 0a 23 69 66 64 65 66 20 53  FSET ){.#ifdef S
2630: 51 4c 49 54 45 5f 45 4e 41 42 4c 45 5f 38 5f 33  QLITE_ENABLE_8_3
2640: 5f 4e 41 4d 45 53 0a 20 20 20 20 69 6e 74 20 69  _NAMES.    int i
2650: 3b 0a 20 20 20 20 66 6f 72 28 69 3d 6e 2d 31 3b  ;.    for(i=n-1;
2660: 20 69 3e 30 20 26 26 20 69 3e 3d 6e 2d 34 20 26   i>0 && i>=n-4 &
2670: 26 20 7a 4f 75 74 5b 69 5d 21 3d 27 2e 27 3b 20  & zOut[i]!='.'; 
2680: 69 2d 2d 29 7b 7d 0a 20 20 20 20 69 66 28 20 69  i--){}.    if( i
2690: 3e 3d 6e 2d 34 20 29 20 6e 20 3d 20 69 2b 31 3b  >=n-4 ) n = i+1;
26a0: 0a 20 20 20 20 69 66 28 20 66 6c 61 67 73 20 26  .    if( flags &
26b0: 20 28 53 51 4c 49 54 45 5f 4f 50 45 4e 5f 4d 41   (SQLITE_OPEN_MA
26c0: 49 4e 5f 4a 4f 55 52 4e 41 4c 7c 53 51 4c 49 54  IN_JOURNAL|SQLIT
26d0: 45 5f 4f 50 45 4e 5f 57 41 4c 29 20 29 7b 0a 20  E_OPEN_WAL) ){. 
26e0: 20 20 20 20 20 2f 2a 20 54 68 65 20 65 78 74 65       /* The exte
26f0: 6e 73 69 6f 6e 73 20 6f 6e 20 6f 76 65 72 66 6c  nsions on overfl
2700: 6f 77 20 66 69 6c 65 73 20 66 6f 72 20 6d 61 69  ow files for mai
2710: 6e 20 64 61 74 61 62 61 73 65 73 20 61 72 65 20  n databases are 
2720: 30 30 31 2c 20 30 30 32 2c 0a 20 20 20 20 20 20  001, 002,.      
2730: 20 2a 2a 20 30 30 33 20 61 6e 64 20 73 6f 20 66   ** 003 and so f
2740: 6f 72 74 68 2e 20 20 54 6f 20 61 76 6f 69 64 20  orth.  To avoid 
2750: 6e 61 6d 65 20 63 6f 6c 6c 69 73 69 6f 6e 73 2c  name collisions,
2760: 20 61 64 64 20 34 30 30 20 74 6f 20 74 68 65 20   add 400 to the 
2770: 0a 20 20 20 20 20 20 20 2a 2a 20 65 78 74 65 6e  .       ** exten
2780: 73 69 6f 6e 73 20 6f 66 20 6a 6f 75 72 6e 61 6c  sions of journal
2790: 20 66 69 6c 65 73 20 73 6f 20 74 68 61 74 20 74   files so that t
27a0: 68 65 79 20 61 72 65 20 34 30 31 2c 20 34 30 32  hey are 401, 402
27b0: 2c 20 34 30 33 2c 20 2e 2e 2e 2e 0a 20 20 20 20  , 403, .....    
27c0: 20 20 20 2a 2f 0a 20 20 20 20 20 20 69 43 68 75     */.      iChu
27d0: 6e 6b 20 2b 3d 20 53 51 4c 49 54 45 5f 4d 55 4c  nk += SQLITE_MUL
27e0: 54 49 50 4c 45 58 5f 4a 4f 55 52 4e 41 4c 5f 38  TIPLEX_JOURNAL_8
27f0: 5f 33 5f 4f 46 46 53 45 54 3b 0a 20 20 20 20 7d  _3_OFFSET;.    }
2800: 0a 23 65 6e 64 69 66 0a 20 20 20 20 73 71 6c 69  .#endif.    sqli
2810: 74 65 33 5f 73 6e 70 72 69 6e 74 66 28 34 2c 26  te3_snprintf(4,&
2820: 7a 4f 75 74 5b 6e 5d 2c 22 25 30 33 64 22 2c 69  zOut[n],"%03d",i
2830: 43 68 75 6e 6b 29 3b 0a 20 20 20 20 6e 20 2b 3d  Chunk);.    n +=
2840: 20 33 3b 0a 20 20 7d 0a 0a 20 20 61 73 73 65 72   3;.  }..  asser
2850: 74 28 20 7a 4f 75 74 5b 6e 5d 3d 3d 27 5c 30 27  t( zOut[n]=='\0'
2860: 20 29 3b 0a 20 20 7a 4f 75 74 5b 6e 2b 31 5d 20   );.  zOut[n+1] 
2870: 3d 20 27 5c 30 27 3b 0a 7d 0a 0a 2f 2a 20 43 6f  = '\0';.}../* Co
2880: 6d 70 75 74 65 20 74 68 65 20 66 69 6c 65 6e 61  mpute the filena
2890: 6d 65 20 66 6f 72 20 74 68 65 20 69 43 68 75 6e  me for the iChun
28a0: 6b 2d 74 68 20 63 68 75 6e 6b 0a 2a 2f 0a 73 74  k-th chunk.*/.st
28b0: 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c  atic int multipl
28c0: 65 78 53 75 62 46 69 6c 65 6e 61 6d 65 28 6d 75  exSubFilename(mu
28d0: 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 2a 70 47  ltiplexGroup *pG
28e0: 72 6f 75 70 2c 20 69 6e 74 20 69 43 68 75 6e 6b  roup, int iChunk
28f0: 29 7b 0a 20 20 69 66 28 20 69 43 68 75 6e 6b 3e  ){.  if( iChunk>
2900: 3d 70 47 72 6f 75 70 2d 3e 6e 52 65 61 6c 20 29  =pGroup->nReal )
2910: 7b 0a 20 20 20 20 73 74 72 75 63 74 20 6d 75 6c  {.    struct mul
2920: 74 69 70 6c 65 78 52 65 61 6c 20 2a 70 3b 0a 20  tiplexReal *p;. 
2930: 20 20 20 70 20 3d 20 73 71 6c 69 74 65 33 5f 72     p = sqlite3_r
2940: 65 61 6c 6c 6f 63 28 70 47 72 6f 75 70 2d 3e 61  ealloc(pGroup->a
2950: 52 65 61 6c 2c 20 28 69 43 68 75 6e 6b 2b 31 29  Real, (iChunk+1)
2960: 2a 73 69 7a 65 6f 66 28 2a 70 29 29 3b 0a 20 20  *sizeof(*p));.  
2970: 20 20 69 66 28 20 70 3d 3d 30 20 29 7b 0a 20 20    if( p==0 ){.  
2980: 20 20 20 20 72 65 74 75 72 6e 20 53 51 4c 49 54      return SQLIT
2990: 45 5f 4e 4f 4d 45 4d 3b 0a 20 20 20 20 7d 0a 20  E_NOMEM;.    }. 
29a0: 20 20 20 6d 65 6d 73 65 74 28 26 70 5b 70 47 72     memset(&p[pGr
29b0: 6f 75 70 2d 3e 6e 52 65 61 6c 5d 2c 20 30 2c 20  oup->nReal], 0, 
29c0: 73 69 7a 65 6f 66 28 70 5b 30 5d 29 2a 28 69 43  sizeof(p[0])*(iC
29d0: 68 75 6e 6b 2b 31 2d 70 47 72 6f 75 70 2d 3e 6e  hunk+1-pGroup->n
29e0: 52 65 61 6c 29 29 3b 0a 20 20 20 20 70 47 72 6f  Real));.    pGro
29f0: 75 70 2d 3e 61 52 65 61 6c 20 3d 20 70 3b 0a 20  up->aReal = p;. 
2a00: 20 20 20 70 47 72 6f 75 70 2d 3e 6e 52 65 61 6c     pGroup->nReal
2a10: 20 3d 20 69 43 68 75 6e 6b 2b 31 3b 0a 20 20 7d   = iChunk+1;.  }
2a20: 0a 20 20 69 66 28 20 70 47 72 6f 75 70 2d 3e 7a  .  if( pGroup->z
2a30: 4e 61 6d 65 20 26 26 20 70 47 72 6f 75 70 2d 3e  Name && pGroup->
2a40: 61 52 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e 7a 3d  aReal[iChunk].z=
2a50: 3d 30 20 29 7b 0a 20 20 20 20 63 68 61 72 20 2a  =0 ){.    char *
2a60: 7a 3b 0a 20 20 20 20 69 6e 74 20 6e 20 3d 20 70  z;.    int n = p
2a70: 47 72 6f 75 70 2d 3e 6e 4e 61 6d 65 3b 0a 20 20  Group->nName;.  
2a80: 20 20 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c 5b    pGroup->aReal[
2a90: 69 43 68 75 6e 6b 5d 2e 7a 20 3d 20 7a 20 3d 20  iChunk].z = z = 
2aa0: 73 71 6c 69 74 65 33 5f 6d 61 6c 6c 6f 63 28 20  sqlite3_malloc( 
2ab0: 6e 2b 35 20 29 3b 0a 20 20 20 20 69 66 28 20 7a  n+5 );.    if( z
2ac0: 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 72 65 74  ==0 ){.      ret
2ad0: 75 72 6e 20 53 51 4c 49 54 45 5f 4e 4f 4d 45 4d  urn SQLITE_NOMEM
2ae0: 3b 0a 20 20 20 20 7d 0a 20 20 20 20 6d 75 6c 74  ;.    }.    mult
2af0: 69 70 6c 65 78 46 69 6c 65 6e 61 6d 65 28 70 47  iplexFilename(pG
2b00: 72 6f 75 70 2d 3e 7a 4e 61 6d 65 2c 20 70 47 72  roup->zName, pGr
2b10: 6f 75 70 2d 3e 6e 4e 61 6d 65 2c 20 70 47 72 6f  oup->nName, pGro
2b20: 75 70 2d 3e 66 6c 61 67 73 2c 20 69 43 68 75 6e  up->flags, iChun
2b30: 6b 2c 20 7a 29 3b 0a 20 20 7d 0a 20 20 72 65 74  k, z);.  }.  ret
2b40: 75 72 6e 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 7d  urn SQLITE_OK;.}
2b50: 0a 0a 2f 2a 20 54 72 61 6e 73 6c 61 74 65 20 61  ../* Translate a
2b60: 6e 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 2a 20  n sqlite3_file* 
2b70: 74 68 61 74 20 69 73 20 72 65 61 6c 6c 79 20 61  that is really a
2b80: 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 2a   multiplexGroup*
2b90: 20 69 6e 74 6f 0a 2a 2a 20 74 68 65 20 73 71 6c   into.** the sql
2ba0: 69 74 65 33 5f 66 69 6c 65 2a 20 66 6f 72 20 74  ite3_file* for t
2bb0: 68 65 20 75 6e 64 65 72 6c 79 69 6e 67 20 6f 72  he underlying or
2bc0: 69 67 69 6e 61 6c 20 56 46 53 2e 0a 2a 2a 0a 2a  iginal VFS..**.*
2bd0: 2a 20 46 6f 72 20 63 68 75 6e 6b 20 30 2c 20 74  * For chunk 0, t
2be0: 68 65 20 70 47 72 6f 75 70 2d 3e 66 6c 61 67 73  he pGroup->flags
2bf0: 20 64 65 74 65 72 6d 69 6e 65 73 20 77 68 65 74   determines whet
2c00: 68 65 72 20 6f 72 20 6e 6f 74 20 61 20 6e 65 77  her or not a new
2c10: 20 66 69 6c 65 0a 2a 2a 20 69 73 20 63 72 65 61   file.** is crea
2c20: 74 65 64 20 69 66 20 69 74 20 64 6f 65 73 20 6e  ted if it does n
2c30: 6f 74 20 61 6c 72 65 61 64 79 20 65 78 69 73 74  ot already exist
2c40: 2e 20 20 46 6f 72 20 63 68 75 6e 6b 73 20 31 20  .  For chunks 1 
2c50: 61 6e 64 20 68 69 67 68 65 72 2c 20 74 68 65 0a  and higher, the.
2c60: 2a 2a 20 66 69 6c 65 20 69 73 20 63 72 65 61 74  ** file is creat
2c70: 65 64 20 6f 6e 6c 79 20 69 66 20 63 72 65 61 74  ed only if creat
2c80: 65 46 6c 61 67 20 69 73 20 31 2e 0a 2a 2f 0a 73  eFlag is 1..*/.s
2c90: 74 61 74 69 63 20 73 71 6c 69 74 65 33 5f 66 69  tatic sqlite3_fi
2ca0: 6c 65 20 2a 6d 75 6c 74 69 70 6c 65 78 53 75 62  le *multiplexSub
2cb0: 4f 70 65 6e 28 0a 20 20 6d 75 6c 74 69 70 6c 65  Open(.  multiple
2cc0: 78 47 72 6f 75 70 20 2a 70 47 72 6f 75 70 2c 20  xGroup *pGroup, 
2cd0: 20 20 20 2f 2a 20 54 68 65 20 6d 75 6c 74 69 70     /* The multip
2ce0: 6c 65 78 6f 72 20 67 72 6f 75 70 20 2a 2f 0a 20  lexor group */. 
2cf0: 20 69 6e 74 20 69 43 68 75 6e 6b 2c 20 20 20 20   int iChunk,    
2d00: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 57              /* W
2d10: 68 69 63 68 20 63 68 75 6e 6b 20 74 6f 20 6f 70  hich chunk to op
2d20: 65 6e 2e 20 20 30 3d 3d 6f 72 69 67 69 6e 61 6c  en.  0==original
2d30: 20 66 69 6c 65 20 2a 2f 0a 20 20 69 6e 74 20 2a   file */.  int *
2d40: 72 63 2c 20 20 20 20 20 20 20 20 20 20 20 20 20  rc,             
2d50: 20 20 20 20 20 20 2f 2a 20 52 65 73 75 6c 74 20        /* Result 
2d60: 63 6f 64 65 20 69 6e 20 61 6e 64 20 6f 75 74 20  code in and out 
2d70: 2a 2f 0a 20 20 69 6e 74 20 2a 70 4f 75 74 46 6c  */.  int *pOutFl
2d80: 61 67 73 2c 20 20 20 20 20 20 20 20 20 20 20 20  ags,            
2d90: 2f 2a 20 4f 75 74 70 75 74 20 66 6c 61 67 73 20  /* Output flags 
2da0: 2a 2f 0a 20 20 69 6e 74 20 63 72 65 61 74 65 46  */.  int createF
2db0: 6c 61 67 20 20 20 20 20 20 20 20 20 20 20 20 20  lag             
2dc0: 2f 2a 20 54 72 75 65 20 74 6f 20 63 72 65 61 74  /* True to creat
2dd0: 65 20 69 66 20 69 43 68 75 6e 6b 3e 30 20 2a 2f  e if iChunk>0 */
2de0: 0a 29 7b 0a 20 20 73 71 6c 69 74 65 33 5f 66 69  .){.  sqlite3_fi
2df0: 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20 30  le *pSubOpen = 0
2e00: 3b 0a 20 20 73 71 6c 69 74 65 33 5f 76 66 73 20  ;.  sqlite3_vfs 
2e10: 2a 70 4f 72 69 67 56 66 73 20 3d 20 67 4d 75 6c  *pOrigVfs = gMul
2e20: 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 3b  tiplex.pOrigVfs;
2e30: 20 20 20 20 20 20 20 20 2f 2a 20 52 65 61 6c 20          /* Real 
2e40: 56 46 53 20 2a 2f 0a 0a 23 69 66 64 65 66 20 53  VFS */..#ifdef S
2e50: 51 4c 49 54 45 5f 45 4e 41 42 4c 45 5f 38 5f 33  QLITE_ENABLE_8_3
2e60: 5f 4e 41 4d 45 53 0a 20 20 2f 2a 20 49 66 20 4a  _NAMES.  /* If J
2e70: 4f 55 52 4e 41 4c 5f 38 5f 33 5f 4f 46 46 53 45  OURNAL_8_3_OFFSE
2e80: 54 20 69 73 20 73 65 74 20 74 6f 20 28 73 61 79  T is set to (say
2e90: 29 20 34 30 30 2c 20 74 68 65 6e 20 61 6e 79 20  ) 400, then any 
2ea0: 6f 76 65 72 66 6c 6f 77 20 66 69 6c 65 73 20 61  overflow files a
2eb0: 72 65 20 0a 20 20 2a 2a 20 70 61 72 74 20 6f 66  re .  ** part of
2ec0: 20 61 20 64 61 74 61 62 61 73 65 20 6a 6f 75 72   a database jour
2ed0: 6e 61 6c 20 61 72 65 20 6e 61 6d 65 64 20 64 62  nal are named db
2ee0: 2e 34 30 31 2c 20 64 62 2e 34 30 32 2c 20 61 6e  .401, db.402, an
2ef0: 64 20 73 6f 20 6f 6e 2e 20 41 20 0a 20 20 2a 2a  d so on. A .  **
2f00: 20 64 61 74 61 62 61 73 65 20 6d 61 79 20 74 68   database may th
2f10: 65 72 65 66 6f 72 65 20 6e 6f 74 20 67 72 6f 77  erefore not grow
2f20: 20 74 6f 20 6c 61 72 67 65 72 20 74 68 61 6e 20   to larger than 
2f30: 34 30 30 20 63 68 75 6e 6b 73 2e 20 41 74 74 65  400 chunks. Atte
2f40: 6d 70 74 69 6e 67 0a 20 20 2a 2a 20 74 6f 20 6f  mpting.  ** to o
2f50: 70 65 6e 20 63 68 75 6e 6b 20 34 30 31 20 69 6e  pen chunk 401 in
2f60: 64 69 63 61 74 65 73 20 74 68 65 20 64 61 74 61  dicates the data
2f70: 62 61 73 65 20 69 73 20 66 75 6c 6c 2e 20 2a 2f  base is full. */
2f80: 0a 20 20 69 66 28 20 69 43 68 75 6e 6b 3e 3d 53  .  if( iChunk>=S
2f90: 51 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f  QLITE_MULTIPLEX_
2fa0: 4a 4f 55 52 4e 41 4c 5f 38 5f 33 5f 4f 46 46 53  JOURNAL_8_3_OFFS
2fb0: 45 54 20 29 7b 0a 20 20 20 20 2a 72 63 20 3d 20  ET ){.    *rc = 
2fc0: 53 51 4c 49 54 45 5f 46 55 4c 4c 3b 0a 20 20 20  SQLITE_FULL;.   
2fd0: 20 72 65 74 75 72 6e 20 30 3b 0a 20 20 7d 0a 23   return 0;.  }.#
2fe0: 65 6e 64 69 66 0a 0a 20 20 2a 72 63 20 3d 20 6d  endif..  *rc = m
2ff0: 75 6c 74 69 70 6c 65 78 53 75 62 46 69 6c 65 6e  ultiplexSubFilen
3000: 61 6d 65 28 70 47 72 6f 75 70 2c 20 69 43 68 75  ame(pGroup, iChu
3010: 6e 6b 29 3b 0a 20 20 69 66 28 20 28 2a 72 63 29  nk);.  if( (*rc)
3020: 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 26 26 20 28  ==SQLITE_OK && (
3030: 70 53 75 62 4f 70 65 6e 20 3d 20 70 47 72 6f 75  pSubOpen = pGrou
3040: 70 2d 3e 61 52 65 61 6c 5b 69 43 68 75 6e 6b 5d  p->aReal[iChunk]
3050: 2e 70 29 3d 3d 30 20 29 7b 0a 20 20 20 20 69 6e  .p)==0 ){.    in
3060: 74 20 66 6c 61 67 73 2c 20 62 45 78 69 73 74 73  t flags, bExists
3070: 3b 0a 20 20 20 20 66 6c 61 67 73 20 3d 20 70 47  ;.    flags = pG
3080: 72 6f 75 70 2d 3e 66 6c 61 67 73 3b 0a 20 20 20  roup->flags;.   
3090: 20 69 66 28 20 63 72 65 61 74 65 46 6c 61 67 20   if( createFlag 
30a0: 29 7b 0a 20 20 20 20 20 20 66 6c 61 67 73 20 7c  ){.      flags |
30b0: 3d 20 53 51 4c 49 54 45 5f 4f 50 45 4e 5f 43 52  = SQLITE_OPEN_CR
30c0: 45 41 54 45 3b 0a 20 20 20 20 7d 65 6c 73 65 20  EATE;.    }else 
30d0: 69 66 28 20 69 43 68 75 6e 6b 3d 3d 30 20 29 7b  if( iChunk==0 ){
30e0: 0a 20 20 20 20 20 20 2f 2a 20 46 61 6c 6c 20 74  .      /* Fall t
30f0: 68 72 6f 75 67 68 20 2a 2f 0a 20 20 20 20 7d 65  hrough */.    }e
3100: 6c 73 65 20 69 66 28 20 70 47 72 6f 75 70 2d 3e  lse if( pGroup->
3110: 61 52 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e 7a 3d  aReal[iChunk].z=
3120: 3d 30 20 29 7b 0a 20 20 20 20 20 20 72 65 74 75  =0 ){.      retu
3130: 72 6e 20 30 3b 0a 20 20 20 20 7d 65 6c 73 65 7b  rn 0;.    }else{
3140: 0a 20 20 20 20 20 20 2a 72 63 20 3d 20 70 4f 72  .      *rc = pOr
3150: 69 67 56 66 73 2d 3e 78 41 63 63 65 73 73 28 70  igVfs->xAccess(p
3160: 4f 72 69 67 56 66 73 2c 20 70 47 72 6f 75 70 2d  OrigVfs, pGroup-
3170: 3e 61 52 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e 7a  >aReal[iChunk].z
3180: 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,.              
3190: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
31a0: 53 51 4c 49 54 45 5f 41 43 43 45 53 53 5f 45 58  SQLITE_ACCESS_EX
31b0: 49 53 54 53 2c 20 26 62 45 78 69 73 74 73 29 3b  ISTS, &bExists);
31c0: 0a 20 20 20 20 20 20 69 66 28 20 2a 72 63 20 7c  .      if( *rc |
31d0: 7c 20 21 62 45 78 69 73 74 73 20 29 20 72 65 74  | !bExists ) ret
31e0: 75 72 6e 20 30 3b 0a 20 20 20 20 20 20 66 6c 61  urn 0;.      fla
31f0: 67 73 20 26 3d 20 7e 53 51 4c 49 54 45 5f 4f 50  gs &= ~SQLITE_OP
3200: 45 4e 5f 43 52 45 41 54 45 3b 0a 20 20 20 20 7d  EN_CREATE;.    }
3210: 0a 20 20 20 20 70 53 75 62 4f 70 65 6e 20 3d 20  .    pSubOpen = 
3220: 73 71 6c 69 74 65 33 5f 6d 61 6c 6c 6f 63 28 20  sqlite3_malloc( 
3230: 70 4f 72 69 67 56 66 73 2d 3e 73 7a 4f 73 46 69  pOrigVfs->szOsFi
3240: 6c 65 20 29 3b 0a 20 20 20 20 69 66 28 20 70 53  le );.    if( pS
3250: 75 62 4f 70 65 6e 3d 3d 30 20 29 7b 0a 20 20 20  ubOpen==0 ){.   
3260: 20 20 20 2a 72 63 20 3d 20 53 51 4c 49 54 45 5f     *rc = SQLITE_
3270: 49 4f 45 52 52 5f 4e 4f 4d 45 4d 3b 0a 20 20 20  IOERR_NOMEM;.   
3280: 20 20 20 72 65 74 75 72 6e 20 30 3b 0a 20 20 20     return 0;.   
3290: 20 7d 0a 20 20 20 20 70 47 72 6f 75 70 2d 3e 61   }.    pGroup->a
32a0: 52 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e 70 20 3d  Real[iChunk].p =
32b0: 20 70 53 75 62 4f 70 65 6e 3b 0a 20 20 20 20 2a   pSubOpen;.    *
32c0: 72 63 20 3d 20 70 4f 72 69 67 56 66 73 2d 3e 78  rc = pOrigVfs->x
32d0: 4f 70 65 6e 28 70 4f 72 69 67 56 66 73 2c 20 70  Open(pOrigVfs, p
32e0: 47 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68  Group->aReal[iCh
32f0: 75 6e 6b 5d 2e 7a 2c 20 70 53 75 62 4f 70 65 6e  unk].z, pSubOpen
3300: 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,.              
3310: 20 20 20 20 20 20 20 20 20 20 20 20 66 6c 61 67              flag
3320: 73 2c 20 70 4f 75 74 46 6c 61 67 73 29 3b 0a 20  s, pOutFlags);. 
3330: 20 20 20 69 66 28 20 28 2a 72 63 29 21 3d 53 51     if( (*rc)!=SQ
3340: 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 20  LITE_OK ){.     
3350: 20 73 71 6c 69 74 65 33 5f 66 72 65 65 28 70 53   sqlite3_free(pS
3360: 75 62 4f 70 65 6e 29 3b 0a 20 20 20 20 20 20 70  ubOpen);.      p
3370: 47 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43 68  Group->aReal[iCh
3380: 75 6e 6b 5d 2e 70 20 3d 20 30 3b 0a 20 20 20 20  unk].p = 0;.    
3390: 20 20 72 65 74 75 72 6e 20 30 3b 0a 20 20 20 20    return 0;.    
33a0: 7d 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20 70  }.  }.  return p
33b0: 53 75 62 4f 70 65 6e 3b 0a 7d 0a 0a 2f 2a 0a 2a  SubOpen;.}../*.*
33c0: 2a 20 52 65 74 75 72 6e 20 74 68 65 20 73 69 7a  * Return the siz
33d0: 65 2c 20 69 6e 20 62 79 74 65 73 2c 20 6f 66 20  e, in bytes, of 
33e0: 63 68 75 6e 6b 20 6e 75 6d 62 65 72 20 69 43 68  chunk number iCh
33f0: 75 6e 6b 2e 20 20 49 66 20 74 68 61 74 20 63 68  unk.  If that ch
3400: 75 6e 6b 0a 2a 2a 20 64 6f 65 73 20 6e 6f 74 20  unk.** does not 
3410: 65 78 69 73 74 2c 20 74 68 65 6e 20 72 65 74 75  exist, then retu
3420: 72 6e 20 30 2e 20 20 54 68 69 73 20 66 75 6e 63  rn 0.  This func
3430: 74 69 6f 6e 20 64 6f 65 73 20 6e 6f 74 20 64 69  tion does not di
3440: 73 74 69 6e 67 69 73 68 20 62 65 74 77 65 65 6e  stingish between
3450: 0a 2a 2a 20 6e 6f 6e 2d 65 78 69 73 74 61 6e 74  .** non-existant
3460: 20 66 69 6c 65 73 20 61 6e 64 20 7a 65 72 6f 2d   files and zero-
3470: 6c 65 6e 67 74 68 20 66 69 6c 65 73 2e 0a 2a 2f  length files..*/
3480: 0a 73 74 61 74 69 63 20 73 71 6c 69 74 65 33 5f  .static sqlite3_
3490: 69 6e 74 36 34 20 6d 75 6c 74 69 70 6c 65 78 53  int64 multiplexS
34a0: 75 62 53 69 7a 65 28 0a 20 20 6d 75 6c 74 69 70  ubSize(.  multip
34b0: 6c 65 78 47 72 6f 75 70 20 2a 70 47 72 6f 75 70  lexGroup *pGroup
34c0: 2c 20 20 20 20 2f 2a 20 54 68 65 20 6d 75 6c 74  ,    /* The mult
34d0: 69 70 6c 65 78 6f 72 20 67 72 6f 75 70 20 2a 2f  iplexor group */
34e0: 0a 20 20 69 6e 74 20 69 43 68 75 6e 6b 2c 20 20  .  int iChunk,  
34f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
3500: 20 57 68 69 63 68 20 63 68 75 6e 6b 20 74 6f 20   Which chunk to 
3510: 6f 70 65 6e 2e 20 20 30 3d 3d 6f 72 69 67 69 6e  open.  0==origin
3520: 61 6c 20 66 69 6c 65 20 2a 2f 0a 20 20 69 6e 74  al file */.  int
3530: 20 2a 72 63 20 20 20 20 20 20 20 20 20 20 20 20   *rc            
3540: 20 20 20 20 20 20 20 20 2f 2a 20 52 65 73 75 6c          /* Resul
3550: 74 20 63 6f 64 65 20 69 6e 20 61 6e 64 20 6f 75  t code in and ou
3560: 74 20 2a 2f 0a 29 7b 0a 20 20 73 71 6c 69 74 65  t */.){.  sqlite
3570: 33 5f 66 69 6c 65 20 2a 70 53 75 62 3b 0a 20 20  3_file *pSub;.  
3580: 73 71 6c 69 74 65 33 5f 69 6e 74 36 34 20 73 7a  sqlite3_int64 sz
3590: 20 3d 20 30 3b 0a 0a 20 20 69 66 28 20 2a 72 63   = 0;..  if( *rc
35a0: 20 29 20 72 65 74 75 72 6e 20 30 3b 0a 20 20 70   ) return 0;.  p
35b0: 53 75 62 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53  Sub = multiplexS
35c0: 75 62 4f 70 65 6e 28 70 47 72 6f 75 70 2c 20 69  ubOpen(pGroup, i
35d0: 43 68 75 6e 6b 2c 20 72 63 2c 20 4e 55 4c 4c 2c  Chunk, rc, NULL,
35e0: 20 30 29 3b 0a 20 20 69 66 28 20 70 53 75 62 3d   0);.  if( pSub=
35f0: 3d 30 20 29 20 72 65 74 75 72 6e 20 30 3b 0a 20  =0 ) return 0;. 
3600: 20 2a 72 63 20 3d 20 70 53 75 62 2d 3e 70 4d 65   *rc = pSub->pMe
3610: 74 68 6f 64 73 2d 3e 78 46 69 6c 65 53 69 7a 65  thods->xFileSize
3620: 28 70 53 75 62 2c 20 26 73 7a 29 3b 0a 20 20 72  (pSub, &sz);.  r
3630: 65 74 75 72 6e 20 73 7a 3b 0a 7d 20 20 20 20 0a  eturn sz;.}    .
3640: 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20 69 73 20 74  ./*.** This is t
3650: 68 65 20 69 6d 70 6c 65 6d 65 6e 74 61 74 69 6f  he implementatio
3660: 6e 20 6f 66 20 74 68 65 20 6d 75 6c 74 69 70 6c  n of the multipl
3670: 65 78 5f 63 6f 6e 74 72 6f 6c 28 29 20 53 51 4c  ex_control() SQL
3680: 20 66 75 6e 63 74 69 6f 6e 2e 0a 2a 2f 0a 73 74   function..*/.st
3690: 61 74 69 63 20 76 6f 69 64 20 6d 75 6c 74 69 70  atic void multip
36a0: 6c 65 78 43 6f 6e 74 72 6f 6c 46 75 6e 63 28 0a  lexControlFunc(.
36b0: 20 20 73 71 6c 69 74 65 33 5f 63 6f 6e 74 65 78    sqlite3_contex
36c0: 74 20 2a 63 6f 6e 74 65 78 74 2c 0a 20 20 69 6e  t *context,.  in
36d0: 74 20 61 72 67 63 2c 0a 20 20 73 71 6c 69 74 65  t argc,.  sqlite
36e0: 33 5f 76 61 6c 75 65 20 2a 2a 61 72 67 76 0a 29  3_value **argv.)
36f0: 7b 0a 20 20 69 6e 74 20 72 63 20 3d 20 53 51 4c  {.  int rc = SQL
3700: 49 54 45 5f 4f 4b 3b 0a 20 20 73 71 6c 69 74 65  ITE_OK;.  sqlite
3710: 33 20 2a 64 62 20 3d 20 73 71 6c 69 74 65 33 5f  3 *db = sqlite3_
3720: 63 6f 6e 74 65 78 74 5f 64 62 5f 68 61 6e 64 6c  context_db_handl
3730: 65 28 63 6f 6e 74 65 78 74 29 3b 0a 20 20 69 6e  e(context);.  in
3740: 74 20 6f 70 3b 0a 20 20 69 6e 74 20 69 56 61 6c  t op;.  int iVal
3750: 3b 0a 0a 20 20 69 66 28 20 21 64 62 20 7c 7c 20  ;..  if( !db || 
3760: 61 72 67 63 21 3d 32 20 29 7b 20 0a 20 20 20 20  argc!=2 ){ .    
3770: 72 63 20 3d 20 53 51 4c 49 54 45 5f 45 52 52 4f  rc = SQLITE_ERRO
3780: 52 3b 20 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20  R; .  }else{.   
3790: 20 2f 2a 20 65 78 74 72 61 63 74 20 70 61 72 61   /* extract para
37a0: 6d 73 20 2a 2f 0a 20 20 20 20 6f 70 20 3d 20 73  ms */.    op = s
37b0: 71 6c 69 74 65 33 5f 76 61 6c 75 65 5f 69 6e 74  qlite3_value_int
37c0: 28 61 72 67 76 5b 30 5d 29 3b 0a 20 20 20 20 69  (argv[0]);.    i
37d0: 56 61 6c 20 3d 20 73 71 6c 69 74 65 33 5f 76 61  Val = sqlite3_va
37e0: 6c 75 65 5f 69 6e 74 28 61 72 67 76 5b 31 5d 29  lue_int(argv[1])
37f0: 3b 0a 20 20 20 20 2f 2a 20 6d 61 70 20 66 75 6e  ;.    /* map fun
3800: 63 74 69 6f 6e 20 6f 70 20 74 6f 20 66 69 6c 65  ction op to file
3810: 5f 63 6f 6e 74 72 6f 6c 20 6f 70 20 2a 2f 0a 20  _control op */. 
3820: 20 20 20 73 77 69 74 63 68 28 20 6f 70 20 29 7b     switch( op ){
3830: 0a 20 20 20 20 20 20 63 61 73 65 20 31 3a 20 0a  .      case 1: .
3840: 20 20 20 20 20 20 20 20 6f 70 20 3d 20 4d 55 4c          op = MUL
3850: 54 49 50 4c 45 58 5f 43 54 52 4c 5f 45 4e 41 42  TIPLEX_CTRL_ENAB
3860: 4c 45 3b 20 0a 20 20 20 20 20 20 20 20 62 72 65  LE; .        bre
3870: 61 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20 32  ak;.      case 2
3880: 3a 20 0a 20 20 20 20 20 20 20 20 6f 70 20 3d 20  : .        op = 
3890: 4d 55 4c 54 49 50 4c 45 58 5f 43 54 52 4c 5f 53  MULTIPLEX_CTRL_S
38a0: 45 54 5f 43 48 55 4e 4b 5f 53 49 5a 45 3b 20 0a  ET_CHUNK_SIZE; .
38b0: 20 20 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20          break;. 
38c0: 20 20 20 20 20 63 61 73 65 20 33 3a 20 0a 20 20       case 3: .  
38d0: 20 20 20 20 20 20 6f 70 20 3d 20 4d 55 4c 54 49        op = MULTI
38e0: 50 4c 45 58 5f 43 54 52 4c 5f 53 45 54 5f 4d 41  PLEX_CTRL_SET_MA
38f0: 58 5f 43 48 55 4e 4b 53 3b 20 0a 20 20 20 20 20  X_CHUNKS; .     
3900: 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20     break;.      
3910: 64 65 66 61 75 6c 74 3a 0a 20 20 20 20 20 20 20  default:.       
3920: 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4e 4f 54   rc = SQLITE_NOT
3930: 46 4f 55 4e 44 3b 0a 20 20 20 20 20 20 20 20 62  FOUND;.        b
3940: 72 65 61 6b 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a  reak;.    }.  }.
3950: 20 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54 45    if( rc==SQLITE
3960: 5f 4f 4b 20 29 7b 0a 20 20 20 20 72 63 20 3d 20  _OK ){.    rc = 
3970: 73 71 6c 69 74 65 33 5f 66 69 6c 65 5f 63 6f 6e  sqlite3_file_con
3980: 74 72 6f 6c 28 64 62 2c 20 30 2c 20 6f 70 2c 20  trol(db, 0, op, 
3990: 26 69 56 61 6c 29 3b 0a 20 20 7d 0a 20 20 73 71  &iVal);.  }.  sq
39a0: 6c 69 74 65 33 5f 72 65 73 75 6c 74 5f 65 72 72  lite3_result_err
39b0: 6f 72 5f 63 6f 64 65 28 63 6f 6e 74 65 78 74 2c  or_code(context,
39c0: 20 72 63 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54   rc);.}../*.** T
39d0: 68 69 73 20 69 73 20 74 68 65 20 65 6e 74 72 79  his is the entry
39e0: 20 70 6f 69 6e 74 20 74 6f 20 72 65 67 69 73 74   point to regist
39f0: 65 72 20 74 68 65 20 61 75 74 6f 2d 65 78 74 65  er the auto-exte
3a00: 6e 73 69 6f 6e 20 66 6f 72 20 74 68 65 20 0a 2a  nsion for the .*
3a10: 2a 20 6d 75 6c 74 69 70 6c 65 78 5f 63 6f 6e 74  * multiplex_cont
3a20: 72 6f 6c 28 29 20 66 75 6e 63 74 69 6f 6e 2e 0a  rol() function..
3a30: 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75  */.static int mu
3a40: 6c 74 69 70 6c 65 78 46 75 6e 63 49 6e 69 74 28  ltiplexFuncInit(
3a50: 0a 20 20 73 71 6c 69 74 65 33 20 2a 64 62 2c 20  .  sqlite3 *db, 
3a60: 0a 20 20 63 68 61 72 20 2a 2a 70 7a 45 72 72 4d  .  char **pzErrM
3a70: 73 67 2c 20 0a 20 20 63 6f 6e 73 74 20 73 71 6c  sg, .  const sql
3a80: 69 74 65 33 5f 61 70 69 5f 72 6f 75 74 69 6e 65  ite3_api_routine
3a90: 73 20 2a 70 41 70 69 0a 29 7b 0a 20 20 69 6e 74  s *pApi.){.  int
3aa0: 20 72 63 3b 0a 20 20 72 63 20 3d 20 73 71 6c 69   rc;.  rc = sqli
3ab0: 74 65 33 5f 63 72 65 61 74 65 5f 66 75 6e 63 74  te3_create_funct
3ac0: 69 6f 6e 28 64 62 2c 20 22 6d 75 6c 74 69 70 6c  ion(db, "multipl
3ad0: 65 78 5f 63 6f 6e 74 72 6f 6c 22 2c 20 32 2c 20  ex_control", 2, 
3ae0: 53 51 4c 49 54 45 5f 41 4e 59 2c 20 0a 20 20 20  SQLITE_ANY, .   
3af0: 20 20 20 30 2c 20 6d 75 6c 74 69 70 6c 65 78 43     0, multiplexC
3b00: 6f 6e 74 72 6f 6c 46 75 6e 63 2c 20 30 2c 20 30  ontrolFunc, 0, 0
3b10: 29 3b 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a  );.  return rc;.
3b20: 7d 0a 0a 2f 2a 0a 2a 2a 20 43 6c 6f 73 65 20 61  }../*.** Close a
3b30: 20 73 69 6e 67 6c 65 20 73 75 62 2d 66 69 6c 65   single sub-file
3b40: 20 69 6e 20 74 68 65 20 63 6f 6e 6e 65 63 74 69   in the connecti
3b50: 6f 6e 20 67 72 6f 75 70 2e 0a 2a 2f 0a 73 74 61  on group..*/.sta
3b60: 74 69 63 20 76 6f 69 64 20 6d 75 6c 74 69 70 6c  tic void multipl
3b70: 65 78 53 75 62 43 6c 6f 73 65 28 0a 20 20 6d 75  exSubClose(.  mu
3b80: 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 2a 70 47  ltiplexGroup *pG
3b90: 72 6f 75 70 2c 0a 20 20 69 6e 74 20 69 43 68 75  roup,.  int iChu
3ba0: 6e 6b 2c 0a 20 20 73 71 6c 69 74 65 33 5f 76 66  nk,.  sqlite3_vf
3bb0: 73 20 2a 70 4f 72 69 67 56 66 73 0a 29 7b 0a 20  s *pOrigVfs.){. 
3bc0: 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70   sqlite3_file *p
3bd0: 53 75 62 4f 70 65 6e 20 3d 20 70 47 72 6f 75 70  SubOpen = pGroup
3be0: 2d 3e 61 52 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e  ->aReal[iChunk].
3bf0: 70 3b 0a 20 20 69 66 28 20 70 53 75 62 4f 70 65  p;.  if( pSubOpe
3c00: 6e 20 29 7b 0a 20 20 20 20 70 53 75 62 4f 70 65  n ){.    pSubOpe
3c10: 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e 78 43 6c  n->pMethods->xCl
3c20: 6f 73 65 28 70 53 75 62 4f 70 65 6e 29 3b 0a 20  ose(pSubOpen);. 
3c30: 20 20 20 69 66 28 20 70 4f 72 69 67 56 66 73 20     if( pOrigVfs 
3c40: 26 26 20 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c  && pGroup->aReal
3c50: 5b 69 43 68 75 6e 6b 5d 2e 7a 20 29 7b 0a 20 20  [iChunk].z ){.  
3c60: 20 20 20 20 70 4f 72 69 67 56 66 73 2d 3e 78 44      pOrigVfs->xD
3c70: 65 6c 65 74 65 28 70 4f 72 69 67 56 66 73 2c 20  elete(pOrigVfs, 
3c80: 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43  pGroup->aReal[iC
3c90: 68 75 6e 6b 5d 2e 7a 2c 20 30 29 3b 0a 20 20 20  hunk].z, 0);.   
3ca0: 20 7d 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 66   }.    sqlite3_f
3cb0: 72 65 65 28 70 47 72 6f 75 70 2d 3e 61 52 65 61  ree(pGroup->aRea
3cc0: 6c 5b 69 43 68 75 6e 6b 5d 2e 70 29 3b 0a 20 20  l[iChunk].p);.  
3cd0: 7d 0a 20 20 73 71 6c 69 74 65 33 5f 66 72 65 65  }.  sqlite3_free
3ce0: 28 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69  (pGroup->aReal[i
3cf0: 43 68 75 6e 6b 5d 2e 7a 29 3b 0a 20 20 6d 65 6d  Chunk].z);.  mem
3d00: 73 65 74 28 26 70 47 72 6f 75 70 2d 3e 61 52 65  set(&pGroup->aRe
3d10: 61 6c 5b 69 43 68 75 6e 6b 5d 2c 20 30 2c 20 73  al[iChunk], 0, s
3d20: 69 7a 65 6f 66 28 70 47 72 6f 75 70 2d 3e 61 52  izeof(pGroup->aR
3d30: 65 61 6c 5b 69 43 68 75 6e 6b 5d 29 29 3b 0a 7d  eal[iChunk]));.}
3d40: 0a 0a 2f 2a 0a 2a 2a 20 44 65 61 6c 6c 6f 63 61  ../*.** Dealloca
3d50: 74 65 20 6d 65 6d 6f 72 79 20 68 65 6c 64 20 62  te memory held b
3d60: 79 20 61 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f  y a multiplexGro
3d70: 75 70 0a 2a 2f 0a 73 74 61 74 69 63 20 76 6f 69  up.*/.static voi
3d80: 64 20 6d 75 6c 74 69 70 6c 65 78 46 72 65 65 43  d multiplexFreeC
3d90: 6f 6d 70 6f 6e 65 6e 74 73 28 6d 75 6c 74 69 70  omponents(multip
3da0: 6c 65 78 47 72 6f 75 70 20 2a 70 47 72 6f 75 70  lexGroup *pGroup
3db0: 29 7b 0a 20 20 69 6e 74 20 69 3b 0a 20 20 66 6f  ){.  int i;.  fo
3dc0: 72 28 69 3d 30 3b 20 69 3c 70 47 72 6f 75 70 2d  r(i=0; i<pGroup-
3dd0: 3e 6e 52 65 61 6c 3b 20 69 2b 2b 29 7b 20 6d 75  >nReal; i++){ mu
3de0: 6c 74 69 70 6c 65 78 53 75 62 43 6c 6f 73 65 28  ltiplexSubClose(
3df0: 70 47 72 6f 75 70 2c 20 69 2c 20 30 29 3b 20 7d  pGroup, i, 0); }
3e00: 0a 20 20 73 71 6c 69 74 65 33 5f 66 72 65 65 28  .  sqlite3_free(
3e10: 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c 29 3b 0a  pGroup->aReal);.
3e20: 20 20 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c 20    pGroup->aReal 
3e30: 3d 20 30 3b 0a 20 20 70 47 72 6f 75 70 2d 3e 6e  = 0;.  pGroup->n
3e40: 52 65 61 6c 20 3d 20 30 3b 0a 7d 0a 0a 0a 2f 2a  Real = 0;.}.../*
3e50: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
3e60: 2a 2a 2a 2a 2a 2a 2a 2a 20 56 46 53 20 4d 65 74  ******** VFS Met
3e70: 68 6f 64 20 57 72 61 70 70 65 72 73 20 2a 2a 2a  hod Wrappers ***
3e80: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
3e90: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2f 0a 0a 2f 2a 0a  **********/../*.
3ea0: 2a 2a 20 54 68 69 73 20 69 73 20 74 68 65 20 78  ** This is the x
3eb0: 4f 70 65 6e 20 6d 65 74 68 6f 64 20 75 73 65 64  Open method used
3ec0: 20 66 6f 72 20 74 68 65 20 22 6d 75 6c 74 69 70   for the "multip
3ed0: 6c 65 78 22 20 56 46 53 2e 0a 2a 2a 0a 2a 2a 20  lex" VFS..**.** 
3ee0: 4d 6f 73 74 20 6f 66 20 74 68 65 20 77 6f 72 6b  Most of the work
3ef0: 20 69 73 20 64 6f 6e 65 20 62 79 20 74 68 65 20   is done by the 
3f00: 75 6e 64 65 72 6c 79 69 6e 67 20 6f 72 69 67 69  underlying origi
3f10: 6e 61 6c 20 56 46 53 2e 20 20 54 68 69 73 20 6d  nal VFS.  This m
3f20: 65 74 68 6f 64 0a 2a 2a 20 73 69 6d 70 6c 79 20  ethod.** simply 
3f30: 6c 69 6e 6b 73 20 74 68 65 20 6e 65 77 20 66 69  links the new fi
3f40: 6c 65 20 69 6e 74 6f 20 74 68 65 20 61 70 70 72  le into the appr
3f50: 6f 70 72 69 61 74 65 20 6d 75 6c 74 69 70 6c 65  opriate multiple
3f60: 78 20 67 72 6f 75 70 20 69 66 20 69 74 20 69 73  x group if it is
3f70: 20 61 0a 2a 2a 20 66 69 6c 65 20 74 68 61 74 20   a.** file that 
3f80: 6e 65 65 64 73 20 74 6f 20 62 65 20 74 72 61 63  needs to be trac
3f90: 6b 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69  ked..*/.static i
3fa0: 6e 74 20 6d 75 6c 74 69 70 6c 65 78 4f 70 65 6e  nt multiplexOpen
3fb0: 28 0a 20 20 73 71 6c 69 74 65 33 5f 76 66 73 20  (.  sqlite3_vfs 
3fc0: 2a 70 56 66 73 2c 20 20 20 20 20 20 20 20 20 2f  *pVfs,         /
3fd0: 2a 20 54 68 65 20 6d 75 6c 74 69 70 6c 65 78 20  * The multiplex 
3fe0: 56 46 53 20 2a 2f 0a 20 20 63 6f 6e 73 74 20 63  VFS */.  const c
3ff0: 68 61 72 20 2a 7a 4e 61 6d 65 2c 20 20 20 20 20  har *zName,     
4000: 20 20 20 20 2f 2a 20 4e 61 6d 65 20 6f 66 20 66      /* Name of f
4010: 69 6c 65 20 74 6f 20 62 65 20 6f 70 65 6e 65 64  ile to be opened
4020: 20 2a 2f 0a 20 20 73 71 6c 69 74 65 33 5f 66 69   */.  sqlite3_fi
4030: 6c 65 20 2a 70 43 6f 6e 6e 2c 20 20 20 20 20 20  le *pConn,      
4040: 20 2f 2a 20 46 69 6c 6c 20 69 6e 20 74 68 69 73   /* Fill in this
4050: 20 66 69 6c 65 20 64 65 73 63 72 69 70 74 6f 72   file descriptor
4060: 20 2a 2f 0a 20 20 69 6e 74 20 66 6c 61 67 73 2c   */.  int flags,
4070: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4080: 20 2f 2a 20 46 6c 61 67 73 20 74 6f 20 63 6f 6e   /* Flags to con
4090: 74 72 6f 6c 20 74 68 65 20 6f 70 65 6e 69 6e 67  trol the opening
40a0: 20 2a 2f 0a 20 20 69 6e 74 20 2a 70 4f 75 74 46   */.  int *pOutF
40b0: 6c 61 67 73 20 20 20 20 20 20 20 20 20 20 20 20  lags            
40c0: 20 2f 2a 20 46 6c 61 67 73 20 73 68 6f 77 69 6e   /* Flags showin
40d0: 67 20 72 65 73 75 6c 74 73 20 6f 66 20 6f 70 65  g results of ope
40e0: 6e 69 6e 67 20 2a 2f 0a 29 7b 0a 20 20 69 6e 74  ning */.){.  int
40f0: 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b   rc = SQLITE_OK;
4100: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4110: 20 20 2f 2a 20 52 65 73 75 6c 74 20 63 6f 64 65    /* Result code
4120: 20 2a 2f 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43   */.  multiplexC
4130: 6f 6e 6e 20 2a 70 4d 75 6c 74 69 70 6c 65 78 4f  onn *pMultiplexO
4140: 70 65 6e 3b 20 20 20 20 20 20 20 2f 2a 20 54 68  pen;       /* Th
4150: 65 20 6e 65 77 20 6d 75 6c 74 69 70 6c 65 78 20  e new multiplex 
4160: 66 69 6c 65 20 64 65 73 63 72 69 70 74 6f 72 20  file descriptor 
4170: 2a 2f 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47 72  */.  multiplexGr
4180: 6f 75 70 20 2a 70 47 72 6f 75 70 3b 20 20 20 20  oup *pGroup;    
4190: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 43 6f 72            /* Cor
41a0: 72 65 73 70 6f 6e 64 69 6e 67 20 6d 75 6c 74 69  responding multi
41b0: 70 6c 65 78 47 72 6f 75 70 20 6f 62 6a 65 63 74  plexGroup object
41c0: 20 2a 2f 0a 20 20 73 71 6c 69 74 65 33 5f 66 69   */.  sqlite3_fi
41d0: 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20 30  le *pSubOpen = 0
41e0: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ;               
41f0: 20 20 20 20 20 2f 2a 20 52 65 61 6c 20 66 69 6c       /* Real fil
4200: 65 20 64 65 73 63 72 69 70 74 6f 72 20 2a 2f 0a  e descriptor */.
4210: 20 20 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 70    sqlite3_vfs *p
4220: 4f 72 69 67 56 66 73 20 3d 20 67 4d 75 6c 74 69  OrigVfs = gMulti
4230: 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 3b 20 20  plex.pOrigVfs;  
4240: 20 2f 2a 20 52 65 61 6c 20 56 46 53 20 2a 2f 0a   /* Real VFS */.
4250: 20 20 69 6e 74 20 6e 4e 61 6d 65 3b 0a 20 20 69    int nName;.  i
4260: 6e 74 20 73 7a 3b 0a 20 20 63 68 61 72 20 2a 7a  nt sz;.  char *z
4270: 54 6f 46 72 65 65 20 3d 20 30 3b 0a 0a 20 20 55  ToFree = 0;..  U
4280: 4e 55 53 45 44 5f 50 41 52 41 4d 45 54 45 52 28  NUSED_PARAMETER(
4290: 70 56 66 73 29 3b 0a 20 20 6d 65 6d 73 65 74 28  pVfs);.  memset(
42a0: 70 43 6f 6e 6e 2c 20 30 2c 20 70 56 66 73 2d 3e  pConn, 0, pVfs->
42b0: 73 7a 4f 73 46 69 6c 65 29 3b 0a 20 20 61 73 73  szOsFile);.  ass
42c0: 65 72 74 28 20 7a 4e 61 6d 65 20 7c 7c 20 28 66  ert( zName || (f
42d0: 6c 61 67 73 20 26 20 53 51 4c 49 54 45 5f 4f 50  lags & SQLITE_OP
42e0: 45 4e 5f 44 45 4c 45 54 45 4f 4e 43 4c 4f 53 45  EN_DELETEONCLOSE
42f0: 29 20 29 3b 0a 0a 20 20 2f 2a 20 57 65 20 6e 65  ) );..  /* We ne
4300: 65 64 20 74 6f 20 63 72 65 61 74 65 20 61 20 67  ed to create a g
4310: 72 6f 75 70 20 73 74 72 75 63 74 75 72 65 20 61  roup structure a
4320: 6e 64 20 6d 61 6e 61 67 65 0a 20 20 2a 2a 20 61  nd manage.  ** a
4330: 63 63 65 73 73 20 74 6f 20 74 68 69 73 20 67 72  ccess to this gr
4340: 6f 75 70 20 6f 66 20 66 69 6c 65 73 2e 0a 20 20  oup of files..  
4350: 2a 2f 0a 20 20 6d 75 6c 74 69 70 6c 65 78 45 6e  */.  multiplexEn
4360: 74 65 72 28 29 3b 0a 20 20 70 4d 75 6c 74 69 70  ter();.  pMultip
4370: 6c 65 78 4f 70 65 6e 20 3d 20 28 6d 75 6c 74 69  lexOpen = (multi
4380: 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b  plexConn*)pConn;
4390: 0a 0a 20 20 69 66 28 20 72 63 3d 3d 53 51 4c 49  ..  if( rc==SQLI
43a0: 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 2f 2a 20  TE_OK ){.    /* 
43b0: 61 6c 6c 6f 63 61 74 65 20 73 70 61 63 65 20 66  allocate space f
43c0: 6f 72 20 67 72 6f 75 70 20 2a 2f 0a 20 20 20 20  or group */.    
43d0: 6e 4e 61 6d 65 20 3d 20 7a 4e 61 6d 65 20 3f 20  nName = zName ? 
43e0: 6d 75 6c 74 69 70 6c 65 78 53 74 72 6c 65 6e 33  multiplexStrlen3
43f0: 30 28 7a 4e 61 6d 65 29 20 3a 20 30 3b 0a 20 20  0(zName) : 0;.  
4400: 20 20 73 7a 20 3d 20 73 69 7a 65 6f 66 28 6d 75    sz = sizeof(mu
4410: 6c 74 69 70 6c 65 78 47 72 6f 75 70 29 20 20 20  ltiplexGroup)   
4420: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4430: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 6d 75 6c            /* mul
4440: 74 69 70 6c 65 78 47 72 6f 75 70 20 2a 2f 0a 20  tiplexGroup */. 
4450: 20 20 20 20 20 20 2b 20 6e 4e 61 6d 65 20 2b 20        + nName + 
4460: 31 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  1;              
4470: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4480: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 7a 4e             /* zN
4490: 61 6d 65 20 2a 2f 0a 20 20 20 20 70 47 72 6f 75  ame */.    pGrou
44a0: 70 20 3d 20 73 71 6c 69 74 65 33 5f 6d 61 6c 6c  p = sqlite3_mall
44b0: 6f 63 28 20 73 7a 20 29 3b 0a 20 20 20 20 69 66  oc( sz );.    if
44c0: 28 20 70 47 72 6f 75 70 3d 3d 30 20 29 7b 0a 20  ( pGroup==0 ){. 
44d0: 20 20 20 20 20 72 63 20 3d 20 53 51 4c 49 54 45       rc = SQLITE
44e0: 5f 4e 4f 4d 45 4d 3b 0a 20 20 20 20 7d 0a 20 20  _NOMEM;.    }.  
44f0: 7d 0a 0a 20 20 69 66 28 20 72 63 3d 3d 53 51 4c  }..  if( rc==SQL
4500: 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 63 6f  ITE_OK ){.    co
4510: 6e 73 74 20 63 68 61 72 20 2a 7a 55 72 69 20 3d  nst char *zUri =
4520: 20 28 66 6c 61 67 73 20 26 20 53 51 4c 49 54 45   (flags & SQLITE
4530: 5f 4f 50 45 4e 5f 55 52 49 29 20 3f 20 7a 4e 61  _OPEN_URI) ? zNa
4540: 6d 65 20 3a 20 30 3b 0a 20 20 20 20 2f 2a 20 61  me : 0;.    /* a
4550: 73 73 69 67 6e 20 70 6f 69 6e 74 65 72 73 20 74  ssign pointers t
4560: 6f 20 65 78 74 72 61 20 73 70 61 63 65 20 61 6c  o extra space al
4570: 6c 6f 63 61 74 65 64 20 2a 2f 0a 20 20 20 20 6d  located */.    m
4580: 65 6d 73 65 74 28 70 47 72 6f 75 70 2c 20 30 2c  emset(pGroup, 0,
4590: 20 73 7a 29 3b 0a 20 20 20 20 70 4d 75 6c 74 69   sz);.    pMulti
45a0: 70 6c 65 78 4f 70 65 6e 2d 3e 70 47 72 6f 75 70  plexOpen->pGroup
45b0: 20 3d 20 70 47 72 6f 75 70 3b 0a 20 20 20 20 70   = pGroup;.    p
45c0: 47 72 6f 75 70 2d 3e 62 45 6e 61 62 6c 65 64 20  Group->bEnabled 
45d0: 3d 20 2d 31 3b 0a 20 20 20 20 70 47 72 6f 75 70  = -1;.    pGroup
45e0: 2d 3e 62 54 72 75 6e 63 61 74 65 20 3d 20 73 71  ->bTruncate = sq
45f0: 6c 69 74 65 33 5f 75 72 69 5f 62 6f 6f 6c 65 61  lite3_uri_boolea
4600: 6e 28 7a 55 72 69 2c 20 22 74 72 75 6e 63 61 74  n(zUri, "truncat
4610: 65 22 2c 20 0a 20 20 20 20 20 20 20 20 20 20 20  e", .           
4620: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4630: 20 20 20 20 20 20 20 20 28 66 6c 61 67 73 20 26          (flags &
4640: 20 53 51 4c 49 54 45 5f 4f 50 45 4e 5f 4d 41 49   SQLITE_OPEN_MAI
4650: 4e 5f 44 42 29 3d 3d 30 29 3b 0a 20 20 20 20 70  N_DB)==0);.    p
4660: 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 20 3d  Group->szChunk =
4670: 20 73 71 6c 69 74 65 33 5f 75 72 69 5f 69 6e 74   sqlite3_uri_int
4680: 36 34 28 7a 55 72 69 2c 20 22 63 68 75 6e 6b 73  64(zUri, "chunks
4690: 69 7a 65 22 2c 0a 20 20 20 20 20 20 20 20 20 20  ize",.          
46a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
46b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 53 51                SQ
46c0: 4c 49 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 43  LITE_MULTIPLEX_C
46d0: 48 55 4e 4b 5f 53 49 5a 45 29 3b 0a 20 20 20 20  HUNK_SIZE);.    
46e0: 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 20  pGroup->szChunk 
46f0: 3d 20 28 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75  = (pGroup->szChu
4700: 6e 6b 2b 30 78 66 66 66 66 29 26 7e 30 78 66 66  nk+0xffff)&~0xff
4710: 66 66 3b 0a 20 20 20 20 69 66 28 20 7a 4e 61 6d  ff;.    if( zNam
4720: 65 20 29 7b 0a 20 20 20 20 20 20 63 68 61 72 20  e ){.      char 
4730: 2a 70 20 3d 20 28 63 68 61 72 20 2a 29 26 70 47  *p = (char *)&pG
4740: 72 6f 75 70 5b 31 5d 3b 0a 20 20 20 20 20 20 70  roup[1];.      p
4750: 47 72 6f 75 70 2d 3e 7a 4e 61 6d 65 20 3d 20 70  Group->zName = p
4760: 3b 0a 20 20 20 20 20 20 6d 65 6d 63 70 79 28 70  ;.      memcpy(p
4770: 47 72 6f 75 70 2d 3e 7a 4e 61 6d 65 2c 20 7a 4e  Group->zName, zN
4780: 61 6d 65 2c 20 6e 4e 61 6d 65 2b 31 29 3b 0a 20  ame, nName+1);. 
4790: 20 20 20 20 20 70 47 72 6f 75 70 2d 3e 6e 4e 61       pGroup->nNa
47a0: 6d 65 20 3d 20 6e 4e 61 6d 65 3b 0a 20 20 20 20  me = nName;.    
47b0: 7d 0a 20 20 20 20 69 66 28 20 70 47 72 6f 75 70  }.    if( pGroup
47c0: 2d 3e 62 45 6e 61 62 6c 65 64 20 29 7b 0a 20 20  ->bEnabled ){.  
47d0: 20 20 20 20 2f 2a 20 4d 61 6b 65 20 73 75 72 65      /* Make sure
47e0: 20 74 68 61 74 20 74 68 65 20 63 68 75 6e 6b 73   that the chunks
47f0: 69 7a 65 20 69 73 20 73 75 63 68 20 74 68 61 74  ize is such that
4800: 20 74 68 65 20 70 65 6e 64 69 6e 67 20 62 79 74   the pending byt
4810: 65 20 64 6f 65 73 20 6e 6f 74 0a 20 20 20 20 20  e does not.     
4820: 20 2a 2a 20 66 61 6c 6c 73 20 61 74 20 74 68 65   ** falls at the
4830: 20 65 6e 64 20 6f 66 20 61 20 63 68 75 6e 6b 2e   end of a chunk.
4840: 20 20 41 20 72 65 67 69 6f 6e 20 6f 66 20 75 70    A region of up
4850: 20 74 6f 20 36 34 4b 20 66 6f 6c 6c 6f 77 69 6e   to 64K followin
4860: 67 0a 20 20 20 20 20 20 2a 2a 20 74 68 65 20 70  g.      ** the p
4870: 65 6e 64 69 6e 67 20 62 79 74 65 20 69 73 20 6e  ending byte is n
4880: 65 76 65 72 20 77 72 69 74 74 65 6e 2c 20 73 6f  ever written, so
4890: 20 69 66 20 74 68 65 20 70 65 6e 64 69 6e 67 20   if the pending 
48a0: 62 79 74 65 20 6f 63 63 75 72 73 0a 20 20 20 20  byte occurs.    
48b0: 20 20 2a 2a 20 6e 65 61 72 20 74 68 65 20 65 6e    ** near the en
48c0: 64 20 6f 66 20 61 20 63 68 75 6e 6b 2c 20 74 68  d of a chunk, th
48d0: 61 74 20 63 68 75 6e 6b 20 77 69 6c 6c 20 62 65  at chunk will be
48e0: 20 74 6f 6f 20 73 6d 61 6c 6c 2e 20 2a 2f 0a 23   too small. */.#
48f0: 69 66 6e 64 65 66 20 53 51 4c 49 54 45 5f 4f 4d  ifndef SQLITE_OM
4900: 49 54 5f 57 53 44 0a 20 20 20 20 20 20 65 78 74  IT_WSD.      ext
4910: 65 72 6e 20 69 6e 74 20 73 71 6c 69 74 65 33 50  ern int sqlite3P
4920: 65 6e 64 69 6e 67 42 79 74 65 3b 0a 23 65 6c 73  endingByte;.#els
4930: 65 0a 20 20 20 20 20 20 69 6e 74 20 73 71 6c 69  e.      int sqli
4940: 74 65 33 50 65 6e 64 69 6e 67 42 79 74 65 20 3d  te3PendingByte =
4950: 20 30 78 34 30 30 30 30 30 30 30 3b 0a 23 65 6e   0x40000000;.#en
4960: 64 69 66 0a 20 20 20 20 20 20 77 68 69 6c 65 28  dif.      while(
4970: 20 28 73 71 6c 69 74 65 33 50 65 6e 64 69 6e 67   (sqlite3Pending
4980: 42 79 74 65 20 25 20 70 47 72 6f 75 70 2d 3e 73  Byte % pGroup->s
4990: 7a 43 68 75 6e 6b 29 3e 3d 28 70 47 72 6f 75 70  zChunk)>=(pGroup
49a0: 2d 3e 73 7a 43 68 75 6e 6b 2d 36 35 35 33 36 29  ->szChunk-65536)
49b0: 20 29 7b 0a 20 20 20 20 20 20 20 20 70 47 72 6f   ){.        pGro
49c0: 75 70 2d 3e 73 7a 43 68 75 6e 6b 20 2b 3d 20 36  up->szChunk += 6
49d0: 35 35 33 36 3b 0a 20 20 20 20 20 20 7d 0a 20 20  5536;.      }.  
49e0: 20 20 7d 0a 20 20 20 20 70 47 72 6f 75 70 2d 3e    }.    pGroup->
49f0: 66 6c 61 67 73 20 3d 20 66 6c 61 67 73 3b 0a 20  flags = flags;. 
4a00: 20 20 20 72 63 20 3d 20 6d 75 6c 74 69 70 6c 65     rc = multiple
4a10: 78 53 75 62 46 69 6c 65 6e 61 6d 65 28 70 47 72  xSubFilename(pGr
4a20: 6f 75 70 2c 20 31 29 3b 0a 20 20 20 20 69 66 28  oup, 1);.    if(
4a30: 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29   rc==SQLITE_OK )
4a40: 7b 0a 20 20 20 20 20 20 70 53 75 62 4f 70 65 6e  {.      pSubOpen
4a50: 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f   = multiplexSubO
4a60: 70 65 6e 28 70 47 72 6f 75 70 2c 20 30 2c 20 26  pen(pGroup, 0, &
4a70: 72 63 2c 20 70 4f 75 74 46 6c 61 67 73 2c 20 30  rc, pOutFlags, 0
4a80: 29 3b 0a 20 20 20 20 20 20 69 66 28 20 70 53 75  );.      if( pSu
4a90: 62 4f 70 65 6e 3d 3d 30 20 26 26 20 72 63 3d 3d  bOpen==0 && rc==
4aa0: 53 51 4c 49 54 45 5f 4f 4b 20 29 20 72 63 20 3d  SQLITE_OK ) rc =
4ab0: 20 53 51 4c 49 54 45 5f 43 41 4e 54 4f 50 45 4e   SQLITE_CANTOPEN
4ac0: 3b 0a 20 20 20 20 7d 0a 20 20 20 20 69 66 28 20  ;.    }.    if( 
4ad0: 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b  rc==SQLITE_OK ){
4ae0: 0a 20 20 20 20 20 20 73 71 6c 69 74 65 33 5f 69  .      sqlite3_i
4af0: 6e 74 36 34 20 73 7a 3b 0a 0a 20 20 20 20 20 20  nt64 sz;..      
4b00: 72 63 20 3d 20 70 53 75 62 4f 70 65 6e 2d 3e 70  rc = pSubOpen->p
4b10: 4d 65 74 68 6f 64 73 2d 3e 78 46 69 6c 65 53 69  Methods->xFileSi
4b20: 7a 65 28 70 53 75 62 4f 70 65 6e 2c 20 26 73 7a  ze(pSubOpen, &sz
4b30: 29 3b 0a 20 20 20 20 20 20 69 66 28 20 72 63 3d  );.      if( rc=
4b40: 3d 53 51 4c 49 54 45 5f 4f 4b 20 26 26 20 7a 4e  =SQLITE_OK && zN
4b50: 61 6d 65 20 29 7b 0a 20 20 20 20 20 20 20 20 69  ame ){.        i
4b60: 6e 74 20 62 45 78 69 73 74 73 3b 0a 20 20 20 20  nt bExists;.    
4b70: 20 20 20 20 69 66 28 20 73 7a 3d 3d 30 20 29 7b      if( sz==0 ){
4b80: 0a 20 20 20 20 20 20 20 20 20 20 69 66 28 20 66  .          if( f
4b90: 6c 61 67 73 20 26 20 53 51 4c 49 54 45 5f 4f 50  lags & SQLITE_OP
4ba0: 45 4e 5f 4d 41 49 4e 5f 4a 4f 55 52 4e 41 4c 20  EN_MAIN_JOURNAL 
4bb0: 29 7b 0a 20 20 20 20 20 20 20 20 20 20 20 20 2f  ){.            /
4bc0: 2a 20 49 66 20 6f 70 65 6e 69 6e 67 20 61 20 6d  * If opening a m
4bd0: 61 69 6e 20 6a 6f 75 72 6e 61 6c 20 66 69 6c 65  ain journal file
4be0: 20 61 6e 64 20 74 68 65 20 66 69 72 73 74 20 63   and the first c
4bf0: 68 75 6e 6b 20 69 73 20 7a 65 72 6f 0a 20 20 20  hunk is zero.   
4c00: 20 20 20 20 20 20 20 20 20 2a 2a 20 62 79 74 65           ** byte
4c10: 73 20 69 6e 20 73 69 7a 65 2c 20 64 65 6c 65 74  s in size, delet
4c20: 65 20 61 6e 79 20 73 75 62 73 65 71 75 65 6e 74  e any subsequent
4c30: 20 63 68 75 6e 6b 73 20 66 72 6f 6d 20 74 68 65   chunks from the
4c40: 20 0a 20 20 20 20 20 20 20 20 20 20 20 20 2a 2a   .            **
4c50: 20 66 69 6c 65 2d 73 79 73 74 65 6d 2e 20 2a 2f   file-system. */
4c60: 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 6e 74  .            int
4c70: 20 69 43 68 75 6e 6b 20 3d 20 31 3b 0a 20 20 20   iChunk = 1;.   
4c80: 20 20 20 20 20 20 20 20 20 64 6f 20 7b 0a 20 20           do {.  
4c90: 20 20 20 20 20 20 20 20 20 20 20 20 72 63 20 3d              rc =
4ca0: 20 70 4f 72 69 67 56 66 73 2d 3e 78 41 63 63 65   pOrigVfs->xAcce
4cb0: 73 73 28 70 4f 72 69 67 56 66 73 2c 20 0a 20 20  ss(pOrigVfs, .  
4cc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4cd0: 70 47 72 6f 75 70 2d 3e 61 52 65 61 6c 5b 69 43  pGroup->aReal[iC
4ce0: 68 75 6e 6b 5d 2e 7a 2c 20 53 51 4c 49 54 45 5f  hunk].z, SQLITE_
4cf0: 41 43 43 45 53 53 5f 45 58 49 53 54 53 2c 20 26  ACCESS_EXISTS, &
4d00: 62 45 78 69 73 74 73 0a 20 20 20 20 20 20 20 20  bExists.        
4d10: 20 20 20 20 20 20 29 3b 0a 20 20 20 20 20 20 20        );.       
4d20: 20 20 20 20 20 20 20 69 66 28 20 72 63 3d 3d 53         if( rc==S
4d30: 51 4c 49 54 45 5f 4f 4b 20 26 26 20 62 45 78 69  QLITE_OK && bExi
4d40: 73 74 73 20 29 7b 0a 20 20 20 20 20 20 20 20 20  sts ){.         
4d50: 20 20 20 20 20 20 20 72 63 20 3d 20 70 4f 72 69         rc = pOri
4d60: 67 56 66 73 2d 3e 78 44 65 6c 65 74 65 28 70 4f  gVfs->xDelete(pO
4d70: 72 69 67 56 66 73 2c 20 70 47 72 6f 75 70 2d 3e  rigVfs, pGroup->
4d80: 61 52 65 61 6c 5b 69 43 68 75 6e 6b 5d 2e 7a 2c  aReal[iChunk].z,
4d90: 20 30 29 3b 0a 20 20 20 20 20 20 20 20 20 20 20   0);.           
4da0: 20 20 20 20 20 69 66 28 20 72 63 3d 3d 53 51 4c       if( rc==SQL
4db0: 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20  ITE_OK ){.      
4dc0: 20 20 20 20 20 20 20 20 20 20 20 20 72 63 20 3d              rc =
4dd0: 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 46 69 6c   multiplexSubFil
4de0: 65 6e 61 6d 65 28 70 47 72 6f 75 70 2c 20 2b 2b  ename(pGroup, ++
4df0: 69 43 68 75 6e 6b 29 3b 0a 20 20 20 20 20 20 20  iChunk);.       
4e00: 20 20 20 20 20 20 20 20 20 7d 0a 20 20 20 20 20           }.     
4e10: 20 20 20 20 20 20 20 20 20 7d 0a 20 20 20 20 20           }.     
4e20: 20 20 20 20 20 20 20 7d 77 68 69 6c 65 28 20 72         }while( r
4e30: 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 26 26 20  c==SQLITE_OK && 
4e40: 62 45 78 69 73 74 73 20 29 3b 0a 20 20 20 20 20  bExists );.     
4e50: 20 20 20 20 20 7d 0a 20 20 20 20 20 20 20 20 7d       }.        }
4e60: 65 6c 73 65 7b 0a 20 20 20 20 20 20 20 20 20 20  else{.          
4e70: 2f 2a 20 49 66 20 74 68 65 20 66 69 72 73 74 20  /* If the first 
4e80: 6f 76 65 72 66 6c 6f 77 20 66 69 6c 65 20 65 78  overflow file ex
4e90: 69 73 74 73 20 61 6e 64 20 69 66 20 74 68 65 20  ists and if the 
4ea0: 73 69 7a 65 20 6f 66 20 74 68 65 20 6d 61 69 6e  size of the main
4eb0: 20 66 69 6c 65 0a 20 20 20 20 20 20 20 20 20 20   file.          
4ec0: 2a 2a 20 69 73 20 64 69 66 66 65 72 65 6e 74 20  ** is different 
4ed0: 66 72 6f 6d 20 74 68 65 20 63 68 75 6e 6b 20 73  from the chunk s
4ee0: 69 7a 65 2c 20 74 68 61 74 20 6d 65 61 6e 73 20  ize, that means 
4ef0: 74 68 65 20 63 68 75 6e 6b 20 73 69 7a 65 20 69  the chunk size i
4f00: 73 20 73 65 74 0a 20 20 20 20 20 20 20 20 20 20  s set.          
4f10: 2a 2a 20 73 65 74 20 69 6e 63 6f 72 72 65 63 74  ** set incorrect
4f20: 6c 79 2e 20 20 53 6f 20 66 69 78 20 69 74 2e 0a  ly.  So fix it..
4f30: 20 20 20 20 20 20 20 20 20 20 2a 2a 0a 20 20 20            **.   
4f40: 20 20 20 20 20 20 20 2a 2a 20 4f 72 2c 20 69 66         ** Or, if
4f50: 20 74 68 65 20 66 69 72 73 74 20 6f 76 65 72 66   the first overf
4f60: 6c 6f 77 20 66 69 6c 65 20 64 6f 65 73 20 6e 6f  low file does no
4f70: 74 20 65 78 69 73 74 20 61 6e 64 20 74 68 65 20  t exist and the 
4f80: 6d 61 69 6e 20 66 69 6c 65 20 69 73 0a 20 20 20  main file is.   
4f90: 20 20 20 20 20 20 20 2a 2a 20 6c 61 72 67 65 72         ** larger
4fa0: 20 74 68 61 6e 20 74 68 65 20 63 68 75 6e 6b 20   than the chunk 
4fb0: 73 69 7a 65 2c 20 74 68 61 74 20 6d 65 61 6e 73  size, that means
4fc0: 20 74 68 65 20 63 68 75 6e 6b 20 73 69 7a 65 20   the chunk size 
4fd0: 69 73 20 74 6f 6f 20 73 6d 61 6c 6c 2e 0a 20 20  is too small..  
4fe0: 20 20 20 20 20 20 20 20 2a 2a 20 42 75 74 20 77          ** But w
4ff0: 65 20 68 61 76 65 20 6e 6f 20 77 61 79 20 6f 66  e have no way of
5000: 20 64 65 74 65 72 6d 69 6e 69 6e 67 20 74 68 65   determining the
5010: 20 69 6e 74 65 6e 64 65 64 20 63 68 75 6e 6b 20   intended chunk 
5020: 73 69 7a 65 2c 20 73 6f 20 0a 20 20 20 20 20 20  size, so .      
5030: 20 20 20 20 2a 2a 20 6a 75 73 74 20 64 69 73 61      ** just disa
5040: 62 6c 65 20 74 68 65 20 6d 75 6c 74 69 70 6c 65  ble the multiple
5050: 78 6f 72 20 61 6c 6c 20 74 6f 67 65 74 68 72 65  xor all togethre
5060: 2e 0a 20 20 20 20 20 20 20 20 20 20 2a 2f 0a 20  ..          */. 
5070: 20 20 20 20 20 20 20 20 20 72 63 20 3d 20 70 4f           rc = pO
5080: 72 69 67 56 66 73 2d 3e 78 41 63 63 65 73 73 28  rigVfs->xAccess(
5090: 70 4f 72 69 67 56 66 73 2c 20 70 47 72 6f 75 70  pOrigVfs, pGroup
50a0: 2d 3e 61 52 65 61 6c 5b 31 5d 2e 7a 2c 0a 20 20  ->aReal[1].z,.  
50b0: 20 20 20 20 20 20 20 20 20 20 20 20 53 51 4c 49              SQLI
50c0: 54 45 5f 41 43 43 45 53 53 5f 45 58 49 53 54 53  TE_ACCESS_EXISTS
50d0: 2c 20 26 62 45 78 69 73 74 73 29 3b 0a 20 20 20  , &bExists);.   
50e0: 20 20 20 20 20 20 20 62 45 78 69 73 74 73 20 3d         bExists =
50f0: 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 53 69 7a   multiplexSubSiz
5100: 65 28 70 47 72 6f 75 70 2c 20 31 2c 20 26 72 63  e(pGroup, 1, &rc
5110: 29 3e 30 3b 0a 20 20 20 20 20 20 20 20 20 20 69  )>0;.          i
5120: 66 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b  f( rc==SQLITE_OK
5130: 20 26 26 20 62 45 78 69 73 74 73 20 20 26 26 20   && bExists  && 
5140: 73 7a 3d 3d 28 73 7a 26 30 78 66 66 66 66 30 30  sz==(sz&0xffff00
5150: 30 30 29 20 26 26 20 73 7a 3e 30 0a 20 20 20 20  00) && sz>0.    
5160: 20 20 20 20 20 20 20 20 20 20 26 26 20 73 7a 21            && sz!
5170: 3d 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b  =pGroup->szChunk
5180: 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20 20 20   ){.            
5190: 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 20  pGroup->szChunk 
51a0: 3d 20 73 7a 3b 0a 20 20 20 20 20 20 20 20 20 20  = sz;.          
51b0: 7d 65 6c 73 65 20 69 66 28 20 72 63 3d 3d 53 51  }else if( rc==SQ
51c0: 4c 49 54 45 5f 4f 4b 20 26 26 20 21 62 45 78 69  LITE_OK && !bExi
51d0: 73 74 73 20 26 26 20 73 7a 3e 70 47 72 6f 75 70  sts && sz>pGroup
51e0: 2d 3e 73 7a 43 68 75 6e 6b 20 29 7b 0a 20 20 20  ->szChunk ){.   
51f0: 20 20 20 20 20 20 20 20 20 70 47 72 6f 75 70 2d           pGroup-
5200: 3e 62 45 6e 61 62 6c 65 64 20 3d 20 30 3b 0a 20  >bEnabled = 0;. 
5210: 20 20 20 20 20 20 20 20 20 7d 0a 20 20 20 20 20           }.     
5220: 20 20 20 7d 0a 20 20 20 20 20 20 7d 0a 20 20 20     }.      }.   
5230: 20 7d 0a 0a 20 20 20 20 69 66 28 20 72 63 3d 3d   }..    if( rc==
5240: 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20  SQLITE_OK ){.   
5250: 20 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e 2d     if( pSubOpen-
5260: 3e 70 4d 65 74 68 6f 64 73 2d 3e 69 56 65 72 73  >pMethods->iVers
5270: 69 6f 6e 3d 3d 31 20 29 7b 0a 20 20 20 20 20 20  ion==1 ){.      
5280: 20 20 70 4d 75 6c 74 69 70 6c 65 78 4f 70 65 6e    pMultiplexOpen
5290: 2d 3e 62 61 73 65 2e 70 4d 65 74 68 6f 64 73 20  ->base.pMethods 
52a0: 3d 20 26 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49  = &gMultiplex.sI
52b0: 6f 4d 65 74 68 6f 64 73 56 31 3b 0a 20 20 20 20  oMethodsV1;.    
52c0: 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 20    }else{.       
52d0: 20 70 4d 75 6c 74 69 70 6c 65 78 4f 70 65 6e 2d   pMultiplexOpen-
52e0: 3e 62 61 73 65 2e 70 4d 65 74 68 6f 64 73 20 3d  >base.pMethods =
52f0: 20 26 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f   &gMultiplex.sIo
5300: 4d 65 74 68 6f 64 73 56 32 3b 0a 20 20 20 20 20  MethodsV2;.     
5310: 20 7d 0a 20 20 20 20 20 20 2f 2a 20 70 6c 61 63   }.      /* plac
5320: 65 20 74 68 69 73 20 67 72 6f 75 70 20 61 74 20  e this group at 
5330: 74 68 65 20 68 65 61 64 20 6f 66 20 6f 75 72 20  the head of our 
5340: 6c 69 73 74 20 2a 2f 0a 20 20 20 20 20 20 70 47  list */.      pG
5350: 72 6f 75 70 2d 3e 70 4e 65 78 74 20 3d 20 67 4d  roup->pNext = gM
5360: 75 6c 74 69 70 6c 65 78 2e 70 47 72 6f 75 70 73  ultiplex.pGroups
5370: 3b 0a 20 20 20 20 20 20 69 66 28 20 67 4d 75 6c  ;.      if( gMul
5380: 74 69 70 6c 65 78 2e 70 47 72 6f 75 70 73 20 29  tiplex.pGroups )
5390: 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 47 72 6f   gMultiplex.pGro
53a0: 75 70 73 2d 3e 70 50 72 65 76 20 3d 20 70 47 72  ups->pPrev = pGr
53b0: 6f 75 70 3b 0a 20 20 20 20 20 20 67 4d 75 6c 74  oup;.      gMult
53c0: 69 70 6c 65 78 2e 70 47 72 6f 75 70 73 20 3d 20  iplex.pGroups = 
53d0: 70 47 72 6f 75 70 3b 0a 20 20 20 20 7d 65 6c 73  pGroup;.    }els
53e0: 65 7b 0a 20 20 20 20 20 20 6d 75 6c 74 69 70 6c  e{.      multipl
53f0: 65 78 46 72 65 65 43 6f 6d 70 6f 6e 65 6e 74 73  exFreeComponents
5400: 28 70 47 72 6f 75 70 29 3b 0a 20 20 20 20 20 20  (pGroup);.      
5410: 73 71 6c 69 74 65 33 5f 66 72 65 65 28 70 47 72  sqlite3_free(pGr
5420: 6f 75 70 29 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a  oup);.    }.  }.
5430: 20 20 6d 75 6c 74 69 70 6c 65 78 4c 65 61 76 65    multiplexLeave
5440: 28 29 3b 0a 20 20 73 71 6c 69 74 65 33 5f 66 72  ();.  sqlite3_fr
5450: 65 65 28 7a 54 6f 46 72 65 65 29 3b 0a 20 20 72  ee(zToFree);.  r
5460: 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 0a  eturn rc;.}../*.
5470: 2a 2a 20 54 68 69 73 20 69 73 20 74 68 65 20 78  ** This is the x
5480: 44 65 6c 65 74 65 20 6d 65 74 68 6f 64 20 75 73  Delete method us
5490: 65 64 20 66 6f 72 20 74 68 65 20 22 6d 75 6c 74  ed for the "mult
54a0: 69 70 6c 65 78 22 20 56 46 53 2e 0a 2a 2a 20 49  iplex" VFS..** I
54b0: 74 20 61 74 74 65 6d 70 74 73 20 74 6f 20 64 65  t attempts to de
54c0: 6c 65 74 65 20 74 68 65 20 66 69 6c 65 6e 61 6d  lete the filenam
54d0: 65 20 73 70 65 63 69 66 69 65 64 2e 0a 2a 2f 0a  e specified..*/.
54e0: 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69  static int multi
54f0: 70 6c 65 78 44 65 6c 65 74 65 28 0a 20 20 73 71  plexDelete(.  sq
5500: 6c 69 74 65 33 5f 76 66 73 20 2a 70 56 66 73 2c  lite3_vfs *pVfs,
5510: 20 20 20 20 20 20 20 20 20 2f 2a 20 54 68 65 20           /* The 
5520: 6d 75 6c 74 69 70 6c 65 78 20 56 46 53 20 2a 2f  multiplex VFS */
5530: 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a  .  const char *z
5540: 4e 61 6d 65 2c 20 20 20 20 20 20 20 20 20 2f 2a  Name,         /*
5550: 20 4e 61 6d 65 20 6f 66 20 66 69 6c 65 20 74 6f   Name of file to
5560: 20 64 65 6c 65 74 65 20 2a 2f 0a 20 20 69 6e 74   delete */.  int
5570: 20 73 79 6e 63 44 69 72 0a 29 7b 0a 20 20 69 6e   syncDir.){.  in
5580: 74 20 72 63 3b 0a 20 20 73 71 6c 69 74 65 33 5f  t rc;.  sqlite3_
5590: 76 66 73 20 2a 70 4f 72 69 67 56 66 73 20 3d 20  vfs *pOrigVfs = 
55a0: 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67  gMultiplex.pOrig
55b0: 56 66 73 3b 20 20 20 2f 2a 20 52 65 61 6c 20 56  Vfs;   /* Real V
55c0: 46 53 20 2a 2f 0a 20 20 72 63 20 3d 20 70 4f 72  FS */.  rc = pOr
55d0: 69 67 56 66 73 2d 3e 78 44 65 6c 65 74 65 28 70  igVfs->xDelete(p
55e0: 4f 72 69 67 56 66 73 2c 20 7a 4e 61 6d 65 2c 20  OrigVfs, zName, 
55f0: 73 79 6e 63 44 69 72 29 3b 0a 20 20 69 66 28 20  syncDir);.  if( 
5600: 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b  rc==SQLITE_OK ){
5610: 0a 20 20 20 20 2f 2a 20 49 66 20 74 68 65 20 6d  .    /* If the m
5620: 61 69 6e 20 63 68 75 6e 6b 20 77 61 73 20 64 65  ain chunk was de
5630: 6c 65 74 65 64 20 73 75 63 63 65 73 73 66 75 6c  leted successful
5640: 6c 79 2c 20 61 6c 73 6f 20 64 65 6c 65 74 65 20  ly, also delete 
5650: 61 6e 79 20 73 75 62 73 65 71 75 65 6e 74 0a 20  any subsequent. 
5660: 20 20 20 2a 2a 20 63 68 75 6e 6b 73 20 2d 20 73     ** chunks - s
5670: 74 61 72 74 69 6e 67 20 77 69 74 68 20 74 68 65  tarting with the
5680: 20 6c 61 73 74 20 28 68 69 67 68 65 73 74 20 6e   last (highest n
5690: 75 6d 62 65 72 65 64 29 2e 20 0a 20 20 20 20 2a  umbered). .    *
56a0: 2f 0a 20 20 20 20 69 6e 74 20 6e 4e 61 6d 65 20  /.    int nName 
56b0: 3d 20 73 74 72 6c 65 6e 28 7a 4e 61 6d 65 29 3b  = strlen(zName);
56c0: 0a 20 20 20 20 63 68 61 72 20 2a 7a 3b 0a 20 20  .    char *z;.  
56d0: 20 20 7a 20 3d 20 73 71 6c 69 74 65 33 5f 6d 61    z = sqlite3_ma
56e0: 6c 6c 6f 63 28 6e 4e 61 6d 65 20 2b 20 35 29 3b  lloc(nName + 5);
56f0: 0a 20 20 20 20 69 66 28 20 7a 3d 3d 30 20 29 7b  .    if( z==0 ){
5700: 0a 20 20 20 20 20 20 72 63 20 3d 20 53 51 4c 49  .      rc = SQLI
5710: 54 45 5f 49 4f 45 52 52 5f 4e 4f 4d 45 4d 3b 0a  TE_IOERR_NOMEM;.
5720: 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20      }else{.     
5730: 20 69 6e 74 20 69 43 68 75 6e 6b 20 3d 20 30 3b   int iChunk = 0;
5740: 0a 20 20 20 20 20 20 69 6e 74 20 62 45 78 69 73  .      int bExis
5750: 74 73 3b 0a 20 20 20 20 20 20 64 6f 7b 0a 20 20  ts;.      do{.  
5760: 20 20 20 20 20 20 6d 75 6c 74 69 70 6c 65 78 46        multiplexF
5770: 69 6c 65 6e 61 6d 65 28 7a 4e 61 6d 65 2c 20 6e  ilename(zName, n
5780: 4e 61 6d 65 2c 20 53 51 4c 49 54 45 5f 4f 50 45  Name, SQLITE_OPE
5790: 4e 5f 4d 41 49 4e 5f 4a 4f 55 52 4e 41 4c 2c 20  N_MAIN_JOURNAL, 
57a0: 2b 2b 69 43 68 75 6e 6b 2c 20 7a 29 3b 0a 20 20  ++iChunk, z);.  
57b0: 20 20 20 20 20 20 72 63 20 3d 20 70 4f 72 69 67        rc = pOrig
57c0: 56 66 73 2d 3e 78 41 63 63 65 73 73 28 70 4f 72  Vfs->xAccess(pOr
57d0: 69 67 56 66 73 2c 20 7a 2c 20 53 51 4c 49 54 45  igVfs, z, SQLITE
57e0: 5f 41 43 43 45 53 53 5f 45 58 49 53 54 53 2c 20  _ACCESS_EXISTS, 
57f0: 26 62 45 78 69 73 74 73 29 3b 0a 20 20 20 20 20  &bExists);.     
5800: 20 7d 77 68 69 6c 65 28 20 72 63 3d 3d 53 51 4c   }while( rc==SQL
5810: 49 54 45 5f 4f 4b 20 26 26 20 62 45 78 69 73 74  ITE_OK && bExist
5820: 73 20 29 3b 0a 20 20 20 20 20 20 77 68 69 6c 65  s );.      while
5830: 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20  ( rc==SQLITE_OK 
5840: 26 26 20 69 43 68 75 6e 6b 3e 31 20 29 7b 0a 20  && iChunk>1 ){. 
5850: 20 20 20 20 20 20 20 6d 75 6c 74 69 70 6c 65 78         multiplex
5860: 46 69 6c 65 6e 61 6d 65 28 7a 4e 61 6d 65 2c 20  Filename(zName, 
5870: 6e 4e 61 6d 65 2c 20 53 51 4c 49 54 45 5f 4f 50  nName, SQLITE_OP
5880: 45 4e 5f 4d 41 49 4e 5f 4a 4f 55 52 4e 41 4c 2c  EN_MAIN_JOURNAL,
5890: 20 2d 2d 69 43 68 75 6e 6b 2c 20 7a 29 3b 0a 20   --iChunk, z);. 
58a0: 20 20 20 20 20 20 20 72 63 20 3d 20 70 4f 72 69         rc = pOri
58b0: 67 56 66 73 2d 3e 78 44 65 6c 65 74 65 28 70 4f  gVfs->xDelete(pO
58c0: 72 69 67 56 66 73 2c 20 7a 2c 20 73 79 6e 63 44  rigVfs, z, syncD
58d0: 69 72 29 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20  ir);.      }.   
58e0: 20 7d 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 66   }.    sqlite3_f
58f0: 72 65 65 28 7a 29 3b 0a 20 20 7d 0a 20 20 72 65  ree(z);.  }.  re
5900: 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 73 74 61 74  turn rc;.}..stat
5910: 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78  ic int multiplex
5920: 41 63 63 65 73 73 28 73 71 6c 69 74 65 33 5f 76  Access(sqlite3_v
5930: 66 73 20 2a 61 2c 20 63 6f 6e 73 74 20 63 68 61  fs *a, const cha
5940: 72 20 2a 62 2c 20 69 6e 74 20 63 2c 20 69 6e 74  r *b, int c, int
5950: 20 2a 64 29 7b 0a 20 20 72 65 74 75 72 6e 20 67   *d){.  return g
5960: 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56  Multiplex.pOrigV
5970: 66 73 2d 3e 78 41 63 63 65 73 73 28 67 4d 75 6c  fs->xAccess(gMul
5980: 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2c  tiplex.pOrigVfs,
5990: 20 62 2c 20 63 2c 20 64 29 3b 0a 7d 0a 73 74 61   b, c, d);.}.sta
59a0: 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65  tic int multiple
59b0: 78 46 75 6c 6c 50 61 74 68 6e 61 6d 65 28 73 71  xFullPathname(sq
59c0: 6c 69 74 65 33 5f 76 66 73 20 2a 61 2c 20 63 6f  lite3_vfs *a, co
59d0: 6e 73 74 20 63 68 61 72 20 2a 62 2c 20 69 6e 74  nst char *b, int
59e0: 20 63 2c 20 63 68 61 72 20 2a 64 29 7b 0a 20 20   c, char *d){.  
59f0: 72 65 74 75 72 6e 20 67 4d 75 6c 74 69 70 6c 65  return gMultiple
5a00: 78 2e 70 4f 72 69 67 56 66 73 2d 3e 78 46 75 6c  x.pOrigVfs->xFul
5a10: 6c 50 61 74 68 6e 61 6d 65 28 67 4d 75 6c 74 69  lPathname(gMulti
5a20: 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2c 20 62  plex.pOrigVfs, b
5a30: 2c 20 63 2c 20 64 29 3b 0a 7d 0a 73 74 61 74 69  , c, d);.}.stati
5a40: 63 20 76 6f 69 64 20 2a 6d 75 6c 74 69 70 6c 65  c void *multiple
5a50: 78 44 6c 4f 70 65 6e 28 73 71 6c 69 74 65 33 5f  xDlOpen(sqlite3_
5a60: 76 66 73 20 2a 61 2c 20 63 6f 6e 73 74 20 63 68  vfs *a, const ch
5a70: 61 72 20 2a 62 29 7b 0a 20 20 72 65 74 75 72 6e  ar *b){.  return
5a80: 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69   gMultiplex.pOri
5a90: 67 56 66 73 2d 3e 78 44 6c 4f 70 65 6e 28 67 4d  gVfs->xDlOpen(gM
5aa0: 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66  ultiplex.pOrigVf
5ab0: 73 2c 20 62 29 3b 0a 7d 0a 73 74 61 74 69 63 20  s, b);.}.static 
5ac0: 76 6f 69 64 20 6d 75 6c 74 69 70 6c 65 78 44 6c  void multiplexDl
5ad0: 45 72 72 6f 72 28 73 71 6c 69 74 65 33 5f 76 66  Error(sqlite3_vf
5ae0: 73 20 2a 61 2c 20 69 6e 74 20 62 2c 20 63 68 61  s *a, int b, cha
5af0: 72 20 2a 63 29 7b 0a 20 20 67 4d 75 6c 74 69 70  r *c){.  gMultip
5b00: 6c 65 78 2e 70 4f 72 69 67 56 66 73 2d 3e 78 44  lex.pOrigVfs->xD
5b10: 6c 45 72 72 6f 72 28 67 4d 75 6c 74 69 70 6c 65  lError(gMultiple
5b20: 78 2e 70 4f 72 69 67 56 66 73 2c 20 62 2c 20 63  x.pOrigVfs, b, c
5b30: 29 3b 0a 7d 0a 73 74 61 74 69 63 20 76 6f 69 64  );.}.static void
5b40: 20 28 2a 6d 75 6c 74 69 70 6c 65 78 44 6c 53 79   (*multiplexDlSy
5b50: 6d 28 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 61  m(sqlite3_vfs *a
5b60: 2c 20 76 6f 69 64 20 2a 62 2c 20 63 6f 6e 73 74  , void *b, const
5b70: 20 63 68 61 72 20 2a 63 29 29 28 76 6f 69 64 29   char *c))(void)
5b80: 7b 0a 20 20 72 65 74 75 72 6e 20 67 4d 75 6c 74  {.  return gMult
5b90: 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2d 3e  iplex.pOrigVfs->
5ba0: 78 44 6c 53 79 6d 28 67 4d 75 6c 74 69 70 6c 65  xDlSym(gMultiple
5bb0: 78 2e 70 4f 72 69 67 56 66 73 2c 20 62 2c 20 63  x.pOrigVfs, b, c
5bc0: 29 3b 0a 7d 0a 73 74 61 74 69 63 20 76 6f 69 64  );.}.static void
5bd0: 20 6d 75 6c 74 69 70 6c 65 78 44 6c 43 6c 6f 73   multiplexDlClos
5be0: 65 28 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 61  e(sqlite3_vfs *a
5bf0: 2c 20 76 6f 69 64 20 2a 62 29 7b 0a 20 20 67 4d  , void *b){.  gM
5c00: 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66  ultiplex.pOrigVf
5c10: 73 2d 3e 78 44 6c 43 6c 6f 73 65 28 67 4d 75 6c  s->xDlClose(gMul
5c20: 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2c  tiplex.pOrigVfs,
5c30: 20 62 29 3b 0a 7d 0a 73 74 61 74 69 63 20 69 6e   b);.}.static in
5c40: 74 20 6d 75 6c 74 69 70 6c 65 78 52 61 6e 64 6f  t multiplexRando
5c50: 6d 6e 65 73 73 28 73 71 6c 69 74 65 33 5f 76 66  mness(sqlite3_vf
5c60: 73 20 2a 61 2c 20 69 6e 74 20 62 2c 20 63 68 61  s *a, int b, cha
5c70: 72 20 2a 63 29 7b 0a 20 20 72 65 74 75 72 6e 20  r *c){.  return 
5c80: 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67  gMultiplex.pOrig
5c90: 56 66 73 2d 3e 78 52 61 6e 64 6f 6d 6e 65 73 73  Vfs->xRandomness
5ca0: 28 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69  (gMultiplex.pOri
5cb0: 67 56 66 73 2c 20 62 2c 20 63 29 3b 0a 7d 0a 73  gVfs, b, c);.}.s
5cc0: 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70  tatic int multip
5cd0: 6c 65 78 53 6c 65 65 70 28 73 71 6c 69 74 65 33  lexSleep(sqlite3
5ce0: 5f 76 66 73 20 2a 61 2c 20 69 6e 74 20 62 29 7b  _vfs *a, int b){
5cf0: 0a 20 20 72 65 74 75 72 6e 20 67 4d 75 6c 74 69  .  return gMulti
5d00: 70 6c 65 78 2e 70 4f 72 69 67 56 66 73 2d 3e 78  plex.pOrigVfs->x
5d10: 53 6c 65 65 70 28 67 4d 75 6c 74 69 70 6c 65 78  Sleep(gMultiplex
5d20: 2e 70 4f 72 69 67 56 66 73 2c 20 62 29 3b 0a 7d  .pOrigVfs, b);.}
5d30: 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74  .static int mult
5d40: 69 70 6c 65 78 43 75 72 72 65 6e 74 54 69 6d 65  iplexCurrentTime
5d50: 28 73 71 6c 69 74 65 33 5f 76 66 73 20 2a 61 2c  (sqlite3_vfs *a,
5d60: 20 64 6f 75 62 6c 65 20 2a 62 29 7b 0a 20 20 72   double *b){.  r
5d70: 65 74 75 72 6e 20 67 4d 75 6c 74 69 70 6c 65 78  eturn gMultiplex
5d80: 2e 70 4f 72 69 67 56 66 73 2d 3e 78 43 75 72 72  .pOrigVfs->xCurr
5d90: 65 6e 74 54 69 6d 65 28 67 4d 75 6c 74 69 70 6c  entTime(gMultipl
5da0: 65 78 2e 70 4f 72 69 67 56 66 73 2c 20 62 29 3b  ex.pOrigVfs, b);
5db0: 0a 7d 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75  .}.static int mu
5dc0: 6c 74 69 70 6c 65 78 47 65 74 4c 61 73 74 45 72  ltiplexGetLastEr
5dd0: 72 6f 72 28 73 71 6c 69 74 65 33 5f 76 66 73 20  ror(sqlite3_vfs 
5de0: 2a 61 2c 20 69 6e 74 20 62 2c 20 63 68 61 72 20  *a, int b, char 
5df0: 2a 63 29 7b 0a 20 20 72 65 74 75 72 6e 20 67 4d  *c){.  return gM
5e00: 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67 56 66  ultiplex.pOrigVf
5e10: 73 2d 3e 78 47 65 74 4c 61 73 74 45 72 72 6f 72  s->xGetLastError
5e20: 28 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69  (gMultiplex.pOri
5e30: 67 56 66 73 2c 20 62 2c 20 63 29 3b 0a 7d 0a 73  gVfs, b, c);.}.s
5e40: 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70  tatic int multip
5e50: 6c 65 78 43 75 72 72 65 6e 74 54 69 6d 65 49 6e  lexCurrentTimeIn
5e60: 74 36 34 28 73 71 6c 69 74 65 33 5f 76 66 73 20  t64(sqlite3_vfs 
5e70: 2a 61 2c 20 73 71 6c 69 74 65 33 5f 69 6e 74 36  *a, sqlite3_int6
5e80: 34 20 2a 62 29 7b 0a 20 20 72 65 74 75 72 6e 20  4 *b){.  return 
5e90: 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72 69 67  gMultiplex.pOrig
5ea0: 56 66 73 2d 3e 78 43 75 72 72 65 6e 74 54 69 6d  Vfs->xCurrentTim
5eb0: 65 49 6e 74 36 34 28 67 4d 75 6c 74 69 70 6c 65  eInt64(gMultiple
5ec0: 78 2e 70 4f 72 69 67 56 66 73 2c 20 62 29 3b 0a  x.pOrigVfs, b);.
5ed0: 7d 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  }../************
5ee0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20 49 2f 4f  ************ I/O
5ef0: 20 4d 65 74 68 6f 64 20 57 72 61 70 70 65 72 73   Method Wrappers
5f00: 20 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a   ***************
5f10: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
5f20: 2f 0a 0a 2f 2a 20 78 43 6c 6f 73 65 20 72 65 71  /../* xClose req
5f30: 75 65 73 74 73 20 67 65 74 20 70 61 73 73 65 64  uests get passed
5f40: 20 74 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20   through to the 
5f50: 6f 72 69 67 69 6e 61 6c 20 56 46 53 2e 0a 2a 2a  original VFS..**
5f60: 20 57 65 20 6c 6f 6f 70 20 6f 76 65 72 20 61 6c   We loop over al
5f70: 6c 20 6f 70 65 6e 20 63 68 75 6e 6b 20 68 61 6e  l open chunk han
5f80: 64 6c 65 73 20 61 6e 64 20 63 6c 6f 73 65 20 74  dles and close t
5f90: 68 65 6d 2e 0a 2a 2a 20 54 68 65 20 67 72 6f 75  hem..** The grou
5fa0: 70 20 73 74 72 75 63 74 75 72 65 20 66 6f 72 20  p structure for 
5fb0: 74 68 69 73 20 66 69 6c 65 20 69 73 20 75 6e 6c  this file is unl
5fc0: 69 6e 6b 65 64 20 66 72 6f 6d 20 0a 2a 2a 20 6f  inked from .** o
5fd0: 75 72 20 6c 69 73 74 20 6f 66 20 67 72 6f 75 70  ur list of group
5fe0: 73 20 61 6e 64 20 66 72 65 65 64 2e 0a 2a 2f 0a  s and freed..*/.
5ff0: 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69  static int multi
6000: 70 6c 65 78 43 6c 6f 73 65 28 73 71 6c 69 74 65  plexClose(sqlite
6010: 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 29 7b 0a  3_file *pConn){.
6020: 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20    multiplexConn 
6030: 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43  *p = (multiplexC
6040: 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 6d 75  onn*)pConn;.  mu
6050: 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 2a 70 47  ltiplexGroup *pG
6060: 72 6f 75 70 20 3d 20 70 2d 3e 70 47 72 6f 75 70  roup = p->pGroup
6070: 3b 0a 20 20 69 6e 74 20 72 63 20 3d 20 53 51 4c  ;.  int rc = SQL
6080: 49 54 45 5f 4f 4b 3b 0a 20 20 6d 75 6c 74 69 70  ITE_OK;.  multip
6090: 6c 65 78 45 6e 74 65 72 28 29 3b 0a 20 20 6d 75  lexEnter();.  mu
60a0: 6c 74 69 70 6c 65 78 46 72 65 65 43 6f 6d 70 6f  ltiplexFreeCompo
60b0: 6e 65 6e 74 73 28 70 47 72 6f 75 70 29 3b 0a 20  nents(pGroup);. 
60c0: 20 2f 2a 20 72 65 6d 6f 76 65 20 66 72 6f 6d 20   /* remove from 
60d0: 6c 69 6e 6b 65 64 20 6c 69 73 74 20 2a 2f 0a 20  linked list */. 
60e0: 20 69 66 28 20 70 47 72 6f 75 70 2d 3e 70 4e 65   if( pGroup->pNe
60f0: 78 74 20 29 20 70 47 72 6f 75 70 2d 3e 70 4e 65  xt ) pGroup->pNe
6100: 78 74 2d 3e 70 50 72 65 76 20 3d 20 70 47 72 6f  xt->pPrev = pGro
6110: 75 70 2d 3e 70 50 72 65 76 3b 0a 20 20 69 66 28  up->pPrev;.  if(
6120: 20 70 47 72 6f 75 70 2d 3e 70 50 72 65 76 20 29   pGroup->pPrev )
6130: 7b 0a 20 20 20 20 70 47 72 6f 75 70 2d 3e 70 50  {.    pGroup->pP
6140: 72 65 76 2d 3e 70 4e 65 78 74 20 3d 20 70 47 72  rev->pNext = pGr
6150: 6f 75 70 2d 3e 70 4e 65 78 74 3b 0a 20 20 7d 65  oup->pNext;.  }e
6160: 6c 73 65 7b 0a 20 20 20 20 67 4d 75 6c 74 69 70  lse{.    gMultip
6170: 6c 65 78 2e 70 47 72 6f 75 70 73 20 3d 20 70 47  lex.pGroups = pG
6180: 72 6f 75 70 2d 3e 70 4e 65 78 74 3b 0a 20 20 7d  roup->pNext;.  }
6190: 0a 20 20 73 71 6c 69 74 65 33 5f 66 72 65 65 28  .  sqlite3_free(
61a0: 70 47 72 6f 75 70 29 3b 0a 20 20 6d 75 6c 74 69  pGroup);.  multi
61b0: 70 6c 65 78 4c 65 61 76 65 28 29 3b 0a 20 20 72  plexLeave();.  r
61c0: 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 20  eturn rc;.}../* 
61d0: 50 61 73 73 20 78 52 65 61 64 20 72 65 71 75 65  Pass xRead reque
61e0: 73 74 73 20 74 68 72 75 20 74 6f 20 74 68 65 20  sts thru to the 
61f0: 6f 72 69 67 69 6e 61 6c 20 56 46 53 20 61 66 74  original VFS aft
6200: 65 72 0a 2a 2a 20 64 65 74 65 72 6d 69 6e 69 6e  er.** determinin
6210: 67 20 74 68 65 20 63 6f 72 72 65 63 74 20 63 68  g the correct ch
6220: 75 6e 6b 20 74 6f 20 6f 70 65 72 61 74 65 20 6f  unk to operate o
6230: 6e 2e 0a 2a 2a 20 42 72 65 61 6b 20 75 70 20 72  n..** Break up r
6240: 65 61 64 73 20 61 63 72 6f 73 73 20 63 68 75 6e  eads across chun
6250: 6b 20 62 6f 75 6e 64 61 72 69 65 73 2e 0a 2a 2f  k boundaries..*/
6260: 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74  .static int mult
6270: 69 70 6c 65 78 52 65 61 64 28 0a 20 20 73 71 6c  iplexRead(.  sql
6280: 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e  ite3_file *pConn
6290: 2c 0a 20 20 76 6f 69 64 20 2a 70 42 75 66 2c 0a  ,.  void *pBuf,.
62a0: 20 20 69 6e 74 20 69 41 6d 74 2c 0a 20 20 73 71    int iAmt,.  sq
62b0: 6c 69 74 65 33 5f 69 6e 74 36 34 20 69 4f 66 73  lite3_int64 iOfs
62c0: 74 0a 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78  t.){.  multiplex
62d0: 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69  Conn *p = (multi
62e0: 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b  plexConn*)pConn;
62f0: 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75  .  multiplexGrou
6300: 70 20 2a 70 47 72 6f 75 70 20 3d 20 70 2d 3e 70  p *pGroup = p->p
6310: 47 72 6f 75 70 3b 0a 20 20 69 6e 74 20 72 63 20  Group;.  int rc 
6320: 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 6d  = SQLITE_OK;.  m
6330: 75 6c 74 69 70 6c 65 78 45 6e 74 65 72 28 29 3b  ultiplexEnter();
6340: 0a 20 20 69 66 28 20 21 70 47 72 6f 75 70 2d 3e  .  if( !pGroup->
6350: 62 45 6e 61 62 6c 65 64 20 29 7b 0a 20 20 20 20  bEnabled ){.    
6360: 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53  sqlite3_file *pS
6370: 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c  ubOpen = multipl
6380: 65 78 53 75 62 4f 70 65 6e 28 70 47 72 6f 75 70  exSubOpen(pGroup
6390: 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 2c 20  , 0, &rc, NULL, 
63a0: 30 29 3b 0a 20 20 20 20 69 66 28 20 70 53 75 62  0);.    if( pSub
63b0: 4f 70 65 6e 3d 3d 30 20 29 7b 0a 20 20 20 20 20  Open==0 ){.     
63c0: 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 49 4f 45   rc = SQLITE_IOE
63d0: 52 52 5f 52 45 41 44 3b 0a 20 20 20 20 7d 65 6c  RR_READ;.    }el
63e0: 73 65 7b 0a 20 20 20 20 20 20 72 63 20 3d 20 70  se{.      rc = p
63f0: 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64  SubOpen->pMethod
6400: 73 2d 3e 78 52 65 61 64 28 70 53 75 62 4f 70 65  s->xRead(pSubOpe
6410: 6e 2c 20 70 42 75 66 2c 20 69 41 6d 74 2c 20 69  n, pBuf, iAmt, i
6420: 4f 66 73 74 29 3b 0a 20 20 20 20 7d 0a 20 20 7d  Ofst);.    }.  }
6430: 65 6c 73 65 7b 0a 20 20 20 20 77 68 69 6c 65 28  else{.    while(
6440: 20 69 41 6d 74 20 3e 20 30 20 29 7b 0a 20 20 20   iAmt > 0 ){.   
6450: 20 20 20 69 6e 74 20 69 20 3d 20 28 69 6e 74 29     int i = (int)
6460: 28 69 4f 66 73 74 20 2f 20 70 47 72 6f 75 70 2d  (iOfst / pGroup-
6470: 3e 73 7a 43 68 75 6e 6b 29 3b 0a 20 20 20 20 20  >szChunk);.     
6480: 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70   sqlite3_file *p
6490: 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70  SubOpen = multip
64a0: 6c 65 78 53 75 62 4f 70 65 6e 28 70 47 72 6f 75  lexSubOpen(pGrou
64b0: 70 2c 20 69 2c 20 26 72 63 2c 20 4e 55 4c 4c 2c  p, i, &rc, NULL,
64c0: 20 31 29 3b 0a 20 20 20 20 20 20 69 66 28 20 70   1);.      if( p
64d0: 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20 20  SubOpen ){.     
64e0: 20 20 20 69 6e 74 20 65 78 74 72 61 20 3d 20 28     int extra = (
64f0: 28 69 6e 74 29 28 69 4f 66 73 74 20 25 20 70 47  (int)(iOfst % pG
6500: 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 29 20 2b  roup->szChunk) +
6510: 20 69 41 6d 74 29 20 2d 20 70 47 72 6f 75 70 2d   iAmt) - pGroup-
6520: 3e 73 7a 43 68 75 6e 6b 3b 0a 20 20 20 20 20 20  >szChunk;.      
6530: 20 20 69 66 28 20 65 78 74 72 61 3c 30 20 29 20    if( extra<0 ) 
6540: 65 78 74 72 61 20 3d 20 30 3b 0a 20 20 20 20 20  extra = 0;.     
6550: 20 20 20 69 41 6d 74 20 2d 3d 20 65 78 74 72 61     iAmt -= extra
6560: 3b 0a 20 20 20 20 20 20 20 20 72 63 20 3d 20 70  ;.        rc = p
6570: 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64  SubOpen->pMethod
6580: 73 2d 3e 78 52 65 61 64 28 70 53 75 62 4f 70 65  s->xRead(pSubOpe
6590: 6e 2c 20 70 42 75 66 2c 20 69 41 6d 74 2c 0a 20  n, pBuf, iAmt,. 
65a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
65b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
65c0: 20 20 20 20 20 20 69 4f 66 73 74 20 25 20 70 47        iOfst % pG
65d0: 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 29 3b 0a  roup->szChunk);.
65e0: 20 20 20 20 20 20 20 20 69 66 28 20 72 63 21 3d          if( rc!=
65f0: 53 51 4c 49 54 45 5f 4f 4b 20 29 20 62 72 65 61  SQLITE_OK ) brea
6600: 6b 3b 0a 20 20 20 20 20 20 20 20 70 42 75 66 20  k;.        pBuf 
6610: 3d 20 28 63 68 61 72 20 2a 29 70 42 75 66 20 2b  = (char *)pBuf +
6620: 20 69 41 6d 74 3b 0a 20 20 20 20 20 20 20 20 69   iAmt;.        i
6630: 4f 66 73 74 20 2b 3d 20 69 41 6d 74 3b 0a 20 20  Ofst += iAmt;.  
6640: 20 20 20 20 20 20 69 41 6d 74 20 3d 20 65 78 74        iAmt = ext
6650: 72 61 3b 0a 20 20 20 20 20 20 7d 65 6c 73 65 7b  ra;.      }else{
6660: 0a 20 20 20 20 20 20 20 20 72 63 20 3d 20 53 51  .        rc = SQ
6670: 4c 49 54 45 5f 49 4f 45 52 52 5f 52 45 41 44 3b  LITE_IOERR_READ;
6680: 0a 20 20 20 20 20 20 20 20 62 72 65 61 6b 3b 0a  .        break;.
6690: 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a 20 20        }.    }.  
66a0: 7d 0a 20 20 6d 75 6c 74 69 70 6c 65 78 4c 65 61  }.  multiplexLea
66b0: 76 65 28 29 3b 0a 20 20 72 65 74 75 72 6e 20 72  ve();.  return r
66c0: 63 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 57  c;.}../* Pass xW
66d0: 72 69 74 65 20 72 65 71 75 65 73 74 73 20 74 68  rite requests th
66e0: 72 75 20 74 6f 20 74 68 65 20 6f 72 69 67 69 6e  ru to the origin
66f0: 61 6c 20 56 46 53 20 61 66 74 65 72 0a 2a 2a 20  al VFS after.** 
6700: 64 65 74 65 72 6d 69 6e 69 6e 67 20 74 68 65 20  determining the 
6710: 63 6f 72 72 65 63 74 20 63 68 75 6e 6b 20 74 6f  correct chunk to
6720: 20 6f 70 65 72 61 74 65 20 6f 6e 2e 0a 2a 2a 20   operate on..** 
6730: 42 72 65 61 6b 20 75 70 20 77 72 69 74 65 73 20  Break up writes 
6740: 61 63 72 6f 73 73 20 63 68 75 6e 6b 20 62 6f 75  across chunk bou
6750: 6e 64 61 72 69 65 73 2e 0a 2a 2f 0a 73 74 61 74  ndaries..*/.stat
6760: 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78  ic int multiplex
6770: 57 72 69 74 65 28 0a 20 20 73 71 6c 69 74 65 33  Write(.  sqlite3
6780: 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c 0a 20 20  _file *pConn,.  
6790: 63 6f 6e 73 74 20 76 6f 69 64 20 2a 70 42 75 66  const void *pBuf
67a0: 2c 0a 20 20 69 6e 74 20 69 41 6d 74 2c 0a 20 20  ,.  int iAmt,.  
67b0: 73 71 6c 69 74 65 33 5f 69 6e 74 36 34 20 69 4f  sqlite3_int64 iO
67c0: 66 73 74 0a 29 7b 0a 20 20 6d 75 6c 74 69 70 6c  fst.){.  multipl
67d0: 65 78 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c  exConn *p = (mul
67e0: 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e  tiplexConn*)pCon
67f0: 6e 3b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47 72  n;.  multiplexGr
6800: 6f 75 70 20 2a 70 47 72 6f 75 70 20 3d 20 70 2d  oup *pGroup = p-
6810: 3e 70 47 72 6f 75 70 3b 0a 20 20 69 6e 74 20 72  >pGroup;.  int r
6820: 63 20 3d 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20  c = SQLITE_OK;. 
6830: 20 6d 75 6c 74 69 70 6c 65 78 45 6e 74 65 72 28   multiplexEnter(
6840: 29 3b 0a 20 20 69 66 28 20 21 70 47 72 6f 75 70  );.  if( !pGroup
6850: 2d 3e 62 45 6e 61 62 6c 65 64 20 29 7b 0a 20 20  ->bEnabled ){.  
6860: 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a    sqlite3_file *
6870: 70 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69  pSubOpen = multi
6880: 70 6c 65 78 53 75 62 4f 70 65 6e 28 70 47 72 6f  plexSubOpen(pGro
6890: 75 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c  up, 0, &rc, NULL
68a0: 2c 20 30 29 3b 0a 20 20 20 20 69 66 28 20 70 53  , 0);.    if( pS
68b0: 75 62 4f 70 65 6e 3d 3d 30 20 29 7b 0a 20 20 20  ubOpen==0 ){.   
68c0: 20 20 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 49     rc = SQLITE_I
68d0: 4f 45 52 52 5f 57 52 49 54 45 3b 0a 20 20 20 20  OERR_WRITE;.    
68e0: 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 72 63 20  }else{.      rc 
68f0: 3d 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74  = pSubOpen->pMet
6900: 68 6f 64 73 2d 3e 78 57 72 69 74 65 28 70 53 75  hods->xWrite(pSu
6910: 62 4f 70 65 6e 2c 20 70 42 75 66 2c 20 69 41 6d  bOpen, pBuf, iAm
6920: 74 2c 20 69 4f 66 73 74 29 3b 0a 20 20 20 20 7d  t, iOfst);.    }
6930: 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 77 68  .  }else{.    wh
6940: 69 6c 65 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f  ile( rc==SQLITE_
6950: 4f 4b 20 26 26 20 69 41 6d 74 3e 30 20 29 7b 0a  OK && iAmt>0 ){.
6960: 20 20 20 20 20 20 69 6e 74 20 69 20 3d 20 28 69        int i = (i
6970: 6e 74 29 28 69 4f 66 73 74 20 2f 20 70 47 72 6f  nt)(iOfst / pGro
6980: 75 70 2d 3e 73 7a 43 68 75 6e 6b 29 3b 0a 20 20  up->szChunk);.  
6990: 20 20 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65      sqlite3_file
69a0: 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c   *pSubOpen = mul
69b0: 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28 70 47  tiplexSubOpen(pG
69c0: 72 6f 75 70 2c 20 69 2c 20 26 72 63 2c 20 4e 55  roup, i, &rc, NU
69d0: 4c 4c 2c 20 31 29 3b 0a 20 20 20 20 20 20 69 66  LL, 1);.      if
69e0: 28 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20  ( pSubOpen ){.  
69f0: 20 20 20 20 20 20 69 6e 74 20 65 78 74 72 61 20        int extra 
6a00: 3d 20 28 28 69 6e 74 29 28 69 4f 66 73 74 20 25  = ((int)(iOfst %
6a10: 20 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b   pGroup->szChunk
6a20: 29 20 2b 20 69 41 6d 74 29 20 2d 0a 20 20 20 20  ) + iAmt) -.    
6a30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6a40: 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 3b  pGroup->szChunk;
6a50: 0a 20 20 20 20 20 20 20 20 69 66 28 20 65 78 74  .        if( ext
6a60: 72 61 3c 30 20 29 20 65 78 74 72 61 20 3d 20 30  ra<0 ) extra = 0
6a70: 3b 0a 20 20 20 20 20 20 20 20 69 41 6d 74 20 2d  ;.        iAmt -
6a80: 3d 20 65 78 74 72 61 3b 0a 20 20 20 20 20 20 20  = extra;.       
6a90: 20 72 63 20 3d 20 70 53 75 62 4f 70 65 6e 2d 3e   rc = pSubOpen->
6aa0: 70 4d 65 74 68 6f 64 73 2d 3e 78 57 72 69 74 65  pMethods->xWrite
6ab0: 28 70 53 75 62 4f 70 65 6e 2c 20 70 42 75 66 2c  (pSubOpen, pBuf,
6ac0: 20 69 41 6d 74 2c 0a 20 20 20 20 20 20 20 20 20   iAmt,.         
6ad0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6ae0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69                 i
6af0: 4f 66 73 74 20 25 20 70 47 72 6f 75 70 2d 3e 73  Ofst % pGroup->s
6b00: 7a 43 68 75 6e 6b 29 3b 0a 20 20 20 20 20 20 20  zChunk);.       
6b10: 20 70 42 75 66 20 3d 20 28 63 68 61 72 20 2a 29   pBuf = (char *)
6b20: 70 42 75 66 20 2b 20 69 41 6d 74 3b 0a 20 20 20  pBuf + iAmt;.   
6b30: 20 20 20 20 20 69 4f 66 73 74 20 2b 3d 20 69 41       iOfst += iA
6b40: 6d 74 3b 0a 20 20 20 20 20 20 20 20 69 41 6d 74  mt;.        iAmt
6b50: 20 3d 20 65 78 74 72 61 3b 0a 20 20 20 20 20 20   = extra;.      
6b60: 7d 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20 6d 75  }.    }.  }.  mu
6b70: 6c 74 69 70 6c 65 78 4c 65 61 76 65 28 29 3b 0a  ltiplexLeave();.
6b80: 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a    return rc;.}..
6b90: 2f 2a 20 50 61 73 73 20 78 54 72 75 6e 63 61 74  /* Pass xTruncat
6ba0: 65 20 72 65 71 75 65 73 74 73 20 74 68 72 75 20  e requests thru 
6bb0: 74 6f 20 74 68 65 20 6f 72 69 67 69 6e 61 6c 20  to the original 
6bc0: 56 46 53 20 61 66 74 65 72 0a 2a 2a 20 64 65 74  VFS after.** det
6bd0: 65 72 6d 69 6e 69 6e 67 20 74 68 65 20 63 6f 72  ermining the cor
6be0: 72 65 63 74 20 63 68 75 6e 6b 20 74 6f 20 6f 70  rect chunk to op
6bf0: 65 72 61 74 65 20 6f 6e 2e 20 20 44 65 6c 65 74  erate on.  Delet
6c00: 65 20 61 6e 79 0a 2a 2a 20 63 68 75 6e 6b 73 20  e any.** chunks 
6c10: 61 62 6f 76 65 20 74 68 65 20 74 72 75 6e 63 61  above the trunca
6c20: 74 65 20 6d 61 72 6b 2e 0a 2a 2f 0a 73 74 61 74  te mark..*/.stat
6c30: 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78  ic int multiplex
6c40: 54 72 75 6e 63 61 74 65 28 73 71 6c 69 74 65 33  Truncate(sqlite3
6c50: 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c 20 73 71  _file *pConn, sq
6c60: 6c 69 74 65 33 5f 69 6e 74 36 34 20 73 69 7a 65  lite3_int64 size
6c70: 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f  ){.  multiplexCo
6c80: 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c  nn *p = (multipl
6c90: 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20  exConn*)pConn;. 
6ca0: 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 20   multiplexGroup 
6cb0: 2a 70 47 72 6f 75 70 20 3d 20 70 2d 3e 70 47 72  *pGroup = p->pGr
6cc0: 6f 75 70 3b 0a 20 20 69 6e 74 20 72 63 20 3d 20  oup;.  int rc = 
6cd0: 53 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 6d 75 6c  SQLITE_OK;.  mul
6ce0: 74 69 70 6c 65 78 45 6e 74 65 72 28 29 3b 0a 20  tiplexEnter();. 
6cf0: 20 69 66 28 20 21 70 47 72 6f 75 70 2d 3e 62 45   if( !pGroup->bE
6d00: 6e 61 62 6c 65 64 20 29 7b 0a 20 20 20 20 73 71  nabled ){.    sq
6d10: 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62  lite3_file *pSub
6d20: 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78  Open = multiplex
6d30: 53 75 62 4f 70 65 6e 28 70 47 72 6f 75 70 2c 20  SubOpen(pGroup, 
6d40: 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 2c 20 30 29  0, &rc, NULL, 0)
6d50: 3b 0a 20 20 20 20 69 66 28 20 70 53 75 62 4f 70  ;.    if( pSubOp
6d60: 65 6e 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 72  en==0 ){.      r
6d70: 63 20 3d 20 53 51 4c 49 54 45 5f 49 4f 45 52 52  c = SQLITE_IOERR
6d80: 5f 54 52 55 4e 43 41 54 45 3b 0a 20 20 20 20 7d  _TRUNCATE;.    }
6d90: 65 6c 73 65 7b 0a 20 20 20 20 20 20 72 63 20 3d  else{.      rc =
6da0: 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68   pSubOpen->pMeth
6db0: 6f 64 73 2d 3e 78 54 72 75 6e 63 61 74 65 28 70  ods->xTruncate(p
6dc0: 53 75 62 4f 70 65 6e 2c 20 73 69 7a 65 29 3b 0a  SubOpen, size);.
6dd0: 20 20 20 20 7d 0a 20 20 7d 65 6c 73 65 7b 0a 20      }.  }else{. 
6de0: 20 20 20 69 6e 74 20 69 3b 0a 20 20 20 20 69 6e     int i;.    in
6df0: 74 20 69 42 61 73 65 47 72 6f 75 70 20 3d 20 28  t iBaseGroup = (
6e00: 69 6e 74 29 28 73 69 7a 65 20 2f 20 70 47 72 6f  int)(size / pGro
6e10: 75 70 2d 3e 73 7a 43 68 75 6e 6b 29 3b 0a 20 20  up->szChunk);.  
6e20: 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a    sqlite3_file *
6e30: 70 53 75 62 4f 70 65 6e 3b 0a 20 20 20 20 73 71  pSubOpen;.    sq
6e40: 6c 69 74 65 33 5f 76 66 73 20 2a 70 4f 72 69 67  lite3_vfs *pOrig
6e50: 56 66 73 20 3d 20 67 4d 75 6c 74 69 70 6c 65 78  Vfs = gMultiplex
6e60: 2e 70 4f 72 69 67 56 66 73 3b 20 20 20 2f 2a 20  .pOrigVfs;   /* 
6e70: 52 65 61 6c 20 56 46 53 20 2a 2f 0a 20 20 20 20  Real VFS */.    
6e80: 2f 2a 20 64 65 6c 65 74 65 20 74 68 65 20 63 68  /* delete the ch
6e90: 75 6e 6b 73 20 61 62 6f 76 65 20 74 68 65 20 74  unks above the t
6ea0: 72 75 6e 63 61 74 65 20 6c 69 6d 69 74 20 2a 2f  runcate limit */
6eb0: 0a 20 20 20 20 66 6f 72 28 69 20 3d 20 70 47 72  .    for(i = pGr
6ec0: 6f 75 70 2d 3e 6e 52 65 61 6c 2d 31 3b 20 69 3e  oup->nReal-1; i>
6ed0: 69 42 61 73 65 47 72 6f 75 70 20 26 26 20 72 63  iBaseGroup && rc
6ee0: 3d 3d 53 51 4c 49 54 45 5f 4f 4b 3b 20 69 2d 2d  ==SQLITE_OK; i--
6ef0: 29 7b 0a 20 20 20 20 20 20 69 66 28 20 70 47 72  ){.      if( pGr
6f00: 6f 75 70 2d 3e 62 54 72 75 6e 63 61 74 65 20 29  oup->bTruncate )
6f10: 7b 0a 20 20 20 20 20 20 20 20 6d 75 6c 74 69 70  {.        multip
6f20: 6c 65 78 53 75 62 43 6c 6f 73 65 28 70 47 72 6f  lexSubClose(pGro
6f30: 75 70 2c 20 69 2c 20 70 4f 72 69 67 56 66 73 29  up, i, pOrigVfs)
6f40: 3b 0a 20 20 20 20 20 20 7d 65 6c 73 65 7b 0a 20  ;.      }else{. 
6f50: 20 20 20 20 20 20 20 70 53 75 62 4f 70 65 6e 20         pSubOpen 
6f60: 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70  = multiplexSubOp
6f70: 65 6e 28 70 47 72 6f 75 70 2c 20 69 2c 20 26 72  en(pGroup, i, &r
6f80: 63 2c 20 30 2c 20 30 29 3b 0a 20 20 20 20 20 20  c, 0, 0);.      
6f90: 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e 20 29    if( pSubOpen )
6fa0: 7b 0a 20 20 20 20 20 20 20 20 20 20 72 63 20 3d  {.          rc =
6fb0: 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68   pSubOpen->pMeth
6fc0: 6f 64 73 2d 3e 78 54 72 75 6e 63 61 74 65 28 70  ods->xTruncate(p
6fd0: 53 75 62 4f 70 65 6e 2c 20 30 29 3b 0a 20 20 20  SubOpen, 0);.   
6fe0: 20 20 20 20 20 7d 0a 20 20 20 20 20 20 7d 0a 20       }.      }. 
6ff0: 20 20 20 7d 0a 20 20 20 20 69 66 28 20 72 63 3d     }.    if( rc=
7000: 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20  =SQLITE_OK ){.  
7010: 20 20 20 20 70 53 75 62 4f 70 65 6e 20 3d 20 6d      pSubOpen = m
7020: 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28  ultiplexSubOpen(
7030: 70 47 72 6f 75 70 2c 20 69 42 61 73 65 47 72 6f  pGroup, iBaseGro
7040: 75 70 2c 20 26 72 63 2c 20 30 2c 20 30 29 3b 0a  up, &rc, 0, 0);.
7050: 20 20 20 20 20 20 69 66 28 20 70 53 75 62 4f 70        if( pSubOp
7060: 65 6e 20 29 7b 0a 20 20 20 20 20 20 20 20 72 63  en ){.        rc
7070: 20 3d 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65   = pSubOpen->pMe
7080: 74 68 6f 64 73 2d 3e 78 54 72 75 6e 63 61 74 65  thods->xTruncate
7090: 28 70 53 75 62 4f 70 65 6e 2c 20 73 69 7a 65 20  (pSubOpen, size 
70a0: 25 20 70 47 72 6f 75 70 2d 3e 73 7a 43 68 75 6e  % pGroup->szChun
70b0: 6b 29 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20 20  k);.      }.    
70c0: 7d 0a 20 20 20 20 69 66 28 20 72 63 20 29 20 72  }.    if( rc ) r
70d0: 63 20 3d 20 53 51 4c 49 54 45 5f 49 4f 45 52 52  c = SQLITE_IOERR
70e0: 5f 54 52 55 4e 43 41 54 45 3b 0a 20 20 7d 0a 20  _TRUNCATE;.  }. 
70f0: 20 6d 75 6c 74 69 70 6c 65 78 4c 65 61 76 65 28   multiplexLeave(
7100: 29 3b 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a  );.  return rc;.
7110: 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 53 79 6e 63  }../* Pass xSync
7120: 20 72 65 71 75 65 73 74 73 20 74 68 72 6f 75 67   requests throug
7130: 68 20 74 6f 20 74 68 65 20 6f 72 69 67 69 6e 61  h to the origina
7140: 6c 20 56 46 53 20 77 69 74 68 6f 75 74 20 63 68  l VFS without ch
7150: 61 6e 67 65 0a 2a 2f 0a 73 74 61 74 69 63 20 69  ange.*/.static i
7160: 6e 74 20 6d 75 6c 74 69 70 6c 65 78 53 79 6e 63  nt multiplexSync
7170: 28 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70  (sqlite3_file *p
7180: 43 6f 6e 6e 2c 20 69 6e 74 20 66 6c 61 67 73 29  Conn, int flags)
7190: 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e  {.  multiplexCon
71a0: 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65  n *p = (multiple
71b0: 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20  xConn*)pConn;.  
71c0: 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 2a  multiplexGroup *
71d0: 70 47 72 6f 75 70 20 3d 20 70 2d 3e 70 47 72 6f  pGroup = p->pGro
71e0: 75 70 3b 0a 20 20 69 6e 74 20 72 63 20 3d 20 53  up;.  int rc = S
71f0: 51 4c 49 54 45 5f 4f 4b 3b 0a 20 20 69 6e 74 20  QLITE_OK;.  int 
7200: 69 3b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 45 6e  i;.  multiplexEn
7210: 74 65 72 28 29 3b 0a 20 20 66 6f 72 28 69 3d 30  ter();.  for(i=0
7220: 3b 20 69 3c 70 47 72 6f 75 70 2d 3e 6e 52 65 61  ; i<pGroup->nRea
7230: 6c 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 73 71 6c  l; i++){.    sql
7240: 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f  ite3_file *pSubO
7250: 70 65 6e 20 3d 20 70 47 72 6f 75 70 2d 3e 61 52  pen = pGroup->aR
7260: 65 61 6c 5b 69 5d 2e 70 3b 0a 20 20 20 20 69 66  eal[i].p;.    if
7270: 28 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20  ( pSubOpen ){.  
7280: 20 20 20 20 69 6e 74 20 72 63 32 20 3d 20 70 53      int rc2 = pS
7290: 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73  ubOpen->pMethods
72a0: 2d 3e 78 53 79 6e 63 28 70 53 75 62 4f 70 65 6e  ->xSync(pSubOpen
72b0: 2c 20 66 6c 61 67 73 29 3b 0a 20 20 20 20 20 20  , flags);.      
72c0: 69 66 28 20 72 63 32 21 3d 53 51 4c 49 54 45 5f  if( rc2!=SQLITE_
72d0: 4f 4b 20 29 20 72 63 20 3d 20 72 63 32 3b 0a 20  OK ) rc = rc2;. 
72e0: 20 20 20 7d 0a 20 20 7d 0a 20 20 6d 75 6c 74 69     }.  }.  multi
72f0: 70 6c 65 78 4c 65 61 76 65 28 29 3b 0a 20 20 72  plexLeave();.  r
7300: 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 20  eturn rc;.}../* 
7310: 50 61 73 73 20 78 46 69 6c 65 53 69 7a 65 20 72  Pass xFileSize r
7320: 65 71 75 65 73 74 73 20 74 68 72 6f 75 67 68 20  equests through 
7330: 74 6f 20 74 68 65 20 6f 72 69 67 69 6e 61 6c 20  to the original 
7340: 56 46 53 2e 0a 2a 2a 20 41 67 67 72 65 67 61 74  VFS..** Aggregat
7350: 65 20 74 68 65 20 73 69 7a 65 20 6f 66 20 61 6c  e the size of al
7360: 6c 20 74 68 65 20 63 68 75 6e 6b 73 20 62 65 66  l the chunks bef
7370: 6f 72 65 20 72 65 74 75 72 6e 69 6e 67 2e 0a 2a  ore returning..*
7380: 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c  /.static int mul
7390: 74 69 70 6c 65 78 46 69 6c 65 53 69 7a 65 28 73  tiplexFileSize(s
73a0: 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f  qlite3_file *pCo
73b0: 6e 6e 2c 20 73 71 6c 69 74 65 33 5f 69 6e 74 36  nn, sqlite3_int6
73c0: 34 20 2a 70 53 69 7a 65 29 7b 0a 20 20 6d 75 6c  4 *pSize){.  mul
73d0: 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d 20  tiplexConn *p = 
73e0: 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a 29  (multiplexConn*)
73f0: 70 43 6f 6e 6e 3b 0a 20 20 6d 75 6c 74 69 70 6c  pConn;.  multipl
7400: 65 78 47 72 6f 75 70 20 2a 70 47 72 6f 75 70 20  exGroup *pGroup 
7410: 3d 20 70 2d 3e 70 47 72 6f 75 70 3b 0a 20 20 69  = p->pGroup;.  i
7420: 6e 74 20 72 63 20 3d 20 53 51 4c 49 54 45 5f 4f  nt rc = SQLITE_O
7430: 4b 3b 0a 20 20 69 6e 74 20 69 3b 0a 20 20 6d 75  K;.  int i;.  mu
7440: 6c 74 69 70 6c 65 78 45 6e 74 65 72 28 29 3b 0a  ltiplexEnter();.
7450: 20 20 69 66 28 20 21 70 47 72 6f 75 70 2d 3e 62    if( !pGroup->b
7460: 45 6e 61 62 6c 65 64 20 29 7b 0a 20 20 20 20 73  Enabled ){.    s
7470: 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75  qlite3_file *pSu
7480: 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65  bOpen = multiple
7490: 78 53 75 62 4f 70 65 6e 28 70 47 72 6f 75 70 2c  xSubOpen(pGroup,
74a0: 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 2c 20 30   0, &rc, NULL, 0
74b0: 29 3b 0a 20 20 20 20 69 66 28 20 70 53 75 62 4f  );.    if( pSubO
74c0: 70 65 6e 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20  pen==0 ){.      
74d0: 72 63 20 3d 20 53 51 4c 49 54 45 5f 49 4f 45 52  rc = SQLITE_IOER
74e0: 52 5f 46 53 54 41 54 3b 0a 20 20 20 20 7d 65 6c  R_FSTAT;.    }el
74f0: 73 65 7b 0a 20 20 20 20 20 20 72 63 20 3d 20 70  se{.      rc = p
7500: 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64  SubOpen->pMethod
7510: 73 2d 3e 78 46 69 6c 65 53 69 7a 65 28 70 53 75  s->xFileSize(pSu
7520: 62 4f 70 65 6e 2c 20 70 53 69 7a 65 29 3b 0a 20  bOpen, pSize);. 
7530: 20 20 20 7d 0a 20 20 7d 65 6c 73 65 7b 0a 20 20     }.  }else{.  
7540: 20 20 2a 70 53 69 7a 65 20 3d 20 30 3b 0a 20 20    *pSize = 0;.  
7550: 20 20 66 6f 72 28 69 3d 30 3b 20 72 63 3d 3d 53    for(i=0; rc==S
7560: 51 4c 49 54 45 5f 4f 4b 3b 20 69 2b 2b 29 7b 0a  QLITE_OK; i++){.
7570: 20 20 20 20 20 20 73 71 6c 69 74 65 33 5f 69 6e        sqlite3_in
7580: 74 36 34 20 73 7a 20 3d 20 6d 75 6c 74 69 70 6c  t64 sz = multipl
7590: 65 78 53 75 62 53 69 7a 65 28 70 47 72 6f 75 70  exSubSize(pGroup
75a0: 2c 20 69 2c 20 26 72 63 29 3b 0a 20 20 20 20 20  , i, &rc);.     
75b0: 20 69 66 28 20 73 7a 3d 3d 30 20 29 20 62 72 65   if( sz==0 ) bre
75c0: 61 6b 3b 0a 20 20 20 20 20 20 2a 70 53 69 7a 65  ak;.      *pSize
75d0: 20 3d 20 69 2a 28 73 71 6c 69 74 65 33 5f 69 6e   = i*(sqlite3_in
75e0: 74 36 34 29 70 47 72 6f 75 70 2d 3e 73 7a 43 68  t64)pGroup->szCh
75f0: 75 6e 6b 20 2b 20 73 7a 3b 0a 20 20 20 20 7d 0a  unk + sz;.    }.
7600: 20 20 7d 0a 20 20 6d 75 6c 74 69 70 6c 65 78 4c    }.  multiplexL
7610: 65 61 76 65 28 29 3b 0a 20 20 72 65 74 75 72 6e  eave();.  return
7620: 20 72 63 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20   rc;.}../* Pass 
7630: 78 4c 6f 63 6b 20 72 65 71 75 65 73 74 73 20 74  xLock requests t
7640: 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20 6f 72  hrough to the or
7650: 69 67 69 6e 61 6c 20 56 46 53 20 75 6e 63 68 61  iginal VFS uncha
7660: 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63 20  nged..*/.static 
7670: 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 4c 6f 63  int multiplexLoc
7680: 6b 28 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a  k(sqlite3_file *
7690: 70 43 6f 6e 6e 2c 20 69 6e 74 20 6c 6f 63 6b 29  pConn, int lock)
76a0: 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e  {.  multiplexCon
76b0: 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65  n *p = (multiple
76c0: 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20  xConn*)pConn;.  
76d0: 69 6e 74 20 72 63 3b 0a 20 20 73 71 6c 69 74 65  int rc;.  sqlite
76e0: 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e  3_file *pSubOpen
76f0: 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f   = multiplexSubO
7700: 70 65 6e 28 70 2d 3e 70 47 72 6f 75 70 2c 20 30  pen(p->pGroup, 0
7710: 2c 20 26 72 63 2c 20 4e 55 4c 4c 2c 20 30 29 3b  , &rc, NULL, 0);
7720: 0a 20 20 69 66 28 20 70 53 75 62 4f 70 65 6e 20  .  if( pSubOpen 
7730: 29 7b 0a 20 20 20 20 72 65 74 75 72 6e 20 70 53  ){.    return pS
7740: 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73  ubOpen->pMethods
7750: 2d 3e 78 4c 6f 63 6b 28 70 53 75 62 4f 70 65 6e  ->xLock(pSubOpen
7760: 2c 20 6c 6f 63 6b 29 3b 0a 20 20 7d 0a 20 20 72  , lock);.  }.  r
7770: 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 42 55 53  eturn SQLITE_BUS
7780: 59 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 55  Y;.}../* Pass xU
7790: 6e 6c 6f 63 6b 20 72 65 71 75 65 73 74 73 20 74  nlock requests t
77a0: 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20 6f 72  hrough to the or
77b0: 69 67 69 6e 61 6c 20 56 46 53 20 75 6e 63 68 61  iginal VFS uncha
77c0: 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63 20  nged..*/.static 
77d0: 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 55 6e 6c  int multiplexUnl
77e0: 6f 63 6b 28 73 71 6c 69 74 65 33 5f 66 69 6c 65  ock(sqlite3_file
77f0: 20 2a 70 43 6f 6e 6e 2c 20 69 6e 74 20 6c 6f 63   *pConn, int loc
7800: 6b 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43  k){.  multiplexC
7810: 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70  onn *p = (multip
7820: 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a  lexConn*)pConn;.
7830: 20 20 69 6e 74 20 72 63 3b 0a 20 20 73 71 6c 69    int rc;.  sqli
7840: 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70  te3_file *pSubOp
7850: 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75  en = multiplexSu
7860: 62 4f 70 65 6e 28 70 2d 3e 70 47 72 6f 75 70 2c  bOpen(p->pGroup,
7870: 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 2c 20 30   0, &rc, NULL, 0
7880: 29 3b 0a 20 20 69 66 28 20 70 53 75 62 4f 70 65  );.  if( pSubOpe
7890: 6e 20 29 7b 0a 20 20 20 20 72 65 74 75 72 6e 20  n ){.    return 
78a0: 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f  pSubOpen->pMetho
78b0: 64 73 2d 3e 78 55 6e 6c 6f 63 6b 28 70 53 75 62  ds->xUnlock(pSub
78c0: 4f 70 65 6e 2c 20 6c 6f 63 6b 29 3b 0a 20 20 7d  Open, lock);.  }
78d0: 0a 20 20 72 65 74 75 72 6e 20 53 51 4c 49 54 45  .  return SQLITE
78e0: 5f 49 4f 45 52 52 5f 55 4e 4c 4f 43 4b 3b 0a 7d  _IOERR_UNLOCK;.}
78f0: 0a 0a 2f 2a 20 50 61 73 73 20 78 43 68 65 63 6b  ../* Pass xCheck
7900: 52 65 73 65 72 76 65 64 4c 6f 63 6b 20 72 65 71  ReservedLock req
7910: 75 65 73 74 73 20 74 68 72 6f 75 67 68 20 74 6f  uests through to
7920: 20 74 68 65 20 6f 72 69 67 69 6e 61 6c 20 56 46   the original VF
7930: 53 20 75 6e 63 68 61 6e 67 65 64 2e 0a 2a 2f 0a  S unchanged..*/.
7940: 73 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69  static int multi
7950: 70 6c 65 78 43 68 65 63 6b 52 65 73 65 72 76 65  plexCheckReserve
7960: 64 4c 6f 63 6b 28 73 71 6c 69 74 65 33 5f 66 69  dLock(sqlite3_fi
7970: 6c 65 20 2a 70 43 6f 6e 6e 2c 20 69 6e 74 20 2a  le *pConn, int *
7980: 70 52 65 73 4f 75 74 29 7b 0a 20 20 6d 75 6c 74  pResOut){.  mult
7990: 69 70 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d 20 28  iplexConn *p = (
79a0: 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70  multiplexConn*)p
79b0: 43 6f 6e 6e 3b 0a 20 20 69 6e 74 20 72 63 3b 0a  Conn;.  int rc;.
79c0: 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a    sqlite3_file *
79d0: 70 53 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69  pSubOpen = multi
79e0: 70 6c 65 78 53 75 62 4f 70 65 6e 28 70 2d 3e 70  plexSubOpen(p->p
79f0: 47 72 6f 75 70 2c 20 30 2c 20 26 72 63 2c 20 4e  Group, 0, &rc, N
7a00: 55 4c 4c 2c 20 30 29 3b 0a 20 20 69 66 28 20 70  ULL, 0);.  if( p
7a10: 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20 72  SubOpen ){.    r
7a20: 65 74 75 72 6e 20 70 53 75 62 4f 70 65 6e 2d 3e  eturn pSubOpen->
7a30: 70 4d 65 74 68 6f 64 73 2d 3e 78 43 68 65 63 6b  pMethods->xCheck
7a40: 52 65 73 65 72 76 65 64 4c 6f 63 6b 28 70 53 75  ReservedLock(pSu
7a50: 62 4f 70 65 6e 2c 20 70 52 65 73 4f 75 74 29 3b  bOpen, pResOut);
7a60: 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20 53 51  .  }.  return SQ
7a70: 4c 49 54 45 5f 49 4f 45 52 52 5f 43 48 45 43 4b  LITE_IOERR_CHECK
7a80: 52 45 53 45 52 56 45 44 4c 4f 43 4b 3b 0a 7d 0a  RESERVEDLOCK;.}.
7a90: 0a 2f 2a 20 50 61 73 73 20 78 46 69 6c 65 43 6f  ./* Pass xFileCo
7aa0: 6e 74 72 6f 6c 20 72 65 71 75 65 73 74 73 20 74  ntrol requests t
7ab0: 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20 6f 72  hrough to the or
7ac0: 69 67 69 6e 61 6c 20 56 46 53 20 75 6e 63 68 61  iginal VFS uncha
7ad0: 6e 67 65 64 2c 0a 2a 2a 20 65 78 63 65 70 74 20  nged,.** except 
7ae0: 66 6f 72 20 61 6e 79 20 4d 55 4c 54 49 50 4c 45  for any MULTIPLE
7af0: 58 5f 43 54 52 4c 5f 2a 20 72 65 71 75 65 73 74  X_CTRL_* request
7b00: 73 20 68 65 72 65 2e 0a 2a 2f 0a 73 74 61 74 69  s here..*/.stati
7b10: 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 46  c int multiplexF
7b20: 69 6c 65 43 6f 6e 74 72 6f 6c 28 73 71 6c 69 74  ileControl(sqlit
7b30: 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c 20  e3_file *pConn, 
7b40: 69 6e 74 20 6f 70 2c 20 76 6f 69 64 20 2a 70 41  int op, void *pA
7b50: 72 67 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78  rg){.  multiplex
7b60: 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69  Conn *p = (multi
7b70: 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b  plexConn*)pConn;
7b80: 0a 20 20 6d 75 6c 74 69 70 6c 65 78 47 72 6f 75  .  multiplexGrou
7b90: 70 20 2a 70 47 72 6f 75 70 20 3d 20 70 2d 3e 70  p *pGroup = p->p
7ba0: 47 72 6f 75 70 3b 0a 20 20 69 6e 74 20 72 63 20  Group;.  int rc 
7bb0: 3d 20 53 51 4c 49 54 45 5f 45 52 52 4f 52 3b 0a  = SQLITE_ERROR;.
7bc0: 20 20 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a    sqlite3_file *
7bd0: 70 53 75 62 4f 70 65 6e 3b 0a 0a 20 20 69 66 28  pSubOpen;..  if(
7be0: 20 21 67 4d 75 6c 74 69 70 6c 65 78 2e 69 73 49   !gMultiplex.isI
7bf0: 6e 69 74 69 61 6c 69 7a 65 64 20 29 20 72 65 74  nitialized ) ret
7c00: 75 72 6e 20 53 51 4c 49 54 45 5f 4d 49 53 55 53  urn SQLITE_MISUS
7c10: 45 3b 0a 20 20 73 77 69 74 63 68 28 20 6f 70 20  E;.  switch( op 
7c20: 29 7b 0a 20 20 20 20 63 61 73 65 20 4d 55 4c 54  ){.    case MULT
7c30: 49 50 4c 45 58 5f 43 54 52 4c 5f 45 4e 41 42 4c  IPLEX_CTRL_ENABL
7c40: 45 3a 0a 20 20 20 20 20 20 69 66 28 20 70 41 72  E:.      if( pAr
7c50: 67 20 29 20 7b 0a 20 20 20 20 20 20 20 20 69 6e  g ) {.        in
7c60: 74 20 62 45 6e 61 62 6c 65 64 20 3d 20 2a 28 69  t bEnabled = *(i
7c70: 6e 74 20 2a 29 70 41 72 67 3b 0a 20 20 20 20 20  nt *)pArg;.     
7c80: 20 20 20 70 47 72 6f 75 70 2d 3e 62 45 6e 61 62     pGroup->bEnab
7c90: 6c 65 64 20 3d 20 62 45 6e 61 62 6c 65 64 3b 0a  led = bEnabled;.
7ca0: 20 20 20 20 20 20 20 20 72 63 20 3d 20 53 51 4c          rc = SQL
7cb0: 49 54 45 5f 4f 4b 3b 0a 20 20 20 20 20 20 7d 0a  ITE_OK;.      }.
7cc0: 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20        break;.   
7cd0: 20 63 61 73 65 20 4d 55 4c 54 49 50 4c 45 58 5f   case MULTIPLEX_
7ce0: 43 54 52 4c 5f 53 45 54 5f 43 48 55 4e 4b 5f 53  CTRL_SET_CHUNK_S
7cf0: 49 5a 45 3a 0a 20 20 20 20 20 20 69 66 28 20 70  IZE:.      if( p
7d00: 41 72 67 20 29 20 7b 0a 20 20 20 20 20 20 20 20  Arg ) {.        
7d10: 75 6e 73 69 67 6e 65 64 20 69 6e 74 20 73 7a 43  unsigned int szC
7d20: 68 75 6e 6b 20 3d 20 2a 28 75 6e 73 69 67 6e 65  hunk = *(unsigne
7d30: 64 2a 29 70 41 72 67 3b 0a 20 20 20 20 20 20 20  d*)pArg;.       
7d40: 20 69 66 28 20 73 7a 43 68 75 6e 6b 3c 31 20 29   if( szChunk<1 )
7d50: 7b 0a 20 20 20 20 20 20 20 20 20 20 72 63 20 3d  {.          rc =
7d60: 20 53 51 4c 49 54 45 5f 4d 49 53 55 53 45 3b 0a   SQLITE_MISUSE;.
7d70: 20 20 20 20 20 20 20 20 7d 65 6c 73 65 7b 0a 20          }else{. 
7d80: 20 20 20 20 20 20 20 20 20 2f 2a 20 52 6f 75 6e           /* Roun
7d90: 64 20 75 70 20 74 6f 20 6e 65 61 72 65 73 74 20  d up to nearest 
7da0: 6d 75 6c 74 69 70 6c 65 20 6f 66 20 4d 41 58 5f  multiple of MAX_
7db0: 50 41 47 45 5f 53 49 5a 45 2e 20 2a 2f 0a 20 20  PAGE_SIZE. */.  
7dc0: 20 20 20 20 20 20 20 20 73 7a 43 68 75 6e 6b 20          szChunk 
7dd0: 3d 20 28 73 7a 43 68 75 6e 6b 20 2b 20 28 4d 41  = (szChunk + (MA
7de0: 58 5f 50 41 47 45 5f 53 49 5a 45 2d 31 29 29 3b  X_PAGE_SIZE-1));
7df0: 0a 20 20 20 20 20 20 20 20 20 20 73 7a 43 68 75  .          szChu
7e00: 6e 6b 20 26 3d 20 7e 28 4d 41 58 5f 50 41 47 45  nk &= ~(MAX_PAGE
7e10: 5f 53 49 5a 45 2d 31 29 3b 0a 20 20 20 20 20 20  _SIZE-1);.      
7e20: 20 20 20 20 70 47 72 6f 75 70 2d 3e 73 7a 43 68      pGroup->szCh
7e30: 75 6e 6b 20 3d 20 73 7a 43 68 75 6e 6b 3b 0a 20  unk = szChunk;. 
7e40: 20 20 20 20 20 20 20 20 20 72 63 20 3d 20 53 51           rc = SQ
7e50: 4c 49 54 45 5f 4f 4b 3b 0a 20 20 20 20 20 20 20  LITE_OK;.       
7e60: 20 7d 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 20   }.      }.     
7e70: 20 62 72 65 61 6b 3b 0a 20 20 20 20 63 61 73 65   break;.    case
7e80: 20 4d 55 4c 54 49 50 4c 45 58 5f 43 54 52 4c 5f   MULTIPLEX_CTRL_
7e90: 53 45 54 5f 4d 41 58 5f 43 48 55 4e 4b 53 3a 0a  SET_MAX_CHUNKS:.
7ea0: 20 20 20 20 20 20 72 63 20 3d 20 53 51 4c 49 54        rc = SQLIT
7eb0: 45 5f 4f 4b 3b 0a 20 20 20 20 20 20 62 72 65 61  E_OK;.      brea
7ec0: 6b 3b 0a 20 20 20 20 63 61 73 65 20 53 51 4c 49  k;.    case SQLI
7ed0: 54 45 5f 46 43 4e 54 4c 5f 53 49 5a 45 5f 48 49  TE_FCNTL_SIZE_HI
7ee0: 4e 54 3a 0a 20 20 20 20 63 61 73 65 20 53 51 4c  NT:.    case SQL
7ef0: 49 54 45 5f 46 43 4e 54 4c 5f 43 48 55 4e 4b 5f  ITE_FCNTL_CHUNK_
7f00: 53 49 5a 45 3a 0a 20 20 20 20 20 20 2f 2a 20 6e  SIZE:.      /* n
7f10: 6f 2d 6f 70 20 74 68 65 73 65 20 2a 2f 0a 20 20  o-op these */.  
7f20: 20 20 20 20 72 63 20 3d 20 53 51 4c 49 54 45 5f      rc = SQLITE_
7f30: 4f 4b 3b 0a 20 20 20 20 20 20 62 72 65 61 6b 3b  OK;.      break;
7f40: 0a 20 20 20 20 64 65 66 61 75 6c 74 3a 0a 20 20  .    default:.  
7f50: 20 20 20 20 70 53 75 62 4f 70 65 6e 20 3d 20 6d      pSubOpen = m
7f60: 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28  ultiplexSubOpen(
7f70: 70 47 72 6f 75 70 2c 20 30 2c 20 26 72 63 2c 20  pGroup, 0, &rc, 
7f80: 4e 55 4c 4c 2c 20 30 29 3b 0a 20 20 20 20 20 20  NULL, 0);.      
7f90: 69 66 28 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a  if( pSubOpen ){.
7fa0: 20 20 20 20 20 20 20 20 72 63 20 3d 20 70 53 75          rc = pSu
7fb0: 62 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d  bOpen->pMethods-
7fc0: 3e 78 46 69 6c 65 43 6f 6e 74 72 6f 6c 28 70 53  >xFileControl(pS
7fd0: 75 62 4f 70 65 6e 2c 20 6f 70 2c 20 70 41 72 67  ubOpen, op, pArg
7fe0: 29 3b 0a 20 20 20 20 20 20 20 20 69 66 28 20 6f  );.        if( o
7ff0: 70 3d 3d 53 51 4c 49 54 45 5f 46 43 4e 54 4c 5f  p==SQLITE_FCNTL_
8000: 56 46 53 4e 41 4d 45 20 26 26 20 72 63 3d 3d 53  VFSNAME && rc==S
8010: 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20  QLITE_OK ){.    
8020: 20 20 20 20 20 2a 28 63 68 61 72 2a 2a 29 70 41       *(char**)pA
8030: 72 67 20 3d 20 73 71 6c 69 74 65 33 5f 6d 70 72  rg = sqlite3_mpr
8040: 69 6e 74 66 28 22 6d 75 6c 74 69 70 6c 65 78 2f  intf("multiplex/
8050: 25 7a 22 2c 20 2a 28 63 68 61 72 2a 2a 29 70 41  %z", *(char**)pA
8060: 72 67 29 3b 0a 20 20 20 20 20 20 20 20 7d 0a 20  rg);.        }. 
8070: 20 20 20 20 20 7d 0a 20 20 20 20 20 20 62 72 65       }.      bre
8080: 61 6b 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e  ak;.  }.  return
8090: 20 72 63 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20   rc;.}../* Pass 
80a0: 78 53 65 63 74 6f 72 53 69 7a 65 20 72 65 71 75  xSectorSize requ
80b0: 65 73 74 73 20 74 68 72 6f 75 67 68 20 74 6f 20  ests through to 
80c0: 74 68 65 20 6f 72 69 67 69 6e 61 6c 20 56 46 53  the original VFS
80d0: 20 75 6e 63 68 61 6e 67 65 64 2e 0a 2a 2f 0a 73   unchanged..*/.s
80e0: 74 61 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70  tatic int multip
80f0: 6c 65 78 53 65 63 74 6f 72 53 69 7a 65 28 73 71  lexSectorSize(sq
8100: 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e  lite3_file *pCon
8110: 6e 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 43  n){.  multiplexC
8120: 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69 70  onn *p = (multip
8130: 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a  lexConn*)pConn;.
8140: 20 20 69 6e 74 20 72 63 3b 0a 20 20 73 71 6c 69    int rc;.  sqli
8150: 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f 70  te3_file *pSubOp
8160: 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 75  en = multiplexSu
8170: 62 4f 70 65 6e 28 70 2d 3e 70 47 72 6f 75 70 2c  bOpen(p->pGroup,
8180: 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 2c 20 30   0, &rc, NULL, 0
8190: 29 3b 0a 20 20 69 66 28 20 70 53 75 62 4f 70 65  );.  if( pSubOpe
81a0: 6e 20 26 26 20 70 53 75 62 4f 70 65 6e 2d 3e 70  n && pSubOpen->p
81b0: 4d 65 74 68 6f 64 73 2d 3e 78 53 65 63 74 6f 72  Methods->xSector
81c0: 53 69 7a 65 20 29 7b 0a 20 20 20 20 72 65 74 75  Size ){.    retu
81d0: 72 6e 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65  rn pSubOpen->pMe
81e0: 74 68 6f 64 73 2d 3e 78 53 65 63 74 6f 72 53 69  thods->xSectorSi
81f0: 7a 65 28 70 53 75 62 4f 70 65 6e 29 3b 0a 20 20  ze(pSubOpen);.  
8200: 7d 0a 20 20 72 65 74 75 72 6e 20 44 45 46 41 55  }.  return DEFAU
8210: 4c 54 5f 53 45 43 54 4f 52 5f 53 49 5a 45 3b 0a  LT_SECTOR_SIZE;.
8220: 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 44 65 76 69  }../* Pass xDevi
8230: 63 65 43 68 61 72 61 63 74 65 72 69 73 74 69 63  ceCharacteristic
8240: 73 20 72 65 71 75 65 73 74 73 20 74 68 72 6f 75  s requests throu
8250: 67 68 20 74 6f 20 74 68 65 20 6f 72 69 67 69 6e  gh to the origin
8260: 61 6c 20 56 46 53 20 75 6e 63 68 61 6e 67 65 64  al VFS unchanged
8270: 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20  ..*/.static int 
8280: 6d 75 6c 74 69 70 6c 65 78 44 65 76 69 63 65 43  multiplexDeviceC
8290: 68 61 72 61 63 74 65 72 69 73 74 69 63 73 28 73  haracteristics(s
82a0: 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 43 6f  qlite3_file *pCo
82b0: 6e 6e 29 7b 0a 20 20 6d 75 6c 74 69 70 6c 65 78  nn){.  multiplex
82c0: 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75 6c 74 69  Conn *p = (multi
82d0: 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b  plexConn*)pConn;
82e0: 0a 20 20 69 6e 74 20 72 63 3b 0a 20 20 73 71 6c  .  int rc;.  sql
82f0: 69 74 65 33 5f 66 69 6c 65 20 2a 70 53 75 62 4f  ite3_file *pSubO
8300: 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53  pen = multiplexS
8310: 75 62 4f 70 65 6e 28 70 2d 3e 70 47 72 6f 75 70  ubOpen(p->pGroup
8320: 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c 4c 2c 20  , 0, &rc, NULL, 
8330: 30 29 3b 0a 20 20 69 66 28 20 70 53 75 62 4f 70  0);.  if( pSubOp
8340: 65 6e 20 29 7b 0a 20 20 20 20 72 65 74 75 72 6e  en ){.    return
8350: 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65 74 68   pSubOpen->pMeth
8360: 6f 64 73 2d 3e 78 44 65 76 69 63 65 43 68 61 72  ods->xDeviceChar
8370: 61 63 74 65 72 69 73 74 69 63 73 28 70 53 75 62  acteristics(pSub
8380: 4f 70 65 6e 29 3b 0a 20 20 7d 0a 20 20 72 65 74  Open);.  }.  ret
8390: 75 72 6e 20 30 3b 0a 7d 0a 0a 2f 2a 20 50 61 73  urn 0;.}../* Pas
83a0: 73 20 78 53 68 6d 4d 61 70 20 72 65 71 75 65 73  s xShmMap reques
83b0: 74 73 20 74 68 72 6f 75 67 68 20 74 6f 20 74 68  ts through to th
83c0: 65 20 6f 72 69 67 69 6e 61 6c 20 56 46 53 20 75  e original VFS u
83d0: 6e 63 68 61 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61  nchanged..*/.sta
83e0: 74 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65  tic int multiple
83f0: 78 53 68 6d 4d 61 70 28 0a 20 20 73 71 6c 69 74  xShmMap(.  sqlit
8400: 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c 20  e3_file *pConn, 
8410: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 48 61             /* Ha
8420: 6e 64 6c 65 20 6f 70 65 6e 20 6f 6e 20 64 61 74  ndle open on dat
8430: 61 62 61 73 65 20 66 69 6c 65 20 2a 2f 0a 20 20  abase file */.  
8440: 69 6e 74 20 69 52 65 67 69 6f 6e 2c 20 20 20 20  int iRegion,    
8450: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8460: 2f 2a 20 52 65 67 69 6f 6e 20 74 6f 20 72 65 74  /* Region to ret
8470: 72 69 65 76 65 20 2a 2f 0a 20 20 69 6e 74 20 73  rieve */.  int s
8480: 7a 52 65 67 69 6f 6e 2c 20 20 20 20 20 20 20 20  zRegion,        
8490: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 53 69             /* Si
84a0: 7a 65 20 6f 66 20 72 65 67 69 6f 6e 73 20 2a 2f  ze of regions */
84b0: 0a 20 20 69 6e 74 20 62 45 78 74 65 6e 64 2c 20  .  int bExtend, 
84c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
84d0: 20 20 20 2f 2a 20 54 72 75 65 20 74 6f 20 65 78     /* True to ex
84e0: 74 65 6e 64 20 66 69 6c 65 20 69 66 20 6e 65 63  tend file if nec
84f0: 65 73 73 61 72 79 20 2a 2f 0a 20 20 76 6f 69 64  essary */.  void
8500: 20 76 6f 6c 61 74 69 6c 65 20 2a 2a 70 70 20 20   volatile **pp  
8510: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4f              /* O
8520: 55 54 3a 20 4d 61 70 70 65 64 20 6d 65 6d 6f 72  UT: Mapped memor
8530: 79 20 2a 2f 0a 29 7b 0a 20 20 6d 75 6c 74 69 70  y */.){.  multip
8540: 6c 65 78 43 6f 6e 6e 20 2a 70 20 3d 20 28 6d 75  lexConn *p = (mu
8550: 6c 74 69 70 6c 65 78 43 6f 6e 6e 2a 29 70 43 6f  ltiplexConn*)pCo
8560: 6e 6e 3b 0a 20 20 69 6e 74 20 72 63 3b 0a 20 20  nn;.  int rc;.  
8570: 73 71 6c 69 74 65 33 5f 66 69 6c 65 20 2a 70 53  sqlite3_file *pS
8580: 75 62 4f 70 65 6e 20 3d 20 6d 75 6c 74 69 70 6c  ubOpen = multipl
8590: 65 78 53 75 62 4f 70 65 6e 28 70 2d 3e 70 47 72  exSubOpen(p->pGr
85a0: 6f 75 70 2c 20 30 2c 20 26 72 63 2c 20 4e 55 4c  oup, 0, &rc, NUL
85b0: 4c 2c 20 30 29 3b 0a 20 20 69 66 28 20 70 53 75  L, 0);.  if( pSu
85c0: 62 4f 70 65 6e 20 29 7b 0a 20 20 20 20 72 65 74  bOpen ){.    ret
85d0: 75 72 6e 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d  urn pSubOpen->pM
85e0: 65 74 68 6f 64 73 2d 3e 78 53 68 6d 4d 61 70 28  ethods->xShmMap(
85f0: 70 53 75 62 4f 70 65 6e 2c 20 69 52 65 67 69 6f  pSubOpen, iRegio
8600: 6e 2c 20 73 7a 52 65 67 69 6f 6e 2c 20 62 45 78  n, szRegion, bEx
8610: 74 65 6e 64 2c 70 70 29 3b 0a 20 20 7d 0a 20 20  tend,pp);.  }.  
8620: 72 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 49 4f  return SQLITE_IO
8630: 45 52 52 3b 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20  ERR;.}../* Pass 
8640: 78 53 68 6d 4c 6f 63 6b 20 72 65 71 75 65 73 74  xShmLock request
8650: 73 20 74 68 72 6f 75 67 68 20 74 6f 20 74 68 65  s through to the
8660: 20 6f 72 69 67 69 6e 61 6c 20 56 46 53 20 75 6e   original VFS un
8670: 63 68 61 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61 74  changed..*/.stat
8680: 69 63 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78  ic int multiplex
8690: 53 68 6d 4c 6f 63 6b 28 0a 20 20 73 71 6c 69 74  ShmLock(.  sqlit
86a0: 65 33 5f 66 69 6c 65 20 2a 70 43 6f 6e 6e 2c 20  e3_file *pConn, 
86b0: 20 20 20 20 20 20 2f 2a 20 44 61 74 61 62 61 73        /* Databas
86c0: 65 20 66 69 6c 65 20 68 6f 6c 64 69 6e 67 20 74  e file holding t
86d0: 68 65 20 73 68 61 72 65 64 20 6d 65 6d 6f 72 79  he shared memory
86e0: 20 2a 2f 0a 20 20 69 6e 74 20 6f 66 73 74 2c 20   */.  int ofst, 
86f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8700: 20 2f 2a 20 46 69 72 73 74 20 6c 6f 63 6b 20 74   /* First lock t
8710: 6f 20 61 63 71 75 69 72 65 20 6f 72 20 72 65 6c  o acquire or rel
8720: 65 61 73 65 20 2a 2f 0a 20 20 69 6e 74 20 6e 2c  ease */.  int n,
8730: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8740: 20 20 20 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f       /* Number o
8750: 66 20 6c 6f 63 6b 73 20 74 6f 20 61 63 71 75 69  f locks to acqui
8760: 72 65 20 6f 72 20 72 65 6c 65 61 73 65 20 2a 2f  re or release */
8770: 0a 20 20 69 6e 74 20 66 6c 61 67 73 20 20 20 20  .  int flags    
8780: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
8790: 20 57 68 61 74 20 74 6f 20 64 6f 20 77 69 74 68   What to do with
87a0: 20 74 68 65 20 6c 6f 63 6b 20 2a 2f 0a 29 7b 0a   the lock */.){.
87b0: 20 20 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20    multiplexConn 
87c0: 2a 70 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43  *p = (multiplexC
87d0: 6f 6e 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 69 6e  onn*)pConn;.  in
87e0: 74 20 72 63 3b 0a 20 20 73 71 6c 69 74 65 33 5f  t rc;.  sqlite3_
87f0: 66 69 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d  file *pSubOpen =
8800: 20 6d 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65   multiplexSubOpe
8810: 6e 28 70 2d 3e 70 47 72 6f 75 70 2c 20 30 2c 20  n(p->pGroup, 0, 
8820: 26 72 63 2c 20 4e 55 4c 4c 2c 20 30 29 3b 0a 20  &rc, NULL, 0);. 
8830: 20 69 66 28 20 70 53 75 62 4f 70 65 6e 20 29 7b   if( pSubOpen ){
8840: 0a 20 20 20 20 72 65 74 75 72 6e 20 70 53 75 62  .    return pSub
8850: 4f 70 65 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e  Open->pMethods->
8860: 78 53 68 6d 4c 6f 63 6b 28 70 53 75 62 4f 70 65  xShmLock(pSubOpe
8870: 6e 2c 20 6f 66 73 74 2c 20 6e 2c 20 66 6c 61 67  n, ofst, n, flag
8880: 73 29 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e  s);.  }.  return
8890: 20 53 51 4c 49 54 45 5f 42 55 53 59 3b 0a 7d 0a   SQLITE_BUSY;.}.
88a0: 0a 2f 2a 20 50 61 73 73 20 78 53 68 6d 42 61 72  ./* Pass xShmBar
88b0: 72 69 65 72 20 72 65 71 75 65 73 74 73 20 74 68  rier requests th
88c0: 72 6f 75 67 68 20 74 6f 20 74 68 65 20 6f 72 69  rough to the ori
88d0: 67 69 6e 61 6c 20 56 46 53 20 75 6e 63 68 61 6e  ginal VFS unchan
88e0: 67 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 76  ged..*/.static v
88f0: 6f 69 64 20 6d 75 6c 74 69 70 6c 65 78 53 68 6d  oid multiplexShm
8900: 42 61 72 72 69 65 72 28 73 71 6c 69 74 65 33 5f  Barrier(sqlite3_
8910: 66 69 6c 65 20 2a 70 43 6f 6e 6e 29 7b 0a 20 20  file *pConn){.  
8920: 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70  multiplexConn *p
8930: 20 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e   = (multiplexCon
8940: 6e 2a 29 70 43 6f 6e 6e 3b 0a 20 20 69 6e 74 20  n*)pConn;.  int 
8950: 72 63 3b 0a 20 20 73 71 6c 69 74 65 33 5f 66 69  rc;.  sqlite3_fi
8960: 6c 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20 6d  le *pSubOpen = m
8970: 75 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28  ultiplexSubOpen(
8980: 70 2d 3e 70 47 72 6f 75 70 2c 20 30 2c 20 26 72  p->pGroup, 0, &r
8990: 63 2c 20 4e 55 4c 4c 2c 20 30 29 3b 0a 20 20 69  c, NULL, 0);.  i
89a0: 66 28 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20  f( pSubOpen ){. 
89b0: 20 20 20 70 53 75 62 4f 70 65 6e 2d 3e 70 4d 65     pSubOpen->pMe
89c0: 74 68 6f 64 73 2d 3e 78 53 68 6d 42 61 72 72 69  thods->xShmBarri
89d0: 65 72 28 70 53 75 62 4f 70 65 6e 29 3b 0a 20 20  er(pSubOpen);.  
89e0: 7d 0a 7d 0a 0a 2f 2a 20 50 61 73 73 20 78 53 68  }.}../* Pass xSh
89f0: 6d 55 6e 6d 61 70 20 72 65 71 75 65 73 74 73 20  mUnmap requests 
8a00: 74 68 72 6f 75 67 68 20 74 6f 20 74 68 65 20 6f  through to the o
8a10: 72 69 67 69 6e 61 6c 20 56 46 53 20 75 6e 63 68  riginal VFS unch
8a20: 61 6e 67 65 64 2e 0a 2a 2f 0a 73 74 61 74 69 63  anged..*/.static
8a30: 20 69 6e 74 20 6d 75 6c 74 69 70 6c 65 78 53 68   int multiplexSh
8a40: 6d 55 6e 6d 61 70 28 73 71 6c 69 74 65 33 5f 66  mUnmap(sqlite3_f
8a50: 69 6c 65 20 2a 70 43 6f 6e 6e 2c 20 69 6e 74 20  ile *pConn, int 
8a60: 64 65 6c 65 74 65 46 6c 61 67 29 7b 0a 20 20 6d  deleteFlag){.  m
8a70: 75 6c 74 69 70 6c 65 78 43 6f 6e 6e 20 2a 70 20  ultiplexConn *p 
8a80: 3d 20 28 6d 75 6c 74 69 70 6c 65 78 43 6f 6e 6e  = (multiplexConn
8a90: 2a 29 70 43 6f 6e 6e 3b 0a 20 20 69 6e 74 20 72  *)pConn;.  int r
8aa0: 63 3b 0a 20 20 73 71 6c 69 74 65 33 5f 66 69 6c  c;.  sqlite3_fil
8ab0: 65 20 2a 70 53 75 62 4f 70 65 6e 20 3d 20 6d 75  e *pSubOpen = mu
8ac0: 6c 74 69 70 6c 65 78 53 75 62 4f 70 65 6e 28 70  ltiplexSubOpen(p
8ad0: 2d 3e 70 47 72 6f 75 70 2c 20 30 2c 20 26 72 63  ->pGroup, 0, &rc
8ae0: 2c 20 4e 55 4c 4c 2c 20 30 29 3b 0a 20 20 69 66  , NULL, 0);.  if
8af0: 28 20 70 53 75 62 4f 70 65 6e 20 29 7b 0a 20 20  ( pSubOpen ){.  
8b00: 20 20 72 65 74 75 72 6e 20 70 53 75 62 4f 70 65    return pSubOpe
8b10: 6e 2d 3e 70 4d 65 74 68 6f 64 73 2d 3e 78 53 68  n->pMethods->xSh
8b20: 6d 55 6e 6d 61 70 28 70 53 75 62 4f 70 65 6e 2c  mUnmap(pSubOpen,
8b30: 20 64 65 6c 65 74 65 46 6c 61 67 29 3b 0a 20 20   deleteFlag);.  
8b40: 7d 0a 20 20 72 65 74 75 72 6e 20 53 51 4c 49 54  }.  return SQLIT
8b50: 45 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a 2a 2a 2a 2a 2a  E_OK;.}../******
8b60: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
8b70: 2a 2a 2a 2a 20 50 75 62 6c 69 63 20 49 6e 74 65  **** Public Inte
8b80: 72 66 61 63 65 73 20 2a 2a 2a 2a 2a 2a 2a 2a 2a  rfaces *********
8b90: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
8ba0: 2a 2a 2a 2a 2f 0a 2f 2a 0a 2a 2a 20 43 41 50 49  ****/./*.** CAPI
8bb0: 3a 20 49 6e 69 74 69 61 6c 69 7a 65 20 74 68 65  : Initialize the
8bc0: 20 6d 75 6c 74 69 70 6c 65 78 20 56 46 53 20 73   multiplex VFS s
8bd0: 68 69 6d 20 2d 20 73 71 6c 69 74 65 33 5f 6d 75  him - sqlite3_mu
8be0: 6c 74 69 70 6c 65 78 5f 69 6e 69 74 69 61 6c 69  ltiplex_initiali
8bf0: 7a 65 28 29 0a 2a 2a 0a 2a 2a 20 55 73 65 20 74  ze().**.** Use t
8c00: 68 65 20 56 46 53 20 6e 61 6d 65 64 20 7a 4f 72  he VFS named zOr
8c10: 69 67 56 66 73 4e 61 6d 65 20 61 73 20 74 68 65  igVfsName as the
8c20: 20 56 46 53 20 74 68 61 74 20 64 6f 65 73 20 74   VFS that does t
8c30: 68 65 20 61 63 74 75 61 6c 20 77 6f 72 6b 2e 20  he actual work. 
8c40: 20 0a 2a 2a 20 55 73 65 20 74 68 65 20 64 65 66   .** Use the def
8c50: 61 75 6c 74 20 69 66 20 7a 4f 72 69 67 56 66 73  ault if zOrigVfs
8c60: 4e 61 6d 65 3d 3d 4e 55 4c 4c 2e 20 20 0a 2a 2a  Name==NULL.  .**
8c70: 0a 2a 2a 20 54 68 65 20 6d 75 6c 74 69 70 6c 65  .** The multiple
8c80: 78 20 56 46 53 20 73 68 69 6d 20 69 73 20 6e 61  x VFS shim is na
8c90: 6d 65 64 20 22 6d 75 6c 74 69 70 6c 65 78 22 2e  med "multiplex".
8ca0: 20 20 49 74 20 77 69 6c 6c 20 62 65 63 6f 6d 65    It will become
8cb0: 20 74 68 65 20 64 65 66 61 75 6c 74 0a 2a 2a 20   the default.** 
8cc0: 56 46 53 20 69 66 20 6d 61 6b 65 44 65 66 61 75  VFS if makeDefau
8cd0: 6c 74 20 69 73 20 6e 6f 6e 2d 7a 65 72 6f 2e 0a  lt is non-zero..
8ce0: 2a 2a 0a 2a 2a 20 54 48 49 53 20 52 4f 55 54 49  **.** THIS ROUTI
8cf0: 4e 45 20 49 53 20 4e 4f 54 20 54 48 52 45 41 44  NE IS NOT THREAD
8d00: 53 41 46 45 2e 20 20 43 61 6c 6c 20 74 68 69 73  SAFE.  Call this
8d10: 20 72 6f 75 74 69 6e 65 20 65 78 61 63 74 6c 79   routine exactly
8d20: 20 6f 6e 63 65 0a 2a 2a 20 64 75 72 69 6e 67 20   once.** during 
8d30: 73 74 61 72 74 2d 75 70 2e 0a 2a 2f 0a 69 6e 74  start-up..*/.int
8d40: 20 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c   sqlite3_multipl
8d50: 65 78 5f 69 6e 69 74 69 61 6c 69 7a 65 28 63 6f  ex_initialize(co
8d60: 6e 73 74 20 63 68 61 72 20 2a 7a 4f 72 69 67 56  nst char *zOrigV
8d70: 66 73 4e 61 6d 65 2c 20 69 6e 74 20 6d 61 6b 65  fsName, int make
8d80: 44 65 66 61 75 6c 74 29 7b 0a 20 20 73 71 6c 69  Default){.  sqli
8d90: 74 65 33 5f 76 66 73 20 2a 70 4f 72 69 67 56 66  te3_vfs *pOrigVf
8da0: 73 3b 0a 20 20 69 66 28 20 67 4d 75 6c 74 69 70  s;.  if( gMultip
8db0: 6c 65 78 2e 69 73 49 6e 69 74 69 61 6c 69 7a 65  lex.isInitialize
8dc0: 64 20 29 20 72 65 74 75 72 6e 20 53 51 4c 49 54  d ) return SQLIT
8dd0: 45 5f 4d 49 53 55 53 45 3b 0a 20 20 70 4f 72 69  E_MISUSE;.  pOri
8de0: 67 56 66 73 20 3d 20 73 71 6c 69 74 65 33 5f 76  gVfs = sqlite3_v
8df0: 66 73 5f 66 69 6e 64 28 7a 4f 72 69 67 56 66 73  fs_find(zOrigVfs
8e00: 4e 61 6d 65 29 3b 0a 20 20 69 66 28 20 70 4f 72  Name);.  if( pOr
8e10: 69 67 56 66 73 3d 3d 30 20 29 20 72 65 74 75 72  igVfs==0 ) retur
8e20: 6e 20 53 51 4c 49 54 45 5f 45 52 52 4f 52 3b 0a  n SQLITE_ERROR;.
8e30: 20 20 61 73 73 65 72 74 28 20 70 4f 72 69 67 56    assert( pOrigV
8e40: 66 73 21 3d 26 67 4d 75 6c 74 69 70 6c 65 78 2e  fs!=&gMultiplex.
8e50: 73 54 68 69 73 56 66 73 20 29 3b 0a 20 20 67 4d  sThisVfs );.  gM
8e60: 75 6c 74 69 70 6c 65 78 2e 70 4d 75 74 65 78 20  ultiplex.pMutex 
8e70: 3d 20 73 71 6c 69 74 65 33 5f 6d 75 74 65 78 5f  = sqlite3_mutex_
8e80: 61 6c 6c 6f 63 28 53 51 4c 49 54 45 5f 4d 55 54  alloc(SQLITE_MUT
8e90: 45 58 5f 46 41 53 54 29 3b 0a 20 20 69 66 28 20  EX_FAST);.  if( 
8ea0: 21 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4d 75 74  !gMultiplex.pMut
8eb0: 65 78 20 29 7b 0a 20 20 20 20 72 65 74 75 72 6e  ex ){.    return
8ec0: 20 53 51 4c 49 54 45 5f 4e 4f 4d 45 4d 3b 0a 20   SQLITE_NOMEM;. 
8ed0: 20 7d 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e   }.  gMultiplex.
8ee0: 70 47 72 6f 75 70 73 20 3d 20 4e 55 4c 4c 3b 0a  pGroups = NULL;.
8ef0: 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 69 73 49    gMultiplex.isI
8f00: 6e 69 74 69 61 6c 69 7a 65 64 20 3d 20 31 3b 0a  nitialized = 1;.
8f10: 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 70 4f 72    gMultiplex.pOr
8f20: 69 67 56 66 73 20 3d 20 70 4f 72 69 67 56 66 73  igVfs = pOrigVfs
8f30: 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73  ;.  gMultiplex.s
8f40: 54 68 69 73 56 66 73 20 3d 20 2a 70 4f 72 69 67  ThisVfs = *pOrig
8f50: 56 66 73 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65  Vfs;.  gMultiple
8f60: 78 2e 73 54 68 69 73 56 66 73 2e 73 7a 4f 73 46  x.sThisVfs.szOsF
8f70: 69 6c 65 20 2b 3d 20 73 69 7a 65 6f 66 28 6d 75  ile += sizeof(mu
8f80: 6c 74 69 70 6c 65 78 43 6f 6e 6e 29 3b 0a 20 20  ltiplexConn);.  
8f90: 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54 68 69 73  gMultiplex.sThis
8fa0: 56 66 73 2e 7a 4e 61 6d 65 20 3d 20 53 51 4c 49  Vfs.zName = SQLI
8fb0: 54 45 5f 4d 55 4c 54 49 50 4c 45 58 5f 56 46 53  TE_MULTIPLEX_VFS
8fc0: 5f 4e 41 4d 45 3b 0a 20 20 67 4d 75 6c 74 69 70  _NAME;.  gMultip
8fd0: 6c 65 78 2e 73 54 68 69 73 56 66 73 2e 78 4f 70  lex.sThisVfs.xOp
8fe0: 65 6e 20 3d 20 6d 75 6c 74 69 70 6c 65 78 4f 70  en = multiplexOp
8ff0: 65 6e 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78  en;.  gMultiplex
9000: 2e 73 54 68 69 73 56 66 73 2e 78 44 65 6c 65 74  .sThisVfs.xDelet
9010: 65 20 3d 20 6d 75 6c 74 69 70 6c 65 78 44 65 6c  e = multiplexDel
9020: 65 74 65 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65  ete;.  gMultiple
9030: 78 2e 73 54 68 69 73 56 66 73 2e 78 41 63 63 65  x.sThisVfs.xAcce
9040: 73 73 20 3d 20 6d 75 6c 74 69 70 6c 65 78 41 63  ss = multiplexAc
9050: 63 65 73 73 3b 0a 20 20 67 4d 75 6c 74 69 70 6c  cess;.  gMultipl
9060: 65 78 2e 73 54 68 69 73 56 66 73 2e 78 46 75 6c  ex.sThisVfs.xFul
9070: 6c 50 61 74 68 6e 61 6d 65 20 3d 20 6d 75 6c 74  lPathname = mult
9080: 69 70 6c 65 78 46 75 6c 6c 50 61 74 68 6e 61 6d  iplexFullPathnam
9090: 65 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e  e;.  gMultiplex.
90a0: 73 54 68 69 73 56 66 73 2e 78 44 6c 4f 70 65 6e  sThisVfs.xDlOpen
90b0: 20 3d 20 6d 75 6c 74 69 70 6c 65 78 44 6c 4f 70   = multiplexDlOp
90c0: 65 6e 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78  en;.  gMultiplex
90d0: 2e 73 54 68 69 73 56 66 73 2e 78 44 6c 45 72 72  .sThisVfs.xDlErr
90e0: 6f 72 20 3d 20 6d 75 6c 74 69 70 6c 65 78 44 6c  or = multiplexDl
90f0: 45 72 72 6f 72 3b 0a 20 20 67 4d 75 6c 74 69 70  Error;.  gMultip
9100: 6c 65 78 2e 73 54 68 69 73 56 66 73 2e 78 44 6c  lex.sThisVfs.xDl
9110: 53 79 6d 20 3d 20 6d 75 6c 74 69 70 6c 65 78 44  Sym = multiplexD
9120: 6c 53 79 6d 3b 0a 20 20 67 4d 75 6c 74 69 70 6c  lSym;.  gMultipl
9130: 65 78 2e 73 54 68 69 73 56 66 73 2e 78 44 6c 43  ex.sThisVfs.xDlC
9140: 6c 6f 73 65 20 3d 20 6d 75 6c 74 69 70 6c 65 78  lose = multiplex
9150: 44 6c 43 6c 6f 73 65 3b 0a 20 20 67 4d 75 6c 74  DlClose;.  gMult
9160: 69 70 6c 65 78 2e 73 54 68 69 73 56 66 73 2e 78  iplex.sThisVfs.x
9170: 52 61 6e 64 6f 6d 6e 65 73 73 20 3d 20 6d 75 6c  Randomness = mul
9180: 74 69 70 6c 65 78 52 61 6e 64 6f 6d 6e 65 73 73  tiplexRandomness
9190: 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73  ;.  gMultiplex.s
91a0: 54 68 69 73 56 66 73 2e 78 53 6c 65 65 70 20 3d  ThisVfs.xSleep =
91b0: 20 6d 75 6c 74 69 70 6c 65 78 53 6c 65 65 70 3b   multiplexSleep;
91c0: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 54  .  gMultiplex.sT
91d0: 68 69 73 56 66 73 2e 78 43 75 72 72 65 6e 74 54  hisVfs.xCurrentT
91e0: 69 6d 65 20 3d 20 6d 75 6c 74 69 70 6c 65 78 43  ime = multiplexC
91f0: 75 72 72 65 6e 74 54 69 6d 65 3b 0a 20 20 67 4d  urrentTime;.  gM
9200: 75 6c 74 69 70 6c 65 78 2e 73 54 68 69 73 56 66  ultiplex.sThisVf
9210: 73 2e 78 47 65 74 4c 61 73 74 45 72 72 6f 72 20  s.xGetLastError 
9220: 3d 20 6d 75 6c 74 69 70 6c 65 78 47 65 74 4c 61  = multiplexGetLa
9230: 73 74 45 72 72 6f 72 3b 0a 20 20 67 4d 75 6c 74  stError;.  gMult
9240: 69 70 6c 65 78 2e 73 54 68 69 73 56 66 73 2e 78  iplex.sThisVfs.x
9250: 43 75 72 72 65 6e 74 54 69 6d 65 49 6e 74 36 34  CurrentTimeInt64
9260: 20 3d 20 6d 75 6c 74 69 70 6c 65 78 43 75 72 72   = multiplexCurr
9270: 65 6e 74 54 69 6d 65 49 6e 74 36 34 3b 0a 0a 20  entTimeInt64;.. 
9280: 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d   gMultiplex.sIoM
9290: 65 74 68 6f 64 73 56 31 2e 69 56 65 72 73 69 6f  ethodsV1.iVersio
92a0: 6e 20 3d 20 31 3b 0a 20 20 67 4d 75 6c 74 69 70  n = 1;.  gMultip
92b0: 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31  lex.sIoMethodsV1
92c0: 2e 78 43 6c 6f 73 65 20 3d 20 6d 75 6c 74 69 70  .xClose = multip
92d0: 6c 65 78 43 6c 6f 73 65 3b 0a 20 20 67 4d 75 6c  lexClose;.  gMul
92e0: 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64  tiplex.sIoMethod
92f0: 73 56 31 2e 78 52 65 61 64 20 3d 20 6d 75 6c 74  sV1.xRead = mult
9300: 69 70 6c 65 78 52 65 61 64 3b 0a 20 20 67 4d 75  iplexRead;.  gMu
9310: 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f  ltiplex.sIoMetho
9320: 64 73 56 31 2e 78 57 72 69 74 65 20 3d 20 6d 75  dsV1.xWrite = mu
9330: 6c 74 69 70 6c 65 78 57 72 69 74 65 3b 0a 20 20  ltiplexWrite;.  
9340: 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65  gMultiplex.sIoMe
9350: 74 68 6f 64 73 56 31 2e 78 54 72 75 6e 63 61 74  thodsV1.xTruncat
9360: 65 20 3d 20 6d 75 6c 74 69 70 6c 65 78 54 72 75  e = multiplexTru
9370: 6e 63 61 74 65 3b 0a 20 20 67 4d 75 6c 74 69 70  ncate;.  gMultip
9380: 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31  lex.sIoMethodsV1
9390: 2e 78 53 79 6e 63 20 3d 20 6d 75 6c 74 69 70 6c  .xSync = multipl
93a0: 65 78 53 79 6e 63 3b 0a 20 20 67 4d 75 6c 74 69  exSync;.  gMulti
93b0: 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56  plex.sIoMethodsV
93c0: 31 2e 78 46 69 6c 65 53 69 7a 65 20 3d 20 6d 75  1.xFileSize = mu
93d0: 6c 74 69 70 6c 65 78 46 69 6c 65 53 69 7a 65 3b  ltiplexFileSize;
93e0: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49  .  gMultiplex.sI
93f0: 6f 4d 65 74 68 6f 64 73 56 31 2e 78 4c 6f 63 6b  oMethodsV1.xLock
9400: 20 3d 20 6d 75 6c 74 69 70 6c 65 78 4c 6f 63 6b   = multiplexLock
9410: 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73  ;.  gMultiplex.s
9420: 49 6f 4d 65 74 68 6f 64 73 56 31 2e 78 55 6e 6c  IoMethodsV1.xUnl
9430: 6f 63 6b 20 3d 20 6d 75 6c 74 69 70 6c 65 78 55  ock = multiplexU
9440: 6e 6c 6f 63 6b 3b 0a 20 20 67 4d 75 6c 74 69 70  nlock;.  gMultip
9450: 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31  lex.sIoMethodsV1
9460: 2e 78 43 68 65 63 6b 52 65 73 65 72 76 65 64 4c  .xCheckReservedL
9470: 6f 63 6b 20 3d 20 6d 75 6c 74 69 70 6c 65 78 43  ock = multiplexC
9480: 68 65 63 6b 52 65 73 65 72 76 65 64 4c 6f 63 6b  heckReservedLock
9490: 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73  ;.  gMultiplex.s
94a0: 49 6f 4d 65 74 68 6f 64 73 56 31 2e 78 46 69 6c  IoMethodsV1.xFil
94b0: 65 43 6f 6e 74 72 6f 6c 20 3d 20 6d 75 6c 74 69  eControl = multi
94c0: 70 6c 65 78 46 69 6c 65 43 6f 6e 74 72 6f 6c 3b  plexFileControl;
94d0: 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49  .  gMultiplex.sI
94e0: 6f 4d 65 74 68 6f 64 73 56 31 2e 78 53 65 63 74  oMethodsV1.xSect
94f0: 6f 72 53 69 7a 65 20 3d 20 6d 75 6c 74 69 70 6c  orSize = multipl
9500: 65 78 53 65 63 74 6f 72 53 69 7a 65 3b 0a 20 20  exSectorSize;.  
9510: 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65  gMultiplex.sIoMe
9520: 74 68 6f 64 73 56 31 2e 78 44 65 76 69 63 65 43  thodsV1.xDeviceC
9530: 68 61 72 61 63 74 65 72 69 73 74 69 63 73 20 3d  haracteristics =
9540: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
9550: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9560: 20 20 20 20 20 20 20 20 20 20 20 20 20 6d 75 6c               mul
9570: 74 69 70 6c 65 78 44 65 76 69 63 65 43 68 61 72  tiplexDeviceChar
9580: 61 63 74 65 72 69 73 74 69 63 73 3b 0a 20 20 67  acteristics;.  g
9590: 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74  Multiplex.sIoMet
95a0: 68 6f 64 73 56 32 20 3d 20 67 4d 75 6c 74 69 70  hodsV2 = gMultip
95b0: 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 31  lex.sIoMethodsV1
95c0: 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73  ;.  gMultiplex.s
95d0: 49 6f 4d 65 74 68 6f 64 73 56 32 2e 69 56 65 72  IoMethodsV2.iVer
95e0: 73 69 6f 6e 20 3d 20 32 3b 0a 20 20 67 4d 75 6c  sion = 2;.  gMul
95f0: 74 69 70 6c 65 78 2e 73 49 6f 4d 65 74 68 6f 64  tiplex.sIoMethod
9600: 73 56 32 2e 78 53 68 6d 4d 61 70 20 3d 20 6d 75  sV2.xShmMap = mu
9610: 6c 74 69 70 6c 65 78 53 68 6d 4d 61 70 3b 0a 20  ltiplexShmMap;. 
9620: 20 67 4d 75 6c 74 69 70 6c 65 78 2e 73 49 6f 4d   gMultiplex.sIoM
9630: 65 74 68 6f 64 73 56 32 2e 78 53 68 6d 4c 6f 63  ethodsV2.xShmLoc
9640: 6b 20 3d 20 6d 75 6c 74 69 70 6c 65 78 53 68 6d  k = multiplexShm
9650: 4c 6f 63 6b 3b 0a 20 20 67 4d 75 6c 74 69 70 6c  Lock;.  gMultipl
9660: 65 78 2e 73 49 6f 4d 65 74 68 6f 64 73 56 32 2e  ex.sIoMethodsV2.
9670: 78 53 68 6d 42 61 72 72 69 65 72 20 3d 20 6d 75  xShmBarrier = mu
9680: 6c 74 69 70 6c 65 78 53 68 6d 42 61 72 72 69 65  ltiplexShmBarrie
9690: 72 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78 2e  r;.  gMultiplex.
96a0: 73 49 6f 4d 65 74 68 6f 64 73 56 32 2e 78 53 68  sIoMethodsV2.xSh
96b0: 6d 55 6e 6d 61 70 20 3d 20 6d 75 6c 74 69 70 6c  mUnmap = multipl
96c0: 65 78 53 68 6d 55 6e 6d 61 70 3b 0a 20 20 73 71  exShmUnmap;.  sq
96d0: 6c 69 74 65 33 5f 76 66 73 5f 72 65 67 69 73 74  lite3_vfs_regist
96e0: 65 72 28 26 67 4d 75 6c 74 69 70 6c 65 78 2e 73  er(&gMultiplex.s
96f0: 54 68 69 73 56 66 73 2c 20 6d 61 6b 65 44 65 66  ThisVfs, makeDef
9700: 61 75 6c 74 29 3b 0a 0a 20 20 73 71 6c 69 74 65  ault);..  sqlite
9710: 33 5f 61 75 74 6f 5f 65 78 74 65 6e 73 69 6f 6e  3_auto_extension
9720: 28 28 76 6f 69 64 2a 29 6d 75 6c 74 69 70 6c 65  ((void*)multiple
9730: 78 46 75 6e 63 49 6e 69 74 29 3b 0a 0a 20 20 72  xFuncInit);..  r
9740: 65 74 75 72 6e 20 53 51 4c 49 54 45 5f 4f 4b 3b  eturn SQLITE_OK;
9750: 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 43 41 50 49 3a 20  .}../*.** CAPI: 
9760: 53 68 75 74 64 6f 77 6e 20 74 68 65 20 6d 75 6c  Shutdown the mul
9770: 74 69 70 6c 65 78 20 73 79 73 74 65 6d 20 2d 20  tiplex system - 
9780: 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65  sqlite3_multiple
9790: 78 5f 73 68 75 74 64 6f 77 6e 28 29 0a 2a 2a 0a  x_shutdown().**.
97a0: 2a 2a 20 41 6c 6c 20 53 51 4c 69 74 65 20 64 61  ** All SQLite da
97b0: 74 61 62 61 73 65 20 63 6f 6e 6e 65 63 74 69 6f  tabase connectio
97c0: 6e 73 20 6d 75 73 74 20 62 65 20 63 6c 6f 73 65  ns must be close
97d0: 64 20 62 65 66 6f 72 65 20 63 61 6c 6c 69 6e 67  d before calling
97e0: 20 74 68 69 73 0a 2a 2a 20 72 6f 75 74 69 6e 65   this.** routine
97f0: 2e 0a 2a 2a 0a 2a 2a 20 54 48 49 53 20 52 4f 55  ..**.** THIS ROU
9800: 54 49 4e 45 20 49 53 20 4e 4f 54 20 54 48 52 45  TINE IS NOT THRE
9810: 41 44 53 41 46 45 2e 20 20 43 61 6c 6c 20 74 68  ADSAFE.  Call th
9820: 69 73 20 72 6f 75 74 69 6e 65 20 65 78 61 63 74  is routine exact
9830: 6c 79 20 6f 6e 63 65 20 77 68 69 6c 65 0a 2a 2a  ly once while.**
9840: 20 73 68 75 74 74 69 6e 67 20 64 6f 77 6e 20 69   shutting down i
9850: 6e 20 6f 72 64 65 72 20 74 6f 20 66 72 65 65 20  n order to free 
9860: 61 6c 6c 20 72 65 6d 61 69 6e 69 6e 67 20 6d 75  all remaining mu
9870: 6c 74 69 70 6c 65 78 20 67 72 6f 75 70 73 2e 0a  ltiplex groups..
9880: 2a 2f 0a 69 6e 74 20 73 71 6c 69 74 65 33 5f 6d  */.int sqlite3_m
9890: 75 6c 74 69 70 6c 65 78 5f 73 68 75 74 64 6f 77  ultiplex_shutdow
98a0: 6e 28 76 6f 69 64 29 7b 0a 20 20 69 66 28 20 67  n(void){.  if( g
98b0: 4d 75 6c 74 69 70 6c 65 78 2e 69 73 49 6e 69 74  Multiplex.isInit
98c0: 69 61 6c 69 7a 65 64 3d 3d 30 20 29 20 72 65 74  ialized==0 ) ret
98d0: 75 72 6e 20 53 51 4c 49 54 45 5f 4d 49 53 55 53  urn SQLITE_MISUS
98e0: 45 3b 0a 20 20 69 66 28 20 67 4d 75 6c 74 69 70  E;.  if( gMultip
98f0: 6c 65 78 2e 70 47 72 6f 75 70 73 20 29 20 72 65  lex.pGroups ) re
9900: 74 75 72 6e 20 53 51 4c 49 54 45 5f 4d 49 53 55  turn SQLITE_MISU
9910: 53 45 3b 0a 20 20 67 4d 75 6c 74 69 70 6c 65 78  SE;.  gMultiplex
9920: 2e 69 73 49 6e 69 74 69 61 6c 69 7a 65 64 20 3d  .isInitialized =
9930: 20 30 3b 0a 20 20 73 71 6c 69 74 65 33 5f 6d 75   0;.  sqlite3_mu
9940: 74 65 78 5f 66 72 65 65 28 67 4d 75 6c 74 69 70  tex_free(gMultip
9950: 6c 65 78 2e 70 4d 75 74 65 78 29 3b 0a 20 20 73  lex.pMutex);.  s
9960: 71 6c 69 74 65 33 5f 76 66 73 5f 75 6e 72 65 67  qlite3_vfs_unreg
9970: 69 73 74 65 72 28 26 67 4d 75 6c 74 69 70 6c 65  ister(&gMultiple
9980: 78 2e 73 54 68 69 73 56 66 73 29 3b 0a 20 20 6d  x.sThisVfs);.  m
9990: 65 6d 73 65 74 28 26 67 4d 75 6c 74 69 70 6c 65  emset(&gMultiple
99a0: 78 2c 20 30 2c 20 73 69 7a 65 6f 66 28 67 4d 75  x, 0, sizeof(gMu
99b0: 6c 74 69 70 6c 65 78 29 29 3b 0a 20 20 72 65 74  ltiplex));.  ret
99c0: 75 72 6e 20 53 51 4c 49 54 45 5f 4f 4b 3b 0a 7d  urn SQLITE_OK;.}
99d0: 0a 0a 2f 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ../*************
99e0: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
99f0: 20 54 65 73 74 20 43 6f 64 65 20 2a 2a 2a 2a 2a   Test Code *****
9a00: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
9a10: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2f 0a  **************/.
9a20: 23 69 66 64 65 66 20 53 51 4c 49 54 45 5f 54 45  #ifdef SQLITE_TE
9a30: 53 54 0a 23 69 6e 63 6c 75 64 65 20 3c 74 63 6c  ST.#include <tcl
9a40: 2e 68 3e 0a 65 78 74 65 72 6e 20 63 6f 6e 73 74  .h>.extern const
9a50: 20 63 68 61 72 20 2a 73 71 6c 69 74 65 33 54 65   char *sqlite3Te
9a60: 73 74 45 72 72 6f 72 4e 61 6d 65 28 69 6e 74 29  stErrorName(int)
9a70: 3b 0a 0a 0a 2f 2a 0a 2a 2a 20 74 63 6c 63 6d 64  ;.../*.** tclcmd
9a80: 3a 20 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70  : sqlite3_multip
9a90: 6c 65 78 5f 69 6e 69 74 69 61 6c 69 7a 65 20 4e  lex_initialize N
9aa0: 41 4d 45 20 4d 41 4b 45 44 45 46 41 55 4c 54 0a  AME MAKEDEFAULT.
9ab0: 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 74 65  */.static int te
9ac0: 73 74 5f 6d 75 6c 74 69 70 6c 65 78 5f 69 6e 69  st_multiplex_ini
9ad0: 74 69 61 6c 69 7a 65 28 0a 20 20 76 6f 69 64 20  tialize(.  void 
9ae0: 2a 20 63 6c 69 65 6e 74 44 61 74 61 2c 0a 20 20  * clientData,.  
9af0: 54 63 6c 5f 49 6e 74 65 72 70 20 2a 69 6e 74 65  Tcl_Interp *inte
9b00: 72 70 2c 0a 20 20 69 6e 74 20 6f 62 6a 63 2c 0a  rp,.  int objc,.
9b10: 20 20 54 63 6c 5f 4f 62 6a 20 2a 43 4f 4e 53 54    Tcl_Obj *CONST
9b20: 20 6f 62 6a 76 5b 5d 0a 29 7b 0a 20 20 63 6f 6e   objv[].){.  con
9b30: 73 74 20 63 68 61 72 20 2a 7a 4e 61 6d 65 3b 20  st char *zName; 
9b40: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
9b50: 4e 61 6d 65 20 6f 66 20 6e 65 77 20 6d 75 6c 74  Name of new mult
9b60: 69 70 6c 65 78 20 56 46 53 20 2a 2f 0a 20 20 69  iplex VFS */.  i
9b70: 6e 74 20 6d 61 6b 65 44 65 66 61 75 6c 74 3b 20  nt makeDefault; 
9b80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
9b90: 2a 20 54 72 75 65 20 74 6f 20 6d 61 6b 65 20 74  * True to make t
9ba0: 68 65 20 6e 65 77 20 56 46 53 20 74 68 65 20 64  he new VFS the d
9bb0: 65 66 61 75 6c 74 20 2a 2f 0a 20 20 69 6e 74 20  efault */.  int 
9bc0: 72 63 3b 20 20 20 20 20 20 20 20 20 20 20 20 20  rc;             
9bd0: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 56              /* V
9be0: 61 6c 75 65 20 72 65 74 75 72 6e 65 64 20 62 79  alue returned by
9bf0: 20 6d 75 6c 74 69 70 6c 65 78 5f 69 6e 69 74 69   multiplex_initi
9c00: 61 6c 69 7a 65 28 29 20 2a 2f 0a 0a 20 20 55 4e  alize() */..  UN
9c10: 55 53 45 44 5f 50 41 52 41 4d 45 54 45 52 28 63  USED_PARAMETER(c
9c20: 6c 69 65 6e 74 44 61 74 61 29 3b 0a 0a 20 20 2f  lientData);..  /
9c30: 2a 20 50 72 6f 63 65 73 73 20 61 72 67 75 6d 65  * Process argume
9c40: 6e 74 73 20 2a 2f 0a 20 20 69 66 28 20 6f 62 6a  nts */.  if( obj
9c50: 63 21 3d 33 20 29 7b 0a 20 20 20 20 54 63 6c 5f  c!=3 ){.    Tcl_
9c60: 57 72 6f 6e 67 4e 75 6d 41 72 67 73 28 69 6e 74  WrongNumArgs(int
9c70: 65 72 70 2c 20 31 2c 20 6f 62 6a 76 2c 20 22 4e  erp, 1, objv, "N
9c80: 41 4d 45 20 4d 41 4b 45 44 45 46 41 55 4c 54 22  AME MAKEDEFAULT"
9c90: 29 3b 0a 20 20 20 20 72 65 74 75 72 6e 20 54 43  );.    return TC
9ca0: 4c 5f 45 52 52 4f 52 3b 0a 20 20 7d 0a 20 20 7a  L_ERROR;.  }.  z
9cb0: 4e 61 6d 65 20 3d 20 54 63 6c 5f 47 65 74 53 74  Name = Tcl_GetSt
9cc0: 72 69 6e 67 28 6f 62 6a 76 5b 31 5d 29 3b 0a 20  ring(objv[1]);. 
9cd0: 20 69 66 28 20 54 63 6c 5f 47 65 74 42 6f 6f 6c   if( Tcl_GetBool
9ce0: 65 61 6e 46 72 6f 6d 4f 62 6a 28 69 6e 74 65 72  eanFromObj(inter
9cf0: 70 2c 20 6f 62 6a 76 5b 32 5d 2c 20 26 6d 61 6b  p, objv[2], &mak
9d00: 65 44 65 66 61 75 6c 74 29 20 29 20 72 65 74 75  eDefault) ) retu
9d10: 72 6e 20 54 43 4c 5f 45 52 52 4f 52 3b 0a 20 20  rn TCL_ERROR;.  
9d20: 69 66 28 20 7a 4e 61 6d 65 5b 30 5d 3d 3d 27 5c  if( zName[0]=='\
9d30: 30 27 20 29 20 7a 4e 61 6d 65 20 3d 20 30 3b 0a  0' ) zName = 0;.
9d40: 0a 20 20 2f 2a 20 43 61 6c 6c 20 73 71 6c 69 74  .  /* Call sqlit
9d50: 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 69 6e 69  e3_multiplex_ini
9d60: 74 69 61 6c 69 7a 65 28 29 20 2a 2f 0a 20 20 72  tialize() */.  r
9d70: 63 20 3d 20 73 71 6c 69 74 65 33 5f 6d 75 6c 74  c = sqlite3_mult
9d80: 69 70 6c 65 78 5f 69 6e 69 74 69 61 6c 69 7a 65  iplex_initialize
9d90: 28 7a 4e 61 6d 65 2c 20 6d 61 6b 65 44 65 66 61  (zName, makeDefa
9da0: 75 6c 74 29 3b 0a 20 20 54 63 6c 5f 53 65 74 52  ult);.  Tcl_SetR
9db0: 65 73 75 6c 74 28 69 6e 74 65 72 70 2c 20 28 63  esult(interp, (c
9dc0: 68 61 72 20 2a 29 73 71 6c 69 74 65 33 54 65 73  har *)sqlite3Tes
9dd0: 74 45 72 72 6f 72 4e 61 6d 65 28 72 63 29 2c 20  tErrorName(rc), 
9de0: 54 43 4c 5f 53 54 41 54 49 43 29 3b 0a 0a 20 20  TCL_STATIC);..  
9df0: 72 65 74 75 72 6e 20 54 43 4c 5f 4f 4b 3b 0a 7d  return TCL_OK;.}
9e00: 0a 0a 2f 2a 0a 2a 2a 20 74 63 6c 63 6d 64 3a 20  ../*.** tclcmd: 
9e10: 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65  sqlite3_multiple
9e20: 78 5f 73 68 75 74 64 6f 77 6e 0a 2a 2f 0a 73 74  x_shutdown.*/.st
9e30: 61 74 69 63 20 69 6e 74 20 74 65 73 74 5f 6d 75  atic int test_mu
9e40: 6c 74 69 70 6c 65 78 5f 73 68 75 74 64 6f 77 6e  ltiplex_shutdown
9e50: 28 0a 20 20 76 6f 69 64 20 2a 20 63 6c 69 65 6e  (.  void * clien
9e60: 74 44 61 74 61 2c 0a 20 20 54 63 6c 5f 49 6e 74  tData,.  Tcl_Int
9e70: 65 72 70 20 2a 69 6e 74 65 72 70 2c 0a 20 20 69  erp *interp,.  i
9e80: 6e 74 20 6f 62 6a 63 2c 0a 20 20 54 63 6c 5f 4f  nt objc,.  Tcl_O
9e90: 62 6a 20 2a 43 4f 4e 53 54 20 6f 62 6a 76 5b 5d  bj *CONST objv[]
9ea0: 0a 29 7b 0a 20 20 69 6e 74 20 72 63 3b 20 20 20  .){.  int rc;   
9eb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9ec0: 20 20 20 20 20 20 2f 2a 20 56 61 6c 75 65 20 72        /* Value r
9ed0: 65 74 75 72 6e 65 64 20 62 79 20 6d 75 6c 74 69  eturned by multi
9ee0: 70 6c 65 78 5f 73 68 75 74 64 6f 77 6e 28 29 20  plex_shutdown() 
9ef0: 2a 2f 0a 0a 20 20 55 4e 55 53 45 44 5f 50 41 52  */..  UNUSED_PAR
9f00: 41 4d 45 54 45 52 28 63 6c 69 65 6e 74 44 61 74  AMETER(clientDat
9f10: 61 29 3b 0a 0a 20 20 69 66 28 20 6f 62 6a 63 21  a);..  if( objc!
9f20: 3d 31 20 29 7b 0a 20 20 20 20 54 63 6c 5f 57 72  =1 ){.    Tcl_Wr
9f30: 6f 6e 67 4e 75 6d 41 72 67 73 28 69 6e 74 65 72  ongNumArgs(inter
9f40: 70 2c 20 31 2c 20 6f 62 6a 76 2c 20 22 22 29 3b  p, 1, objv, "");
9f50: 0a 20 20 20 20 72 65 74 75 72 6e 20 54 43 4c 5f  .    return TCL_
9f60: 45 52 52 4f 52 3b 0a 20 20 7d 0a 0a 20 20 2f 2a  ERROR;.  }..  /*
9f70: 20 43 61 6c 6c 20 73 71 6c 69 74 65 33 5f 6d 75   Call sqlite3_mu
9f80: 6c 74 69 70 6c 65 78 5f 73 68 75 74 64 6f 77 6e  ltiplex_shutdown
9f90: 28 29 20 2a 2f 0a 20 20 72 63 20 3d 20 73 71 6c  () */.  rc = sql
9fa0: 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78 5f 73  ite3_multiplex_s
9fb0: 68 75 74 64 6f 77 6e 28 29 3b 0a 20 20 54 63 6c  hutdown();.  Tcl
9fc0: 5f 53 65 74 52 65 73 75 6c 74 28 69 6e 74 65 72  _SetResult(inter
9fd0: 70 2c 20 28 63 68 61 72 20 2a 29 73 71 6c 69 74  p, (char *)sqlit
9fe0: 65 33 54 65 73 74 45 72 72 6f 72 4e 61 6d 65 28  e3TestErrorName(
9ff0: 72 63 29 2c 20 54 43 4c 5f 53 54 41 54 49 43 29  rc), TCL_STATIC)
a000: 3b 0a 0a 20 20 72 65 74 75 72 6e 20 54 43 4c 5f  ;..  return TCL_
a010: 4f 4b 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 74 63 6c  OK;.}../*.** tcl
a020: 63 6d 64 3a 20 20 73 71 6c 69 74 65 33 5f 6d 75  cmd:  sqlite3_mu
a030: 6c 74 69 70 6c 65 78 5f 64 75 6d 70 0a 2a 2f 0a  ltiplex_dump.*/.
a040: 73 74 61 74 69 63 20 69 6e 74 20 74 65 73 74 5f  static int test_
a050: 6d 75 6c 74 69 70 6c 65 78 5f 64 75 6d 70 28 0a  multiplex_dump(.
a060: 20 20 76 6f 69 64 20 2a 20 63 6c 69 65 6e 74 44    void * clientD
a070: 61 74 61 2c 0a 20 20 54 63 6c 5f 49 6e 74 65 72  ata,.  Tcl_Inter
a080: 70 20 2a 69 6e 74 65 72 70 2c 0a 20 20 69 6e 74  p *interp,.  int
a090: 20 6f 62 6a 63 2c 0a 20 20 54 63 6c 5f 4f 62 6a   objc,.  Tcl_Obj
a0a0: 20 2a 43 4f 4e 53 54 20 6f 62 6a 76 5b 5d 0a 29   *CONST objv[].)
a0b0: 7b 0a 20 20 54 63 6c 5f 4f 62 6a 20 2a 70 52 65  {.  Tcl_Obj *pRe
a0c0: 73 75 6c 74 3b 0a 20 20 54 63 6c 5f 4f 62 6a 20  sult;.  Tcl_Obj 
a0d0: 2a 70 47 72 6f 75 70 54 65 72 6d 3b 0a 20 20 6d  *pGroupTerm;.  m
a0e0: 75 6c 74 69 70 6c 65 78 47 72 6f 75 70 20 2a 70  ultiplexGroup *p
a0f0: 47 72 6f 75 70 3b 0a 20 20 69 6e 74 20 69 3b 0a  Group;.  int i;.
a100: 20 20 69 6e 74 20 6e 43 68 75 6e 6b 73 20 3d 20    int nChunks = 
a110: 30 3b 0a 0a 20 20 55 4e 55 53 45 44 5f 50 41 52  0;..  UNUSED_PAR
a120: 41 4d 45 54 45 52 28 63 6c 69 65 6e 74 44 61 74  AMETER(clientDat
a130: 61 29 3b 0a 20 20 55 4e 55 53 45 44 5f 50 41 52  a);.  UNUSED_PAR
a140: 41 4d 45 54 45 52 28 6f 62 6a 63 29 3b 0a 20 20  AMETER(objc);.  
a150: 55 4e 55 53 45 44 5f 50 41 52 41 4d 45 54 45 52  UNUSED_PARAMETER
a160: 28 6f 62 6a 76 29 3b 0a 0a 20 20 70 52 65 73 75  (objv);..  pResu
a170: 6c 74 20 3d 20 54 63 6c 5f 4e 65 77 4f 62 6a 28  lt = Tcl_NewObj(
a180: 29 3b 0a 20 20 6d 75 6c 74 69 70 6c 65 78 45 6e  );.  multiplexEn
a190: 74 65 72 28 29 3b 0a 20 20 66 6f 72 28 70 47 72  ter();.  for(pGr
a1a0: 6f 75 70 3d 67 4d 75 6c 74 69 70 6c 65 78 2e 70  oup=gMultiplex.p
a1b0: 47 72 6f 75 70 73 3b 20 70 47 72 6f 75 70 3b 20  Groups; pGroup; 
a1c0: 70 47 72 6f 75 70 3d 70 47 72 6f 75 70 2d 3e 70  pGroup=pGroup->p
a1d0: 4e 65 78 74 29 7b 0a 20 20 20 20 70 47 72 6f 75  Next){.    pGrou
a1e0: 70 54 65 72 6d 20 3d 20 54 63 6c 5f 4e 65 77 4f  pTerm = Tcl_NewO
a1f0: 62 6a 28 29 3b 0a 0a 20 20 20 20 69 66 28 20 70  bj();..    if( p
a200: 47 72 6f 75 70 2d 3e 7a 4e 61 6d 65 20 29 7b 0a  Group->zName ){.
a210: 20 20 20 20 20 20 70 47 72 6f 75 70 2d 3e 7a 4e        pGroup->zN
a220: 61 6d 65 5b 70 47 72 6f 75 70 2d 3e 6e 4e 61 6d  ame[pGroup->nNam
a230: 65 5d 20 3d 20 27 5c 30 27 3b 0a 20 20 20 20 20  e] = '\0';.     
a240: 20 54 63 6c 5f 4c 69 73 74 4f 62 6a 41 70 70 65   Tcl_ListObjAppe
a250: 6e 64 45 6c 65 6d 65 6e 74 28 69 6e 74 65 72 70  ndElement(interp
a260: 2c 20 70 47 72 6f 75 70 54 65 72 6d 2c 0a 20 20  , pGroupTerm,.  
a270: 20 20 20 20 20 20 20 20 54 63 6c 5f 4e 65 77 53          Tcl_NewS
a280: 74 72 69 6e 67 4f 62 6a 28 70 47 72 6f 75 70 2d  tringObj(pGroup-
a290: 3e 7a 4e 61 6d 65 2c 20 2d 31 29 29 3b 0a 20 20  >zName, -1));.  
a2a0: 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 54    }else{.      T
a2b0: 63 6c 5f 4c 69 73 74 4f 62 6a 41 70 70 65 6e 64  cl_ListObjAppend
a2c0: 45 6c 65 6d 65 6e 74 28 69 6e 74 65 72 70 2c 20  Element(interp, 
a2d0: 70 47 72 6f 75 70 54 65 72 6d 2c 20 54 63 6c 5f  pGroupTerm, Tcl_
a2e0: 4e 65 77 4f 62 6a 28 29 29 3b 0a 20 20 20 20 7d  NewObj());.    }
a2f0: 0a 20 20 20 20 54 63 6c 5f 4c 69 73 74 4f 62 6a  .    Tcl_ListObj
a300: 41 70 70 65 6e 64 45 6c 65 6d 65 6e 74 28 69 6e  AppendElement(in
a310: 74 65 72 70 2c 20 70 47 72 6f 75 70 54 65 72 6d  terp, pGroupTerm
a320: 2c 0a 20 20 20 20 20 20 20 20 20 20 54 63 6c 5f  ,.          Tcl_
a330: 4e 65 77 49 6e 74 4f 62 6a 28 70 47 72 6f 75 70  NewIntObj(pGroup
a340: 2d 3e 6e 4e 61 6d 65 29 29 3b 0a 20 20 20 20 54  ->nName));.    T
a350: 63 6c 5f 4c 69 73 74 4f 62 6a 41 70 70 65 6e 64  cl_ListObjAppend
a360: 45 6c 65 6d 65 6e 74 28 69 6e 74 65 72 70 2c 20  Element(interp, 
a370: 70 47 72 6f 75 70 54 65 72 6d 2c 0a 20 20 20 20  pGroupTerm,.    
a380: 20 20 20 20 20 20 54 63 6c 5f 4e 65 77 49 6e 74        Tcl_NewInt
a390: 4f 62 6a 28 70 47 72 6f 75 70 2d 3e 66 6c 61 67  Obj(pGroup->flag
a3a0: 73 29 29 3b 0a 0a 20 20 20 20 2f 2a 20 63 6f 75  s));..    /* cou
a3b0: 6e 74 20 6e 75 6d 62 65 72 20 6f 66 20 63 68 75  nt number of chu
a3c0: 6e 6b 73 20 77 69 74 68 20 6f 70 65 6e 20 68 61  nks with open ha
a3d0: 6e 64 6c 65 73 20 2a 2f 0a 20 20 20 20 66 6f 72  ndles */.    for
a3e0: 28 69 3d 30 3b 20 69 3c 70 47 72 6f 75 70 2d 3e  (i=0; i<pGroup->
a3f0: 6e 52 65 61 6c 3b 20 69 2b 2b 29 7b 0a 20 20 20  nReal; i++){.   
a400: 20 20 20 69 66 28 20 70 47 72 6f 75 70 2d 3e 61     if( pGroup->a
a410: 52 65 61 6c 5b 69 5d 2e 70 21 3d 30 20 29 20 6e  Real[i].p!=0 ) n
a420: 43 68 75 6e 6b 73 2b 2b 3b 0a 20 20 20 20 7d 0a  Chunks++;.    }.
a430: 20 20 20 20 54 63 6c 5f 4c 69 73 74 4f 62 6a 41      Tcl_ListObjA
a440: 70 70 65 6e 64 45 6c 65 6d 65 6e 74 28 69 6e 74  ppendElement(int
a450: 65 72 70 2c 20 70 47 72 6f 75 70 54 65 72 6d 2c  erp, pGroupTerm,
a460: 0a 20 20 20 20 20 20 20 20 20 20 54 63 6c 5f 4e  .          Tcl_N
a470: 65 77 49 6e 74 4f 62 6a 28 6e 43 68 75 6e 6b 73  ewIntObj(nChunks
a480: 29 29 3b 0a 0a 20 20 20 20 54 63 6c 5f 4c 69 73  ));..    Tcl_Lis
a490: 74 4f 62 6a 41 70 70 65 6e 64 45 6c 65 6d 65 6e  tObjAppendElemen
a4a0: 74 28 69 6e 74 65 72 70 2c 20 70 47 72 6f 75 70  t(interp, pGroup
a4b0: 54 65 72 6d 2c 0a 20 20 20 20 20 20 20 20 20 20  Term,.          
a4c0: 54 63 6c 5f 4e 65 77 49 6e 74 4f 62 6a 28 70 47  Tcl_NewIntObj(pG
a4d0: 72 6f 75 70 2d 3e 73 7a 43 68 75 6e 6b 29 29 3b  roup->szChunk));
a4e0: 0a 20 20 20 20 54 63 6c 5f 4c 69 73 74 4f 62 6a  .    Tcl_ListObj
a4f0: 41 70 70 65 6e 64 45 6c 65 6d 65 6e 74 28 69 6e  AppendElement(in
a500: 74 65 72 70 2c 20 70 47 72 6f 75 70 54 65 72 6d  terp, pGroupTerm
a510: 2c 0a 20 20 20 20 20 20 20 20 20 20 54 63 6c 5f  ,.          Tcl_
a520: 4e 65 77 49 6e 74 4f 62 6a 28 70 47 72 6f 75 70  NewIntObj(pGroup
a530: 2d 3e 6e 52 65 61 6c 29 29 3b 0a 0a 20 20 20 20  ->nReal));..    
a540: 54 63 6c 5f 4c 69 73 74 4f 62 6a 41 70 70 65 6e  Tcl_ListObjAppen
a550: 64 45 6c 65 6d 65 6e 74 28 69 6e 74 65 72 70 2c  dElement(interp,
a560: 20 70 52 65 73 75 6c 74 2c 20 70 47 72 6f 75 70   pResult, pGroup
a570: 54 65 72 6d 29 3b 0a 20 20 7d 0a 20 20 6d 75 6c  Term);.  }.  mul
a580: 74 69 70 6c 65 78 4c 65 61 76 65 28 29 3b 0a 20  tiplexLeave();. 
a590: 20 54 63 6c 5f 53 65 74 4f 62 6a 52 65 73 75 6c   Tcl_SetObjResul
a5a0: 74 28 69 6e 74 65 72 70 2c 20 70 52 65 73 75 6c  t(interp, pResul
a5b0: 74 29 3b 0a 20 20 72 65 74 75 72 6e 20 54 43 4c  t);.  return TCL
a5c0: 5f 4f 4b 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54 63  _OK;.}../*.** Tc
a5d0: 6c 63 6d 64 3a 20 74 65 73 74 5f 6d 75 6c 74 69  lcmd: test_multi
a5e0: 70 6c 65 78 5f 63 6f 6e 74 72 6f 6c 20 48 41 4e  plex_control HAN
a5f0: 44 4c 45 20 44 42 4e 41 4d 45 20 53 55 42 2d 43  DLE DBNAME SUB-C
a600: 4f 4d 4d 41 4e 44 20 3f 49 4e 54 2d 56 41 4c 55  OMMAND ?INT-VALU
a610: 45 3f 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74  E?.*/.static int
a620: 20 74 65 73 74 5f 6d 75 6c 74 69 70 6c 65 78 5f   test_multiplex_
a630: 63 6f 6e 74 72 6f 6c 28 0a 20 20 43 6c 69 65 6e  control(.  Clien
a640: 74 44 61 74 61 20 63 64 2c 0a 20 20 54 63 6c 5f  tData cd,.  Tcl_
a650: 49 6e 74 65 72 70 20 2a 69 6e 74 65 72 70 2c 0a  Interp *interp,.
a660: 20 20 69 6e 74 20 6f 62 6a 63 2c 0a 20 20 54 63    int objc,.  Tc
a670: 6c 5f 4f 62 6a 20 2a 43 4f 4e 53 54 20 6f 62 6a  l_Obj *CONST obj
a680: 76 5b 5d 0a 29 7b 0a 20 20 69 6e 74 20 72 63 3b  v[].){.  int rc;
a690: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a6a0: 20 20 20 20 20 20 20 20 20 2f 2a 20 52 65 74 75           /* Retu
a6b0: 72 6e 20 63 6f 64 65 20 66 72 6f 6d 20 66 69 6c  rn code from fil
a6c0: 65 5f 63 6f 6e 74 72 6f 6c 28 29 20 2a 2f 0a 20  e_control() */. 
a6d0: 20 69 6e 74 20 69 64 78 3b 20 20 20 20 20 20 20   int idx;       
a6e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a6f0: 20 2f 2a 20 49 6e 64 65 78 20 69 6e 20 61 53 75   /* Index in aSu
a700: 62 5b 5d 20 2a 2f 0a 20 20 54 63 6c 5f 43 6d 64  b[] */.  Tcl_Cmd
a710: 49 6e 66 6f 20 63 6d 64 49 6e 66 6f 3b 20 20 20  Info cmdInfo;   
a720: 20 20 20 20 20 20 20 20 20 2f 2a 20 43 6f 6d 6d           /* Comm
a730: 61 6e 64 20 69 6e 66 6f 20 73 74 72 75 63 74 75  and info structu
a740: 72 65 20 66 6f 72 20 48 41 4e 44 4c 45 20 2a 2f  re for HANDLE */
a750: 0a 20 20 73 71 6c 69 74 65 33 20 2a 64 62 3b 20  .  sqlite3 *db; 
a760: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a770: 20 20 20 2f 2a 20 55 6e 64 65 72 6c 79 69 6e 67     /* Underlying
a780: 20 64 62 20 68 61 6e 64 6c 65 20 66 6f 72 20 48   db handle for H
a790: 41 4e 44 4c 45 20 2a 2f 0a 20 20 69 6e 74 20 69  ANDLE */.  int i
a7a0: 56 61 6c 75 65 20 3d 20 30 3b 0a 20 20 76 6f 69  Value = 0;.  voi
a7b0: 64 20 2a 70 41 72 67 20 3d 20 30 3b 0a 0a 20 20  d *pArg = 0;..  
a7c0: 73 74 72 75 63 74 20 53 75 62 43 6f 6d 6d 61 6e  struct SubComman
a7d0: 64 20 7b 0a 20 20 20 20 63 6f 6e 73 74 20 63 68  d {.    const ch
a7e0: 61 72 20 2a 7a 4e 61 6d 65 3b 0a 20 20 20 20 69  ar *zName;.    i
a7f0: 6e 74 20 6f 70 3b 0a 20 20 20 20 69 6e 74 20 61  nt op;.    int a
a800: 72 67 74 79 70 65 3b 0a 20 20 7d 20 61 53 75 62  rgtype;.  } aSub
a810: 5b 5d 20 3d 20 7b 0a 20 20 20 20 7b 20 22 65 6e  [] = {.    { "en
a820: 61 62 6c 65 22 2c 20 20 20 20 20 20 20 4d 55 4c  able",       MUL
a830: 54 49 50 4c 45 58 5f 43 54 52 4c 5f 45 4e 41 42  TIPLEX_CTRL_ENAB
a840: 4c 45 2c 20 20 20 20 20 20 20 20 20 20 20 31 20  LE,           1 
a850: 7d 2c 0a 20 20 20 20 7b 20 22 63 68 75 6e 6b 5f  },.    { "chunk_
a860: 73 69 7a 65 22 2c 20 20 20 4d 55 4c 54 49 50 4c  size",   MULTIPL
a870: 45 58 5f 43 54 52 4c 5f 53 45 54 5f 43 48 55 4e  EX_CTRL_SET_CHUN
a880: 4b 5f 53 49 5a 45 2c 20 20 20 31 20 7d 2c 0a 20  K_SIZE,   1 },. 
a890: 20 20 20 7b 20 22 6d 61 78 5f 63 68 75 6e 6b 73     { "max_chunks
a8a0: 22 2c 20 20 20 4d 55 4c 54 49 50 4c 45 58 5f 43  ",   MULTIPLEX_C
a8b0: 54 52 4c 5f 53 45 54 5f 4d 41 58 5f 43 48 55 4e  TRL_SET_MAX_CHUN
a8c0: 4b 53 2c 20 20 20 31 20 7d 2c 0a 20 20 20 20 7b  KS,   1 },.    {
a8d0: 20 30 2c 20 30 2c 20 30 20 7d 0a 20 20 7d 3b 0a   0, 0, 0 }.  };.
a8e0: 0a 20 20 69 66 28 20 6f 62 6a 63 21 3d 35 20 29  .  if( objc!=5 )
a8f0: 7b 0a 20 20 20 20 54 63 6c 5f 57 72 6f 6e 67 4e  {.    Tcl_WrongN
a900: 75 6d 41 72 67 73 28 69 6e 74 65 72 70 2c 20 31  umArgs(interp, 1
a910: 2c 20 6f 62 6a 76 2c 20 22 48 41 4e 44 4c 45 20  , objv, "HANDLE 
a920: 44 42 4e 41 4d 45 20 53 55 42 2d 43 4f 4d 4d 41  DBNAME SUB-COMMA
a930: 4e 44 20 49 4e 54 2d 56 41 4c 55 45 22 29 3b 0a  ND INT-VALUE");.
a940: 20 20 20 20 72 65 74 75 72 6e 20 54 43 4c 5f 45      return TCL_E
a950: 52 52 4f 52 3b 0a 20 20 7d 0a 0a 20 20 69 66 28  RROR;.  }..  if(
a960: 20 30 3d 3d 54 63 6c 5f 47 65 74 43 6f 6d 6d 61   0==Tcl_GetComma
a970: 6e 64 49 6e 66 6f 28 69 6e 74 65 72 70 2c 20 54  ndInfo(interp, T
a980: 63 6c 5f 47 65 74 53 74 72 69 6e 67 28 6f 62 6a  cl_GetString(obj
a990: 76 5b 31 5d 29 2c 20 26 63 6d 64 49 6e 66 6f 29  v[1]), &cmdInfo)
a9a0: 20 29 7b 0a 20 20 20 20 54 63 6c 5f 41 70 70 65   ){.    Tcl_Appe
a9b0: 6e 64 52 65 73 75 6c 74 28 69 6e 74 65 72 70 2c  ndResult(interp,
a9c0: 20 22 65 78 70 65 63 74 65 64 20 64 61 74 61 62   "expected datab
a9d0: 61 73 65 20 68 61 6e 64 6c 65 2c 20 67 6f 74 20  ase handle, got 
a9e0: 5c 22 22 2c 20 30 29 3b 0a 20 20 20 20 54 63 6c  \"", 0);.    Tcl
a9f0: 5f 41 70 70 65 6e 64 52 65 73 75 6c 74 28 69 6e  _AppendResult(in
aa00: 74 65 72 70 2c 20 54 63 6c 5f 47 65 74 53 74 72  terp, Tcl_GetStr
aa10: 69 6e 67 28 6f 62 6a 76 5b 31 5d 29 2c 20 22 5c  ing(objv[1]), "\
aa20: 22 22 2c 20 30 29 3b 0a 20 20 20 20 72 65 74 75  "", 0);.    retu
aa30: 72 6e 20 54 43 4c 5f 45 52 52 4f 52 3b 0a 20 20  rn TCL_ERROR;.  
aa40: 7d 65 6c 73 65 7b 0a 20 20 20 20 64 62 20 3d 20  }else{.    db = 
aa50: 2a 28 73 71 6c 69 74 65 33 20 2a 2a 29 63 6d 64  *(sqlite3 **)cmd
aa60: 49 6e 66 6f 2e 6f 62 6a 43 6c 69 65 6e 74 44 61  Info.objClientDa
aa70: 74 61 3b 0a 20 20 7d 0a 0a 20 20 72 63 20 3d 20  ta;.  }..  rc = 
aa80: 54 63 6c 5f 47 65 74 49 6e 64 65 78 46 72 6f 6d  Tcl_GetIndexFrom
aa90: 4f 62 6a 53 74 72 75 63 74 28 0a 20 20 20 20 20  ObjStruct(.     
aaa0: 20 69 6e 74 65 72 70 2c 20 6f 62 6a 76 5b 33 5d   interp, objv[3]
aab0: 2c 20 61 53 75 62 2c 20 73 69 7a 65 6f 66 28 61  , aSub, sizeof(a
aac0: 53 75 62 5b 30 5d 29 2c 20 22 73 75 62 2d 63 6f  Sub[0]), "sub-co
aad0: 6d 6d 61 6e 64 22 2c 20 30 2c 20 26 69 64 78 0a  mmand", 0, &idx.
aae0: 20 20 29 3b 0a 20 20 69 66 28 20 72 63 21 3d 54    );.  if( rc!=T
aaf0: 43 4c 5f 4f 4b 20 29 20 72 65 74 75 72 6e 20 72  CL_OK ) return r
ab00: 63 3b 0a 0a 20 20 73 77 69 74 63 68 28 20 61 53  c;..  switch( aS
ab10: 75 62 5b 69 64 78 5d 2e 61 72 67 74 79 70 65 20  ub[idx].argtype 
ab20: 29 7b 0a 20 20 20 20 63 61 73 65 20 31 3a 0a 20  ){.    case 1:. 
ab30: 20 20 20 20 20 69 66 28 20 54 63 6c 5f 47 65 74       if( Tcl_Get
ab40: 49 6e 74 46 72 6f 6d 4f 62 6a 28 69 6e 74 65 72  IntFromObj(inter
ab50: 70 2c 20 6f 62 6a 76 5b 34 5d 2c 20 26 69 56 61  p, objv[4], &iVa
ab60: 6c 75 65 29 20 29 7b 0a 20 20 20 20 20 20 20 20  lue) ){.        
ab70: 72 65 74 75 72 6e 20 54 43 4c 5f 45 52 52 4f 52  return TCL_ERROR
ab80: 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20  ;.      }.      
ab90: 70 41 72 67 20 3d 20 28 76 6f 69 64 20 2a 29 26  pArg = (void *)&
aba0: 69 56 61 6c 75 65 3b 0a 20 20 20 20 20 20 62 72  iValue;.      br
abb0: 65 61 6b 3b 0a 20 20 20 20 64 65 66 61 75 6c 74  eak;.    default
abc0: 3a 0a 20 20 20 20 20 20 54 63 6c 5f 57 72 6f 6e  :.      Tcl_Wron
abd0: 67 4e 75 6d 41 72 67 73 28 69 6e 74 65 72 70 2c  gNumArgs(interp,
abe0: 20 34 2c 20 6f 62 6a 76 2c 20 22 53 55 42 2d 43   4, objv, "SUB-C
abf0: 4f 4d 4d 41 4e 44 22 29 3b 0a 20 20 20 20 20 20  OMMAND");.      
ac00: 72 65 74 75 72 6e 20 54 43 4c 5f 45 52 52 4f 52  return TCL_ERROR
ac10: 3b 0a 20 20 7d 0a 0a 20 20 72 63 20 3d 20 73 71  ;.  }..  rc = sq
ac20: 6c 69 74 65 33 5f 66 69 6c 65 5f 63 6f 6e 74 72  lite3_file_contr
ac30: 6f 6c 28 64 62 2c 20 54 63 6c 5f 47 65 74 53 74  ol(db, Tcl_GetSt
ac40: 72 69 6e 67 28 6f 62 6a 76 5b 32 5d 29 2c 20 61  ring(objv[2]), a
ac50: 53 75 62 5b 69 64 78 5d 2e 6f 70 2c 20 70 41 72  Sub[idx].op, pAr
ac60: 67 29 3b 0a 20 20 54 63 6c 5f 53 65 74 52 65 73  g);.  Tcl_SetRes
ac70: 75 6c 74 28 69 6e 74 65 72 70 2c 20 28 63 68 61  ult(interp, (cha
ac80: 72 20 2a 29 73 71 6c 69 74 65 33 54 65 73 74 45  r *)sqlite3TestE
ac90: 72 72 6f 72 4e 61 6d 65 28 72 63 29 2c 20 54 43  rrorName(rc), TC
aca0: 4c 5f 53 54 41 54 49 43 29 3b 0a 20 20 72 65 74  L_STATIC);.  ret
acb0: 75 72 6e 20 28 72 63 3d 3d 53 51 4c 49 54 45 5f  urn (rc==SQLITE_
acc0: 4f 4b 29 20 3f 20 54 43 4c 5f 4f 4b 20 3a 20 54  OK) ? TCL_OK : T
acd0: 43 4c 5f 45 52 52 4f 52 3b 0a 7d 0a 0a 2f 2a 0a  CL_ERROR;.}../*.
ace0: 2a 2a 20 54 68 69 73 20 72 6f 75 74 69 6e 65 20  ** This routine 
acf0: 72 65 67 69 73 74 65 72 73 20 74 68 65 20 63 75  registers the cu
ad00: 73 74 6f 6d 20 54 43 4c 20 63 6f 6d 6d 61 6e 64  stom TCL command
ad10: 73 20 64 65 66 69 6e 65 64 20 69 6e 20 74 68 69  s defined in thi
ad20: 73 0a 2a 2a 20 6d 6f 64 75 6c 65 2e 20 20 54 68  s.** module.  Th
ad30: 69 73 20 73 68 6f 75 6c 64 20 62 65 20 74 68 65  is should be the
ad40: 20 6f 6e 6c 79 20 70 72 6f 63 65 64 75 72 65 20   only procedure 
ad50: 76 69 73 69 62 6c 65 20 66 72 6f 6d 20 6f 75 74  visible from out
ad60: 73 69 64 65 0a 2a 2a 20 6f 66 20 74 68 69 73 20  side.** of this 
ad70: 6d 6f 64 75 6c 65 2e 0a 2a 2f 0a 69 6e 74 20 53  module..*/.int S
ad80: 71 6c 69 74 65 6d 75 6c 74 69 70 6c 65 78 5f 49  qlitemultiplex_I
ad90: 6e 69 74 28 54 63 6c 5f 49 6e 74 65 72 70 20 2a  nit(Tcl_Interp *
ada0: 69 6e 74 65 72 70 29 7b 0a 20 20 73 74 61 74 69  interp){.  stati
adb0: 63 20 73 74 72 75 63 74 20 7b 0a 20 20 20 20 20  c struct {.     
adc0: 63 68 61 72 20 2a 7a 4e 61 6d 65 3b 0a 20 20 20  char *zName;.   
add0: 20 20 54 63 6c 5f 4f 62 6a 43 6d 64 50 72 6f 63    Tcl_ObjCmdProc
ade0: 20 2a 78 50 72 6f 63 3b 0a 20 20 7d 20 61 43 6d   *xProc;.  } aCm
adf0: 64 5b 5d 20 3d 20 7b 0a 20 20 20 20 7b 20 22 73  d[] = {.    { "s
ae00: 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c 65 78  qlite3_multiplex
ae10: 5f 69 6e 69 74 69 61 6c 69 7a 65 22 2c 20 74 65  _initialize", te
ae20: 73 74 5f 6d 75 6c 74 69 70 6c 65 78 5f 69 6e 69  st_multiplex_ini
ae30: 74 69 61 6c 69 7a 65 20 7d 2c 0a 20 20 20 20 7b  tialize },.    {
ae40: 20 22 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70   "sqlite3_multip
ae50: 6c 65 78 5f 73 68 75 74 64 6f 77 6e 22 2c 20 74  lex_shutdown", t
ae60: 65 73 74 5f 6d 75 6c 74 69 70 6c 65 78 5f 73 68  est_multiplex_sh
ae70: 75 74 64 6f 77 6e 20 7d 2c 0a 20 20 20 20 7b 20  utdown },.    { 
ae80: 22 73 71 6c 69 74 65 33 5f 6d 75 6c 74 69 70 6c  "sqlite3_multipl
ae90: 65 78 5f 64 75 6d 70 22 2c 20 74 65 73 74 5f 6d  ex_dump", test_m
aea0: 75 6c 74 69 70 6c 65 78 5f 64 75 6d 70 20 7d 2c  ultiplex_dump },
aeb0: 0a 20 20 20 20 7b 20 22 73 71 6c 69 74 65 33 5f  .    { "sqlite3_
aec0: 6d 75 6c 74 69 70 6c 65 78 5f 63 6f 6e 74 72 6f  multiplex_contro
aed0: 6c 22 2c 20 74 65 73 74 5f 6d 75 6c 74 69 70 6c  l", test_multipl
aee0: 65 78 5f 63 6f 6e 74 72 6f 6c 20 7d 2c 0a 20 20  ex_control },.  
aef0: 7d 3b 0a 20 20 69 6e 74 20 69 3b 0a 0a 20 20 66  };.  int i;..  f
af00: 6f 72 28 69 3d 30 3b 20 69 3c 73 69 7a 65 6f 66  or(i=0; i<sizeof
af10: 28 61 43 6d 64 29 2f 73 69 7a 65 6f 66 28 61 43  (aCmd)/sizeof(aC
af20: 6d 64 5b 30 5d 29 3b 20 69 2b 2b 29 7b 0a 20 20  md[0]); i++){.  
af30: 20 20 54 63 6c 5f 43 72 65 61 74 65 4f 62 6a 43    Tcl_CreateObjC
af40: 6f 6d 6d 61 6e 64 28 69 6e 74 65 72 70 2c 20 61  ommand(interp, a
af50: 43 6d 64 5b 69 5d 2e 7a 4e 61 6d 65 2c 20 61 43  Cmd[i].zName, aC
af60: 6d 64 5b 69 5d 2e 78 50 72 6f 63 2c 20 30 2c 20  md[i].xProc, 0, 
af70: 30 29 3b 0a 20 20 7d 0a 0a 20 20 72 65 74 75 72  0);.  }..  retur
af80: 6e 20 54 43 4c 5f 4f 4b 3b 0a 7d 0a 23 65 6e 64  n TCL_OK;.}.#end
af90: 69 66 0a                                         if.